Skip to content

Commit 66a700b

Browse files
Fix LLIR
1 parent cd3ac61 commit 66a700b

File tree

11 files changed

+307
-54
lines changed

11 files changed

+307
-54
lines changed

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -760,6 +760,8 @@ class Lowering()(using Config, TL, Raise, State, Ctx):
760760
// * BbML-specific cases: t.Cls#field and mutable operations
761761
case sp @ SelProj(prefix, _, proj) =>
762762
setupSelection(prefix, proj, sp.sym, N)(k)
763+
case Resolved(sp @ SelProj(prefix, _, proj), sym) =>
764+
setupSelection(prefix, proj, sp.sym, S(sym))(k)
763765
case Region(reg, body) =>
764766
Assign(reg, Instantiate(mut = false, Select(Value.Ref(State.globalThisSymbol), Tree.Ident("Region"))(N), Nil),
765767
term_nonTail(body)(k))

hkmc2/shared/src/main/scala/hkmc2/semantics/Elaborator.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -554,7 +554,7 @@ extends Importer:
554554
case _ =>
555555
raise(ErrorReport(msg"Identifier `${idn.name}` does not name a known class symbol." -> idn.toLoc :: Nil))
556556
N
557-
Term.SelProj(subterm(pre), c, idp)(f)
557+
Term.SelProj(subterm(pre), c, idp)(f, N)
558558
case App(Ident("#"), Tup(Sel(pre, Ident(name)) :: App(Ident(proj), args) :: Nil)) =>
559559
subterm(App(App(Ident("#"), Tup(Sel(pre, Ident(name)) :: Ident(proj) :: Nil)), args))
560560
case App(Ident("!"), Tup(rhs :: Nil)) =>
@@ -635,7 +635,7 @@ extends Importer:
635635
)
636636
val rs = FlowSymbol.app()
637637
Term.Lam(ps,
638-
Term.App(Term.SelProj(self.ref(), c, nme)(f), args.ref())(
638+
Term.App(Term.SelProj(self.ref(), c, nme)(f, N), args.ref())(
639639
App(nme, Tup(Nil)) // FIXME
640640
, N, rs)
641641
)

hkmc2/shared/src/main/scala/hkmc2/semantics/Resolver.scala

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -555,13 +555,17 @@ class Resolver(tl: TraceLogger)
555555
targs.foreach(traverse(_, expect = Any))
556556
(t.callableDefn, ictx)
557557

558-
case AnySel(pre: Resolvable, id) =>
558+
case AnySel(pre: Resolvable, id, cls) =>
559559
resolve(pre, prefer = Selectable(N), inAppPrefix = false, inCtxPrefix = false, inTyPrefix = false)
560+
cls.foreach:
561+
case cls: Resolvable => resolve(cls, prefer = Class(N), inAppPrefix = false, inCtxPrefix = false, inTyPrefix = false)
562+
case cls => traverse(cls, expect = Class(N))
560563
resolveSymbol(t, prefer = prefer, sign = false)
561564
resolveType(t, prefer = prefer)
562565
(t.callableDefn, ictx)
563-
case AnySel(pre, id) =>
566+
case AnySel(pre, id, cls) =>
564567
traverse(pre, expect = Selectable(N))
568+
cls.foreach(traverse(_, expect = Class(N)))
565569
(t.callableDefn, ictx)
566570

567571
case Term.Ref(_: BlockMemberSymbol) =>
@@ -842,10 +846,14 @@ class Resolver(tl: TraceLogger)
842846
resolveType(t, prefer = prefer)
843847
log(s"Resolved symbol for ${t}: ${sym}")
844848

845-
case t @ AnySel(lhs: Resolvable, id) => lhs.expandedResolvableIn: lhs =>
849+
case t @ AnySel(lhs: Resolvable, id, cls) => lhs.expandedResolvableIn: lhs =>
846850
log(s"Resolving symbol for selection ${t}, defn = ${lhs.defn}")
847851

848-
// Signleton Definitions
852+
val clsDefn = cls.flatMap: sym =>
853+
sym.resolvedSym.flatMap(_.asCls).map: clsSym =>
854+
clsSym.defn.getOrElse(die)
855+
856+
// Singleton Definitions
849857
lhs.singletonDefn.foreach: defn =>
850858
val fsym = defn.body.members.get(id.name)
851859
fsym match
@@ -867,7 +875,7 @@ class Resolver(tl: TraceLogger)
867875
extraInfo = S(defn))
868876

869877
// Class-Like Definitions
870-
lhs.defn.foreach:
878+
(clsDefn orElse lhs.defn).foreach:
871879
case defn: ClassLikeDef =>
872880
// A reference to a member within the class is elaborated into a SynthSel, e.g.,
873881
// class C with
@@ -1007,8 +1015,8 @@ class Resolver(tl: TraceLogger)
10071015
case Term.App(Term.Ref(_: BuiltinSymbol), Term.Tup(Fld(term = Term.Lit(_)) :: Nil)) =>
10081016

10091017
// Selection. The prefix should be a term, rather than a type, that
1010-
// can be selected from.
1011-
case AnySel(base, _) =>
1018+
// can be selected from. This should not be a selection projection.
1019+
case AnySel(base, _, N) =>
10121020
base.subTerms.foreach(traverse(_, expect = Any))
10131021

10141022
// Type Application. Traverse the type constructor and arguments,
@@ -1132,9 +1140,10 @@ class Resolver(tl: TraceLogger)
11321140
end Resolver
11331141

11341142
object AnySel:
1135-
def unapply(t: (Term.Sel | Term.SynthSel)): S[(Term, Tree.Ident)] = t match
1136-
case Term.Sel(lhs, id) => S((lhs, id))
1137-
case Term.SynthSel(lhs, id) => S((lhs, id))
1143+
def unapply(t: (Term.Sel | Term.SynthSel | Term.SelProj)): S[(Term, Tree.Ident, Opt[Term])] = t match
1144+
case Term.Sel(lhs, id) => S((lhs, id, N))
1145+
case Term.SynthSel(lhs, id) => S((lhs, id, N))
1146+
case Term.SelProj(lhs, cls, proj) => S((lhs, proj, S(cls)))
11381147

11391148
object ModuleChecker:
11401149

hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,15 @@ sealed trait ResolvableImpl:
5959
case t: Term.TyApp => t.copy()(t.typ)
6060
case t: Term.Sel => t.copy()(t.sym, t.typ)
6161
case t: Term.SynthSel => t.copy()(t.sym, t.typ)
62+
case t: Term.SelProj => t.copy()(t.sym, t.typ)
6263
.withLocOf(this)
6364
.asInstanceOf
6465

6566
def withSym(sym: FieldSymbol): this.type =
6667
this.match
6768
case t: Term.Sel => t.copy()(S(sym), t.typ)
6869
case t: Term.SynthSel => t.copy()(S(sym), t.typ)
70+
case t: Term.SelProj => t.copy()(S(sym), t.typ)
6971
case _ => lastWords(s"Cannot attach a symbol to a non-selection term: ${this.show}")
7072
.withLocOf(this)
7173
.asInstanceOf
@@ -78,6 +80,7 @@ sealed trait ResolvableImpl:
7880
case t: Term.TyApp => t.copy()(S(typ))
7981
case t: Term.Sel => t.copy()(t.sym, S(typ))
8082
case t: Term.SynthSel => t.copy()(t.sym, S(typ))
83+
case t: Term.SelProj => t.copy()(t.sym, S(typ))
8184
.withLocOf(this)
8285
.asInstanceOf
8386

@@ -206,6 +209,8 @@ enum Term extends Statement:
206209
(val sym: Opt[FieldSymbol], val typ: Opt[Type]) extends Term, ResolvableImpl
207210
case SynthSel(prefix: Term, nme: Tree.Ident)
208211
(val sym: Opt[FieldSymbol], val typ: Opt[Type]) extends Term, ResolvableImpl
212+
case SelProj(prefix: Term, cls: Term, proj: Tree.Ident)
213+
(val sym: Opt[FieldSymbol], val typ: Opt[Type]) extends Term, ResolvableImpl
209214
case DynSel(prefix: Term, fld: Term, arrayIdx: Bool)
210215
case Tup(fields: Ls[Elem])(val tree: Tree.Tup)
211216
case Mut(underlying: Tup | Rcd | New | DynNew)
@@ -221,7 +226,6 @@ enum Term extends Statement:
221226
case Unquoted(body: Term)
222227
case New(cls: Term, args: Ls[Term], rft: Opt[ClassSymbol -> ObjBody])
223228
case DynNew(cls: Term, args: Ls[Term])
224-
case SelProj(prefix: Term, cls: Term, proj: Tree.Ident)(val sym: Opt[FieldSymbol])
225229
case Asc(term: Term, ty: Term)
226230
case CompType(lhs: Term, rhs: Term, pol: Bool)
227231
case Neg(rhs: Term)
@@ -330,7 +334,7 @@ enum Term extends Statement:
330334
New(cls.mkClone, args.map(_.mkClone), rft.map { case (cs, ob) => cs -> ObjBody(ob.blk.mkBlkClone) })
331335
case DynNew(cls, args) => DynNew(cls.mkClone, args.map(_.mkClone))
332336
case term @ SelProj(prefix, cls, proj) =>
333-
SelProj(prefix.mkClone, cls.mkClone, Tree.Ident(proj.name))(term.sym)
337+
SelProj(prefix.mkClone, cls.mkClone, Tree.Ident(proj.name))(term.sym, term.typ)
334338
case Asc(term, ty) => Asc(term.mkClone, ty.mkClone)
335339
case CompType(lhs, rhs, pol) => CompType(lhs.mkClone, rhs.mkClone, pol)
336340
case Neg(rhs) => Neg(rhs.mkClone)

hkmc2/shared/src/test/mlscript/basics/BadMemberProjections.mls

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
//│ ║ ^
1010
//│ ╟── Note: any expression of the form `‹expression›::‹identifier›` is a member projection;
1111
//│ ╙── add a space before ‹identifier› to make it an operator application.
12+
//│ ╔══[ERROR] Expected a statically known class; found integer literal.
13+
//│ ║ l.6: 1::x
14+
//│ ╙── ^
1215
//│ JS (unsanitized):
1316
//│ let lambda;
1417
//│ lambda = (undefined, function (self, ...args) { return runtime.safeCall(self.x(...args)) });
@@ -20,10 +23,13 @@
2023
:re
2124
1::x()
2225
//│ ╔══[ERROR] Integer literal is not a known class.
23-
//│ ║ l.21: 1::x()
26+
//│ ║ l.24: 1::x()
2427
//│ ║ ^
2528
//│ ╟── Note: any expression of the form `‹expression›::‹identifier›` is a member projection;
2629
//│ ╙── add a space before ‹identifier› to make it an operator application.
30+
//│ ╔══[ERROR] Expected a statically known class; found integer literal.
31+
//│ ║ l.24: 1::x()
32+
//│ ╙── ^
2733
//│ JS:
2834
//│ lambda1 = (undefined, function (...args1) {
2935
//│ runtime.checkArgs("", 1, false, args1.length);
@@ -50,19 +56,25 @@ let x = 1
5056
:e
5157
"A"::x
5258
//│ ╔══[ERROR] String literal is not a known class.
53-
//│ ║ l.51: "A"::x
59+
//│ ║ l.57: "A"::x
5460
//│ ║ ^^^
5561
//│ ╟── Note: any expression of the form `‹expression›::‹identifier›` is a member projection;
5662
//│ ╙── add a space before ‹identifier› to make it an operator application.
63+
//│ ╔══[ERROR] Expected a statically known class; found string literal.
64+
//│ ║ l.57: "A"::x
65+
//│ ╙── ^^^
5766
//│ = fun
5867

5968
:e
6069
"A" ::x
6170
//│ ╔══[ERROR] String literal is not a known class.
62-
//│ ║ l.60: "A" ::x
71+
//│ ║ l.69: "A" ::x
6372
//│ ║ ^^^
6473
//│ ╟── Note: any expression of the form `‹expression›::‹identifier›` is a member projection;
6574
//│ ╙── add a space before ‹identifier› to make it an operator application.
75+
//│ ╔══[ERROR] Expected a statically known class; found string literal.
76+
//│ ║ l.69: "A" ::x
77+
//│ ╙── ^^^
6678
//│ = fun
6779

6880

hkmc2/shared/src/test/mlscript/basics/MemberProjections.mls

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -81,13 +81,14 @@ foo.Foo#m()
8181
//│ ╔══[ERROR] Identifier `Foo` does not name a known class symbol.
8282
//│ ║ l.77: foo.Foo#m()
8383
//│ ╙── ^^^^
84+
//│ ═══[ERROR] Expected a statically known class; found ‹error›.
8485
//│ = 124
8586

8687
:e
8788
:re
8889
foo.M.Foo::m()
8990
//│ ╔══[ERROR] Selection is not a known class.
90-
//│ ║ l.88: foo.M.Foo::m()
91+
//│ ║ l.89: foo.M.Foo::m()
9192
//│ ║ ^^^
9293
//│ ╟── Note: any expression of the form `‹expression›::‹identifier›` is a member projection;
9394
//│ ╙── add a space before ‹identifier› to make it an operator application.
@@ -97,36 +98,39 @@ foo.M.Foo::m()
9798
:re
9899
foo.M.Foo#m()
99100
//│ ╔══[ERROR] Name not found: Foo
100-
//│ ║ l.98: foo.M.Foo#m()
101+
//│ ║ l.99: foo.M.Foo#m()
101102
//│ ╙── ^^^^
102103
//│ ╔══[ERROR] Identifier `Foo` does not name a known class symbol.
103-
//│ ║ l.98: foo.M.Foo#m()
104+
//│ ║ l.99: foo.M.Foo#m()
104105
//│ ╙── ^^^^
106+
//│ ═══[ERROR] Expected a statically known class; found ‹error›.
105107
//│ ═══[RUNTIME ERROR] Error: Access to required field 'M' yielded 'undefined'
106108

107109
:e
108110
Foo::m
109111
//│ ╔══[ERROR] Name not found: Foo
110-
//│ ║ l.108: Foo::m
112+
//│ ║ l.110: Foo::m
111113
//│ ╙── ^^^
112114
//│ ╔══[ERROR] Identifier is not a known class.
113-
//│ ║ l.108: Foo::m
115+
//│ ║ l.110: Foo::m
114116
//│ ║ ^^^
115117
//│ ╟── Note: any expression of the form `‹expression›::‹identifier›` is a member projection;
116118
//│ ╙── add a space before ‹identifier› to make it an operator application.
119+
//│ ═══[ERROR] Expected a statically known class; found ‹error›.
117120
//│ = fun
118121

119122
:e
120123
:sjs
121124
Foo::n(foo, 2)
122125
//│ ╔══[ERROR] Name not found: Foo
123-
//│ ║ l.121: Foo::n(foo, 2)
126+
//│ ║ l.124: Foo::n(foo, 2)
124127
//│ ╙── ^^^
125128
//│ ╔══[ERROR] Identifier is not a known class.
126-
//│ ║ l.121: Foo::n(foo, 2)
129+
//│ ║ l.124: Foo::n(foo, 2)
127130
//│ ║ ^^^
128131
//│ ╟── Note: any expression of the form `‹expression›::‹identifier›` is a member projection;
129132
//│ ╙── add a space before ‹identifier› to make it an operator application.
133+
//│ ═══[ERROR] Expected a statically known class; found ‹error›.
130134
//│ JS (unsanitized):
131135
//│ let lambda9;
132136
//│ lambda9 = (undefined, function (self, ...args) {

hkmc2/shared/src/test/mlscript/bbml/bbErrors.mls

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,27 +27,28 @@
2727
//│ ╔══[ERROR] Identifier `Foo` does not name a known class symbol.
2828
//│ ║ l.23: (1).Foo#a()
2929
//│ ╙── ^^^^
30+
//│ ═══[ERROR] Expected a statically known class; found ‹error›.
3031
//│ ═══[ERROR] Not a valid class: ‹error›
3132
//│ Type: ⊥
3233

3334

3435
fun Oops() = 1
3536
Oops().Oops#a()
3637
//│ ╔══[ERROR] Identifier `Oops` does not name a known class symbol.
37-
//│ ║ l.35: Oops().Oops#a()
38+
//│ ║ l.36: Oops().Oops#a()
3839
//│ ╙── ^^^^^
3940
//│ ╔══[ERROR] Not a valid class: reference
40-
//│ ║ l.35: Oops().Oops#a()
41+
//│ ║ l.36: Oops().Oops#a()
4142
//│ ╙── ^^^^^
4243
//│ Type: ⊥
4344

4445
data class Oops2()
4546
(new Oops2()).Oops2#a()
4647
//│ ╔══[ERROR] Class 'Oops2' does not contain member 'a'.
47-
//│ ║ l.45: (new Oops2()).Oops2#a()
48+
//│ ║ l.46: (new Oops2()).Oops2#a()
4849
//│ ╙── ^
4950
//│ ╔══[ERROR] a is not a valid member in class Oops2
50-
//│ ║ l.45: (new Oops2()).Oops2#a()
51+
//│ ║ l.46: (new Oops2()).Oops2#a()
5152
//│ ╙── ^^^^^^^^^^^^^^^^^^^^
5253
//│ Type: ⊥
5354

@@ -56,7 +57,7 @@ data class Oops2()
5657
fun inc(x) = x + 1
5758
inc("oops")
5859
//│ ╔══[ERROR] Type error in string literal with expected type 'x
59-
//│ ║ l.57: inc("oops")
60+
//│ ║ l.58: inc("oops")
6061
//│ ║ ^^^^^^
6162
//│ ╟── because: cannot constrain Str <: 'x
6263
//│ ╟── because: cannot constrain Str <: 'x
@@ -66,7 +67,7 @@ inc("oops")
6667
fun inc(x) = x + 1
6768
inc as Int
6869
//│ ╔══[ERROR] Type error in reference with expected type Int
69-
//│ ║ l.67: inc as Int
70+
//│ ║ l.68: inc as Int
7071
//│ ║ ^^^
7172
//│ ╙── because: cannot constrain ('x) ->{⊥} (Int) <: Int
7273
//│ Type: Int

hkmc2/shared/src/test/mlscript/llir/Classes.mls

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,26 @@ fun main() =
2424
let d = Derived()
2525
d.Base#get() * d.Derived#get()
2626
main()
27-
//│ FAILURE: Unexpected compilation error
28-
//│ FAILURE LOCATION: bErrStop (Builder.scala:22)
29-
//│ ═══[COMPILATION ERROR] Unsupported kind of Call Call(Select(Ref(d,None),Ident(get)),List())
30-
//│ Stopped due to an error during the Llir generation
27+
//│ LLIR:
28+
//│ class Base() {
29+
//│ def get() =
30+
//│ 1
31+
//│ }
32+
//│ class Derived() extends Base {
33+
//│ def get1() =
34+
//│ 2
35+
//│ }
36+
//│ def main() =
37+
//│ let x = Derived() in
38+
//│ let x1 = Base.get(x) in
39+
//│ let x2 = Derived.get(x) in
40+
//│ let x3 = *(x1,x2) in
41+
//│ x3
42+
//│ def entry() =
43+
//│ let* (x4) = main() in
44+
//│ x4
45+
//│ entry = entry
46+
//│
47+
//│ Interpreted:
48+
//│ 4
3149

0 commit comments

Comments
 (0)