File size: 2,072 Bytes
f5deffb | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | import BCPL.Semantics
/-!
# BCPL.Compile
Lowering of BCPL to Universal Word IR. There is no BCPL runtime: variables are memory cells
at `addr x`, expressions leave their value on the data stack, and statements leave the data
stack as they found it.
-/
namespace WordDialect
namespace BCPL
open IR
def binCode {n : Nat} : BinOp β List (Instr n)
| .add => [.add]
| .sub => [.sub]
| .mul => [.mul]
| .div => [.sdiv]
| .and => [.and]
| .or => [.or]
| .neqv => [.xor]
| .shl => [.shl]
| .shr => [.shr]
| .eq => cmpFlagCode .eq
| .ne => cmpFlagCode .ne
| .lt => cmpFlagCode .slt
| .gt => cmpFlagCode .sgt
| .le => cmpFlagCode .sle
| .ge => cmpFlagCode .sge
/-- `neg`: compute `0 - v` as `v 0 SWAP SUB`. -/
def unCode {n : Nat} : UnOp β List (Instr n)
| .neg => [.word 0#n, .swap, .sub]
| .not => [.not]
def compileE {n : Nat} (addr : Var β Word n) : Expr β List (Instr n)
| .num z => [.word (BitVec.ofInt n z)]
| .var x => [.word (addr x), .load]
| .addrOf x => [.word (addr x)]
| .rv e => compileE addr e ++ [.load]
| .un o e => compileE addr e ++ unCode o
| .bin o a b => compileE addr a ++ compileE addr b ++ binCode o
/-- Right-hand side first, then (for an indirect target) the address, then `STORE`. -/
def assignCode {n : Nat} (addr : Var β Word n) : LVal β Expr β List (Instr n)
| .var x, e => compileE addr e ++ [.word (addr x), .store]
| .rv a, e => compileE addr e ++ compileE addr a ++ [.store]
def compile {n : Nat} (addr : Var β Word n) : Stmt β Frag n
| .skip => Frag.empty
| .assign l e => Frag.ofCode (assignCode addr l e)
| .seq a b => (compile addr a).seq (compile addr b)
| .test c t e => (Frag.ofCode (compileE addr c)).seq (Frag.ite (compile addr t) (compile addr e))
| .while c body => Frag.whileLoop (Frag.ofCode (compileE addr c)) (compile addr body)
/-- A complete program: the statement at address 0, followed by `HALT`. -/
def compileProgram {n : Nat} (addr : Var β Word n) (s : Stmt) : Prog n :=
(compile addr s).emit 0 ++ [.halt]
end BCPL
end WordDialect
|