1module Type.Environment where
3import Control.Applicative ((<$>), (<*>))
5import qualified Control.Monad.State as State
6import qualified Data.Traversable as Traverse
7import qualified Data.Map as Map
8import Data.List (isPrefixOf)
9import qualified Data.UnionFind.IO as UF
11import qualified SourceSyntax.Type as Src
12import SourceSyntax.Module (ADT)
15type TypeDict = Map.Map String Type
16type VarDict = Map.Map String Variable
18data Environment = Environment {
19 constructor :: Map.Map String (IO (Int, [Variable], [Type], Type)),
20 aliases :: Map.Map String ([String], Src.Type),
25initialEnvironment :: [ADT] -> [(String, [String], Src.Type)] -> IO Environment
26initialEnvironment datatypes aliases = do
27 types <- makeTypes datatypes
28 let aliases' = Map.fromList $ map (\(a,b,c) -> (a,(b,c))) aliases
30 constructor = Map.empty,
35 return $ env { constructor = makeConstructors env datatypes }
37makeTypes :: [ADT] -> IO TypeDict
39 Map.fromList <$> mapM makeCtor (builtins ++ map nameAndKind datatypes)
41 nameAndKind (name, tvars, _) = (name, length tvars)
43 makeCtor (name, kind) = do
44 ctor <- VarN <$> namedVar Constant name
47 tuple n = ("_Tuple" ++ show n, n)
49 kind n names = map (\name -> (name, n)) names
51 builtins :: [(String,Int)]
52 builtins = concat [ map tuple [0..9]
54 , kind 0 ["Int","Float","Char","Bool"]
58makeConstructors :: Environment
60 -> Map.Map String (IO (Int, [Variable], [Type], Type))
61makeConstructors env datatypes = Map.fromList builtins
63 list t = (types env Map.! "_List") <| t
65 inst :: Int -> ([Type] -> ([Type], Type)) -> IO (Int, [Variable], [Type], Type)
66 inst numTVars tipe = do
67 vars <- forM [1..numTVars] $ \_ -> var Flexible
68 let (args, result) = tipe (map VarN vars)
69 return (length args, vars, args, result)
72 let name = "_Tuple" ++ show n
73 in (name, inst n $ \vs -> (vs, foldl (<|) (types env Map.! name) vs))
75 builtins :: [ (String, IO (Int, [Variable], [Type], Type)) ]
76 builtins = [ ("[]", inst 1 $ \ [t] -> ([], list t))
77 , ("::", inst 1 $ \ [t] -> ([t, list t], list t))
78 ] ++ map tupleCtor [0..9]
79 ++ concatMap (ctorToType env) datatypes
82ctorToType :: Environment -> ADT -> [ (String, IO (Int, [Variable], [Type], Type)) ]
83ctorToType env (name, tvars, ctors) =
84 zip (map fst ctors) (map inst ctors)
86 inst :: (String, [Src.Type]) -> IO (Int, [Variable], [Type], Type)
88 ((args, tipe), (dict,_)) <- State.runStateT (go ctor) (Map.empty, Map.empty)
89 return (length args, Map.elems dict, args, tipe)
92 go :: (String, [Src.Type]) -> State.StateT (VarDict, TypeDict) IO ([Type], Type)
94 types <- mapM (instantiator env) args
95 returnType <- instantiator env (Src.Data name (map Src.Var tvars))
96 return (types, returnType)
99get :: Environment -> (Environment -> Map.Map String a) -> String -> a
100get env subDict key = Map.findWithDefault err key (subDict env)
102 err = error $ "\nCould not find type constructor '" ++ key ++ "' while checking types."
105freshDataScheme :: Environment -> String -> IO (Int, [Variable], [Type], Type)
106freshDataScheme env name = get env constructor name
109 Environment -> Src.Type -> VarDict -> IO ([Variable], Type)
110instantiateType env sourceType dict =
111 do (tipe, (dict',_)) <- State.runStateT (instantiator env sourceType) (dict, Map.empty)
112 return (Map.elems dict', tipe)
114instantiator :: Environment -> Src.Type
115 -> State.StateT (VarDict, TypeDict) IO Type
116instantiator env sourceType = go sourceType
118 go :: Src.Type -> State.StateT (VarDict, TypeDict) IO Type
121 Src.Lambda t1 t2 -> (==>) <$> go t1 <*> go t2
124 (dict, aliases) <- State.get
125 case (Map.lookup x dict, Map.lookup x aliases) of
126 (_, Just t) -> return t
127 (Just v, _) -> return (VarN v)
129 do var <- State.liftIO $ namedVar flex x
130 State.put (Map.insert x var dict, aliases)
133 flex | "number" `isPrefixOf` x = Is Number
134 | "comparable" `isPrefixOf` x = Is Comparable
135 | "appendable" `isPrefixOf` x = Is Appendable
136 | otherwise = Flexible
138 Src.Data "String" [] ->
139 return (get env types "_List" <| get env types "Char")
141 Src.Data name ts -> do
143 case (Map.lookup name (types env), Map.lookup name (aliases env)) of
144 (Just t, _) -> return $ foldl (<|) t ts'
145 (_, Just (tvars, t)) ->
146 let tvarLen = length tvars
147 msg = "\nType alias '" ++ name ++ "' expects " ++ show tvarLen ++
148 " type argument" ++ (if tvarLen == 1 then "" else "s") ++
149 " but was given " ++ show (length ts')
150 in if length ts' /= length tvars then error msg else
151 do (dict, aliases) <- State.get
152 let aliases' = Map.union (Map.fromList $ zip tvars ts') aliases
153 State.put (dict, aliases')
155 State.put (dict, aliases)
157 _ -> error $ "\nCould not find type constructor '" ++
158 name ++ "' while checking types."
160 Src.EmptyRecord -> return (TermN EmptyRecord1)
162 Src.Record fields ext ->
163 TermN <$> (Record1 <$> Traverse.traverse (mapM go) (Src.fieldMap fields) <*> go 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