1 {-# LANGUAGE AllowAmbiguousTypes #-}
2 {-# LANGUAGE TypeApplications #-}
3 {-# LANGUAGE UndecidableInstances #-}
4 {-# OPTIONS_GHC -fno-warn-orphans #-}
5 module Typing.Test where
8 import Test.Tasty.HUnit
10 import Control.Applicative (Applicative(..))
11 import Control.Arrow (left)
12 import Data.Functor.Identity (Identity(..))
13 import Data.List.NonEmpty (NonEmpty)
14 import Data.Map.Strict (Map)
15 import Data.Maybe (isJust)
16 import Data.NonNull (NonNull)
18 import Data.Ratio (Ratio)
19 import Data.Text (Text)
20 import Data.Void (Void)
21 import GHC.Exts (Constraint)
22 import Prelude hiding (exp)
23 import qualified Control.Monad.Classes.Run as MC
24 import qualified Control.Monad.Trans.State.Strict as SS
25 import qualified Data.Function as Fun
26 import qualified Data.Map.Strict as Map
27 import qualified Data.MonoTraversable as MT
28 import qualified Data.Sequences as Seqs
29 import qualified System.IO as IO
30 import qualified Text.Megaparsec as P
32 import Language.Symantic.Grammar
33 import Language.Symantic
34 import Language.Symantic.Lib hiding ((<$>), (<*))
36 import Grammar.Megaparsec ()
67 , Proxy MT.MonoFoldable
68 , Proxy MT.MonoFunctor
72 , Proxy Seqs.IsSequence
73 , Proxy Seqs.SemiSequence
77 type SRC = SrcTe (NonEmpty P.SourcePos) SS
79 impsTy :: Imports NameTy
80 impsTy = importTypes @SS []
82 modsTy :: Source src => ModulesTy src
84 Map.insert ([] `Mod` "String")
85 (TypeTLen $ \len -> TypeT $
86 tyConstLen @(K []) @[] len `tyApp`
87 tyConstLen @(K Char) @Char len) $
92 g ~ P.ParsecT err inp (SS.StateT (Imports NameTy, ModulesTy src) Identity) =>
93 P.MonadParsec err inp (P.ParsecT err inp g) =>
96 inp -> Either (P.ParseError Char err) (AST_Type src)
99 MC.evalStateStrict (impsTy, modsTy @src) $
100 P.runParserT g "" inp
101 where g = unCF $ g_type <* eoi
104 tests = testGroup "Typing" $
105 [ testGroup "readType" $
106 let run inp (TypeT exp :: TypeT SRC '[]) =
107 testCase inp $ got @?= Right (Right $ TypeVT exp)
109 got :: Either (P.ParseError Char Void)
110 (Either (Error_Type SRC) (TypeVT SRC))
111 got = readType <$> parseTy inp
113 let (==>) = run; infixr 0 ==> in
114 [ "Bool" ==> TypeT $ tyBool
115 , "(->) Bool" ==> TypeT $ tyFun `tyApp` tyBool
116 , "[]" ==> TypeT $ tyConst @(K []) @[]
117 , "[Char]" ==> TypeT $ tyList tyChar
118 , "[Char -> [Char]]" ==> TypeT $ tyList (tyChar ~> tyList tyChar)
119 , "([])" ==> TypeT $ tyConst @(K []) @[]
120 , "[()]" ==> TypeT $ tyList tyUnit
121 , "()" ==> TypeT $ tyUnit
122 , "(())" ==> TypeT $ tyUnit
123 , "(,)" ==> TypeT $ tyConst @(K (,)) @(,)
124 , "((,))" ==> TypeT $ tyConst @(K (,)) @(,)
125 , "(,) Int" ==> TypeT $ tyConst @(K (,)) @(,) `tyApp` tyInt
126 , "(Bool)" ==> TypeT $ tyBool
127 , "((Bool))" ==> TypeT $ tyBool
128 , "(Bool, Int)" ==> TypeT $ tyBool `tyTuple2` tyInt
129 , "((Bool, Int))" ==> TypeT $ tyBool `tyTuple2` tyInt
130 , "((Bool, Int), Char)" ==> TypeT $ (tyBool `tyTuple2` tyInt) `tyTuple2` tyChar
131 , "(Bool, Int) -> Char" ==> TypeT $ (tyBool `tyTuple2` tyInt) ~> tyChar
132 , "(Bool -> Int)" ==> TypeT $ tyBool ~> tyInt
133 , "String" ==> TypeT $ tyList tyChar
134 , "[Char] -> String" ==> TypeT $ tyList tyChar ~> tyList tyChar
135 , "String -> [Char]" ==> TypeT $ tyList tyChar ~> tyList tyChar
136 , "Maybe Bool" ==> TypeT $ tyMaybe tyBool
137 , "Either Bool Int" ==> TypeT $ tyEither tyBool tyInt
138 , "Bool -> Int" ==> TypeT $ tyBool ~> tyInt
139 , "(Bool -> Int) -> Char" ==> TypeT $ (tyBool ~> tyInt) ~> tyChar
140 , "Bool -> (Int -> Char)" ==> TypeT $ tyBool ~> (tyInt ~> tyChar)
141 , "Bool -> Int -> Char" ==> TypeT $ tyBool ~> tyInt ~> tyChar
142 , "Bool -> (Int -> Char) -> ()" ==> TypeT $ tyBool ~> (tyInt ~> tyChar) ~> tyUnit
143 , "IO" ==> TypeT $ tyConst @(K IO) @IO
144 , "Traversable IO" ==> TypeT $ tyTraversable (tyConst @(K IO) @IO)
145 , "Monad IO" ==> TypeT $ tyMonad (tyConst @(K IO) @IO)
146 , "(->) (IO Bool)" ==> TypeT $ tyConst @(K (->)) @(->) `tyApp` (tyIO tyBool)
147 , "Monad IO" ==> TypeT $ tyMonad (tyConst @(K IO) @IO)
148 , "Eq" ==> TypeT $ tyConst @(K Eq) @Eq
149 , "Eq Bool" ==> TypeT $ tyEq tyBool
151 , testGroup "Parsing errors" $
152 let run inp = testCase inp $ got @?= Left ()
154 got :: Either () (AST_Type SRC)
155 got = left (\(_::P.ParseError (P.Token String) Void) -> ()) $ parseTy inp in
158 , "(Bool -> Int) Char"
161 , testGroup "Compiling errors" $
162 let run inp = testCase inp $ got @?= Right (Left ())
164 got :: Either (P.ParseError Char Void) (Either () (TypeVT SRC))
165 got = left (Fun.const ()) . readType <$> parseTy inp in
170 , "(->) Bool Int Char"
173 , testGroup "proveConstraint" $
174 let (==>) (typ::Type SRC SS (t::Constraint)) expected =
175 let imps = importTypes @SS [] in
176 let conf = config_Doc_Type{config_Doc_Type_imports = imps} in
177 testCase (showType conf typ) $
178 isJust (proveConstraint typ) @?= expected in
179 [ tyEq tyBool ==> True
180 , tyOrd tyBool ==> True
181 , tyFunctor (tyConst @(K Maybe) @Maybe) ==> True
182 , tyFunctor (tyConst @(K IO) @IO) ==> True
183 , tyMonad (tyConst @(K IO) @IO) ==> True
184 , tyTraversable (tyConst @(K IO) @IO) ==> False