Skip to content

Commit e4508ae

Browse files
Enforce rules on module arguments
1 parent edbc565 commit e4508ae

File tree

14 files changed

+74
-29
lines changed

14 files changed

+74
-29
lines changed

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

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,34 @@ extends Importer:
259259
term(rhs)
260260
case tree @ App(lhs, rhs) =>
261261
val sym = FlowSymbol("‹app-res›", nextUid)
262-
Term.App(term(lhs), term(rhs))(tree, sym)
262+
val lt = term(lhs)
263+
val rt = term(rhs)
264+
265+
// Check if module arguments match module parameters
266+
val args = rt match
267+
case Term.Tup(fields) => S(fields)
268+
case _ => N
269+
val params = lt.symbol
270+
.collect:
271+
case sym: BlockMemberSymbol => sym.trmTree
272+
.flatten
273+
.collect:
274+
case td: TermDef => td.paramLists.headOption
275+
.flatten
276+
for
277+
(args, params) <- (args zip params)
278+
(arg, param) <- (args zip params.fields)
279+
do
280+
val argMod = arg.flags.mod
281+
val paramMod = param match
282+
case Tree.TypeDef(Mod, _, N, N) => true
283+
case _ => false
284+
if argMod && !paramMod then raise:
285+
ErrorReport:
286+
msg"Only module parameters may receive module arguments (values)." ->
287+
arg.toLoc :: Nil
288+
289+
Term.App(lt, rt)(tree, sym)
263290
case Sel(pre, nme) =>
264291
val preTrm = term(pre)
265292
val sym = resolveField(nme, preTrm.symbol, nme)
@@ -356,9 +383,10 @@ extends Importer:
356383
Fld(FldFlags.empty, term(lhs), S(term(rhs)))
357384
case _ =>
358385
val t = term(tree)
359-
t.symbol.flatMap(_.asMod) match
360-
case S(_) => Fld(FldFlags.empty.copy(mod = true), t, N)
361-
case N => Fld(FldFlags.empty, t, N)
386+
val flags = FldFlags.empty
387+
if ModuleChecker.evalsToModule(t)
388+
then Fld(flags.copy(mod = true), t, N)
389+
else Fld(flags, t, N)
362390

363391
def unit: Term.Lit = Term.Lit(UnitLit(true))
364392

hkmc2/shared/src/test/mlscript-compile/Stack.mls

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
module Stack with ...
66

77
class (::) Cons[A](head: A, tail)
8-
module Nil
8+
object Nil
99

1010
fun isEmpty(xs) = xs is Nil
1111

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

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,48 +6,65 @@ class C with {
66
module M with {
77
// module method foo
88
fun foo(x) = x
9+
// module method self
10+
fun self(): module M = M
911
}
1012

1113
:e
1214
fun f1(module m)
1315
//│ ╔══[ERROR] Module parameters must have explicit types.
14-
//│ ║ l.12: fun f1(module m)
16+
//│ ║ l.14: fun f1(module m)
1517
//│ ╙── ^
1618

1719
:e
1820
fun f2[T](module m: T)
1921
//│ ╔══[ERROR] Module parameters must have concrete types.
20-
//│ ║ l.18: fun f2[T](module m: T)
22+
//│ ║ l.20: fun f2[T](module m: T)
2123
//│ ╙── ^^^^
2224

2325
:e
2426
module N with {
2527
fun f3() = M
2628
}
2729
//│ ╔══[ERROR] Function returning module values must have explicit return types.
28-
//│ ║ l.25: fun f3() = M
30+
//│ ║ l.27: fun f3() = M
2931
//│ ╙── ^^^^
3032

3133
:e
3234
module N with {
3335
fun f4[T](): module T = M
3436
}
3537
//│ ╔══[ERROR] Function returning module values must have explicit return types.
36-
//│ ║ l.33: fun f4[T](): module T = M
38+
//│ ║ l.35: fun f4[T](): module T = M
3739
//│ ╙── ^^^^^^^^^^^^^^^^^
3840

3941
:e
4042
module N with {
4143
fun f5(): M = M
4244
}
4345
//│ ╔══[ERROR] The return type of functions returning module values must be prefixed with module keyword.
44-
//│ ║ l.41: fun f5(): M = M
46+
//│ ║ l.43: fun f5(): M = M
4547
//│ ╙── ^^^^^^^
4648

49+
50+
fun f6(m: M)
51+
52+
:e
53+
f6(M)
54+
//│ ╔══[ERROR] Only module parameters may receive module arguments (values).
55+
//│ ║ l.53: f6(M)
56+
//│ ╙── ^
57+
58+
:e
59+
f6(M.self())
60+
//│ ╔══[ERROR] Only module parameters may receive module arguments (values).
61+
//│ ║ l.59: f6(M.self())
62+
//│ ╙── ^^^^^^^^
63+
4764
:e
4865
fun f7(): module M
4966
//│ ╔══[ERROR] Only module methods may return module values.
50-
//│ ║ l.48: fun f7(): module M
67+
//│ ║ l.65: fun f7(): module M
5168
//│ ╙── ^^^^^^^^^^^^^^
5269

5370

hkmc2/shared/src/test/mlscript/codegen/ClassMatching.mls

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
class Some[out A](value: A)
88

9-
module None
9+
object None
1010

1111

1212
:sjs

hkmc2/shared/src/test/mlscript/codegen/ModuleMatching.mls

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
:js
22

33

4-
module Foo
4+
object Foo
55

66
fun test(x) = x is Foo
77

@@ -10,7 +10,7 @@ test(Foo)
1010

1111

1212
fun foo() =
13-
module Foo
13+
object Foo
1414
Foo is Foo
1515

1616
foo()

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
// TODO could use `globalThis.Example` instead of `this` in the generated code
55
:sjs
6-
module Example with
6+
object Example with
77
val a = 456
88
fun f(x) = [x, a]
99
//│ JS:

hkmc2/shared/src/test/mlscript/codegen/OptMatch.mls

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33

44
class Some(value)
5-
module None
5+
object None
66

77

88
:sjs

hkmc2/shared/src/test/mlscript/codegen/ThisCallVariations.mls

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
//│ Imported 2 member(s)
55

66

7-
module Example with
7+
object Example with
88
val a = 1
99
fun f(x) = [x, a]
1010

hkmc2/shared/src/test/mlscript/ucs/examples/BinarySearchTree.mls

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ fun abs(x) = if x < 0 then -x else x
1414

1515
abstract class Option[T]: (Some[T] | None)
1616
class Some[T](val value: T) extends Option[T]
17-
module None extends Option[nothing]
17+
object None extends Option[nothing]
1818

1919
fun (??) getOrElse(o, v) = if o is
2020
Some(v') then v'
@@ -24,15 +24,15 @@ let anyToString = toString
2424

2525
abstract class List[out T]: (Cons[T] | Nil)
2626
class Cons[out T](val head: T, val tail: List[T]) extends List[T]
27-
module Nil extends List[nothing]
27+
object Nil extends List[nothing]
2828

2929
fun (::) cons(head, tail) = Cons(head, tail)
3030

3131
1 :: 2 :: 3 :: 4 :: Nil
3232

3333
abstract class Tree[out A]: (Empty | Node[A])
3434
class Node[out A](value: A, left: Tree[A], right: Tree[A]) extends Tree[A]
35-
module Empty extends Tree
35+
object Empty extends Tree
3636

3737
fun single(v) = Node(v, Empty, Empty)
3838

hkmc2/shared/src/test/mlscript/ucs/examples/LeftistTree.mls

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,21 @@ fun abs(x) = if x < 0 then -x else x
1212

1313
abstract class Option[out T]: (Some[T] | None)
1414
class Some[out T](val value: T) extends Option[T]
15-
module None extends Option[nothing]
15+
object None extends Option[nothing]
1616

1717
fun (??) getOrElse(o, v) = if o is
1818
Some(v') then v'
1919
None then v
2020

2121
abstract class List[out T]: (Cons[T] | Nil)
2222
class Cons[out T](val head: T, val tail: List[T]) extends List[T]
23-
module Nil extends List[nothing]
23+
object Nil extends List[nothing]
2424

2525
fun (::) cons(head, tail) = Cons(head, tail)
2626

2727
abstract class Tree[out A]: (Empty | Node[A])
2828
class Node[out A](value: A, left: Tree[A], right: Tree[A], rank: Int) extends Tree[A]
29-
module Empty extends Tree[nothing]
29+
object Empty extends Tree[nothing]
3030

3131
fun show(t: Tree[Any]): Str = if t is
3232
Node(v, l, r, _) then

hkmc2/shared/src/test/mlscript/ucs/examples/SimpleTree.mls

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22

33
type Option[out A] = Some[A] | None
44
class Some[out A](value: A)
5-
module None
5+
object None
66

77
type Tree[out A] = Node[A] | Empty
8-
module Empty
8+
object Empty
99
class Node[out A](value: A, left: Tree[A], right: Tree[A])
1010

1111
fun find(t, v) = if t is

hkmc2/shared/src/test/mlscript/ucs/general/DualOptions.mls

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
abstract class Option[T]
99
class Some[T](value: T) extends Option[T]
10-
module None extends Option[nothing]
10+
object None extends Option[nothing]
1111
class Pair[A, B](x: A, y: B)
1212

1313
// All `add_n` functions should be inferred to have the same type.

hkmc2/shared/src/test/mlscript/ucs/hygiene/HygienicBindings.mls

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@ fun error = ()
55
fun (~~>) expect(a, b) = if a == b then () else error
66

77
type Option[out T] = None | Some[T]
8-
module None
8+
object None
99
class Some[out T](val value: T)
1010

1111
type Either[A, B] = Left[A] | Right[B]
1212
class Left[A](val leftValue: A)
1313
class Right[B](val rightValue: B)
1414

1515
type List[out A] = Nil | Cons[A]
16-
module Nil
16+
object Nil
1717
class Cons[out A](head: A, tail: List[A])
1818

1919
fun justTrue(_) = true

hkmc2/shared/src/test/mlscript/ucs/syntax/SimpleUCS.mls

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
abstract class Option[A]: Some[A] | None
44
class Some[A](value: A) extends Option[A]
5-
module None extends Option
5+
object None extends Option
66

77
abstract class Either[out A, out B]: Left[A] | Right[B]
88
class Left[A](leftValue: A) extends Either[A, nothing]

0 commit comments

Comments
 (0)