diff --git a/compiler/__tests__/parser.test.ts b/compiler/__tests__/parser.test.ts index d4d5e33..c3985ac 100644 --- a/compiler/__tests__/parser.test.ts +++ b/compiler/__tests__/parser.test.ts @@ -853,4 +853,35 @@ speck Second { } }); }); + + // Cycle 65: default-value syntax `= ` on event fields was + // bleeding into the type expression. Real federated-meetup has + // initial_mesh_peers: List = [] + // emitted as `List = [] initial_mesh_peers = 1;` + // which protoc rejects. The fix strips `= ` 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 = [] + } +}`; + 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('= []'); + } + }); + }); }); diff --git a/compiler/src/parser.ts b/compiler/src/parser.ts index 1e3d8a8..fa26c2a 100644 --- a/compiler/src/parser.ts +++ b/compiler/src/parser.ts @@ -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 `= ` from the type + // expression. The federated-meetup speckdl has fields like + // initial_mesh_peers: List = [] + // 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 = []` 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()) }); }