diff --git a/experiments/modern/src/maki-interpreter/parser.js b/experiments/modern/src/maki-interpreter/parser.js index 86a21d24..9f492346 100644 --- a/experiments/modern/src/maki-interpreter/parser.js +++ b/experiments/modern/src/maki-interpreter/parser.js @@ -10,6 +10,22 @@ const PRIMITIVE_TYPES = { 6: "STRING", }; +// TODO: Don't depend upon COMMANDS +function opcodeToArgType(opcode) { + const argType = COMMANDS[opcode].arg; + switch (argType) { + case "func": + case "line": + return "COMMAND_OFFSET"; + case "var": + case "objFunc": + case "obj": + return "VARIABLE_OFFSET"; + default: + return "NONE"; + } +} + // Holds a buffer and a pointer. Consumers can consume bytesoff the end of the // file. When we want to run in the browser, we can refactor this class to use a // typed array: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays @@ -232,23 +248,20 @@ function parseComand({ start, makiFile, length, pos }) { pos, opcode, arg: null, + argType: opcodeToArgType(opcode), }; - const argType = COMMANDS[opcode].arg; - if (argType == null) { + if (command.argType == "NONE") { return command; } let arg = null; - switch (argType) { - case "func": - case "line": + switch (command.argType) { + case "COMMAND_OFFSET": // Note in the perl code here: "todo, something strange going on here..." arg = makiFile.readInt32LE() + 5 + pos; break; - case "var": - case "objFunc": - case "obj": + case "VARIABLE_OFFSET": arg = makiFile.readUInt32LE(); break; default: @@ -314,16 +327,22 @@ function parse(buffer) { binaryOffset: undefined, }); }); + + const resolvedCommands = commands.map(command => { + if (command.argType === "COMMAND_OFFSET") { + return Object.assign({}, command, { arg: offsetToCommand[command.arg] }); + } + return command; + }); return { magic, classes, methods, variables, bindings: resolvedBindings, - commands, + commands: resolvedCommands, version, extraVersion, - offsetToCommand, }; } diff --git a/experiments/modern/src/maki-interpreter/virtualMachine.js b/experiments/modern/src/maki-interpreter/virtualMachine.js index af48ca20..b79f40ab 100644 --- a/experiments/modern/src/maki-interpreter/virtualMachine.js +++ b/experiments/modern/src/maki-interpreter/virtualMachine.js @@ -11,7 +11,7 @@ function coerceTypes(var1, var2, val1, val2) { } async function interpret(start, program, stack = [], { logger = null }) { - const { commands, methods, variables, classes, offsetToCommand } = program; + const { commands, methods, variables, classes } = program; function twoArgCoercingOperator(operator) { const a = stack.pop(); @@ -32,11 +32,6 @@ async function interpret(start, program, stack = [], { logger = null }) { stack.push(operator(bValue, aValue)); } - function jumpToOffset(offset) { - const nextCommandIndex = offsetToCommand[offset]; - return nextCommandIndex - 1; - } - let i = start; while (i < commands.length) { const command = commands[i]; @@ -105,7 +100,7 @@ async function interpret(start, program, stack = [], { logger = null }) { if (value) { break; } - i = jumpToOffset(command.arg); + i = command.arg - 1; break; } // jumpIfNot @@ -115,12 +110,12 @@ async function interpret(start, program, stack = [], { logger = null }) { if (!value) { break; } - i = jumpToOffset(command.arg); + i = command.arg - 1; break; } // jump case 18: { - i = jumpToOffset(command.arg); + i = command.arg - 1; break; } // call @@ -149,10 +144,9 @@ async function interpret(start, program, stack = [], { logger = null }) { // callGlobal case 25: { const offset = command.arg; - const nextCommandIndex = offsetToCommand[offset]; // Remove this await when we can run the VM synchronously. // See GitHub issue #814 - const value = await interpret(nextCommandIndex, program, stack, { + const value = await interpret(offset, program, stack, { logger, }); stack.push(value);