diff --git a/src/index.ts b/src/index.ts index 50673ab60..f6d0f1f84 100644 --- a/src/index.ts +++ b/src/index.ts @@ -179,7 +179,7 @@ export function runInContext( value: sandboxedEval(transpiled) } as Result) } catch (error) { - if (error instanceof RuntimeSourceError) { + if (error instanceof RuntimeSourceError || error instanceof ExceptionError) { context.errors.push(error) return resolvedErrorPromise } diff --git a/src/interpreter.ts b/src/interpreter.ts index d9fbff678..c3217984c 100644 --- a/src/interpreter.ts +++ b/src/interpreter.ts @@ -614,9 +614,10 @@ export function* apply( break } catch (e) { // Recover from exception - const globalEnvironment = - context.runtime.environments[context.runtime.environments.length - 1] - context.runtime.environments = [globalEnvironment] + context.runtime.environments = context.runtime.environments.slice( + -context.numberOfOuterEnvironments + ) + const loc = node ? node.loc! : constants.UNKNOWN_LOCATION if (!(e instanceof errors.RuntimeSourceError)) { // The error could've arisen when the builtin called a source function which errored. diff --git a/src/stdlib/__tests__/__snapshots__/list.ts.snap b/src/stdlib/__tests__/__snapshots__/list.ts.snap index 495fc5440..973dea97b 100644 --- a/src/stdlib/__tests__/__snapshots__/list.ts.snap +++ b/src/stdlib/__tests__/__snapshots__/list.ts.snap @@ -161,6 +161,27 @@ Object { "parsedErrors": "Line 1: Error: head(xs) expects a pair as argument xs, but encountered null", "result": undefined, "resultStatus": "error", + "transpiled": "const native = $$NATIVE_STORAGE; +const callIfFuncAndRightArgs = native.operators.get(\\"callIfFuncAndRightArgs\\"); +const boolOrErr = native.operators.get(\\"boolOrErr\\"); +const wrap = native.operators.get(\\"wrap\\"); +const unaryOp = native.operators.get(\\"unaryOp\\"); +const binaryOp = native.operators.get(\\"binaryOp\\"); +const throwIfTimeout = native.operators.get(\\"throwIfTimeout\\"); +const setProp = native.operators.get(\\"setProp\\"); +const getProp = native.operators.get(\\"getProp\\"); +let lastStatementResult = undefined; +(( ) => { + return (() => { + { + { + lastStatementResult = eval(\\"callIfFuncAndRightArgs(list_ref, 1, 0, callIfFuncAndRightArgs(list, 1, 9, 1, 2, 3), 3);\\"); + } + } + return lastStatementResult; + })(); +})(); +", "visualiseListResult": Array [], } `; @@ -190,6 +211,27 @@ Object { "parsedErrors": "Line 1: Error: list_ref(xs, n) expects a positive integer as argument n, but encountered -1", "result": undefined, "resultStatus": "error", + "transpiled": "const native = $$NATIVE_STORAGE; +const callIfFuncAndRightArgs = native.operators.get(\\"callIfFuncAndRightArgs\\"); +const boolOrErr = native.operators.get(\\"boolOrErr\\"); +const wrap = native.operators.get(\\"wrap\\"); +const unaryOp = native.operators.get(\\"unaryOp\\"); +const binaryOp = native.operators.get(\\"binaryOp\\"); +const throwIfTimeout = native.operators.get(\\"throwIfTimeout\\"); +const setProp = native.operators.get(\\"setProp\\"); +const getProp = native.operators.get(\\"getProp\\"); +let lastStatementResult = undefined; +(( ) => { + return (() => { + { + { + lastStatementResult = eval(\\"callIfFuncAndRightArgs(list_ref, 1, 0, callIfFuncAndRightArgs(list, 1, 9, 1, 2, 3), unaryOp(\\\\\\"-\\\\\\", 1, 1, 24));\\"); + } + } + return lastStatementResult; + })(); +})(); +", "visualiseListResult": Array [], } `; @@ -219,6 +261,27 @@ Object { "parsedErrors": "Line 1: Error: list_ref(xs, n) expects a positive integer as argument n, but encountered 1.5", "result": undefined, "resultStatus": "error", + "transpiled": "const native = $$NATIVE_STORAGE; +const callIfFuncAndRightArgs = native.operators.get(\\"callIfFuncAndRightArgs\\"); +const boolOrErr = native.operators.get(\\"boolOrErr\\"); +const wrap = native.operators.get(\\"wrap\\"); +const unaryOp = native.operators.get(\\"unaryOp\\"); +const binaryOp = native.operators.get(\\"binaryOp\\"); +const throwIfTimeout = native.operators.get(\\"throwIfTimeout\\"); +const setProp = native.operators.get(\\"setProp\\"); +const getProp = native.operators.get(\\"getProp\\"); +let lastStatementResult = undefined; +(( ) => { + return (() => { + { + { + lastStatementResult = eval(\\"callIfFuncAndRightArgs(list_ref, 1, 0, callIfFuncAndRightArgs(list, 1, 9, 1, 2, 3), 1.5);\\"); + } + } + return lastStatementResult; + })(); +})(); +", "visualiseListResult": Array [], } `; @@ -248,6 +311,27 @@ Object { "parsedErrors": "Line 1: Error: list_ref(xs, n) expects a positive integer as argument n, but encountered 1", "result": undefined, "resultStatus": "error", + "transpiled": "const native = $$NATIVE_STORAGE; +const callIfFuncAndRightArgs = native.operators.get(\\"callIfFuncAndRightArgs\\"); +const boolOrErr = native.operators.get(\\"boolOrErr\\"); +const wrap = native.operators.get(\\"wrap\\"); +const unaryOp = native.operators.get(\\"unaryOp\\"); +const binaryOp = native.operators.get(\\"binaryOp\\"); +const throwIfTimeout = native.operators.get(\\"throwIfTimeout\\"); +const setProp = native.operators.get(\\"setProp\\"); +const getProp = native.operators.get(\\"getProp\\"); +let lastStatementResult = undefined; +(( ) => { + return (() => { + { + { + lastStatementResult = eval(\\"callIfFuncAndRightArgs(list_ref, 1, 0, callIfFuncAndRightArgs(list, 1, 9, 1, 2, 3), '1');\\"); + } + } + return lastStatementResult; + })(); +})(); +", "visualiseListResult": Array [], } `; @@ -277,6 +361,27 @@ Object { "parsedErrors": "Line 1: Error: build_list(n, fun) expects a positive integer as argument n, but encountered -1", "result": undefined, "resultStatus": "error", + "transpiled": "const native = $$NATIVE_STORAGE; +const callIfFuncAndRightArgs = native.operators.get(\\"callIfFuncAndRightArgs\\"); +const boolOrErr = native.operators.get(\\"boolOrErr\\"); +const wrap = native.operators.get(\\"wrap\\"); +const unaryOp = native.operators.get(\\"unaryOp\\"); +const binaryOp = native.operators.get(\\"binaryOp\\"); +const throwIfTimeout = native.operators.get(\\"throwIfTimeout\\"); +const setProp = native.operators.get(\\"setProp\\"); +const getProp = native.operators.get(\\"getProp\\"); +let lastStatementResult = undefined; +(( ) => { + return (() => { + { + { + lastStatementResult = eval(\\"callIfFuncAndRightArgs(build_list, 1, 0, unaryOp(\\\\\\"-\\\\\\", 1, 1, 11), wrap(x => ({ isTail: false, value: x }), \\\\\\"x => x\\\\\\"));\\"); + } + } + return lastStatementResult; + })(); +})(); +", "visualiseListResult": Array [], } `; @@ -306,6 +411,27 @@ Object { "parsedErrors": "Line 1: Error: build_list(n, fun) expects a positive integer as argument n, but encountered 1.5", "result": undefined, "resultStatus": "error", + "transpiled": "const native = $$NATIVE_STORAGE; +const callIfFuncAndRightArgs = native.operators.get(\\"callIfFuncAndRightArgs\\"); +const boolOrErr = native.operators.get(\\"boolOrErr\\"); +const wrap = native.operators.get(\\"wrap\\"); +const unaryOp = native.operators.get(\\"unaryOp\\"); +const binaryOp = native.operators.get(\\"binaryOp\\"); +const throwIfTimeout = native.operators.get(\\"throwIfTimeout\\"); +const setProp = native.operators.get(\\"setProp\\"); +const getProp = native.operators.get(\\"getProp\\"); +let lastStatementResult = undefined; +(( ) => { + return (() => { + { + { + lastStatementResult = eval(\\"callIfFuncAndRightArgs(build_list, 1, 0, 1.5, wrap(x => ({ isTail: false, value: x }), \\\\\\"x => x\\\\\\"));\\"); + } + } + return lastStatementResult; + })(); +})(); +", "visualiseListResult": Array [], } `; @@ -335,6 +461,27 @@ Object { "parsedErrors": "Line 1: Error: build_list(n, fun) expects a positive integer as argument n, but encountered 1", "result": undefined, "resultStatus": "error", + "transpiled": "const native = $$NATIVE_STORAGE; +const callIfFuncAndRightArgs = native.operators.get(\\"callIfFuncAndRightArgs\\"); +const boolOrErr = native.operators.get(\\"boolOrErr\\"); +const wrap = native.operators.get(\\"wrap\\"); +const unaryOp = native.operators.get(\\"unaryOp\\"); +const binaryOp = native.operators.get(\\"binaryOp\\"); +const throwIfTimeout = native.operators.get(\\"throwIfTimeout\\"); +const setProp = native.operators.get(\\"setProp\\"); +const getProp = native.operators.get(\\"getProp\\"); +let lastStatementResult = undefined; +(( ) => { + return (() => { + { + { + lastStatementResult = eval(\\"callIfFuncAndRightArgs(build_list, 1, 0, '1', wrap(x => ({ isTail: false, value: x }), \\\\\\"x => x\\\\\\"));\\"); + } + } + return lastStatementResult; + })(); +})(); +", "visualiseListResult": Array [], } `; @@ -364,6 +511,27 @@ Object { "parsedErrors": "Line 1: Error: enum_list(start, end) expects a number as argument start, but encountered 1", "result": undefined, "resultStatus": "error", + "transpiled": "const native = $$NATIVE_STORAGE; +const callIfFuncAndRightArgs = native.operators.get(\\"callIfFuncAndRightArgs\\"); +const boolOrErr = native.operators.get(\\"boolOrErr\\"); +const wrap = native.operators.get(\\"wrap\\"); +const unaryOp = native.operators.get(\\"unaryOp\\"); +const binaryOp = native.operators.get(\\"binaryOp\\"); +const throwIfTimeout = native.operators.get(\\"throwIfTimeout\\"); +const setProp = native.operators.get(\\"setProp\\"); +const getProp = native.operators.get(\\"getProp\\"); +let lastStatementResult = undefined; +(( ) => { + return (() => { + { + { + lastStatementResult = eval(\\"callIfFuncAndRightArgs(enum_list, 1, 0, '1', '5');\\"); + } + } + return lastStatementResult; + })(); +})(); +", "visualiseListResult": Array [], } `; @@ -393,6 +561,27 @@ Object { "parsedErrors": "Line 1: Error: enum_list(start, end) expects a number as argument start, but encountered 1", "result": undefined, "resultStatus": "error", + "transpiled": "const native = $$NATIVE_STORAGE; +const callIfFuncAndRightArgs = native.operators.get(\\"callIfFuncAndRightArgs\\"); +const boolOrErr = native.operators.get(\\"boolOrErr\\"); +const wrap = native.operators.get(\\"wrap\\"); +const unaryOp = native.operators.get(\\"unaryOp\\"); +const binaryOp = native.operators.get(\\"binaryOp\\"); +const throwIfTimeout = native.operators.get(\\"throwIfTimeout\\"); +const setProp = native.operators.get(\\"setProp\\"); +const getProp = native.operators.get(\\"getProp\\"); +let lastStatementResult = undefined; +(( ) => { + return (() => { + { + { + lastStatementResult = eval(\\"callIfFuncAndRightArgs(enum_list, 1, 0, '1', 5);\\"); + } + } + return lastStatementResult; + })(); +})(); +", "visualiseListResult": Array [], } `; @@ -422,6 +611,27 @@ Object { "parsedErrors": "Line 1: Error: enum_list(start, end) expects a number as argument start, but encountered 5", "result": undefined, "resultStatus": "error", + "transpiled": "const native = $$NATIVE_STORAGE; +const callIfFuncAndRightArgs = native.operators.get(\\"callIfFuncAndRightArgs\\"); +const boolOrErr = native.operators.get(\\"boolOrErr\\"); +const wrap = native.operators.get(\\"wrap\\"); +const unaryOp = native.operators.get(\\"unaryOp\\"); +const binaryOp = native.operators.get(\\"binaryOp\\"); +const throwIfTimeout = native.operators.get(\\"throwIfTimeout\\"); +const setProp = native.operators.get(\\"setProp\\"); +const getProp = native.operators.get(\\"getProp\\"); +let lastStatementResult = undefined; +(( ) => { + return (() => { + { + { + lastStatementResult = eval(\\"callIfFuncAndRightArgs(enum_list, 1, 0, 1, '5');\\"); + } + } + return lastStatementResult; + })(); +})(); +", "visualiseListResult": Array [], } `; @@ -704,6 +914,37 @@ list(1, 'a string \\"\\"', () => a, f, true, 3.14);", ], ], "resultStatus": "finished", + "transpiled": "const native = $$NATIVE_STORAGE; +const callIfFuncAndRightArgs = native.operators.get(\\"callIfFuncAndRightArgs\\"); +const boolOrErr = native.operators.get(\\"boolOrErr\\"); +const wrap = native.operators.get(\\"wrap\\"); +const unaryOp = native.operators.get(\\"unaryOp\\"); +const binaryOp = native.operators.get(\\"binaryOp\\"); +const throwIfTimeout = native.operators.get(\\"throwIfTimeout\\"); +const setProp = native.operators.get(\\"setProp\\"); +const getProp = native.operators.get(\\"getProp\\"); +let lastStatementResult = undefined; +(( ) => { + return (() => { + { + { + const f = wrap(() => { + return { + isTail: false, + value: 1 + }; + }, \\"function f() {\\\\n return 1;\\\\n}\\"); + lastStatementResult = eval(\\"callIfFuncAndRightArgs(list, 2, 0, 1, 'a string \\\\\\"\\\\\\"', wrap(() => ({ isTail: false, value: a }), \\\\\\"() => a\\\\\\"), f, true, 3.14);\\"); + native.globals.variables.set(\\"f\\", { + kind: \\"const\\", + value: f + }); + } + } + return lastStatementResult; + })(); +})(); +", "visualiseListResult": Array [], } `; @@ -871,6 +1112,27 @@ Object { "parsedErrors": "Line 1: Error: head(xs) expects a pair as argument xs, but encountered undefined", "result": undefined, "resultStatus": "error", + "transpiled": "const native = $$NATIVE_STORAGE; +const callIfFuncAndRightArgs = native.operators.get(\\"callIfFuncAndRightArgs\\"); +const boolOrErr = native.operators.get(\\"boolOrErr\\"); +const wrap = native.operators.get(\\"wrap\\"); +const unaryOp = native.operators.get(\\"unaryOp\\"); +const binaryOp = native.operators.get(\\"binaryOp\\"); +const throwIfTimeout = native.operators.get(\\"throwIfTimeout\\"); +const setProp = native.operators.get(\\"setProp\\"); +const getProp = native.operators.get(\\"getProp\\"); +let lastStatementResult = undefined; +(( ) => { + return (() => { + { + { + lastStatementResult = eval(\\"callIfFuncAndRightArgs(accumulate, 1, 0, wrap((x, y) => ({ isTail: false, value: binaryOp(\\\\\\"+\\\\\\", x, y, 1, 21) }), \\\\\\"(x, y) => x + y\\\\\\"), [1, 2, 3]);\\"); + } + } + return lastStatementResult; + })(); +})(); +", "visualiseListResult": Array [], } `; @@ -900,20 +1162,41 @@ Object { "parsedErrors": "Line 1: Error: head(xs) expects a pair as argument xs, but encountered undefined", "result": undefined, "resultStatus": "error", - "visualiseListResult": Array [], -} -`; - -exports[`non-list error append: expectParsedError 1`] = ` -Object { - "alertResult": Array [], - "code": "append([1, 2, 3], list(1, 2, 3));", - "displayResult": Array [], - "errors": Array [ - ExceptionError { - "error": [Error: head(xs) expects a pair as argument xs, but encountered [1, 2, 3]], - "location": SourceLocation { - "end": Position { + "transpiled": "const native = $$NATIVE_STORAGE; +const callIfFuncAndRightArgs = native.operators.get(\\"callIfFuncAndRightArgs\\"); +const boolOrErr = native.operators.get(\\"boolOrErr\\"); +const wrap = native.operators.get(\\"wrap\\"); +const unaryOp = native.operators.get(\\"unaryOp\\"); +const binaryOp = native.operators.get(\\"binaryOp\\"); +const throwIfTimeout = native.operators.get(\\"throwIfTimeout\\"); +const setProp = native.operators.get(\\"setProp\\"); +const getProp = native.operators.get(\\"getProp\\"); +let lastStatementResult = undefined; +(( ) => { + return (() => { + { + { + lastStatementResult = eval(\\"callIfFuncAndRightArgs(accumulate, 1, 0, wrap((x, y) => ({ isTail: false, value: binaryOp(\\\\\\"+\\\\\\", x, y, 1, 21) }), \\\\\\"(x, y) => x + y\\\\\\"), [1, 2, 3]);\\"); + } + } + return lastStatementResult; + })(); +})(); +", + "visualiseListResult": Array [], +} +`; + +exports[`non-list error append: expectParsedError 1`] = ` +Object { + "alertResult": Array [], + "code": "append([1, 2, 3], list(1, 2, 3));", + "displayResult": Array [], + "errors": Array [ + ExceptionError { + "error": [Error: head(xs) expects a pair as argument xs, but encountered [1, 2, 3]], + "location": SourceLocation { + "end": Position { "column": 32, "line": 1, }, @@ -929,6 +1212,27 @@ Object { "parsedErrors": "Line 1: Error: head(xs) expects a pair as argument xs, but encountered [1, 2, 3]", "result": undefined, "resultStatus": "error", + "transpiled": "const native = $$NATIVE_STORAGE; +const callIfFuncAndRightArgs = native.operators.get(\\"callIfFuncAndRightArgs\\"); +const boolOrErr = native.operators.get(\\"boolOrErr\\"); +const wrap = native.operators.get(\\"wrap\\"); +const unaryOp = native.operators.get(\\"unaryOp\\"); +const binaryOp = native.operators.get(\\"binaryOp\\"); +const throwIfTimeout = native.operators.get(\\"throwIfTimeout\\"); +const setProp = native.operators.get(\\"setProp\\"); +const getProp = native.operators.get(\\"getProp\\"); +let lastStatementResult = undefined; +(( ) => { + return (() => { + { + { + lastStatementResult = eval(\\"callIfFuncAndRightArgs(append, 1, 0, [1, 2, 3], callIfFuncAndRightArgs(list, 1, 18, 1, 2, 3));\\"); + } + } + return lastStatementResult; + })(); +})(); +", "visualiseListResult": Array [], } `; @@ -987,6 +1291,27 @@ Object { "parsedErrors": "Line 1: Error: head(xs) expects a pair as argument xs, but encountered [1, 2, 3]", "result": undefined, "resultStatus": "error", + "transpiled": "const native = $$NATIVE_STORAGE; +const callIfFuncAndRightArgs = native.operators.get(\\"callIfFuncAndRightArgs\\"); +const boolOrErr = native.operators.get(\\"boolOrErr\\"); +const wrap = native.operators.get(\\"wrap\\"); +const unaryOp = native.operators.get(\\"unaryOp\\"); +const binaryOp = native.operators.get(\\"binaryOp\\"); +const throwIfTimeout = native.operators.get(\\"throwIfTimeout\\"); +const setProp = native.operators.get(\\"setProp\\"); +const getProp = native.operators.get(\\"getProp\\"); +let lastStatementResult = undefined; +(( ) => { + return (() => { + { + { + lastStatementResult = eval(\\"callIfFuncAndRightArgs(filter, 1, 0, wrap(x => ({ isTail: false, value: true }), \\\\\\"x => true\\\\\\"), [1, 2, 3]);\\"); + } + } + return lastStatementResult; + })(); +})(); +", "visualiseListResult": Array [], } `; @@ -1016,6 +1341,27 @@ Object { "parsedErrors": "Line 1: Error: for_each expects a list as argument xs, but encountered 1,2,3", "result": undefined, "resultStatus": "error", + "transpiled": "const native = $$NATIVE_STORAGE; +const callIfFuncAndRightArgs = native.operators.get(\\"callIfFuncAndRightArgs\\"); +const boolOrErr = native.operators.get(\\"boolOrErr\\"); +const wrap = native.operators.get(\\"wrap\\"); +const unaryOp = native.operators.get(\\"unaryOp\\"); +const binaryOp = native.operators.get(\\"binaryOp\\"); +const throwIfTimeout = native.operators.get(\\"throwIfTimeout\\"); +const setProp = native.operators.get(\\"setProp\\"); +const getProp = native.operators.get(\\"getProp\\"); +let lastStatementResult = undefined; +(( ) => { + return (() => { + { + { + lastStatementResult = eval(\\"callIfFuncAndRightArgs(for_each, 1, 0, wrap(x => ({ isTail: false, value: x }), \\\\\\"x => x\\\\\\"), [1, 2, 3]);\\"); + } + } + return lastStatementResult; + })(); +})(); +", "visualiseListResult": Array [], } `; @@ -1045,6 +1391,27 @@ Object { "parsedErrors": "Line 1: Error: head(xs) expects a pair as argument xs, but encountered [1, 2, 3]", "result": undefined, "resultStatus": "error", + "transpiled": "const native = $$NATIVE_STORAGE; +const callIfFuncAndRightArgs = native.operators.get(\\"callIfFuncAndRightArgs\\"); +const boolOrErr = native.operators.get(\\"boolOrErr\\"); +const wrap = native.operators.get(\\"wrap\\"); +const unaryOp = native.operators.get(\\"unaryOp\\"); +const binaryOp = native.operators.get(\\"binaryOp\\"); +const throwIfTimeout = native.operators.get(\\"throwIfTimeout\\"); +const setProp = native.operators.get(\\"setProp\\"); +const getProp = native.operators.get(\\"getProp\\"); +let lastStatementResult = undefined; +(( ) => { + return (() => { + { + { + lastStatementResult = eval(\\"callIfFuncAndRightArgs(head, 1, 0, [1, 2, 3]);\\"); + } + } + return lastStatementResult; + })(); +})(); +", "visualiseListResult": Array [], } `; @@ -1074,6 +1441,27 @@ Object { "parsedErrors": "Line 1: Error: tail(xs) expects a pair as argument xs, but encountered [1, 2, 3]", "result": undefined, "resultStatus": "error", + "transpiled": "const native = $$NATIVE_STORAGE; +const callIfFuncAndRightArgs = native.operators.get(\\"callIfFuncAndRightArgs\\"); +const boolOrErr = native.operators.get(\\"boolOrErr\\"); +const wrap = native.operators.get(\\"wrap\\"); +const unaryOp = native.operators.get(\\"unaryOp\\"); +const binaryOp = native.operators.get(\\"binaryOp\\"); +const throwIfTimeout = native.operators.get(\\"throwIfTimeout\\"); +const setProp = native.operators.get(\\"setProp\\"); +const getProp = native.operators.get(\\"getProp\\"); +let lastStatementResult = undefined; +(( ) => { + return (() => { + { + { + lastStatementResult = eval(\\"callIfFuncAndRightArgs(length, 1, 0, [1, 2, 3]);\\"); + } + } + return lastStatementResult; + })(); +})(); +", "visualiseListResult": Array [], } `; @@ -1103,6 +1491,27 @@ Object { "parsedErrors": "Line 1: Error: head(xs) expects a pair as argument xs, but encountered [1, 2, 3]", "result": undefined, "resultStatus": "error", + "transpiled": "const native = $$NATIVE_STORAGE; +const callIfFuncAndRightArgs = native.operators.get(\\"callIfFuncAndRightArgs\\"); +const boolOrErr = native.operators.get(\\"boolOrErr\\"); +const wrap = native.operators.get(\\"wrap\\"); +const unaryOp = native.operators.get(\\"unaryOp\\"); +const binaryOp = native.operators.get(\\"binaryOp\\"); +const throwIfTimeout = native.operators.get(\\"throwIfTimeout\\"); +const setProp = native.operators.get(\\"setProp\\"); +const getProp = native.operators.get(\\"getProp\\"); +let lastStatementResult = undefined; +(( ) => { + return (() => { + { + { + lastStatementResult = eval(\\"callIfFuncAndRightArgs(map, 1, 0, wrap(x => ({ isTail: false, value: x }), \\\\\\"x => x\\\\\\"), [1, 2, 3]);\\"); + } + } + return lastStatementResult; + })(); +})(); +", "visualiseListResult": Array [], } `; @@ -1132,6 +1541,27 @@ Object { "parsedErrors": "Line 1: Error: head(xs) expects a pair as argument xs, but encountered [1, 2, 3]", "result": undefined, "resultStatus": "error", + "transpiled": "const native = $$NATIVE_STORAGE; +const callIfFuncAndRightArgs = native.operators.get(\\"callIfFuncAndRightArgs\\"); +const boolOrErr = native.operators.get(\\"boolOrErr\\"); +const wrap = native.operators.get(\\"wrap\\"); +const unaryOp = native.operators.get(\\"unaryOp\\"); +const binaryOp = native.operators.get(\\"binaryOp\\"); +const throwIfTimeout = native.operators.get(\\"throwIfTimeout\\"); +const setProp = native.operators.get(\\"setProp\\"); +const getProp = native.operators.get(\\"getProp\\"); +let lastStatementResult = undefined; +(( ) => { + return (() => { + { + { + lastStatementResult = eval(\\"callIfFuncAndRightArgs(member, 1, 0, 1, [1, 2, 3]);\\"); + } + } + return lastStatementResult; + })(); +})(); +", "visualiseListResult": Array [], } `; @@ -1161,6 +1591,27 @@ Object { "parsedErrors": "Line 1: Error: head(xs) expects a pair as argument xs, but encountered [1, 2, 3]", "result": undefined, "resultStatus": "error", + "transpiled": "const native = $$NATIVE_STORAGE; +const callIfFuncAndRightArgs = native.operators.get(\\"callIfFuncAndRightArgs\\"); +const boolOrErr = native.operators.get(\\"boolOrErr\\"); +const wrap = native.operators.get(\\"wrap\\"); +const unaryOp = native.operators.get(\\"unaryOp\\"); +const binaryOp = native.operators.get(\\"binaryOp\\"); +const throwIfTimeout = native.operators.get(\\"throwIfTimeout\\"); +const setProp = native.operators.get(\\"setProp\\"); +const getProp = native.operators.get(\\"getProp\\"); +let lastStatementResult = undefined; +(( ) => { + return (() => { + { + { + lastStatementResult = eval(\\"callIfFuncAndRightArgs(remove, 1, 0, 1, [1, 2, 3]);\\"); + } + } + return lastStatementResult; + })(); +})(); +", "visualiseListResult": Array [], } `; @@ -1190,6 +1641,27 @@ Object { "parsedErrors": "Line 1: Error: head(xs) expects a pair as argument xs, but encountered [1, 2, 3]", "result": undefined, "resultStatus": "error", + "transpiled": "const native = $$NATIVE_STORAGE; +const callIfFuncAndRightArgs = native.operators.get(\\"callIfFuncAndRightArgs\\"); +const boolOrErr = native.operators.get(\\"boolOrErr\\"); +const wrap = native.operators.get(\\"wrap\\"); +const unaryOp = native.operators.get(\\"unaryOp\\"); +const binaryOp = native.operators.get(\\"binaryOp\\"); +const throwIfTimeout = native.operators.get(\\"throwIfTimeout\\"); +const setProp = native.operators.get(\\"setProp\\"); +const getProp = native.operators.get(\\"getProp\\"); +let lastStatementResult = undefined; +(( ) => { + return (() => { + { + { + lastStatementResult = eval(\\"callIfFuncAndRightArgs(remove_all, 1, 0, 1, [1, 2, 3]);\\"); + } + } + return lastStatementResult; + })(); +})(); +", "visualiseListResult": Array [], } `; @@ -1219,6 +1691,27 @@ Object { "parsedErrors": "Line 1: Error: reverse(xs) expects a list as argument xs, but encountered 1,2,3", "result": undefined, "resultStatus": "error", + "transpiled": "const native = $$NATIVE_STORAGE; +const callIfFuncAndRightArgs = native.operators.get(\\"callIfFuncAndRightArgs\\"); +const boolOrErr = native.operators.get(\\"boolOrErr\\"); +const wrap = native.operators.get(\\"wrap\\"); +const unaryOp = native.operators.get(\\"unaryOp\\"); +const binaryOp = native.operators.get(\\"binaryOp\\"); +const throwIfTimeout = native.operators.get(\\"throwIfTimeout\\"); +const setProp = native.operators.get(\\"setProp\\"); +const getProp = native.operators.get(\\"getProp\\"); +let lastStatementResult = undefined; +(( ) => { + return (() => { + { + { + lastStatementResult = eval(\\"callIfFuncAndRightArgs(reverse, 1, 0, [1, 2, 3]);\\"); + } + } + return lastStatementResult; + })(); +})(); +", "visualiseListResult": Array [], } `; @@ -1248,6 +1741,27 @@ Object { "parsedErrors": "Line 1: Error: set_head(xs,x) expects a pair as argument xs, but encountered [1, 2, 3]", "result": undefined, "resultStatus": "error", + "transpiled": "const native = $$NATIVE_STORAGE; +const callIfFuncAndRightArgs = native.operators.get(\\"callIfFuncAndRightArgs\\"); +const boolOrErr = native.operators.get(\\"boolOrErr\\"); +const wrap = native.operators.get(\\"wrap\\"); +const unaryOp = native.operators.get(\\"unaryOp\\"); +const binaryOp = native.operators.get(\\"binaryOp\\"); +const throwIfTimeout = native.operators.get(\\"throwIfTimeout\\"); +const setProp = native.operators.get(\\"setProp\\"); +const getProp = native.operators.get(\\"getProp\\"); +let lastStatementResult = undefined; +(( ) => { + return (() => { + { + { + lastStatementResult = eval(\\"callIfFuncAndRightArgs(set_head, 1, 0, [1, 2, 3], 4);\\"); + } + } + return lastStatementResult; + })(); +})(); +", "visualiseListResult": Array [], } `; @@ -1277,6 +1791,27 @@ Object { "parsedErrors": "Line 1: Error: set_tail(xs,x) expects a pair as argument xs, but encountered [1, 2, 3]", "result": undefined, "resultStatus": "error", + "transpiled": "const native = $$NATIVE_STORAGE; +const callIfFuncAndRightArgs = native.operators.get(\\"callIfFuncAndRightArgs\\"); +const boolOrErr = native.operators.get(\\"boolOrErr\\"); +const wrap = native.operators.get(\\"wrap\\"); +const unaryOp = native.operators.get(\\"unaryOp\\"); +const binaryOp = native.operators.get(\\"binaryOp\\"); +const throwIfTimeout = native.operators.get(\\"throwIfTimeout\\"); +const setProp = native.operators.get(\\"setProp\\"); +const getProp = native.operators.get(\\"getProp\\"); +let lastStatementResult = undefined; +(( ) => { + return (() => { + { + { + lastStatementResult = eval(\\"callIfFuncAndRightArgs(set_tail, 1, 0, [1, 2, 3], 4);\\"); + } + } + return lastStatementResult; + })(); +})(); +", "visualiseListResult": Array [], } `; @@ -1306,6 +1841,27 @@ Object { "parsedErrors": "Line 1: Error: tail(xs) expects a pair as argument xs, but encountered [1, 2, 3]", "result": undefined, "resultStatus": "error", + "transpiled": "const native = $$NATIVE_STORAGE; +const callIfFuncAndRightArgs = native.operators.get(\\"callIfFuncAndRightArgs\\"); +const boolOrErr = native.operators.get(\\"boolOrErr\\"); +const wrap = native.operators.get(\\"wrap\\"); +const unaryOp = native.operators.get(\\"unaryOp\\"); +const binaryOp = native.operators.get(\\"binaryOp\\"); +const throwIfTimeout = native.operators.get(\\"throwIfTimeout\\"); +const setProp = native.operators.get(\\"setProp\\"); +const getProp = native.operators.get(\\"getProp\\"); +let lastStatementResult = undefined; +(( ) => { + return (() => { + { + { + lastStatementResult = eval(\\"callIfFuncAndRightArgs(tail, 1, 0, [1, 2, 3]);\\"); + } + } + return lastStatementResult; + })(); +})(); +", "visualiseListResult": Array [], } `; diff --git a/src/stdlib/__tests__/list.ts b/src/stdlib/__tests__/list.ts index 2a6943802..e2bf7f9fd 100644 --- a/src/stdlib/__tests__/list.ts +++ b/src/stdlib/__tests__/list.ts @@ -7,7 +7,7 @@ test('list creates list', () => { function f() { return 1; } list(1, 'a string ""', () => a, f, true, 3.14); `, - { chapter: 2 } + { chapter: 2, native: true } ).toMatchInlineSnapshot(` Array [ 1, @@ -283,7 +283,7 @@ test('non-list error head', () => { stripIndent` head([1, 2, 3]); `, - { chapter: 3 } + { chapter: 3, native: true } ).toMatchInlineSnapshot( `"Line 1: Error: head(xs) expects a pair as argument xs, but encountered [1, 2, 3]"` ) @@ -294,7 +294,7 @@ test('non-list error tail', () => { stripIndent` tail([1, 2, 3]); `, - { chapter: 3 } + { chapter: 3, native: true } ).toMatchInlineSnapshot( `"Line 1: Error: tail(xs) expects a pair as argument xs, but encountered [1, 2, 3]"` ) @@ -305,7 +305,7 @@ test('non-list error length', () => { stripIndent` length([1, 2, 3]); `, - { chapter: 3 } + { chapter: 3, native: true } ).toMatchInlineSnapshot( `"Line 1: Error: tail(xs) expects a pair as argument xs, but encountered [1, 2, 3]"` ) @@ -316,7 +316,7 @@ test('non-list error map', () => { stripIndent` map(x=>x, [1, 2, 3]); `, - { chapter: 3 } + { chapter: 3, native: true } ).toMatchInlineSnapshot( `"Line 1: Error: head(xs) expects a pair as argument xs, but encountered [1, 2, 3]"` ) @@ -327,7 +327,7 @@ test('non-list error for_each', () => { stripIndent` for_each(x=>x, [1, 2, 3]); `, - { chapter: 3 } + { chapter: 3, native: true } ).toMatchInlineSnapshot( `"Line 1: Error: for_each expects a list as argument xs, but encountered 1,2,3"` ) @@ -338,7 +338,7 @@ test('non-list error reverse', () => { stripIndent` reverse([1, 2, 3]); `, - { chapter: 3 } + { chapter: 3, native: true } ).toMatchInlineSnapshot( `"Line 1: Error: reverse(xs) expects a list as argument xs, but encountered 1,2,3"` ) @@ -349,7 +349,7 @@ test('non-list error append', () => { stripIndent` append([1, 2, 3], list(1, 2, 3)); `, - { chapter: 3 } + { chapter: 3, native: true } ).toMatchInlineSnapshot( `"Line 1: Error: head(xs) expects a pair as argument xs, but encountered [1, 2, 3]"` ) @@ -360,7 +360,7 @@ test('non-list error member', () => { stripIndent` member(1, [1, 2, 3]); `, - { chapter: 3 } + { chapter: 3, native: true } ).toMatchInlineSnapshot( `"Line 1: Error: head(xs) expects a pair as argument xs, but encountered [1, 2, 3]"` ) @@ -371,7 +371,7 @@ test('non-list error remove', () => { stripIndent` remove(1, [1, 2, 3]); `, - { chapter: 3 } + { chapter: 3, native: true } ).toMatchInlineSnapshot( `"Line 1: Error: head(xs) expects a pair as argument xs, but encountered [1, 2, 3]"` ) @@ -382,7 +382,7 @@ test('non-list error remove_all', () => { stripIndent` remove_all(1, [1, 2, 3]); `, - { chapter: 3 } + { chapter: 3, native: true } ).toMatchInlineSnapshot( `"Line 1: Error: head(xs) expects a pair as argument xs, but encountered [1, 2, 3]"` ) @@ -404,7 +404,7 @@ test('non-list error filter', () => { stripIndent` filter(x => true, [1, 2, 3]); `, - { chapter: 3 } + { chapter: 3, native: true } ).toMatchInlineSnapshot( `"Line 1: Error: head(xs) expects a pair as argument xs, but encountered [1, 2, 3]"` ) @@ -415,7 +415,7 @@ test('non-list error accumulate', () => { stripIndent` accumulate((x, y) => x + y, [1, 2, 3]); `, - { chapter: 3 } + { chapter: 3, native: true } ).toMatchInlineSnapshot( `"Line 1: Error: head(xs) expects a pair as argument xs, but encountered undefined"` ) @@ -426,7 +426,7 @@ test('non-list error accumulate', () => { stripIndent` accumulate((x, y) => x + y, [1, 2, 3]); `, - { chapter: 3 } + { chapter: 3, native: true } ).toMatchInlineSnapshot( `"Line 1: Error: head(xs) expects a pair as argument xs, but encountered undefined"` ) @@ -437,7 +437,7 @@ test('non-list error set_head', () => { stripIndent` set_head([1, 2, 3], 4); `, - { chapter: 3 } + { chapter: 3, native: true } ).toMatchInlineSnapshot( `"Line 1: Error: set_head(xs,x) expects a pair as argument xs, but encountered [1, 2, 3]"` ) @@ -448,7 +448,7 @@ test('non-list error set_tail', () => { stripIndent` set_tail([1, 2, 3], 4); `, - { chapter: 3 } + { chapter: 3, native: true } ).toMatchInlineSnapshot( `"Line 1: Error: set_tail(xs,x) expects a pair as argument xs, but encountered [1, 2, 3]"` ) @@ -459,7 +459,7 @@ test('bad number error build_list', () => { stripIndent` build_list(-1, x => x); `, - { chapter: 2 } + { chapter: 2, native: true } ).toMatchInlineSnapshot( `"Line 1: Error: build_list(n, fun) expects a positive integer as argument n, but encountered -1"` ) @@ -470,7 +470,7 @@ test('bad number error build_list', () => { stripIndent` build_list(1.5, x => x); `, - { chapter: 2 } + { chapter: 2, native: true } ).toMatchInlineSnapshot( `"Line 1: Error: build_list(n, fun) expects a positive integer as argument n, but encountered 1.5"` ) @@ -481,7 +481,7 @@ test('bad number error build_list', () => { stripIndent` build_list('1', x => x); `, - { chapter: 2 } + { chapter: 2, native: true } ).toMatchInlineSnapshot( `"Line 1: Error: build_list(n, fun) expects a positive integer as argument n, but encountered 1"` ) @@ -492,7 +492,7 @@ test('bad number error enum_list', () => { stripIndent` enum_list('1', '5'); `, - { chapter: 2 } + { chapter: 2, native: true } ).toMatchInlineSnapshot( `"Line 1: Error: enum_list(start, end) expects a number as argument start, but encountered 1"` ) @@ -503,7 +503,7 @@ test('bad number error enum_list', () => { stripIndent` enum_list('1', 5); `, - { chapter: 2 } + { chapter: 2, native: true } ).toMatchInlineSnapshot( `"Line 1: Error: enum_list(start, end) expects a number as argument start, but encountered 1"` ) @@ -514,7 +514,7 @@ test('bad number error enum_list', () => { stripIndent` enum_list(1, '5'); `, - { chapter: 2 } + { chapter: 2, native: true } ).toMatchInlineSnapshot( `"Line 1: Error: enum_list(start, end) expects a number as argument start, but encountered 5"` ) @@ -525,7 +525,7 @@ test('bad index error list_ref', () => { stripIndent` list_ref(list(1, 2, 3), 3); `, - { chapter: 2 } + { chapter: 2, native: true } ).toMatchInlineSnapshot( `"Line 1: Error: head(xs) expects a pair as argument xs, but encountered null"` ) @@ -536,7 +536,7 @@ test('bad index error list_ref', () => { stripIndent` list_ref(list(1, 2, 3), -1); `, - { chapter: 2 } + { chapter: 2, native: true } ).toMatchInlineSnapshot( `"Line 1: Error: list_ref(xs, n) expects a positive integer as argument n, but encountered -1"` ) @@ -547,7 +547,7 @@ test('bad index error list_ref', () => { stripIndent` list_ref(list(1, 2, 3), 1.5); `, - { chapter: 2 } + { chapter: 2, native: true } ).toMatchInlineSnapshot( `"Line 1: Error: list_ref(xs, n) expects a positive integer as argument n, but encountered 1.5"` ) @@ -558,7 +558,7 @@ test('bad index error list_ref', () => { stripIndent` list_ref(list(1, 2, 3), '1'); `, - { chapter: 2 } + { chapter: 2, native: true } ).toMatchInlineSnapshot( `"Line 1: Error: list_ref(xs, n) expects a positive integer as argument n, but encountered 1"` ) diff --git a/src/utils/operators.ts b/src/utils/operators.ts index 87f31e0d5..061546113 100644 --- a/src/utils/operators.ts +++ b/src/utils/operators.ts @@ -2,6 +2,7 @@ import { BinaryOperator, UnaryOperator } from 'estree' import { JSSLANG_PROPERTIES } from '../constants' import { CallingNonFunctionValue, + ExceptionError, GetInheritedPropertyError, InvalidNumberOfArguments } from '../interpreter-errors' @@ -27,14 +28,20 @@ export function callIfFuncAndRightArgs( end: { line, column } }) if (typeof candidate === 'function') { - if (candidate.transformedFunction !== undefined) { + if (candidate.transformedFunction === undefined) { + try { + return candidate(...args) + } catch (error) { + throw new ExceptionError(error, dummy.loc!) + } + } else { const expectedLength = candidate.transformedFunction.length const receivedLength = args.length if (expectedLength !== receivedLength) { throw new InvalidNumberOfArguments(dummy, expectedLength, receivedLength) } + return candidate(...args) } - return candidate(...args) } else { throw new CallingNonFunctionValue(candidate, dummy) }