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 AST.Module (ADTs)
16import qualified AST.Type as T
17import qualified AST.Variable as V
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 :: ADTs -> IO Environment
30initialEnvironment datatypes = do
31 types <- makeTypes datatypes
33 { constructor = Map.empty
37 return $ env { constructor = makeConstructors env datatypes }
39makeTypes :: ADTs -> IO TypeDict
41 do adts <- Traverse.sequence (Map.mapWithKey make datatypes)
42 bs <- Map.fromList . zip (map fst builtins) <$> mapM (uncurry make) builtins
43 return (Map.union adts bs)
45 make name _ = 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","String","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) (Map.toList datatypes)
82--ctorToType :: Environment -> ADT -> [ (String, IO (Int, [Variable], [Type], Type)) ]
83ctorToType env (name, (tvars, ctors)) =
84 zip (map fst ctors) (map inst ctors)
86 inst :: (String, [T.CanonicalType]) -> IO (Int, [Variable], [Type], Type)
88 ((args, tipe), dict) <- State.runStateT (go ctor) Map.empty
89 return (length args, Map.elems dict, args, tipe)
92 go :: (String, [T.CanonicalType]) -> State.StateT VarDict IO ([Type], Type)
94 types <- mapM (instantiator env) args
95 returnType <- instantiator env (T.Data (error "name") (map T.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
108instance ErrorList PP.Doc where
109 listMsg str = [PP.text str]
111instantiateType :: Environment -> T.CanonicalType -> VarDict -> ErrorT [PP.Doc] IO ([Variable], Type)
112instantiateType env sourceType dict =
113 do result <- liftIO $ try (State.runStateT (instantiator env sourceType) dict)
114 case result :: Either SomeException (Type, VarDict) of
115 Left someError -> throwError [ PP.text $ show someError ]
116 Right (tipe, dict') -> return (Map.elems dict', tipe)
118instantiator :: Environment -> T.CanonicalType -> State.StateT VarDict IO Type
119instantiator env sourceType = go sourceType
121 go :: T.CanonicalType -> State.StateT VarDict IO Type
124 T.Lambda t1 t2 -> (==>) <$> go t1 <*> go t2
128 case Map.lookup x dict of
129 Just v -> return (VarN v)
131 do var <- State.liftIO $ namedVar flex x
132 State.put (Map.insert x var dict)
135 flex | "number" `isPrefixOf` x = Is Number
136 | "comparable" `isPrefixOf` x = Is Comparable
137 | "appendable" `isPrefixOf` x = Is Appendable
138 | otherwise = Flexible
142 case Map.lookup (V.toString name) (types env) of
143 Just t -> return $ foldl (<|) t ts'
144 Nothing -> error $ "\nCould not find type constructor '" ++
145 V.toString name ++ "' while checking types."
147 T.Record fields ext -> do
148 fields' <- Traverse.traverse (mapM go) (T.fieldMap fields)
150 Nothing -> return $ TermN EmptyRecord1
152 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