1module Type.Environment where
3import Control.Applicative ((<$>), (<*>))
4import Control.Exception (try, SomeException)
6import Control.Monad.Error (ErrorT, throwError, liftIO)
7import qualified Control.Monad.State as State
8import qualified Data.Traversable as Traverse
9import qualified Data.Map as Map
10import Data.List (isPrefixOf)
11import qualified Text.PrettyPrint as PP
13import qualified AST.Type as T
14import qualified AST.Variable as V
15import AST.Module (CanonicalAdt, AdtInfo)
18type TypeDict = Map.Map String Type
19type VarDict = Map.Map String Variable
21data Environment = Environment
22 { constructor :: Map.Map String (IO (Int, [Variable], [Type], Type))
27initialEnvironment :: [CanonicalAdt] -> IO Environment
28initialEnvironment datatypes = do
29 types <- makeTypes datatypes
31 { constructor = Map.empty
35 return $ env { constructor = makeConstructors env datatypes }
37makeTypes :: [CanonicalAdt] -> IO TypeDict
39 do adts <- mapM makeImported datatypes
40 bs <- mapM makeBuiltin builtins
41 return (Map.fromList (adts ++ bs))
43 makeImported :: (V.Canonical, AdtInfo V.Canonical) -> IO (String, Type)
44 makeImported (var, _) = do
45 tvar <- namedVar Constant var
46 return (V.toString var, varN tvar)
48 makeBuiltin :: (String, Int) -> IO (String, Type)
49 makeBuiltin (name, _) = do
50 name' <- namedVar Constant (V.builtin name)
51 return (name, varN name')
53 builtins :: [(String, Int)]
54 builtins = concat [ map tuple [0..9]
56 , kind 0 ["Int","Float","Char","String","Bool"]
59 tuple n = ("_Tuple" ++ show n, n)
60 kind n names = map (\name -> (name, n)) names
64makeConstructors :: Environment
66 -> Map.Map String (IO (Int, [Variable], [Type], Type))
67makeConstructors env datatypes = Map.fromList builtins
69 list t = (types env Map.! "List") <| t
71 inst :: Int -> ([Type] -> ([Type], Type)) -> IO (Int, [Variable], [Type], Type)
72 inst numTVars tipe = do
73 vars <- forM [1..numTVars] $ \_ -> variable Flexible
74 let (args, result) = tipe (map (varN) vars)
75 return (length args, vars, args, result)
78 let name = "_Tuple" ++ show n
79 in (name, inst n $ \vs -> (vs, foldl (<|) (types env Map.! name) vs))
81 builtins :: [ (String, IO (Int, [Variable], [Type], Type)) ]
82 builtins = [ ("[]", inst 1 $ \ [t] -> ([], list t))
83 , ("::", inst 1 $ \ [t] -> ([t, list t], list t))
84 ] ++ map tupleCtor [0..9]
85 ++ concatMap (ctorToType env) datatypes
88ctorToType :: Environment
89 -> (V.Canonical, AdtInfo V.Canonical)
90 -> [(String, IO (Int, [Variable], [Type], Type))]
91ctorToType env (name, (tvars, ctors)) =
92 zip (map (V.toString . fst) ctors) (map inst ctors)
94 inst :: (V.Canonical, [T.CanonicalType]) -> IO (Int, [Variable], [Type], Type)
96 ((args, tipe), dict) <- State.runStateT (go ctor) Map.empty
97 return (length args, Map.elems dict, args, tipe)
100 go :: (V.Canonical, [T.CanonicalType]) -> State.StateT VarDict IO ([Type], Type)
102 types <- mapM (instantiator env) args
103 returnType <- instantiator env (T.App (T.Type name) (map T.Var tvars))
104 return (types, returnType)
107get :: Environment -> (Environment -> Map.Map String a) -> String -> a
108get env subDict key = Map.findWithDefault (error msg) key (subDict env)
110 msg = "Could not find type constructor '" ++ key ++ "' while checking types."
113freshDataScheme :: Environment -> String -> IO (Int, [Variable], [Type], Type)
114freshDataScheme env name = get env constructor name
116instantiateType :: Environment -> T.CanonicalType -> VarDict -> ErrorT [PP.Doc] IO ([Variable], Type)
117instantiateType env sourceType dict =
118 do result <- liftIO $ try (State.runStateT (instantiator env sourceType) dict)
119 case result :: Either SomeException (Type, VarDict) of
120 Left someError -> throwError [ PP.text $ show someError ]
121 Right (tipe, dict') -> return (Map.elems dict', tipe)
123instantiator :: Environment -> T.CanonicalType -> State.StateT VarDict IO Type
124instantiator env sourceType = go sourceType
126 go :: T.CanonicalType -> State.StateT VarDict IO Type
129 T.Lambda t1 t2 -> (==>) <$> go t1 <*> go t2
133 case Map.lookup x dict of
134 Just v -> return (varN v)
136 do v <- State.liftIO $ namedVar flex (V.local x)
137 State.put (Map.insert x v dict)
140 flex | "number" `isPrefixOf` x = Is Number
141 | "comparable" `isPrefixOf` x = Is Comparable
142 | "appendable" `isPrefixOf` x = Is Appendable
143 | otherwise = Flexible
145 T.Aliased name t -> do
148 VarN _ v -> return (VarN (Just name) v)
149 TermN _ term -> return (TermN (Just name) term)
152 case Map.lookup (V.toString name) (types env) of
154 Nothing -> error $ "Could not find type constructor '" ++
155 V.toString name ++ "' while checking types."
160 return $ foldl (<|) t' ts'
162 T.Record fields ext -> do
163 fields' <- Traverse.traverse (mapM go) (T.fieldMap fields)
165 Nothing -> return $ termN EmptyRecord1
167 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