142 lines
6.5 KiB
TypeScript
142 lines
6.5 KiB
TypeScript
/// SPDX-License-Identifier: GPL-3.0-or-later
|
|
/// SPDX-FileCopyrightText: Copyright © 2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
|
|
|
|
import { compile, CompileOptions, Syntax } from '../src/index';
|
|
import Pos = Syntax.Pos;
|
|
import './test-utils';
|
|
|
|
type Error = { message: string, start: Pos | undefined, end: Pos | undefined };
|
|
|
|
function translate(source: string, options: Partial<CompileOptions> = {}): { code: string, errors: Error[] } {
|
|
const errors: Error[] = [];
|
|
const result = compile({
|
|
... options,
|
|
module: 'none',
|
|
source,
|
|
emitError: (message, start, end) => errors.push({ message, start, end }),
|
|
});
|
|
return { code: result.text, errors };
|
|
}
|
|
|
|
function translateNoErrors(source: string): string {
|
|
const o = translate(source);
|
|
expect(o.errors.length).toBe(0);
|
|
return o.code;
|
|
}
|
|
|
|
describe('react', () => {
|
|
it('without label', () => {
|
|
expect(translateNoErrors(`react { a; b; c; }`)).toBe(
|
|
`__SYNDICATE__.Turn.active.facet(() => {const currentSyndicateFacet = __SYNDICATE__.Turn.activeFacet; a; b; c; });`);
|
|
});
|
|
it('with label', () => {
|
|
expect(translateNoErrors(`someLabel: react { a; b; c; }`)).toBe(
|
|
`__SYNDICATE__.Turn.active.facet(() => {const currentSyndicateFacet = __SYNDICATE__.Turn.activeFacet; const someLabel = currentSyndicateFacet; a; b; c; });`);
|
|
});
|
|
});
|
|
|
|
describe('spawn', () => {
|
|
it('without name', () => {
|
|
expect(translateNoErrors(`spawn { a; b; c; }`)).toBe(
|
|
`__SYNDICATE__.Dataspace._spawn(() => { const currentSyndicateFacet = __SYNDICATE__.Turn.activeFacet; a; b; c; });`);
|
|
});
|
|
it('with name', () => {
|
|
expect(translateNoErrors(`spawn named 'foo' { a; b; c; }`)).toBe(
|
|
`__SYNDICATE__.Dataspace._spawn(() => { const currentSyndicateFacet = __SYNDICATE__.Turn.activeFacet; currentSyndicateFacet.actor.name = 'foo'; a; b; c; });`);
|
|
});
|
|
it('with missing name (known incorrect parsing and codegen)', () => {
|
|
// At present, the expr() parser accepts *empty input*. TODO: something better.
|
|
expect(translateNoErrors(`spawn named { a; b; c; }`)).toBe(
|
|
`__SYNDICATE__.Dataspace._spawn(() => { const currentSyndicateFacet = __SYNDICATE__.Turn.activeFacet; currentSyndicateFacet.actor.name = ; a; b; c; });`);
|
|
});
|
|
});
|
|
|
|
describe('stop', () => {
|
|
it('non-statement', () => {
|
|
expect(translateNoErrors(`stop`)).toBe(
|
|
`stop`);
|
|
});
|
|
it('without facet, without body', () => {
|
|
expect(translateNoErrors(`stop;`)).toBe(
|
|
`__SYNDICATE__.Turn.active._stop(currentSyndicateFacet, () => {const currentSyndicateFacet = __SYNDICATE__.Turn.activeFacet;});`);
|
|
});
|
|
it('without facet, empty body', () => {
|
|
expect(translateNoErrors(`stop {}`)).toBe(
|
|
`__SYNDICATE__.Turn.active._stop(currentSyndicateFacet, () => {const currentSyndicateFacet = __SYNDICATE__.Turn.activeFacet;});`);
|
|
});
|
|
it('without facet, non-empty body', () => {
|
|
expect(translateNoErrors(`stop { a; b; }`)).toBe(
|
|
`__SYNDICATE__.Turn.active._stop(currentSyndicateFacet, () => {const currentSyndicateFacet = __SYNDICATE__.Turn.activeFacet; a; b; });`);
|
|
});
|
|
it('with facet, without body', () => {
|
|
expect(translateNoErrors(`stop x.y;`)).toBe(
|
|
`__SYNDICATE__.Turn.active._stop(x.y, () => {const currentSyndicateFacet = __SYNDICATE__.Turn.activeFacet;});`);
|
|
});
|
|
it('with facet, empty body', () => {
|
|
expect(translateNoErrors(`stop x.y {}`)).toBe(
|
|
`__SYNDICATE__.Turn.active._stop(x.y, () => {const currentSyndicateFacet = __SYNDICATE__.Turn.activeFacet;});`);
|
|
});
|
|
it('with facet, non-empty body', () => {
|
|
expect(translateNoErrors(`stop x.y { a; b; }`)).toBe(
|
|
`__SYNDICATE__.Turn.active._stop(x.y, () => {const currentSyndicateFacet = __SYNDICATE__.Turn.activeFacet; a; b; });`);
|
|
});
|
|
it('nested stop, no labels', () => {
|
|
expect(translateNoErrors(`stop { stop; }`)).toBe(
|
|
`__SYNDICATE__.Turn.active._stop(currentSyndicateFacet, () => {const currentSyndicateFacet = __SYNDICATE__.Turn.activeFacet; __SYNDICATE__.Turn.active._stop(currentSyndicateFacet, () => {const currentSyndicateFacet = __SYNDICATE__.Turn.activeFacet;}); });`);
|
|
});
|
|
});
|
|
|
|
describe('during', () => {
|
|
it('stop in body', () => {
|
|
expect(translateNoErrors(`during P => { a; stop; b; }`)).toBe(
|
|
`__SYNDICATE__.Turn.active.assertDataflow(() => ({ target: currentSyndicateTarget, assertion: __SYNDICATE__.Observe({
|
|
pattern: __SYNDICATE__.QuasiValue.finish((__SYNDICATE__.QuasiValue.lit(__SYNDICATE__.fromJS(P)))),
|
|
observer: __SYNDICATE__.Turn.ref(__SYNDICATE__.assertionFacetObserver(
|
|
(__vs) => {
|
|
if (Array.isArray(__vs)) {
|
|
|
|
a; __SYNDICATE__.Turn.active._stop(currentSyndicateFacet, () => {const currentSyndicateFacet = __SYNDICATE__.Turn.activeFacet;}); b;
|
|
}
|
|
}
|
|
))
|
|
}) }));`);
|
|
});
|
|
});
|
|
|
|
describe('once', () => {
|
|
it('basics with block', () => {
|
|
expect(translateNoErrors(`once asserted P => { a; b; }`)).toBe(
|
|
`__SYNDICATE__.Turn.active.facet(() => {const __once_facet = __SYNDICATE__.Turn.activeFacet; __SYNDICATE__.Turn.active.assertDataflow(() => ({
|
|
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)) {
|
|
|
|
__SYNDICATE__.Turn.active._stop(__once_facet, () => { a; b; })
|
|
}
|
|
}
|
|
}),
|
|
}),
|
|
}));});`);
|
|
});
|
|
it('basics with statement', () => {
|
|
expect(translateNoErrors(`once asserted P => x;`)).toBe(
|
|
`__SYNDICATE__.Turn.active.facet(() => {const __once_facet = __SYNDICATE__.Turn.activeFacet; __SYNDICATE__.Turn.active.assertDataflow(() => ({
|
|
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)) {
|
|
|
|
__SYNDICATE__.Turn.active._stop(__once_facet, () => {x;})
|
|
}
|
|
}
|
|
}),
|
|
}),
|
|
}));});`);
|
|
});
|
|
});
|