Skip to content

Commit

Permalink
swapped to using shunting yards
Browse files Browse the repository at this point in the history
  • Loading branch information
AjaniBilby committed Mar 24, 2024
1 parent 1ddb781 commit 340968e
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 51 deletions.
108 changes: 63 additions & 45 deletions source/compiler/codegen/expression/precedence.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,26 @@ import { Panic } from "~/compiler/helper.ts";

const precedence = {
".": 1, "->": 1,
"**": 2,
"*" : 3, "/" : 3, "%" : 3,
"+" : 4, "-" : 4,
"<<": 5, ">>": 5,
"<" : 6, ">" : 6, "<=": 6, ">=": 6,
"instanceof": 6.5,
"==": 7, "!=": 7,
"as": 7.5,
"&": 8,
"^": 9,
"|": 10,
"&&": 11,
"||": 12,
"instanceof": 7,
"==": 8, "!=": 8,
"as": 9,
"&": 10,
"^": 11,
"|": 12,
"&&": 13,
"||": 14,
} as { [key: string]: number };

export function GetPrecedence (a: string, b: string) {
const A = precedence[a];
const B = precedence[b];
if (!A) Panic(`Unknown infix operation ${a}`);
if (!B) Panic(`Unknown infix operation ${a}`);
if (A === undefined) Panic(`Unknown infix operation ${a} 0x${a.charCodeAt(0).toString(16)}`);
if (B === undefined) Panic(`Unknown infix operation ${b} 0x${b.charCodeAt(0).toString(16)}`);

return A !== B
? Math.min(1, Math.max(-1, A-B))
Expand All @@ -39,51 +40,68 @@ export type PrecedenceTree = Term_Expr_arg | {
};

export function ApplyPrecedence(syntax: Term_Expr) {
let root: PrecedenceTree = syntax.value[0] as PrecedenceTree;

const val_stack = new Array<PrecedenceTree>();
const op_stack = new Array<string>();

val_stack.push(syntax.value[0]);

for (const action of syntax.value[1].value) {
const op = action.value[0].value;
const arg = action.value[1]

// First action
if (root.type !== "infix") {
root = {
type: "infix",
lhs: root,
op,
rhs: arg,
ref: ReferenceRange.union(root.ref, arg.ref)
};
continue;
}
const arg = action.value[1];

const p = GetPrecedence(root.op, op);
if (p > 0) {
// Transform stealing previous operand
// (1 + 2) * 3 -> (2 * 3) + 1
root = {
type: "infix",
lhs: root.lhs,
op: root.op,
rhs: {
type: "infix",
lhs: root.rhs,
op,
rhs: arg,
ref: ReferenceRange.union(root.ref, arg.ref)
},
ref: ReferenceRange.union(arg.ref, arg.ref)
}
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 {
root = {
const lhs = val_stack.pop()!;

val_stack.push({
type: "infix",
lhs: root,
lhs: lhs,
op: op,
rhs: arg,
ref: ReferenceRange.union(root.ref, arg.ref)
}
ref: ReferenceRange.union(lhs.ref, arg.ref)
});
op_stack.push(prev);
}
}

let root = val_stack[0]!;
for (let i=1; i<val_stack.length; i++) {
const nx = val_stack[i]!;
root = {
type: "infix",
lhs: root,
op: op_stack[i-1]!,
rhs: nx,
ref: ReferenceRange.union(root.ref, nx.ref),
}
console.log(root.op);
}

console.log(val_stack);

[9.5, 0.5, 8.0, 1.0];
["-", "-", "="]

// while (op_stack.length > 0) {
// const op = op_stack.pop()!;
// const rhs = val_stack.pop()!;
// const lhs = val_stack.pop()!;

// val_stack.push({
// type: "infix",
// lhs,
// op,
// rhs,
// ref: ReferenceRange.union(lhs.ref, rhs.ref),
// });
// }

// if (val_stack.length !== 1) throw new Error("Operand stack unexpectedly didn't fully drain");

return root;
}
20 changes: 14 additions & 6 deletions tests/e2e/compiler/numeric.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,40 +8,48 @@ import { FuncRef } from "~/wasm/funcRef.ts";

const source = `
fn left(): f32 {
// return (-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 main(): i32 {
return 1;
// if ( 10.0 - ( 3.0 / 2.0 ) - 8.0 != 10.0 - 3.0 / 2.0 - 8.0 ) {
// return 20;
// };
// (-2.5 % 2.0) * -3.0 == 10.0 - ((1.0 / 2.0) % 10.0) - 8.0;
// 1.5 == 1.5
// true == 1
// doing this in a single expression to also ensure == is applied correctly
if ( (-2.5 % 2.0) * -3.0 ) != ( 10.0 - ( (1.0 / 2.0) % 10.0 ) - 8.0 ) {
return 25;
return 29;
};
if ( (-2.5 % 2.0) * -3.0 != 10.0 - ( (1.0 / 2.0) % 10.0 ) - 8.0 ) {
return 29;
return 33;
};
if ( (-2.5 % 2.0) * -3.0 != 10.0 - ( 1.0 / 2.0 % 10.0 ) - 8.0 ) {
return 33;
return 37;
};
if ( -2.5 % 2.0 * -3.0 != 10.0 - ( 1.0 / 2.0 % 10.0 ) - 8.0 ) {
return 37;
return 41;
};
if ( -2.5 % 2.0 * -3.0 != 10.0 - 1.0 / 2.0 % 10.0 - 8.0 ) {
return 41;
return 45;
};
return 36;
return 0;
}`;

Deno.test(`Numeric logic test`, async () => {
Expand Down

0 comments on commit 340968e

Please sign in to comment.