Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions hkmc2/shared/src/main/scala/hkmc2/semantics/Elaborator.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1096,9 +1096,9 @@ extends Importer:
if ctx.outer.isDefined then TermSymbol(k, ctx.outer, id)
else VarSymbol(id)

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

def params(t: Tree): Ctxl[(ParamList, Ctx)] = t match
Expand All @@ -1118,7 +1118,7 @@ extends Importer:
ps match
case Nil => (ParamList(flags, acc.reverse, N), ctx)
case hd :: tl =>
param(hd)(using ctx) match
param(hd, flags.ctx)(using ctx) match
case S((isSpd, p)) =>
val isCtx = hd match
case Modified(Keyword.`using`, _, _) => true
Expand Down
19 changes: 12 additions & 7 deletions hkmc2/shared/src/main/scala/hkmc2/syntax/Tree.scala
Original file line number Diff line number Diff line change
Expand Up @@ -192,20 +192,25 @@ enum Tree extends AutoLocated:
LetLike(letLike, id, S(App(Ident(nme.init), Tup(id :: r :: Nil))), bodo).withLocOf(this).desugared
case _ => this

/** S(true) means eager spread, S(false) means lazy spread, N means no spread. */
def asParam: Opt[(Opt[Bool], Ident, Opt[Tree])] = this match
/**
* Parameter `inUsing` means the param list is modified by `using`.
* In the first result, `S(true)` means eager spread, `S(false)` means lazy spread, and `N` means no spread.
*/
def asParam(inUsing: Bool): Opt[(Opt[Bool], Ident, Opt[Tree])] = this match
case und: Under => S(N, new Ident("_").withLocOf(und), N)
// * In `using` clauses, identifiers are understood as type names for unnamed contextual parameters:
case id: Ident if inUsing => S(N, Ident(""), S(id))
case id: Ident => S(N, id, N)
case Spread(Keyword.`..`, _, S(id: Ident)) => S(S(false), id, N)
case Spread(Keyword.`...`, _, S(id: Ident)) => S(S(true), id, N)
case Spread(Keyword.`..`, _, S(und: Under)) => S(S(false), new Ident("_").withLocOf(und), N)
case Spread(Keyword.`...`, _, S(und: Under)) => S(S(true), new Ident("_").withLocOf(und), N)
case InfixApp(lhs: Ident, Keyword.`:`, rhs) => S(N, lhs, S(rhs))
case TermDef(ImmutVal, inner, _) => inner.asParam
case TermDef(ImmutVal, inner, _) => inner.asParam(inUsing)
case Modified(Keyword.`using`, _, inner) => inner match
// Param of form (using ..., name: Type). Parse it as usual.
case inner: InfixApp => inner.asParam
// Param of form (using ..., Type). Synthesize an identifier for it.
// Param of form (using name: Type). Parse it as usual.
case inner: InfixApp => inner.asParam(inUsing)
// Param of form (using Type). Synthesize an identifier for it.
case _ => S(N, Ident(""), S(inner))

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

lazy val clsParams: Ls[semantics.TermSymbol] =
this.paramLists.headOption.fold(Nil): tup =>
tup.fields.iterator.flatMap(_.asParam).map:
tup.fields.iterator.flatMap(_.asParam(false)).map:
case (S(spd), id, _) => ??? // spreads are not allowed in class parameters
case (N, id, _) => semantics.TermSymbol(ParamBind, symbol.asClsLike, id)
.toList
Expand Down
12 changes: 12 additions & 0 deletions hkmc2/shared/src/test/mlscript/basics/TypeClasses.mls
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,18 @@ module M with
module M with
fun f(using foo: Int)(using bar: Int) = 42

module M with
fun f(using foo: Int, bar: Int) = 42

module M with
fun f(using Int, Int) = 42

module M with
fun foo(using Int, arg: Str) = 42

module M with
fun foo(using arg: Str, Int) = 42


// Basic Resolution

Expand Down
Loading