master
Drake 1 year ago
commit 1a0984a060

1
.gitignore vendored

@ -0,0 +1 @@
tstest.ts

@ -0,0 +1,9 @@
{
"deno.enable": true,
"deno.unstable": true,
"editor.formatOnSave": true,
"[typescript]": {
"editor.tabSize": 4,
"editor.defaultFormatter": "denoland.vscode-deno"
}
}

7
LrisScript.d.ts vendored

@ -0,0 +1,7 @@
export {};
declare global {
function free(variable: unknown): void;
function print(arg: string | number | boolean): void;
function println(arg: string | number | boolean): void;
}

@ -0,0 +1,7 @@
{
"fmt": {
"options": {
"indentWidth": 4
}
}
}

@ -0,0 +1,134 @@
{
"version": "2",
"remote": {
"https://deno.land/std@0.170.0/fmt/colors.ts": "03ad95e543d2808bc43c17a3dd29d25b43d0f16287fe562a0be89bf632454a12",
"https://deno.land/x/cliffy@v0.25.7/_utils/distance.ts": "02af166952c7c358ac83beae397aa2fbca4ad630aecfcd38d92edb1ea429f004",
"https://deno.land/x/cliffy@v0.25.7/command/_errors.ts": "a9bd23dc816b32ec96c9b8f3057218241778d8c40333b43341138191450965e5",
"https://deno.land/x/cliffy@v0.25.7/command/_utils.ts": "9ab3d69fabab6c335b881b8a5229cbd5db0c68f630a1c307aff988b6396d9baf",
"https://deno.land/x/cliffy@v0.25.7/command/command.ts": "a2b83c612acd65c69116f70dec872f6da383699b83874b70fcf38cddf790443f",
"https://deno.land/x/cliffy@v0.25.7/command/completions/_bash_completions_generator.ts": "43b4abb543d4dc60233620d51e69d82d3b7c44e274e723681e0dce2a124f69f9",
"https://deno.land/x/cliffy@v0.25.7/command/completions/_fish_completions_generator.ts": "d0289985f5cf0bd288c05273bfa286b24c27feb40822eb7fd9d7fee64e6580e8",
"https://deno.land/x/cliffy@v0.25.7/command/completions/_zsh_completions_generator.ts": "14461eb274954fea4953ee75938821f721da7da607dc49bcc7db1e3f33a207bd",
"https://deno.land/x/cliffy@v0.25.7/command/completions/bash.ts": "053aa2006ec327ccecacb00ba28e5eb836300e5c1bec1b3cfaee9ddcf8189756",
"https://deno.land/x/cliffy@v0.25.7/command/completions/complete.ts": "58df61caa5e6220ff2768636a69337923ad9d4b8c1932aeb27165081c4d07d8b",
"https://deno.land/x/cliffy@v0.25.7/command/completions/fish.ts": "9938beaa6458c6cf9e2eeda46a09e8cd362d4f8c6c9efe87d3cd8ca7477402a5",
"https://deno.land/x/cliffy@v0.25.7/command/completions/mod.ts": "aeef7ec8e319bb157c39a4bab8030c9fe8fa327b4c1e94c9c1025077b45b40c0",
"https://deno.land/x/cliffy@v0.25.7/command/completions/zsh.ts": "8b04ab244a0b582f7927d405e17b38602428eeb347a9968a657e7ea9f40e721a",
"https://deno.land/x/cliffy@v0.25.7/command/deprecated.ts": "bbe6670f1d645b773d04b725b8b8e7814c862c9f1afba460c4d599ffe9d4983c",
"https://deno.land/x/cliffy@v0.25.7/command/deps.ts": "275b964ce173770bae65f6b8ebe9d2fd557dc10292cdd1ed3db1735f0d77fa1d",
"https://deno.land/x/cliffy@v0.25.7/command/help/_help_generator.ts": "f7c349cb2ddb737e70dc1f89bcb1943ca9017a53506be0d4138e0aadb9970a49",
"https://deno.land/x/cliffy@v0.25.7/command/help/mod.ts": "09d74d3eb42d21285407cda688074c29595d9c927b69aedf9d05ff3f215820d3",
"https://deno.land/x/cliffy@v0.25.7/command/mod.ts": "d0a32df6b14028e43bb2d41fa87d24bc00f9662a44e5a177b3db02f93e473209",
"https://deno.land/x/cliffy@v0.25.7/command/type.ts": "24e88e3085e1574662b856ccce70d589959648817135d4469fab67b9cce1b364",
"https://deno.land/x/cliffy@v0.25.7/command/types.ts": "ae02eec0ed7a769f7dba2dd5d3a931a61724b3021271b1b565cf189d9adfd4a0",
"https://deno.land/x/cliffy@v0.25.7/command/types/action_list.ts": "33c98d449617c7a563a535c9ceb3741bde9f6363353fd492f90a74570c611c27",
"https://deno.land/x/cliffy@v0.25.7/command/types/boolean.ts": "3879ec16092b4b5b1a0acb8675f8c9250c0b8a972e1e4c7adfba8335bd2263ed",
"https://deno.land/x/cliffy@v0.25.7/command/types/child_command.ts": "f1fca390c7fbfa7a713ca15ef55c2c7656bcbb394d50e8ef54085bdf6dc22559",
"https://deno.land/x/cliffy@v0.25.7/command/types/command.ts": "325d0382e383b725fd8d0ef34ebaeae082c5b76a1f6f2e843fee5dbb1a4fe3ac",
"https://deno.land/x/cliffy@v0.25.7/command/types/enum.ts": "2178345972adf7129a47e5f02856ca3e6852a91442a1c78307dffb8a6a3c6c9f",
"https://deno.land/x/cliffy@v0.25.7/command/types/file.ts": "8618f16ac9015c8589cbd946b3de1988cc4899b90ea251f3325c93c46745140e",
"https://deno.land/x/cliffy@v0.25.7/command/types/integer.ts": "29864725fd48738579d18123d7ee78fed37515e6dc62146c7544c98a82f1778d",
"https://deno.land/x/cliffy@v0.25.7/command/types/number.ts": "aeba96e6f470309317a16b308c82e0e4138a830ec79c9877e4622c682012bc1f",
"https://deno.land/x/cliffy@v0.25.7/command/types/string.ts": "e4dadb08a11795474871c7967beab954593813bb53d9f69ea5f9b734e43dc0e0",
"https://deno.land/x/cliffy@v0.25.7/command/upgrade/mod.ts": "17e2df3b620905583256684415e6c4a31e8de5c59066eb6d6c9c133919292dc4",
"https://deno.land/x/cliffy@v0.25.7/command/upgrade/provider.ts": "d6fb846043232cbd23c57d257100c7fc92274984d75a5fead0f3e4266dc76ab8",
"https://deno.land/x/cliffy@v0.25.7/command/upgrade/provider/deno_land.ts": "24f8d82e38c51e09be989f30f8ad21f9dd41ac1bb1973b443a13883e8ba06d6d",
"https://deno.land/x/cliffy@v0.25.7/command/upgrade/provider/github.ts": "99e1b133dd446c6aa79f69e69c46eb8bc1c968dd331c2a7d4064514a317c7b59",
"https://deno.land/x/cliffy@v0.25.7/command/upgrade/provider/nest_land.ts": "0e07936cea04fa41ac9297f32d87f39152ea873970c54cb5b4934b12fee1885e",
"https://deno.land/x/cliffy@v0.25.7/command/upgrade/upgrade_command.ts": "3640a287d914190241ea1e636774b1b4b0e1828fa75119971dd5304784061e05",
"https://deno.land/x/cliffy@v0.25.7/flags/_errors.ts": "f1fbb6bfa009e7950508c9d491cfb4a5551027d9f453389606adb3f2327d048f",
"https://deno.land/x/cliffy@v0.25.7/flags/_utils.ts": "340d3ecab43cde9489187e1f176504d2c58485df6652d1cdd907c0e9c3ce4cc2",
"https://deno.land/x/cliffy@v0.25.7/flags/_validate_flags.ts": "16eb5837986c6f6f7620817820161a78d66ce92d690e3697068726bbef067452",
"https://deno.land/x/cliffy@v0.25.7/flags/deprecated.ts": "a72a35de3cc7314e5ebea605ca23d08385b218ef171c32a3f135fb4318b08126",
"https://deno.land/x/cliffy@v0.25.7/flags/flags.ts": "68a9dfcacc4983a84c07ba19b66e5e9fccd04389fad215210c60fb414cc62576",
"https://deno.land/x/cliffy@v0.25.7/flags/types.ts": "7452ea5296758fb7af89930349ce40d8eb9a43b24b3f5759283e1cb5113075fd",
"https://deno.land/x/cliffy@v0.25.7/flags/types/boolean.ts": "4c026dd66ec9c5436860dc6d0241427bdb8d8e07337ad71b33c08193428a2236",
"https://deno.land/x/cliffy@v0.25.7/flags/types/integer.ts": "b60d4d590f309ddddf066782d43e4dc3799f0e7d08e5ede7dc62a5ee94b9a6d9",
"https://deno.land/x/cliffy@v0.25.7/flags/types/number.ts": "610936e2d29de7c8c304b65489a75ebae17b005c6122c24e791fbed12444d51e",
"https://deno.land/x/cliffy@v0.25.7/flags/types/string.ts": "e89b6a5ce322f65a894edecdc48b44956ec246a1d881f03e97bbda90dd8638c5",
"https://deno.land/x/cliffy@v0.25.7/table/border.ts": "2514abae4e4f51eda60a5f8c927ba24efd464a590027e900926b38f68e01253c",
"https://deno.land/x/cliffy@v0.25.7/table/cell.ts": "1d787d8006ac8302020d18ec39f8d7f1113612c20801b973e3839de9c3f8b7b3",
"https://deno.land/x/cliffy@v0.25.7/table/deps.ts": "5b05fa56c1a5e2af34f2103fd199e5f87f0507549963019563eae519271819d2",
"https://deno.land/x/cliffy@v0.25.7/table/layout.ts": "46bf10ae5430cf4fbb92f23d588230e9c6336edbdb154e5c9581290562b169f4",
"https://deno.land/x/cliffy@v0.25.7/table/row.ts": "5f519ba7488d2ef76cbbf50527f10f7957bfd668ce5b9169abbc44ec88302645",
"https://deno.land/x/cliffy@v0.25.7/table/table.ts": "ec204c9d08bb3ff1939c5ac7412a4c9ed7d00925d4fc92aff9bfe07bd269258d",
"https://deno.land/x/cliffy@v0.25.7/table/utils.ts": "187bb7dcbcfb16199a5d906113f584740901dfca1007400cba0df7dcd341bc29"
},
"npm": {
"specifiers": {
"@swc/core@1.3.35": "@swc/core@1.3.35",
"@swc/wasm-web@1.3.35": "@swc/wasm-web@1.3.35",
"@swc/wasm@1.3.35": "@swc/wasm@1.3.35",
"acorn@8.8.2": "acorn@8.8.2"
},
"packages": {
"@swc/core-darwin-arm64@1.3.35": {
"integrity": "sha512-zQUFkHx4gZpu0uo2IspvPnKsz8bsdXd5bC33xwjtoAI1cpLerDyqo4v2zIahEp+FdKZjyVsLHtfJiQiA1Qka3A==",
"dependencies": {}
},
"@swc/core-darwin-x64@1.3.35": {
"integrity": "sha512-oOSkSGWtALovaw22lNevKD434OQTPf8X+dVPvPMrJXJpJ34dWDlFWpLntoc+arvKLNZ7LQmTuk8rR1hkrAY7cw==",
"dependencies": {}
},
"@swc/core-linux-arm-gnueabihf@1.3.35": {
"integrity": "sha512-Yie8k00O6O8BCATS/xeKStquV4OYSskUGRDXBQVDw1FrE23PHaSeHCgg4q6iNZjJzXCOJbaTCKnYoIDn9DMf7A==",
"dependencies": {}
},
"@swc/core-linux-arm64-gnu@1.3.35": {
"integrity": "sha512-Zlv3WHa/4x2p51HSvjUWXHfSe1Gl2prqImUZJc8NZOlj75BFzVuR0auhQ+LbwvIQ3gaA1LODX9lyS9wXL3yjxA==",
"dependencies": {}
},
"@swc/core-linux-arm64-musl@1.3.35": {
"integrity": "sha512-u6tCYsrSyZ8U+4jLMA/O82veBfLy2aUpn51WxQaeH7wqZGy9TGSJXoO8vWxARQ6b72vjsnKDJHP4MD8hFwcctg==",
"dependencies": {}
},
"@swc/core-linux-x64-gnu@1.3.35": {
"integrity": "sha512-Dtxf2IbeH7XlNhP1Qt2/MvUPkpEbn7hhGfpSRs4ot8D3Vf5QEX4S/QtC1OsFWuciiYgHAT1Ybjt4xZic9DSkmA==",
"dependencies": {}
},
"@swc/core-linux-x64-musl@1.3.35": {
"integrity": "sha512-4XavNJ60GprjpTiESCu5daJUnmErixPAqDitJSMu4TV32LNIE8G00S9pDLXinDTW1rgcGtQdq1NLkNRmwwovtg==",
"dependencies": {}
},
"@swc/core-win32-arm64-msvc@1.3.35": {
"integrity": "sha512-dNGfKCUSX2M4qVyaS80Lyos0FkXyHRCvrdQ2Y4Hrg3FVokiuw3yY6fLohpUfQ5ws3n2A39dh7jGDeh34+l0sGA==",
"dependencies": {}
},
"@swc/core-win32-ia32-msvc@1.3.35": {
"integrity": "sha512-ChuPSrDR+JBf7S7dEKPicnG8A3bM0uWPsW2vG+V2wH4iNfNxKVemESHosmYVeEZXqMpomNMvLyeHep1rjRsc0Q==",
"dependencies": {}
},
"@swc/core-win32-x64-msvc@1.3.35": {
"integrity": "sha512-/RvphT4WfuGfIK84Ha0dovdPrKB1bW/mc+dtdmhv2E3EGkNc5FoueNwYmXWRimxnU7X0X7IkcRhyKB4G5DeAmg==",
"dependencies": {}
},
"@swc/core@1.3.35": {
"integrity": "sha512-KmiBin0XSVzJhzX19zTiCqmLslZ40Cl7zqskJcTDeIrRhfgKdiAsxzYUanJgMJIRjYtl9Kcg1V/Ip2o2wL8v3w==",
"dependencies": {
"@swc/core-darwin-arm64": "@swc/core-darwin-arm64@1.3.35",
"@swc/core-darwin-x64": "@swc/core-darwin-x64@1.3.35",
"@swc/core-linux-arm-gnueabihf": "@swc/core-linux-arm-gnueabihf@1.3.35",
"@swc/core-linux-arm64-gnu": "@swc/core-linux-arm64-gnu@1.3.35",
"@swc/core-linux-arm64-musl": "@swc/core-linux-arm64-musl@1.3.35",
"@swc/core-linux-x64-gnu": "@swc/core-linux-x64-gnu@1.3.35",
"@swc/core-linux-x64-musl": "@swc/core-linux-x64-musl@1.3.35",
"@swc/core-win32-arm64-msvc": "@swc/core-win32-arm64-msvc@1.3.35",
"@swc/core-win32-ia32-msvc": "@swc/core-win32-ia32-msvc@1.3.35",
"@swc/core-win32-x64-msvc": "@swc/core-win32-x64-msvc@1.3.35"
}
},
"@swc/wasm-web@1.3.35": {
"integrity": "sha512-iMNkVgHGJgSJsekNIyyDme8DazmQvMwd2qYsWAqA9IZHtbuvurIfhSiK2nMqN5nM+YEWIoa/y1Daug49DuyDxg==",
"dependencies": {}
},
"@swc/wasm@1.3.35": {
"integrity": "sha512-8xBOgl9eziAuqF4HYwYx4Kh6eHfOQECvO0ZMlrFNW0jgE+ntqxcRjBhuzZ6iWb24nifzXbuGLQntbns4IJYJgQ==",
"dependencies": {}
},
"acorn@8.8.2": {
"integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==",
"dependencies": {}
}
}
}
}

12
src/index.d.ts vendored

@ -0,0 +1,12 @@
type VariablesTableType = {
[name: string]: {
memoryLocation: number;
memorySize: number;
memoryType: "string" | "int" | "bool";
};
};
type VariablesThingType = {
getVariableMemoryOffset: (varSize: number) => number;
freeVariable: (variableName: string) => void;
};

@ -0,0 +1,144 @@
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";
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) {
memoryHole.memorySize -= varSize;
return memoryHole.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[] = [];
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;
}
default:
throw new Error(`Unimplemented node ${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"));
}

@ -0,0 +1,217 @@
import swc from "npm:@swc/wasm@1.3.35";
import VariableDeclaration from "./VariableDeclaration.ts";
export default function ExpressionStatement(
node: swc.Node,
variablesTable: VariablesTableType,
variableModificationThings: VariablesThingType,
prc: { count: number },
instructions: string[],
) {
const expression = (node as swc.ExpressionStatement)
.expression;
switch (expression.type) {
case "CallExpression": {
const typedNode = expression as swc.CallExpression;
const functionName = (typedNode.callee as swc.Identifier).value;
switch (functionName) {
case "print":
case "println": {
if (typedNode.arguments.length !== 1) {
throw new Error(
"Incorrect arguments passed to println",
);
}
switch (typedNode.arguments[0].expression.type) {
case "Identifier": {
const typedExpr = typedNode.arguments[0]
.expression as swc.Identifier;
const variableInfo =
variablesTable[typedExpr.value];
if (
variableInfo.memoryType === "int" ||
variableInfo.memoryType === "bool"
) {
instructions.push(`LOL 01 0119`);
prc.count += 4;
}
instructions.push(`LOL 00 0118`);
instructions.push(`LOL 01 0117`);
prc.count += 8;
for (
let i = variableInfo.memoryLocation;
i <
variableInfo.memoryLocation +
variableInfo.memorySize;
i++
) {
instructions.push(
`LOA ${
i.toString(16).padStart(
4,
"0",
)
} 0118`,
);
prc.count += 5;
}
instructions.push(`LOL 00 0117`);
prc.count += 4;
break;
}
case "StringLiteral": {
//define tmp variable
const typedExpr = typedNode.arguments[0]
.expression as swc.StringLiteral;
const tmpVariableName = "printTmpVar";
VariableDeclaration(
{
declarations: [{
id: {
value: tmpVariableName,
},
init: {
type: "StringLiteral",
value: typedExpr.value,
},
}],
} as swc.VariableDeclaration,
variablesTable,
variableModificationThings,
prc,
instructions,
);
const variableInfo =
variablesTable[tmpVariableName];
// pritning code
instructions.push(`LOL 00 0118`);
instructions.push(`LOL 01 0117`);
prc.count += 8;
for (
let i = variableInfo.memoryLocation;
i <
variableInfo.memoryLocation +
variableInfo.memorySize;
i++
) {
instructions.push(
`LOA ${
i.toString(16).padStart(
4,
"0",
)
} 0118`,
);
prc.count += 5;
}
instructions.push(`LOL 00 0117`);
prc.count += 4;
//free tmp variable
variableModificationThings.freeVariable(
tmpVariableName,
);
break;
}
default:
throw new Error(
`node type ${
typedNode.arguments[0].expression.type
} not allowed in println`,
);
}
instructions.push(`LOL 00 0119`);
instructions.push(`LOL 00 0118`);
prc.count += 8;
// print newline
if (functionName === "println") {
instructions.push(`LOL 01 0116`);
instructions.push(`LOL 01 0117`);
instructions.push(`LOL 00 0116`);
instructions.push(`LOL 00 0117`);
prc.count += 16;
}
break;
}
case "asm": {
const typedNode = (node as swc.ExpressionStatement)
.expression as swc.CallExpression;
const typedValue = typedNode.arguments[0]
.expression as swc.Identifier;
instructions.push(typedValue.value);
const eles = typedValue.value.split(" ");
eles.shift();
prc.count += 1;
for (let i = 0; i < eles.length; i++) {
const e = eles[i];
switch (e.length) {
case 2: {
prc.count += 1;
break;
}
case 4: {
prc.count += 2;
break;
}
default:
throw new Error(
"what the hell are you doing in your inline assembly",
);
}
}
break;
}
case "free": {
const typedNode = (node as swc.ExpressionStatement)
.expression as swc.CallExpression;
const typedValue = typedNode.arguments[0]
.expression as swc.Identifier;
variableModificationThings.freeVariable(typedValue.value);
break;
}
default:
throw new Error(
`Unimplemented function ${functionName}`,
);
}
break;
}
case "AssignmentExpression": {
const typedNode = expression as swc.AssignmentExpression;
switch (expression.operator) {
case "=": {
const variableInfo = variablesTable[
(expression.left as swc.Identifier).value
];
if (variableInfo.memoryType === "string") {
throw new Error(
"string variable reassignment not supported",
);
} else {
VariableDeclaration(
{
type: "VariableDeclaration",
declarations: [
{
init: typedNode.right,
id: typedNode.left,
},
],
} as swc.VariableDeclaration,
variablesTable,
variableModificationThings,
prc,
instructions,
);
}
break;
}
default:
throw new Error("please kill me");
}
break;
}
}
}

@ -0,0 +1,130 @@
import swc from "npm:@swc/wasm@1.3.35";
import { resolveNode } from "../index.ts";
export default function IfStatement(
node: swc.Node,
variablesTable: VariablesTableType,
variableModificationThings: VariablesThingType,
prc: { count: number },
mainInstructions: string[],
) {
const typedNode = node as swc.IfStatement;
switch (typedNode.test.type) {
case "BinaryExpression": {
const typedExpr = typedNode.test as swc.BinaryExpression;
let addr1: number;
let addr2: number;
switch (typedExpr.left.type) {
case "Identifier": {
const typedValue = typedExpr.left;
const variableInfo = variablesTable[typedValue.value];
if (variableInfo.memoryType === "string") {
// TODO: implement string comparisons
throw new Error(
"i would rather pipi in pampers than implement string comparisons",
);
}
addr1 = variableInfo.memoryLocation;
break;
}
default:
throw new Error(
`left side comparison not implemented for node type ${typedExpr.left.type}`,
);
}
switch (typedExpr.right.type) {
case "Identifier": {
const typedValue = typedExpr.right;
const variableInfo = variablesTable[typedValue.value];
if (variableInfo.memoryType === "string") {
// TODO: implement string comparisons
throw new Error(
"i would rather pipi in pampers than implement string comparisons",
);
}
addr2 = variableInfo.memoryLocation;
break;
}
case "BooleanLiteral": {
const value = typedExpr.right.value;
mainInstructions.push(
`LOL ${value ? "01" : "00"} 00F2`,
);
addr2 = 0x00F2;
prc.count += 4;
break;
}
default:
throw new Error(
`right side comparison not implemented for node type ${typedExpr.right.type}`,
);
}
let ourInsts = [`${(() => {
switch (typedExpr.operator) {
case "!=":
case "!==":
return "JEA";
case "==":
case "===":
return "JNA";
default:
throw new Error(
`if statement comparison operator ${typedExpr.operator} unimplemented`,
);
}
})} TODO${
(
typedExpr.operator === "<" ||
typedExpr.operator === ">"
)
? ` ${
addr1.toString(16).padStart(
4,
"0",
)
} ${
addr2.toString(16).padStart(
4,
"0",
)
}`
: ""
}`];
prc.count += 7;
const oldPRC = prc;
for (
const node of (typedNode.consequent as swc.BlockStatement)
.stmts
) {
ourInsts = ourInsts.concat(
resolveNode(
node,
prc,
variableModificationThings,
variablesTable,
),
);
}
ourInsts[0] = ourInsts[0].replace(
"TODO",
prc.count.toString(16).padStart(
4,
"0",
),
);
ourInsts.push("NOP");
prc.count++;
for (const inst of ourInsts) {
mainInstructions.push(inst);
}
break;
}
default:
throw new Error(
`if statement test with node type ${typedNode.test.type} not implemented`,
);
}
}

@ -0,0 +1,325 @@
import swc from "npm:@swc/wasm@1.3.35";
export default function VariableDeclaration(
node: swc.Node,
variablesTable: VariablesTableType,
variableModificationThings: VariablesThingType,
prc: { count: number },
instructions: string[],
) {
const typedNode = node as swc.VariableDeclaration;
switch (typedNode.declarations[0].init?.type) {
case "StringLiteral": {
const typedValue = typedNode.declarations[0]
.init as swc.StringLiteral;
variablesTable[
(typedNode.declarations[0].id as swc.Identifier).value
] = {
memorySize: typedValue.value.length,
memoryLocation: variableModificationThings
.getVariableMemoryOffset(typedValue.value.length),
memoryType: "string",
};
for (let i = 0; i < typedValue.value.length; i++) {
const char = typedValue.value[i];
const charCode = char.charCodeAt(0);
instructions.push(
`LOL ${charCode.toString(16).padStart(2, "0")} ${
(variablesTable[
(typedNode.declarations[0].id as swc.Identifier)
.value
].memoryLocation + i).toString(16).padStart(
4,
"0",
)
}`,
);
prc.count += 4;
}
break;
}
case "NumericLiteral": {
const typedValue = typedNode.declarations[0]
.init as swc.NumericLiteral;
if (typedValue.value > 255) {
// TODO: implement 16-bit etc.
throw new Error("only 8-bit integers allowed");
}
if (
!variablesTable[
(typedNode.declarations[0].id as swc.Identifier).value
]
) {
variablesTable[
(typedNode.declarations[0].id as swc.Identifier).value
] = {
memorySize: 1,
memoryLocation: variableModificationThings
.getVariableMemoryOffset(1),
memoryType: "int",
};
}
instructions.push(
`LOL ${typedValue.value.toString(16).padStart(2, "0")} ${
variablesTable[
(typedNode.declarations[0].id as swc.Identifier).value
].memoryLocation.toString(16).padStart(
4,
"0",
)
}`,
);
prc.count += 4;
break;
}
case "BooleanLiteral": {
const typedValue = typedNode.declarations[0]
.init as swc.BooleanLiteral;
if (
!variablesTable[
(typedNode.declarations[0].id as swc.Identifier).value
]
) {
variablesTable[
(typedNode.declarations[0].id as swc.Identifier).value
] = {
memorySize: 1,
memoryLocation: variableModificationThings
.getVariableMemoryOffset(1),
memoryType: "bool",
};
}
instructions.push(
`LOL ${typedValue.value ? "01" : "00"} ${
variablesTable[
(typedNode.declarations[0].id as swc.Identifier).value
].memoryLocation.toString(16).padStart(
4,
"0",
)
}`,
);
prc.count += 4;
break;
}
// FIXME: this should be impled elsewhere, especially because recursion
case "BinaryExpression": {
const typedValue = typedNode.declarations[0]
.init as swc.BinaryExpression;
switch (typedValue.operator) {
case "+": {
switch (typedValue.left.type) {
case "Identifier": {
switch (typedValue.right.type) {
case "Identifier": {
const leftVar = variablesTable[
typedValue.left.value
];
const rightVar = variablesTable[
typedValue.right.value
];
instructions.push(
`AAA ${
leftVar.memoryLocation
.toString(16).padStart(
4,
"0",
)
} ${
rightVar.memoryLocation
.toString(16).padStart(
4,
"0",
)
}`,
);
prc.count += 5;
if (
!variablesTable[
(typedNode.declarations[0]
.id as swc.Identifier).value
]
) {
variablesTable[
(typedNode.declarations[0]
.id as swc.Identifier).value
] = {
memorySize: 1,
memoryLocation:
variableModificationThings
.getVariableMemoryOffset(1),
memoryType: "int",
};
}
instructions.push(
`STA ${
variablesTable[
(typedNode.declarations[0]
.id as swc.Identifier).value
].memoryLocation
.toString(16).padStart(
4,
"0",
)
}`,
);
prc.count += 3;
break;
}
case "NumericLiteral": {
const leftVar = variablesTable[
typedValue.left.value
];
const rightVal = typedValue.right.value;
instructions.push(
`LOL ${
rightVal.toString(16).padStart(
2,
"0",
)
} 00F0`,
);
prc.count += 4;
instructions.push(
`AAA ${
leftVar.memoryLocation
.toString(16).padStart(
4,
"0",
)
} 00F0`,
);
prc.count += 5;
if (
!variablesTable[
(typedNode.declarations[0]
.id as swc.Identifier).value
]
) {
variablesTable[
(typedNode.declarations[0]
.id as swc.Identifier).value
] = {
memorySize: 1,
memoryLocation:
variableModificationThings
.getVariableMemoryOffset(1),
memoryType: "int",
};
}
instructions.push(
`STA ${
variablesTable[
(typedNode.declarations[0]
.id as swc.Identifier).value
].memoryLocation
.toString(16).padStart(
4,
"0",
)
}`,
);
prc.count += 3;
break;
}
default:
throw new Error(
`Arithmetic on ${typedValue.right.type} not implemented`,
);
}
break;
}
default:
throw new Error(
`Arithmetic on ${typedValue.left.type} not implemented`,
);
}
break;
}
case "-": {
switch (typedValue.left.type) {
case "Identifier": {
switch (typedValue.right.type) {
case "Identifier": {
const leftVar = variablesTable[
typedValue.left.value
];
const rightVar = variablesTable[
typedValue.right.value
];
instructions.push(
`SAA ${
leftVar.memoryLocation
.toString(16).padStart(
4,
"0",
)
} ${
rightVar.memoryLocation
.toString(16).padStart(
4,
"0",
)
}`,
);
prc.count += 5;
if (
!variablesTable[
(typedNode.declarations[0]
.id as swc.Identifier).value
]
) {
variablesTable[
(typedNode.declarations[0]
.id as swc.Identifier).value
] = {
memorySize: 1,
memoryLocation:
variableModificationThings
.getVariableMemoryOffset(1),
memoryType: "int",
};
}
instructions.push(
`STA ${
variablesTable[
(typedNode.declarations[0]
.id as swc.Identifier).value
].memoryLocation
.toString(16).padStart(
4,
"0",
)
}`,
);
prc.count += 3;
break;
}
default:
throw new Error(
`Arithmetic on ${typedValue.right.type} not implemented`,
);
}
break;
}
default:
throw new Error(
`Arithmetic on ${typedValue.left.type} not implemented`,
);
}
break;
}
default:
throw new Error(
`Operator type ${typedValue.operator} not implemented`,
);
}
break;
}
default:
throw new Error(
`Variable type ${typedNode.declarations[0].init
?.type} not implemented`,
);
}
}

@ -0,0 +1,354 @@
import swc from "npm:@swc/wasm@1.3.35";
import { resolveNode } from "../index.ts";
export default function WhileStatement(
node: swc.Node,
variablesTable: VariablesTableType,
variableModificationThings: VariablesThingType,
prc: { count: number },
mainInstructions: string[],
) {
const typedNode = node as swc.WhileStatement;
switch (typedNode.test.type) {
case "BinaryExpression": {
const typedExpr = typedNode.test as swc.BinaryExpression;
switch (typedExpr.operator) {
case "==":
case "===": {
let addr1: number;
let addr2: number;
switch (typedExpr.left.type) {
case "Identifier": {
const typedValue = typedExpr.left;
const variableInfo =
variablesTable[typedValue.value];
if (variableInfo.memoryType === "string") {
// TODO: implement string comparisons
throw new Error(
"i would rather pipi in pampers than implement string comparisons",
);
}
addr1 = variableInfo.memoryLocation;
break;
}
default:
throw new Error(
"probably something idk i don't feel like writing error messages anymore",
);
}
switch (typedExpr.right.type) {
case "Identifier": {
const typedValue = typedExpr.right;
const variableInfo =
variablesTable[typedValue.value];
if (variableInfo.memoryType === "string") {
// TODO: implement string comparisons
throw new Error(
"i would rather pipi in pampers than implement string comparisons",
);
}
addr2 = variableInfo.memoryLocation;
break;
}
default:
throw new Error(
"probably something idk i don't feel like writing error messages anymore",
);
}
let ourInsts = [`JMP TODO`];
prc.count += 3;
const oldPRC = prc;
for (
const node of (typedNode.body as swc.BlockStatement)
.stmts
) {
ourInsts = ourInsts.concat(
resolveNode(
node,
prc,
variableModificationThings,
variablesTable,
),
);
}
ourInsts[0] = ourInsts[0].replace(
"TODO",
prc.count.toString(16).padStart(
4,
"0",
),
);
ourInsts.push(`JEA ${
oldPRC.count.toString(16).padStart(
4,
"0",
)
} ${
addr1.toString(16).padStart(
4,
"0",
)
} ${
addr2.toString(16).padStart(
4,
"0",
)
}`);
prc.count += 7;
for (const inst of ourInsts) {
mainInstructions.push(inst);
}
break;
}
case "!=":
case "!==": {
let addr1: number;
let addr2: number;
switch (typedExpr.left.type) {
case "Identifier": {
const typedValue = typedExpr.left;
const variableInfo =
variablesTable[typedValue.value];
if (variableInfo.memoryType === "string") {
// TODO: implement string comparisons
throw new Error(
"i would rather pipi in pampers than implement string comparisons",
);
}
addr1 = variableInfo.memoryLocation;
break;
}
case "NumericLiteral": {
const value = typedExpr.left.value;
mainInstructions.push(
`LOL ${
value.toString(16).padStart(
2,
"0",
)
} 00F1`,
);
addr1 = 0x00F1;
prc.count += 4;
break;
}
default:
throw new Error(
"probably something idk i don't feel like writing error messages anymore",
);
}
switch (typedExpr.right.type) {
case "Identifier": {
const typedValue = typedExpr.right;
const variableInfo =
variablesTable[typedValue.value];
if (variableInfo.memoryType === "string") {
// TODO: implement string comparisons
throw new Error(
"i would rather pipi in pampers than implement string comparisons",
);
}
addr2 = variableInfo.memoryLocation;
break;
}
case "NumericLiteral": {
const value = typedExpr.right.value;
mainInstructions.push(
`LOL ${
value.toString(16).padStart(
2,
"0",
)
} 00F2`,
);
addr2 = 0x00F2;
prc.count += 4;
break;
}
default:
throw new Error(
`probably something to do with ${typedExpr.right.type} idk i don't feel like writing error messages anymore`,
);
}
let ourInsts = [`JML TODO`];
prc.count += 3;
const oldPRC = prc.count;
for (
const node of (typedNode.body as swc.BlockStatement)
.stmts
) {
ourInsts = ourInsts.concat(
resolveNode(
node,
prc,
variableModificationThings,
variablesTable,
),
);
}
ourInsts[0] = ourInsts[0].replace(
"TODO",
prc.count.toString(16).padStart(
4,
"0",
),
);
ourInsts.push(`JNA ${
oldPRC.toString(16).padStart(
4,
"0",
)
} ${
addr1.toString(16).padStart(
4,
"0",
)
} ${
addr2.toString(16).padStart(
4,
"0",
)
}`);
prc.count += 7;
for (const inst of ourInsts) {
mainInstructions.push(inst);
}
break;
}
case ">": {
let addr1: number;
let addr2: number;
switch (typedExpr.left.type) {
case "Identifier": {
const typedValue = typedExpr.left;
const variableInfo =
variablesTable[typedValue.value];
if (variableInfo.memoryType === "string") {
// TODO: implement string comparisons
throw new Error(
"i would rather pipi in pampers than implement string comparisons",
);
}
addr1 = variableInfo.memoryLocation;
break;
}
case "NumericLiteral": {
const value = typedExpr.left.value;
mainInstructions.push(
`LOL ${
value.toString(16).padStart(
2,
"0",
)
} 00F1`,
);
addr1 = 0x00F1;
prc.count += 4;
break;
}
default:
throw new Error(
"probably something idk i don't feel like writing error messages anymore",
);
}
switch (typedExpr.right.type) {
case "Identifier": {
const typedValue = typedExpr.right;
const variableInfo =
variablesTable[typedValue.value];
if (variableInfo.memoryType === "string") {
// TODO: implement string comparisons
throw new Error(
"i would rather pipi in pampers than implement string comparisons",
);
}
addr2 = variableInfo.memoryLocation;
break;
}
case "NumericLiteral": {
const value = typedExpr.right.value;
mainInstructions.push(
`LOL ${
value.toString(16).padStart(
2,
"0",
)
} 00F2`,
);
addr2 = 0x00F2;
prc.count += 4;
break;
}
default:
throw new Error(
`probably something to do with ${typedExpr.right.type} idk i don't feel like writing error messages anymore`,
);
}
let ourInsts = [`JML TODO`];
prc.count += 3;
const oldPRC = prc.count;
for (
const node of (typedNode.body as swc.BlockStatement)
.stmts
) {
ourInsts = ourInsts.concat(
resolveNode(
node,
prc,
variableModificationThings,
variablesTable,
),
);
}
ourInsts[0] = ourInsts[0].replace(
"TODO",
prc.count.toString(16).padStart(
4,
"0",
),
);
ourInsts.push(`JGT ${
oldPRC.toString(16).padStart(
4,
"0",
)
} ${
addr1.toString(16).padStart(
4,
"0",
)
} ${
addr2.toString(16).padStart(
4,
"0",
)
}`);
prc.count += 7;
for (const inst of ourInsts) {
mainInstructions.push(inst);
}
break;
}
default:
throw new Error(
`comparison operator ${typedExpr.operator} not implemented`,
);
}
break;
}
default:
throw new Error(
`if statement test with node type ${typedNode.test.type} not implemented`,
);
}
}
Loading…
Cancel
Save