mirror of
https://github.com/captbaritone/webamp.git
synced 2026-07-22 17:47:16 +00:00
Move offset mapping entirely into the parser
This commit is contained in:
parent
8529d948ec
commit
c61fbb952d
2 changed files with 34 additions and 21 deletions
|
|
@ -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,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue