Skip to content

Commit 210606b

Browse files
committed
keep track of nested function definitions
1 parent 8e350df commit 210606b

File tree

1 file changed

+25
-10
lines changed

1 file changed

+25
-10
lines changed

effekt/shared/src/main/scala/effekt/generator/js/TransformerCps.scala

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)