fix(speckl): strip default-value syntax from event field types (cycle 65)
End-to-end compile of FederatedMeetup.speckdl (with the cycle-65 Transition envelope added) surfaced a real bug: the speckdl uses default-value syntax on event fields: initial_mesh_peers: List<InitialMeshPeer> = [] The default is a Speckl semantic — a state-machine init value — but the .proto wire format has no place for it. Without stripping, the type expression 'List<InitialMeshPeer> = []' was emitted verbatim as the field type, producing broken proto3 syntax that protoc rejected. Fix: parseEventBlockMultiline now strips '= <expr>' suffix from the type expression before calling parseTypeExpr. The default value is dropped (it's a Speckl semantic only; the wire format carries no default). Tests: 1 new parser test covers the federated-meetup 'initial_mesh_peers: List<InitialMeshPeer> = []' shape. All 56 tests pass (55 baseline + 1 new). tsc build clean. End-to-end verified: with this fix and the cycle-65 federated- meetup speckdl changes, the Speckl-generated .proto now compiles cleanly with 'protoc' (previously rejected).
This commit is contained in:
parent
f37c0ccc57
commit
7beaf6f3cc
2 changed files with 41 additions and 1 deletions
|
|
@ -853,4 +853,35 @@ speck Second {
|
|||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Cycle 65: default-value syntax `= <expr>` on event fields was
|
||||
// bleeding into the type expression. Real federated-meetup has
|
||||
// initial_mesh_peers: List<InitialMeshPeer> = []
|
||||
// emitted as `List<InitialMeshPeer> = [] initial_mesh_peers = 1;`
|
||||
// which protoc rejects. The fix strips `= <expr>` from the type
|
||||
// before parsing (the default is a Speckl semantic; the .proto wire
|
||||
// format has no place for it).
|
||||
describe('default value stripping (cycle 65)', () => {
|
||||
it('should strip `= []` from event field type expressions', () => {
|
||||
const content = `speck One {
|
||||
event CreateGroup {
|
||||
initial_mesh_peers: List<InitialMeshPeer> = []
|
||||
}
|
||||
}`;
|
||||
const ast = parseSpeckContent(content);
|
||||
const ev = ast.specks[0].members.find(m => m.name === 'CreateGroup');
|
||||
if (ev?.type === 'event') {
|
||||
const f = ev.fields[0];
|
||||
expect(f.name).toBe('initial_mesh_peers');
|
||||
expect(f.type.type).toBe('list');
|
||||
expect(f.type.elementType?.name).toBe('InitialMeshPeer');
|
||||
// The full type string should not contain '= []' anywhere — verify
|
||||
// via the elementType name and the parent's name (both undefined
|
||||
// for List, so we check the parser did not preserve the default
|
||||
// in any visible field).
|
||||
const asAny = f.type as any;
|
||||
expect(JSON.stringify(asAny)).not.toContain('= []');
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1309,7 +1309,16 @@ function parseEventBlockMultiline(lines: string[], startIndex: number, startBrac
|
|||
// bytes // 4 bytes (IPv4 overlay) mesh_ip = 2;
|
||||
// (broken syntax — comment is in the type position).
|
||||
const noComment = line.replace(/\/\/.*$/, '').trim();
|
||||
const match = noComment.match(/^(\w+)\s*:\s*(.+?),?$/);
|
||||
// Cycle 65: strip default-value suffix `= <expr>` from the type
|
||||
// expression. The federated-meetup speckdl has fields like
|
||||
// initial_mesh_peers: List<InitialMeshPeer> = []
|
||||
// where the default is meaningful in Speckl semantics (a state-
|
||||
// machine init) but the .proto wire format doesn't carry a
|
||||
// default — it's a generator concern. Without this, the type
|
||||
// expression was emitted as `List<InitialMeshPeer> = []` and
|
||||
// protoc rejects the resulting syntax.
|
||||
const noDefault = noComment.replace(/\s*=\s*[^,]+$/, '').trim();
|
||||
const match = noDefault.match(/^(\w+)\s*:\s*(.+?),?$/);
|
||||
if (match) {
|
||||
fields.push({ name: match[1], type: parseTypeExpr(match[2].replace(/,$/, '').trim()) });
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue