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.
@@ -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('error on arg list mismatch', () => {
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')