unified top level type with expression type
This commit is contained in:
parent
62724964d7
commit
c3ea343d00
2 changed files with 23 additions and 32 deletions
|
|
@ -9,13 +9,13 @@ import Control.Monad.Reader
|
||||||
import Control.Monad.State
|
import Control.Monad.State
|
||||||
import Data.Foldable (traverse_)
|
import Data.Foldable (traverse_)
|
||||||
import Data.Functor.Identity (runIdentity)
|
import Data.Functor.Identity (runIdentity)
|
||||||
import Debug.Trace (trace)
|
|
||||||
import Data.List (foldl')
|
import Data.List (foldl')
|
||||||
import Data.Map (Map)
|
import Data.Map (Map)
|
||||||
import Data.Map qualified as M
|
import Data.Map qualified as M
|
||||||
|
import Data.Maybe (fromMaybe)
|
||||||
import Data.Set (Set)
|
import Data.Set (Set)
|
||||||
import Data.Set qualified as S
|
import Data.Set qualified as S
|
||||||
import Data.Maybe (fromMaybe)
|
import Debug.Trace (trace)
|
||||||
import Grammar.Abs
|
import Grammar.Abs
|
||||||
import Grammar.Print (printTree)
|
import Grammar.Print (printTree)
|
||||||
import TypeChecker.TypeCheckerIr (
|
import TypeChecker.TypeCheckerIr (
|
||||||
|
|
@ -53,16 +53,16 @@ freshenData (Data (Constr name ts) constrs) = do
|
||||||
frs <- traverse (const fresh) xs
|
frs <- traverse (const fresh) xs
|
||||||
let m = M.fromList $ zip xs frs
|
let m = M.fromList $ zip xs frs
|
||||||
return $ Data (Constr name (map (freshenType m) ts)) (map (\(Constructor ident t) -> Constructor ident (freshenType m t)) constrs)
|
return $ Data (Constr name (map (freshenType m) ts)) (map (\(Constructor ident t) -> Constructor ident (freshenType m t)) constrs)
|
||||||
|
|
||||||
{- | Freshen all polymorphic variables, regardless of name
|
{- | Freshen all polymorphic variables, regardless of name
|
||||||
| freshenType "d" (a -> b -> c) becomes (d -> d -> d)
|
| freshenType "d" (a -> b -> c) becomes (d -> d -> d)
|
||||||
-}
|
-}
|
||||||
freshenType :: Map Ident Type -> Type -> Type
|
freshenType :: Map Ident Type -> Type -> Type
|
||||||
freshenType m t = case t of
|
freshenType m t = case t of
|
||||||
TPol poly -> fromMaybe (error "bug in \'free\'") (M.lookup poly m)
|
TPol poly -> fromMaybe (error "bug in \'free\'") (M.lookup poly m)
|
||||||
TMono mono -> TMono mono
|
TMono mono -> TMono mono
|
||||||
TArr t1 t2 -> TArr (freshenType m t1) (freshenType m t2)
|
TArr t1 t2 -> TArr (freshenType m t1) (freshenType m t2)
|
||||||
TConstr (Constr ident ts) -> TConstr (Constr ident (map (freshenType m) ts))
|
TConstr (Constr ident ts) -> TConstr (Constr ident (map (freshenType m) ts))
|
||||||
|
|
||||||
checkData :: Data -> Infer ()
|
checkData :: Data -> Infer ()
|
||||||
checkData d = do
|
checkData d = do
|
||||||
|
|
@ -115,10 +115,12 @@ checkPrg (Program bs) = do
|
||||||
d' <- freshenData d
|
d' <- freshenData d
|
||||||
fmap (T.DData d' :) (checkDef xs)
|
fmap (T.DData d' :) (checkDef xs)
|
||||||
|
|
||||||
|
-- TODO: Unify top level types with the types of the expressions beneath
|
||||||
|
-- PERHAPS DONE
|
||||||
checkBind :: Bind -> Infer T.Bind
|
checkBind :: Bind -> Infer T.Bind
|
||||||
checkBind (Bind n t _ args e) = do
|
checkBind (Bind n t _ args e) = do
|
||||||
(t', e') <- inferExp $ makeLambda e (reverse args)
|
(t', e) <- inferExp $ makeLambda e (reverse args)
|
||||||
s <- unify t t'
|
s <- unify t' t
|
||||||
let t'' = apply s t
|
let t'' = apply s t
|
||||||
unless
|
unless
|
||||||
(t `typeEq` t'')
|
(t `typeEq` t'')
|
||||||
|
|
@ -130,7 +132,7 @@ checkBind (Bind n t _ args e) = do
|
||||||
, printTree t''
|
, printTree t''
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
return $ T.Bind (n, t) e'
|
return $ T.Bind (n, t) (apply s e)
|
||||||
where
|
where
|
||||||
makeLambda :: Exp -> [Ident] -> Exp
|
makeLambda :: Exp -> [Ident] -> Exp
|
||||||
makeLambda = foldl (flip EAbs)
|
makeLambda = foldl (flip EAbs)
|
||||||
|
|
@ -287,7 +289,6 @@ algoW = \case
|
||||||
(s2, t2, e1') <- algoW e1
|
(s2, t2, e1') <- algoW e1
|
||||||
let composition = s2 `compose` s1
|
let composition = s2 `compose` s1
|
||||||
return (composition, t2, apply composition $ T.ELet (T.Bind (name, t2) e0') e1')
|
return (composition, t2, apply composition $ T.ELet (T.Bind (name, t2) e0') e1')
|
||||||
|
|
||||||
ECase caseExpr injs -> do
|
ECase caseExpr injs -> do
|
||||||
(_, t0, e0') <- algoW caseExpr
|
(_, t0, e0') <- algoW caseExpr
|
||||||
(injs', ts) <- mapAndUnzipM (checkInj t0) injs
|
(injs', ts) <- mapAndUnzipM (checkInj t0) injs
|
||||||
|
|
@ -340,7 +341,7 @@ I.E. { a = a -> b } is an unsolvable constraint since there is no substitution
|
||||||
where these are equal
|
where these are equal
|
||||||
-}
|
-}
|
||||||
occurs :: Ident -> Type -> Infer Subst
|
occurs :: Ident -> Type -> Infer Subst
|
||||||
occurs _ (TPol _) = return nullSubst
|
occurs i t@(TPol a) = 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
|
||||||
|
|
@ -414,14 +415,14 @@ instance FreeVars T.Exp where
|
||||||
free = error "free not implemented for T.Exp"
|
free = error "free not implemented for T.Exp"
|
||||||
apply :: Subst -> T.Exp -> T.Exp
|
apply :: Subst -> T.Exp -> T.Exp
|
||||||
apply s = \case
|
apply s = \case
|
||||||
T.EId (ident, t) -> T.EId (ident, apply s t)
|
T.EId (ident, t) -> T.EId (ident, apply s t)
|
||||||
T.ELit t lit -> T.ELit (apply s t) lit
|
T.ELit t lit -> T.ELit (apply s t) lit
|
||||||
T.ELet (T.Bind (ident, t) e1) e2 -> T.ELet (T.Bind (ident, apply s t) (apply s e1)) (apply s e2)
|
T.ELet (T.Bind (ident, t) e1) e2 -> T.ELet (T.Bind (ident, apply s t) (apply s e1)) (apply s e2)
|
||||||
T.EApp t e1 e2 -> T.EApp (apply s t) (apply s e1) (apply s e2)
|
T.EApp t e1 e2 -> T.EApp (apply s t) (apply s e1) (apply s e2)
|
||||||
T.EAdd t e1 e2 -> T.EAdd (apply s t) (apply s e1) (apply s e2)
|
T.EAdd t e1 e2 -> T.EAdd (apply s t) (apply s e1) (apply s e2)
|
||||||
T.EAbs t1 (ident, t2) e -> T.EAbs (apply s t1) (ident, apply s t2) (apply s e)
|
T.EAbs t1 (ident, t2) e -> T.EAbs (apply s t1) (ident, apply s t2) (apply s e)
|
||||||
T.ECase t e injs -> T.ECase (apply s t) (apply s e) (apply s injs)
|
T.ECase t e injs -> T.ECase (apply s t) (apply s e) (apply s injs)
|
||||||
|
|
||||||
instance FreeVars T.Inj where
|
instance FreeVars T.Inj where
|
||||||
free :: T.Inj -> Set Ident
|
free :: T.Inj -> Set Ident
|
||||||
free = undefined
|
free = undefined
|
||||||
|
|
@ -469,14 +470,12 @@ checkInj caseType (Inj it expr) = do
|
||||||
(args, t') <- initType caseType it
|
(args, t') <- initType caseType it
|
||||||
subst <- unify caseType t'
|
subst <- unify caseType t'
|
||||||
applySt subst $ do
|
applySt subst $ do
|
||||||
(_, t, e') <- local (\st -> st { vars = args `M.union` vars st }) (algoW expr)
|
(_, t, e') <- local (\st -> st{vars = args `M.union` vars st}) (algoW expr)
|
||||||
return (T.Inj (it, t') e', t)
|
return (T.Inj (it, t') e', t)
|
||||||
|
|
||||||
initType :: Type -> Init -> Infer (Map Ident Poly, Type)
|
initType :: Type -> Init -> Infer (Map Ident Poly, Type)
|
||||||
initType expected = \case
|
initType expected = \case
|
||||||
|
|
||||||
InitLit lit -> error "Pattern match on literals not implemented yet"
|
InitLit lit -> error "Pattern match on literals not implemented yet"
|
||||||
|
|
||||||
InitConstr c args -> do
|
InitConstr c args -> do
|
||||||
st <- gets constructors
|
st <- gets constructors
|
||||||
case M.lookup c st of
|
case M.lookup c st of
|
||||||
|
|
|
||||||
10
test_program
10
test_program
|
|
@ -1,10 +1,2 @@
|
||||||
data Maybe ('a) where {
|
|
||||||
Nothing : Maybe ('a)
|
|
||||||
Just : 'a -> Maybe ('a)
|
|
||||||
};
|
|
||||||
|
|
||||||
id : 'a -> 'a ;
|
id : 'a -> 'a ;
|
||||||
id x = x ;
|
id = \x. x ;
|
||||||
|
|
||||||
main : Maybe ('a -> 'a) ;
|
|
||||||
main = Just id ;
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue