reverted Hindley-Milner type checker to before mutual recursion merge

This commit is contained in:
sebastian 2023-04-01 17:10:26 +02:00
parent ec57712eec
commit 4b14cbdebf

View file

@ -6,20 +6,20 @@
-- | A module for type checking and inference using algorithm W, Hindley-Milner -- | A module for type checking and inference using algorithm W, Hindley-Milner
module TypeChecker.TypeCheckerHm where module TypeChecker.TypeCheckerHm where
import Auxiliary (int, litType, maybeToRightM, unzip4) import Auxiliary (int, litType, maybeToRightM, tupSequence, unzip4)
import Auxiliary qualified as Aux import Auxiliary qualified as Aux
import Control.Arrow ((&&&))
import Control.Monad.Except import Control.Monad.Except
import Control.Monad.Identity (Identity, runIdentity) import Control.Monad.Identity (Identity, runIdentity)
import Control.Monad.Reader import Control.Monad.Reader
import Control.Monad.State import Control.Monad.State
import Data.Bifunctor (first)
import Data.Coerce (coerce) import Data.Coerce (coerce)
import Data.Function (on) import Data.Function (on)
import Data.List (foldl', intercalate) import Data.List (foldl')
import Data.List.Extra (unsnoc) import Data.List.Extra (unsnoc)
import Data.Map (Map) import Data.Map (Map)
import Data.Map qualified as M import Data.Map qualified as M
import Data.Maybe (fromJust, fromMaybe, mapMaybe) import Data.Maybe (fromJust)
import Data.Set (Set) import Data.Set (Set)
import Data.Set qualified as S import Data.Set qualified as S
import Debug.Trace (trace) import Debug.Trace (trace)
@ -27,6 +27,8 @@ import Grammar.Abs
import Grammar.Print (printTree) import Grammar.Print (printTree)
import TypeChecker.TypeCheckerIr qualified as T import TypeChecker.TypeCheckerIr qualified as T
-- TODO: Disallow mutual recursion
-- | Type check a program -- | Type check a program
typecheck :: Program -> Either String (T.Program' Type) typecheck :: Program -> Either String (T.Program' Type)
typecheck = onLeft msg . run . checkPrg typecheck = onLeft msg . run . checkPrg
@ -36,16 +38,20 @@ typecheck = onLeft msg . run . checkPrg
onLeft _ (Right x) = Right x onLeft _ (Right x) = Right x
checkPrg :: Program -> Infer (T.Program' Type) checkPrg :: Program -> Infer (T.Program' Type)
checkPrg (Program bs) = T.Program <$> (preRun bs >> checkDef bs >>= mapM substPrg) checkPrg (Program bs) = do
preRun bs
bs <- checkDef bs
sub0 <- solveUndecidable
bs <- mapM (mono sub0) bs
return $ T.Program bs
substPrg :: T.Def' Type -> Infer (T.Def' Type) mono :: Subst -> T.Def' Type -> Infer (T.Def' Type)
substPrg (T.DBind (T.Bind (name, t) args e)) = do mono s bind@(T.DBind (T.Bind (name, t) args e)) = do
(bu, sub) <- gets (bindUsages &&& bindSubs) b <- gets (S.member name . toDecide)
let uses = fromMaybe [] $ M.lookup name bu if b
let subs = mapMaybe (`M.lookup` sub) (name : uses) then return $ T.DBind $ T.Bind (name, apply s t) (apply s args) (apply s e)
sub <- foldM composey nullSubst (reverse subs) else return bind
return . T.DBind $ T.Bind (name, apply sub t) (apply sub args) (apply sub e) mono _ (T.DData d) = return $ T.DData d
substPrg d = return d
preRun :: [Def] -> Infer () preRun :: [Def] -> Infer ()
preRun [] = return () preRun [] = return ()
@ -56,8 +62,7 @@ preRun (x : xs) = case x of
duplicateDecl n s $ Aux.do duplicateDecl n s $ Aux.do
"Multiple signatures of function" "Multiple signatures of function"
quote $ printTree n quote $ printTree n
insertSig (coerce n) (Instantiated t) insertSig (coerce n) (Just t) >> preRun xs
preRun xs
DBind (Bind n _ e) -> do DBind (Bind n _ e) -> do
s <- gets (S.toList . declaredBinds) s <- gets (S.toList . declaredBinds)
duplicateDecl n s $ Aux.do duplicateDecl n s $ Aux.do
@ -65,17 +70,13 @@ preRun (x : xs) = case x of
quote $ printTree n quote $ printTree n
collect (collectTVars e) collect (collectTVars e)
insertBind $ coerce n insertBind $ coerce n
sigs <- gets sigs s <- gets sigs
case M.lookup (coerce n) sigs of case M.lookup (coerce n) s of
Nothing -> do Nothing -> insertSig (coerce n) Nothing >> preRun xs
fr <- fresh
insertSig (coerce n) (Generalized fr)
preRun xs
Just _ -> preRun xs Just _ -> preRun xs
DData d@(Data t _) -> collect (collectTVars t) >> checkData d >> preRun xs DData d@(Data t _) -> collect (collectTVars t) >> checkData d >> preRun xs
where where
-- Check if function body / signature has been declared already -- Check if function body / signature has been declared already
duplicateDecl :: (Monad m, MonadError Error m) => LIdent -> [T.Ident] -> String -> m ()
duplicateDecl n env msg = when (coerce n `elem` env) (uncatchableErr msg) duplicateDecl n env msg = when (coerce n `elem` env) (uncatchableErr msg)
checkDef :: [Def] -> Infer [T.Def' Type] checkDef :: [Def] -> Infer [T.Def' Type]
@ -100,16 +101,12 @@ checkBind bind@(Bind name args e) = do
(sub0, (e, lambda_t)) <- inferExp lambda (sub0, (e, lambda_t)) <- inferExp lambda
s <- gets sigs s <- gets sigs
case M.lookup (coerce name) s of case M.lookup (coerce name) s of
Just t -> do Just (Just t') -> do
let t' = case t of sub1 <- bindErr (unify lambda_t (skolemize t')) bind
Instantiated a -> skolemize a return $ T.Bind (coerce name, apply (sub1 `compose` sub0) t') [] (e, lambda_t)
Generalized a -> a
sub1 <- bindErr (unify t' lambda_t) bind
comp <- sub1 `composey` sub0
insertBindSubst (coerce name) comp
return (T.Bind (coerce name, apply comp t') [] (e, lambda_t))
_ -> do _ -> do
uncatchableErr $ "Undeclared function: " ++ printTree name insertSig (coerce name) (Just lambda_t)
return (T.Bind (coerce name, lambda_t) [] (e, lambda_t))
checkData :: (MonadState Env m, Monad m, MonadError Error m) => Data -> m () checkData :: (MonadState Env m, Monad m, MonadError Error m) => Data -> m ()
checkData err@(Data typ injs) = do checkData err@(Data typ injs) = do
@ -178,6 +175,7 @@ inferExp :: Exp -> Infer (Subst, T.ExpT' Type)
inferExp e = do inferExp e = do
(s, (e', t)) <- algoW e (s, (e', t)) <- algoW e
let subbed = apply s t let subbed = apply s t
modify (\st -> st{undecidedSigs = apply s st.undecidedSigs})
return (s, (e', subbed)) return (s, (e', subbed))
class CollectTVars a where class CollectTVars a where
@ -213,7 +211,7 @@ algoW = \case
quote $ printTree t' quote $ printTree t'
) )
let comp = sub2 `compose` sub1 `compose` sub0 let comp = sub2 `compose` sub1 `compose` sub0
return (comp, (e', t)) return (comp, apply comp (e', t))
-- \| ------------------ -- \| ------------------
-- \| Γ ⊢ i : Int, ∅ -- \| Γ ⊢ i : Int, ∅
@ -232,9 +230,11 @@ algoW = \case
sig <- gets sigs sig <- gets sigs
cb <- gets currentBind cb <- gets currentBind
case M.lookup (coerce i) sig of case M.lookup (coerce i) sig of
Just t -> do Just (Just t) -> return (nullSubst, (T.EVar $ coerce i, t))
insertBindUsage cb (coerce i) Just Nothing -> do
return (nullSubst, (T.EVar $ coerce i, unlevel t)) fr <- fresh
modify (\st -> st{toDecide = S.insert cb st.toDecide, undecidedSigs = M.insert (coerce $ concat [[prefix], i, [delim], coerce cb]) fr st.undecidedSigs})
return (nullSubst, (T.EVar $ coerce i, fr))
Nothing -> Nothing ->
uncatchableErr $ uncatchableErr $
"Unbound variable: " "Unbound variable: "
@ -259,7 +259,7 @@ algoW = \case
(s1, (e', t')) <- exprErr (algoW e) err (s1, (e', t')) <- exprErr (algoW e) err
let varType = apply s1 fr let varType = apply s1 fr
let newArr = TFun varType t' let newArr = TFun varType t'
return (s1, (T.EAbs (coerce name) (e', t'), newArr)) return (s1, apply s1 (T.EAbs (coerce name) (e', t'), newArr))
-- \| Γ ⊢ e₀ : τ₀, S₀ S₀Γ ⊢ e₁ : τ₁, S₁ -- \| Γ ⊢ e₀ : τ₀, S₀ S₀Γ ⊢ e₁ : τ₁, S₁
-- \| s₂ = mgu(s₁τ₀, Int) s₃ = mgu(s₂τ₁, Int) -- \| s₂ = mgu(s₁τ₀, Int) s₃ = mgu(s₂τ₁, Int)
@ -273,7 +273,10 @@ algoW = \case
s3 <- exprErr (unify (apply s2 t0) int) err s3 <- exprErr (unify (apply s2 t0) int) err
s4 <- exprErr (unify (apply s3 t1) int) err s4 <- exprErr (unify (apply s3 t1) int) err
let comp = s4 `compose` s3 `compose` s2 `compose` s1 let comp = s4 `compose` s3 `compose` s2 `compose` s1
return (comp, (T.EAdd (e0', t0) (e1', t1), int)) return
( comp
, apply comp (T.EAdd (e0', t0) (e1', t1), int)
)
-- \| Γ ⊢ e₀ : τ₀, S₀ S₀Γ ⊢ e₁ : τ₁, S1 -- \| Γ ⊢ e₀ : τ₀, S₀ S₀Γ ⊢ e₁ : τ₁, S1
-- \| τ' = newvar S₂ = mgu(S₁τ₀, τ₁ → τ') -- \| τ' = newvar S₂ = mgu(S₁τ₀, τ₁ → τ')
@ -284,11 +287,12 @@ algoW = \case
fr <- fresh fr <- fresh
(s0, (e0', t0)) <- algoW e0 (s0, (e0', t0)) <- algoW e0
applySt s0 $ do applySt s0 $ do
modify (\st -> st{sigs = apply s0 st.sigs})
(s1, (e1', t1)) <- algoW e1 (s1, (e1', t1)) <- algoW e1
s2 <- exprErr (unify (apply s1 t0) (TFun t1 fr)) err s2 <- exprErr (unify (apply s1 t0) (TFun t1 fr)) err
let t = apply s2 fr let t = apply s2 fr
comp <- foldM composey nullSubst [s2, s1, s0] let comp = s2 `compose` s1 `compose` s0
return (comp, (T.EApp (e0', t0) (e1', t1), t)) return (comp, apply comp (T.EApp (e0', t0) (e1', t1), t))
-- \| Γ ⊢ e₀ : τ, S₀ S₀Γ, x : S̅₀Γ̅(τ) ⊢ e₁ : τ', S₁ -- \| Γ ⊢ e₀ : τ, S₀ S₀Γ, x : S̅₀Γ̅(τ) ⊢ e₁ : τ', S₁
-- \| ---------------------------------------------- -- \| ----------------------------------------------
@ -296,23 +300,20 @@ algoW = \case
-- The bar over S₀ and Γ means "generalize" -- The bar over S₀ and Γ means "generalize"
(ELet (Bind name args e) e1) -> do err@(ELet b@(Bind name args e) e1) -> do
(s1, (e, t0)) <- algoW (makeLambda e (coerce args)) (s1, (_, t0)) <- algoW (makeLambda e (coerce args))
bind' <- exprErr (checkBind b) err
env <- asks vars env <- asks vars
let t' = generalize (apply s1 env) t0 let t' = generalize (apply s1 env) t0
withBinding (coerce name) t' $ do withBinding (coerce name) t' $ do
(s2, (e1', t2)) <- algoW e1 (s2, (e1', t2)) <- algoW e1
let comp = s2 `compose` s1 let comp = s2 `compose` s1
return return (comp, apply comp (T.ELet bind' (e1', t2), t2))
( comp
, (T.ELet (T.Bind (coerce name, t0) [] (e, t0)) (e1', t2), t2)
)
ECase caseExpr injs -> do ECase caseExpr injs -> do
(sub, (e', t)) <- algoW caseExpr (sub, (e', t)) <- algoW caseExpr
(subst, injs, ret_t) <- checkCase t injs (subst, injs, ret_t) <- checkCase t injs
let comp = subst `compose` sub let comp = subst `compose` sub
-- return (comp, apply comp (T.ECase (e', t) injs, ret_t)) return (comp, apply comp (T.ECase (e', t) injs, ret_t))
return (comp, (T.ECase (e', t) injs, ret_t))
EAppInf{} -> error "desugar phase failed" EAppInf{} -> error "desugar phase failed"
checkCase :: Type -> [Branch] -> Infer (Subst, [T.Branch' Type], Type) checkCase :: Type -> [Branch] -> Infer (Subst, [T.Branch' Type], Type)
@ -421,17 +422,15 @@ unify t0 t1 =
s1 <- unify a c s1 <- unify a c
s2 <- unify (apply s1 b) (apply s1 d) s2 <- unify (apply s1 b) (apply s1 d)
return $ s2 `compose` s1 return $ s2 `compose` s1
(TVar (MkTVar a), t@(TData _ _)) -> (TVar (MkTVar a), t@(TData _ _)) -> return $ M.singleton (coerce a) t
return $ coerce $ M.singleton (coerce a) t (t@(TData _ _), TVar (MkTVar b)) -> return $ M.singleton (coerce b) t
(t@(TData _ _), TVar (MkTVar b)) ->
return $ coerce $ M.singleton (coerce b) t
(TVar (MkTVar a), t) -> occurs (coerce a) t (TVar (MkTVar a), t) -> occurs (coerce a) t
(t, TVar (MkTVar b)) -> occurs (coerce b) t (t, TVar (MkTVar b)) -> occurs (coerce b) t
(TAll _ t, b) -> unify t b (TAll _ t, b) -> unify t b
(a, TAll _ t) -> unify a t (a, TAll _ t) -> unify a t
(TLit a, TLit b) -> (TLit a, TLit b) ->
if a == b if a == b
then return nullSubst then return M.empty
else catchableErr $ else catchableErr $
Aux.do Aux.do
"Can not unify" "Can not unify"
@ -453,7 +452,7 @@ unify t0 t1 =
quote $ printTree t' quote $ printTree t'
(TEVar a, TEVar b) -> (TEVar a, TEVar b) ->
if a == b if a == b
then return nullSubst then return M.empty
else catchableErr $ else catchableErr $
Aux.do Aux.do
"Can not unify" "Can not unify"
@ -473,7 +472,7 @@ I.E. { a = a -> b } is an unsolvable constraint since there is no substitution
where these are equal where these are equal
-} -}
occurs :: T.Ident -> Type -> Infer Subst occurs :: T.Ident -> Type -> Infer Subst
occurs i t@(TVar _) = return (coerce $ M.singleton i t) occurs i t@(TVar _) = return (M.singleton i t)
occurs i t = occurs i t =
if S.member i (free t) if S.member i (free t)
then then
@ -484,7 +483,7 @@ occurs i t =
"with" "with"
quote $ printTree t quote $ printTree t
) )
else return $ coerce $ M.singleton i t else return $ M.singleton i t
{- | Generalize a type over all free variables in the substitution set {- | Generalize a type over all free variables in the substitution set
Used for let bindings to allow expression that do not type check in Used for let bindings to allow expression that do not type check in
@ -510,7 +509,7 @@ inst :: Type -> Infer Type
inst = \case inst = \case
TAll (MkTVar bound) t -> do TAll (MkTVar bound) t -> do
fr <- fresh fr <- fresh
let s = coerce $ M.singleton (coerce bound) fr let s = M.singleton (coerce bound) fr
apply s <$> inst t apply s <$> inst t
TFun t1 t2 -> TFun <$> inst t1 <*> inst t2 TFun t1 t2 -> TFun <$> inst t1 <*> inst t2
rest -> return rest rest -> return rest
@ -546,7 +545,6 @@ skolemize t = t
-- | A class for substitutions -- | A class for substitutions
class SubstType t where class SubstType t where
-- | Apply a substitution to t -- | Apply a substitution to t
-- apply :: MonadError e m => Subst -> t -> m t
apply :: Subst -> t -> t apply :: Subst -> t -> t
class FreeVars t where class FreeVars t where
@ -567,18 +565,19 @@ instance FreeVars a => FreeVars [a] where
free = let f acc x = acc `S.union` free x in foldl' f S.empty free = let f acc x = acc `S.union` free x in foldl' f S.empty
instance SubstType Type where instance SubstType Type where
apply sub@(Subst s) t = do apply :: Subst -> Type -> Type
apply sub t = do
case t of case t of
TLit a -> TLit a TLit a -> TLit a
TVar (MkTVar a) -> case M.lookup (coerce a) s of TVar (MkTVar a) -> case M.lookup (coerce a) sub of
Nothing -> TVar (MkTVar $ coerce a) Nothing -> TVar (MkTVar $ coerce a)
Just t -> t Just t -> t
TAll (MkTVar i) t -> case M.lookup (coerce i) s of TAll (MkTVar i) t -> case M.lookup (coerce i) sub of
Nothing -> TAll (MkTVar i) (apply sub t) Nothing -> TAll (MkTVar i) (apply sub t)
Just _ -> apply sub t Just _ -> apply sub t
TFun a b -> TFun (apply sub a) (apply sub b) TFun a b -> TFun (apply sub a) (apply sub b)
TData name a -> TData name (apply sub a) TData name a -> TData name (apply sub a)
TEVar (MkTEVar a) -> case M.lookup (coerce a) s of TEVar (MkTEVar a) -> case M.lookup (coerce a) sub of
Nothing -> TEVar (MkTEVar a) Nothing -> TEVar (MkTEVar a)
Just t -> t Just t -> t
@ -587,12 +586,11 @@ instance FreeVars (Map T.Ident Type) where
free = free . M.elems free = free . M.elems
instance SubstType (Map T.Ident Type) where instance SubstType (Map T.Ident Type) where
apply s = M.map (apply s) apply :: Subst -> Map T.Ident Type -> Map T.Ident Type
apply = M.map . apply
instance SubstType Subst where instance SubstType (Map T.Ident (Maybe Type)) where
apply s (Subst m2) = Subst $ apply s m2 apply s = M.map (fmap $ apply s)
-- Subst $ M.map (apply s) m2
instance SubstType (T.ExpT' Type) where instance SubstType (T.ExpT' Type) where
apply s (e, t) = (apply s e, apply s t) apply s (e, t) = (apply s e, apply s t)
@ -613,8 +611,7 @@ instance SubstType (T.Exp' Type) where
instance SubstType (T.Def' Type) where instance SubstType (T.Def' Type) where
apply s = \case apply s = \case
T.DBind (T.Bind name args e) -> T.DBind (T.Bind name args e) -> T.DBind $ T.Bind (apply s name) (apply s args) (apply s e)
T.DBind $ T.Bind (apply s name) (apply s args) (apply s e)
d -> d d -> d
instance SubstType (T.Branch' Type) where instance SubstType (T.Branch' Type) where
@ -639,49 +636,16 @@ instance SubstType (T.Id' Type) where
-- | Represents the empty substition set -- | Represents the empty substition set
nullSubst :: Subst nullSubst :: Subst
nullSubst = Subst mempty nullSubst = mempty
-- | Compose two substitution sets -- | Compose two substitution sets
compose :: Subst -> Subst -> Subst compose :: Subst -> Subst -> Subst
compose m1 m2 = Subst $ M.map (apply $ coerce m1) (coerce m2) `M.union` coerce m1 compose m1 m2 = M.map (apply m1) m2 `M.union` m1
-- Order matters.
{-
sub0 = Subst $ (M.singleton "a" (arr d e))
`M.union` (M.singleton "b" (arr d f))
`M.union` (M.singleton "c" (arr f e))
sub1 = Subst $ (M.singleton "a" (arr g bool))
`M.union` (M.singleton "b" (arr g bool))
`M.union` (M.singleton "c" (arr bool bool))
`M.union` (M.singleton "h" bool)
`M.union` (M.singleton "i" bool)
sub0 `composey` sub1 != sub1 `composey` sub0
-}
composey :: Subst -> Subst -> Infer Subst
composey s0@(Subst m1) s1@(Subst m2) = do
let both = M.keys $ M.intersection m1 m2
case both of
[] -> return $ s0 `compose` s1
xs -> do
let m2' = apply s0 m2
sub <- loop xs m1 m2'
return $ sub `compose` Subst m2
where
loop [] _ _ = return nullSubst
loop (x : xs) m1 m2 = do
let k1 = m1 M.! x
let k2 = m2 M.! x
sub <- unify k1 k2
subs <- loop xs m1 m2
return $ sub `compose` subs
-- | Compose a list of substitution sets into one -- | Compose a list of substitution sets into one
composeAll :: [Subst] -> Subst composeAll :: [Subst] -> Subst
composeAll = foldl' compose nullSubst composeAll = foldl' compose nullSubst
unionSubsts :: [Subst] -> Subst
unionSubsts = Subst . foldl' M.union M.empty . map coerce
{- | Convert a function with arguments to its pointfree version {- | Convert a function with arguments to its pointfree version
> makeLambda (add x y = x + y) = add = \x. \y. x + y > makeLambda (add x y = x + y) = add = \x. \y. x + y
-} -}
@ -707,21 +671,12 @@ withPattern p ma = case p of
T.PEnum _ -> ma T.PEnum _ -> ma
-- | Insert a function signature into the environment -- | Insert a function signature into the environment
insertSig :: T.Ident -> Level Type -> Infer () insertSig :: T.Ident -> Maybe Type -> Infer ()
insertSig i t = modify (\st -> st{sigs = M.insert i t (sigs st)}) insertSig i t = modify (\st -> st{sigs = M.insert i t (sigs st)})
insertBind :: T.Ident -> Infer () insertBind :: T.Ident -> Infer ()
insertBind i = modify (\st -> st{declaredBinds = S.insert i st.declaredBinds}) insertBind i = modify (\st -> st{declaredBinds = S.insert i st.declaredBinds})
insertBindSubst :: T.Ident -> Subst -> Infer ()
insertBindSubst name sub = modify (\st -> st{bindSubs = M.insert name sub st.bindSubs})
setCurrentBind :: T.Ident -> Infer ()
setCurrentBind n = modify (\st -> st{currentBind = n, bindUsages = M.insertWith (++) n [] st.bindUsages})
insertBindUsage :: T.Ident -> T.Ident -> Infer ()
insertBindUsage cur use = modify (\st -> st{bindUsages = M.insertWith (++) cur [use] st.bindUsages})
-- | Insert a constructor into the start with its type -- | Insert a constructor into the start with its type
insertInj :: (Monad m, MonadState Env m) => T.Ident -> Type -> m () insertInj :: (Monad m, MonadState Env m) => T.Ident -> Type -> m ()
insertInj i t = insertInj i t =
@ -736,6 +691,24 @@ with an equivalent name has been declared already
existInj :: (Monad m, MonadState Env m) => T.Ident -> m (Maybe Type) existInj :: (Monad m, MonadState Env m) => T.Ident -> m (Maybe Type)
existInj n = gets (M.lookup n . injections) existInj n = gets (M.lookup n . injections)
setCurrentBind :: T.Ident -> Infer ()
setCurrentBind i = modify (\st -> st{currentBind = i})
solveUndecidable :: Infer Subst
solveUndecidable = do
sigs <- gets sigs
undecided <- gets undecidedSigs
ys <-
maybeToRightM
(Error "SIGNATURE MISSING" False)
( mapM (tupSequence . first (join . flip M.lookup sigs . getOriginal)) $
M.toList undecided
)
composeAll <$> mapM (uncurry unify) ys
getOriginal :: T.Ident -> T.Ident
getOriginal (T.Ident i) = coerce $ takeWhile (/= delim) $ drop 1 i
delim :: Char delim :: Char
delim = '_' delim = '_'
prefix :: Char prefix :: Char
@ -812,7 +785,7 @@ dataErr ma d =
) )
initCtx = Ctx mempty initCtx = Ctx mempty
initEnv = Env 0 'a' mempty mempty mempty mempty "" mempty mempty initEnv = Env 0 'a' mempty mempty mempty "" mempty mempty mempty
run :: Infer a -> Either Error a run :: Infer a -> Either Error a
run = run' initEnv initCtx run = run' initEnv initCtx
@ -831,28 +804,19 @@ newtype Ctx = Ctx {vars :: Map T.Ident Type}
data Env = Env data Env = Env
{ count :: Int { count :: Int
, nextChar :: Char , nextChar :: Char
, sigs :: Map T.Ident (Level Type) , sigs :: Map T.Ident (Maybe Type)
, takenTypeVars :: Set T.Ident , takenTypeVars :: Set T.Ident
, injections :: Map T.Ident Type , injections :: Map T.Ident Type
, declaredBinds :: Set T.Ident
, currentBind :: T.Ident , currentBind :: T.Ident
, bindSubs :: Map T.Ident Subst , undecidedSigs :: Map T.Ident Type
, bindUsages :: Map T.Ident [T.Ident] , toDecide :: Set T.Ident
, declaredBinds :: Set T.Ident
} }
deriving (Show) deriving (Show)
data Level a = Instantiated {unlevel :: a} | Generalized {unlevel :: a}
deriving (Show)
data Error = Error {msg :: String, catchable :: Bool} data Error = Error {msg :: String, catchable :: Bool}
deriving (Show) deriving (Show)
type Subst = Map T.Ident Type
newtype Subst = Subst (Map T.Ident Type)
instance Show Subst where
show (Subst s) = "[ " ++ intercalate " | " xs ++ " ]"
where
xs = map (\(a, b) -> printTree a ++ " = " ++ printTree b) $ M.toList s
newtype Infer a = Infer {runInfer :: StateT Env (ReaderT Ctx (ExceptT Error Identity)) a} newtype Infer a = Infer {runInfer :: StateT Env (ReaderT Ctx (ExceptT Error Identity)) a}
deriving (Functor, Applicative, Monad, MonadReader Ctx, MonadError Error, MonadState Env) deriving (Functor, Applicative, Monad, MonadReader Ctx, MonadError Error, MonadState Env)
@ -868,3 +832,4 @@ quote s = "'" ++ s ++ "'"
ctrace :: (Monad m, Show a) => String -> a -> m () ctrace :: (Monad m, Show a) => String -> a -> m ()
ctrace str a = trace (str ++ ": " ++ show a) pure () ctrace str a = trace (str ++ ": " ++ show a) pure ()