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 $ "Could 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 of
126 Just var -> return (VarN var)
128 case Map.lookup x aliases of
131 do var <- State.liftIO $ namedVar flex x
132 State.put (Map.insert x var dict, aliases)
135 flex | "number" `isPrefixOf` x = Is Number
136 | "comparable" `isPrefixOf` x = Is Comparable
137 | "appendable" `isPrefixOf` x = Is Appendable
138 | otherwise = Flexible
140 Src.Data "String" [] ->
141 return (get env types "_List" <| get env types "Char")
143 Src.Data name ts -> do
145 case Map.lookup name (types env) of
146 Just t -> return $ foldl (<|) t ts'
148 case Map.lookup name (aliases env) of
149 Nothing -> error $ "Could not find type constructor '" ++ name ++ "' while checking types."
151 let msg = "Type alias '" ++ name ++ "' expects " ++ show (length tvars) ++
152 " but was given " ++ show (length ts')
153 in if length ts' /= length tvars then error msg else
154 do (dict, aliases) <- State.get
155 State.put (dict, Map.union aliases . Map.fromList $ zip tvars ts')
158 Src.EmptyRecord -> return (TermN EmptyRecord1)
160 Src.Record fields ext ->
161 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