Skip to content

Commit c65dcee

Browse files
committed
kind based tests
1 parent a6533b0 commit c65dcee

File tree

2 files changed

+115
-1
lines changed

2 files changed

+115
-1
lines changed
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
unitL : forall {a b : Type, id : Name} .
1+
unitL : forall {a b : Type, id : Name} .
22
*(FloatArray id) -> (exists {id1 : Name} . *(FloatArray id1) -> b) -> b
33
unitL t f = clone (share t) as x in f x
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
{-# LANGUAGE ImplicitParams #-}
2+
3+
module Language.Granule.Checker.KindSpec where
4+
5+
import Test.Hspec
6+
7+
import Control.Monad.State.Strict
8+
9+
import Language.Granule.Checker.Kinding
10+
import Language.Granule.Checker.Monad
11+
import Language.Granule.Checker.Predicates
12+
import Language.Granule.Checker.Primitives as Primitives
13+
import Language.Granule.Checker.DataTypes
14+
import Language.Granule.Syntax.Identifiers
15+
import Language.Granule.Syntax.Type
16+
17+
import Data.List (sort)
18+
19+
spec :: Spec
20+
spec = let ?globals = mempty in do
21+
describe "typeVarsOfKind" $ do
22+
23+
it "extracts type variables of kind Type from a simple type" $ do
24+
result <- evalChecker initState $ do
25+
-- Register primitives
26+
_ <- runAll registerTypeConstructor Primitives.dataTypes
27+
_ <- runAll registerDataConstructors Primitives.dataTypes
28+
-- Add type variable 'a' with kind Type to context
29+
let var = mkId "a"
30+
modify (\st -> st { tyVarContext = [(var, (Type 0, ForallQ))] })
31+
-- Extract type vars of kind Type from `a -> a`
32+
typeVarsOfKind (FunTy Nothing Nothing (TyVar var) (TyVar var)) (Type 0)
33+
case result of
34+
Right vars -> sort vars `shouldBe` [mkId "a"]
35+
Left err -> expectationFailure $ "Checker failed: " ++ show err
36+
37+
it "extracts multiple type variables of kind Type" $ do
38+
result <- evalChecker initState $ do
39+
_ <- runAll registerTypeConstructor Primitives.dataTypes
40+
_ <- runAll registerDataConstructors Primitives.dataTypes
41+
-- Add type variables with kind Type
42+
modify (\st -> st { tyVarContext = [ (mkId "a", (Type 0, ForallQ))
43+
, (mkId "b", (Type 0, ForallQ)) ] })
44+
typeVarsOfKind (FunTy Nothing Nothing (TyVar (mkId "a")) (TyVar (mkId "b"))) (Type 0)
45+
case result of
46+
Right vars -> sort vars `shouldBe` sort [mkId "a", mkId "b"]
47+
Left err -> expectationFailure $ "Checker failed: " ++ show err
48+
49+
it "returns empty list when no type variables match the kind" $ do
50+
result <- evalChecker initState $ do
51+
_ <- runAll registerTypeConstructor Primitives.dataTypes
52+
_ <- runAll registerDataConstructors Primitives.dataTypes
53+
-- Add type variable with kind Nat (not Type)
54+
modify (\st -> st { tyVarContext = [(mkId "n", (tyCon "Nat", BoundQ))] })
55+
typeVarsOfKind (TyVar (mkId "n")) (tyCon "Q")
56+
case result of
57+
Right vars -> vars `shouldBe` []
58+
Left err -> expectationFailure $ "Checker failed: " ++ show err
59+
60+
it "extracts type variables from nested types" $ do
61+
result <- evalChecker initState $ do
62+
_ <- runAll registerTypeConstructor Primitives.dataTypes
63+
_ <- runAll registerDataConstructors Primitives.dataTypes
64+
modify (\st -> st { tyVarContext = [ (mkId "a", (Type 0, ForallQ))
65+
, (mkId "b", (Type 0, ForallQ))
66+
, (mkId "c", (Type 0, ForallQ)) ] })
67+
-- Type: (a -> b) -> c
68+
let nestedTy = FunTy Nothing Nothing
69+
(FunTy Nothing Nothing (tyVar "a") (tyVar "b"))
70+
(tyVar "c")
71+
typeVarsOfKind nestedTy (Type 0)
72+
case result of
73+
Right vars -> sort vars `shouldBe` sort [mkId "a", mkId "b", mkId "c"]
74+
Left err -> expectationFailure $ "Checker failed: " ++ show err
75+
76+
it "handles Box types correctly" $ do
77+
result <- evalChecker initState $ do
78+
_ <- runAll registerTypeConstructor Primitives.dataTypes
79+
_ <- runAll registerDataConstructors Primitives.dataTypes
80+
modify (\st -> st { tyVarContext = [(mkId "a", (Type 0, ForallQ))] })
81+
-- Type: Box r a (simplified - just checking a is found inside Box)
82+
let boxTy = Box (TyInt 1) (tyVar "a")
83+
typeVarsOfKind boxTy (Type 0)
84+
case result of
85+
Right vars -> vars `shouldBe` [mkId "a"]
86+
Left err -> expectationFailure $ "Checker failed: " ++ show err
87+
88+
it "handles TyApp correctly" $ do
89+
result <- evalChecker initState $ do
90+
_ <- runAll registerTypeConstructor Primitives.dataTypes
91+
_ <- runAll registerDataConstructors Primitives.dataTypes
92+
modify (\st -> st { tyVarContext = [(mkId "a", (Type 0, ForallQ))] })
93+
-- Type: Maybe a (as TyApp (TyCon Maybe) (TyVar a))
94+
let maybeATy = TyApp (tyCon "Maybe") (tyVar "a")
95+
typeVarsOfKind maybeATy (Type 0)
96+
case result of
97+
Right vars -> vars `shouldBe` [mkId "a"]
98+
Left err -> expectationFailure $ "Checker failed: " ++ show err
99+
100+
it "filters type variables by kind when mixed kinds present" $ do
101+
result <- evalChecker initState $ do
102+
_ <- runAll registerTypeConstructor Primitives.dataTypes
103+
_ <- runAll registerDataConstructors Primitives.dataTypes
104+
-- Mix of Type and Nat kinded variables
105+
modify (\st -> st { tyVarContext = [ (mkId "a", (Type 0, ForallQ))
106+
, (mkId "n", (tyCon "Nat", BoundQ))
107+
, (mkId "b", (Type 0, ForallQ)) ] })
108+
-- Type that mentions all three: a -> N n -> b
109+
let mixedTy = FunTy Nothing Nothing (tyVar "a")
110+
(FunTy Nothing Nothing (TyApp (tyCon "N") (tyVar "n")) (tyVar "b"))
111+
typeVarsOfKind mixedTy (Type 0)
112+
case result of
113+
Right vars -> sort vars `shouldBe` sort [mkId "a", mkId "b"]
114+
Left err -> expectationFailure $ "Checker failed: " ++ show err

0 commit comments

Comments
 (0)