2module Type.Environment where
4import Control.Applicative ((<$>), (<*>))
5import Control.Exception (try, SomeException)
7import Control.Monad.Trans.Error (ErrorList(..))
8import Control.Monad.Error (ErrorT, throwError, liftIO)
9import qualified Control.Monad.State as State
10import qualified Data.Traversable as Traverse
11import qualified Data.Map as Map
12import Data.List (isPrefixOf)
13import qualified Text.PrettyPrint as PP
15import qualified AST.Type as T
16import qualified AST.Variable as V
17import AST.Module (CanonicalAdt, AdtInfo)
20type TypeDict = Map.Map String Type
21type VarDict = Map.Map String Variable
23data Environment = Environment
24 { constructor :: Map.Map String (IO (Int, [Variable], [Type], Type))
29initialEnvironment :: [CanonicalAdt] -> IO Environment
30initialEnvironment datatypes = do
31 types <- makeTypes datatypes
33 { constructor = Map.empty
37 return $ env { constructor = makeConstructors env datatypes }
39makeTypes :: [CanonicalAdt] -> IO TypeDict
41 do adts <- mapM makeImported datatypes
42 bs <- mapM makeBuiltin builtins
43 return (Map.fromList (adts ++ bs))
45 makeImported :: (V.Canonical, AdtInfo V.Canonical) -> IO (String, Type)
46 makeImported (var, _) = do
47 tvar <- namedVar Constant var
48 return (V.toString var, VarN tvar)
50 makeBuiltin :: (String, Int) -> IO (String, Type)
51 makeBuiltin (name, _) = do
52 name' <- namedVar Constant (V.builtin name)
53 return (name, VarN name')
55 builtins :: [(String, Int)]
56 builtins = concat [ map tuple [0..9]
58 , kind 0 ["Int","Float","Char","String","Bool"]
61 tuple n = ("_Tuple" ++ show n, n)
62 kind n names = map (\name -> (name, n)) names
66makeConstructors :: Environment
68 -> Map.Map String (IO (Int, [Variable], [Type], Type))
69makeConstructors env datatypes = Map.fromList builtins
71 list t = (types env Map.! "_List") <| t
73 inst :: Int -> ([Type] -> ([Type], Type)) -> IO (Int, [Variable], [Type], Type)
74 inst numTVars tipe = do
75 vars <- forM [1..numTVars] $ \_ -> var Flexible
76 let (args, result) = tipe (map VarN vars)
77 return (length args, vars, args, result)
80 let name = "_Tuple" ++ show n
81 in (name, inst n $ \vs -> (vs, foldl (<|) (types env Map.! name) vs))
83 builtins :: [ (String, IO (Int, [Variable], [Type], Type)) ]
84 builtins = [ ("[]", inst 1 $ \ [t] -> ([], list t))
85 , ("::", inst 1 $ \ [t] -> ([t, list t], list t))
86 ] ++ map tupleCtor [0..9]
87 ++ concatMap (ctorToType env) datatypes
90ctorToType :: Environment
91 -> (V.Canonical, AdtInfo V.Canonical)
92 -> [(String, IO (Int, [Variable], [Type], Type))]
93ctorToType env (name, (tvars, ctors)) =
94 zip (map (V.toString . fst) ctors) (map inst ctors)
96 inst :: (V.Canonical, [T.CanonicalType]) -> IO (Int, [Variable], [Type], Type)
98 ((args, tipe), dict) <- State.runStateT (go ctor) Map.empty
99 return (length args, Map.elems dict, args, tipe)
102 go :: (V.Canonical, [T.CanonicalType]) -> State.StateT VarDict IO ([Type], Type)
104 types <- mapM (instantiator env) args
105 returnType <- instantiator env (T.App (T.Type name) (map T.Var tvars))
106 return (types, returnType)
109get :: Environment -> (Environment -> Map.Map String a) -> String -> a
110get env subDict key = Map.findWithDefault err key (subDict env)
112 err = error $ "Could not find type constructor '" ++ key ++ "' while checking types."
115freshDataScheme :: Environment -> String -> IO (Int, [Variable], [Type], Type)
116freshDataScheme env name = get env constructor name
118instance ErrorList PP.Doc where
119 listMsg str = [PP.text str]
121instantiateType :: Environment -> T.CanonicalType -> VarDict -> ErrorT [PP.Doc] IO ([Variable], Type)
122instantiateType env sourceType dict =
123 do result <- liftIO $ try (State.runStateT (instantiator env sourceType) dict)
124 case result :: Either SomeException (Type, VarDict) of
125 Left someError -> throwError [ PP.text $ show someError ]
126 Right (tipe, dict') -> return (Map.elems dict', tipe)
128instantiator :: Environment -> T.CanonicalType -> State.StateT VarDict IO Type
129instantiator env sourceType = go sourceType
131 go :: T.CanonicalType -> State.StateT VarDict IO Type
134 T.Lambda t1 t2 -> (==>) <$> go t1 <*> go t2
138 case Map.lookup x dict of
139 Just v -> return (VarN v)
141 do var <- State.liftIO $ namedVar flex (V.local x)
142 State.put (Map.insert x var dict)
145 flex | "number" `isPrefixOf` x = Is Number
146 | "comparable" `isPrefixOf` x = Is Comparable
147 | "appendable" `isPrefixOf` x = Is Appendable
148 | otherwise = Flexible
150 T.Aliased _ t -> go t
153 case Map.lookup (V.toString var) (types env) of
155 Nothing -> error $ "Could not find type constructor '" ++
156 V.toString var ++ "' while checking types."
161 return $ foldl (<|) t' ts'
163 T.Record fields ext -> do
164 fields' <- Traverse.traverse (mapM go) (T.fieldMap fields)
166 Nothing -> return $ TermN EmptyRecord1
168 return $ TermN (Record1 fields' ext')
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list