@@ -23,13 +23,10 @@ final case class BbCtx(
23
23
ctx : Ctx ,
24
24
parent : Option [BbCtx ],
25
25
lvl : Int ,
26
- clsDefs : HashMap [Str , ClassDef ],
27
- env : HashMap [Uid [Symbol ], GeneralType ],
28
- quoteSkolemEnv : HashMap [Uid [Symbol ], InfVar ], // * SkolemTag for variables in quasiquotes
26
+ env : HashMap [Uid [Symbol ], GeneralType ]
29
27
):
30
28
def += (p : Symbol -> GeneralType ): Unit = env += p._1.uid -> p._2
31
29
def get (sym : Symbol ): Option [GeneralType ] = env.get(sym.uid) orElse parent.dlof(_.get(sym))(None )
32
- def *= (cls : ClassDef ): Unit = clsDefs += cls.sym.id.name -> cls
33
30
def getCls (name : Str ): Option [TypeSymbol ] =
34
31
for
35
32
elem <- ctx.get(name)
@@ -38,10 +35,8 @@ final case class BbCtx(
38
35
yield cls
39
36
def &= (p : (Symbol , Type , InfVar )): Unit =
40
37
env += p._1.uid -> BbCtx .varTy(p._2, p._3)(using this )
41
- quoteSkolemEnv += p._1.uid -> p._3
42
- def getSk (sym : Symbol ): Option [Type ] = quoteSkolemEnv.get(sym.uid) orElse parent.dlof(_.getSk(sym))(None )
43
- def nest : BbCtx = copy(parent = Some (this ))
44
- def nextLevel : BbCtx = copy(lvl = lvl + 1 )
38
+ def nest : BbCtx = copy(parent = Some (this ), env = HashMap .empty)
39
+ def nextLevel : BbCtx = copy(parent = Some (this ), lvl = lvl + 1 , env = HashMap .empty)
45
40
46
41
given (using ctx : BbCtx ): Raise = ctx.raise
47
42
@@ -62,7 +57,7 @@ object BbCtx:
62
57
def refTy (ct : Type , sk : Type )(using ctx : BbCtx ): Type =
63
58
ClassLikeType (ctx.getCls(" Ref" ).get, Wildcard (ct, ct) :: Wildcard .out(sk) :: Nil )
64
59
def init (raise : Raise )(using Elaborator .State , Elaborator .Ctx ): BbCtx =
65
- new BbCtx (raise, summon, None , 1 , HashMap .empty, HashMap .empty, HashMap .empty )
60
+ new BbCtx (raise, summon, None , 1 , HashMap .empty)
66
61
end BbCtx
67
62
68
63
@@ -72,13 +67,13 @@ class BBTyper(using elState: Elaborator.State, tl: TL):
72
67
private val infVarState = new InfVarUid .State ()
73
68
private val solver = new ConstraintSolver (infVarState, tl)
74
69
75
- private def freshSkolem (using ctx : BbCtx ): InfVar =
76
- InfVar (ctx.lvl, infVarState.nextUid, new VarState (), true )
77
- private def freshVar (using ctx : BbCtx ): InfVar =
78
- InfVar (ctx.lvl, infVarState.nextUid, new VarState (), false )
79
- private def freshWildcard (using ctx : BbCtx ) =
80
- val in = freshVar
81
- val out = freshVar
70
+ private def freshSkolem (hint : Option [ Str ])( using ctx : BbCtx ): InfVar =
71
+ InfVar (ctx.lvl, infVarState.nextUid, new VarState (), true )(hint)
72
+ private def freshVar (hint : Option [ Str ])( using ctx : BbCtx ): InfVar =
73
+ InfVar (ctx.lvl, infVarState.nextUid, new VarState (), false )(hint)
74
+ private def freshWildcard (hint : Option [ Str ])( using ctx : BbCtx ) =
75
+ val in = freshVar(hint)
76
+ val out = freshVar(hint)
82
77
// in.state.upperBounds ::= out // * Not needed for soundness; complicates inferred types
83
78
Wildcard (in, out)
84
79
@@ -157,7 +152,7 @@ class BBTyper(using elState: Elaborator.State, tl: TL):
157
152
private def genPolyType (tvs : Ls [QuantVar ], body : => GeneralType )(using ctx : BbCtx , cctx : CCtx ) =
158
153
val bds = tvs.map:
159
154
case qv @ QuantVar (sym, ub, lb) =>
160
- val tv = freshVar
155
+ val tv = freshVar( S (sym.name))
161
156
ctx += sym -> tv // TODO: a type var symbol may be better...
162
157
tv -> qv
163
158
bds.foreach:
@@ -176,7 +171,7 @@ class BBTyper(using elState: Elaborator.State, tl: TL):
176
171
177
172
private def instantiate (ty : PolyType )(using ctx : BbCtx ): GeneralType = ty.instantiate(infVarState.nextUid, ctx.lvl)(tl)
178
173
179
- private def extrude (ty : GeneralType )(using ctx : BbCtx , pol : Bool ): GeneralType = ty match
174
+ private def extrude (ty : GeneralType )(using ctx : BbCtx , pol : Bool , cctx : CCtx ): GeneralType = ty match
180
175
case ty : Type => solver.extrude(ty)(using ctx.lvl, pol, HashMap .empty)
181
176
case PolyType (tvs, body) => PolyType (tvs, extrude(body))
182
177
case PolyFunType (args, ret, eff) =>
@@ -185,7 +180,6 @@ class BBTyper(using elState: Elaborator.State, tl: TL):
185
180
private def constrain (lhs : Type , rhs : Type )(using ctx : BbCtx , cctx : CCtx ): Unit =
186
181
solver.constrain(lhs, rhs)
187
182
188
- // TODO: content type
189
183
private def typeCode (code : Term )(using ctx : BbCtx ): (Type , Type , Type ) =
190
184
given CCtx = CCtx .init(code, N )
191
185
code match
@@ -201,12 +195,12 @@ class BBTyper(using elState: Elaborator.State, tl: TL):
201
195
given BbCtx = nestCtx
202
196
val bds = params.map:
203
197
case Param (_, sym, _) =>
204
- val tv = freshVar
205
- val sk = freshSkolem
198
+ val tv = freshVar( S (sym.name))
199
+ val sk = freshSkolem( S (sym.name))
206
200
nestCtx &= (sym, tv, sk)
207
201
(tv, sk)
208
202
val (bodyTy, ctxTy, eff) = typeCode(body)
209
- val res = freshVar(using ctx)
203
+ val res = freshVar(N )( using ctx)
210
204
constrain(ctxTy, bds.foldLeft[Type ](res)((res, bd) => res | bd._2))
211
205
(FunType (bds.map(_._1), bodyTy, Bot ), res, eff)
212
206
case Term .App (lhs, Term .Tup (rhs)) =>
@@ -215,26 +209,29 @@ class BBTyper(using elState: Elaborator.State, tl: TL):
215
209
case (res, p : Fld ) =>
216
210
val (ty, ctx, eff) = typeCode(p.term)
217
211
(ty :: res._1, res._2 | ctx, res._3 | eff)
218
- val resTy = freshVar
212
+ val resTy = freshVar( N )
219
213
constrain(lhsTy, FunType (rhsTy.reverse, resTy, Bot )) // TODO: right
220
214
(resTy, lhsCtx | rhsCtx, lhsEff | rhsEff)
215
+ case sel @ Term .Sel (Term .Ref (_ : TopLevelSymbol ), _) if sel.symbol.isDefined =>
216
+ val (opTy, eff) = typeCheck(Ref (sel.symbol.get)(sel.nme, 666 )) // FIXME 666
217
+ (tryMkMono(opTy, sel), Bot , eff)
221
218
case Term .Unquoted (body) =>
222
219
val (ty, eff) = typeCheck(body)
223
- val tv = freshVar
224
- val cr = freshVar
220
+ val tv = freshVar( N )
221
+ val cr = freshVar( N )
225
222
constrain(tryMkMono(ty, body), BbCtx .codeTy(tv, cr))
226
223
(tv, cr, eff)
227
224
case Term .Blk (LetDecl (sym) :: DefineVar (sym2, rhs) :: Nil , body) if sym2 is sym => // TODO: more than one!!
228
225
val (rhsTy, rhsCtx, rhsEff) = typeCode(rhs)(using ctx)
229
226
val nestCtx = ctx.nextLevel
230
227
given BbCtx = nestCtx
231
- val sk = freshSkolem
228
+ val sk = freshSkolem( S (sym.nme))
232
229
nestCtx &= (sym, rhsTy, sk)
233
230
val (bodyTy, bodyCtx, bodyEff) = typeCode(body)
234
- val res = freshVar(using ctx)
231
+ val res = freshVar(N )( using ctx)
235
232
constrain(bodyCtx, sk | res)
236
233
(bodyTy, rhsCtx | res, rhsEff | bodyEff)
237
- case Term .IfLike (Keyword .`if`, Split .Cons (Branch (cond , Pattern .Lit (BoolLit (true )), Split .Else (cons)), Split .Else (alts))) =>
234
+ case Term .IfLike (Keyword .`if`, Split .Let (_, cond, Split . Cons (Branch (_ , Pattern .Lit (BoolLit (true )), Split .Else (cons)), Split .Else (alts) ))) =>
238
235
val (condTy, condCtx, condEff) = typeCode(cond)
239
236
val (consTy, consCtx, consEff) = typeCode(cons)
240
237
val (altsTy, altsCtx, altsEff) = typeCode(alts)
@@ -252,7 +249,7 @@ class BBTyper(using elState: Elaborator.State, tl: TL):
252
249
()
253
250
case N =>
254
251
given BbCtx = ctx.nextLevel
255
- val funTyV = freshVar
252
+ val funTyV = freshVar( S (sym.nme))
256
253
pctx += sym -> funTyV // for recursive functions
257
254
val (res, _) = typeCheck(lam)
258
255
val funTy = tryMkMono(res, lam)
@@ -266,10 +263,10 @@ class BBTyper(using elState: Elaborator.State, tl: TL):
266
263
: (GeneralType , Type ) =
267
264
split match
268
265
case Split .Cons (Branch (scrutinee, Pattern .ClassLike (sym, _, _, _), cons), alts) =>
269
- // * Pattern matching
266
+ // * Pattern matching for classes
270
267
val (clsTy, tv, emptyTy) = ctx.getCls(sym.nme).flatMap(_.defn) match
271
268
case S (cls) =>
272
- (ClassLikeType (sym, cls.tparams.map(_ => freshWildcard)), freshVar, ClassLikeType (sym, cls.tparams.map(_ => Wildcard .empty)))
269
+ (ClassLikeType (sym, cls.tparams.map(_ => freshWildcard( N ))), ( freshVar( N )) , ClassLikeType (sym, cls.tparams.map(_ => Wildcard .empty)))
273
270
case _ =>
274
271
error(msg " Cannot match ${scrutinee.toString} as ${sym.toString}" -> split.toLoc :: Nil )
275
272
(Bot , Bot , Bot )
@@ -286,6 +283,23 @@ class BBTyper(using elState: Elaborator.State, tl: TL):
286
283
val (altsTy, altsEff) = typeSplit(alts, sign)(using nestCtx2)
287
284
val allEff = scrutineeEff | (consEff | altsEff)
288
285
(sign.getOrElse(tryMkMono(consTy, cons) | tryMkMono(altsTy, alts)), allEff)
286
+ // * Pattern matching for literals
287
+ case Split .Cons (Branch (scrutinee, Pattern .Lit (lit), cons), alts) =>
288
+ val (scrutineeTy, scrutineeEff) = typeCheck(scrutinee)
289
+ val litTy = lit match
290
+ case _ : Tree .BoolLit => BbCtx .boolTy
291
+ case _ : Tree .IntLit => BbCtx .intTy
292
+ case _ : Tree .DecLit => BbCtx .numTy
293
+ case _ : Tree .StrLit => BbCtx .strTy
294
+ case _ : Tree .UnitLit => Top
295
+
296
+ constrain(tryMkMono(scrutineeTy, scrutinee), litTy)
297
+ val nestCtx1 = ctx.nest
298
+ val nestCtx2 = ctx.nest
299
+ val (consTy, consEff) = typeSplit(cons, sign)(using nestCtx1)
300
+ val (altsTy, altsEff) = typeSplit(alts, sign)(using nestCtx2)
301
+ val allEff = scrutineeEff | (consEff | altsEff)
302
+ (sign.getOrElse(tryMkMono(consTy, cons) | tryMkMono(altsTy, alts)), allEff)
289
303
case Split .Let (name, term, tail) =>
290
304
val nestCtx = ctx.nest
291
305
given BbCtx = nestCtx
@@ -361,8 +375,8 @@ class BBTyper(using elState: Elaborator.State, tl: TL):
361
375
val (ty, eff) = typeCheck(f.term)
362
376
Left (ty) :: Right (eff) :: Nil
363
377
.partitionMap(x => x)
364
- val effVar = freshVar
365
- val retVar = freshVar
378
+ val effVar = freshVar( N )
379
+ val retVar = freshVar( N )
366
380
constrain(tryMkMono(funTy, t), FunType (argTy.map((tryMkMono(_, t))), retVar, effVar))
367
381
(retVar, argEff.foldLeft[Type ](effVar | lhsEff)((res, e) => res | e))
368
382
@@ -394,8 +408,6 @@ class BBTyper(using elState: Elaborator.State, tl: TL):
394
408
(error(msg " Variable not found: ${sym.nme}"
395
409
-> t.toLoc :: Nil ), Bot )
396
410
case Blk (stats, res) =>
397
- val nestCtx = ctx.nest
398
- given BbCtx = nestCtx
399
411
val effBuff = ListBuffer .empty[Type ]
400
412
def goStats (stats : Ls [Statement ]): Unit = stats match
401
413
case Nil => ()
@@ -406,7 +418,7 @@ class BBTyper(using elState: Elaborator.State, tl: TL):
406
418
require(sym2 is sym)
407
419
val (rhsTy, eff) = typeCheck(rhs)
408
420
effBuff += eff
409
- nestCtx += sym -> rhsTy
421
+ ctx += sym -> rhsTy
410
422
goStats(stats)
411
423
case TermDefinition (_, Fun , sym, ParamList (_, ps) :: Nil , sig, Some (body), _, _) :: stats =>
412
424
typeFunDef(sym, Term .Lam (ps, body), sig, ctx)
@@ -418,7 +430,6 @@ class BBTyper(using elState: Elaborator.State, tl: TL):
418
430
ctx += sym -> typeType(sig)
419
431
goStats(stats)
420
432
case (clsDef : ClassDef ) :: stats =>
421
- ctx *= clsDef
422
433
goStats(stats)
423
434
goStats(stats)
424
435
val (ty, eff) = typeCheck(res)
@@ -434,7 +445,7 @@ class BBTyper(using elState: Elaborator.State, tl: TL):
434
445
given BbCtx = nestCtx
435
446
val tvs = params.map:
436
447
case Param (_, sym, sign) =>
437
- val ty = sign.map(s => typeType(s)(using nestCtx)).getOrElse(freshVar)
448
+ val ty = sign.map(s => typeType(s)(using nestCtx)).getOrElse(freshVar( S (sym.nme)) )
438
449
nestCtx += sym -> ty
439
450
ty
440
451
val (bodyTy, eff) = typeCheck(body)
@@ -446,7 +457,7 @@ class BBTyper(using elState: Elaborator.State, tl: TL):
446
457
val map = HashMap [Uid [Symbol ], TypeArg ]()
447
458
val targs = clsDfn.tparams.map {
448
459
case TyParam (_, _, targ) =>
449
- val ty = freshWildcard
460
+ val ty = freshWildcard( N )
450
461
map += targ.uid -> ty
451
462
ty
452
463
}
@@ -471,12 +482,12 @@ class BBTyper(using elState: Elaborator.State, tl: TL):
471
482
val map = HashMap [Uid [Symbol ], TypeArg ]()
472
483
val targs = clsDfn.tparams.map {
473
484
case TyParam (_, S (_), targ) =>
474
- val ty = freshVar
485
+ val ty = freshVar( N )
475
486
map += targ.uid -> ty
476
487
ty
477
488
case TyParam (_, N , targ) =>
478
489
// val ty = freshWildcard // FIXME probably not correct
479
- val ty = freshVar
490
+ val ty = freshVar( N )
480
491
map += targ.uid -> ty
481
492
ty
482
493
}
@@ -498,28 +509,28 @@ class BBTyper(using elState: Elaborator.State, tl: TL):
498
509
case Term .Region (sym, body) =>
499
510
val nestCtx = ctx.nextLevel
500
511
given BbCtx = nestCtx
501
- val sk = freshSkolem
512
+ val sk = freshSkolem( S (sym.nme))
502
513
nestCtx += sym -> BbCtx .regionTy(sk)
503
514
val (res, eff) = typeCheck(body)
504
- val tv = freshVar(using ctx)
515
+ val tv = freshVar(N )( using ctx)
505
516
constrain(eff, tv | sk)
506
517
(extrude(res)(using ctx, true ), tv | allocType)
507
518
case Term .RegRef (reg, value) =>
508
519
val (regTy, regEff) = typeCheck(reg)
509
520
val (valTy, valEff) = typeCheck(value)
510
- val sk = freshVar
521
+ val sk = freshVar( N )
511
522
constrain(tryMkMono(regTy, reg), BbCtx .regionTy(sk))
512
523
(BbCtx .refTy(tryMkMono(valTy, value), sk), sk | (regEff | valEff))
513
524
case Term .Assgn (lhs, rhs) =>
514
525
val (lhsTy, lhsEff) = typeCheck(lhs)
515
526
val (rhsTy, rhsEff) = typeCheck(rhs)
516
- val sk = freshVar
527
+ val sk = freshVar( N )
517
528
constrain(tryMkMono(lhsTy, lhs), BbCtx .refTy(tryMkMono(rhsTy, rhs), sk))
518
529
(tryMkMono(rhsTy, rhs), sk | (lhsEff | rhsEff))
519
530
case Term .Deref (ref) =>
520
531
val (refTy, refEff) = typeCheck(ref)
521
- val sk = freshVar
522
- val ctnt = freshVar
532
+ val sk = freshVar( N )
533
+ val ctnt = freshVar( N )
523
534
constrain(tryMkMono(refTy, ref), BbCtx .refTy(ctnt, sk))
524
535
(ctnt, sk | refEff)
525
536
case Term .Quoted (body) =>
0 commit comments