@@ -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,20 +83,21 @@ 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))
96- }
93+ def toJS (d : cps.ToplevelDefinition )(using ctx : TransformerContext ): js.Stmt = d match {
94+ case cps.ToplevelDefinition .Def (id, block) =>
95+ js.Const (nameDef(id), requiringThunk { toJS(id, block) })
96+ case cps.ToplevelDefinition .Val (id, ks, k, binding) =>
97+ js.Const (nameDef(id), Call (RUN_TOPLEVEL , js.Lambda (List (nameDef(ks), nameDef(k)), toJS(binding).stmts)))
98+ case cps.ToplevelDefinition .Let (id, binding) =>
99+ js.Const (nameDef(id), toJS(binding))
100+ }
97101
98102 def toJSParam (id : Id ): JSName = nameDef(id)
99103
@@ -200,6 +204,7 @@ object TransformerCps extends Transformer {
200204
201205 case cps.Stmt .LetDef (id, block, body) =>
202206 Binding { k =>
207+ given TransformerContext = D .copy(blockDefs = D .blockDefs + (id -> block))
203208 js.Const (nameDef(id), requiringThunk { toJS(id, block) }) :: toJS(body).run(k)
204209 }
205210
@@ -320,10 +325,20 @@ object TransformerCps extends Transformer {
320325 } else None
321326 }
322327
328+ // Compute which blocks need to be substituted (those that capture overlapping variables)
329+ val valueSubst = paramTmps.map { case (p, t) => p -> Expr .ValueVar (t) }
330+ val blockSubst : Map [Id , cps.Block ] = D .blockDefs.collect {
331+ case (blockId, blockDef) if Variables .free(blockDef).intersect(overlapping).nonEmpty =>
332+ val substitutedBlock = substitutions.substitute(blockDef)(using Substitution (values = valueSubst))
333+ val newId = Id (s " ${blockId}_subst " )
334+ stmts.append(js.Const (nameDef(newId), argumentToJS(substitutedBlock)))
335+ blockId -> cps.Block .BlockVar (newId)
336+ }
337+
323338 // Prepare the substitution
324339 val subst = Substitution (
325- values = paramTmps.map { case (p, t) => p -> Expr . ValueVar (t) } ,
326- blocks = Map .empty ,
340+ values = valueSubst ,
341+ blocks = blockSubst ,
327342 conts = tmp_k.map(t => k1 -> Cont .ContVar (t)).toMap,
328343 metaconts = tmp_ks.map(t => ks1 -> MetaCont (t)).toMap
329344 )
0 commit comments