initial pattern matching implementation. should be somewhat correct

This commit is contained in:
sebastian 2023-03-21 14:33:18 +01:00
parent 9cd2cdb511
commit 4c015a4aac
3 changed files with 32 additions and 28 deletions

View file

@ -118,11 +118,10 @@ 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) let lambda = makeLambda e (reverse args)
(t', e) <- inferExp lambda
s <- unify t' t s <- unify t' t
let t'' = apply s t let t'' = apply s t
unless unless
@ -296,10 +295,11 @@ algoW = \case
-- TODO: give caseExpr a concrete type before proceeding -- TODO: give caseExpr a concrete type before proceeding
-- probably by returning substitutions in the functions used in this body -- probably by returning substitutions in the functions used in this body
ECase caseExpr injs -> do ECase caseExpr injs -> do
(sub, _, e') <- algoW caseExpr (sub, t, e') <- algoW caseExpr
trace ("SUB: " ++ show sub) return () (subst, t) <- checkCase t injs
t <- checkCase caseExpr injs let composition = subst `compose` sub
return (sub, t, T.ECase t e' (map (\(Inj i _) -> T.Inj (i, t) e') injs)) let t' = apply composition t
return (composition, t', T.ECase t' e' (map (\(Inj i _) -> T.Inj (i, t') e') injs))
-- | Unify two types producing a new substitution -- | Unify two types producing a new substitution
unify :: Type -> Type -> Infer Subst unify :: Type -> Type -> Infer Subst
@ -328,12 +328,18 @@ unify t0 t1 = do
, printTree name' , printTree name'
, "(" ++ printTree t' ++ ")" , "(" ++ printTree t' ++ ")"
] ]
(a, b) -> (a, b) -> do
ctx <- ask
env <- get
throwError . unwords $ throwError . unwords $
[ "Type:" [ "Type:"
, printTree a , printTree a
, "can't be unified with:" , "can't be unified with:"
, printTree b , printTree b
, "\nCtx:"
, show ctx
, "\nEnv:"
, show env
] ]
{- | Check if a type is contained in another type. {- | Check if a type is contained in another type.
@ -464,23 +470,12 @@ insertConstr i t =
-------- PATTERN MATCHING --------- -------- PATTERN MATCHING ---------
unifyAll :: [Type] -> Infer [Subst] checkCase :: Type -> [Inj] -> Infer (Subst, Type)
unifyAll [] = return [] checkCase expT injs = do
unifyAll [_] = return [] (injs, returns) <- mapAndUnzipM checkInj injs
unifyAll (x : y : xs) = do (sub, _) <- foldM (\(sub, acc) x -> (\a -> (a `compose` sub, (a `apply` acc))) <$> unify x acc) (nullSubst, expT) injs
uni <- unify x y t <- foldM (\acc x -> (`apply` acc) <$> unify x acc) (head returns) (tail returns)
all <- unifyAll (y : xs) return (sub, t)
return $ uni : all
checkCase :: Exp -> [Inj] -> Infer Type
checkCase e injs = do
expT <- fst <$> inferExp e
(injTs, returns) <- mapAndUnzipM checkInj injs
unifyAll (expT : injTs)
subst <- foldl1 compose <$> zipWithM unify returns (tail returns)
let substed = map (apply subst) returns
unless (allSame substed || null substed) (throwError "Different return types of case, or no cases")
return $ head substed
{- | fst = type of init {- | fst = type of init
| snd = type of expr | snd = type of expr
@ -510,3 +505,5 @@ flattenType a = [a]
litType :: Literal -> Type litType :: Literal -> Type
litType (LInt _) = TMono "Int" litType (LInt _) = TMono "Int"
ctrace a = trace (show a) a

View file

@ -23,12 +23,13 @@ data Poly = Forall [Ident] Type
deriving (Show) deriving (Show)
newtype Ctx = Ctx {vars :: Map Ident Poly} newtype Ctx = Ctx {vars :: Map Ident Poly}
deriving Show
data Env = Env data Env = Env
{ count :: Int { count :: Int
, sigs :: Map Ident Type , sigs :: Map Ident Type
, constructors :: Map Ident Type , constructors :: Map Ident Type
} } deriving Show
type Error = String type Error = String
type Subst = Map Ident Type type Subst = Map Ident Type

View file

@ -3,7 +3,13 @@ data Bool () where {
False : Bool () False : Bool ()
}; };
main : Bool () -> _Int ; data Maybe ('a) where {
Nothing : Maybe ('a)
Just : 'a -> Maybe ('a)
};
main : Bool () -> Maybe (Bool ()) ;
main x = case x of { main x = case x of {
1 => 0 True => Nothing;
False => Just 0
} }