-- -- A compiler for Minila programs -- -- -- - Function compile takes a Minila program and converts it into -- a command sequence. -- - Function generator actually does this. -- - genForExp does this for expression. -- mod! COMPILER { pr(STM) pr(CLIST) op compile : Stm -> CList op generator : Stm CList -> CList op genForExp : Exp -> CList vars E E1 E2 : Exp vars S S1 S2 : Stm var V : Var var N : Nat var CL : CList -- compile eq compile(S) = generator(S,clnil) @ (quit | clnil) . -- generator eq generator(estm,CL) = CL . eq generator(V := E ; S,CL) = generator(S, CL @ genForExp(E) @ (store(V) | clnil) ) . eq generator(if E then S1 else S2 fi S,CL) = generator(S, CL @ genForExp(E) @ (jumpOnCond(2) | jump(len(generator(S1,clnil)) + 2) | clnil) @ generator(S1,clnil) @ (jump(len(generator(S2,clnil)) + 1) | clnil) @ generator(S2,clnil) ) . eq generator(while E do S1 od S,CL) = generator(S, CL @ genForExp(E) @ (jumpOnCond(2) | jump(len(generator(S1,clnil)) + 2) | clnil) @ generator(S1,clnil) @ (bjump(len(genForExp(E)) + len(generator(S1,clnil)) + 2) | clnil)) . eq generator(for V E1 E2 do S1 od S,CL) = generator(S, CL @ genForExp(E1) @ (store(V) | load(V) | clnil) @ genForExp(E2) @ (greaterThan | jumpOnCond(len(generator(S1,clnil)) + 6) | clnil) @ generator(S1,clnil) @ (load(V) | push(1) | add | store(V) | bjump(len(genForExp(E2)) + len(generator(S1,clnil)) + 7) | clnil) ) . -- genForExp eq genForExp(N) = push(N) | clnil . eq genForExp(V) = load(V) | clnil . eq genForExp(E1 ** E2) = genForExp(E1) @ genForExp(E2) @ (multiply | clnil) . eq genForExp(E1 // E2) = genForExp(E1) @ genForExp(E2) @ (divide | clnil) . eq genForExp(E1 %% E2) = genForExp(E1) @ genForExp(E2) @ (mod | clnil) . eq genForExp(E1 ++ E2) = genForExp(E1) @ genForExp(E2) @ (add | clnil) . eq genForExp(E1 -- E2) = genForExp(E1) @ genForExp(E2) @ (minus | clnil) . eq genForExp(E1 << E2) = genForExp(E1) @ genForExp(E2) @ (lessThan | clnil) . eq genForExp(E1 >> E2) = genForExp(E1) @ genForExp(E2) @ (greaterThan | clnil) . eq genForExp(E1 === E2) = genForExp(E1) @ genForExp(E2) @ (equal | clnil) . eq genForExp(E1 !== E2) = genForExp(E1) @ genForExp(E2) @ (notEqual | clnil) . eq genForExp(E1 && E2) = genForExp(E1) @ genForExp(E2) @ (and | clnil) . eq genForExp(E1 || E2) = genForExp(E1) @ genForExp(E2) @ (or | clnil) . } eof open COMPILER + VM op p1 : -> Stm . eq p1 = v(0) := 1 ; v(1) := 1 ; while v(1) << 10 || v(1) === 10 do v(0) := v(0) ** v(1) ; v(1) := v(1) ++ 1 ; od . op p2 : -> Stm . eq p2 = v(0) := 1 ; for v(1) 1 10 do v(0) := v(1) ** v(0) ; od . op p3 : -> Stm . eq p3 = v(0) := 24 ; v(1) := 30 ; while v(1) !== 0 do v(2) := v(0) %% v(1) ; v(0) := v(1) ; v(1) := v(2) ; od . op p4 : -> Stm . eq p4 = v(0) := 200000000 ; v(1) := 0 ; v(2) := v(0) ; while v(1) !== v(2) do if ((v(2) -- v(1)) %% 2) === 0 then v(3) := v(1) ++ (v(2) -- v(1)) // 2 ; else v(3) := v(1) ++ ((v(2) -- v(1)) // 2) ++ 1 ; fi if v(3) ** v(3) >> v(0) then v(2) := v(3) -- 1 ; else v(1) := v(3) ; fi od . red vm(compile(p1)) . red vm(compile(p2)) . red vm(compile(p3)) . red vm(compile(p4)) . close