@@ -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
5+ , collectLambdas
6+ , prettyParens
7+ ) where
28
39import Control.Applicative ((<$>), (<*>))
410import Control.Arrow (second)
@@ -11,13 +17,15 @@ import qualified AST.Helpers as Help
1117import Text.PrettyPrint as P
1218
1319
20+-- DEFINITION
21+
1422data Type var
1523 = Lambda (Type var) (Type var)
1624 | Var String
1725 | Type var
1826 | App (Type var) [Type var]
1927 | Record [(String, Type var)] (Maybe (Type var))
20− | Aliased Var.Canonical (Type var)
28+ | Aliased Var.Canonical [(String, Type var)] (Type var)
2129 deriving (Eq,Show)
2230
2331
@@ -52,29 +60,64 @@ tupleOf types =
5260 let name = Var.Raw ("_Tuple" ++ show (length types))
5361 in
5462 App (Type name) types
55−
5663
57−dealias :: Type v -> Type v
58−dealias tipe =
64+
65+-- DEALIASING
66+
67+deepDealias :: Type v -> Type v
68+deepDealias tipe =
69+ let go = deepDealias in
5970 case tipe of
60− Lambda arg body ->
61− Lambda (dealias arg) (dealias body)
71+ Lambda a b ->
72+ Lambda (go a) (go b)
6273
6374 Var _ ->
6475 tipe
6576
77+ Record fields ext ->
78+ Record (map (second go) fields) (fmap go ext)
79+
80+ Aliased _name args tipe' ->
81+ dealias args tipe'
82+
6683 Type _ ->
6784 tipe
6885
6986 App f args ->
70− App (dealias f) (map dealias args)
87+ App (go f) (map go args)
7188
72− Record fields ext ->
73− Record (map (second dealias) fields) (fmap dealias ext)
7489
75− Aliased _ t ->
76− dealias t
90+dealias :: [(String, Type v)] -> Type v -> Type v
91+dealias args tipe =
92+ replace (Map.fromList args) tipe
93+
7794
95+replace :: Map.Map String (Type var) -> Type var -> Type var
96+replace typeTable t =
97+ let go = replace typeTable in
98+ case t of
99+ Lambda a b ->
100+ Lambda (go a) (go b)
101+
102+ Var x ->
103+ Map.findWithDefault t x typeTable
104+
105+ Record fields ext ->
106+ Record (map (second go) fields) (fmap go ext)
107+
108+ Aliased original args t' ->
109+ let typeTable' = foldr Map.delete typeTable (map fst args)
110+ in
111+ Aliased original (map (second go) args) (replace typeTable' t')
112+
113+ Type _ ->
114+ t
115+
116+ App f args ->
117+ App (go f) (map go args)
118+
119+
120+-- PRETTY PRINTING
78121
79122instance (Var.ToString var, Pretty var) => Pretty (Type var) where
80123 pretty tipe =
@@ -127,13 +170,16 @@ instance (Var.ToString var, Pretty var) => Pretty (Type var) where
127170 prettyField (field, tipe) =
128171 P.text field <+> P.text ":" <+> pretty tipe
129172
130− Aliased name t ->
173+ Aliased name [] t ->
131174 let t' = pretty t
132175 in
133176 if show t' `elem` ["Int", "Float", "String", "Char", "Bool"]
134177 then t'
135178 else pretty name
136179
180+ Aliased name args _ ->
181+ P.hang (pretty name) 2 (P.sep (map (prettyParens . snd) args))
182+
137183
138184collectLambdas :: Type var -> [Type var]
139185collectLambdas tipe =
@@ -151,7 +197,9 @@ prettyParens tipe =
151197 where
152198 needed t =
153199 case t of
154− Aliased _ t' -> needed t'
200+ Aliased _ [] _ -> False
201+
202+ Aliased _ _ _ -> True
155203
156204 Lambda _ _ -> True
157205
@@ -180,22 +228,35 @@ flattenRecord tipe =
180228 in
181229 (fields' ++ fields, ext')
182230
183− Aliased _ tipe' ->
231+ Aliased _ _ tipe' ->
184232 flattenRecord tipe'
185233
186234 _ ->
187235 error "Trying to flatten ill-formed record."
188236
189237
238+-- BINARY
239+
190240instance Binary var => Binary (Type var) where
191241 put tipe =
192242 case tipe of
193− Lambda t1 t2 -> putWord8 0 >> put t1 >> put t2
194− Var x -> putWord8 1 >> put x
195− Type name -> putWord8 2 >> put name
196− App t1 t2 -> putWord8 3 >> put t1 >> put t2
197− Record fs ext -> putWord8 4 >> put fs >> put ext
198− Aliased var t -> putWord8 5 >> put var >> put t
243+ Lambda t1 t2 ->
244+ putWord8 0 >> put t1 >> put t2
245+
246+ Var x ->
247+ putWord8 1 >> put x
248+
249+ Type name ->
250+ putWord8 2 >> put name
251+
252+ App t1 t2 ->
253+ putWord8 3 >> put t1 >> put t2
254+
255+ Record fs ext ->
256+ putWord8 4 >> put fs >> put ext
257+
258+ Aliased var args t ->
259+ putWord8 5 >> put var >> put args >> put t
199260
200261 get = do
201262 n <- getWord8
@@ -205,5 +266,5 @@ instance Binary var => Binary (Type var) where
205266 2 -> Type <$> get
206267 3 -> App <$> get <*> get
207268 4 -> Record <$> get <*> get
208− 5 -> Aliased <$> get <*> get
269+ 5 -> Aliased <$> get <*> get <*> get
209270 _ -> error "Error reading a valid type from serialized string"