@@ -235,9 +235,17 @@ object Normalizer { normal =>
235
235
236
236
case Stmt .Val (id, tpe, binding, body) =>
237
237
238
- // def barendregt(stmt: Stmt): Stmt = new Renamer().apply(stmt)
238
+ def joinpoint (id : Id , tpe : ValueType , body : Stmt )(f : BlockVar => Context ?=> Stmt )(using C : Context ): Stmt = body match {
239
+ // do not eta-expand variables
240
+ case Stmt .App (k : BlockVar , Nil , ValueVar (x, tpe) :: Nil , Nil ) if x == id || tpe == Type .TUnit => f(k)
241
+ case _ =>
242
+ val k = Id (" k" )
243
+ C .usage.put(k, Usage .Many )
244
+ val kDef = Block .BlockLit (Nil , Nil , ValueParam (id, tpe) :: Nil , Nil , body)
245
+ Stmt .Def (k, kDef, f(Block .BlockVar (k, kDef.tpe, kDef.capt))(using C .bind(k, kDef)))
246
+ }
239
247
240
- def normalizeVal (id : Id , tpe : ValueType , binding : Stmt , body : Stmt ): Stmt = normalize(binding) match {
248
+ def normalizeVal (id : Id , tpe : ValueType , binding : Stmt , body : Stmt )( using C : Context ) : Stmt = normalize(binding) match {
241
249
242
250
// [[ val x = ABORT; body ]] = ABORT
243
251
case abort if abort.tpe == Type .TBottom =>
@@ -252,34 +260,36 @@ object Normalizer { normal =>
252
260
BlockLit (tparams, cparams, vparams, BlockParam (k, BlockType .Interface (Type .ResumeSymbol , List (tpeB, answer)), captures) :: Nil ,
253
261
normalize(body2)))
254
262
255
- // [[ val x = sc match { case id(ps) => body2 }; body ]] = sc match { case id(ps) => val x = body2; body }
256
263
case Stmt .Match (sc, List ((id2, BlockLit (tparams2, cparams2, vparams2, bparams2, body2))), None ) =>
257
264
Stmt .Match (sc, List ((id2, BlockLit (tparams2, cparams2, vparams2, bparams2,
258
265
normalizeVal(id, tpe, body2, body)))), None )
259
266
260
- // These rewrites do not seem to contribute a lot given their complexity...
261
- // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
262
-
263
- // [[ val x = if (cond) { thn } else { els }; body ]] = if (cond) { [[ val x = thn; body ]] } else { [[ val x = els; body ]] }
264
- // case normalized @ Stmt.If(cond, thn, els) if body.size <= 2 =>
265
- // // since we duplicate the body, we need to freshen the names
266
- // val normalizedThn = barendregt(normalizeVal(id, tpe, thn, body))
267
- // val normalizedEls = barendregt(normalizeVal(id, tpe, els, body))
268
- //
269
- // Stmt.If(cond, normalizedThn, normalizedEls)
270
- //
271
- // case Stmt.Match(sc, clauses, default)
272
- // // necessary since otherwise we loose Nothing-boxing
273
- // // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
274
- // if body.size <= 2 && (clauses.size + default.size) >= 1 =>
275
- // val normalizedClauses = clauses map {
276
- // case (id2, BlockLit(tparams2, cparams2, vparams2, bparams2, body2)) =>
277
- // (id2, BlockLit(tparams2, cparams2, vparams2, bparams2, barendregt(normalizeVal(id, tpe, body2, body))): BlockLit)
278
- // }
279
- // val normalizedDefault = default map { stmt => barendregt(normalizeVal(id, tpe, stmt, body)) }
280
- // Stmt.Match(sc, normalizedClauses, normalizedDefault)
281
-
282
- // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
267
+ // Introduce joinpoints that are potentially later inlined or garbage collected
268
+ // [[ val x = if (cond) { thn } else { els }; body ]] =
269
+ // def k(x) = [[ body ]]
270
+ // if (cond) { [[ val x1 = thn; k(x1) ]] } else { [[ val x2 = els; k(x2) ]] }
271
+ case Stmt .If (cond, thn, els) =>
272
+ joinpoint(id, tpe, normalize(body)) { k =>
273
+ val x1 = Id (id.name)
274
+ val x2 = Id (id.name)
275
+ Stmt .If (cond,
276
+ normalizeVal(x1, tpe, thn, Stmt .App (k, Nil , List (ValueVar (x1, tpe)), Nil )),
277
+ normalizeVal(x2, tpe, els, Stmt .App (k, Nil , List (ValueVar (x2, tpe)), Nil )))
278
+ }
279
+
280
+
281
+ case Stmt .Match (sc, clauses, default) =>
282
+ joinpoint(id, tpe, normalize(body)) { k =>
283
+ Stmt .Match (sc, clauses.map {
284
+ case (tag, BlockLit (tparams, cparams, vparams, bparams, body)) =>
285
+ val x = Id (id.name)
286
+ (tag, BlockLit (tparams, cparams, vparams, bparams,
287
+ normalizeVal(x, tpe, body, Stmt .App (k, Nil , List (ValueVar (x, tpe)), Nil ))))
288
+ }, default.map { stmt =>
289
+ val x = Id (id.name)
290
+ normalizeVal(x, tpe, stmt, Stmt .App (k, Nil , List (ValueVar (x, tpe)), Nil ))
291
+ })
292
+ }
283
293
284
294
// [[ val x = return e; s ]] = let x = [[ e ]]; [[ s ]]
285
295
case Stmt .Return (expr2) =>
@@ -312,9 +322,12 @@ object Normalizer { normal =>
312
322
case Stmt .Put (ref2, capt2, value2, body2) =>
313
323
Stmt .Put (ref2, capt2, value2, normalizeVal(id, tpe, body2, body))
314
324
315
- // [[ val x = stmt; return x ]] = [[ stmt ]]
316
325
case other => normalize(body) match {
326
+ // [[ val x = stmt; return x ]] = [[ stmt ]]
317
327
case Stmt .Return (x : ValueVar ) if x.id == id => other
328
+ // [[ val x: Unit = stmt; return () ]] = [[ stmt ]]
329
+ case Stmt .Return (x) if x.tpe == Type .TUnit && other.tpe == Type .TUnit => other
330
+ // [[ val x = stmt; body ]] = val x = [[ stmt ]]; [[ body ]]
318
331
case normalizedBody => Stmt .Val (id, tpe, other, normalizedBody)
319
332
}
320
333
}
0 commit comments