diff --git a/example.gby b/example.gby index 73067e6..8d0e5a6 100644 --- a/example.gby +++ b/example.gby @@ -1,5 +1,4 @@ u8 x; u8 y; -x <- 1; -y <- -x; +x <- y + 2; diff --git a/lib/asm.ts b/lib/asm.ts index 998afbc..5553ebc 100644 --- a/lib/asm.ts +++ b/lib/asm.ts @@ -106,6 +106,55 @@ const convertASM_SSA = (state: ASMState, ssa: SSA): void => { export const convertASM_SSA_Binary = (state: ASMState, ssa: SSABinary): void => { const dest = state.alloc_sym_loc(ssa.dest) + + if (typeof ssa.source === "number") { + state.insns.push(`LD A, ${ssa.source}`) + } else { + const loc = state.get_sym_loc(ssa.source) + + if (loc === null) { + state.insns.push(`LD A, (${ssa.source})`) + } else if (typeof loc === "string") { + state.insns.push(`LD A, ${loc}`) + } else { + state.insns.push( + `LD HL, SP + (${loc})`, + `LD A, (HL)` + ) + } + } + + switch (ssa.op) { + case "add": + if (typeof ssa.source1 === "number") { + state.insns.push(`ADD ${ssa.source1}`) + } else { + const loc = state.get_sym_loc(ssa.source1) + if (loc === null) { + throw new Error('fuck') + } else if (typeof loc === "string") { + state.insns.push(`ADD ${loc}`) + } else { + throw new Error('fuck') + state.insns.push( + `LD HL, SP + (${loc})` + ) + } + } + break + + default: + throw new Error(`unsupported binary op \`${ssa.op}'`) + } + + if (typeof dest === "string") { + state.insns.push(`LD ${dest}, A`) + } else { + state.insns.push( + `LD HL, SP + (${dest})`, + `LD (HL), A` + ) + } } export const convertASM_SSA_Unary = (state: ASMState, ssa: SSAUnary): void => { diff --git a/lib/ast.d.ts b/lib/ast.d.ts index 98887ab..b4a5ce3 100644 --- a/lib/ast.d.ts +++ b/lib/ast.d.ts @@ -30,7 +30,14 @@ type AStmt = { } // Expressions -export type Expr = UnaryExpr | BasicExpr +export type Expr = BinaryExpr | UnaryExpr | BasicExpr + +type BinaryExpr = { + type: "binary", + op: string, + left: Expr, + right: Expr, +} type UnaryExpr = { type: "unary", diff --git a/lib/ir.ts b/lib/ir.ts index e1ffdab..4a07c32 100644 --- a/lib/ir.ts +++ b/lib/ir.ts @@ -46,18 +46,32 @@ export const convertAssignStmt = (state: IRState, stmt: AssignStmt): Array export const convertExpr = (state: IRState, expr: Expr): [string | number, Array] => { if (typeof expr === "number" || typeof expr === "string") { return [expr, []] - } + } else if (expr.type === "unary") { + const [source, expr_stmts] = convertExpr(state, expr.arg) - const [source, expr_stmts] = convertExpr(state, expr.arg) + const name = `temp${state.nextID++}` + expr_stmts.push({ + dest: name, + source, + op: expr.op, + }) - const name = `temp${state.nextID++}` - expr_stmts.push({ - dest: name, - source, - op: expr.op, - }) - - return [name, expr_stmts] + return [name, expr_stmts] + } else { + const [left_source, left_stmts] = convertExpr(state, expr.left) + const [right_source, right_stmts] = convertExpr(state, expr.right) + const expr_stmts = [...left_stmts, ...right_stmts] + + const name = `temp${state.nextID++}` + expr_stmts.push({ + dest: name, + op: expr.op, + source: left_source, + source1: right_source, + }) + + return [name, expr_stmts] + } } export const prettyPrintIR = (ssa: SSA): string => { diff --git a/lib/parser.pegjs b/lib/parser.pegjs index 1d8a373..b0474e5 100644 --- a/lib/parser.pegjs +++ b/lib/parser.pegjs @@ -4,7 +4,12 @@ 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 }) + const bexpr = (op, left, right) => ({ type: "binary", op, left, right }) + + const assocl = (head, tail) => tail.reduce((left, arg) => { + const [op, right] = arg + return bexpr(op, left, right) + }, head) } Program = WS @(Decl / Stmt)* WS @@ -18,7 +23,10 @@ Stmt = @AssignStmt SEMI AssignStmt = name:Ident ASSIGN expr:Expr { return stmt("assign", { name, expr }) } // Expressions -Expr = UnaryExpr +Expr = AddExpr + +AddExpr = head:UnaryExpr tail:(op:AddOp e:UnaryExpr)* { return assocl(head, tail || []) } +AddOp = PLUS { return "add" } UnaryExpr = op:UnaryOp? e:BaseExpr { return op ? uexpr(op, e) : e } UnaryOp = TILDE { return "bit_negate" } @@ -51,6 +59,7 @@ U8 = @'u8' WS U16 = @'u16' WS // Terminal symbols +PLUS = '+' WS TILDE = '~' WS MINUS = '-' WS SEMI = ';' WS