septima-lang 0.0.5 → 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/parser.js +9 -5
- package/dist/src/runtime.d.ts +2 -1
- package/dist/src/runtime.js +9 -5
- package/dist/src/septima.d.ts +3 -3
- package/dist/src/septima.js +10 -10
- package/dist/tests/septima-compute-module.spec.js +9 -3
- package/dist/tests/septima.spec.js +40 -7
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/jest-output.json +1 -1
- package/package.json +1 -1
- package/src/parser.ts +8 -4
- package/src/runtime.ts +8 -3
- package/src/septima.ts +15 -8
- package/tests/septima-compute-module.spec.ts +10 -2
- package/tests/septima.spec.ts +47 -6
package/tests/septima.spec.ts
CHANGED
|
@@ -16,7 +16,7 @@ function run(input: string) {
|
|
|
16
16
|
*/
|
|
17
17
|
function runSink(input: string) {
|
|
18
18
|
const septima = new Septima()
|
|
19
|
-
const res = septima.compute(input)
|
|
19
|
+
const res = septima.compute(input, {}, 'quiet', {})
|
|
20
20
|
|
|
21
21
|
if (res.tag !== 'sink') {
|
|
22
22
|
throw new Error(`Not a sink: ${res.value}`)
|
|
@@ -431,6 +431,10 @@ describe('septima', () => {
|
|
|
431
431
|
expect(run(`let triple = (fun(a) 3*a); triple(100) - triple(90)`)).toEqual(30)
|
|
432
432
|
expect(run(`let triple = fun(a) 3*a; triple(100) - triple(90)`)).toEqual(30)
|
|
433
433
|
})
|
|
434
|
+
test('allows a dangling comma, at the call site, after the last actual argument', () => {
|
|
435
|
+
expect(run(`let triple = (fun(a) 3*a); triple(100,)`)).toEqual(300)
|
|
436
|
+
expect(run(`let mean = (fun(a,b) (a+b)/2); mean(4, 28,)`)).toEqual(16)
|
|
437
|
+
})
|
|
434
438
|
describe('arrow function notation', () => {
|
|
435
439
|
test('a single formal argument does not need to be surrounded with parenthesis', () => {
|
|
436
440
|
expect(run(`let triple = a => 3*a; triple(100)`)).toEqual(300)
|
|
@@ -462,7 +466,7 @@ describe('septima', () => {
|
|
|
462
466
|
expect(run(`let pi = fun() 3.14; 2*pi()`)).toEqual(6.28)
|
|
463
467
|
expect(run(`(fun() 3.14)()*2`)).toEqual(6.28)
|
|
464
468
|
})
|
|
465
|
-
test('
|
|
469
|
+
test('errors on arg list mismatch', () => {
|
|
466
470
|
expect(() => run(`let quadSum = fun(a,b,c,d) a+b+c+d; quadSum(4,8,2)`)).toThrowError(
|
|
467
471
|
'Arg list length mismatch: expected 4 but got 3',
|
|
468
472
|
)
|
|
@@ -522,6 +526,9 @@ describe('septima', () => {
|
|
|
522
526
|
expect(run(`let f = fun (a) if (a > 0) a else sink; 2+f(-1)+4`)).toEqual(undefined)
|
|
523
527
|
expect(run(`let f = fun (a) if (a > 0) a else sink; 2+f(3)+4`)).toEqual(9)
|
|
524
528
|
})
|
|
529
|
+
test('the "undefined" literal is an alias for "sink"', () => {
|
|
530
|
+
expect(run(`let x = sink; 5+8+9+x+20+30`)).toEqual(undefined)
|
|
531
|
+
})
|
|
525
532
|
test('an array can hold a sink without becoming a sink itself', () => {
|
|
526
533
|
expect(run(`let f = fun (a) if (a > 0) a else sink; [f(1), f(-1), f(8)]`)).toEqual([1, undefined, 8])
|
|
527
534
|
})
|
|
@@ -621,6 +628,13 @@ describe('septima', () => {
|
|
|
621
628
|
].join('\n'),
|
|
622
629
|
)
|
|
623
630
|
})
|
|
631
|
+
test(`can also appear in code as undefined!`, () => {
|
|
632
|
+
expect(runSink(`1000 + undefined!`).trace).toEqual(
|
|
633
|
+
[` at (1:1..17) 1000 + undefined!`, ` at (1:1..17) 1000 + undefined!`, ` at (1:8..17) undefined!`].join(
|
|
634
|
+
'\n',
|
|
635
|
+
),
|
|
636
|
+
)
|
|
637
|
+
})
|
|
624
638
|
})
|
|
625
639
|
describe('sink!!', () => {
|
|
626
640
|
test(`captures the expression trace and the symbol-table at runtime`, () => {
|
|
@@ -631,7 +645,7 @@ describe('septima', () => {
|
|
|
631
645
|
x: 30,
|
|
632
646
|
y: 40,
|
|
633
647
|
})
|
|
634
|
-
expect(Object.keys(actual.symbols ?? {})).toEqual(['Object', 'a', 'f', 'x', 'y'])
|
|
648
|
+
expect(Object.keys(actual.symbols ?? {})).toEqual(['Object', 'args', 'a', 'f', 'x', 'y'])
|
|
635
649
|
expect(actual.trace).toEqual(
|
|
636
650
|
[
|
|
637
651
|
` at (1:1..58) let a = 2; let f = fun(x, y) x * y * sink!! * a; f(30, 40)`,
|
|
@@ -649,6 +663,11 @@ describe('septima', () => {
|
|
|
649
663
|
n: -3,
|
|
650
664
|
})
|
|
651
665
|
})
|
|
666
|
+
test(`can also appear in code as undefined!!`, () => {
|
|
667
|
+
expect(runSink(`let f = fun (n) undefined!!; f(18)`).symbols).toMatchObject({
|
|
668
|
+
n: 18,
|
|
669
|
+
})
|
|
670
|
+
})
|
|
652
671
|
})
|
|
653
672
|
|
|
654
673
|
describe('array methods', () => {
|
|
@@ -803,7 +822,7 @@ describe('septima', () => {
|
|
|
803
822
|
const preimports = {
|
|
804
823
|
libA: `{ plus10: fun (n) n+10, plus20: fun (n) n+20}`,
|
|
805
824
|
}
|
|
806
|
-
expect(septima.compute(input, preimports)).toMatchObject({ value: 36 })
|
|
825
|
+
expect(septima.compute(input, preimports, 'quiet', {})).toMatchObject({ value: 36 })
|
|
807
826
|
})
|
|
808
827
|
test('supports multiple preimports', () => {
|
|
809
828
|
const septima = new Septima()
|
|
@@ -813,13 +832,35 @@ describe('septima', () => {
|
|
|
813
832
|
a: `{ calc: fun (n) n+10 }`,
|
|
814
833
|
b: `{ calc: fun (n) n+20 }`,
|
|
815
834
|
}
|
|
816
|
-
expect(septima.compute(input, preimports)).toMatchObject({ value: 35 })
|
|
835
|
+
expect(septima.compute(input, preimports, 'quiet', {})).toMatchObject({ value: 35 })
|
|
836
|
+
})
|
|
837
|
+
})
|
|
838
|
+
describe('args', () => {
|
|
839
|
+
test('are bounded at runtime to a special variable called "args"', () => {
|
|
840
|
+
const septima = new Septima()
|
|
841
|
+
expect(
|
|
842
|
+
septima.compute(`args.a + '_' + args.color[0] + '_' + args.b + '_' + args.color[1]`, {}, 'quiet', {
|
|
843
|
+
a: 'Sunday',
|
|
844
|
+
b: 'Monday',
|
|
845
|
+
color: ['Red', 'Green'],
|
|
846
|
+
}),
|
|
847
|
+
).toMatchObject({ value: 'Sunday_Red_Monday_Green' })
|
|
848
|
+
})
|
|
849
|
+
test('are shadowed by a program-defined "args" symbol', () => {
|
|
850
|
+
const septima = new Septima()
|
|
851
|
+
expect(
|
|
852
|
+
septima.compute(`let args = {color: 'Green' }; args.color`, {}, 'quiet', {
|
|
853
|
+
color: 'Red',
|
|
854
|
+
}),
|
|
855
|
+
).toMatchObject({ value: 'Green' })
|
|
856
|
+
})
|
|
857
|
+
test('are supported also via the Septima.run() API', () => {
|
|
858
|
+
expect(Septima.run(`args.a + args.b`, undefined, { a: 100, b: 2 })).toEqual(102)
|
|
817
859
|
})
|
|
818
860
|
})
|
|
819
861
|
test.todo('support file names in locations')
|
|
820
862
|
test.todo('string interpolation via `foo` strings')
|
|
821
863
|
test.todo('imports')
|
|
822
|
-
test.todo('arrow functions')
|
|
823
864
|
test.todo('optional parameters')
|
|
824
865
|
test.todo('optional type annotations?')
|
|
825
866
|
test.todo('allow redundant commas')
|