Merge branch 'master' of https://github.com/dopefishh/cc1516
[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 [] 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 k = gamma >>= \g-> case 'Map'.member k g of
182 False = liftT (Left $ UndeclaredVariableError zero k)
183 True = instantiate $ 'Map'.find k g
184
185 //The inference class
186 //When tying it all together we will treat the program is a big
187 //let x=e1 in let y=e2 in ....
188 class infer a :: a -> Typing (Substitution, Type)
189
190 ////---- Inference for Expressions ----
191
192 instance infer Expr where
193 infer e = case e of
194 VarExpr _ (VarDef k fs) = lookup k >>= \t ->
195 foldM foldFieldSelectors t fs >>= \finalT ->
196 pure (zero, finalT)
197
198 Op2Expr _ e1 op e2 =
199 infer e1 >>= \(s1, t1) ->
200 infer e2 >>= \(s2, t2) ->
201 fresh >>= \tv ->
202 let given = t1 ->> t2 ->> tv in
203 op2Type op >>= \expected ->
204 lift (unify expected given) >>= \s3 ->
205 pure ((compose s3 $ compose s2 s1), subst s3 tv)
206
207 Op1Expr _ op e1 =
208 infer e1 >>= \(s1, t1) ->
209 fresh >>= \tv ->
210 let given = t1 ->> tv in
211 op1Type op >>= \expected ->
212 lift (unify expected given) >>= \s2 ->
213 pure (compose s2 s1, subst s2 tv)
214
215 EmptyListExpr _ = (\tv->(zero,tv)) <$> fresh
216
217 TupleExpr _ (e1, e2) =
218 infer e1 >>= \(s1, t1) ->
219 infer e2 >>= \(s2, t2) ->
220 pure (compose s2 s1, TupleType (t1,t2))
221
222 FunExpr _ f args fs = //todo: fieldselectors
223 lookup f >>= \expected ->
224 let accST = (\(s,ts) e->infer e >>= \(s_,et)->pure (compose s_ s,ts++[et])) in
225 foldM accST (zero,[]) args >>= \(s1, argTs)->
226 fresh >>= \tv->
227 let given = foldr (->>) tv argTs in
228 lift (unify expected given) >>= \s2->
229 let fReturnType = subst s2 tv in
230 foldM foldFieldSelectors fReturnType fs >>= \returnType ->
231 pure (compose s2 s1, returnType)
232
233 IntExpr _ _ = pure $ (zero, IntType)
234 BoolExpr _ _ = pure $ (zero, BoolType)
235 CharExpr _ _ = pure $ (zero, CharType)
236
237 foldFieldSelectors :: Type FieldSelector -> Typing Type
238 foldFieldSelectors (ListType t) (FieldHd) = pure t
239 foldFieldSelectors t=:(ListType _) (FieldTl) = pure t
240 foldFieldSelectors (TupleType (t1, _)) (FieldFst) = pure t1
241 foldFieldSelectors (TupleType (_, t2)) (FieldSnd) = pure t2
242 foldFieldSelectors t fs = liftT $ Left $ FieldSelectorError zero t fs
243
244 op2Type :: Op2 -> Typing Type
245 op2Type op
246 | elem op [BiPlus, BiMinus, BiTimes, BiDivide, BiMod]
247 = pure (IntType ->> IntType ->> IntType)
248 | elem op [BiEquals, BiUnEqual]
249 = fresh >>= \t1-> fresh >>= \t2-> pure (t1 ->> t2 ->> BoolType)
250 | elem op [BiLesser, BiGreater, BiLesserEq, BiGreaterEq]
251 = pure (IntType ->> IntType ->> BoolType)
252 | elem op [BiAnd, BiOr]
253 = pure (BoolType ->> BoolType ->> BoolType)
254 | op == BiCons
255 = fresh >>= \t1-> pure (t1 ->> ListType t1 ->> ListType t1)
256
257 op1Type :: Op1 -> Typing Type
258 op1Type UnNegation = pure $ (BoolType ->> BoolType)
259 op1Type UnMinus = pure $ (IntType ->> IntType)
260
261 ////----- Inference for Statements -----
262 applySubst :: Substitution -> Typing Gamma
263 applySubst s = changeGamma (subst s)
264
265 instance infer Stmt where
266 infer s = case s of
267 IfStmt e th el =
268 infer e >>= \(s1, et)->
269 lift (unify et BoolType) >>= \s2 ->
270 applySubst (compose s2 s1) >>|
271 infer th >>= \(s3, tht)->
272 applySubst s3 >>|
273 infer el >>= \(s4, elt)->
274 applySubst s4 >>|
275 lift (unify tht elt) >>= \s5->
276 pure (compose s5 $ compose s4 $ compose s3 $ compose s2 s1, subst s5 tht)
277
278 WhileStmt e wh =
279 infer e >>= \(s1, et)->
280 lift (unify et BoolType) >>= \s2 ->
281 applySubst (compose s2 s1) >>|
282 infer wh >>= \(s3, wht)->
283 pure (compose s3 $ compose s2 s1, subst s3 wht)
284
285 AssStmt (VarDef k fs) e =
286 lookup k >>= \expected ->
287 infer e >>= \(s1, given)->
288 foldM reverseFs given (reverse fs) >>= \varType->
289 lift (unify expected varType) >>= \s2->
290 let s = compose s2 s1 in
291 applySubst s >>|
292 changeGamma (extend k (Forall [] (subst s varType))) >>|
293 pure (s, VoidType)
294
295 FunStmt f es _ = pure (zero, VoidType)
296
297 ReturnStmt Nothing = pure (zero, VoidType)
298 ReturnStmt (Just e) = infer e
299
300 reverseFs :: Type FieldSelector -> Typing Type
301 reverseFs t FieldHd = pure $ ListType t
302 reverseFs t FieldTl = pure $ ListType t
303 reverseFs t FieldFst = fresh >>= \tv -> pure $ TupleType (t, tv)
304 reverseFs t FieldSnd = fresh >>= \tv -> pure $ TupleType (tv, t)
305
306 //The type of a list of statements is either an encountered
307 //return, or VoidType
308 instance infer [a] | infer a where
309 infer [] = pure (zero, VoidType)
310 infer [stmt:ss] =
311 infer stmt >>= \(s1, t1) ->
312 applySubst s1 >>|
313 infer ss >>= \(s2, t2) ->
314 applySubst s2 >>|
315 case t1 of
316 VoidType = pure (compose s2 s1, t2)
317 _ = case t2 of
318 VoidType = pure (compose s2 s1, t1)
319 _ = lift (unify t1 t2) >>= \s3 ->
320 pure (compose s3 $ compose s2 s1, t1)
321
322 //the type class inferes the type of an AST element (VarDecl or FunDecl)
323 //and adds it to the AST element
324 class type a :: a -> Typing (Substitution, a)
325
326 instance type VarDecl where
327 type (VarDecl p expected k e) =
328 infer e >>= \(s1, given) ->
329 applySubst s1 >>|
330 case expected of
331 Nothing = pure zero
332 Just expected_ = lift (unify expected_ given)
333 >>= \s2->
334 applySubst s2 >>|
335 let vtype = subst (compose s2 s1) given in
336 generalize vtype >>= \t ->
337 changeGamma (extend k t) >>|
338 pure (compose s2 s1, VarDecl p (Just vtype) k e)
339
340 instance type FunDecl where
341 type (FunDecl p f args expected vds stmts) =
342 gamma >>= \outerScope-> //functions are infered in their own scopde
343 introduce f >>|
344 mapM introduce args >>= \argTs->
345 type vds >>= \(s1, tVds)->
346 applySubst s1 >>|
347 infer stmts >>= \(s2, result)->
348 applySubst s1 >>|
349 let argTs_ = map (subst $ compose s2 s1) argTs in
350 //abort (concat $ intersperse "\n" $ map toString argTs_) >>|
351 let given = foldr (->>) result argTs_ in
352 (case expected of
353 Nothing = pure zero
354 Just expected_ = lift (unify expected_ given))
355 >>= \s3 ->
356 let ftype = subst (compose s3 $ compose s2 s1) given in
357 generalize ftype >>= \t->
358 putGamma outerScope >>|
359 changeGamma (extend f t) >>|
360 pure (compose s3 $ compose s2 s1, FunDecl p f args (Just ftype) tVds stmts)
361
362 instance type [a] | type a where
363 type [] = pure (zero, [])
364 type [v:vs] =
365 type v >>= \(s1, v_)->
366 applySubst s1 >>|
367 type vs >>= \(s2, vs_)->
368 applySubst (compose s2 s1) >>|
369 pure (compose s2 s1, [v_:vs_])
370
371 introduce :: String -> Typing Type
372 introduce k =
373 fresh >>= \tv ->
374 changeGamma (extend k (Forall [] tv)) >>|
375 pure tv
376
377 instance toString Scheme where
378 toString (Forall x t) =
379 concat ["Forall ": intersperse "," x] +++ concat [". ", toString t];
380
381 instance toString Gamma where
382 toString mp =
383 concat [concat [k, ": ", toString v, "\n"]\\(k, v)<-'Map'.toList mp]
384
385 instance toString Substitution where
386 toString subs =
387 concat [concat [k, ": ", toString t, "\n"]\\(k, t)<-'Map'.toList subs]
388
389 instance toString SemError where
390 toString (SanityError p e) = concat [toString p,
391 "SemError: SanityError: ", e]
392 toString (ParseError p s) = concat [toString p,
393 "ParseError: ", s]
394 toString (UnifyError p t1 t2) = concat [toString p,
395 "Can not unify types, expected|given:\n", toString t1,
396 "\n", toString t2]
397 toString (InfiniteTypeError p t) = concat [toString p,
398 "Infinite type: ", toString t]
399 toString (FieldSelectorError p t fs) = concat [toString p,
400 "Can not run fieldselector '", toString fs, "' on type: ",
401 toString t]
402 toString (OperatorError p op t) = concat [toString p,
403 "Operator error, operator '", toString op, "' can not be",
404 "used on type: ", toString t]
405 toString (UndeclaredVariableError p k) = concat [toString p,
406 "Undeclared identifier: ", k]
407 toString (ArgumentMisMatchError p str) = concat [toString p,
408 "Argument mismatch: ", str]
409 toString (Error e) = concat ["Unknown error during semantical",
410 "analysis: ", e]
411
412 instance toString (Maybe a) | toString a where
413 toString Nothing = "Nothing"
414 toString (Just e) = concat ["Just ", toString e]
415
416 instance MonadTrans (StateT (Gamma, [TVar])) where
417 liftT m = StateT \s-> m >>= \a-> return (a, s)
418
419 Mapmap :: (a->b) ('Map'.Map k a) -> ('Map'.Map k b)
420 Mapmap _ 'Map'.Tip = 'Map'.Tip
421 Mapmap f ('Map'.Bin sz k v ml mr) = 'Map'.Bin sz k (f v)
422 (Mapmap f ml)
423 (Mapmap f mr)