You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
162 lines
3.8 KiB
162 lines
3.8 KiB
import { Command } from "https://deno.land/x/cliffy@v0.25.7/command/mod.ts";
|
|
import swc from "npm:@swc/wasm@1.3.35";
|
|
|
|
import VariableDeclaration from "./nodes/VariableDeclaration.ts";
|
|
import ExpressionStatement from "./nodes/ExpressionStatement.ts";
|
|
import IfStatement from "./nodes/IfStatement.ts";
|
|
import WhileStatement from "./nodes/WhileStatement.ts";
|
|
import BlockStatement from "./nodes/BlockStatement.ts";
|
|
|
|
const { args } = await new Command()
|
|
.name("lrisscript")
|
|
.version("0.0.1")
|
|
.description(
|
|
"Compiles LrisScript (goofy subset of JS) to LASM (LRIS text representation)",
|
|
)
|
|
.arguments("<input:string> [output:string]")
|
|
.parse(Deno.args);
|
|
|
|
let ast: swc.Module;
|
|
|
|
if (args[0].endsWith(".ts")) {
|
|
ast = await swc.parse(await Deno.readTextFile(args[0]), {
|
|
syntax: "typescript",
|
|
});
|
|
} else {
|
|
ast = await swc.parse(await Deno.readTextFile(args[0]), {
|
|
syntax: "ecmascript",
|
|
});
|
|
}
|
|
|
|
const variablesTable: VariablesTableType = {};
|
|
const variableHoles: {
|
|
memoryLocation: number;
|
|
memorySize: number;
|
|
}[] = []; // 😳
|
|
// deno-lint-ignore prefer-const
|
|
let variableMemoryOffset = {
|
|
offset: 0x011F,
|
|
};
|
|
function getVariableMemoryOffset(varSize: number) {
|
|
for (const memoryHole of variableHoles) {
|
|
if (varSize <= memoryHole.memorySize) {
|
|
const memoryLocation = memoryHole.memoryLocation;
|
|
memoryHole.memoryLocation += varSize;
|
|
memoryHole.memorySize -= varSize;
|
|
return memoryLocation;
|
|
}
|
|
}
|
|
const oldMemoryOffset = variableMemoryOffset.offset;
|
|
variableMemoryOffset.offset += varSize;
|
|
return oldMemoryOffset;
|
|
}
|
|
// FIXME: zero out old memory here
|
|
function freeVariable(
|
|
variableName: string,
|
|
) {
|
|
const variableInfo = variablesTable[variableName];
|
|
delete variablesTable[variableName];
|
|
variableHoles.push({
|
|
memoryLocation: variableInfo.memoryLocation,
|
|
memorySize: variableInfo.memorySize,
|
|
});
|
|
}
|
|
|
|
function resolveNode(
|
|
node: swc.Node,
|
|
prc: { count: number },
|
|
variableModificationThings: VariablesThingType,
|
|
variablesTable: VariablesTableType,
|
|
) {
|
|
// deno-lint-ignore prefer-const
|
|
let instructions: string[] = [];
|
|
instructions.push(`/* start ${node.type} */`);
|
|
switch (node.type) {
|
|
case "VariableDeclaration": {
|
|
VariableDeclaration(
|
|
node,
|
|
variablesTable,
|
|
variableModificationThings,
|
|
prc,
|
|
instructions,
|
|
);
|
|
break;
|
|
}
|
|
case "ExpressionStatement": {
|
|
ExpressionStatement(
|
|
node,
|
|
variablesTable,
|
|
variableModificationThings,
|
|
prc,
|
|
instructions,
|
|
);
|
|
break;
|
|
}
|
|
case "IfStatement": {
|
|
IfStatement(
|
|
node,
|
|
variablesTable,
|
|
variableModificationThings,
|
|
prc,
|
|
instructions,
|
|
);
|
|
break;
|
|
}
|
|
case "WhileStatement": {
|
|
WhileStatement(
|
|
node,
|
|
variablesTable,
|
|
variableModificationThings,
|
|
prc,
|
|
instructions,
|
|
);
|
|
break;
|
|
}
|
|
case "BlockStatement": {
|
|
BlockStatement(
|
|
node,
|
|
variablesTable,
|
|
variableModificationThings,
|
|
prc,
|
|
instructions,
|
|
);
|
|
break;
|
|
}
|
|
default:
|
|
throw new Error(`Unimplemented node ${node.type}`);
|
|
}
|
|
instructions.push(`/* end ${node.type} */`);
|
|
return instructions;
|
|
}
|
|
|
|
export { resolveNode };
|
|
|
|
// deno-lint-ignore prefer-const
|
|
let prc = {
|
|
// i love java's crypt for only doing references in objects
|
|
count: 0,
|
|
};
|
|
let outputInstructions: string[] = [];
|
|
for (const node of ast.body) {
|
|
outputInstructions = outputInstructions.concat(
|
|
resolveNode(
|
|
node,
|
|
prc,
|
|
{
|
|
getVariableMemoryOffset,
|
|
freeVariable,
|
|
},
|
|
variablesTable,
|
|
),
|
|
);
|
|
console.log(variablesTable);
|
|
console.log(prc.count);
|
|
}
|
|
outputInstructions.push("HLT");
|
|
|
|
if (args[1]) {
|
|
await Deno.writeTextFile(`./${args[1]}`, outputInstructions.join("\n"));
|
|
} else {
|
|
console.log(outputInstructions.join("\n"));
|
|
}
|