From ebe7700ceeeae88e44c08edee1de0f91ed05aa8d Mon Sep 17 00:00:00 2001 From: Tony Garnock-Jones Date: Wed, 17 Apr 2024 13:26:06 +0200 Subject: [PATCH] Allow "when (...)" clause on "on" endpoints --- packages/compiler/src/compiler/codegen.ts | 19 +++++--- packages/compiler/src/compiler/grammar.ts | 7 ++- packages/compiler/test/compiler.test.ts | 53 ++++++++++++++++++++++- 3 files changed, 69 insertions(+), 10 deletions(-) diff --git a/packages/compiler/src/compiler/codegen.ts b/packages/compiler/src/compiler/codegen.ts index 116de21..de78c9e 100644 --- a/packages/compiler/src/compiler/codegen.ts +++ b/packages/compiler/src/compiler/codegen.ts @@ -296,14 +296,19 @@ ${joinItems(sa.captureBinders.map(binderTypeGuard(t)), '\n')} })`; if (s.isDynamic) { - return wrap(t`__SYNDICATE__.Turn.active.assertDataflow(() => ({ - target: currentSyndicateTarget, - assertion: ${assertion}, - }));`); + if (s.test === void 0) { + return wrap(t`__SYNDICATE__.Turn.active.assertDataflow(() => ({ target: currentSyndicateTarget, assertion: ${assertion} }));`); + } else { + return wrap(t`__SYNDICATE__.Turn.active.assertDataflow(() => (${walk(s.test)}) + ? ({ target: currentSyndicateTarget, assertion: ${assertion} }) + : ({ target: void 0, assertion: void 0 }));`); + } } else { - return wrap( - t`__SYNDICATE__.Turn.active.replace(currentSyndicateTarget, void 0, ${assertion});` - ); + if (s.test === void 0) { + return wrap(t`__SYNDICATE__.Turn.active.replace(currentSyndicateTarget, void 0, ${assertion});`); + } else { + return wrap(t`__SYNDICATE__.Turn.active.replace(currentSyndicateTarget, void 0, (${walk(s.test)}) ? ${assertion} : void 0);`); + } } }); diff --git a/packages/compiler/src/compiler/grammar.ts b/packages/compiler/src/compiler/grammar.ts index 3585e2b..ae623a6 100644 --- a/packages/compiler/src/compiler/grammar.ts +++ b/packages/compiler/src/compiler/grammar.ts @@ -75,6 +75,7 @@ export interface PseudoEventEndpointStatement extends GenericEventEndpointStatem export interface AssertionEventEndpointStatement extends GenericEventEndpointStatement { triggerType: 'asserted' | 'retracted' | 'message'; pattern: ValuePattern; + test?: Expr, } export type EventHandlerEndpointStatement = @@ -325,7 +326,11 @@ export class SyndicateParser { atomString('message'))), option(map(kw('snapshot'), _ => o.isDynamic = false)), bind(o as AssertionEventEndpointStatement, 'pattern', - this.valuePattern(1, atom('=>'))), + this.valuePattern(1, atom('=>'), + seq(atom('when'), group('(', discard)))), + option(seq(atom('when'), group( + '(', bind(o as AssertionEventEndpointStatement, 'test', + this.expr())))), this.mandatoryIfNotTerminal( o, seq(atom('=>'), this.statement(o.body)))))); }); diff --git a/packages/compiler/test/compiler.test.ts b/packages/compiler/test/compiler.test.ts index c924f0a..b77e73c 100644 --- a/packages/compiler/test/compiler.test.ts +++ b/packages/compiler/test/compiler.test.ts @@ -187,7 +187,7 @@ __SYNDICATE__.Turn.active.facet(() => { } } }), - }), + }) })); });`)); @@ -206,8 +206,57 @@ __SYNDICATE__.Turn.active.facet(() => { } } }), - }), + }) })); });`)); }); + +describe('on', () => { + it('message with guard', () => expectCodeEqual(` + on message S.Focus(entity) when (isLast.value) => { + text.node.focus(); + }`, `__SYNDICATE__.Turn.active.assertDataflow(() => (isLast.value) ? + ({ + target: currentSyndicateTarget, + assertion: __SYNDICATE__.Observe({ + pattern: __SYNDICATE__.QuasiValue.finish((__SYNDICATE__.QuasiValue.ctor(S.Focus, (__SYNDICATE__.QuasiValue.lit(__SYNDICATE__.fromJS(entity)))))), + observer: __SYNDICATE__.Turn.ref({ + message: (__vs) => { + if (Array.isArray(__vs)) { + + + text.node.focus(); + + } + } + }), + }) + }) : + ({ + target: void 0, + assertion: void 0 + }));`)); + + it('asserted with guard', () => expectCodeEqual(`on asserted P when (someTest) => x;`, ` +__SYNDICATE__.Turn.active.assertDataflow(() => (someTest) ? +({ + target: currentSyndicateTarget, + assertion: __SYNDICATE__.Observe({ + pattern: __SYNDICATE__.QuasiValue.finish((__SYNDICATE__.QuasiValue.lit(__SYNDICATE__.fromJS(P)))), + observer: __SYNDICATE__.Turn.ref({ + assert: (__vs, __handle) => { + if (Array.isArray(__vs)) { + + x; + } + } + }), + }) +}) : +({ + target: void 0, + assertion: void 0 +}));`)); + +});