Skip to content

Commit 7fbe62c

Browse files
Fix syntax of (using ..., Type) (hkust-taco#275)
1 parent 62cb284 commit 7fbe62c

File tree

3 files changed

+29
-12
lines changed

3 files changed

+29
-12
lines changed

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1096,9 +1096,9 @@ extends Importer:
10961096
if ctx.outer.isDefined then TermSymbol(k, ctx.outer, id)
10971097
else VarSymbol(id)
10981098

1099-
def param(t: Tree): Ctxl[Opt[Opt[Bool] -> Param]] = t match
1099+
def param(t: Tree, inUsing: Bool): Ctxl[Opt[Opt[Bool] -> Param]] = t match
11001100
case TypeDef(Mod, inner, N, N) =>
1101-
val ps = param(inner).map(_.mapSecond(p => p.copy(flags = p.flags.copy(mod = true))))
1101+
val ps = param(inner, inUsing).map(_.mapSecond(p => p.copy(flags = p.flags.copy(mod = true))))
11021102
for p <- ps if p._2.flags.mod do p._2.sign match
11031103
case N =>
11041104
raise(ErrorReport(msg"Module parameters must have explicit types." -> t.toLoc :: Nil))
@@ -1107,9 +1107,9 @@ extends Importer:
11071107
case _ => ()
11081108
ps
11091109
case TypeDef(Pat, inner, N, N) =>
1110-
param(inner).map(_.mapSecond(p => p.copy(flags = p.flags.copy(pat = true))))
1110+
param(inner, inUsing).map(_.mapSecond(p => p.copy(flags = p.flags.copy(pat = true))))
11111111
case _ =>
1112-
t.asParam.map: (isSpd, p, t) =>
1112+
t.asParam(inUsing).map: (isSpd, p, t) =>
11131113
isSpd -> Param(FldFlags.empty, fieldOrVarSym(ParamBind, p), t.map(term(_)))
11141114

11151115
def params(t: Tree): Ctxl[(ParamList, Ctx)] = t match
@@ -1118,7 +1118,7 @@ extends Importer:
11181118
ps match
11191119
case Nil => (ParamList(flags, acc.reverse, N), ctx)
11201120
case hd :: tl =>
1121-
param(hd)(using ctx) match
1121+
param(hd, flags.ctx)(using ctx) match
11221122
case S((isSpd, p)) =>
11231123
val isCtx = hd match
11241124
case Modified(Keyword.`using`, _, _) => true

hkmc2/shared/src/main/scala/hkmc2/syntax/Tree.scala

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -192,20 +192,25 @@ enum Tree extends AutoLocated:
192192
LetLike(letLike, id, S(App(Ident(nme.init), Tup(id :: r :: Nil))), bodo).withLocOf(this).desugared
193193
case _ => this
194194

195-
/** S(true) means eager spread, S(false) means lazy spread, N means no spread. */
196-
def asParam: Opt[(Opt[Bool], Ident, Opt[Tree])] = this match
195+
/**
196+
* Parameter `inUsing` means the param list is modified by `using`.
197+
* In the first result, `S(true)` means eager spread, `S(false)` means lazy spread, and `N` means no spread.
198+
*/
199+
def asParam(inUsing: Bool): Opt[(Opt[Bool], Ident, Opt[Tree])] = this match
197200
case und: Under => S(N, new Ident("_").withLocOf(und), N)
201+
// * In `using` clauses, identifiers are understood as type names for unnamed contextual parameters:
202+
case id: Ident if inUsing => S(N, Ident(""), S(id))
198203
case id: Ident => S(N, id, N)
199204
case Spread(Keyword.`..`, _, S(id: Ident)) => S(S(false), id, N)
200205
case Spread(Keyword.`...`, _, S(id: Ident)) => S(S(true), id, N)
201206
case Spread(Keyword.`..`, _, S(und: Under)) => S(S(false), new Ident("_").withLocOf(und), N)
202207
case Spread(Keyword.`...`, _, S(und: Under)) => S(S(true), new Ident("_").withLocOf(und), N)
203208
case InfixApp(lhs: Ident, Keyword.`:`, rhs) => S(N, lhs, S(rhs))
204-
case TermDef(ImmutVal, inner, _) => inner.asParam
209+
case TermDef(ImmutVal, inner, _) => inner.asParam(inUsing)
205210
case Modified(Keyword.`using`, _, inner) => inner match
206-
// Param of form (using ..., name: Type). Parse it as usual.
207-
case inner: InfixApp => inner.asParam
208-
// Param of form (using ..., Type). Synthesize an identifier for it.
211+
// Param of form (using name: Type). Parse it as usual.
212+
case inner: InfixApp => inner.asParam(inUsing)
213+
// Param of form (using Type). Synthesize an identifier for it.
209214
case _ => S(N, Ident(""), S(inner))
210215

211216
def isModuleModifier: Bool = this match
@@ -400,7 +405,7 @@ trait TypeDefImpl(using State) extends TypeOrTermDef:
400405

401406
lazy val clsParams: Ls[semantics.TermSymbol] =
402407
this.paramLists.headOption.fold(Nil): tup =>
403-
tup.fields.iterator.flatMap(_.asParam).map:
408+
tup.fields.iterator.flatMap(_.asParam(false)).map:
404409
case (S(spd), id, _) => ??? // spreads are not allowed in class parameters
405410
case (N, id, _) => semantics.TermSymbol(ParamBind, symbol.asClsLike, id)
406411
.toList

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,18 @@ module M with
2424
module M with
2525
fun f(using foo: Int)(using bar: Int) = 42
2626

27+
module M with
28+
fun f(using foo: Int, bar: Int) = 42
29+
30+
module M with
31+
fun f(using Int, Int) = 42
32+
33+
module M with
34+
fun foo(using Int, arg: Str) = 42
35+
36+
module M with
37+
fun foo(using arg: Str, Int) = 42
38+
2739

2840
// Basic Resolution
2941

0 commit comments

Comments
 (0)