Browse Source

Add length function; preserve Number node line numbers

master
Dylan Baker 5 years ago
parent
commit
da6ce44556
5 changed files with 37 additions and 8 deletions
  1. 11
    0
      src/core.js
  2. 3
    1
      src/parser.js
  3. 19
    3
      test/coreTest.js
  4. 2
    2
      test/evaluatorTest.js
  5. 2
    2
      test/parserTest.js

+ 11
- 0
src/core.js View File

@@ -1,4 +1,5 @@
1 1
 const AST = require('./ast')
2
+const OsloError = require('./osloError')
2 3
 
3 4
 module.exports = {
4 5
   '+': (a, b) => new AST.Number({ value: a.value + b.value }),
@@ -11,4 +12,14 @@ module.exports = {
11 12
   '>=': (a, b) => new AST.Boolean({ value: a.value >= b.value }),
12 13
   '<=': (a, b) => new AST.Boolean({ value: a.value <= b.value }),
13 14
   'list': (...args) => { return new AST.List({ elements: args }) },
15
+  'length': xs => {
16
+    if (xs.constructor == AST.List) {
17
+      return new AST.Number({ value: xs.elements.length })
18
+    }
19
+
20
+    return new OsloError({
21
+      line: xs.line,
22
+      message: 'length: argument is not a list'
23
+    })
24
+  }
14 25
 }

+ 3
- 1
src/parser.js View File

@@ -171,8 +171,10 @@ module.exports = class Parser {
171 171
   }
172 172
 
173 173
   number() {
174
+    const token = this.tokenStream.eat(tokenTypes.NUMBER)
174 175
     return new AST.Number({
175
-      value: this.tokenStream.eat(tokenTypes.NUMBER).value,
176
+      line: token.line,
177
+      value: token.value,
176 178
     })
177 179
   }
178 180
 

+ 19
- 3
test/coreTest.js View File

@@ -10,9 +10,25 @@ test('list function', t => {
10 10
   const tree = helpers.evaluate('(list 1 2 3)')
11 11
   t.deepEqual(tree[0], new AST.List({
12 12
     elements: [
13
-      new AST.Number({ value: 1 }),
14
-      new AST.Number({ value: 2 }),
15
-      new AST.Number({ value: 3 }),
13
+      new AST.Number({ value: 1, line: 1 }),
14
+      new AST.Number({ value: 2, line: 1 }),
15
+      new AST.Number({ value: 3, line: 1 }),
16 16
     ]
17 17
   }))
18 18
 })
19
+
20
+test('length function', t => {
21
+  t.plan(2)
22
+
23
+  let tree = helpers.evaluate('(length (list 1 2 3))')
24
+  t.deepEqual(tree[0], new AST.Number({ value: 3 }))
25
+
26
+  tree = helpers.evaluate('(length 5)')
27
+  t.deepEqual(
28
+    tree,
29
+    new OsloError({
30
+      line: 1,
31
+      message: 'length: argument is not a list'
32
+    })
33
+  )
34
+})

+ 2
- 2
test/evaluatorTest.js View File

@@ -32,10 +32,10 @@ test('conditionals', t => {
32 32
   t.plan(3)
33 33
 
34 34
   let tree = helpers.evaluate('(if #t 1 0)')
35
-  t.deepEqual(tree[0], new AST.Number({ value: 1 }))
35
+  t.deepEqual(tree[0], new AST.Number({ value: 1, line: 1 }))
36 36
 
37 37
   tree = helpers.evaluate('(if #f 1 0)')
38
-  t.deepEqual(tree[0], new AST.Number({ value: 0 }))
38
+  t.deepEqual(tree[0], new AST.Number({ value: 0, line: 1 }))
39 39
 
40 40
   tree = helpers.evaluate('(if (= (+ 4 9) (- 20 7)) (+ 10 9) (- 4 2))')
41 41
   t.deepEqual(tree[0], new AST.Number({ value: 19 }))

+ 2
- 2
test/parserTest.js View File

@@ -62,11 +62,11 @@ test('parse lambdas and expressions in function position', t => {
62 62
           function: new AST.Identifier({ name: '+', line: 1 }),
63 63
           args: [
64 64
             new AST.Identifier({ name: 'n', line: 1 }),
65
-            new AST.Number({ value: 1 }),
65
+            new AST.Number({ value: 1, line: 1 }),
66 66
           ],
67 67
         }),
68 68
       }),
69
-      args: [new AST.Number({ value: 5 })],
69
+      args: [new AST.Number({ value: 5, line: 1 })],
70 70
     }),
71 71
   ])
72 72
 })

Loading…
Cancel
Save