Pull local functions into their own thing

This commit is contained in:
Jordan Eldredge 2019-07-09 08:16:16 -07:00
parent 53c06ab7c4
commit ec754cfbce
3 changed files with 30 additions and 33 deletions

View file

@ -52,7 +52,7 @@ describe("standardframe.maki", () => {
"MouseRedir",
"DropDownList",
"LayoutStatus",
"TabSheet"
"TabSheet",
]);
});
@ -69,7 +69,7 @@ describe("standardframe.maki", () => {
"messagebox",
"onNotify",
"newGroup",
"init"
"init",
]);
expect(maki.methods.every(func => func.typeOffset != null)).toBe(true);
});
@ -154,10 +154,18 @@ describe("standardframe.maki", () => {
{ variableOffset: 0, commandOffset: 0, methodOffset: 0 },
{ variableOffset: 0, commandOffset: 76, methodOffset: 4 },
{ variableOffset: 2, commandOffset: 143, methodOffset: 9 },
{ function: { code: [], name: "func722", offset: 722 }, offset: 722 }
]);
});
test("can read localFunctions", () => {
expect(maki.localFunctions).toEqual({
"722": {
function: { code: [], name: "func722", offset: 722 },
offset: 722,
},
});
});
// [opcode, size] as output by the Perl decompiler
// TODO: Get rid of the size values here, they are not used any more
const expectedCommands = [
@ -416,7 +424,7 @@ describe("standardframe.maki", () => {
[24],
[2],
[1],
[33]
[33],
];
test("can read commands", () => {

View file

@ -5,9 +5,6 @@ const interpret = require("./virtualMachine");
function main({ runtime, data, system, log }) {
const program = parse(data);
// Set the System global
program.variables[0].setValue(system);
// Replace class hashes with actual JavaScript classes from the runtime
program.classes = program.classes.map(hash => {
const resolved = runtime[hash];
@ -23,18 +20,21 @@ function main({ runtime, data, system, log }) {
return resolved;
});
// Bind toplevel handlers.
// Bind top level hooks.
program.bindings.forEach(binding => {
const handler = () => {
return interpret(binding.commandOffset, program, { log });
};
const variable = program.variables[binding.variableOffset];
const method = program.methods[binding.methodOffset];
variable.hook(method.name, handler);
const { commandOffset, variableOffset, methodOffset } = binding;
const variable = program.variables[variableOffset];
const method = program.methods[methodOffset];
// TODO: Handle disposing of this.
// TODO: Handle passing in variables.
variable.hook(method.name, () => {
interpret(commandOffset, program, { log });
});
});
// Set the System global
// TODO: We could confirm that this variable has the "system" flag set.
program.variables[0].setValue(system);
system.js_start();
}

View file

@ -198,7 +198,7 @@ function readBindings(makiFile) {
return bindings;
}
function decodeCode({ makiFile, classes, variables, methods, bindings }) {
function decodeCode({ makiFile, classes, variables, methods }) {
const length = makiFile.readUInt32LE();
const start = makiFile.getPosition();
@ -206,29 +206,18 @@ function decodeCode({ makiFile, classes, variables, methods, bindings }) {
return makiFile.getPosition() - start;
}
const localFunctions = {};
const results = [];
const commands = [];
while (makiFile.getPosition() < start + length) {
const command = parseComand({
makiFile,
length,
pos: getPos(),
classes,
variables,
methods,
localFunctions,
});
results.push(command);
commands.push(command);
}
// TODO: Don't mutate
Object.values(localFunctions).forEach(localFunction => {
bindings.push(localFunction);
});
bindings.sort((a, b) => {
return a.binaryOffset - b.binaryOffset;
});
return results;
return { commands, localFunctions };
}
// TODO: Refactor this to consume bytes directly off the end of MakiFile
@ -321,12 +310,11 @@ function parse(buffer) {
const variables = readVariables({ makiFile: makiFile, classes });
readConstants({ makiFile: makiFile, variables });
const bindings = readBindings(makiFile);
const commands = decodeCode({
const { commands, localFunctions } = decodeCode({
makiFile,
classes,
variables,
methods,
bindings,
});
// Map binary offsets to command indexes.
@ -355,6 +343,7 @@ function parse(buffer) {
variables,
bindings: resolvedBindings,
commands,
localFunctions,
};
}