import type { BinaryOp, UnaryOp } from "../ast" import type { Loc } from "./loc" export type Operand = Loc | number export type AbsInsnCopy = { type: "copy", dest: Loc, source: Operand, } type UnaryInsn = { type: "unary", dest: Loc, op: Op, source: Operand, } // NOTE: We convert binary -> unary when going SSA3 -> SSA2 export type AbsInsn2Unary = UnaryInsn // Abstract instruction in two-address form export type AbsInsn2 = AbsInsnCopy | AbsInsn2Unary type CopyFn = (dest: Loc, source: Operand) => A type UnaryFn = (dest: Loc, op: Op, source: Operand) => A type UnaryFn2 = UnaryFn export const insnReduce2 = (copy: CopyFn, unary: UnaryFn2, insn: AbsInsn2): A => insn.type === 'copy' ? copy(insn.dest, insn.source) : unary(insn.dest, insn.op, insn.source) export type AbsInsn3Unary = UnaryInsn export type AbsInsnBinary = { type: "binary", dest: Loc, source: Operand, op: BinaryOp, source1: Operand } // Abstract instruction in three-address form export type AbsInsn3 = AbsInsnCopy | AbsInsn3Unary | AbsInsnBinary export const CopyInsn = (dest: Loc, source: Operand): AbsInsnCopy => ({ type: 'copy', dest, source, }) export const UnaryInsn = (dest: Loc, op: Op, source: Operand): UnaryInsn => ({ type: 'unary', dest, op, source, }) export const BinaryInsn = (dest: Loc, source: Operand, op: BinaryOp, source1: Operand): AbsInsnBinary => ({ type: 'binary', dest, source, op, source1, })