diff --git a/example.gby b/example.gby index a040d15..73067e6 100644 --- a/example.gby +++ b/example.gby @@ -1,3 +1,5 @@ u8 x; +u8 y; x <- 1; +y <- -x; diff --git a/lib/asm.ts b/lib/asm.ts index 5ba4fe7..998afbc 100644 --- a/lib/asm.ts +++ b/lib/asm.ts @@ -129,14 +129,14 @@ export const convertASM_SSA_Unary = (state: ASMState, ssa: SSAUnary): void => { } switch (ssa.op) { - case '-': + case 'arith_negate': state.insns.push( `CPL`, `INC A`, ) break - case '~': + case 'bit_negate': state.insns.push( `CPL` ) diff --git a/lib/ast.d.ts b/lib/ast.d.ts index e8e6030..98887ab 100644 --- a/lib/ast.d.ts +++ b/lib/ast.d.ts @@ -30,7 +30,15 @@ type AStmt = { } // Expressions -export type Expr = number +export type Expr = UnaryExpr | BasicExpr + +type UnaryExpr = { + type: "unary", + op: string, + arg: Expr, +} + +type BasicExpr = number | string // Attributes export type Attr = { diff --git a/lib/ir.ts b/lib/ir.ts index 4aa7f82..e1ffdab 100644 --- a/lib/ir.ts +++ b/lib/ir.ts @@ -1,6 +1,5 @@ import type { AssignStmt, Expr, Stmt } from "./ast" -// dest <- op(x, y) type Operand = string | number type ASSA = { dest: string, source: Operand } & Data @@ -44,9 +43,21 @@ export const convertAssignStmt = (state: IRState, stmt: AssignStmt): Array return expr_stmts } -export const convertExpr = (state: IRState, expr: Expr): [string, Array] => { +export const convertExpr = (state: IRState, expr: Expr): [string | number, Array] => { + if (typeof expr === "number" || typeof expr === "string") { + return [expr, []] + } + + const [source, expr_stmts] = convertExpr(state, expr.arg) + const name = `temp${state.nextID++}` - return [name, [{ dest: name, source: expr }]] + expr_stmts.push({ + dest: name, + source, + op: expr.op, + }) + + return [name, expr_stmts] } export const prettyPrintIR = (ssa: SSA): string => { diff --git a/lib/parser.pegjs b/lib/parser.pegjs index b929f71..1d8a373 100644 --- a/lib/parser.pegjs +++ b/lib/parser.pegjs @@ -3,6 +3,8 @@ const attr = (name, args) => ({ name, args }) const stmt = (stmt_type, args) => ({ type: "stmt", stmt_type, args }) const decl = (decl_type, name, attrs, args) => ({ type: "decl", decl_type, name, attrs: attrs || [], args }) + const uexpr = (op, arg) => ({ type: "unary", op, arg }) + const bexpr = (op, arg1, arg2) => ({ type: "binary", op, arg1, arg2 }) } Program = WS @(Decl / Stmt)* WS @@ -16,8 +18,13 @@ Stmt = @AssignStmt SEMI AssignStmt = name:Ident ASSIGN expr:Expr { return stmt("assign", { name, expr }) } // Expressions -Expr = BaseExpr -BaseExpr = Number +Expr = UnaryExpr + +UnaryExpr = op:UnaryOp? e:BaseExpr { return op ? uexpr(op, e) : e } +UnaryOp = TILDE { return "bit_negate" } + / MINUS { return "arith_negate" } + +BaseExpr = Ident / Number / LPAREN @Expr RPAREN // Attributes Attrs = LATTR @AttrList RATTR @@ -44,6 +51,8 @@ U8 = @'u8' WS U16 = @'u16' WS // Terminal symbols +TILDE = '~' WS +MINUS = '-' WS SEMI = ';' WS ASSIGN = '<-' WS LPAREN = '(' WS