@@ -1,4 +1,10 @@
1−module AST.Type where
1+module AST.Type
2+ ( Type(..), RawType, CanonicalType
3+ , fieldMap, recordOf, listOf, tupleOf
4+ , deepDealias, dealias
3import Control.Applicative ((<$>), (<*>))
9import Control.Applicative ((<$>), (<*>))
4import Control.Arrow (second)
10import Control.Arrow (second)
@@ -11,13 +17,15 @@ import qualified AST.Helpers as Help
11import Text.PrettyPrint as P
17import Text.PrettyPrint as P
14data Type var
22data Type var
15 = Lambda (Type var) (Type var)
23 = Lambda (Type var) (Type var)
16 | Var String
24 | Var String
17 | Type var
25 | Type var
18 | App (Type var) [Type var]
26 | App (Type var) [Type var]
19 | Record [(String, Type var)] (Maybe (Type var))
27 | Record [(String, Type var)] (Maybe (Type var))
20− | Aliased Var.Canonical (Type var)
28+ | Aliased Var.Canonical [(String, Type var)] (Type var)
21 deriving (Eq,Show)
29 deriving (Eq,Show)
@@ -52,29 +60,64 @@ tupleOf types =
52 let name = Var.Raw ("_Tuple" ++ show (length types))
60 let name = Var.Raw ("_Tuple" ++ show (length types))
54 App (Type name) types
62 App (Type name) types
57−dealias :: Type v -> Type v
67+deepDealias :: Type v -> Type v
58−dealias tipe =
68+deepDealias tipe =
69+ let go = deepDealias in
59 case tipe of
70 case tipe of
60− Lambda arg body ->
71+ Lambda a b ->
61− Lambda (dealias arg) (dealias body)
72+ Lambda (go a) (go b)
78+ Record (map (second go) fields) (fmap go ext)
80+ Aliased _name args tipe' ->
69 App f args ->
86 App f args ->
70− App (dealias f) (map dealias args)
87+ App (go f) (map go args)
73− Record (map (second dealias) fields) (fmap dealias ext)
75− Aliased _ t ->
90+dealias :: [(String, Type v)] -> Type v -> Type v
76− dealias t
91+dealias args tipe =
92+ replace (Map.fromList args) tipe
95+replace :: Map.Map String (Type var) -> Type var -> Type var
97+ let go = replace typeTable in
100+ Lambda (go a) (go b)
103+ Map.findWithDefault t x typeTable
105+ Record fields ext ->
106+ Record (map (second go) fields) (fmap go ext)
108+ Aliased original args t' ->
109+ let typeTable' = foldr Map.delete typeTable (map fst args)
111+ Aliased original (map (second go) args) (replace typeTable' t')
117+ App (go f) (map go args)
79instance (Var.ToString var, Pretty var) => Pretty (Type var) where
122instance (Var.ToString var, Pretty var) => Pretty (Type var) where
80 pretty tipe =
123 pretty tipe =
@@ -127,13 +170,16 @@ instance (Var.ToString var, Pretty var) => Pretty (Type var) where
127 prettyField (field, tipe) =
170 prettyField (field, tipe) =
128 P.text field <+> P.text ":" <+> pretty tipe
171 P.text field <+> P.text ":" <+> pretty tipe
130− Aliased name t ->
173+ Aliased name [] t ->
131 let t' = pretty t
174 let t' = pretty t
133 if show t' `elem` ["Int", "Float", "String", "Char", "Bool"]
176 if show t' `elem` ["Int", "Float", "String", "Char", "Bool"]
135 else pretty name
178 else pretty name
180+ Aliased name args _ ->
181+ P.hang (pretty name) 2 (P.sep (map (prettyParens . snd) args))
138collectLambdas :: Type var -> [Type var]
184collectLambdas :: Type var -> [Type var]
139collectLambdas tipe =
185collectLambdas tipe =
@@ -151,7 +197,9 @@ prettyParens tipe =
152 needed t =
198 needed t =
153 case t of
199 case t of
154− Aliased _ t' -> needed t'
200+ Aliased _ [] _ -> False
202+ Aliased _ _ _ -> True
156 Lambda _ _ -> True
204 Lambda _ _ -> True
@@ -180,22 +228,35 @@ flattenRecord tipe =
181 (fields' ++ fields, ext')
229 (fields' ++ fields, ext')
183− Aliased _ tipe' ->
231+ Aliased _ _ tipe' ->
184 flattenRecord tipe'
232 flattenRecord tipe'
187 error "Trying to flatten ill-formed record."
235 error "Trying to flatten ill-formed record."
190instance Binary var => Binary (Type var) where
240instance Binary var => Binary (Type var) where
191 put tipe =
241 put tipe =
192 case tipe of
242 case tipe of
193− Lambda t1 t2 -> putWord8 0 >> put t1 >> put t2
244+ putWord8 0 >> put t1 >> put t2
194− Var x -> putWord8 1 >> put x
247+ putWord8 1 >> put x
195− Type name -> putWord8 2 >> put name
250+ putWord8 2 >> put name
196− App t1 t2 -> putWord8 3 >> put t1 >> put t2
253+ putWord8 3 >> put t1 >> put t2
197− Record fs ext -> putWord8 4 >> put fs >> put ext
256+ putWord8 4 >> put fs >> put ext
258+ Aliased var args t ->
198− Aliased var t -> putWord8 5 >> put var >> put t
259+ putWord8 5 >> put var >> put args >> put t
201 n <- getWord8
262 n <- getWord8
@@ -205,5 +266,5 @@ instance Binary var => Binary (Type var) where
205 2 -> Type <$> get
266 2 -> Type <$> get
206 3 -> App <$> get <*> get
267 3 -> App <$> get <*> get
207 4 -> Record <$> get <*> get
268 4 -> Record <$> get <*> get
208− 5 -> Aliased <$> get <*> get
269+ 5 -> Aliased <$> get <*> get <*> get
209 _ -> error "Error reading a valid type from serialized string"
270 _ -> error "Error reading a valid type from serialized string"