+ (* anything else should be impossible *)
+
+ (* trans_stms : Temp.temp Symbol.table -> (Label.label * Label.label) option -> A.stm list -> Tree.stm list
+ * translates a statement to the corresponding IR
+ * we pass around the environment and the current loop context, if any
+ * (usually called ls, which contains a continue label and a break label)
+ *)
+ fun trans_stms vars vartypes ls (A.Assign(e1,e2)::stms) = T.MOVE(trans_exp vars vartypes e1, trans_exp vars vartypes e2, AU.Type.size (typeof' vartypes e2))::(trans_stms vars vartypes ls stms)
+ | trans_stms vars vartypes ls (A.AsnOp(oop,e1,e2)::stms) =
+ let
+ val te1 = trans_exp vars vartypes e1
+ val te2 = trans_exp vars vartypes e2
+ val t1 = T.TEMP (Temp.new "memory deref cache" 8)
+ val size = AU.Type.size (typeof' vartypes e2)
+ in
+ case te1
+ of T.MEMORY(m) => T.MOVE(t1, m, 8) :: T.MOVE (T.MEMORY(t1), T.BINOP(trans_oper oop, T.MEMORY(t1), te2), size) :: (trans_stms vars vartypes ls stms)
+ | _ => T.MOVE(te1, T.BINOP(trans_oper oop, te1, te2), size) :: (trans_stms vars vartypes ls stms)
+ end
+ | trans_stms vars vartypes ls (A.Return e::stms) =
+ let
+ val remainder = trans_stms vars vartypes ls stms
+ in
+ T.RETURN (trans_exp vars vartypes e, AU.Type.size (typeof' vartypes e))
+ :: remainder
+ end
+ | trans_stms vars vartypes ls (A.If(e, s, NONE)::stms) =
+ let
+ val l = Label.new ()
+ val strans = trans_stms vars vartypes ls s
+ val remainder = trans_stms vars vartypes ls stms
+ in
+ (T.JUMPIFN(trans_exp vars vartypes e, l)
+ :: strans
+ @ [T.LABEL (l)]
+ @ remainder)
+ end
+ | trans_stms vars vartypes ls (A.If(e, s, SOME s2)::stms) =
+ let
+ val l = Label.new ()
+ val l2 = Label.new ()
+ val s1trans = trans_stms vars vartypes ls s
+ val s2trans = trans_stms vars vartypes ls s2
+ val remainder = trans_stms vars vartypes ls stms
+ in
+ (T.JUMPIFN(trans_exp vars vartypes e, l)
+ :: s1trans
+ @ [T.JUMP (l2), T.LABEL (l)]
+ @ s2trans
+ @ [T.LABEL (l2)]
+ @ remainder)
+ end
+ | trans_stms vars vartypes ls (A.For(s1, e, s2, s)::stms) =
+ let
+ val head = Label.new ()
+ val tail = Label.new ()
+ val loop = Label.new ()
+ val stm1 = if isSome s1 then trans_stms vars vartypes NONE [valOf s1] else nil
+ val strans = trans_stms vars vartypes (SOME(loop,tail)) s
+ val stm2 = if isSome s2 then trans_stms vars vartypes NONE [valOf s2] else nil
+ val remainder = trans_stms vars vartypes ls stms
+ in
+ (stm1
+ @ [T.LABEL head, T.JUMPIFN(trans_exp vars vartypes e, tail)]
+ @ strans
+ @ [T.LABEL loop]
+ @ stm2
+ @ [T.JUMP head, T.LABEL tail]
+ @ remainder)
+ end
+ | trans_stms vars vartypes ls (A.While(e, s)::stms) =
+ let
+ val head = Label.new ()
+ val tail = Label.new ()
+ val strans = trans_stms vars vartypes (SOME(head,tail)) s
+ val remainder = trans_stms vars vartypes ls stms
+ in
+ (T.LABEL head
+ :: T.JUMPIFN(trans_exp vars vartypes e, tail)
+ :: strans
+ @ [T.JUMP head, T.LABEL tail]
+ @ remainder)
+ end
+ | trans_stms vars vartypes ls (A.Effect(e)::stms) = (T.EFFECT (trans_exp vars vartypes e, AU.Type.size (typeof' vartypes e))) :: (trans_stms vars vartypes ls stms)
+ | trans_stms vars vartypes (SOME(b,e)) (A.Break::stms) =
+ let
+ val remainder = trans_stms vars vartypes (SOME(b,e)) stms
+ in
+ ((T.JUMP e) :: remainder)
+ end
+ | trans_stms vars vartypes NONE (A.Break::_) = raise ErrorMsg.InternalError "Break from invalid location... should have been caught in typechecker"
+ | trans_stms vars vartypes (SOME(b,e)) (A.Continue::stms) =
+ let
+ val remainder = trans_stms vars vartypes (SOME(b,e)) stms
+ in
+ ((T.JUMP b) :: remainder)
+ end
+ | trans_stms vars vartypes NONE (A.Continue::_) = raise ErrorMsg.InternalError "Continue from invalid location... should have been caught in typechecker"
+ | trans_stms vars vartypes ls (A.Nop::stms) = trans_stms vars vartypes ls stms
+ | trans_stms vars vartypes ls (A.MarkedStm m :: stms) = trans_stms vars vartypes ls ((Mark.data m) :: stms)
+ | trans_stms vars vartypes _ nil = nil