diff --git a/source/compiler/codegen/expression/precedence.ts b/source/compiler/codegen/expression/precedence.ts index 92a2274..8a08e01 100644 --- a/source/compiler/codegen/expression/precedence.ts +++ b/source/compiler/codegen/expression/precedence.ts @@ -6,18 +6,19 @@ import { Panic } from "~/compiler/helper.ts"; const precedence = { ".": 1, "->": 1, "**": 2, - "*" : 3, "/" : 3, "%" : 3, - "+" : 4, "-" : 4, - "<<": 5, ">>": 5, - "<" : 6, ">" : 6, "<=": 6, ">=": 6, - "instanceof": 7, - "==": 8, "!=": 8, - "as": 9, + "%": 3, + "*" : 4, "/" : 4, + "+" : 5, "-" : 5, + "<<": 6, ">>": 6, + "<" : 7, ">" : 7, "<=": 7, ">=": 7, + "instanceof": 8, + "==": 9, "!=": 9, "&": 10, "^": 11, "|": 12, - "&&": 13, - "||": 14, + "as": 13, + "&&": 14, + "||": 15, } as { [key: string]: number }; export function GetPrecedence (a: string, b: string) { @@ -41,67 +42,68 @@ export type PrecedenceTree = Term_Expr_arg | { export function ApplyPrecedence(syntax: Term_Expr) { - const val_stack = new Array(); + const rpn = new Array(); const op_stack = new Array(); - val_stack.push(syntax.value[0]); - + rpn.push(syntax.value[0]); for (const action of syntax.value[1].value) { - const op = action.value[0].value; - const arg = action.value[1]; - - const prev = op_stack.pop(); - if (prev === undefined || GetPrecedence(prev, op) < 0) { - if (prev) op_stack.push(prev); - val_stack.push(arg); - op_stack.push(op); - } else { - const lhs = val_stack.pop()!; - - val_stack.push({ - type: "infix", - lhs: lhs, - op: op, - rhs: arg, - ref: ReferenceRange.union(lhs.ref, arg.ref) - }); - op_stack.push(prev); + const op = action.value[0].value; + while (op_stack.length > 0) { + const prev = op_stack[op_stack.length - 1]!; // peak + if (GetPrecedence(prev, op) <= 0) { + rpn.push(op_stack.pop()!); + } else break; } + op_stack.push(op); + rpn.push(action.value[1]); } - let root = val_stack[0]!; - for (let i=1; i 0) { + rpn.push(op_stack.pop()!); } - console.log(val_stack); + const stack = new Array(); + while (rpn.length > 0) { + const token = rpn.shift()!; - [9.5, 0.5, 8.0, 1.0]; - ["-", "-", "="] + if (typeof token != "string") { + stack.push(token); + continue; + } - // while (op_stack.length > 0) { - // const op = op_stack.pop()!; - // const rhs = val_stack.pop()!; - // const lhs = val_stack.pop()!; + const rhs = stack.pop()!; + const lhs = stack.pop()!; - // val_stack.push({ - // type: "infix", - // lhs, - // op, - // rhs, - // ref: ReferenceRange.union(lhs.ref, rhs.ref), - // }); - // } + stack.push({ + type: "infix", + lhs: lhs, + op: token, + rhs: rhs, + ref: ReferenceRange.union(lhs.ref, rhs.ref) + }) + } - // if (val_stack.length !== 1) throw new Error("Operand stack unexpectedly didn't fully drain"); + const root = stack.pop()!; + if (typeof root === "string") throw new Error("Please no"); + if (stack.length != 0) throw new Error("Please no"); return root; +} + + +// For debugging assistance +function StringifyPrecedence(tree: PrecedenceTree | string): string { + if (typeof tree === "string") return tree; + + if (tree.type === "infix") return `(${StringifyPrecedence(tree.lhs)} ${tree.op} ${StringifyPrecedence(tree.rhs)})`; + + const arg = tree.value[1].value[0]; + if (arg.type == "expr_brackets") return `(...)`; + if (arg.type != "constant") return `type[${arg.type}]`; + + if (arg.value[0].type == "boolean") return arg.value[0].value[0].value; + if (arg.value[0].type == "integer") return arg.value[0].value[0].value; + if (arg.value[0].type == "float") return arg.value[0].value[0].value; + return "str"; } \ No newline at end of file diff --git a/tests/e2e/compiler/numeric.test.ts b/tests/e2e/compiler/numeric.test.ts index 8dfb128..a0234d3 100644 --- a/tests/e2e/compiler/numeric.test.ts +++ b/tests/e2e/compiler/numeric.test.ts @@ -8,17 +8,17 @@ import { FuncRef } from "~/wasm/funcRef.ts"; const source = ` fn left(): f32 { - // return (-2.5 % 2.0) * -3.0; + // (-2.5 % 2.0) * -3.0; return -2.5 % 2.0 * -3.0; } -fn right(): f32 { - // return 9.5 - 0.5 - 8.0; - return 10.0 - 1.0 / 2.0 % 10.0 - 8.0; +fn right(): i32 { + // 10.0 - 0.5 - 8.0 + // return 10.0 - 1.0 / 2.0 % 10.0 - 8.0; + return 10 - 0 - 8; } fn main(): i32 { - return 1; // if ( 10.0 - ( 3.0 / 2.0 ) - 8.0 != 10.0 - 3.0 / 2.0 - 8.0 ) { // return 20;