Typechecking of fieldselectors
[cc1516.git] / sem.icl
1 implementation module sem
2
3 import qualified Data.Map as Map
4
5 from Data.Func import $
6 from StdFunc import o, flip, const, id
7
8 import Control.Monad
9 import Control.Monad.Trans
10 import Control.Monad.State
11 import Data.Either
12 import Data.Maybe
13 import Data.Monoid
14 import Data.List
15 import Data.Functor
16 import Data.Tuple
17
18 import StdString
19 import StdTuple
20 import StdList
21 import StdMisc
22 import StdEnum
23 import GenEq
24
25 from Text import class Text(concat), instance Text String
26
27 import AST
28
29 :: Scheme = Forall [TVar] Type
30 :: Gamma :== 'Map'.Map String Scheme //map from Variables! to types
31 :: Typing a :== StateT (Gamma, [TVar]) (Either SemError) a
32 :: Substitution :== 'Map'.Map TVar Type
33 :: Constraints :== [(Type, Type)]
34 :: SemError
35 = ParseError Pos String
36 | UnifyError Pos Type Type
37 | InfiniteTypeError Pos Type
38 | FieldSelectorError Pos Type FieldSelector
39 | OperatorError Pos Op2 Type
40 | UndeclaredVariableError Pos String
41 | ArgumentMisMatchError Pos String
42 | SanityError Pos String
43 | Error String
44
45 instance zero Gamma where
46 zero = 'Map'.newMap
47
48 variableStream :: [TVar]
49 variableStream = map toString [1..]
50
51 defaultGamma :: Gamma //includes all default functions
52 defaultGamma = extend "print" (Forall ["a"] ((IdType "a") ->> VoidType))
53 $ extend "isEmpty" (Forall ["a"] (ListType (IdType "a") ->> BoolType))
54 $ extend "read" (Forall [] (IntType ->> (ListType CharType)))
55 zero
56
57 sem :: AST -> Either [SemError] AST
58 sem (AST fd) = case foldM (const $ hasNoDups fd) () fd
59 >>| foldM (const isNiceMain) () fd
60 >>| hasMain fd
61 >>| evalStateT (type fd) (defaultGamma, variableStream) of
62 Left e = Left [e]
63 Right (_,fds) = Right (AST fds)
64 where
65 hasNoDups :: [FunDecl] FunDecl -> Either SemError ()
66 hasNoDups fds (FunDecl p n _ _ _ _)
67 # mbs = map (\(FunDecl p` n` _ _ _ _)->if (n == n`) (Just p`) Nothing) fds
68 = case catMaybes mbs of
69 [] = Left $ SanityError p "HUH THIS SHOULDN'T HAPPEN"
70 [x] = pure ()
71 [_:x] = Left $ SanityError p (concat
72 [n, " multiply defined at ", toString p])
73
74 hasMain :: [FunDecl] -> Either SemError ()
75 hasMain [(FunDecl _ "main" _ _ _ _):fd] = pure ()
76 hasMain [_:fd] = hasMain fd
77 hasMain [] = Left $ SanityError zero "no main function defined"
78
79 isNiceMain :: FunDecl -> Either SemError ()
80 isNiceMain (FunDecl p "main" as mt _ _) = case (as, mt) of
81 ([_:_], _) = Left $ SanityError p "main must have arity 0"
82 ([], t) = (case t of
83 Nothing = pure ()
84 Just VoidType = pure ()
85 _ = Left $ SanityError p "main has to return Void")
86 isNiceMain _ = pure ()
87
88 class Typeable a where
89 ftv :: a -> [TVar]
90 subst :: Substitution a -> a
91
92 instance Typeable Scheme where
93 ftv (Forall bound t) = difference (ftv t) bound
94 subst s (Forall bound t) = Forall bound $ subst s_ t
95 where s_ = 'Map'.filterWithKey (\k _ -> not (elem k bound)) s
96
97 instance Typeable [a] | Typeable a where
98 ftv types = foldr (\t ts-> ftv t ++ ts) [] types
99 subst s ts = map (\t->subst s t) ts
100
101 instance Typeable Type where
102 ftv (TupleType (t1, t2)) = ftv t1 ++ ftv t2
103 ftv (ListType t) = ftv t
104 ftv (IdType tvar) = [tvar]
105 ftv (t1 ->> t2) = ftv t1 ++ ftv t2
106 ftv _ = []
107 subst s (TupleType (t1, t2))= TupleType (subst s t1, subst s t2)
108 subst s (ListType t1) = ListType (subst s t1)
109 subst s (t1 ->> t2) = (subst s t1) ->> (subst s t2)
110 subst s t1=:(IdType tvar) = 'Map'.findWithDefault t1 tvar s
111 subst s t = t
112
113 instance Typeable Gamma where
114 ftv gamma = concatMap id $ map ftv ('Map'.elems gamma)
115 subst s gamma = Mapmap (subst s) gamma
116
117 extend :: String Scheme Gamma -> Gamma
118 extend k t g = 'Map'.put k t g
119
120 //// ------------------------
121 //// algorithm U, Unification
122 //// ------------------------
123 instance zero Substitution where zero = 'Map'.newMap
124
125 compose :: Substitution Substitution -> Substitution
126 compose s1 s2 = 'Map'.union (Mapmap (subst s1) s2) s1
127 //Note: just like function compositon compose does snd first
128
129 occurs :: TVar a -> Bool | Typeable a
130 occurs tvar a = elem tvar (ftv a)
131
132 unify :: Type Type -> Either SemError Substitution
133 unify t1 t2=:(IdType tv) | t1 == (IdType tv) = Right zero
134 | occurs tv t1 = Left $ InfiniteTypeError zero t1
135 | otherwise = Right $ 'Map'.singleton tv t1
136 unify t1=:(IdType tv) t2 = unify t2 t1
137 unify (ta1->>ta2) (tb1->>tb2) = unify ta1 tb1 >>= \s1->
138 unify ta2 tb2 >>= \s2->
139 Right $ compose s1 s2
140 unify (TupleType (ta1,ta2)) (TupleType (tb1,tb2)) = unify ta1 tb1 >>= \s1->
141 unify ta2 tb2 >>= \s2->
142 Right $ compose s1 s2
143 unify (ListType t1) (ListType t2) = unify t1 t2
144 unify t1 t2 | t1 == t2 = Right zero
145 | otherwise = Left $ UnifyError zero t1 t2
146
147 //// ------------------------
148 //// Algorithm M, Inference and Solving
149 //// ------------------------
150 gamma :: Typing Gamma
151 gamma = gets fst
152 putGamma :: Gamma -> Typing ()
153 putGamma g = modify (appFst $ const g) >>| pure ()
154 changeGamma :: (Gamma -> Gamma) -> Typing Gamma
155 changeGamma f = modify (appFst f) >>| gamma
156 withGamma :: (Gamma -> a) -> Typing a
157 withGamma f = f <$> gamma
158 fresh :: Typing Type
159 fresh = gets snd >>= \vars->
160 modify (appSnd $ const $ tail vars) >>|
161 pure (IdType (head vars))
162
163 lift :: (Either SemError a) -> Typing a
164 lift (Left e) = liftT $ Left e
165 lift (Right v) = pure v
166
167 //instantiate maps a schemes type variables to variables with fresh names
168 //and drops the quantification: i.e. forall a,b.a->[b] becomes c->[d]
169 instantiate :: Scheme -> Typing Type
170 instantiate (Forall bound t) =
171 mapM (const fresh) bound >>= \newVars->
172 let s = 'Map'.fromList (zip (bound,newVars)) in
173 pure (subst s t)
174
175 //generalize quentifies all free type variables in a type which are not
176 //in the gamma
177 generalize :: Type -> Typing Scheme
178 generalize t = gamma >>= \g-> pure $ Forall (difference (ftv t) (ftv g)) t
179
180 lookup :: String -> Typing Type
181 lookup "isEmpty" = ListType <$> fresh
182 lookup k = gamma >>= \g-> case 'Map'.member k g of
183 False = liftT (Left $ UndeclaredVariableError zero k)
184 True = instantiate $ 'Map'.find k g
185
186 //The inference class
187 //When tying it all together we will treat the program is a big
188 //let x=e1 in let y=e2 in ....
189 class infer a :: a -> Typing (Substitution, Type)
190
191 ////---- Inference for Expressions ----
192
193 instance infer Expr where
194 infer e = case e of
195 VarExpr _ (VarDef k fs) = lookup k >>= \t ->
196 foldM foldFieldSelectors t fs >>= \finalT ->
197 pure (zero, finalT)
198
199 Op2Expr _ e1 op e2 =
200 infer e1 >>= \(s1, t1) ->
201 infer e2 >>= \(s2, t2) ->
202 fresh >>= \tv ->
203 let given = t1 ->> t2 ->> tv in
204 op2Type op >>= \expected ->
205 lift (unify expected given) >>= \s3 ->
206 pure ((compose s3 $ compose s2 s1), subst s3 tv)
207
208 Op1Expr _ op e1 =
209 infer e1 >>= \(s1, t1) ->
210 fresh >>= \tv ->
211 let given = t1 ->> tv in
212 op1Type op >>= \expected ->
213 lift (unify expected given) >>= \s2 ->
214 pure (compose s2 s1, subst s2 tv)
215
216 EmptyListExpr _ = (\tv->(zero,tv)) <$> fresh
217
218 TupleExpr _ (e1, e2) =
219 infer e1 >>= \(s1, t1) ->
220 infer e2 >>= \(s2, t2) ->
221 pure (compose s2 s1, TupleType (t1,t2))
222
223 FunExpr _ f args fs = //todo: fieldselectors
224 lookup f >>= \expected ->
225 let accST = (\(s,ts) e->infer e >>= \(s_,et)->pure (compose s_ s,ts++[et])) in
226 foldM accST (zero,[]) args >>= \(s1, argTs)->
227 fresh >>= \tv->
228 let given = foldr (->>) tv argTs in
229 lift (unify expected given) >>= \s2->
230 let fReturnType = subst s2 tv in
231 foldM foldFieldSelectors fReturnType fs >>= \returnType ->
232 pure (compose s2 s1, returnType)
233
234 IntExpr _ _ = pure $ (zero, IntType)
235 BoolExpr _ _ = pure $ (zero, BoolType)
236 CharExpr _ _ = pure $ (zero, CharType)
237
238 foldFieldSelectors :: Type FieldSelector -> Typing Type
239 foldFieldSelectors (ListType t) (FieldHd) = pure t
240 foldFieldSelectors t=:(ListType _) (FieldTl) = pure t
241 foldFieldSelectors (TupleType (t1, _)) (FieldFst) = pure t1
242 foldFieldSelectors (TupleType (_, t2)) (FieldSnd) = pure t2
243 foldFieldSelectors t fs = liftT $ Left $ FieldSelectorError zero t fs
244
245 op2Type :: Op2 -> Typing Type
246 op2Type op
247 | elem op [BiPlus, BiMinus, BiTimes, BiDivide, BiMod]
248 = pure (IntType ->> IntType ->> IntType)
249 | elem op [BiEquals, BiUnEqual]
250 = fresh >>= \t1-> fresh >>= \t2-> pure (t1 ->> t2 ->> BoolType)
251 | elem op [BiLesser, BiGreater, BiLesserEq, BiGreaterEq]
252 = pure (IntType ->> IntType ->> BoolType)
253 | elem op [BiAnd, BiOr]
254 = pure (BoolType ->> BoolType ->> BoolType)
255 | op == BiCons
256 = fresh >>= \t1-> pure (t1 ->> ListType t1 ->> ListType t1)
257
258 op1Type :: Op1 -> Typing Type
259 op1Type UnNegation = pure $ (BoolType ->> BoolType)
260 op1Type UnMinus = pure $ (IntType ->> IntType)
261
262 ////----- Inference for Statements -----
263 applySubst :: Substitution -> Typing Gamma
264 applySubst s = changeGamma (subst s)
265
266 instance infer Stmt where
267 infer s = case s of
268 IfStmt e th el =
269 infer e >>= \(s1, et)->
270 lift (unify et BoolType) >>= \s2 ->
271 applySubst (compose s2 s1) >>|
272 infer th >>= \(s3, tht)->
273 applySubst s3 >>|
274 infer el >>= \(s4, elt)->
275 applySubst s4 >>|
276 lift (unify tht elt) >>= \s5->
277 pure (compose s5 $ compose s4 $ compose s3 $ compose s2 s1, subst s5 tht)
278
279 WhileStmt e wh =
280 infer e >>= \(s1, et)->
281 lift (unify et BoolType) >>= \s2 ->
282 applySubst (compose s2 s1) >>|
283 infer wh >>= \(s3, wht)->
284 pure (compose s3 $ compose s2 s1, subst s3 wht)
285
286 AssStmt (VarDef k fs) e =
287 lookup k >>= \expected ->
288 infer e >>= \(s1, given)->
289 foldM reverseFs given (reverse fs) >>= \varType->
290 lift (unify expected varType) >>= \s2->
291 let s = compose s2 s1 in
292 applySubst s >>|
293 changeGamma (extend k (Forall [] (subst s varType))) >>|
294 pure (s, VoidType)
295
296 FunStmt f es _ = pure (zero, VoidType)
297
298 ReturnStmt Nothing = pure (zero, VoidType)
299 ReturnStmt (Just e) = infer e
300
301 reverseFs :: Type FieldSelector -> Typing Type
302 reverseFs t FieldHd = pure $ ListType t
303 reverseFs t FieldTl = pure $ ListType t
304 reverseFs t FieldFst = fresh >>= \tv -> pure $ TupleType (t, tv)
305 reverseFs t FieldSnd = fresh >>= \tv -> pure $ TupleType (tv, t)
306
307 //The type of a list of statements is either an encountered
308 //return, or VoidType
309 instance infer [a] | infer a where
310 infer [] = pure (zero, VoidType)
311 infer [stmt:ss] =
312 infer stmt >>= \(s1, t1) ->
313 applySubst s1 >>|
314 infer ss >>= \(s2, t2) ->
315 applySubst s2 >>|
316 case t1 of
317 VoidType = pure (compose s2 s1, t2)
318 _ = case t2 of
319 VoidType = pure (compose s2 s1, t1)
320 _ = lift (unify t1 t2) >>= \s3 ->
321 pure (compose s3 $ compose s2 s1, t1)
322
323 //the type class inferes the type of an AST element (VarDecl or FunDecl)
324 //and adds it to the AST element
325 class type a :: a -> Typing (Substitution, a)
326
327 instance type VarDecl where
328 type (VarDecl p expected k e) =
329 infer e >>= \(s1, given) ->
330 applySubst s1 >>|
331 case expected of
332 Nothing = pure zero
333 Just expected_ = lift (unify expected_ given)
334 >>= \s2->
335 applySubst s2 >>|
336 let vtype = subst (compose s2 s1) given in
337 generalize vtype >>= \t ->
338 changeGamma (extend k t) >>|
339 pure (compose s2 s1, VarDecl p (Just vtype) k e)
340
341 instance type FunDecl where
342 type (FunDecl p f args expected vds stmts) =
343 gamma >>= \outerScope-> //functions are infered in their own scopde
344 introduce f >>|
345 mapM introduce args >>= \argTs->
346 type vds >>= \(s1, tVds)->
347 applySubst s1 >>|
348 infer stmts >>= \(s2, result)->
349 applySubst s1 >>|
350 let argTs_ = map (subst $ compose s2 s1) argTs in
351 //abort (concat $ intersperse "\n" $ map toString argTs_) >>|
352 let given = foldr (->>) result argTs_ in
353 (case expected of
354 Nothing = pure zero
355 Just expected_ = lift (unify expected_ given))
356 >>= \s3 ->
357 let ftype = subst (compose s3 $ compose s2 s1) given in
358 generalize ftype >>= \t->
359 putGamma outerScope >>|
360 changeGamma (extend f t) >>|
361 pure (compose s3 $ compose s2 s1, FunDecl p f args (Just ftype) tVds stmts)
362
363 instance type [a] | type a where
364 type [] = pure (zero, [])
365 type [v:vs] =
366 type v >>= \(s1, v_)->
367 applySubst s1 >>|
368 type vs >>= \(s2, vs_)->
369 applySubst (compose s2 s1) >>|
370 pure (compose s2 s1, [v_:vs_])
371
372 introduce :: String -> Typing Type
373 introduce k =
374 fresh >>= \tv ->
375 changeGamma (extend k (Forall [] tv)) >>|
376 pure tv
377
378 instance toString Scheme where
379 toString (Forall x t) =
380 concat ["Forall ": intersperse "," x] +++ concat [". ", toString t];
381
382 instance toString Gamma where
383 toString mp =
384 concat [concat [k, ": ", toString v, "\n"]\\(k, v)<-'Map'.toList mp]
385
386 instance toString Substitution where
387 toString subs =
388 concat [concat [k, ": ", toString t, "\n"]\\(k, t)<-'Map'.toList subs]
389
390 instance toString SemError where
391 toString (SanityError p e) = concat [toString p,
392 "SemError: SanityError: ", e]
393 toString (ParseError p s) = concat [toString p,
394 "ParseError: ", s]
395 toString (UnifyError p t1 t2) = concat [toString p,
396 "Can not unify types, expected|given:\n", toString t1,
397 "\n", toString t2]
398 toString (InfiniteTypeError p t) = concat [toString p,
399 "Infinite type: ", toString t]
400 toString (FieldSelectorError p t fs) = concat [toString p,
401 "Can not run fieldselector '", toString fs, "' on type: ",
402 toString t]
403 toString (OperatorError p op t) = concat [toString p,
404 "Operator error, operator '", toString op, "' can not be",
405 "used on type: ", toString t]
406 toString (UndeclaredVariableError p k) = concat [toString p,
407 "Undeclared identifier: ", k]
408 toString (ArgumentMisMatchError p str) = concat [toString p,
409 "Argument mismatch: ", str]
410 toString (Error e) = concat ["Unknown error during semantical",
411 "analysis: ", e]
412
413 instance toString (Maybe a) | toString a where
414 toString Nothing = "Nothing"
415 toString (Just e) = concat ["Just ", toString e]
416
417 instance MonadTrans (StateT (Gamma, [TVar])) where
418 liftT m = StateT \s-> m >>= \a-> return (a, s)
419
420 Mapmap :: (a->b) ('Map'.Map k a) -> ('Map'.Map k b)
421 Mapmap _ 'Map'.Tip = 'Map'.Tip
422 Mapmap f ('Map'.Bin sz k v ml mr) = 'Map'.Bin sz k (f v)
423 (Mapmap f ml)
424 (Mapmap f mr)