+
+ | trans_stms env ls (A.If(e, s, NONE)::stms) =
+ let val l = Label.new ()
+ val (strans, env') = trans_stms env ls s
+ val (remainder, env') = trans_stms env' ls stms
+ in
+ (T.JUMPIFN(trans_exp env e, l)
+ :: strans
+ @ [T.LABEL (l)]
+ @ remainder, env')
+ end
+ | trans_stms env ls (A.If(e, s, SOME s2)::stms) =
+ let val l = Label.new ()
+ val l2 = Label.new ()
+ val (s1trans, env') = trans_stms env ls s
+ val (s2trans, env') = trans_stms env' ls s2
+ val (remainder, env') = trans_stms env' ls stms
+ in
+ (T.JUMPIFN(trans_exp env e, l)
+ :: s1trans
+ @ [T.JUMP (l2), T.LABEL (l)]
+ @ s2trans
+ @ [T.LABEL (l2)]
+ @ remainder, env')
+ end
+ | trans_stms env ls (A.For(s1, e, s2, s)::stms) =
+ let
+ val head = Label.new ()
+ val tail = Label.new ()
+ val loop = Label.new ()
+ val (stm1, env') = if isSome s1 then trans_stms env NONE [valOf s1] else (nil, env)
+ val (strans, env') = trans_stms env' (SOME(loop,tail)) s
+ val (stm2, env') = if isSome s2 then trans_stms env' NONE [valOf s2] else (nil, env')
+ val (remainder, env') = trans_stms env' ls stms
+ in
+ (stm1
+ @ [T.LABEL head, T.JUMPIFN(trans_exp env' e, tail)]
+ @ strans
+ @ [T.LABEL loop]
+ @ stm2
+ @ [T.JUMP head, T.LABEL tail]
+ @ remainder, env')
+ end
+ | trans_stms env ls (A.While(e, s)::stms) =
+ let
+ val head = Label.new ()
+ val tail = Label.new ()
+ val (strans, env') = trans_stms env (SOME(head,tail)) s
+ val (remainder, env') = trans_stms env' ls stms
+ in
+ (T.LABEL head
+ :: T.JUMPIFN(trans_exp env e, tail)
+ :: strans
+ @ [T.JUMP head, T.LABEL tail]
+ @ remainder, env')
+ end
+
+ | trans_stms env (SOME(b,e)) (A.Break::stms) =
+ let
+ val (remainder, env') = trans_stms env (SOME(b,e)) stms
+ in
+ ((T.JUMP e) :: remainder, env')
+ end
+ | trans_stms env NONE (A.Break::_) = raise ErrorMsg.InternalError "Break from invalid location... should have been caught in typechecker"
+ | trans_stms env (SOME(b,e)) (A.Continue::stms) =
+ let
+ val (remainder, env') = trans_stms env (SOME(b,e)) stms
+ in
+ ((T.JUMP b) :: remainder, env')
+ end
+ | trans_stms env NONE (A.Continue::_) = raise ErrorMsg.InternalError "Continue from invalid location... should have been caught in typechecker"
+
+ | trans_stms env ls (A.Nop::stms) = trans_stms env ls stms
+ | trans_stms env ls (A.MarkedStm m :: stms) = trans_stms env ls ((Mark.data m) :: stms)
+ | trans_stms env _ nil = (nil, env)