Repository: source-academy/js-slang (ts)

Issue:
Phrasing of error messages for runtime stack overflow
Error messages for runtime stack overflow or excessive time consumption should never include a phrasing like "infinite loop detected" or the like. Infinite loops cannot be detected.

(This may have been fixed already; cannot check this right now.)

Pull request:
Changed stack overflow error message
 from 'Infinite recursion' to 'Maximum call stack size exceeded'.

Resolves #148 

Patch:
diff --git a/src/interpreter-errors.ts b/src/interpreter-errors.ts
index 5676e840..f8842ff9 100644
--- a/src/interpreter-errors.ts
+++ b/src/interpreter-errors.ts
@@ -73,7 +73,9 @@ export class MaximumStackLimitExceeded extends RuntimeSourceError {
 
   public explain() {
     const repr = (call: es.CallExpression) => generate(call, { generator: this.customGenerator })
-    return 'Infinite recursion\n  ' + this.calls.map(call => repr(call) + '..').join('  ')
+    return (
+      'Maximum call stack size exceeded\n  ' + this.calls.map(call => repr(call) + '..').join('  ')
+    )
   }
 
   public elaborate() {


Test patch:
diff --git a/src/__tests__/__snapshots__/index.ts.snap b/src/__tests__/__snapshots__/index.ts.snap
index 2d120f89..bb32d4fe 100644
--- a/src/__tests__/__snapshots__/index.ts.snap
+++ b/src/__tests__/__snapshots__/index.ts.snap
@@ -48,7 +48,7 @@ Object {
 f(list(1, 2));",
   "displayResult": Array [],
   "errors": Any<Array>,
-  "parsedErrors": "Line 1: Infinite recursion
+  "parsedErrors": "Line 1: Maximum call stack size exceeded
   f([1, [2, null]])..  f([1, [2, null]])..  f([1, [2, null]])..",
   "result": undefined,
   "resultStatus": "error",
@@ -189,7 +189,7 @@ Object {
 f(list(1, 2));",
   "displayResult": Array [],
   "errors": Any<Array>,
-  "parsedErrors": "Line 1: Infinite recursion
+  "parsedErrors": "Line 1: Maximum call stack size exceeded
   f([1, [2, null]])..  f([1, [2, null]])..  f([1, [2, null]])..",
   "result": undefined,
   "resultStatus": "error",
@@ -232,7 +232,7 @@ Object {
   "code": "(x => x(x)(x))(x => x(x)(x));",
   "displayResult": Array [],
   "errors": Any<Array>,
-  "parsedErrors": "Line 1: Infinite recursion
+  "parsedErrors": "Line 1: Maximum call stack size exceeded
   x(x => x(x)(x))..  x(x => x(x)(x))..  x(x => x(x)(x))..",
   "result": undefined,
   "resultStatus": "error",
@@ -246,7 +246,7 @@ Object {
   "code": "function f(x) {return x(x)(x);} f(f);",
   "displayResult": Array [],
   "errors": Any<Array>,
-  "parsedErrors": "Line 1: Infinite recursion
+  "parsedErrors": "Line 1: Maximum call stack size exceeded
   x(function f(x) {
   return x(x)(x);
 })..  x(function f(x) {
diff --git a/src/__tests__/index.ts b/src/__tests__/index.ts
index 702babc3..8e8b6fea 100644
--- a/src/__tests__/index.ts
+++ b/src/__tests__/index.ts
@@ -84,7 +84,7 @@ test('parseError for missing semicolon', () => {
 
 test('Simple arrow function infinite recursion represents CallExpression well', () => {
   return expectParsedErrorNoErrorSnapshot('(x => x(x)(x))(x => x(x)(x));').toMatchInlineSnapshot(`
-"Line 1: Infinite recursion
+"Line 1: Maximum call stack size exceeded
   x(x => x(x)(x))..  x(x => x(x)(x))..  x(x => x(x)(x)).."
 `)
 }, 30000)
@@ -92,7 +92,7 @@ test('Simple arrow function infinite recursion represents CallExpression well',
 test('Simple function infinite recursion represents CallExpression well', () => {
   return expectParsedErrorNoErrorSnapshot('function f(x) {return x(x)(x);} f(f);')
     .toMatchInlineSnapshot(`
-"Line 1: Infinite recursion
+"Line 1: Maximum call stack size exceeded
   x(function f(x) {
   return x(x)(x);
 })..  x(function f(x) {
@@ -139,7 +139,7 @@ test('Arrow function infinite recursion with list args represents CallExpression
   `,
     2
   ).toMatchInlineSnapshot(`
-"Line 1: Infinite recursion
+"Line 1: Maximum call stack size exceeded
   f([1, [2, null]])..  f([1, [2, null]])..  f([1, [2, null]]).."
 `)
 }, 30000)
@@ -152,7 +152,7 @@ test('Function infinite recursion with list args represents CallExpression well'
   `,
     2
   ).toMatchInlineSnapshot(`
-"Line 1: Infinite recursion
+"Line 1: Maximum call stack size exceeded
   f([1, [2, null]])..  f([1, [2, null]])..  f([1, [2, null]]).."
 `)
 }, 30000)
@@ -161,14 +161,18 @@ test('Arrow function infinite recursion with different args represents CallExpre
   return expectParsedErrorNoSnapshot(stripIndent`
     const f = i => f(i+1) - 1;
     f(0);
-  `).toEqual(expect.stringMatching(/^Line 1: Infinite recursion\n\ *(f\(\d*\)[^f]{2,4}){3}/))
+  `).toEqual(
+    expect.stringMatching(/^Line 1: Maximum call stack size exceeded\n\ *(f\(\d*\)[^f]{2,4}){3}/)
+  )
 }, 30000)
 
 test('Function infinite recursion with different args represents CallExpression well', () => {
   return expectParsedErrorNoSnapshot(stripIndent`
     function f(i) { return f(i+1) - 1; }
     f(0);
-  `).toEqual(expect.stringMatching(/^Line 1: Infinite recursion\n\ *(f\(\d*\)[^f]{2,4}){3}/))
+  `).toEqual(
+    expect.stringMatching(/^Line 1: Maximum call stack size exceeded\n\ *(f\(\d*\)[^f]{2,4}){3}/)
+  )
 }, 30000)
 
 test('Functions passed into non-source functions remain equal', () => {
diff --git a/src/__tests__/interpreter-errors.ts b/src/__tests__/interpreter-errors.ts
index bc4bfd3f..c985df3e 100644
--- a/src/__tests__/interpreter-errors.ts
+++ b/src/__tests__/interpreter-errors.ts
@@ -119,7 +119,7 @@ test('Infinite recursion with a block bodied function', () => {
     i(1000);
   `,
     4
-  ).toEqual(expect.stringMatching(/Infinite recursion\n *(i\(\d*\)[^i]{2,4}){3}/))
+  ).toEqual(expect.stringMatching(/Maximum call stack size exceeded\n *(i\(\d*\)[^i]{2,4}){3}/))
 }, 10000)
 
 test('Infinite recursion with function calls in argument', () => {
@@ -134,7 +134,9 @@ test('Infinite recursion with function calls in argument', () => {
     i(1000, 1);
   `,
     4
-  ).toEqual(expect.stringMatching(/Infinite recursion\n *(i\(\d*, 1\)[^i]{2,4}){2}[ir]/))
+  ).toEqual(
+    expect.stringMatching(/Maximum call stack size exceeded\n *(i\(\d*, 1\)[^i]{2,4}){2}[ir]/)
+  )
 }, 10000)
 
 test('Infinite recursion of mutually recursive functions', () => {
@@ -149,7 +151,11 @@ test('Infinite recursion of mutually recursive functions', () => {
     f(1000);
   `,
     4
-  ).toEqual(expect.stringMatching(/Infinite recursion\n([^f]*f[^g]*g[^f]*f|[^g]*g[^f]*f[^g]*g)/))
+  ).toEqual(
+    expect.stringMatching(
+      /Maximum call stack size exceeded\n([^f]*f[^g]*g[^f]*f|[^g]*g[^f]*f[^g]*g)/
+    )
+  )
 })
 
 test('Error when calling non function value undefined', () => {
diff --git a/src/__tests__/tailcall-return.ts b/src/__tests__/tailcall-return.ts
index 23c85e40..3a4f8159 100644
--- a/src/__tests__/tailcall-return.ts
+++ b/src/__tests__/tailcall-return.ts
@@ -10,7 +10,7 @@ test('Check that stack is at most 10k in size', () => {
       }
     }
     f(10000);
-  `).toEqual(expect.stringMatching(/Infinite recursion\n([^f]*f){3}/))
+  `).toEqual(expect.stringMatching(/Maximum call stack size exceeded\n([^f]*f){3}/))
 }, 10000)
 
 test('Simple tail call returns work', () => {