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
337 changes: 337 additions & 0 deletions hkmc2/shared/src/test/mlscript/invalml/invalDP.mls
Original file line number Diff line number Diff line change
@@ -0,0 +1,337 @@
:js

:global
:invalml


declare class Array[T]

fun mkArray: [T] -> () -> Array[T]
fun mkArray() = @untyped globalThis.Array()

fun mkArrayWith: [T] -> (T, Int) -> Array[T]
fun mkArrayWith(iv, size) = @untyped globalThis.Array(size).fill(iv)

fun at: [T] -> (Array[T], Int) -> T
fun at(xs, i) = @untyped xs.at(i)

fun splice: [T] -> (Array[T], Int, T) -> ()
fun splice(xs, i, v) = @untyped xs.splice(i, 1, v); ()

class Option[A] with
constructor
Some(x: A)
None()


class ArrayList[T, out R](val d: Array[T])
class Iter[T, out R](val arr: Array[T], val i: Ref[Int, out R], val step: Int, val end: Int)
class Array2D[T, out R](val d: Array[Array[T]])

class Interviewee with
constructor
Itv(score: Int, salary: Int)


fun debug: Any -> ()
fun debug(s) = @untyped print(s)


fun (;) seq(_, res) = res

fun toString: Any -> Str
fun toString(x) = @untyped x.toString()

fun concat: (Str, Str) -> Str
fun concat(x, y) = @untyped x + y

fun println: Str -> ()
fun println(s) = @untyped print(s)

fun empty: [A, R] -> Region[out R] ->{R} ArrayList[A, out R]
fun empty(r) = new ArrayList(mkArray())

fun push: [A, R] -> (ArrayList[A, out R], A) ->{R} ()
fun push(arr, e) = @untyped arr.ArrayList#d.push(e); ()

fun len: [A, R] -> (ArrayList[A, out R]) ->{R} Int
fun len(arr) = @untyped arr.ArrayList#d.length

fun iter: [Res, R, E extends ~R, T] -> (ArrayList[T, out R], [S] -> Iter[T, S] ->{S | E} Res) ->{E | R} Res
fun iter(arr, f) =
region r in f(new Iter(arr.ArrayList#d, (r.ref 0), 1, len(arr)))

fun revIter: [Res, R, E extends ~R, T] -> (ArrayList[T, out R], [S] -> Iter[T, S] ->{S | E} Res) ->{E | R} Res
fun revIter(arr, f) =
region r in f(new Iter(arr.ArrayList#d, (r.ref (len(arr) - 1)), 0 - 1, 0 - 1))

fun next: [T, S] -> Iter[T, S] ->{S} Option[T]
fun next(it) =
let i = !it.Iter#i
if i == it.Iter#end then None()
else
let res = Some(at of it.Iter#arr, i)
it.Iter#i := i + it.Iter#step
res

fun whileDo: [R] -> (() ->{R} Bool) ->{R} ()
fun whileDo(f) =
if f() then whileDo(f) else ()

fun init: [A, R] -> (Region[out R], Int, Int, A) ->{R} Array2D[A, R]
fun init(r, d1, d2, iv) =
let res = new Array2D(mkArrayWith(mkArrayWith(iv, d2), d1))
region r in
let i = r.ref 0
whileDo of () =>
if !i == d1 then false
else
splice(res.Array2D#d, !i, mkArrayWith(iv, d2))
i := !i + 1
true
res

fun update: [A, R] -> (Array2D[A, out R], Int, Int, A) ->{R} ()
fun update(arr, d1, d2, v) = splice(at(arr.Array2D#d, d1), d2, v)

fun get: [A, R] -> (Array2D[A, out R], Int, Int) ->{R} A
fun get(arr, d1, d2) = at(at(arr.Array2D#d, d1), d2)

fun max: (Int, Int) -> Int
fun max(x, y) = if x > y then x else y


fun format(it) =
if it is Itv(score, salary) then
concat("interviewee score: ", concat(toString(score), concat(", salary: ", toString(salary))))


fun printAll(arr) =
iter of arr, it =>
whileDo of () =>
if next(it) is
Some(x) then println(format(x)); true
None then false


fun select: [outer, R1 extends outer, R2 extends ~R1] -> (ArrayList[Interviewee, R1], Int, ArrayList[Interviewee, R2]) ->{R1 | R2} Int
fun select(interviewees, budget, results) =
region r in
let size = len(interviewees), let i = r.ref 1
let dp = init(r, size + 1, budget + 1, 0)
iter of interviewees, it => whileDo of () =>
if next(it) is
Some(itv) then if itv is Itv(score, salary) then
let j = r.ref 0
whileDo of () =>
if !j < salary then update(dp, !i, !j, get(dp, !i - 1, !j))
else
let p = get(dp, !i - 1, !j - salary), let np = get(dp, !i - 1, !j)
update(dp, !i, !j, max of np, p + score)
j := !j + 1; !j <= budget
i := !i + 1
true
None then false
i := size
let rest = r.ref budget
revIter of interviewees, it =>
whileDo of () =>
if next(it) is
Some(itv) then if itv is Itv(score, salary) then
if get(dp, !i, !rest) == get(dp, !i - 1, !rest - salary) + score
do push(results, itv); rest := !rest - salary
i := !i - 1
true
None then false
get(dp, size, budget)

select
// //│ Type: [outer, 'A, 'R, 'T, 'R1, 'T1, 'T2, 'R2, 'A1, 'R3] -> ((ArrayList[in 'T1 out 'T2, out 'R2] ∧ ArrayList[in 'T out Interviewee ∧ 'T, out 'R1]) ∧ ArrayList['A, out 'R], Int, ArrayList['A1, out 'R3]) ->{(('R2 ∨ 'R3) ∨ 'R1) ∨ 'R} Int
// //│ Where:
// //│ 'T <: Interviewee
// //│ 'T <: 'T1
// //│ 'R <: outer
// //│ 'R1 <: outer
// //│ 'T <: 'A
// //│ 'R2 <: ¬'R
//│ = [function select]
//│ Type: [outer, 'R1, 'R2] -> (ArrayList[Interviewee, out 'R1], Int, ArrayList[Interviewee, out 'R2]) ->{'R1 ∨ 'R2} Int
//│ Where:
//│ 'R1 <: outer
//│ 'R2 <: ¬'R1

region r in
let interviewees = empty(r)
push(interviewees, Itv(20, 3))
push(interviewees, Itv(50, 1))
push(interviewees, Itv(30, 1))
println("all interviewees:")
printAll(interviewees)
region r2 in
let results = empty(r2)
let m = select(interviewees, 4, results)
println("candidates:")
printAll(results)
m
//│ > all interviewees:
//│ > interviewee score: 20, salary: 3
//│ > interviewee score: 50, salary: 1
//│ > interviewee score: 30, salary: 1
//│ > candidates:
//│ > interviewee score: 30, salary: 1
//│ > interviewee score: 50, salary: 1
//│ = 80
//│ Type: Int


region r in
let interviewees = empty(r)
push(interviewees, Itv(100, 71))
push(interviewees, Itv(1, 69))
push(interviewees, Itv(2, 1))
println("all interviewees:")
printAll(interviewees)
region r2 in
let results = empty(r2)
let m = select(interviewees, 70, results)
println("candidates:")
printAll(results)
m
//│ > all interviewees:
//│ > interviewee score: 100, salary: 71
//│ > interviewee score: 1, salary: 69
//│ > interviewee score: 2, salary: 1
//│ > candidates:
//│ > interviewee score: 2, salary: 1
//│ > interviewee score: 1, salary: 69
//│ = 3
//│ Type: Int


region r in
let interviewees = empty(r)
push(interviewees, Itv(40, 10))
push(interviewees, Itv(60, 20))
push(interviewees, Itv(120, 30))
push(interviewees, Itv(70, 20))
println("all interviewees:")
printAll(interviewees)
region r2 in
let results = empty(r2)
let m = select(interviewees, 60, results)
println("candidates:")
printAll(results)
m
//│ > all interviewees:
//│ > interviewee score: 40, salary: 10
//│ > interviewee score: 60, salary: 20
//│ > interviewee score: 120, salary: 30
//│ > interviewee score: 70, salary: 20
//│ > candidates:
//│ > interviewee score: 70, salary: 20
//│ > interviewee score: 120, salary: 30
//│ > interviewee score: 40, salary: 10
//│ = 230
//│ Type: Int


:e
region r in
let interviewees = empty(r)
push(interviewees, Itv(20, 3))
push(interviewees, Itv(50, 1))
push(interviewees, Itv(30, 1))
let results = empty(r)
let m = select(interviewees, 4, results)
println("candidates:")
printAll(results)
m
// //│ ╔══[ERROR] Type error in reference with expected type 'results
// //│ ║ l.110: let m = select(interviewees, 4000, results)
// //│ ║ ^^^^^^^
// //│ ╟── because: cannot constrain ArrayList['A, in ⊥ out 'R] <: 'results
// //│ ╟── because: cannot constrain ArrayList['A, in ⊥ out 'R] <: ArrayList['A1, in ⊥ out 'R1]
// //│ ╟── because: cannot constrain 'R <: 'R1
// //│ ╟── because: cannot constrain 'R <: ¬'R2
// //│ ╟── because: cannot constrain 'R2 <: ¬'R
// //│ ╟── because: cannot constrain 'R3 <: ¬'R
// //│ ╟── because: cannot constrain 'R <: ¬'R3
// //│ ╟── because: cannot constrain r <: ¬'R3
// //│ ╟── because: cannot constrain 'R3 <: ¬r
// //│ ╙── because: cannot constrain r <: ¬r
// //│ Type: Int
//│ > candidates:
//│ > interviewee score: 30, salary: 1
//│ > interviewee score: 50, salary: 1
//│ = 80
//│ ╔══[ERROR] Type error in reference with expected type ArrayList[Interviewee, out 'R2]
//│ ║ l.245: let m = select(interviewees, 4, results)
//│ ║ ^^^^^^^
//│ ╟── because: cannot constrain ArrayList['A, in ⊥ out 'R] <: ArrayList[Interviewee, in ⊥ out 'R2]
//│ ╟── because: cannot constrain 'R <: 'R2
//│ ╟── because: cannot constrain 'R <: ¬'R1
//│ ╟── because: cannot constrain 'R1 <: ¬'R
//│ ╟── because: cannot constrain 'R3 <: ¬'R
//│ ╟── because: cannot constrain 'R <: ¬'R3
//│ ╟── because: cannot constrain r <: ¬'R3
//│ ╟── because: cannot constrain 'R3 <: ¬r
//│ ╙── because: cannot constrain r <: ¬r
//│ Type: Int


fun wrongSelect(interviewees, budget, results) =
region r in
let size = len(interviewees), let i = r.ref 1
let dp = init(r, size + 1, budget + 1, 0)
iter of interviewees, it =>
whileDo of () =>
if next(it) is
Some(itv) then if itv is Itv(score, salary) then
let j = r.ref 0
whileDo of () =>
if !j < salary then update(dp, !i, !j, get(dp, !i - 1, !j))
else
let p = get(dp, !i - 1, !j - salary), let np = get(dp, !i - 1, !j)
update(dp, !i, !j, max of np, p + score)
j := !j + 1; !j <= budget
i := !i + 1
true
None then false
i := size
let rest = r.ref budget
revIter of interviewees, it =>
whileDo of () =>
if next(it) is
Some(itv) then if itv is Itv(score, salary) then
if get(dp, !i, !rest) == get(dp, !i - 1, !rest - salary) + score
do push(interviewees, itv); rest := !rest - salary
i := !i - 1
true
None then false
get(dp, size, budget)

:e
region r in
let interviewees = empty(r)
push(interviewees, Itv(20, 3000))
push(interviewees, Itv(50, 1000))
push(interviewees, Itv(30, 1000))
region r2 in
let results = empty(r2)
let m = wrongSelect(interviewees, 4000, results)
println("candidates:")
printAll(results)
m
//│ > candidates:
//│ = 80
//│ ╔══[ERROR] Type error in reference with expected type 'interviewees
//│ ║ l.321: let m = wrongSelect(interviewees, 4000, results)
//│ ║ ^^^^^^^^^^^^
//│ ╟── because: cannot constrain ArrayList['A, in ⊥ out 'R] <: 'interviewees
//│ ╟── because: cannot constrain ArrayList['A, in ⊥ out 'R] <: ArrayList[in 'T out 'T1, in ⊥ out 'R1]
//│ ╟── because: cannot constrain 'R <: 'R1
//│ ╟── because: cannot constrain 'R <: ¬'R
//│ ╟── because: cannot constrain 'R <: ⊥
//│ ╙── because: cannot constrain r <: ⊥
//│ Type: Int

Loading
Loading