@@ -34,6 +34,8 @@ object TransformerCps extends Transformer {
3434 recursive : Option [RecursiveDefInfo ],
3535 // the direct-style continuation, if available (used in case cps.Stmt.LetCont)
3636 directStyle : Option [ContinuationInfo ],
37+ // collected definitions for applying substitutions to when preparing a call
38+ blockDefs : Map [Id , cps.Block ],
3739 // the current direct-style metacontinuation
3840 metacont : Option [Id ],
3941 // the original declaration context (used to compile pattern matching)
@@ -62,6 +64,7 @@ object TransformerCps extends Transformer {
6264 externs.collect { case d : Extern .Def => (d.id, d) }.toMap,
6365 None ,
6466 None ,
67+ Map .empty,
6568 None ,
6669 D , C )
6770
@@ -80,19 +83,23 @@ object TransformerCps extends Transformer {
8083 input.externs.collect { case d : Extern .Def => (d.id, d) }.toMap,
8184 None ,
8285 None ,
86+ Map .empty,
8387 None ,
8488 D , C )
8589
8690 input.definitions.map(toJS)
8791
8892
89- def toJS (d : cps.ToplevelDefinition )(using TransformerContext ): js.Stmt = d match {
90- case cps.ToplevelDefinition .Def (id, block) =>
91- js.Const (nameDef(id), requiringThunk { toJS(id, block) })
92- case cps.ToplevelDefinition .Val (id, ks, k, binding) =>
93- js.Const (nameDef(id), Call (RUN_TOPLEVEL , js.Lambda (List (nameDef(ks), nameDef(k)), toJS(binding).stmts)))
94- case cps.ToplevelDefinition .Let (id, binding) =>
95- js.Const (nameDef(id), toJS(binding))
93+ def toJS (d : cps.ToplevelDefinition )(using ctx : TransformerContext ): js.Stmt = {
94+ given TransformerContext = ctx.copy(blockDefs = Map .empty)
95+ d match {
96+ case cps.ToplevelDefinition .Def (id, block) =>
97+ js.Const (nameDef(id), requiringThunk { toJS(id, block) })
98+ case cps.ToplevelDefinition .Val (id, ks, k, binding) =>
99+ js.Const (nameDef(id), Call (RUN_TOPLEVEL , js.Lambda (List (nameDef(ks), nameDef(k)), toJS(binding).stmts)))
100+ case cps.ToplevelDefinition .Let (id, binding) =>
101+ js.Const (nameDef(id), toJS(binding))
102+ }
96103 }
97104
98105 def toJSParam (id : Id ): JSName = nameDef(id)
@@ -200,6 +207,7 @@ object TransformerCps extends Transformer {
200207
201208 case cps.Stmt .LetDef (id, block, body) =>
202209 Binding { k =>
210+ given TransformerContext = D .copy(blockDefs = D .blockDefs + (id -> block))
203211 js.Const (nameDef(id), requiringThunk { toJS(id, block) }) :: toJS(body).run(k)
204212 }
205213
@@ -320,10 +328,20 @@ object TransformerCps extends Transformer {
320328 } else None
321329 }
322330
331+ // Compute which blocks need to be substituted (those that capture overlapping variables)
332+ val valueSubst = paramTmps.map { case (p, t) => p -> Expr .ValueVar (t) }
333+ val blockSubst : Map [Id , cps.Block ] = D .blockDefs.collect {
334+ case (blockId, blockDef) if Variables .free(blockDef).intersect(overlapping).nonEmpty =>
335+ val substitutedBlock = substitutions.substitute(blockDef)(using Substitution (values = valueSubst))
336+ val newId = Id (s " ${blockId}_subst " )
337+ stmts.append(js.Const (nameDef(newId), argumentToJS(substitutedBlock)))
338+ blockId -> cps.Block .BlockVar (newId)
339+ }
340+
323341 // Prepare the substitution
324342 val subst = Substitution (
325- values = paramTmps.map { case (p, t) => p -> Expr . ValueVar (t) } ,
326- blocks = Map .empty ,
343+ values = valueSubst ,
344+ blocks = blockSubst ,
327345 conts = tmp_k.map(t => k1 -> Cont .ContVar (t)).toMap,
328346 metaconts = tmp_ks.map(t => ks1 -> MetaCont (t)).toMap
329347 )
0 commit comments