|
|
|
@ -2,216 +2,211 @@ 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[],
|
|
|
|
|
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;
|
|
|
|
|
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;
|
|
|
|
|
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];
|
|
|
|
|
// 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}`,
|
|
|
|
|
);
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
|
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
|
|
|
|
|
];
|
|
|
|
|
variableModificationThings.freeVariable(
|
|
|
|
|
(expression.left as swc.Identifier).value,
|
|
|
|
|
);
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|