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.

101 lines
2.2 KiB

  1. import type { BinaryOp, UnaryOp } from "../ast"
  2. import type { Loc } from "./loc"
  3. export type Operand = Loc | number
  4. export type AbsInsnCopy = {
  5. type: "copy",
  6. dest: Loc,
  7. source: Operand,
  8. }
  9. export type AbsInsnGoto = {
  10. type: "goto",
  11. dest: string,
  12. }
  13. export type AbsInsnLabel = {
  14. type: "label",
  15. dest: string,
  16. }
  17. type UnaryInsn<Op> = {
  18. type: "unary",
  19. dest: Loc,
  20. op: Op,
  21. source: Operand,
  22. }
  23. // NOTE: We convert binary -> unary when going SSA3 -> SSA2
  24. export type AbsInsn2Unary = UnaryInsn<UnaryOp | BinaryOp>
  25. // Abstract instruction in two-address form
  26. export type AbsInsn2 = AbsInsnCopy | AbsInsnLabel | AbsInsnGoto | AbsInsn2Unary
  27. type CopyFn<A> = (dest: Loc, source: Operand) => A
  28. type StringFn<A> = (name: string) => A
  29. type UnaryFn<Op, A> = (dest: Loc, op: Op, source: Operand) => A
  30. type UnaryFn2<A> = UnaryFn<UnaryOp | BinaryOp, A>
  31. export const insnReduce2 = <A>(
  32. copy: CopyFn<A>,
  33. label: StringFn<A>,
  34. goto: StringFn<A>,
  35. unary: UnaryFn2<A>,
  36. insn: AbsInsn2
  37. ): A => {
  38. switch (insn.type) {
  39. case 'copy':
  40. return copy(insn.dest, insn.source)
  41. case 'label':
  42. return label(insn.dest)
  43. case 'goto':
  44. return goto(insn.dest)
  45. case 'unary':
  46. return unary(insn.dest, insn.op, insn.source)
  47. }
  48. }
  49. export type AbsInsn3Unary = UnaryInsn<UnaryOp>
  50. export type AbsInsnBinary = {
  51. type: "binary",
  52. dest: Loc,
  53. source: Operand,
  54. op: BinaryOp,
  55. source1: Operand
  56. }
  57. // Abstract instruction in three-address form
  58. export type AbsInsn3 = AbsInsnCopy | AbsInsnLabel | AbsInsnGoto | AbsInsn3Unary | AbsInsnBinary
  59. export const CopyInsn = (dest: Loc, source: Operand): AbsInsnCopy => ({
  60. type: 'copy',
  61. dest,
  62. source,
  63. })
  64. export const UnaryInsn = <Op>(dest: Loc, op: Op, source: Operand): UnaryInsn<Op> => ({
  65. type: 'unary',
  66. dest,
  67. op,
  68. source,
  69. })
  70. export const BinaryInsn = (dest: Loc, source: Operand, op: BinaryOp, source1: Operand): AbsInsnBinary => ({
  71. type: 'binary',
  72. dest,
  73. source,
  74. op,
  75. source1,
  76. })
  77. export const LabelInsn = (dest: string): AbsInsnLabel => ({
  78. type: 'label',
  79. dest,
  80. })
  81. export const GotoInsn = (dest: string): AbsInsnGoto => ({
  82. type: 'goto',
  83. dest,
  84. })