Skip to content

Commit 6e0238b

Browse files
Separate module methods from regular methods
1 parent 59ede6f commit 6e0238b

File tree

5 files changed

+214
-12
lines changed

5 files changed

+214
-12
lines changed

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -407,13 +407,13 @@ class BBTyper(using elState: Elaborator.State, tl: TL):
407407
effBuff += eff
408408
nestCtx += sym -> rhsTy
409409
goStats(stats)
410-
case TermDefinition(_, Fun, sym, ParamList(_, ps) :: Nil, sig, Some(body), _) :: stats =>
410+
case TermDefinition(_, Fun, sym, ParamList(_, ps) :: Nil, sig, Some(body), _, _) :: stats =>
411411
typeFunDef(sym, Term.Lam(ps, body), sig, ctx)
412412
goStats(stats)
413-
case TermDefinition(_, Fun, sym, Nil, sig, Some(body), _) :: stats =>
413+
case TermDefinition(_, Fun, sym, Nil, sig, Some(body), _, _) :: stats =>
414414
typeFunDef(sym, body, sig, ctx) // * may be a case expressions
415415
goStats(stats)
416-
case TermDefinition(_, Fun, sym, _, S(sig), None, _) :: stats =>
416+
case TermDefinition(_, Fun, sym, _, S(sig), None, _, _) :: stats =>
417417
ctx += sym -> typeType(sig)
418418
goStats(stats)
419419
case (clsDef: ClassDef) :: stats =>

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,7 @@ extends Importer:
471471
case R(id) =>
472472
val sym = members.getOrElse(id.name, die)
473473
val owner = ctx.outer
474+
val isModMember = owner.fold(false)(_.isInstanceOf[ModuleSymbol])
474475
val tdf = ctx.nest(N).givenIn:
475476
// * Add type parameters to context
476477
val (tps, newCtx1) = td.typeParams match
@@ -485,7 +486,8 @@ extends Importer:
485486
val b = rhs.map(term(_)(using newCtx))
486487
val r = FlowSymbol(s"‹result of ${sym}", nextUid)
487488
val tdf = TermDefinition(owner, k, sym, pss,
488-
td.signature.orElse(newSignatureTrees.get(id.name)).map(term), b, r)
489+
td.signature.orElse(newSignatureTrees.get(id.name)).map(term), b, r,
490+
TermDefFlags(isModMember))
489491
sym.defn = S(tdf)
490492
tdf
491493
go(sts, tdf :: acc)
@@ -654,7 +656,7 @@ extends Importer:
654656
def computeVariances(s: Statement): Unit =
655657
val trav = VarianceTraverser()
656658
def go(s: Statement): Unit = s match
657-
case TermDefinition(_, k, sym, pss, sign, body, r) =>
659+
case TermDefinition(_, k, sym, pss, sign, body, r, _) =>
658660
pss.foreach(ps => ps.params.foreach(trav.traverseType(S(false))))
659661
sign.foreach(trav.traverseType(S(true)))
660662
body match

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

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package semantics
33

44
import mlscript.utils.*, shorthands.*
55
import syntax.*
6+
import scala.collection.mutable.Buffer
67

78

89
final case class QuantVar(sym: VarSymbol, ub: Opt[Term], lb: Opt[Term])
@@ -101,7 +102,7 @@ sealed trait Statement extends AutoLocated:
101102
case RegRef(reg, value) => reg :: value :: Nil
102103
case Assgn(lhs, rhs) => lhs :: rhs :: Nil
103104
case Deref(term) => term :: Nil
104-
case TermDefinition(_, k, _, ps, sign, body, res) =>
105+
case TermDefinition(_, k, _, ps, sign, body, res, _) =>
105106
ps.toList.flatMap(_.subTerms) ::: sign.toList ::: body.toList
106107
case cls: ClassDef =>
107108
cls.paramsOpt.toList.flatMap(_.flatMap(_.subTerms)) ::: cls.body.blk :: Nil
@@ -169,7 +170,7 @@ sealed trait Statement extends AutoLocated:
169170
case CompType(lhs, rhs, pol) => s"${lhs.showDbg} ${if pol then "|" else "&"} ${rhs.showDbg}"
170171
case Error => "<error>"
171172
case Tup(fields) => fields.map(_.showDbg).mkString("[", ", ", "]")
172-
case TermDefinition(_, k, sym, ps, sign, body, res) => s"${k.str} ${sym}${
173+
case TermDefinition(_, k, sym, ps, sign, body, res, flags) => s"${flags} ${k.str} ${sym}${
173174
ps.map(_.showDbg).mkString("")
174175
}${sign.fold("")(": "+_.showDbg)}${
175176
body match
@@ -186,6 +187,15 @@ final case class LetDecl(sym: LocalSymbol) extends Statement
186187

187188
final case class DefineVar(sym: LocalSymbol, rhs: Term) extends Statement
188189

190+
final case class TermDefFlags(mod: Bool):
191+
def showDbg: Str =
192+
val flags = Buffer.empty[String]
193+
if mod then flags += "module"
194+
flags.mkString(" ")
195+
override def toString: String = "" + showDbg + ""
196+
197+
object TermDefFlags { val empty: TermDefFlags = TermDefFlags(false) }
198+
189199
final case class TermDefinition(
190200
owner: Opt[InnerSymbol],
191201
k: TermDefKind,
@@ -194,6 +204,7 @@ final case class TermDefinition(
194204
sign: Opt[Term],
195205
body: Opt[Term],
196206
resSym: FlowSymbol,
207+
flags: TermDefFlags,
197208
) extends Companion
198209

199210
case class ObjBody(blk: Term.Blk):
@@ -273,8 +284,14 @@ case class TypeDef(
273284

274285

275286
// TODO Store optional source locations for the flags instead of booleans
276-
final case class FldFlags(mut: Bool, spec: Bool, genGetter: Bool):
277-
def showDbg: Str = (if mut then "mut " else "") + (if spec then "spec " else "") + (if genGetter then "val " else "")
287+
final case class FldFlags(mut: Bool, spec: Bool, genGetter: Bool, mod: Bool):
288+
def showDbg: Str =
289+
val flags = Buffer.empty[String]
290+
if mut then flags += "mut"
291+
if spec then flags += "spec"
292+
if genGetter then flags += "gen"
293+
if mod then flags += "module"
294+
flags.mkString(" ")
278295
override def toString: String = "" + showDbg + ""
279296

280297
final case class Fld(flags: FldFlags, value: Term, asc: Opt[Term]) extends FldImpl
@@ -298,7 +315,7 @@ final case class Param(flags: FldFlags, sym: LocalSymbol & NamedSymbol, sign: Op
298315
// def showDbg: Str = flags.showDbg + sym.name + ": " + sign.showDbg
299316
def showDbg: Str = flags.showDbg + sym + sign.fold("")(": " + _.showDbg)
300317

301-
object FldFlags { val empty: FldFlags = FldFlags(false, false, false) }
318+
object FldFlags { val empty: FldFlags = FldFlags(false, false, false, false) }
302319

303320
final case class ParamListFlags(ctx: Bool):
304321
def showDbg: Str = (if ctx then "ctx " else "")

hkmc2/shared/src/main/scala/hkmc2/utils/utils.scala

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ extension (s: String)
2020
.mkString("\"", "", "\"")
2121

2222

23+
import hkmc2.semantics.TermDefFlags
2324
import hkmc2.semantics.FldFlags
2425
import scala.collection.mutable.Buffer
2526
import mlscript.utils.StringOps
@@ -36,12 +37,17 @@ extension (t: Product)
3637
case Nil => "Nil"
3738
case xs: List[_] => "Ls of \n" + xs.iterator.map(aux(_)).mkString("\n").indent(" ")
3839
case s: String => s.escaped
39-
case FldFlags(mut, spec, genGetter) =>
40+
case TermDefFlags(mod) =>
41+
val flags = Buffer.empty[String]
42+
if mod then flags += "module"
43+
flags.mkString("(", ", ", ")")
44+
case FldFlags(mut, spec, genGetter, mod) =>
4045
val flags = Buffer.empty[String]
4146
if mut then flags += "mut"
4247
if spec then flags += "spec"
4348
if genGetter then flags += "gen"
44-
if flags.isEmpty then "()" else flags.mkString("(", ", ", ")")
49+
if mod then flags += "module"
50+
flags.mkString("(", ", ", ")")
4551
case t: Product => t.showAsTree(inTailPos)
4652
case v => v.toString
4753
val postfix = post(t)
Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
class C with {
2+
// regular method foo
3+
fun foo(x) = x
4+
}
5+
6+
module M with {
7+
// module method foo
8+
fun foo(x) = x
9+
// module method self that returns itself
10+
fun self(): module M = M
11+
}
12+
//│ FAILURE: Unexpected exception
13+
//│ /!!!\ Uncaught error: java.lang.Exception: Internal Error: keyword 'module' does not have right precedence
14+
//│ at: mlscript.utils.package$.lastWords(package.scala:211)
15+
//│ at: hkmc2.syntax.Keyword.assumeRightPrec$$anonfun$1(Keyword.scala:31)
16+
//│ at: scala.Option.getOrElse(Option.scala:201)
17+
//│ at: hkmc2.syntax.Keyword.assumeRightPrec(Keyword.scala:31)
18+
//│ at: hkmc2.syntax.Parser.parseRuleImpl(Parser.scala:351)
19+
//│ at: hkmc2.syntax.Parser.parseRule$$anonfun$2(Parser.scala:321)
20+
//│ at: hkmc2.syntax.Parser.wrap(Parser.scala:129)
21+
//│ at: hkmc2.syntax.Parser.parseRule(Parser.scala:321)
22+
//│ at: hkmc2.syntax.Parser.expr(Parser.scala:460)
23+
//│ at: hkmc2.syntax.Parser.exprContImpl(Parser.scala:921)
24+
25+
:e
26+
fun f1(module m)
27+
//│ FAILURE: Unexpected exception
28+
//│ /!!!\ Uncaught error: scala.MatchError: TypeDef(Mod,Ident(m),None,None) (of class hkmc2.syntax.Tree$TypeDef)
29+
//│ at: hkmc2.semantics.Elaborator.param(Elaborator.scala:610)
30+
//│ at: hkmc2.semantics.Elaborator.$anonfun$19(Elaborator.scala:614)
31+
//│ at: scala.collection.immutable.List.flatMap(List.scala:294)
32+
//│ at: hkmc2.semantics.Elaborator.params(Elaborator.scala:614)
33+
//│ at: hkmc2.semantics.Elaborator.$anonfun$10(Elaborator.scala:484)
34+
//│ at: scala.collection.LinearSeqOps.foldLeft(LinearSeq.scala:183)
35+
//│ at: scala.collection.LinearSeqOps.foldLeft$(LinearSeq.scala:179)
36+
//│ at: scala.collection.immutable.List.foldLeft(List.scala:79)
37+
//│ at: hkmc2.semantics.Elaborator.go$2(Elaborator.scala:483)
38+
//│ at: hkmc2.semantics.Elaborator.block$$anonfun$3(Elaborator.scala:597)
39+
40+
:e
41+
fun f2[T](module m: T)
42+
//│ FAILURE: Unexpected exception
43+
//│ /!!!\ Uncaught error: scala.MatchError: TypeDef(Mod,InfixApp(Ident(m),keyword ':',Ident(T)),None,None) (of class hkmc2.syntax.Tree$TypeDef)
44+
//│ at: hkmc2.semantics.Elaborator.param(Elaborator.scala:610)
45+
//│ at: hkmc2.semantics.Elaborator.$anonfun$19(Elaborator.scala:614)
46+
//│ at: scala.collection.immutable.List.flatMap(List.scala:294)
47+
//│ at: hkmc2.semantics.Elaborator.params(Elaborator.scala:614)
48+
//│ at: hkmc2.semantics.Elaborator.$anonfun$10(Elaborator.scala:484)
49+
//│ at: scala.collection.LinearSeqOps.foldLeft(LinearSeq.scala:183)
50+
//│ at: scala.collection.LinearSeqOps.foldLeft$(LinearSeq.scala:179)
51+
//│ at: scala.collection.immutable.List.foldLeft(List.scala:79)
52+
//│ at: hkmc2.semantics.Elaborator.go$2(Elaborator.scala:483)
53+
//│ at: hkmc2.semantics.Elaborator.block$$anonfun$3(Elaborator.scala:597)
54+
55+
:e
56+
module N with {
57+
fun f3(): M = M
58+
}
59+
//│ ╔══[ERROR] Name not found: M
60+
//│ ║ l.57: fun f3(): M = M
61+
//│ ╙── ^
62+
//│ ╔══[ERROR] Name not found: M
63+
//│ ║ l.57: fun f3(): M = M
64+
//│ ╙── ^
65+
66+
:e
67+
module N with {
68+
fun f4[T](): module T = M
69+
}
70+
//│ FAILURE: Unexpected exception
71+
//│ /!!!\ Uncaught error: java.lang.Exception: Internal Error: keyword 'module' does not have right precedence
72+
//│ at: mlscript.utils.package$.lastWords(package.scala:211)
73+
//│ at: hkmc2.syntax.Keyword.assumeRightPrec$$anonfun$1(Keyword.scala:31)
74+
//│ at: scala.Option.getOrElse(Option.scala:201)
75+
//│ at: hkmc2.syntax.Keyword.assumeRightPrec(Keyword.scala:31)
76+
//│ at: hkmc2.syntax.Parser.parseRuleImpl(Parser.scala:351)
77+
//│ at: hkmc2.syntax.Parser.parseRule$$anonfun$2(Parser.scala:321)
78+
//│ at: hkmc2.syntax.Parser.wrap(Parser.scala:129)
79+
//│ at: hkmc2.syntax.Parser.parseRule(Parser.scala:321)
80+
//│ at: hkmc2.syntax.Parser.expr(Parser.scala:460)
81+
//│ at: hkmc2.syntax.Parser.exprContImpl(Parser.scala:921)
82+
83+
:e
84+
module N with {
85+
fun f5(): M = M
86+
}
87+
//│ ╔══[ERROR] Name not found: M
88+
//│ ║ l.85: fun f5(): M = M
89+
//│ ╙── ^
90+
//│ ╔══[ERROR] Name not found: M
91+
//│ ║ l.85: fun f5(): M = M
92+
//│ ╙── ^
93+
94+
95+
fun f6(m: M)
96+
//│ FAILURE: Unexpected type error
97+
//│ ╔══[ERROR] Name not found: M
98+
//│ ║ l.95: fun f6(m: M)
99+
//│ ╙── ^
100+
101+
:e
102+
f6(M)
103+
//│ ╔══[ERROR] Name not found: M
104+
//│ ║ l.102: f6(M)
105+
//│ ╙── ^
106+
107+
:e
108+
f6(M.self())
109+
//│ ╔══[ERROR] Name not found: M
110+
//│ ║ l.108: f6(M.self())
111+
//│ ╙── ^
112+
113+
:e
114+
fun f7(): module M
115+
//│ FAILURE: Unexpected exception
116+
//│ /!!!\ Uncaught error: java.lang.Exception: Internal Error: keyword 'module' does not have right precedence
117+
//│ at: mlscript.utils.package$.lastWords(package.scala:211)
118+
//│ at: hkmc2.syntax.Keyword.assumeRightPrec$$anonfun$1(Keyword.scala:31)
119+
//│ at: scala.Option.getOrElse(Option.scala:201)
120+
//│ at: hkmc2.syntax.Keyword.assumeRightPrec(Keyword.scala:31)
121+
//│ at: hkmc2.syntax.Parser.parseRuleImpl(Parser.scala:351)
122+
//│ at: hkmc2.syntax.Parser.parseRule$$anonfun$2(Parser.scala:321)
123+
//│ at: hkmc2.syntax.Parser.wrap(Parser.scala:129)
124+
//│ at: hkmc2.syntax.Parser.parseRule(Parser.scala:321)
125+
//│ at: hkmc2.syntax.Parser.expr(Parser.scala:460)
126+
//│ at: hkmc2.syntax.Parser.exprContImpl(Parser.scala:921)
127+
128+
129+
fun ok1(module m: M)
130+
//│ FAILURE: Unexpected exception
131+
//│ /!!!\ Uncaught error: scala.MatchError: TypeDef(Mod,InfixApp(Ident(m),keyword ':',Ident(M)),None,None) (of class hkmc2.syntax.Tree$TypeDef)
132+
//│ at: hkmc2.semantics.Elaborator.param(Elaborator.scala:610)
133+
//│ at: hkmc2.semantics.Elaborator.$anonfun$19(Elaborator.scala:614)
134+
//│ at: scala.collection.immutable.List.flatMap(List.scala:294)
135+
//│ at: hkmc2.semantics.Elaborator.params(Elaborator.scala:614)
136+
//│ at: hkmc2.semantics.Elaborator.$anonfun$10(Elaborator.scala:484)
137+
//│ at: scala.collection.LinearSeqOps.foldLeft(LinearSeq.scala:183)
138+
//│ at: scala.collection.LinearSeqOps.foldLeft$(LinearSeq.scala:179)
139+
//│ at: scala.collection.immutable.List.foldLeft(List.scala:79)
140+
//│ at: hkmc2.semantics.Elaborator.go$2(Elaborator.scala:483)
141+
//│ at: hkmc2.semantics.Elaborator.block$$anonfun$3(Elaborator.scala:597)
142+
143+
module N with {
144+
fun ok2(): module M = M
145+
}
146+
//│ FAILURE: Unexpected exception
147+
//│ /!!!\ Uncaught error: java.lang.Exception: Internal Error: keyword 'module' does not have right precedence
148+
//│ at: mlscript.utils.package$.lastWords(package.scala:211)
149+
//│ at: hkmc2.syntax.Keyword.assumeRightPrec$$anonfun$1(Keyword.scala:31)
150+
//│ at: scala.Option.getOrElse(Option.scala:201)
151+
//│ at: hkmc2.syntax.Keyword.assumeRightPrec(Keyword.scala:31)
152+
//│ at: hkmc2.syntax.Parser.parseRuleImpl(Parser.scala:351)
153+
//│ at: hkmc2.syntax.Parser.parseRule$$anonfun$2(Parser.scala:321)
154+
//│ at: hkmc2.syntax.Parser.wrap(Parser.scala:129)
155+
//│ at: hkmc2.syntax.Parser.parseRule(Parser.scala:321)
156+
//│ at: hkmc2.syntax.Parser.expr(Parser.scala:460)
157+
//│ at: hkmc2.syntax.Parser.exprContImpl(Parser.scala:921)
158+
159+
ok1(M)
160+
//│ FAILURE: Unexpected type error
161+
//│ ╔══[ERROR] Name not found: ok1
162+
//│ ║ l.159: ok1(M)
163+
//│ ╙── ^^^
164+
//│ FAILURE: Unexpected type error
165+
//│ ╔══[ERROR] Name not found: M
166+
//│ ║ l.159: ok1(M)
167+
//│ ╙── ^
168+
169+
ok1(M.self())
170+
//│ FAILURE: Unexpected type error
171+
//│ ╔══[ERROR] Name not found: ok1
172+
//│ ║ l.169: ok1(M.self())
173+
//│ ╙── ^^^
174+
//│ FAILURE: Unexpected type error
175+
//│ ╔══[ERROR] Name not found: M
176+
//│ ║ l.169: ok1(M.self())
177+
//│ ╙── ^

0 commit comments

Comments
 (0)