Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix JuvixTree unification #3087

Merged
merged 4 commits into from
Oct 9, 2024
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
28 changes: 4 additions & 24 deletions src/Juvix/Compiler/Tree/Extra/Type.hs
Original file line number Diff line number Diff line change
Expand Up @@ -35,17 +35,11 @@ curryType ty = case typeArgs ty of
[] ->
ty
tyargs ->
let ty' = curryType (typeTarget ty)
in foldr (\tyarg ty'' -> mkTypeFun [tyarg] ty'') (typeTarget ty') tyargs
foldr (\tyarg ty'' -> mkTypeFun [tyarg] ty'') (curryType (typeTarget ty)) tyargs

isSubtype :: Type -> Type -> Bool
isSubtype ty1 ty2 =
let (ty1', ty2') =
if
| typeTarget (uncurryType ty1) == TyDynamic || typeTarget (uncurryType ty2) == TyDynamic ->
(curryType ty1, curryType ty2)
| otherwise ->
(ty1, ty2)
let (ty1', ty2') = (curryType ty1, curryType ty2)
in case (ty1', ty2') of
(TyDynamic, _) -> True
(_, TyDynamic) -> True
Expand Down Expand Up @@ -96,12 +90,7 @@ isSubtype ty1 ty2 =

unifyTypes :: forall t e r. (Members '[Error TreeError, Reader (Maybe Location), Reader (InfoTable' t e)] r) => Type -> Type -> Sem r Type
unifyTypes ty1 ty2 =
let (ty1', ty2') =
if
| typeTarget (uncurryType ty1) == TyDynamic || typeTarget (uncurryType ty2) == TyDynamic ->
(curryType ty1, curryType ty2)
| otherwise ->
(ty1, ty2)
let (ty1', ty2') = (curryType ty1, curryType ty2)
in case (ty1', ty2') of
(TyDynamic, x) -> return x
(x, TyDynamic) -> return x
Expand Down Expand Up @@ -171,13 +160,4 @@ unifyTypes' :: forall t e r. (Member (Error TreeError) r) => Maybe Location -> I
unifyTypes' loc tab ty1 ty2 =
runReader loc $
runReader tab $
-- The `if` is to ensure correct behaviour with dynamic type targets. E.g.
-- `(A, B) -> *` should unify with `A -> B -> C -> D`.
if
| tgt1 == TyDynamic || tgt2 == TyDynamic ->
unifyTypes @t @e (curryType ty1) (curryType ty2)
| otherwise ->
unifyTypes @t @e ty1 ty2
where
tgt1 = typeTarget (uncurryType ty1)
tgt2 = typeTarget (uncurryType ty2)
unifyTypes @t @e ty1 ty2
7 changes: 6 additions & 1 deletion test/Tree/Eval/Positive.hs
Original file line number Diff line number Diff line change
Expand Up @@ -244,5 +244,10 @@ tests =
"Test041: Type unification"
$(mkRelDir ".")
$(mkRelFile "test041.jvt")
$(mkRelFile "out/test041.out")
$(mkRelFile "out/test041.out"),
PosTest
"Test042: Uncurried function type unification"
$(mkRelDir ".")
$(mkRelFile "test042.jvt")
$(mkRelFile "out/test042.out")
]
1 change: 1 addition & 0 deletions tests/Tree/positive/out/test042.out
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
true
25 changes: 25 additions & 0 deletions tests/Tree/positive/test042.jvt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
type Eq {
mkEq : ((*, *) → bool) → Eq;
}

function lambda_app(f : (*, *) → bool, a : *, b : *) : bool {
ccall(f, a, b)
}

function spec(Eq) : Eq {
alloc[mkEq](calloc[lambda_app](case[Eq](arg[0]) {
mkEq: save {
tmp[0].mkEq[0]
}
}))
}

function cmp(integer, integer) : bool {
lt(arg[0], arg[1])
}

function main() : bool {
save(call[spec](alloc[mkEq](calloc[cmp]()))) {
ccall(tmp[0].mkEq[0], 1, 2)
}
}
Loading