A "high-level" language for the Gameboy
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

64 lines
1.6 KiB

  1. import type { AssignStmt, Expr, Stmt } from "./ast"
  2. // dest <- op(x, y)
  3. type Operand = string | number
  4. type ASSA<Data> = { dest: string, source: Operand } & Data
  5. export type SSACopy = ASSA<{ source: Operand }> // dest = source
  6. export type SSAUnary = ASSA<{ op: string }> // dest = op(source)
  7. export type SSABinary = ASSA<{ op: string, source1: Operand }> // dest = op(source, source1)
  8. export type SSA = SSACopy | SSAUnary | SSABinary
  9. type IRState = {
  10. nextID: number
  11. ssa_stmts: Array<SSA>
  12. }
  13. export const convertIR = (stmts: Array<Stmt>): Array<SSA> => {
  14. const state: IRState = {
  15. nextID: 0,
  16. ssa_stmts: [],
  17. }
  18. stmts.forEach(stmt => {
  19. const ssa_stmts = convertAssignStmt(state, stmt)
  20. state.ssa_stmts.push(...ssa_stmts)
  21. })
  22. return state.ssa_stmts
  23. }
  24. export const convertAssignStmt = (state: IRState, stmt: AssignStmt): Array<SSA> => {
  25. const dest = stmt.args.name
  26. const [source, expr_stmts] = convertExpr(state, stmt.args.expr)
  27. expr_stmts.push({
  28. dest,
  29. source,
  30. })
  31. return expr_stmts
  32. }
  33. export const convertExpr = (state: IRState, expr: Expr): [string, Array<SSA>] => {
  34. const name = `temp${state.nextID++}`
  35. return [name, [{ dest: name, source: expr }]]
  36. }
  37. export const prettyPrintIR = (ssa: SSA): string => {
  38. let output = ""
  39. if ("source1" in ssa) {
  40. output = `${ssa.dest} = ${ssa.source} ${ssa.op} ${ssa.source1}`
  41. } else if ("op" in ssa) {
  42. output = `${ssa.dest} = ${ssa.op} ${ssa.source}`
  43. } else {
  44. output = `${ssa.dest} = ${ssa.source}`
  45. }
  46. return output
  47. }