Browse Source

Begin adding support for binary operators

master
Forest Belton 3 years ago
parent
commit
85e184b2eb
5 changed files with 93 additions and 15 deletions
  1. +1
    -2
      example.gby
  2. +49
    -0
      lib/asm.ts
  3. +8
    -1
      lib/ast.d.ts
  4. +24
    -10
      lib/ir.ts
  5. +11
    -2
      lib/parser.pegjs

+ 1
- 2
example.gby View File

@ -1,5 +1,4 @@
u8 x; u8 x;
u8 y; u8 y;
x <- 1;
y <- -x;
x <- y + 2;

+ 49
- 0
lib/asm.ts View File

@ -106,6 +106,55 @@ const convertASM_SSA = (state: ASMState, ssa: SSA): void => {
export const convertASM_SSA_Binary = (state: ASMState, ssa: SSABinary): void => { export const convertASM_SSA_Binary = (state: ASMState, ssa: SSABinary): void => {
const dest = state.alloc_sym_loc(ssa.dest) 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 => { export const convertASM_SSA_Unary = (state: ASMState, ssa: SSAUnary): void => {

+ 8
- 1
lib/ast.d.ts View File

@ -30,7 +30,14 @@ type AStmt = {
} }
// Expressions // 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 UnaryExpr = {
type: "unary", type: "unary",

+ 24
- 10
lib/ir.ts View File

@ -46,18 +46,32 @@ export const convertAssignStmt = (state: IRState, stmt: AssignStmt): Array
export const convertExpr = (state: IRState, expr: Expr): [string | number, Array<SSA>] => { export const convertExpr = (state: IRState, expr: Expr): [string | number, Array<SSA>] => {
if (typeof expr === "number" || typeof expr === "string") { if (typeof expr === "number" || typeof expr === "string") {
return [expr, []] 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 => { export const prettyPrintIR = (ssa: SSA): string => {

+ 11
- 2
lib/parser.pegjs View File

@ -4,7 +4,12 @@
const stmt = (stmt_type, args) => ({ type: "stmt", stmt_type, 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 decl = (decl_type, name, attrs, args) => ({ type: "decl", decl_type, name, attrs: attrs || [], args })
const uexpr = (op, arg) => ({ type: "unary", op, arg }) 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 Program = WS @(Decl / Stmt)* WS
@ -18,7 +23,10 @@ Stmt = @AssignStmt SEMI
AssignStmt = name:Ident ASSIGN expr:Expr { return stmt("assign", { name, expr }) } AssignStmt = name:Ident ASSIGN expr:Expr { return stmt("assign", { name, expr }) }
// Expressions // 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 } UnaryExpr = op:UnaryOp? e:BaseExpr { return op ? uexpr(op, e) : e }
UnaryOp = TILDE { return "bit_negate" } UnaryOp = TILDE { return "bit_negate" }
@ -51,6 +59,7 @@ U8 = @'u8' WS
U16 = @'u16' WS U16 = @'u16' WS
// Terminal symbols // Terminal symbols
PLUS = '+' WS
TILDE = '~' WS TILDE = '~' WS
MINUS = '-' WS MINUS = '-' WS
SEMI = ';' WS SEMI = ';' WS

Loading…
Cancel
Save