@@ -63,20 +63,113 @@ class Lowering()(using Config, TL, Raise, State, Ctx):
63
63
def unit : Path =
64
64
Select (Value .Ref (State .runtimeSymbol), Tree .Ident (" Unit" ))(S (summon[Ctx ].builtins.Unit ))
65
65
66
+
67
+ type Rcd = List [RcdArg ]
68
+
66
69
def returnedTerm (t : st)(using Subst ): Block = term(t)(Ret )
67
70
68
71
// * Used to work around Scala's @tailrec annotation for those few calls that are not in tail position.
69
72
final def term_nonTail (t : st, inStmtPos : Bool = false )(k : Result => Block )(using Subst ): Block =
70
73
term(t : st, inStmtPos : Bool )(k)
71
74
75
+ def block (stats : Ls [Statement ], res : Rcd \/ Term )(k : Result => Block )(using Subst ): Block =
76
+ stats match
77
+ case (t : sem.Term ) :: stats =>
78
+ subTerm(t, inStmtPos = true ): r =>
79
+ block(stats, res)(r => k(r))
80
+ case Nil =>
81
+ res match
82
+ case R (res) => term(res)(k)
83
+ case L (flds) =>
84
+ k(Value .Rcd (flds.reverse))
85
+ case RcdField (lhs, rhs) :: stats =>
86
+ res match
87
+ case R (_) => wat(" RcdField in non-Rcd context" , res)
88
+ case L (flds) =>
89
+ subTerm(lhs): l =>
90
+ subTerm_nonTail(rhs): r =>
91
+ block(stats, L (RcdArg (S (l), r) :: flds))(k)
92
+ case (decl @ LetDecl (sym, annotations)) :: (stats @ ((_ : DefineVar ) :: _)) =>
93
+ reportAnnotations(decl, annotations)
94
+ block(stats, res)(k)
95
+ case (decl @ LetDecl (sym, annotations)) :: stats =>
96
+ reportAnnotations(decl, annotations)
97
+ block(DefineVar (sym, Term .Lit (Tree .UnitLit (false ))) :: stats, res)(k)
98
+ case DefineVar (sym, rhs) :: stats =>
99
+ subTerm(rhs): r =>
100
+ Assign (sym, r, block(stats, res)(k))
101
+ case (imp @ Import (sym, path)) :: stats =>
102
+ raise(ErrorReport (
103
+ msg " Imports must be at the top level " ->
104
+ imp.toLoc :: Nil ,
105
+ source = Diagnostic .Source .Compilation ))
106
+ block(stats, res)(k)
107
+ case (d : Declaration ) :: stats =>
108
+ d match
109
+ case td : TermDefinition =>
110
+ reportAnnotations(td, td.extraAnnotations)
111
+ td.body match
112
+ case N => // abstract declarations have no lowering
113
+ block(stats, res)(k)
114
+ case S (bod) =>
115
+ td.k match
116
+ case knd : syntax.Val =>
117
+ assert(td.params.isEmpty)
118
+ subTerm_nonTail(bod)(r =>
119
+ // Assign(td.sym, r,
120
+ // term(st.Blk(stats, res))(k)))
121
+ Define (ValDefn (td.owner, knd, td.sym, r),
122
+ block(stats, res)(k)))
123
+ case syntax.Fun =>
124
+ val (paramLists, bodyBlock) = setupFunctionOrByNameDef(td.params, bod, S (td.sym.nme))
125
+ Define (FunDefn (td.owner, td.sym, paramLists, bodyBlock),
126
+ block(stats, res)(k))
127
+ case syntax.Ins =>
128
+ // Implicit instances are not parameterized for now.
129
+ assert(td.params.isEmpty)
130
+ subTerm(bod)(r =>
131
+ Define (ValDefn (td.owner, syntax.ImmutVal , td.sym, r),
132
+ block(stats, res)(k)))
133
+ case cls : ClassLikeDef if cls.sym.defn.exists(_.isDeclare.isDefined) =>
134
+ // * Declarations have no lowering
135
+ block(stats, res)(k)
136
+ case cls : ClassLikeDef =>
137
+ reportAnnotations(cls, cls.extraAnnotations)
138
+ val (mtds, publicFlds, privateFlds, ctor) = gatherMembers(cls.body)
139
+ cls.ext match
140
+ case N =>
141
+ Define (ClsLikeDefn (cls.owner, cls.sym, cls.bsym, cls.kind, cls.paramsOpt, Nil , N ,
142
+ mtds,
143
+ privateFlds,
144
+ publicFlds,
145
+ End (),
146
+ ctor
147
+ ),
148
+ block(stats, res)(k))
149
+ case S (ext) =>
150
+ assert(k isnt syntax.Mod ) // modules can't extend things and can't have super calls
151
+ subTerm(ext.cls): clsp =>
152
+ val pctor = // TODO dedup with New case
153
+ args(ext.args): args =>
154
+ Return (Call (Value .Ref (State .builtinOpsMap(" super" )), args)(true , true ), implct = true )
155
+ Define (
156
+ ClsLikeDefn (
157
+ cls.owner, cls.sym, cls.bsym, cls.kind, cls.paramsOpt, Nil , S (clsp),
158
+ mtds, privateFlds, publicFlds, pctor, ctor
159
+ ),
160
+ block(stats, res)(k)
161
+ )
162
+ case td : TypeDef => // * Type definitions are erased
163
+ block(stats, res)(k)
164
+
72
165
@ tailrec
73
166
final def term (t : st, inStmtPos : Bool = false )(k : Result => Block )(using Subst ): Block =
74
167
tl.log(s " Lowering.term ${t.showDbg.truncate(100 , " [...]" )}${
75
168
if inStmtPos then " (in stmt)" else " " }${
76
169
t.symbol.fold(" " )(" – symbol " + _)}" )
77
170
def warnStmt = if inStmtPos then
78
- raise( WarningReport :
79
- msg " Pure expression in statement position " -> t.toLoc :: Nil )
171
+ raise :
172
+ WarningReport ( msg " Pure expression in statement position " -> t.toLoc :: Nil , S (t) )
80
173
t match
81
174
case st.UnitVal () => k(unit)
82
175
case st.Lit (lit) =>
@@ -234,8 +327,7 @@ class Lowering()(using Config, TL, Raise, State, Ctx):
234
327
subTerm(prefix): p =>
235
328
conclude(Select (p, nme)(sel.sym))
236
329
case _ => subTerm(f)(conclude)
237
-
238
- case st.Blk ((h @ Handle (lhs, rhs, as, cls, defs)) :: stmts, res) =>
330
+ case h @ Handle (lhs, rhs, as, cls, defs, bod) =>
239
331
if ! lowerHandlers then
240
332
raise(ErrorReport (
241
333
msg " Effect handlers are not enabled " ->
@@ -255,83 +347,9 @@ class Lowering()(using Config, TL, Raise, State, Ctx):
255
347
subTerm(rhs): par =>
256
348
subTerms(as): asr =>
257
349
HandleBlock (lhs, resSym, par, asr, cls, handlers,
258
- term_nonTail(st. Blk (stmts, res) )(HandleBlockReturn (_)),
350
+ term_nonTail(bod )(HandleBlockReturn (_)),
259
351
k(Value .Ref (resSym)))
260
-
261
- case st.TyApp (lhs, _) => term(lhs)(k)
262
- case st.Blk (Nil , res) => term(res)(k)
263
- case st.Blk ((t : sem.Term ) :: stats, res) =>
264
- subTerm(t, inStmtPos = true )(r => term_nonTail(st.Blk (stats, res))(k))
265
- case st.Blk ((d : Declaration ) :: stats, res) =>
266
- d match
267
- case td : TermDefinition =>
268
- reportAnnotations(td, td.extraAnnotations)
269
- td.body match
270
- case N => // abstract declarations have no lowering
271
- term(st.Blk (stats, res))(k)
272
- case S (bod) =>
273
- td.k match
274
- case knd : syntax.Val =>
275
- assert(td.params.isEmpty)
276
- subTerm_nonTail(bod)(r =>
277
- // Assign(td.sym, r,
278
- // term(st.Blk(stats, res))(k)))
279
- Define (ValDefn (td.owner, knd, td.sym, r),
280
- term_nonTail(st.Blk (stats, res))(k)))
281
- case syntax.Fun =>
282
- val (paramLists, bodyBlock) = setupFunctionOrByNameDef(td.params, bod, S (td.sym.nme))
283
- Define (FunDefn (td.owner, td.sym, paramLists, bodyBlock),
284
- term_nonTail(st.Blk (stats, res))(k))
285
- case syntax.Ins =>
286
- // Implicit instances are not parameterized for now.
287
- assert(td.params.isEmpty)
288
- subTerm(bod)(r =>
289
- Define (ValDefn (td.owner, syntax.ImmutVal , td.sym, r),
290
- term_nonTail(st.Blk (stats, res))(k)))
291
- case cls : ClassLikeDef if cls.sym.defn.exists(_.isDeclare.isDefined) =>
292
- // * Declarations have no lowering
293
- term(st.Blk (stats, res))(k)
294
- case cls : ClassLikeDef =>
295
- reportAnnotations(cls, cls.extraAnnotations)
296
- val (mtds, publicFlds, privateFlds, ctor) = gatherMembers(cls.body)
297
- cls.ext match
298
- case N =>
299
- Define (
300
- ClsLikeDefn (cls.owner, cls.sym, cls.bsym, cls.kind, cls.paramsOpt, Nil , N ,
301
- mtds, privateFlds, publicFlds, End (), ctor),
302
- term_nonTail(st.Blk (stats, res))(k)
303
- )
304
- case S (ext) =>
305
- assert(k isnt syntax.Mod ) // modules can't extend things and can't have super calls
306
- subTerm(ext.cls): clsp =>
307
- val pctor = // TODO dedup with `New` case
308
- args(ext.args): args =>
309
- Return (Call (Value .Ref (State .builtinOpsMap(" super" )), args)(true , true ), implct = true )
310
- Define (
311
- ClsLikeDefn (cls.owner, cls.sym, cls.bsym, cls.kind, cls.paramsOpt, Nil , S (clsp),
312
- mtds, privateFlds, publicFlds, pctor, ctor),
313
- term_nonTail(st.Blk (stats, res))(k)
314
- )
315
- case _ =>
316
- // TODO handle
317
- term(st.Blk (stats, res))(k)
318
- case st.Blk ((decl @ LetDecl (sym, annotations)) :: (stats @ ((_ : DefineVar ) :: _)), res) =>
319
- reportAnnotations(decl, annotations)
320
- term(st.Blk (stats, res))(k)
321
- case st.Blk ((decl @ LetDecl (sym, annotations)) :: stats, res) =>
322
- reportAnnotations(decl, annotations)
323
- term(st.Blk (DefineVar (sym, Term .Lit (Tree .UnitLit (false ))) :: stats, res))(k)
324
- case st.Blk (DefineVar (sym, rhs) :: stats, res) =>
325
- val oldSubst = subst
326
- rhs match
327
- // * This is currently wrong because if `r` is mutable, we can't substitute `sym` with `r`
328
- // * TODO: Distinguish mutable from immutable local variables
329
- // case Ref(r) =>
330
- // given Subst = oldSubst + (sym -> Value.Ref(r))
331
- // term(st.Blk(stats, res))(k)
332
- case _ =>
333
- subTerm(rhs): r =>
334
- Assign (sym, r, term_nonTail(st.Blk (stats, res))(k))
352
+ case st.Blk (sts, res) => block(sts, R (res))(k)
335
353
case Assgn (lhs, rhs) =>
336
354
lhs match
337
355
case Ref (sym) =>
@@ -493,13 +511,13 @@ class Lowering()(using Config, TL, Raise, State, Ctx):
493
511
subTerm(prefix): p =>
494
512
subTerm_nonTail(fld): f =>
495
513
k(DynSelect (p, f, ai))
496
-
514
+
497
515
498
516
case New (cls, as, N ) =>
499
517
subTerm(cls): sr =>
500
518
subTerms(as): asr =>
501
519
k(Instantiate (sr, asr))
502
-
520
+
503
521
case New (cls, as, S ((isym, rft))) =>
504
522
subTerm(cls): clsp =>
505
523
val sym = new BlockMemberSymbol (isym.name, Nil )
@@ -510,15 +528,15 @@ class Lowering()(using Config, TL, Raise, State, Ctx):
510
528
val clsDef = ClsLikeDefn (N , isym, sym, syntax.Cls , N , Nil , S (clsp),
511
529
mtds, privateFlds, publicFlds, pctor, ctor)
512
530
Define (clsDef, term_nonTail(New (sym.ref(), Nil , N ))(k))
513
-
531
+
514
532
case Try (sub, finallyDo) =>
515
533
val l = new TempSymbol (S (sub))
516
534
TryBlock (
517
535
subTerm_nonTail(sub)(p => Assign (l, p, End ())),
518
536
subTerm_nonTail(finallyDo)(_ => End ()),
519
537
k(Value .Ref (l))
520
538
)
521
-
539
+
522
540
// * BbML-specific cases: t.Cls#field and mutable operations
523
541
case sp @ SelProj (prefix, _, proj) =>
524
542
setupSelection(prefix, proj, sp.sym)(k)
@@ -536,6 +554,9 @@ class Lowering()(using Config, TL, Raise, State, Ctx):
536
554
subTerm_nonTail(rhs): value =>
537
555
AssignField (ref, Tree .Ident (" value" ), value, k(value))(N )
538
556
557
+ case Rcd (stats) =>
558
+ block(stats, L (Nil ))(k)
559
+
539
560
case Neg (_) =>
540
561
raise(ErrorReport (
541
562
msg " Unexpected type annotations ${t.show}" ->
0 commit comments