diff --git a/packages/compiler/src/compiler/codegen.ts b/packages/compiler/src/compiler/codegen.ts index 5f71eaf..2c91059 100644 --- a/packages/compiler/src/compiler/codegen.ts +++ b/packages/compiler/src/compiler/codegen.ts @@ -194,10 +194,10 @@ ${joinItems(sa.captureBinders.map(binderTypeGuard(t)), '\n')} )) })`; if (s.test === void 0) { - return t`assertDataflow(() => ({ target: currentSyndicateTarget, assertion: ${assertion} }));`; + return t`assertDataflow(() => ({ target: currentSyndicateTarget(), assertion: ${assertion} }));`; } else { return t`assertDataflow(() => (${walk(s.test)}) - ? ({ target: currentSyndicateTarget, assertion: ${assertion} }) + ? ({ target: currentSyndicateTarget(), assertion: ${assertion} }) : ({ target: void 0, assertion: void 0 }));`; } }); @@ -222,7 +222,7 @@ ${joinItems(sa.captureBinders.map(binderTypeGuard(t)), '\n')} }); x(ctx.parser.atStatement, (s, t) => { - return t`(((${ctx.argDecl(t, 'currentSyndicateTarget', '__SYNDICATE__.Ref')}) => {${walk(s.body)}})(${walk(s.target)}));`; + return t`(((${ctx.argDecl(t, 'currentSyndicateTarget', '() => __SYNDICATE__.Ref')}) => {${walk(s.body)}})(() => (${walk(s.target)})));`; }); x(ctx.parser.createExpression, (s, t) => { @@ -232,17 +232,17 @@ ${joinItems(sa.captureBinders.map(binderTypeGuard(t)), '\n')} xf(ctx.parser.assertionEndpointStatement, (s, t) => { if (s.isDynamic) { if (s.test === void 0) { - return t`assertDataflow(() => ({ target: currentSyndicateTarget, assertion: ${walk(s.template)} }));`; + return t`assertDataflow(() => ({ target: currentSyndicateTarget(), assertion: ${walk(s.template)} }));`; } else { return t`assertDataflow(() => (${walk(s.test)}) - ? ({ target: currentSyndicateTarget, assertion: ${walk(s.template)} }) + ? ({ target: currentSyndicateTarget(), assertion: ${walk(s.template)} }) : ({ target: void 0, assertion: void 0 }));`; } } else { if (s.test === void 0) { - return t`assert(currentSyndicateTarget, ${walk(s.template)});`; + return t`assert(currentSyndicateTarget(), ${walk(s.template)});`; } else { - return t`replace(currentSyndicateTarget, void 0, (${walk(s.test)}) ? (${walk(s.template)}) : void 0);`; + return t`replace(currentSyndicateTarget(), void 0, (${walk(s.test)}) ? (${walk(s.template)}) : void 0);`; } } }); @@ -297,17 +297,17 @@ ${joinItems(sa.captureBinders.map(binderTypeGuard(t)), '\n')} if (s.isDynamic) { if (s.test === void 0) { - return wrap(t`__SYNDICATE__.Turn.active.assertDataflow(() => ({ target: currentSyndicateTarget, assertion: ${assertion} }));`); + 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: currentSyndicateTarget(), assertion: ${assertion} }) : ({ target: void 0, assertion: void 0 }));`); } } else { if (s.test === void 0) { - return wrap(t`__SYNDICATE__.Turn.active.replace(currentSyndicateTarget, void 0, ${assertion});`); + 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);`); + return wrap(t`__SYNDICATE__.Turn.active.replace(currentSyndicateTarget(), void 0, (${walk(s.test)}) ? ${assertion} : void 0);`); } } }); @@ -322,7 +322,7 @@ ${joinItems(sa.captureBinders.map(binderTypeGuard(t)), '\n')} return t`const ${[s.label]} = __SYNDICATE__.Record.makeConstructor${fs}()(${maybeWalk(s.wireName) ?? l}, ${fns});`; }); - xf(ctx.parser.messageSendStatement, (s, t) => t`message(currentSyndicateTarget, ${walk(s.expr)});`); + xf(ctx.parser.messageSendStatement, (s, t) => t`message(currentSyndicateTarget(), ${walk(s.expr)});`); x(ctx.parser.reactStatement, (s, t) => facetWrap(t, s.label ?? 'default', s.body)); diff --git a/packages/compiler/syndicate-browser-compiler.js b/packages/compiler/syndicate-browser-compiler.js index c7d1100..92765b8 100644 --- a/packages/compiler/syndicate-browser-compiler.js +++ b/packages/compiler/syndicate-browser-compiler.js @@ -2,7 +2,7 @@ /// SPDX-FileCopyrightText: Copyright © 2023-2024 Tony Garnock-Jones const __SYNDICATE__ = Syndicate; -const currentSyndicateTarget = Syndicate.Dataspace.local; +const currentSyndicateTarget = () => Syndicate.Dataspace.local; (() => { async function translateScripts() { diff --git a/packages/compiler/test/compiler.test.ts b/packages/compiler/test/compiler.test.ts index 8db0cef..77433e7 100644 --- a/packages/compiler/test/compiler.test.ts +++ b/packages/compiler/test/compiler.test.ts @@ -61,6 +61,20 @@ __SYNDICATE__.Turn.active._sync(p, __SYNDICATE__.Turn.ref({ }));`)); }); +describe('at', () => { + it('produces a closure for currentSyndicateTarget', () => { + expectCodeEqual(`at someField.value { foo(); }`, + `(((currentSyndicateTarget) => { + foo(); + })(() => (someField.value)));`); + expectCodeEqual(`at someField.value { foo(); }`, + `(((currentSyndicateTarget: () => __SYNDICATE__.Ref) => { + foo(); + })(() => (someField.value)));`, + { typescript: true }); + }); +}); + describe('spawn', () => { it('without name', () => expectCodeEqual(`spawn { a; b; c; }`, ` @@ -147,7 +161,7 @@ describe('during', () => { it('stop in body', () => expectCodeEqual(`during P => { a; stop; b; }`, ` __SYNDICATE__.Turn.active.assertDataflow(() => ({ - target: currentSyndicateTarget, + target: currentSyndicateTarget(), assertion: __SYNDICATE__.Observe({ pattern: __SYNDICATE__.QuasiValue.finish((__SYNDICATE__.QuasiValue.lit(__SYNDICATE__.fromJS(P)))), observer: __SYNDICATE__.Turn.ref(__SYNDICATE__.assertionFacetObserver( @@ -167,7 +181,7 @@ __SYNDICATE__.Turn.active.assertDataflow(() => ({ it('capture with type at top', () => expectCodeEqual(`during $v: T => { ok() }`, ` __SYNDICATE__.Turn.active.assertDataflow(() => ({ - target: currentSyndicateTarget, + target: currentSyndicateTarget(), assertion: __SYNDICATE__.Observe({ pattern: __SYNDICATE__.QuasiValue.finish((__SYNDICATE__.QuasiValue.bind((__SYNDICATE__.QuasiValue._)))), observer: __SYNDICATE__.Turn.ref(__SYNDICATE__.assertionFacetObserver( @@ -191,7 +205,7 @@ describe('once', () => { __SYNDICATE__.Turn.active.facet(() => { const __once_facet = __SYNDICATE__.Turn.activeFacet; __SYNDICATE__.Turn.active.assertDataflow(() => ({ - target: currentSyndicateTarget, + target: currentSyndicateTarget(), assertion: __SYNDICATE__.Observe({ pattern: __SYNDICATE__.QuasiValue.finish((__SYNDICATE__.QuasiValue.lit(__SYNDICATE__.fromJS(P)))), observer: __SYNDICATE__.Turn.ref({ @@ -210,7 +224,7 @@ __SYNDICATE__.Turn.active.facet(() => { __SYNDICATE__.Turn.active.facet(() => { const __once_facet = __SYNDICATE__.Turn.activeFacet; __SYNDICATE__.Turn.active.assertDataflow(() => ({ - target: currentSyndicateTarget, + target: currentSyndicateTarget(), assertion: __SYNDICATE__.Observe({ pattern: __SYNDICATE__.QuasiValue.finish((__SYNDICATE__.QuasiValue.lit(__SYNDICATE__.fromJS(P)))), observer: __SYNDICATE__.Turn.ref({ @@ -233,7 +247,7 @@ describe('on', () => { text.node.focus(); }`, `__SYNDICATE__.Turn.active.assertDataflow(() => (isLast.value) ? ({ - target: currentSyndicateTarget, + target: currentSyndicateTarget(), assertion: __SYNDICATE__.Observe({ pattern: __SYNDICATE__.QuasiValue.finish((__SYNDICATE__.QuasiValue.ctor(S.Focus, (__SYNDICATE__.QuasiValue.lit(__SYNDICATE__.fromJS(entity)))))), observer: __SYNDICATE__.Turn.ref({ @@ -256,7 +270,7 @@ describe('on', () => { it('asserted with guard', () => expectCodeEqual(`on asserted P when (someTest) => x;`, ` __SYNDICATE__.Turn.active.assertDataflow(() => (someTest) ? ({ - target: currentSyndicateTarget, + target: currentSyndicateTarget(), assertion: __SYNDICATE__.Observe({ pattern: __SYNDICATE__.QuasiValue.finish((__SYNDICATE__.QuasiValue.lit(__SYNDICATE__.fromJS(P)))), observer: __SYNDICATE__.Turn.ref({ diff --git a/packages/loader/src/index.ts b/packages/loader/src/index.ts index 2394e96..adfee7f 100644 --- a/packages/loader/src/index.ts +++ b/packages/loader/src/index.ts @@ -7,7 +7,7 @@ import Pos = Syntax.Pos; import * as Syndicate from '@syndicate-lang/core'; Object.defineProperty(globalThis, 'currentSyndicateTarget', { - value: Syndicate.Dataspace.local, + value: () => Syndicate.Dataspace.local, writable: false, });