Skip to content
Draft
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
b5bdd5b
Basic adt typing and fix subst pol
NeilKleistGao May 20, 2025
e8d47a0
Support type parameters
NeilKleistGao May 21, 2025
37d6f63
Distinguish generic ctors from normal ones
NeilKleistGao May 22, 2025
921a079
WIP: Add pattern matching
NeilKleistGao May 22, 2025
75c2afd
Add docs
NeilKleistGao May 23, 2025
5850017
Merge branch 'hkmc2' into adt💬
LPTK May 27, 2025
929a49a
Deal with merge conflicts
chengluyu May 27, 2025
056e138
WIP from meeting
LPTK May 28, 2025
0c534f1
Add proper Unit type
LPTK May 28, 2025
a36c6d2
Elaborate example a bit
LPTK May 28, 2025
973afbc
Reject non-variable pattern args for now
NeilKleistGao May 28, 2025
8b259cf
WIP: Fix
NeilKleistGao May 28, 2025
37a60a3
WIP: Rerun test
NeilKleistGao May 29, 2025
0194f4d
Use mutable set for cache and have more test cases
NeilKleistGao May 29, 2025
7b77eef
Add more spaces for Paper example
NeilKleistGao May 29, 2025
8999fec
Add example test file
LPTK May 30, 2025
8febb63
Changes from meeting
LPTK May 30, 2025
36560d2
Fix missing cases
NeilKleistGao May 30, 2025
27038a7
W
LPTK May 30, 2025
94bf051
W
LPTK May 30, 2025
d0915ba
Merge remote-tracking branch 'NeilKleistGao/adt💬' into adt💬
LPTK May 30, 2025
096f282
Add pmsort
NeilKleistGao May 30, 2025
84f4712
Merge
NeilKleistGao May 30, 2025
b6ddcaf
Add a clean version
NeilKleistGao May 30, 2025
d318440
Remove difftests things for now
NeilKleistGao May 30, 2025
2783f5f
Add more examples
NeilKleistGao May 30, 2025
9f48b1e
Fix problems in ExamplesInResponse.mls
LPTK Jun 2, 2025
15e5fcb
Add equivalent sig
LPTK Jun 2, 2025
4fbb6ea
Port some examples from flix
NeilKleistGao Jun 6, 2025
8be7290
Port GUI example from flix
NeilKleistGao Jun 9, 2025
1a3b41d
Add extension examples
NeilKleistGao Jun 9, 2025
9ada6c8
Categorize examples and add more documentations
NeilKleistGao Jun 10, 2025
4e8a8a1
Add else type check
NeilKleistGao Jun 16, 2025
717a864
Merge
NeilKleistGao Jun 17, 2025
2788340
WIP: Add decl-site variance
NeilKleistGao Jun 17, 2025
c0198de
Add test for pat-mat
NeilKleistGao Jun 19, 2025
3c1abef
Changes from meeting + some older changes (start making the constrain…
LPTK Jun 24, 2025
60e27b3
Merge from hkmc2
NeilKleistGao Jun 25, 2025
cd6b77c
Rename
NeilKleistGao Jun 25, 2025
a5f3219
Make region targ covariant
NeilKleistGao Jul 3, 2025
afc5e74
Merge branch 'hkmc2' of github.com:hkust-taco/mlscript into adt💬
NeilKleistGao Jul 22, 2025
32a98c0
Add case study examples
NeilKleistGao Jul 23, 2025
3cd0c3a
WIP: Add codegen for constraint solver (without tests) and minor fix
NeilKleistGao Jul 24, 2025
9cb9f26
Some fix
NeilKleistGao Jul 25, 2025
4c6c366
Update web demo code
NeilKleistGao Jul 30, 2025
240a555
Add missing updates
NeilKleistGao Aug 20, 2025
522f9c1
Minor
NeilKleistGao Aug 21, 2025
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
16 changes: 15 additions & 1 deletion hkmc2/shared/src/main/scala/hkmc2/bbml/bbML.scala
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,11 @@ class BBTyper(using elState: Elaborator.State, tl: TL):
// A temporary solution for ADT matching exhausive checking
// `adtCtors` maps IDs of ADTs to their constructors' IDs
// `adtParent` maps constructors' IDs to the ADT class symbol they belong to
// `typeNames` maintains all type names
// since we need to reject all non-variable patterns in ADT match for now
private val adtCtors = HashMap.empty[Uid[Symbol], ListBuffer[Uid[Symbol]]]
private val adtParent = HashMap.empty[Uid[Symbol], Symbol]
private val typeNames = HashSet.empty[Str]

private def freshSkolem(sym: Symbol, hint: Str = "")(using ctx: BbCtx): InfVar =
InfVar(ctx.lvl, infVarState.nextUid, new VarState(), true)(sym, hint)
Expand Down Expand Up @@ -115,6 +118,8 @@ class BBTyper(using elState: Elaborator.State, tl: TL):
adtCtors += pSym.uid -> ListBuffer(cSym.uid)
else adtCtors(pSym.uid) += cSym.uid
adtParent += cSym.uid -> pSym
typeNames.add(pSym.nme)
typeNames.add(cSym.nme)

private def typeAndSubstType
(ty: Term, pol: Bool)(using map: Map[Uid[Symbol], TypeArg])(using ctx: BbCtx, cctx: CCtx)
Expand Down Expand Up @@ -336,6 +341,13 @@ class BBTyper(using elState: Elaborator.State, tl: TL):
val map = HashMap[Uid[Symbol], TypeArg]()
pattern match
case Pattern.ResolvedClassOrModule(sym, paramsOpt) =>
paramsOpt.foreach: params =>
params.foreach:
case (_, p, _) => p match
case Under() => ()
case Ident(nme) if !typeNames(nme) => ()
case _ =>
error(msg"Pattern ${p.toString} is not supported yet." -> split.toLoc :: Nil)
val clsTy = adtParent.get(sym.uid).flatMap(_.asCls.flatMap(_.defn)) match
case S(cls) =>
ClassLikeType(cls.sym, cls.tparams.map(_ => freshWildcard(sym)))
Expand Down Expand Up @@ -372,7 +384,7 @@ class BBTyper(using elState: Elaborator.State, tl: TL):
params.iterator.zip(paramList).foreach:
case (p, Param(_, _, S(ty), _)) =>
nestCtx += p.scrutinee -> typeAndSubstType(ty, true)(using map.toMap)
val (consTy, consEff, _) = typeADTMatch(cons, sign)(using nestCtx)
val (consTy, consEff) = typeAllSplits(cons, sign)(using nestCtx)
val (altsTy, altsEff, altCases) = typeADTMatch(alts, sign)
val allEff = scrutineeEff | (consEff | altsEff)
(sign.getOrElse(tryMkMono(consTy, cons) | tryMkMono(altsTy, alts)), allEff, sym :: altCases)
Expand Down Expand Up @@ -621,11 +633,13 @@ class BBTyper(using elState: Elaborator.State, tl: TL):
ctx += td.sym -> typeType(sig)
goStats(stats)
case (clsDef: ClassDef) :: stats =>
typeNames.add(clsDef.sym.nme)
clsDef.ext match
case S(Term.New(ty, _, N)) => createADTCtor(clsDef, ty)
case _ => ()
goStats(stats)
case (modDef: ModuleDef) :: stats =>
typeNames.add(modDef.sym.nme)
goStats(stats)
case Import(sym, pth) :: stats =>
goStats(stats) // TODO:
Expand Down
74 changes: 49 additions & 25 deletions hkmc2/shared/src/test/mlscript/bbml/ConSolver.mls
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,16 @@ class Iter[T, R]
fun

// empty: [A, R] -> Region[R] ->{R} ArrayList[out A, out R] // TODO investigate: why does this break things?
empty: [A, R] -> Region[R] ->{R} ArrayList[A, R]
empty: [A, R] -> Region[R] ->{R} ArrayList[A, out R]

clear: [A, R] -> (ArrayList[A, R]) ->{R} ()
push: [A, R] -> (ArrayList[A, R], A) ->{R} ()
clear: [A, R] -> (ArrayList[A, out R]) ->{R} ()
push: [A, R] -> (ArrayList[A, out R], A) ->{R} ()
foreach: [E, R, T] -> (Iter[T, R], T ->{E} ()) ->{R | E} ()
iter: [Res, R, E extends ~R, T] ->
(ArrayList[T, R], [S] -> Iter[T, S] ->{S | E} Res) ->{E | R} Res
(ArrayList[T, out R], [S] -> Iter[T, S] ->{S | E} Res) ->{E | R} Res

push
//│ Type: ['A, 'R] -> (ArrayList['A, 'R], 'A) ->{'R} ()
//│ Type: ['A, 'R] -> (ArrayList['A, out 'R], 'A) ->{'R} ()


class Type[R] with
Expand All @@ -55,6 +55,24 @@ fun pp = case
pp(ty)
//│ Type: Str


:e
fun matchP = case
Pair(IntType, IntType) then ()
//│ ╔══[ERROR] Pattern Ident(IntType) is not supported yet.
//│ ║ l.61: Pair(IntType, IntType) then ()
//│ ╙── ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//│ ╔══[ERROR] Pattern Ident(IntType) is not supported yet.
//│ ║ l.61: Pair(IntType, IntType) then ()
//│ ╙── ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//│ ╔══[ERROR] Expect 3 cases, but 1 got.
//│ ║ l.61: Pair(IntType, IntType) then ()
//│ ╙── ^^^^^^^^^^^^^^^^
//│ ╔══[ERROR] Expect 3 cases, but 1 got.
//│ ║ l.61: Pair(IntType, IntType) then ()
//│ ╙── ^^^^^^^^^^^^^^^^^^^^^^^^^


fun error() = error()

fun solve = case
Expand All @@ -81,12 +99,10 @@ solve
//│ Where:
//│ ⊥ <: 'Fun
//│ 'Fun <: ⊤
//│ 'Fun <: ⊥
//│ 'Fun <: 'Fun
//│ ⊥ <: 'Fun
//│ 'Fun <: ⊤
//│ 'Fun <: 'Fun
//│ 'Fun <: ⊥
//│ 'Fun <: 'Unif
//│ 'Fun <: 'Unif
//│ 'Fun <: 'eff
Expand All @@ -99,12 +115,9 @@ solve
//│ 'eff1 <: 'eff
//│ 'Unif <: 'eff
//│ 'Unif <: 'eff1
//│ 'Unif <: ⊥



Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's not change the whitespace.



solve(Cons(Pair(ty, ty), Nil))


// * Paper example
Expand All @@ -113,9 +126,7 @@ solve
region r in
let xs = empty(r)
xs
//│ Type: ArrayList['A, in 'R]
//│ Where:
//│ 'R <: ⊥
//│ Type: ArrayList['A, ?]

region r in
let xs = empty(r)
Expand All @@ -135,7 +146,7 @@ region r in // This is used to delimit the scope of mutation
push(xs, "1"); push(xs, "2"); push(xs, "3")
iter(xs, it => foreach(it, e => println(e); clear(xs)))
//│ ╔══[ERROR] Type error in function literal with expected type (Iter['T, S]) ->{S ∨ 'E} 'Res
//│ ║ l.136: iter(xs, it => foreach(it, e => println(e); clear(xs)))
//│ ║ l.163: iter(xs, it => foreach(it, e => println(e); clear(xs)))
//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//│ ╟── because: cannot constrain 'R ∨ 'E1 <: S ∨ 'E
//│ ╟── because: cannot constrain 'E1 <: 'E ∨ S
Expand Down Expand Up @@ -163,8 +174,6 @@ fun test(x) = case

test
//│ Type: ['Unif] -> ⊤ -> (((Type[out 'Unif] ∧ Type[?]) ∧ Type[?]) ->{'Unif} ())
//│ Where:
//│ 'Unif <: ⊥



Expand All @@ -190,22 +199,21 @@ fun solve = case
// Handle unification case here
error() // Placeholder for unification logic
//│ ╔══[ERROR] Expect 3 cases, but 1 got.
//│ ║ l.182: IntType then ()
//│ ║ l.207: IntType then ()
//│ ║ ^^^^^^^^^^^^^^^
//│ ║ l.183: else error()
//│ ║ l.208: else error()
//│ ╙── ^^^^^^^^^^^^^^^^^^^^^^
//│ ╔══[ERROR] Expect 3 cases, but 1 got.
//│ ║ l.185: Fun(l2, r2) then
//│ ║ l.210: Fun(l2, r2) then
//│ ║ ^^^^^^^^^^^^^^^^
//│ ║ l.186: solve(Cons(Pair(l2, l1), cs))
//│ ║ l.211: solve(Cons(Pair(l2, l1), cs))
//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//│ ║ l.187: solve(Cons(Pair(r1, r2), cs))
//│ ║ l.212: solve(Cons(Pair(r1, r2), cs))
//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//│ ║ l.188: else error()
//│ ║ l.213: else error()
//│ ╙── ^^^^^^^^^^^^^^^^^^^^^^

// Q: why is it not complaining, here?
// :fixme
:fixme
fun solve = case
Nil then ()
Cons(c, cs) and c is
Expand All @@ -221,6 +229,22 @@ fun solve = case
Unif(id, lbs, ubs) then
// Handle unification case here
error() // Placeholder for unification logic
//│ ╔══[ERROR] Expect 3 cases, but 1 got.
//│ ║ l.238: IntType then ()
//│ ║ ^^^^^^^^^^^^^^^
//│ ║ l.239: else error()
//│ ╙── ^^^^^^^^^^^^^^^^^^^^
//│ ╔══[ERROR] Expect 3 cases, but 1 got.
//│ ║ l.240: Fun(l1, r1) and rhs is
//│ ║ ^^^^^^^^^^^^^^^^^^
//│ ║ l.241: Fun(l2, r2) then
//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^
//│ ║ l.242: solve(Cons(Pair(l2, l1), cs))
//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//│ ║ l.243: solve(Cons(Pair(r1, r2), cs))
//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//│ ║ l.244: else error()
//│ ╙── ^^^^^^^^^^^^^^^^^^^^

solve
//│ Type: (Stack[out PairOf[out Type[?], out Type[?]]] ∧ Stack[?]) -> ()
Expand Down
Loading