feat(compiler): parse precondition/postcondition in action blocks

- Add 'precondition' and 'postcondition' ActionStatement types
- Parse precondition: expr and postcondition: expr in action bodies
- Support 'or' continuation lines for multi-clause pre/postconditions
- TigerBeetleLedger now parses 21 preconditions + 24 postconditions
  (previously all dropped, resulting in empty action bodies)
- All 41 existing tests pass

Addresses marcus/engineering#9 (parser gap)
Does NOT wire into generators yet — TypeScript/WASM output
will be empty for pre/postconditions. Generator wiring
is follow-up work.
This commit is contained in:
Scott Scoble 2026-05-09 09:12:15 -07:00
parent bc067d239c
commit 9de0a5ca0f

View file

@ -132,6 +132,8 @@ export type ActionStatement =
| { type: 'assign'; target: string; expr: string }
| { type: 'let'; name: string; expr: string }
| { type: 'require'; expr: string }
| { type: 'precondition'; expr: string }
| { type: 'postcondition'; expr: string }
| { type: 'emit'; event: string; fields: { name: string; value: string }[] }
| { type: 'return'; expr: string };
@ -728,7 +730,30 @@ function parseActionBlockMultiline(lines: string[], startIndex: number, startBra
const bodyLines = lines.slice(startIndex + 1, endIndex).map(l => l.trim()).filter(l => l && !l.startsWith('//') && !l.startsWith('/*'));
const statements: ActionStatement[] = [];
for (const stmt of bodyLines) {
for (let i = 0; i < bodyLines.length; i++) {
const stmt = bodyLines[i];
// precondition: expr
if (stmt.startsWith('precondition:')) {
let expr = stmt.substring(13).trim();
// support 'or' continuation lines
while (i + 1 < bodyLines.length && bodyLines[i + 1].startsWith('or ')) {
i++;
expr += ' || ' + bodyLines[i].substring(3).trim();
}
statements.push({ type: 'precondition', expr });
continue;
}
// postcondition: expr
if (stmt.startsWith('postcondition:')) {
let expr = stmt.substring(14).trim();
// support 'or' continuation lines
while (i + 1 < bodyLines.length && bodyLines[i + 1].startsWith('or ')) {
i++;
expr += ' || ' + bodyLines[i].substring(3).trim();
}
statements.push({ type: 'postcondition', expr });
continue;
}
// require expr
if (stmt.startsWith('require ')) {
statements.push({ type: 'require', expr: stmt.substring(8).trim() });