Repository: source-academy/js-slang
Pull request #108 (2018-11-01 15:22:58)

Fix parser arrow functions
Realized I was testing the wrong thing in #107. 
Fixed the errors and wrote correct tests this time (see mci-parser.ts)

@martin-henz please check whether the output in https://github.com/source-academy/js-slang/blob/c58006ca36867e79f1819d2c99d953bf1af7ddab/src/__tests__/__snapshots__/mci-parser.ts.snap is what's expected.

Should work with docker after merging.


Patch:
diff --git a/src/stdlib/parser.js b/src/stdlib/parser.js
index 4c9c5fd5..942153e1 100644
--- a/src/stdlib/parser.js
+++ b/src/stdlib/parser.js
@@ -90,7 +90,7 @@ case 2: case 3: case 69: case 73: case 78:
  this.$ = [];
 break;
 case 4:
- this.$ = pair($$[$0-1], $$[$0]);
+ this.$ = [$$[$0-1], $$[$0]];
 break;
 case 8:
 
@@ -207,7 +207,7 @@ case 21:
 				tag: 'conditional_statement',
 				predicate: $$[$0-6],
 				consequent: { tag: 'block', body: $$[$0-3] },
-				alternative: pair($$[$0], []),
+				alternative: [$$[$0], []],
 				line: yylineno
 			};
 
@@ -317,8 +317,8 @@ case 44:
       location: {
         start_line: _$[$0 - 2].first_line,
         start_col: _$[$0 - 2].first_column,
-        end_line: _$[$02].first_line,
-        end_col: _$[$02].first_column
+        end_line: _$[$0 - 2].first_line,
+        end_col: _$[$0 - 2].first_column
       }
     };
   } else {


Test patch:
diff --git a/src/__tests__/__snapshots__/index.ts.snap b/src/__tests__/__snapshots__/index.ts.snap
index aa32396b..fc429cc0 100644
--- a/src/__tests__/__snapshots__/index.ts.snap
+++ b/src/__tests__/__snapshots__/index.ts.snap
@@ -237,6 +237,20 @@ exports[`Inifinite recursion with list args represents CallExpression well 1`] =
   f([1, [2, []]])..  f([1, [2, []]])..  f([1, [2, []]]).."
 `;
 
+exports[`Metacircular Interpreter parses Arrow Function Assignments properly 1`] = `
+Object {
+  "status": "finished",
+  "value": "[{\\"tag\\":\\"constant_declaration\\",\\"name\\":\\"y\\",\\"value\\":{\\"tag\\":\\"function_definition\\",\\"parameters\\":[{\\"tag\\":\\"name\\",\\"name\\":\\"x\\",\\"line\\":0},[]],\\"body\\":{\\"tag\\":\\"return_statement\\",\\"expression\\":{\\"tag\\":\\"application\\",\\"operator\\":{\\"tag\\":\\"name\\",\\"name\\":\\"+\\",\\"line\\":0},\\"operands\\":[{\\"tag\\":\\"name\\",\\"name\\":\\"x\\",\\"line\\":0},[1,[]]],\\"line\\":0},\\"line\\":0},\\"line\\":0,\\"location\\":{\\"start_line\\":1,\\"start_col\\":10,\\"end_line\\":1,\\"end_col\\":10}},\\"line\\":0},[]]",
+}
+`;
+
+exports[`Metacircular Interpreter parses Arrow Function Expressions properly 1`] = `
+Object {
+  "status": "finished",
+  "value": "[{\\"tag\\":\\"function_definition\\",\\"parameters\\":[{\\"tag\\":\\"name\\",\\"name\\":\\"x\\",\\"line\\":0},[]],\\"body\\":{\\"tag\\":\\"return_statement\\",\\"expression\\":{\\"tag\\":\\"application\\",\\"operator\\":{\\"tag\\":\\"name\\",\\"name\\":\\"+\\",\\"line\\":0},\\"operands\\":[{\\"tag\\":\\"name\\",\\"name\\":\\"x\\",\\"line\\":0},[1,[]]],\\"line\\":0},\\"line\\":0},\\"line\\":0,\\"location\\":{\\"start_line\\":1,\\"start_col\\":0,\\"end_line\\":1,\\"end_col\\":0}},[]]",
+}
+`;
+
 exports[`Simple inifinite recursion represents CallExpression well 1`] = `
 "Line 1: Infinite recursion
   x(x => x(x))..  x(x => x(x))..  x(x => x(x)).."
diff --git a/src/__tests__/__snapshots__/mci-parser.ts.snap b/src/__tests__/__snapshots__/mci-parser.ts.snap
new file mode 100644
index 00000000..db67e8bf
--- /dev/null
+++ b/src/__tests__/__snapshots__/mci-parser.ts.snap
@@ -0,0 +1,102 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Parse an arrow function 1`] = `
+Array [
+  Object {
+    "body": Object {
+      "expression": Object {
+        "line": 0,
+        "operands": Array [
+          Object {
+            "line": 0,
+            "name": "x",
+            "tag": "name",
+          },
+          Array [
+            1,
+            Array [],
+          ],
+        ],
+        "operator": Object {
+          "line": 0,
+          "name": "+",
+          "tag": "name",
+        },
+        "tag": "application",
+      },
+      "line": 0,
+      "tag": "return_statement",
+    },
+    "line": 0,
+    "location": Object {
+      "end_col": 0,
+      "end_line": 1,
+      "start_col": 0,
+      "start_line": 1,
+    },
+    "parameters": Array [
+      Object {
+        "line": 0,
+        "name": "x",
+        "tag": "name",
+      },
+      Array [],
+    ],
+    "tag": "function_definition",
+  },
+  Array [],
+]
+`;
+
+exports[`Parse arrow function assignment 1`] = `
+Array [
+  Object {
+    "line": 0,
+    "name": "y",
+    "tag": "constant_declaration",
+    "value": Object {
+      "body": Object {
+        "expression": Object {
+          "line": 0,
+          "operands": Array [
+            Object {
+              "line": 0,
+              "name": "x",
+              "tag": "name",
+            },
+            Array [
+              1,
+              Array [],
+            ],
+          ],
+          "operator": Object {
+            "line": 0,
+            "name": "+",
+            "tag": "name",
+          },
+          "tag": "application",
+        },
+        "line": 0,
+        "tag": "return_statement",
+      },
+      "line": 0,
+      "location": Object {
+        "end_col": 10,
+        "end_line": 1,
+        "start_col": 10,
+        "start_line": 1,
+      },
+      "parameters": Array [
+        Object {
+          "line": 0,
+          "name": "x",
+          "tag": "name",
+        },
+        Array [],
+      ],
+      "tag": "function_definition",
+    },
+  },
+  Array [],
+]
+`;
diff --git a/src/__tests__/__snapshots__/parser.ts.snap b/src/__tests__/__snapshots__/parser.ts.snap
index 817d6227..ad712b75 100644
--- a/src/__tests__/__snapshots__/parser.ts.snap
+++ b/src/__tests__/__snapshots__/parser.ts.snap
@@ -260,3 +260,17 @@ Node {
   "type": "Program",
 }
 `;
+
+exports[`Parse an arrow function assignment in js-slang 1`] = `
+Object {
+  "status": "finished",
+  "value": "[{\\"tag\\":\\"constant_declaration\\",\\"name\\":\\"y\\",\\"value\\":{\\"tag\\":\\"function_definition\\",\\"parameters\\":[{\\"tag\\":\\"name\\",\\"name\\":\\"x\\",\\"line\\":0},[]],\\"body\\":{\\"tag\\":\\"return_statement\\",\\"expression\\":{\\"tag\\":\\"application\\",\\"operator\\":{\\"tag\\":\\"name\\",\\"name\\":\\"+\\",\\"line\\":0},\\"operands\\":[{\\"tag\\":\\"name\\",\\"name\\":\\"x\\",\\"line\\":0},[1,[]]],\\"line\\":0},\\"line\\":0},\\"line\\":0,\\"location\\":{\\"start_line\\":1,\\"start_col\\":10,\\"end_line\\":1,\\"end_col\\":10}},\\"line\\":0},[]]",
+}
+`;
+
+exports[`Parse an arrow function expression in js-slang 1`] = `
+Object {
+  "status": "finished",
+  "value": "[{\\"tag\\":\\"function_definition\\",\\"parameters\\":[{\\"tag\\":\\"name\\",\\"name\\":\\"x\\",\\"line\\":0},[]],\\"body\\":{\\"tag\\":\\"return_statement\\",\\"expression\\":{\\"tag\\":\\"application\\",\\"operator\\":{\\"tag\\":\\"name\\",\\"name\\":\\"+\\",\\"line\\":0},\\"operands\\":[{\\"tag\\":\\"name\\",\\"name\\":\\"x\\",\\"line\\":0},[1,[]]],\\"line\\":0},\\"line\\":0},\\"line\\":0,\\"location\\":{\\"start_line\\":1,\\"start_col\\":0,\\"end_line\\":1,\\"end_col\\":0}},[]]",
+}
+`;
diff --git a/src/__tests__/index.ts b/src/__tests__/index.ts
index a68a9aba..96c10714 100644
--- a/src/__tests__/index.ts
+++ b/src/__tests__/index.ts
@@ -188,3 +188,23 @@ test(
   },
   30000
 )
+
+test('Metacircular Interpreter parses Arrow Function Expressions properly', () => {
+  const code = 'stringify(parse("x => x + 1;"));'
+  const context = mockContext(4)
+  const promise = runInContext(code, context, { scheduler: 'preemptive' })
+  return promise.then(obj => {
+    expect(obj).toMatchSnapshot()
+    expect(obj.status).toBe('finished')
+  })
+})
+
+test('Metacircular Interpreter parses Arrow Function Assignments properly', () => {
+  const code = 'stringify(parse("const y = x => x + 1;"));'
+  const context = mockContext(4)
+  const promise = runInContext(code, context, { scheduler: 'preemptive' })
+  return promise.then(obj => {
+    expect(obj).toMatchSnapshot()
+    expect(obj.status).toBe('finished')
+  })
+})
diff --git a/src/__tests__/mci-parser.ts b/src/__tests__/mci-parser.ts
new file mode 100644
index 00000000..858af044
--- /dev/null
+++ b/src/__tests__/mci-parser.ts
@@ -0,0 +1,18 @@
+import { mockContext } from '../mocks/context'
+//@ts-ignore
+import { Parser } from '../stdlib/parser.js'
+
+const parser = new Parser();
+
+test('Parse an arrow function', () => {
+  const context = mockContext()
+  const program = parser.parse('x => x + 1;', context)
+  expect(program).toMatchSnapshot()
+})
+
+test('Parse arrow function assignment', () => {
+  const context = mockContext()
+  const program = parser.parse('const y = x => x + 1;', context)
+  expect(program).toMatchSnapshot()
+})
+
diff --git a/src/__tests__/parser.ts b/src/__tests__/parser.ts
index 94c25cf1..5e54431c 100644
--- a/src/__tests__/parser.ts
+++ b/src/__tests__/parser.ts
@@ -1,5 +1,6 @@
 import { mockContext } from '../mocks/context'
 import { parse } from '../parser'
+import { runInContext } from '../index'
 
 test('Empty parse returns empty Program Node', () => {
   const context = mockContext()
@@ -24,3 +25,23 @@ test('Parse an arrow function', () => {
   const program = parse('x => x + 1;', context)
   expect(program).toMatchSnapshot()
 })
+
+test('Parse an arrow function expression in js-slang', () => {
+  const code = 'stringify(parse("x => x + 1;"));'
+  const context = mockContext(4)
+  const promise = runInContext(code, context, { scheduler: 'preemptive' })
+  return promise.then(obj => {
+    expect(obj).toMatchSnapshot()
+    expect(obj.status).toBe('finished')
+  })
+})
+
+test('Parse an arrow function assignment in js-slang', () => {
+  const code = 'stringify(parse("const y = x => x + 1;"));'
+  const context = mockContext(4)
+  const promise = runInContext(code, context, { scheduler: 'preemptive' })
+  return promise.then(obj => {
+    expect(obj).toMatchSnapshot()
+    expect(obj.status).toBe('finished')
+  })
+})