76cde8cf9669507d300fc561ca13a6287ec266c1
[minfp.git] / check.icl
1 implementation module check
2
3 import StdEnv
4
5 import Control.Monad => qualified join
6 import Control.Monad.State
7 import Control.Monad.Trans
8 import Control.Monad.Writer
9 import Data.Either
10 import Data.Func
11 import Data.List
12 import Data.Tuple
13 import Data.Map => qualified put, union, difference, find, updateAt
14 import Data.Maybe
15 import Text
16
17 import ast, scc
18
19 check :: [Function] -> Either [String] (Expression, [([Char], Scheme)])
20 check fs
21 # dups = filter (\x->length x > 1) (groupBy (\(Function i _ _) (Function j _ _)->i == j) fs)
22 | length dups > 0 = Left ["Duplicate functions: ":[toString n\\[(Function n _ _):_]<-dups]]
23 = case partition (\a->a=:(Function ['start'] _ _)) fs of
24 ([], _) = Left ["No start function defined"]
25 ([Function _ [] e:_], fs) = (\x->(e, x)) <$> runInfer (infer preamble (makeExpression fs e))
26 ([Function _ _ _:_], _) = Left ["Start cannot have arguments"]
27
28 makeExpression :: [Function] Expression -> Expression
29 makeExpression fs start = foldr mkExpr start $ scc [(l, vars e [])\\(l, e)<-nicefuns]
30 where
31 mkExpr :: [[Char]] -> (Expression -> Expression)
32 mkExpr scc = Let [(l, e)\\(l, e)<-nicefuns, s<-scc | s == l]
33
34 nicefuns :: [([Char], Expression)]
35 nicefuns = [(l, foldr (\x c->Lambda x o c) id i e)\\(Function l i e)<-fs]
36
37 vars :: Expression [[Char]] -> [[Char]]
38 vars (Var v=:[m:_]) c = [v:c]
39 vars (App l r) c = vars l $ vars r c
40 vars (Lambda l e) c = [v\\v<-vars e c | v <> l]
41 vars (Let ns e) c = flatten
42 [ [v\\v<-vars e c | not (isMember v (map fst ns))]
43 : map (\(i, e)->[v\\v<-vars e [] | v <> i]) ns]
44 vars _ c = c
45
46 instance toString Scheme where
47 toString (Forall [] t) = toString t
48 toString (Forall as t) = concat ["A.", join " " (map toString as), ": ", toString t]
49
50 instance toString Type where
51 toString (TVar a) = toString a
52 toString TInt = "Int"
53 toString TBool = "Bool"
54 toString (a --> b) = concat ["(", toString a, " -> ", toString b, ")"]
55
56 :: TypeEnv :== Map [Char] Scheme
57 preamble :: TypeEnv
58 preamble = fromList
59 [(['_if'], Forall [['_ift']]
60 $ TBool --> TVar ['_ift'] --> TVar ['_ift'] --> TVar ['_ift'])
61 ,(['_eq'], Forall [['_eq']] $ TInt --> TInt --> TBool)
62 ,(['_mul'], Forall [['_mul']] $ TInt --> TInt --> TInt)
63 ,(['_add'], Forall [['_add']] $ TInt --> TInt --> TInt)
64 ,(['_sub'], Forall [['_sub']] $ TInt --> TInt --> TInt)
65 ]
66 :: Subst :== Map [Char] Type
67
68 :: Infer a :== StateT [Int] (WriterT [([Char], Scheme)] (Either [String])) a
69
70 runInfer :: (Infer (Subst, Type)) -> Either [String] [([Char], Scheme)]
71 runInfer i = case runWriterT (evalStateT i [0..]) of
72 Left e = Left e
73 Right ((s, t), w) = pure [(['start'], generalize newMap (apply s t)):w]
74
75 fresh :: Infer Type
76 fresh = getState >>= \[s:ss]->put ss >>| pure (TVar (['v':[c\\c<-:toString s]]))
77
78 (oo) infixl 9 :: Subst Subst -> Subst
79 (oo) s1 s2 = 'Data.Map'.union (apply s1 <$> s2) s1
80
81 class Substitutable a where
82 apply :: Subst a -> a
83 ftv :: a -> [[Char]]
84
85 instance Substitutable Type where
86 apply s t=:(TVar v) = fromMaybe t (get v s)
87 apply s (t1 --> t2) = apply s t1 --> apply s t2
88 apply _ x = x
89
90 ftv (TVar v) = [v]
91 ftv (t1 --> t2) = on union ftv t1 t2
92 ftv _ = []
93
94 instance Substitutable Scheme where
95 apply s (Forall as t) = Forall as $ apply (foldr del s as) t
96 ftv (Forall as t) = difference (ftv t) (removeDup as)
97
98 instance Substitutable TypeEnv where
99 apply s env = apply s <$> env
100 ftv env = ftv (elems env)
101
102 instance Substitutable [a] | Substitutable a where
103 apply s l = apply s <$> l
104 ftv t = foldr (union o ftv) [] t
105
106 occursCheck :: [Char] -> (a -> Bool) | Substitutable a
107 occursCheck a = isMember a o ftv
108
109 err :: [String] -> Infer a
110 err e = liftT (liftT (Left e))
111
112 unify :: Type Type -> Infer Subst
113 unify (l --> r) (l` --> r`)
114 = unify l l`
115 >>= \s1->on unify (apply s1) r r`
116 >>= \s2->pure (s1 oo s2)
117 unify (TVar a) (TVar t)
118 | a == t = pure newMap
119 unify (TVar a) t
120 | occursCheck a t = err ["Infinite type: ", toString a, " to ", toString t]
121 = pure (singleton a t)
122 unify t (TVar a) = unify (TVar a) t
123 unify TInt TInt = pure newMap
124 unify TBool TBool = pure newMap
125 unify t1 t2 = err ["Cannot unify: ", toString t1, " with ", toString t2]
126
127 unifyl :: [Type] -> Infer Subst
128 unifyl [t1,t2:ts] = unify t1 t2 >>= \s->unifyl (map (apply s) [t2:ts])
129 unifyl _ = pure newMap
130
131 instantiate :: Scheme -> Infer Type
132 instantiate (Forall as t)
133 = sequence [fresh\\_<-as]
134 >>= \as`->pure (apply (fromList $ zip2 as as`) t)
135
136 generalize :: TypeEnv Type -> Scheme
137 generalize env t = Forall (difference (ftv t) (ftv env)) t
138
139 infer :: TypeEnv Expression -> Infer (Subst, Type)
140 infer env (Lit (Int _)) = pure (newMap, TInt)
141 infer env (Lit (Bool _)) = pure (newMap, TBool)
142 infer env (Var x) = maybe (err ["Unbound variable: ", toString x])
143 (\s->tuple newMap <$> instantiate s) $ get x env
144 infer env (App e1 e2)
145 = fresh
146 >>= \tv-> infer env e1
147 >>= \(s1, t1)->infer (apply s1 env) e2
148 >>= \(s2, t2)->unify (apply s2 t1) (t2 --> tv)
149 >>= \s3-> pure (s3 oo s2 oo s1, apply s3 tv)
150 infer env (Lambda x b)
151 = fresh
152 >>= \tv-> infer ('Data.Map'.put x (Forall [] tv) env) b
153 >>= \(s1, t1)->pure (s1, apply s1 tv --> t1)
154 //Non recursion
155 //infer env (Let [(x, e1)] e2)
156 // = infer env e1
157 // >>= \(s1, t1)->infer ('Data.Map'.put x (generalize (apply s1 env) t1) env) e2
158 // >>= \(s2, t2)->liftT (tell [(x, Forall [] t1)])
159 // >>| pure (s1 oo s2, t2)
160 //Single recursion
161 //infer env (Let [(x, e1)] e2)
162 // = fresh
163 // >>= \tv-> let env` = 'Data.Map'.put x (Forall [] tv) env
164 // in infer env` e1
165 // >>= \(s1,t1)-> infer ('Data.Map'.put x (generalize (apply s1 env`) t1) env`) e2
166 // >>= \(s2, t2)->pure (s1 oo s2, t2)
167 //Multiple recursion
168 infer env (Let xs e2)
169 # (ns, bs) = unzip xs
170 = sequence [fresh\\_<-ns]
171 >>= \tvs-> let env` = foldr (\(k, v)->'Data.Map'.put k (Forall [] v)) env (zip2 ns tvs)
172 in unzip <$> sequence (map (infer env`) bs)
173 >>= \(ss,ts)-> unifyl ts
174 >>= \s-> liftT (tell [(n, generalize (apply s env`) t)\\t<-ts & n<-ns])
175 >>| let env`` = foldr (\(n, s, t) m->'Data.Map'.put n (generalize (apply s env`) t) m) env` (zip3 ns ss ts)
176 in infer env`` e2
177 >>= \(s2, t2)->pure (s oo s2, t2)