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.

355 lines
14 KiB

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`,
);
}
}