Skip to content

Commit b9e4151

Browse files
Enforce module parameters to receive only module arguments
1 parent 933af7c commit b9e4151

File tree

3 files changed

+44
-10
lines changed

3 files changed

+44
-10
lines changed

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

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,33 @@ extends Importer:
232232
term(rhs)
233233
case tree @ App(lhs, rhs) =>
234234
val sym = FlowSymbol("‹app-res›", nextUid)
235-
Term.App(term(lhs), term(rhs))(tree, sym)
235+
val lt = term(lhs)
236+
val rt = term(rhs)
237+
238+
// Check module parameters
239+
val args = rt match
240+
case Term.Tup(fields) => S(fields)
241+
case _ => N
242+
val argsModFlags = args
243+
.map(_.map(_.flags.mod))
244+
val paramsModFlags = lt.symbol match
245+
case S(sym: BlockMemberSymbol) => sym.defn match
246+
case S(defn: TermDefinition) => defn.params.lift(0)
247+
.map(_.params.map(_.flags.mod))
248+
case _ => argsModFlags.map(_.map(_ => false))
249+
case _ => argsModFlags.map(_.map(_ => false))
250+
for
251+
(argLists, amfs, pmfs) <- (args lazyZip argsModFlags lazyZip paramsModFlags)
252+
(a, amf, pmf) <- (argLists lazyZip amfs lazyZip pmfs)
253+
if amf && !pmf
254+
do
255+
log(s"${a.value}")
256+
raise(ErrorReport(
257+
msg"Module values can only be passed to module parameters." -> a.toLoc
258+
:: Nil,
259+
))
260+
261+
Term.App(lt, rt)(tree, sym)
236262
case Sel(pre, nme) =>
237263
val preTrm = term(pre)
238264
val sym = resolveField(nme, preTrm.symbol, nme)
@@ -325,8 +351,12 @@ extends Importer:
325351
def fld(tree: Tree): Ctxl[Fld] = tree match
326352
case InfixApp(lhs, Keyword.`:`, rhs) =>
327353
Fld(FldFlags.empty, term(lhs), S(term(rhs)))
328-
case _ => Fld(FldFlags.empty, term(tree), N)
329-
354+
case _ =>
355+
val t = term(tree)
356+
t.symbol.flatMap(_.asMod) match
357+
case S(_) => Fld(FldFlags.module, t, N)
358+
case N => Fld(FldFlags.empty, t, N)
359+
330360
def unit: Term.Lit = Term.Lit(UnitLit(true))
331361

332362

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,7 @@ final case class Param(flags: FldFlags, sym: LocalSymbol & NamedSymbol, sign: Op
311311
object FldFlags {
312312
val empty: FldFlags = FldFlags(false, false, false, false)
313313

314-
// module parameter
314+
// module parameter / module argument, depending on the context
315315
val module: FldFlags = FldFlags(false, false, false, true)
316316
}
317317

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

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,9 @@ f1(new C)
124124
// Error: module values can only be passed to module parameters.
125125
:e
126126
f1(M)
127+
//│ ╔══[ERROR] Module values can only be passed to module parameters.
128+
//│ ║ l.126: f1(M)
129+
//│ ╙── ^
127130
//│ Elaborated tree:
128131
//│ Blk:
129132
//│ stats = Nil
@@ -133,12 +136,11 @@ f1(M)
133136
//│ nme = Ident of "f1"
134137
//│ rhs = Tup of Ls of
135138
//│ Fld:
136-
//│ flags = ()
139+
//│ flags = (module)
137140
//│ value = Sel:
138141
//│ prefix = Ref of globalThis:block#1
139142
//│ nme = Ident of "M"
140143
//│ asc = N
141-
//│ FAILURE: Unexpected lack of type error
142144

143145

144146
// Good: m is a module parameter, therefore the module method foo can be called on m.
@@ -206,7 +208,7 @@ f2(M)
206208
//│ nme = Ident of "f2"
207209
//│ rhs = Tup of Ls of
208210
//│ Fld:
209-
//│ flags = ()
211+
//│ flags = (module)
210212
//│ value = Sel:
211213
//│ prefix = Ref of globalThis:block#1
212214
//│ nme = Ident of "M"
@@ -276,6 +278,9 @@ fun id[T](t: T): T = t
276278
// Error: Module values can only be passed to module parameters.
277279
:e
278280
id(IntMT)
281+
//│ ╔══[ERROR] Module values can only be passed to module parameters.
282+
//│ ║ l.280: id(IntMT)
283+
//│ ╙── ^^^^^
279284
//│ Elaborated tree:
280285
//│ Blk:
281286
//│ stats = Nil
@@ -285,12 +290,11 @@ id(IntMT)
285290
//│ nme = Ident of "id"
286291
//│ rhs = Tup of Ls of
287292
//│ Fld:
288-
//│ flags = ()
293+
//│ flags = (module)
289294
//│ value = Sel:
290295
//│ prefix = Ref of globalThis:block#9
291296
//│ nme = Ident of "IntMT"
292297
//│ asc = N
293-
//│ FAILURE: Unexpected lack of type error
294298

295299

296300
// Good: module parameters must have an explicit and concrete type.
@@ -330,7 +334,7 @@ idMod(IntMT)
330334
//│ nme = Ident of "idMod"
331335
//│ rhs = Tup of Ls of
332336
//│ Fld:
333-
//│ flags = ()
337+
//│ flags = (module)
334338
//│ value = Sel:
335339
//│ prefix = Ref of globalThis:block#9
336340
//│ nme = Ident of "IntMT"

0 commit comments

Comments
 (0)