diff --git a/packages/compiler/src/compiler/codegen.ts b/packages/compiler/src/compiler/codegen.ts index 7d45de7..847368c 100644 --- a/packages/compiler/src/compiler/codegen.ts +++ b/packages/compiler/src/compiler/codegen.ts @@ -148,25 +148,29 @@ export function expand(tree: Items, ctx: ExpansionContext): Items { spawn.linkedToken = getRange(s.body); } - let body = (spawn == null) + let body = (spawn === null) ? walk(s.body) : expandSpawn(spawn, t, t`__SYNDICATE__.Turn.activeFacet.preventInertCheck();`); const sa = compilePattern(s.pattern); - return t`assertDataflow(() => ({ - target: currentSyndicateTarget, - assertion: __SYNDICATE__.fromObserve(__SYNDICATE__.Observe({ - pattern: __SYNDICATE__.QuasiValue.finish(${sa.skeleton}), - observer: __SYNDICATE__.Turn.ref(__SYNDICATE__.assertionFacetObserver( - (${ctx.argDecl(t, '__vs', '__SYNDICATE__.AnyValue')}) => { - if (Array.isArray(__vs)) { + const assertion = t`__SYNDICATE__.fromObserve(__SYNDICATE__.Observe({ + pattern: __SYNDICATE__.QuasiValue.finish(${sa.skeleton}), + observer: __SYNDICATE__.Turn.ref(__SYNDICATE__.assertionFacetObserver( + (${ctx.argDecl(t, '__vs', '__SYNDICATE__.AnyValue')}) => { + if (Array.isArray(__vs)) { ${joinItems(sa.captureBinders.map(binderTypeGuard(ctx, t)), '\n')} - ${body} - } + ${body} } - )) - })), - }));`; + } + )) + }))`; + if (s.test === void 0) { + return t`assertDataflow(() => ({ target: currentSyndicateTarget, assertion: ${assertion} }));`; + } else { + return t`assertDataflow(() => (${walk(s.test)}) + ? ({ target: currentSyndicateTarget, assertion: ${assertion} }) + : ({ target: void 0, assertion: void 0 }));`; + } }); function expandSpawn(spawn: SpawnStatement, t: TemplateFunction, inject: Items = []): Items { @@ -197,7 +201,7 @@ ${joinItems(sa.captureBinders.map(binderTypeGuard(ctx, t)), '\n')} xf(ctx.parser.assertionEndpointStatement, (s, t) => { if (s.isDynamic) { - if (s.test == void 0) { + if (s.test === void 0) { return t`assertDataflow(() => ({ target: currentSyndicateTarget, assertion: ${walk(s.template)} }));`; } else { return t`assertDataflow(() => (${walk(s.test)}) @@ -205,7 +209,7 @@ ${joinItems(sa.captureBinders.map(binderTypeGuard(ctx, t)), '\n')} : ({ target: void 0, assertion: void 0 }));`; } } else { - if (s.test == void 0) { + if (s.test === void 0) { return t`assert(currentSyndicateTarget, ${walk(s.template)});`; } else { return t`replace(currentSyndicateTarget, void 0, (${walk(s.test)}) ? (${walk(s.template)}) : void 0);`; diff --git a/packages/compiler/src/compiler/grammar.ts b/packages/compiler/src/compiler/grammar.ts index d07632a..adb379d 100644 --- a/packages/compiler/src/compiler/grammar.ts +++ b/packages/compiler/src/compiler/grammar.ts @@ -85,6 +85,7 @@ export interface MessageSendStatement extends TurnAction { export interface DuringStatement extends FacetSetupAction { pattern: ValuePattern; + test?: Expr, } export interface ReactStatement extends FacetSetupAction { @@ -314,7 +315,9 @@ export class SyndicateParser { this.turnAction(o => { o.body = []; return seq(atom('during'), - bind(o, 'pattern', this.valuePattern(1, atom('=>'))), + bind(o, 'pattern', + this.valuePattern(1, atom('=>'), seq(atom('when'), group('(', discard)))), + option(seq(atom('when'), group('(', bind(o, 'test', this.expr())))), seq(atom('=>'), this.statement(o.body))); });