import StdEnv
+import Control.Monad => qualified join
+import Control.Monad.State
+import Control.Monad.Trans
import Data.Either
-import Data.List
-import Data.Functor
import Data.Func
+import Data.List
+import Data.Map => qualified put, union, difference, find, updateAt
import Data.Maybe
-import Data.Tuple
-import Control.Monad => qualified join
-import Control.Monad.Trans
-import Control.Monad.State
import Text
-import qualified Data.Map
-from Data.Map import :: Map(..), newMap, get, instance Functor (Map k)
-
import ast
-check :: [Function] -> Either [String] Expression
+check :: [Function] -> Either [String] (Expression, Scheme)
check fs
# dups = filter (\x->length x > 1) (groupBy (\(Function i _ _) (Function j _ _)->i == j) fs)
| length dups > 0 = Left ["Duplicate functions: ":[toString n\\[(Function n _ _):_]<-dups]]
([], _) = Left ["No start function defined"]
([Function _ [] e], fs)
# e = foldr (\(Function i a e)->Let i (foldr ((o) o Lambda) id a e)) e fs
- = case runInfer (infer newMap e) of
- Left e = Left e
- Right s = Left [toString s]
+ = (\x->(e, x)) <$> runInfer (infer newMap e)
([Function _ _ _], _) = Left ["Start cannot have arguments"]
instance toString Scheme where
ftv _ = []
instance Substitutable Scheme where
- apply s (Forall as t) = Forall as $ apply (foldr 'Data.Map'.del s as) t
+ apply s (Forall as t) = Forall as $ apply (foldr del s as) t
ftv (Forall as t) = difference (ftv t) (removeDup as)
instance Substitutable TypeEnv where
apply s env = apply s <$> env
- ftv env = ftv ('Data.Map'.elems env)
+ ftv env = ftv (elems env)
instance Substitutable [a] | Substitutable a where
apply s l = apply s <$> l
>>= \s2->pure (compose s1 s2)
unify (TVar a) t = bind a t
unify t (TVar a) = bind a t
-unify TInt TInt = pure 'Data.Map'.newMap
-unify TBool TBool = pure 'Data.Map'.newMap
+unify TInt TInt = pure newMap
+unify TBool TBool = pure newMap
unify t1 t2 = liftT (Left ["Cannot unify: ", toString t1, " with ", toString t2])
bind :: [Char] Type -> Infer Subst
-bind a (TVar t) | a == t = pure 'Data.Map'.newMap
+bind a (TVar t) | a == t = pure newMap
bind a t
| occursCheck a t = liftT (Left ["Infinite type: ", toString a, " and ", toString t])
- = pure ('Data.Map'.singleton a t)
+ = pure (singleton a t)
instantiate :: Scheme -> Infer Type
instantiate (Forall as t)
= sequence [fresh\\_<-as]
- >>= \as`->pure (apply ('Data.Map'.fromList $ zip2 as as`) t)
+ >>= \as`->pure (apply (fromList $ zip2 as as`) t)
generalize :: TypeEnv Type -> Scheme
generalize env t = Forall (difference (ftv t) (ftv env)) t
infer :: TypeEnv Expression -> Infer (Subst, Type)
-infer env (Lit (Int _)) = pure ('Data.Map'.newMap, TInt)
-infer env (Lit (Bool _)) = pure ('Data.Map'.newMap, TBool)
-infer env (Var x) = case 'Data.Map'.get x env of
+infer env (Lit (Int _)) = pure (newMap, TInt)
+infer env (Lit (Bool _)) = pure (newMap, TBool)
+infer env (Var x) = case get x env of
Nothing = liftT (Left ["Unbound variable: ", toString x])
- Just s = tuple 'Data.Map'.newMap <$> instantiate s
+ Just s = (\x->(newMap, x)) <$> instantiate s
infer env (App e1 e2)
= fresh
>>= \tv-> infer env e1