@@ -305,7 +305,7 @@ object semantics {
305305 case Resume (k : Id , body : BasicBlock )
306306
307307 case Var (id : BlockParam , init : Addr , body : BasicBlock )
308- // case Put
308+ case Put ( ref : Id , tpe : ValueType , cap : Captures , value : Addr , body : BasicBlock )
309309
310310 // aborts at runtime
311311 case Hole (span : Span )
@@ -322,6 +322,7 @@ object semantics {
322322 case NeutralStmt .Resume (k, body) => Set (k) ++ body.free
323323 case NeutralStmt .Var (id, init, body) => Set (init) ++ body.free - id.id
324324 case NeutralStmt .Hole (span) => Set .empty
325+ case NeutralStmt .Put (ref, tpe, cap, value, body) => Set (ref, value) ++ body.free
325326 }
326327 }
327328
@@ -396,13 +397,14 @@ object semantics {
396397 case Stack .Var (id1, curr, init, frame, next) if ref == id1.id => Some (curr)
397398 case Stack .Var (id1, curr, init, frame, next) => get(ref, next)
398399 }
399-
400- def put (id : Id , value : Addr , ks : Stack ): Stack = ks match {
400+
401+ def put (id : Id , value : Addr , ks : Stack ): Option [ Stack ] = ks match {
401402 case Stack .Empty => sys error s " Should not happen: trying to put ${util.show(id)} in empty stack "
402- case Stack .Unknown => sys error s " Cannot put ${util.show(id)} in unknown stack "
403- case Stack .Reset (prompt, frame, next) => Stack .Reset (prompt, frame, put(id, value, next))
404- case Stack .Var (id1, curr, init, frame, next) if id == id1.id => Stack .Var (id1, value, init, frame, next)
405- case Stack .Var (id1, curr, init, frame, next) => Stack .Var (id1, curr, init, frame, put(id, value, next))
403+ // We have reached the end of the known stack, so the variable must be in the unknown part.
404+ case Stack .Unknown => None
405+ case Stack .Reset (prompt, frame, next) => put(id, value, next).map(Stack .Reset (prompt, frame, _))
406+ case Stack .Var (id1, curr, init, frame, next) if id == id1.id => Some (Stack .Var (id1, value, init, frame, next))
407+ case Stack .Var (id1, curr, init, frame, next) => put(id, value, next).map(Stack .Var (id1, curr, init, frame, _))
406408 }
407409
408410 enum Cont {
@@ -544,6 +546,9 @@ object semantics {
544546 " var" <+> toDoc(id) <+> " =" <+> toDoc(init) <> line <> toDoc(body)
545547
546548 case NeutralStmt .Hole (span) => " hole()"
549+
550+ case NeutralStmt .Put (ref, tpe, cap, value, body) =>
551+ " put" <+> toDoc(ref) <+> " =" <+> toDoc(value) <> line <> toDoc(body)
547552 }
548553
549554 def toDoc (id : Id ): Doc = id.show
@@ -598,7 +603,7 @@ object semantics {
598603 (if (targs.isEmpty) emptyDoc else brackets(hsep(targs.map(toDoc), comma))) <>
599604 parens(hsep(vargs.map(toDoc), comma)) <> hcat(bargs.map(b => braces { toDoc(b) })) <> line
600605 case (addr, Binding .Unbox (innerAddr, tpe, capt)) => " def" <+> toDoc(addr) <+> " =" <+> " unbox" <+> toDoc(innerAddr) <> line
601- case (addr, Binding .Get (ref, tpe, cap)) => " let " <+> toDoc(addr) <+> " =" <+> " !" <> toDoc(ref) <> line
606+ case (addr, Binding .Get (ref, tpe, cap)) => " get " <+> toDoc(addr) <+> " =" <+> " !" <> toDoc(ref) <> line
602607 })
603608
604609 def toDoc (block : BasicBlock ): Doc =
@@ -872,7 +877,11 @@ class NewNormalizer(shouldInline: (Id, BlockLit) => Boolean) {
872877 case None => bind(id, scope.allocateGet(ref, annotatedTpe, annotatedCapt)) { evaluate(body, k, ks) }
873878 }
874879 case Stmt .Put (ref, annotatedCapt, value, body) =>
875- evaluate(body, k, put(ref, evaluate(value), ks))
880+ put(ref, evaluate(value), ks) match {
881+ case Some (stack) => evaluate(body, k, stack)
882+ case None =>
883+ NeutralStmt .Put (ref, value.tpe, annotatedCapt, evaluate(value), nested { evaluate(body, k, ks) })
884+ }
876885
877886 // Control Effects
878887 case Stmt .Shift (prompt, core.Block .BlockLit (Nil , cparam :: Nil , Nil , k2 :: Nil , body)) =>
@@ -1017,6 +1026,8 @@ class NewNormalizer(shouldInline: (Id, BlockLit) => Boolean) {
10171026 Stmt .Var (blockParam.id, embedExpr(init), capt, embedStmt(body)(using G .bind(blockParam.id, blockParam.tpe, blockParam.capt)))
10181027 case NeutralStmt .Hole (span) =>
10191028 Stmt .Hole (span)
1029+ case NeutralStmt .Put (ref, annotatedTpe, annotatedCapt, value, body) =>
1030+ Stmt .Put (ref, annotatedCapt, embedExpr(value), embedStmt(body))
10201031 }
10211032
10221033 def embedStmt (basicBlock : BasicBlock )(using G : TypingContext ): core.Stmt = basicBlock match {
0 commit comments