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
9import Data.List (isPrefixOf)
10import qualified Data.UnionFind.IO as UF
12import qualified SourceSyntax.Type as Src
13import SourceSyntax.Module (ADT)
16type TypeDict = Map.Map String Type
17type VarDict = Map.Map String Variable
19data Environment = Environment {
20 constructor :: Map.Map String (IO (Int, [Variable], [Type], Type)),
21 aliases :: Map.Map String ([String], Src.Type),
26initialEnvironment :: [ADT] -> [(String, [String], Src.Type)] -> IO Environment
27initialEnvironment datatypes aliases = do
28 types <- makeTypes datatypes
29 let aliases' = Map.fromList $ map (\(a,b,c) -> (a,(b,c))) aliases
31 constructor = Map.empty,
36 return $ env { constructor = makeConstructors env datatypes }
38makeTypes :: [ADT] -> IO TypeDict
40 Map.fromList <$> mapM makeCtor (builtins ++ map nameAndKind datatypes)
42 nameAndKind (name, tvars, _) = (name, length tvars)
44 makeCtor (name, kind) = do
45 ctor <- VarN <$> namedVar Constant name
48 tuple n = ("_Tuple" ++ show n, n)
50 kind n names = map (\name -> (name, n)) names
52 builtins :: [(String,Int)]
53 builtins = concat [ map tuple [0..9]
54 , kind 1 ["_List","Signal"]
55 , kind 0 ["Int","Float","Char","Bool"]
59makeConstructors :: Environment
61 -> Map.Map String (IO (Int, [Variable], [Type], Type))
62makeConstructors env datatypes = Map.fromList builtins
64 list t = (types env ! "_List") <| t
66 inst :: Int -> ([Type] -> ([Type], Type)) -> IO (Int, [Variable], [Type], Type)
67 inst numTVars tipe = do
68 vars <- forM [1..numTVars] $ \_ -> var Flexible
69 let (args, result) = tipe (map VarN vars)
70 return (length args, vars, args, result)
73 let name = "_Tuple" ++ show n
74 in (name, inst n $ \vs -> (vs, foldl (<|) (types env ! name) vs))
76 builtins :: [ (String, IO (Int, [Variable], [Type], Type)) ]
77 builtins = [ ("[]" , inst 1 $ \ [t] -> ([], list t))
78 , ("::" , inst 1 $ \ [t] -> ([t, list t], list t))
79 ] ++ map tupleCtor [0..9]
80 ++ concatMap (ctorToType env) datatypes
83ctorToType :: Environment -> ADT -> [ (String, IO (Int, [Variable], [Type], Type)) ]
84ctorToType env (name, tvars, ctors) =
85 zip (map fst ctors) (map inst ctors)
87 inst :: (String, [Src.Type]) -> IO (Int, [Variable], [Type], Type)
89 ((args, tipe), (dict,_)) <- State.runStateT (go ctor) (Map.empty, Map.empty)
90 return (length args, Map.elems dict, args, tipe)
93 go :: (String, [Src.Type]) -> State.StateT (VarDict, TypeDict) IO ([Type], Type)
95 types <- mapM (instantiator env) args
96 returnType <- instantiator env (Src.Data name (map Src.Var tvars))
97 return (types, returnType)
100get :: Environment -> (Environment -> Map.Map String a) -> String -> a
101get env subDict key = Map.findWithDefault err key (subDict env)
103 err = error $ "Could not find type constructor '" ++ key ++ "' while checking types."
106freshDataScheme :: Environment -> String -> IO (Int, [Variable], [Type], Type)
107freshDataScheme env name = get env constructor name
110 Environment -> Src.Type -> VarDict -> IO ([Variable], Type)
111instantiateType env sourceType dict =
112 do (tipe, (dict',_)) <- State.runStateT (instantiator env sourceType) (dict, Map.empty)
113 return (Map.elems dict', tipe)
115instantiator :: Environment -> Src.Type
116 -> State.StateT (VarDict, TypeDict) IO Type
117instantiator env sourceType = go sourceType
119 go :: Src.Type -> State.StateT (VarDict, TypeDict) IO Type
122 Src.Lambda t1 t2 -> (==>) <$> go t1 <*> go t2
125 (dict, aliases) <- State.get
126 case Map.lookup x dict of
127 Just var -> return (VarN var)
129 case Map.lookup x aliases of
132 do var <- State.liftIO $ namedVar flex x
133 State.put (Map.insert x var dict, aliases)
136 flex | "number" `isPrefixOf` x = Is Number
137 | "comparable" `isPrefixOf` x = Is Comparable
138 | "appendable" `isPrefixOf` x = Is Appendable
139 | otherwise = Flexible
141 Src.Data "String" [] ->
142 return (get env types "_List" <| get env types "Char")
144 Src.Data name ts -> do
146 case Map.lookup name (types env) of
147 Just t -> return $ foldl (<|) t ts'
149 case Map.lookup name (aliases env) of
150 Nothing -> error $ "Could not find type constructor '" ++ name ++ "' while checking types."
152 let msg = "Type alias '" ++ name ++ "' expects " ++ show (length tvars) ++
153 " but was given " ++ show (length ts')
154 in if length ts' /= length tvars then error msg else
155 do (dict, aliases) <- State.get
156 State.put (dict, Map.union aliases . Map.fromList $ zip tvars ts')
159 Src.EmptyRecord -> return (TermN EmptyRecord1)
161 Src.Record fields ext ->
162 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