Skip to content

Commit f764eb9

Browse files
committed
Refactor code generation for local definitions & annotations + fix various problems
1 parent 5839d4d commit f764eb9

136 files changed

Lines changed: 2153 additions & 1536 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

hkmc2/shared/src/main/scala/hkmc2/MLsCompiler.scala

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,16 +71,19 @@ class MLsCompiler(preludeFile: os.Path):
7171

7272
newCtx.nest(N).givenIn:
7373

74-
val (blk, newCtx) = elab.importFrom(mainParse.resultBlk)
74+
val parsed = mainParse.resultBlk
75+
val (blk, newCtx) = elab.importFrom(parsed)
7576
val low = ltl.givenIn:
7677
codegen.Lowering(lowerHandlers = false)
7778
val jsb = codegen.js.JSBuilder()
7879
val le = low.program(blk)
7980
val baseScp: utils.Scope =
8081
utils.Scope.empty
8182
val nestedScp = baseScp.nest
83+
val nme = file.baseName
84+
val exportedSymbol = parsed.definedSymbols.find(_._1 === nme).map(_._2)
8285
val je = nestedScp.givenIn:
83-
jsb.program(le, S(file.baseName), wd)
86+
jsb.program(le, exportedSymbol, wd)
8487
val jsStr = je.stripBreaks.mkString(100)
8588
val out = file / os.up / (file.baseName + ".mjs")
8689
os.write.over(out, jsStr)

hkmc2/shared/src/main/scala/hkmc2/bbml/bbML.scala

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ object BbCtx:
6969
def init(raise: Raise)(using Elaborator.State, Elaborator.Ctx): BbCtx =
7070
new BbCtx(raise, summon, None, 1, HashMap.empty, Bot, N)
7171

72-
val builtinOps = Set("+", "-", "*", "/", "<", ">", "<=", ">=", "==", "!=", "&&", "||")
72+
val builtinOps = Elaborator.binaryOps ++ Elaborator.unaryOps ++ Elaborator.aliasOps.keySet
7373
end BbCtx
7474

7575

@@ -84,8 +84,8 @@ class BBTyper(using elState: Elaborator.State, tl: TL):
8484
private def freshVar(sym: Symbol, hint: Str = "")(using ctx: BbCtx): InfVar =
8585
InfVar(ctx.lvl, infVarState.nextUid, new VarState(), false)(sym, hint)
8686
private def freshWildcard(sym: Symbol)(using ctx: BbCtx) =
87-
val in = freshVar(sym, "-")
88-
val out = freshVar(sym, "+")
87+
val in = freshVar(sym, "")
88+
val out = freshVar(sym, "")
8989
// in.state.upperBounds ::= out // * Not needed for soundness; complicates inferred types
9090
Wildcard(in, out)
9191
private def freshReg(sym: Symbol)(using ctx: BbCtx) =
@@ -138,8 +138,8 @@ class BBTyper(using elState: Elaborator.State, tl: TL):
138138
// log(s"Type application: ${cls.nme} with ${targs}")
139139
cls.symbol.flatMap(_.asTpe) match
140140
case S(tpeSym) =>
141-
if tpeSym.nme === "Any" then Top
142-
else if tpeSym.nme === "Nothing" then Bot
141+
if tpeSym.nme === "Any" then Top // FIXME hygiene
142+
else if tpeSym.nme === "Nothing" then Bot // FIXME hygiene
143143
else
144144
val defn = tpeSym.defn.get
145145
if targs.length != defn.tparams.length then
@@ -425,6 +425,7 @@ class BBTyper(using elState: Elaborator.State, tl: TL):
425425
trace[(GeneralType, Type)](s"${ctx.lvl}. Typing ${t.showDbg}", res => s": (${res._1.showDbg}, ${res._2.showDbg})"):
426426
given CCtx = CCtx.init(t, N)
427427
t match
428+
case Term.Annotated(Annot.Untyped, _) => (Bot, Bot)
428429
case sel @ Term.SynthSel(Ref(_: TopLevelSymbol), nme)
429430
if sel.symbol.isDefined =>
430431
typeCheck(Ref(sel.symbol.get)(sel.nme, 666)) // FIXME 666
@@ -507,8 +508,6 @@ class BBTyper(using elState: Elaborator.State, tl: TL):
507508
case _ => (error(msg"${field.name} is not a valid member in class ${clsSym.nme}" -> t.toLoc :: Nil), Bot)
508509
case N =>
509510
(error(msg"Not a valid class: ${cls.describe}" -> cls.toLoc :: Nil), Bot)
510-
case Term.App(lhs: Term.SynthSel, Term.Tup(Nil)) if lhs.sym.exists(_.isGetter) =>
511-
typeCheck(lhs) // * Getter access will be elaborated to applications. But they cannot be typed as normal applications.
512511
case t @ Term.App(lhs, Term.Tup(rhs)) =>
513512
val (funTy, lhsEff) = typeCheck(lhs)
514513
app((funTy, lhsEff), rhs, t)

hkmc2/shared/src/main/scala/hkmc2/codegen/Block.scala

Lines changed: 49 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,9 @@ sealed abstract class Block extends Product with AutoLocated:
3636
case End(_) => Set.empty
3737
case Break(_) => Set.empty
3838
case Continue(_) => Set.empty
39-
case Define(defn, rst) => rst.definedVars
39+
case Define(defn, rst) =>
40+
val rest = rst.definedVars
41+
if defn.isOwned then rest else rest + defn.sym
4042
case HandleBlock(lhs, res, par, cls, hdr, bod, rst) => bod.definedVars ++ rst.definedVars + lhs
4143
case HandleBlockReturn(_) => Set.empty
4244
case TryBlock(sub, fin, rst) => sub.definedVars ++ fin.definedVars ++ rst.definedVars
@@ -86,7 +88,17 @@ sealed abstract class Block extends Product with AutoLocated:
8688
(bod.freeVars - lhs) ++ rst.freeVars ++ hdr.flatMap(_.freeVars)
8789
case HandleBlockReturn(res) => res.freeVars
8890
case End(msg) => Set.empty
89-
91+
92+
lazy val subBlocks: Ls[Block] = this match
93+
case Match(_, arms, dflt, rest) => arms.map(_._2) ++ dflt.toList :+ rest
94+
case Begin(sub, rest) => sub :: rest :: Nil
95+
case TryBlock(sub, finallyDo, rest) => sub :: finallyDo :: rest :: Nil
96+
case Assign(_, rhs, rest) => rest :: Nil
97+
case AssignField(_, _, rhs, rest) => rest :: Nil
98+
case Define(_, rest) => rest :: Nil
99+
case HandleBlock(_, _, _, _, handlers, body, rest) => handlers.map(_.body) :+ body :+ rest
100+
case _: Return | _: Throw | _: Label | _: Break | _: Continue | _: End | _: HandleBlockReturn => Nil
101+
90102
def floatOutDefns =
91103
def rec(b: Block, acc: List[Defn]): (Block, List[Defn]) = b match
92104
case Match(scrut, arms, dflt, rest) =>
@@ -143,7 +155,7 @@ sealed abstract class Block extends Product with AutoLocated:
143155
case HandleBlockReturn(res) => (b, acc)
144156
case End(msg) => (b, acc)
145157
rec(this, Nil)
146-
158+
147159
end Block
148160

149161
sealed abstract class BlockTail extends Block
@@ -178,43 +190,62 @@ case class AssignField(lhs: Path, nme: Tree.Ident, rhs: Result, rest: Block)(val
178190

179191
case class Define(defn: Defn, rest: Block) extends Block with ProductWithTail
180192

181-
case class HandleBlock(lhs: Local, res: Local, par: Path, cls: ClassSymbol, handlers: Ls[Handler], body: Block, rest: Block) extends Block with ProductWithTail
193+
case class HandleBlock(
194+
lhs: Local,
195+
res: Local,
196+
par: Path,
197+
cls: ClassSymbol,
198+
handlers: Ls[Handler],
199+
body: Block,
200+
rest: Block
201+
) extends Block with ProductWithTail
202+
182203
case class HandleBlockReturn(res: Result) extends BlockTail
183204

184205
sealed abstract class Defn:
185-
val sym: MemberSymbol[?]
206+
val innerSym: Opt[MemberSymbol[?]]
207+
val sym: BlockMemberSymbol
208+
def isOwned: Bool = owner.isDefined
209+
def owner: Opt[InnerSymbol]
186210

187211
lazy val freeVars: Set[Local] = this match
188-
case FunDefn(sym, params, body) => body.freeVars -- params.flatMap(_.paramSyms) - sym
212+
case FunDefn(own, sym, params, body) => body.freeVars -- params.flatMap(_.paramSyms) - sym
189213
case ValDefn(owner, k, sym, rhs) => rhs.freeVars
190-
case ClsLikeDefn(sym, k, parentSym, methods, privateFields, publicFields, preCtor, ctor) =>
214+
case ClsLikeDefn(own, isym, sym, k, paramsOpt, parentSym, methods, privateFields, publicFields, preCtor, ctor) =>
191215
preCtor.freeVars
192216
++ ctor.freeVars ++ methods.flatMap(_.freeVars)
193217
-- privateFields -- publicFields.map(_.sym)
194218

195219
final case class FunDefn(
220+
owner: Opt[InnerSymbol],
196221
sym: BlockMemberSymbol,
197222
params: Ls[ParamList],
198223
body: Block,
199-
) extends Defn
224+
) extends Defn:
225+
val innerSym = N
200226

201227
final case class ValDefn(
202228
owner: Opt[InnerSymbol],
203229
k: syntax.Val,
204230
sym: BlockMemberSymbol,
205231
rhs: Path,
206-
) extends Defn
232+
) extends Defn:
233+
val innerSym = N
207234

208235
final case class ClsLikeDefn(
209-
sym: MemberSymbol[? <: ClassLikeDef],
210-
k: syntax.ClsLikeKind,
211-
parentPath: Opt[Path],
212-
methods: Ls[FunDefn],
213-
privateFields: Ls[TermSymbol],
214-
publicFields: Ls[TermDefinition],
215-
preCtor: Block,
216-
ctor: Block,
217-
) extends Defn
236+
owner: Opt[InnerSymbol],
237+
isym: MemberSymbol[? <: ClassLikeDef],
238+
sym: BlockMemberSymbol,
239+
k: syntax.ClsLikeKind,
240+
paramsOpt: Opt[ParamList],
241+
parentPath: Opt[Path],
242+
methods: Ls[FunDefn],
243+
privateFields: Ls[TermSymbol],
244+
publicFields: Ls[TermDefinition],
245+
preCtor: Block,
246+
ctor: Block,
247+
) extends Defn:
248+
val innerSym = S(isym)
218249

219250
final case class Handler(
220251
sym: BlockMemberSymbol,

hkmc2/shared/src/main/scala/hkmc2/codegen/BlockTransformer.scala

Lines changed: 54 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,12 @@ import hkmc2.utils.*
77
import semantics.*
88
import os.write.over
99

10+
1011
// Default implementation: nothing is transformed
1112
class BlockTransformer(subst: SymbolSubst):
12-
13+
1314
given SymbolSubst = subst
14-
15+
1516
def applyBlock(b: Block): Block = b match
1617
case _: End => b
1718
case Break(lbl) =>
@@ -31,15 +32,15 @@ class BlockTransformer(subst: SymbolSubst):
3132
if res2 is res then b else HandleBlockReturn(res2)
3233
case Match(scrut, arms, dflt, rst) =>
3334
val scrut2 = applyPath(scrut)
34-
val arms2 = arms.map: arm =>
35+
val arms2 = arms.mapConserve: arm =>
3536
val cse2 = applyCase(arm._1)
3637
val blk2 = applyBlock(arm._2)
3738
if (cse2 is arm._1) && (blk2 is arm._2) then arm else (cse2, blk2)
38-
val dflt2 = dflt.map(applyBlock)
39+
val dflt2 = dflt.mapConserve(applyBlock)
3940
val rst2 = applyBlock(rst)
4041
if (scrut2 is scrut) &&
41-
(arms2 zip arms).forall(_ is _) &&
42-
(dflt2 zip dflt).forall(_ is _) && (rst2 is rst)
42+
(arms2 is arms) &&
43+
(dflt2 is dflt) && (rst2 is rst)
4344
then b else Match(scrut2, arms2, dflt2, rst2)
4445
case Label(lbl, bod, rst) =>
4546
val lbl2 = applyLocal(lbl)
@@ -64,8 +65,8 @@ class BlockTransformer(subst: SymbolSubst):
6465
applyResult2(r): r2 =>
6566
val l2 = applyPath(l)
6667
val rst2 = applyBlock(rst)
67-
val sym = b.symbol.map(_.subst)
68-
if (l2 is l) && (r2 is r) && (rst2 is rst) && (sym zip b.symbol).forall(_ is _)
68+
val sym = b.symbol.mapConserve(_.subst)
69+
if (l2 is l) && (r2 is r) && (rst2 is rst) && (sym is b.symbol)
6970
then b else AssignField(l2, n, r2, rst2)(sym)
7071
case Define(defn, rst) =>
7172
val defn2 = applyDefn(defn)
@@ -76,31 +77,31 @@ class BlockTransformer(subst: SymbolSubst):
7677
val res2 = applyLocal(res)
7778
val par2 = applyPath(par)
7879
val cls2 = cls.subst
79-
val hdr2 = hdr.map(applyHandler)
80+
val hdr2 = hdr.mapConserve(applyHandler)
8081
val bod2 = applyBlock(bod)
8182
val rst2 = applyBlock(rst)
8283
if (l2 is l) && (res2 is res) && (par2 is par) && (cls2 is cls) &&
83-
(hdr2 zip hdr).forall(_ is _) && (bod2 is bod) && (rst2 is rst)
84+
(hdr2 is hdr) && (bod2 is bod) && (rst2 is rst)
8485
then b else HandleBlock(l2, res2, par2, cls2, hdr2, bod2, rst2)
8586

8687
def applyResult2(r: Result)(k: Result => Block): Block = k(applyResult(r))
8788

8889
def applyResult(r: Result): Result = r match
8990
case r @ Call(fun, args) =>
9091
val fun2 = applyPath(fun)
91-
val args2 = args.map(applyArg)
92-
if (fun2 is fun) && (args2 zip args).forall(_ is _) then r else Call(fun2, args2)(r.isMlsFun)
92+
val args2 = args.mapConserve(applyArg)
93+
if (fun2 is fun) && (args2 is args) then r else Call(fun2, args2)(r.isMlsFun)
9394
case Instantiate(cls, args) =>
9495
val cls2 = applyPath(cls)
95-
val args2 = args.map(applyPath)
96-
if (cls2 is cls) && (args2 zip args).forall(_ is _) then r else Instantiate(cls2, args2)
96+
val args2 = args.mapConserve(applyPath)
97+
if (cls2 is cls) && (args2 is args) then r else Instantiate(cls2, args2)
9798
case p: Path => applyPath(p)
9899

99100
def applyPath(p: Path): Path = p match
100101
case p @ Select(qual, name) =>
101102
val qual2 = applyPath(qual)
102-
val sym2 = p.symbol.map(_.subst)
103-
if (qual2 is qual) && (sym2 zip p.symbol).forall(_ is _) then p else Select(qual2, name)(sym2)
103+
val sym2 = p.symbol.mapConserve(_.subst)
104+
if (qual2 is qual) && (sym2 is p.symbol) then p else Select(qual2, name)(sym2)
104105
case v: Value => applyValue(v)
105106

106107
def applyValue(v: Value): Value = v match
@@ -113,40 +114,46 @@ class BlockTransformer(subst: SymbolSubst):
113114
case Value.Lit(lit) => v
114115
case v @ Value.Lam(params, body) => applyLam(v)
115116
case Value.Arr(elems) =>
116-
val elems2 = elems.map(applyArg)
117-
if (elems2 zip elems).forall(_ is _) then v else Value.Arr(elems2)
117+
val elems2 = elems.mapConserve(applyArg)
118+
if (elems2 is elems) then v else Value.Arr(elems2)
118119

119120
def applyLocal(sym: Local): Local = sym.subst
120-
121+
121122
def applyFunDefn(fun: FunDefn): FunDefn =
123+
val own2 = fun.owner.mapConserve(_.subst)
122124
val sym2 = fun.sym.subst
123-
val params2 = fun.params.map(applyParamList)
125+
val params2 = fun.params.mapConserve(applyParamList)
124126
val body2 = applyBlock(fun.body)
125-
if (sym2 is fun.sym) && (params2 zip fun.params).forall(_ is _) && (body2 is fun.body)
126-
then fun else FunDefn(sym2, params2, body2)
127+
if (own2 is fun.owner) && (sym2 is fun.sym) && (params2 is fun.params) && (body2 is fun.body)
128+
then fun else FunDefn(own2, sym2, params2, body2)
127129

128130
def applyDefn(defn: Defn): Defn = defn match
129-
case defn @ FunDefn(sym, params, body) => applyFunDefn(defn)
131+
case defn: FunDefn => applyFunDefn(defn)
130132
case ValDefn(owner, k, sym, rhs) =>
131-
val owner2 = owner.map(_.subst)
133+
val owner2 = owner.mapConserve(_.subst)
132134
val sym2 = sym.subst
133135
val rhs2 = applyPath(rhs)
134-
if (owner2 zip owner).forall(_ is _) && (sym2 is sym) && (rhs2 is rhs)
136+
if (owner2 is owner) && (sym2 is sym) && (rhs2 is rhs)
135137
then defn else ValDefn(owner2, k, sym2, rhs2)
136-
case ClsLikeDefn(sym, k, parentPath, methods, privateFields, publicFields, preCtor, ctor) =>
138+
case ClsLikeDefn(own, isym, sym, k, paramsOpt, parentPath, methods, privateFields, publicFields, preCtor, ctor) =>
139+
val own2 = own.mapConserve(_.subst)
140+
val isym2 = isym.subst
137141
val sym2 = sym.subst
138-
val parentPath2 = parentPath.map(applyPath)
139-
val methods2 = methods.map(applyFunDefn)
140-
val privateFields2 = privateFields.map(_.subst)
141-
val publicFields2 = publicFields.map(applyTermDefinition)
142+
val paramsOpt2 = paramsOpt.mapConserve(applyParamList)
143+
val parentPath2 = parentPath.mapConserve(applyPath)
144+
val methods2 = methods.mapConserve(applyFunDefn)
145+
val privateFields2 = privateFields.mapConserve(_.subst)
146+
val publicFields2 = publicFields.mapConserve(applyTermDefinition)
142147
val preCtor2 = applyBlock(preCtor)
143148
val ctor2 = applyBlock(ctor)
144-
if (sym2 is sym) && (parentPath2 zip parentPath).forall(_ is _) &&
145-
(methods2 zip methods).forall(_ is _) &&
146-
(privateFields2 zip privateFields).forall(_ is _) &&
147-
(publicFields2 zip publicFields).forall(_ is _) &&
149+
if (own2 is own) && (isym2 is isym) && (sym2 is sym) &&
150+
(paramsOpt2 is paramsOpt) &&
151+
(parentPath2 is parentPath) &&
152+
(methods2 is methods) &&
153+
(privateFields2 is privateFields) &&
154+
(publicFields2 is publicFields) &&
148155
(preCtor2 is preCtor) && (ctor2 is ctor)
149-
then defn else ClsLikeDefn(sym2, k, parentPath2, methods2, privateFields2, publicFields2, preCtor2, ctor2)
156+
then defn else ClsLikeDefn(own, isym2, sym2, k, paramsOpt, parentPath2, methods2, privateFields2, publicFields2, preCtor2, ctor2)
150157

151158
def applyArg(arg: Arg): Arg =
152159
val val2 = applyPath(arg.value)
@@ -156,9 +163,9 @@ class BlockTransformer(subst: SymbolSubst):
156163
def applyParam(p: Param): Param =
157164
val sym2 = p.sym.subst
158165
if sym2 is p.sym then p else Param(p.flags, sym2, p.sign)
159-
val params2 = pl.params.map(applyParam)
160-
val rest2 = pl.restParam.map(applyParam)
161-
if (params2 zip pl.params).forall(_ is _) && (rest2 zip pl.restParam).forall(_ is _)
166+
val params2 = pl.params.mapConserve(applyParam)
167+
val rest2 = pl.restParam.mapConserve(applyParam)
168+
if (params2 is pl.params) && (rest2 is pl.restParam)
162169
then pl else ParamList(pl.flags, params2, rest2)
163170

164171
def applyCase(cse: Case): Case = cse match
@@ -172,10 +179,10 @@ class BlockTransformer(subst: SymbolSubst):
172179
def applyHandler(hdr: Handler): Handler =
173180
val sym2 = hdr.sym.subst
174181
val resumeSym2 = hdr.resumeSym.subst
175-
val params2 = hdr.params.map(applyParamList)
182+
val params2 = hdr.params.mapConserve(applyParamList)
176183
val body2 = applyBlock(hdr.body)
177184
if (sym2 is hdr.sym) && (resumeSym2 is hdr.resumeSym) &&
178-
(params2 zip hdr.params).forall(_ is _) && (body2 is hdr.body)
185+
(params2 is hdr.params) && (body2 is hdr.body)
179186
then hdr else Handler(sym2, resumeSym2, params2, body2)
180187

181188
def applyLam(lam: Value.Lam): Value.Lam =
@@ -184,12 +191,12 @@ class BlockTransformer(subst: SymbolSubst):
184191
if (params2 is lam.params) && (body2 is lam.body) then lam else Value.Lam(params2, body2)
185192

186193
def applyTermDefinition(td: TermDefinition): TermDefinition =
187-
val owner2 = td.owner.map(_.subst)
194+
val owner2 = td.owner.mapConserve(_.subst)
188195
val sym2 = td.sym.subst
189-
val params2 = td.params.map(applyParamList)
196+
val params2 = td.params.mapConserve(applyParamList)
190197
val resSym2 = td.resSym.subst
191-
if (owner2 zip td.owner).forall(_ is _) && (sym2 is td.sym) &&
192-
(params2 zip td.params).forall(_ is _) && (resSym2 is td.resSym)
198+
if (owner2 is td.owner) && (sym2 is td.sym) &&
199+
(params2 is td.params) && (resSym2 is td.resSym)
193200
then td else TermDefinition(owner2, td.k, sym2, params2, td.sign, td.body, resSym2, td.flags, td.annotations)
194201

195202
class BlockTransformerShallow(subst: SymbolSubst) extends BlockTransformer(subst):
@@ -207,9 +214,10 @@ class BlockTransformerShallow(subst: SymbolSubst) extends BlockTransformer(subst
207214
val res2 = applyLocal(res)
208215
val par2 = applyPath(par)
209216
val cls2 = cls.subst
210-
val hdr2 = hdr.map(applyHandler)
217+
val hdr2 = hdr.mapConserve(applyHandler)
211218
val rst2 = applyBlock(rst)
212219
if (l2 is l) && (res2 is res) && (par2 is par) && (cls2 is cls) &&
213-
(hdr2 zip hdr).forall(_ is _) && (rst2 is rst)
220+
(hdr2 is hdr) && (rst2 is rst)
214221
then b else HandleBlock(l2, res2, par2, cls2, hdr2, bod, rst2)
215222
case _ => super.applyBlock(b)
223+

0 commit comments

Comments
 (0)