diff --git a/src/cse-machine/__tests__/__snapshots__/cse-machine-runtime-context.ts.snap b/src/cse-machine/__tests__/__snapshots__/cse-machine-runtime-context.ts.snap new file mode 100644 index 000000000..00ac26440 --- /dev/null +++ b/src/cse-machine/__tests__/__snapshots__/cse-machine-runtime-context.ts.snap @@ -0,0 +1,409 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Breakpoint steps match 1`] = ` +Array [ + 7, + 46, + 66, + 86, +] +`; + +exports[`Breakpoint steps match 2`] = ` +Array [ + 6, + 20, +] +`; + +exports[`Breakpoint steps match 3`] = ` +Array [ + 46, +] +`; + +exports[`Breakpoint steps match 4`] = ` +Array [ + 46, + 152, + 332, + 364, + 544, + 724, + 756, + 788, + 968, + 1148, + 1180, + 1360, + 1540, + 1572, + 1604, + 1636, +] +`; + +exports[`Changepoint steps match 1`] = ` +Array [ + 1, + 5, + 6, + 14, + 15, + 19, + 20, + 24, + 38, + 39, + 46, + 58, + 59, + 66, + 78, + 79, + 86, + 98, +] +`; + +exports[`Changepoint steps match 2`] = ` +Array [ + 1, + 5, + 10, + 11, + 19, + 20, +] +`; + +exports[`Changepoint steps match 3`] = ` +Array [ + 1, + 6, + 8, + 9, + 13, + 14, + 20, + 32, + 33, + 45, + 52, + 53, + 54, + 55, + 58, + 59, + 68, + 69, +] +`; + +exports[`Changepoint steps match 4`] = ` +Array [ + 1, + 6, + 8, + 9, + 13, + 14, + 20, + 32, + 33, + 45, + 52, + 53, + 54, + 55, + 58, + 59, + 65, + 77, + 83, + 85, + 91, + 92, + 98, + 110, + 122, + 123, + 139, + 149, + 150, + 151, + 158, + 159, + 160, + 161, + 166, + 171, + 183, + 189, + 191, + 197, + 198, + 204, + 216, + 228, + 229, + 245, + 257, + 263, + 265, + 271, + 272, + 278, + 290, + 302, + 303, + 319, + 329, + 330, + 331, + 338, + 339, + 340, + 341, + 346, + 351, + 361, + 362, + 363, + 370, + 371, + 372, + 373, + 378, + 383, + 395, + 401, + 403, + 409, + 410, + 416, + 428, + 440, + 441, + 457, + 469, + 475, + 477, + 483, + 484, + 490, + 502, + 514, + 515, + 531, + 541, + 542, + 543, + 550, + 551, + 552, + 553, + 558, + 563, + 575, + 581, + 583, + 589, + 590, + 596, + 608, + 620, + 621, + 637, + 649, + 655, + 657, + 663, + 664, + 670, + 682, + 694, + 695, + 711, + 721, + 722, + 723, + 730, + 731, + 732, + 733, + 738, + 743, + 753, + 754, + 755, + 762, + 763, + 764, + 765, + 770, + 775, + 785, + 786, + 787, + 794, + 795, + 796, + 797, + 802, + 807, + 819, + 825, + 827, + 833, + 834, + 840, + 852, + 864, + 865, + 881, + 893, + 899, + 901, + 907, + 908, + 914, + 926, + 938, + 939, + 955, + 965, + 966, + 967, + 974, + 975, + 976, + 977, + 982, + 987, + 999, + 1005, + 1007, + 1013, + 1014, + 1020, + 1032, + 1044, + 1045, + 1061, + 1073, + 1079, + 1081, + 1087, + 1088, + 1094, + 1106, + 1118, + 1119, + 1135, + 1145, + 1146, + 1147, + 1154, + 1155, + 1156, + 1157, + 1162, + 1167, + 1177, + 1178, + 1179, + 1186, + 1187, + 1188, + 1189, + 1194, + 1199, + 1211, + 1217, + 1219, + 1225, + 1226, + 1232, + 1244, + 1256, + 1257, + 1273, + 1285, + 1291, + 1293, + 1299, + 1300, + 1306, + 1318, + 1330, + 1331, + 1347, + 1357, + 1358, + 1359, + 1366, + 1367, + 1368, + 1369, + 1374, + 1379, + 1391, + 1397, + 1399, + 1405, + 1406, + 1412, + 1424, + 1436, + 1437, + 1453, + 1465, + 1471, + 1473, + 1479, + 1480, + 1486, + 1498, + 1510, + 1511, + 1527, + 1537, + 1538, + 1539, + 1546, + 1547, + 1548, + 1549, + 1554, + 1559, + 1569, + 1570, + 1571, + 1578, + 1579, + 1580, + 1581, + 1586, + 1591, + 1601, + 1602, + 1603, + 1610, + 1611, + 1612, + 1613, + 1618, + 1623, + 1633, + 1634, + 1635, + 1642, + 1643, + 1644, + 1645, + 1650, + 1655, + 1665, +] +`; diff --git a/src/cse-machine/__tests__/cse-machine-runtime-context.ts b/src/cse-machine/__tests__/cse-machine-runtime-context.ts new file mode 100644 index 000000000..f80e1b8da --- /dev/null +++ b/src/cse-machine/__tests__/cse-machine-runtime-context.ts @@ -0,0 +1,71 @@ +import { mockContext } from '../../mocks/context' +import { parse } from '../../parser/parser' +import { Chapter } from '../../types' +import { stripIndent } from '../../utils/formatters' +import { sourceRunner } from '../../runner' + +const getContextFrom = async (code: string) => { + const context = mockContext(Chapter.SOURCE_4) + const parsed = parse(code, context) + await sourceRunner(parsed!, context, false, { executionMethod: 'cse-machine' }) + return context +} + +const codeSamples = [ + ` + function create(n) { + const arr = []; + let x = 0; + + while (x < n) { + arr[x] = () => x; + x = x + 1; + debugger; + } + return arr; + } + debugger; + create(3)[1](); + `, + ` + let a = 0; + debugger; + function f(x) { + if (x <= 0) { + return x => x; + } + a = list(a); + debugger; + return f(x - 1); + } + apply_in_underlying_javascript(f, list(3)); + debugger; + `, + ` + const s = build_stream(i => { + const prev = i > 0 ? stream_ref(s, i - 1) : -1; + debugger; + return i; + }, 5); + apply_in_underlying_javascript(stream_ref, list(s, 4)); + `, + ` + const s = build_stream(i => { + const prev = i > 0 ? stream_ref(s, i - 1) : -1; + debugger; + return i; + }, 5); + stream_ref(s, 4); + ` +] + +const contexts = codeSamples.map(code => getContextFrom(stripIndent(code))) + +for (const context of contexts) { + test(`Breakpoint steps match`, async () => { + expect((await context).runtime.breakpointSteps).toMatchSnapshot() + }) + test(`Changepoint steps match`, async () => { + expect((await context).runtime.changepointSteps).toMatchSnapshot() + }) +} diff --git a/src/cse-machine/closure.ts b/src/cse-machine/closure.ts index 42084e07a..42dc64784 100644 --- a/src/cse-machine/closure.ts +++ b/src/cse-machine/closure.ts @@ -22,7 +22,18 @@ const closureToJS = (value: Closure, context: Context) => { ) // Create a new CSE Machine with the same context as the current one, but with // the control reset to only contain the call expression, and the stash emptied. - const newContext = { ...context, runtime: { ...context.runtime, debuggerOn: false } } + const newContext: Context = { + ...context, + runtime: { + ...context.runtime, + // Only environments are intended to be mutated by the new CSE Machine, the + // rest of the runtime properties should stay the same + nodes: [...context.runtime.nodes], + breakpointSteps: [...context.runtime.breakpointSteps], + changepointSteps: [...context.runtime.changepointSteps], + debuggerOn: false + } + } newContext.runtime.control = new Control() // Also need the env instruction to return back to the current environment at the end. // The call expression won't create one as there is only one item in the control. @@ -119,7 +130,7 @@ export default class Closure extends Callable { public predefined: boolean /** The original node that created this Closure */ - public originalNode: es.Function + public originalNode: es.ArrowFunctionExpression constructor( public node: es.ArrowFunctionExpression, diff --git a/src/cse-machine/utils.ts b/src/cse-machine/utils.ts index 0792d3197..125208c08 100644 --- a/src/cse-machine/utils.ts +++ b/src/cse-machine/utils.ts @@ -219,6 +219,8 @@ export const envChanging = (command: ControlItem): boolean => { } else { const type = command.instrType return ( + type === InstrType.ENVIRONMENT || + type === InstrType.ARRAY_LITERAL || type === InstrType.ASSIGNMENT || type === InstrType.ARRAY_ASSIGNMENT || (type === InstrType.APPLICATION && (command as AppInstr).numOfArgs > 0)