Commit e3e82257 authored by Michael Hanus 's avatar Michael Hanus
Browse files

Type inference tool added

parent df266301
......@@ -15,6 +15,7 @@ all:
@cd currytest && $(MAKE)
@cd genint && $(MAKE)
@cd importcalls && $(MAKE)
@cd typeinference && $(MAKE)
.PHONY: clean
clean:
......@@ -28,3 +29,4 @@ clean:
cd currytest && $(MAKE) clean
cd genint && $(MAKE) clean
cd importcalls && $(MAKE) clean
cd typeinference && $(MAKE) clean
......@@ -10,12 +10,18 @@ Currently it contains:
A tool that adds type signatures to a given Curry program.
`analysis`:
A directory containing various analyzers for Curry programs.
A directory containing various analyses for Curry programs.
These are used in the `CASS` and `currydoc` tools.
`browser`:
A tool to browse through the modules and functions of a Curry program,
show them in various formats, and analyze their properties.
`CASS`:
This directory contains the implementation of the
Curry Analysis Server System, a generic and distributed analysis system
for Curry programs.
`createmakefile`:
A tool to create a simple makefile for a Curry application.
......@@ -36,3 +42,9 @@ of some Curry systems).
`importcalls`:
A tool to show all calls to imported functions in a module.
`typeinference`:
This directory contains the implementation of a type
inferencer for FlatCurry programs which annotates
each expression occurring in a FlatCurry program with its
actual type.
------------------------------------------------------------------------------
--- Library to annotate the expressions of a FlatCurry program
--- with type information.
---
--- @author Jonas Oberschweiber, Björn Peemöller, Michael Hanus
--- @version April 2013
------------------------------------------------------------------------------
module Inference
( TypeEnv, getTypeEnv
, inferProg, inferProgEnv, inferFunction, inferFunctionEnv
) where
import FiniteMap
import List (find)
import AnnotatedFlatCurry
import FlatCurry
import Unification
-- ---------------------------------------------------------------------------
-- public functions
-- ---------------------------------------------------------------------------
--- Extract the type environment from the given Prog.
---
--- @param p - the Prog
--- @return a type environment
getTypeEnv :: Prog -> IO TypeEnv
getTypeEnv p = do
imps <- extractImported p
return (extractKnownTypes (p : imps))
--- Infers the type of a whole program.
---
--- @param p - the Prog to infer
--- @return the inferred program or an error
inferProg :: Prog -> IO (Either String (AProg TypeExpr))
inferProg p = getTypeEnv p >>= \te -> return (inferProgEnv te p)
--- Infers the type of a whole program.
--- Uses the given type environment instead of generating a new one.
---
--- @param env - the type environment
--- @param p - the Prog to infer
--- @return the inferred program or an error
inferProgEnv :: TypeEnv -> Prog -> Either String (AProg TypeExpr)
inferProgEnv te p = evalES (annProg p >+= inferAProg te) initTIM
--- Infers the types of a single function specified by its qualified name.
---
--- @param q - the qualified name of the function
--- @param p - the Prog containing the function
--- @return the inferred function or an error
inferFunction :: QName -> Prog -> IO (Either String (AFuncDecl TypeExpr))
inferFunction f p = getTypeEnv p >>= \te -> return (inferFunctionEnv te f p)
--- Infers the types of a single function specified by its qualified name.
--- Uses the given type environment instead of generating a new one.
---
--- @param env - the type environment
--- @param q - the qualified name of the function
--- @param p - the Prog containing the function
--- @return the inferred function or an error
inferFunctionEnv :: TypeEnv -> QName -> Prog
-> Either String (AFuncDecl TypeExpr)
inferFunctionEnv te fun (Prog _ _ _ fd _) = case find (hasName fun) fd of
Nothing -> Left "No such function"
Just f -> evalES (annFunc f >+= inferFunc te) initTIM
where hasName f (Func g _ _ _ _) = f == g
-- ---------------------------------------------------------------------------
-- Type environment
-- ---------------------------------------------------------------------------
--- A type environment.
type TypeEnv = FM QName TypeExpr
--- Looks up a type with a qualified name in a type environment.
---
--- @param env - the type environment
--- @param q - the qualified name to look for
--- @return maybe the type
lookupType :: TypeEnv -> QName -> Maybe TypeExpr
lookupType = lookupFM
--- Reads the interfaces of all modules imported into the given Prog.
---
--- @param p - the Prog whose imports should be read
--- @return the list of interface Progs
extractImported :: Prog -> IO [Prog]
extractImported (Prog _ is _ _ _) = mapIO readFlatCurryInt is
--- Extracts the type information of all function and datatype
--- declarations from the given list of Progs.
---
--- @param ps - the list of Progs
--- @return a type environment
extractKnownTypes :: [Prog] -> TypeEnv
extractKnownTypes ps = listToFM (<) (concatMap extractProg ps)
where
extractProg :: Prog -> [(QName, TypeExpr)]
extractProg (Prog _ _ td fd _)
= concatMap extractTypeDecl td ++ map extractFuncDecl fd
extractFuncDecl :: FuncDecl -> (QName, TypeExpr)
extractFuncDecl (Func n _ _ ty _) = (n, ty)
extractTypeDecl :: TypeDecl -> [(QName, TypeExpr)]
extractTypeDecl (TypeSyn n _ _ ty) = [(n, ty)]
extractTypeDecl (Type n _ vs cs) = map (extractConsDecl ty) cs
where ty = TCons n (map TVar vs)
extractConsDecl :: TypeExpr -> ConsDecl -> (QName, TypeExpr)
extractConsDecl ty (Cons n _ _ tys) = (n, foldr FuncType ty tys)
-- ---------------------------------------------------------------------------
-- A combination of Error and state monad like `ErrorT State` in Haskell
-- ---------------------------------------------------------------------------
--- Error state monad.
type ES e s a = s -> Either e (a, s)
--- Evaluate an `ES` monad
evalES :: ES e s a -> s -> Either e a
evalES m s = case m s of
Left e -> Left e
Right (x, _) -> Right x
--- Lift a value into the `ES` monad
returnES :: a -> ES e s a
returnES x s = Right (x, s)
--- Bind of the `ES` monad
(>+=) :: ES e s a -> (a -> ES e s b) -> ES e s b
(m >+= f) s = case m s of
Left e -> Left e
Right (x, s') -> f x s'
--- Sequence operator of the `ES` monad
(>+) :: ES e s a -> ES e s b -> ES e s b
m >+ n = m >+= \_ -> n
--- Failing computation in the `ES` monad
failES :: e -> ES e s a
failES e _ = Left e
--- Retrieve the current state
gets :: ES e s s
gets s = Right (s, s)
--- Replace the current state
puts :: s -> ES e s ()
puts s _ = Right ((), s)
--- Lift the given unary function into the monad.
liftES :: (a -> b) -> ES e s a -> ES e s b
liftES f m = m >+= (returnES . f)
--- Lift the given binary function into the monad.
liftES2 :: (a -> b -> c) -> ES e s a -> ES e s b -> ES e s c
liftES2 f m n = m >+= \x -> n >+= \y -> returnES (f x y)
--- Append two lists yielded by monadic computations.
(++=) :: TIM [a] -> TIM [a] -> TIM [a]
(++=) = liftES2 (++)
--- Map a monadic function on all elements of a list by sequencing
--- the effects.
mapES :: (a -> ES e s b) -> [a] -> ES e s [b]
mapES _ [] = returnES []
mapES f (x : xs) = f x >+= \y ->
mapES f xs >+= \ys ->
returnES (y:ys)
--- Same as `concatMap`, but for a monadic function.
concatMapES :: (a -> ES e s [b]) -> [a] -> ES e s [b]
concatMapES f xs = concat `liftES` mapES f xs
--- Same as `mapES` but with an additional accumulator threaded.
mapAccumES :: (a -> b -> ES e s (a, c)) -> a -> [b] -> ES e s (a, [c])
mapAccumES _ s [] = returnES (s, [])
mapAccumES f s (x : xs) = f s x >+= \(s', y) ->
mapAccumES f s' xs >+= \(s'', ys) ->
returnES (s'', y:ys)
--- Type Inference Monad.
--- The monad contains an `Int` value for fresh type variable generation
--- and a mapping from variable indices to their associated type
--- variables. It returns a `String` if an error occured
type TIM a = ES String (Int, FM Int TypeExpr) a
--- Initial TIM state.
initTIM = (0, emptyFM (<))
--- Retrieve the next fresh type variable.
nextTVar :: TIM TypeExpr
nextTVar = gets >+= \ (n,var2tvar) -> puts (n+1, var2tvar) >+ returnES (TVar n)
--- Intialize the "variable to type variable mapping", i.e., delete all
--- associations.
initVar2TVar :: TIM ()
initVar2TVar = gets >+= \ (n,_) -> puts (n, emptyFM (<))
--- Insert a new variable/type variable association.
insertVar2TVar :: Int -> TypeExpr -> TIM ()
insertVar2TVar var tvar =
gets >+= \ (n,var2tvar) -> puts (n, addToFM var2tvar var tvar)
--- Look up the type variable associated to a variable.
lookupVar2TVar :: Int -> TIM (Maybe TypeExpr)
lookupVar2TVar var =
gets >+= \ (_,var2tvar) -> returnES (lookupFM var2tvar var)
-- ---------------------------------------------------------------------------
-- Annotation functions, traversing the AST and inserting fresh type variables
-- ---------------------------------------------------------------------------
--- Converts the Prog to an AProg, inserting TVars into all expressions.
---
--- @param prog - the prog to convert
--- @return an AProg and the next TVar number in an TIM
annProg :: Prog -> TIM (AProg TypeExpr)
annProg (Prog mid is td fd od) =
(\afd -> AProg mid is td afd od) `liftES` mapES annFunc fd
--- Converts the FuncDecl to an AFuncDecl, inserting TVars into all
--- expressions.
---
--- @return the AFuncDecl and the new next TVar number in an TIM
annFunc ::FuncDecl -> TIM (AFuncDecl TypeExpr)
annFunc (Func qn a v t r) = AFunc qn a v t `liftES` annRule r
--- Converts the Rule to an ARule, inserting TVars into all expressions.
---
--- @param n - the first TVar number to use
--- @return the ARule and the new next TVar number in an TIM
annRule :: Rule -> TIM (ARule TypeExpr)
annRule (Rule vs e) =
ARule vs `liftES` (initVar2TVar >+ mapES initVarType vs >+ annExpr e)
where initVarType v = nextTVar >+= \ty -> insertVar2TVar v ty
annRule (External e) = returnES (AExternal e)
--- Converts the Expr to an AExpr, inserting TVars into all
--- expressions
---
--- @param n - the first TVar number to use
--- @return the AExpr and the new next TVar number in an TIM
annExpr :: Expr -> TIM (AExpr TypeExpr)
annExpr (Var i) =
lookupVar2TVar i >+=
maybe (error $ "annExpr: variable "++show i++" not initialized with a type!")
(\ty -> returnES (AVar ty i))
annExpr (Lit l) = nextTVar >+= \ty -> returnES (ALit ty l)
annExpr (Comb t q es) = nextTVar >+= \ty ->
mapES annExpr es >+= \aes ->
returnES (AComb ty t q aes)
annExpr (Case t e bs) = nextTVar >+= \ty ->
annExpr e >+= \e' ->
mapES annBranch bs >+= \bs' ->
returnES (ACase ty t e' bs')
annExpr (Or a b) = nextTVar >+= \ty ->
annExpr a >+= \ a' ->
annExpr b >+= \ b' ->
returnES (AOr ty a' b')
annExpr (Let ds e) = mapES annLVar vs >+
mapES annExpr bes >+= \baes ->
nextTVar >+= \ty ->
annExpr e >+= \e' ->
returnES (ALet ty (zip vs baes) e')
where (vs,bes) = unzip ds
annLVar v = checkShadowing v >+ nextTVar >+= insertVar2TVar v
annExpr (Free vs e) = nextTVar >+= \ty ->
mapES annFree vs >+= \vs' ->
annExpr e >+= \e' ->
returnES (AFree ty vs' e')
where annFree v = checkShadowing v >+
nextTVar >+= \ty -> insertVar2TVar v ty >+
returnES (v, ty)
annExpr (Typed e t) = nextTVar >+= \ty ->
annExpr e >+= \ e' ->
returnES (ATyped ty e' t)
--- Checks whether a local variable is already defined which indicates
--- variable shadowing that is not allowed in FlatCurry files.
--- This is our basic assumption in this type inferencer, otherwise it
--- must be extended.
checkShadowing v =
lookupVar2TVar v >+=
maybe (returnES ())
(error $ "annExpr: shadowing with variable "++show v++" occurred!")
--- Converts the BranchExpr to an ABranchExpr, inserting TVars
--- into all expressions
---
--- @param n - the first TVar number to use
--- @return the ABranchExpr and the new next TVar number in an TIM
annBranch :: BranchExpr -> TIM (ABranchExpr TypeExpr)
annBranch (Branch p e) = annPattern p >+= \p' ->
annExpr e >+= \e' ->
returnES (ABranch p' e')
--- Converts the Pattern into an APattern, inserting a TVar
--- into the pattern
---
--- @param n - the TVar number to use
--- @return the APattern and the new next TVar number in an TIM
annPattern :: Pattern -> TIM (APattern TypeExpr)
annPattern (Pattern c vs) = mapES annPVar vs >+
nextTVar >+= \ty ->
returnES (APattern ty c vs)
where annPVar v = checkShadowing v >+
nextTVar >+= \ty -> insertVar2TVar v ty
annPattern (LPattern l) = nextTVar >+= \ty ->
returnES (ALPattern ty l)
-- ---------------------------------------------------------------------------
-- Type inference
-- ---------------------------------------------------------------------------
--- Infers all types in the given program.
---
--- @param p - the program to infer
--- @param env - the type environment to use for type lookups
--- @param n - the next fresh TVar number
--- @return the inferred program or an error
inferAProg :: TypeEnv -> AProg TypeExpr -> TIM (AProg TypeExpr)
inferAProg env (AProg mid is td fd od)
= inferFuncs env fd >+= \fd' -> returnES (AProg mid is td fd' od)
--- Infers all types in the given functions.
---
--- @param fs - the function declarations
--- @param env - the type environment to use for type lookups
--- @param n - the next fresh TVar number
--- @return the inferred functions or an error
inferFuncs :: TypeEnv -> [AFuncDecl TypeExpr] -> TIM [AFuncDecl TypeExpr]
inferFuncs env fs = mapES (inferFunc env) fs
--- Infers all types in the given function.
---
--- @param env - the type environment to use for type lookups
--- @param n - the next fresh TVar number
--- @param f - the function
--- @return the inferred function or an error
inferFunc :: TypeEnv -> AFuncDecl TypeExpr -> TIM (AFuncDecl TypeExpr)
inferFunc env (AFunc f a v _ r@(ARule _ _)) =
inferRule env r >+= \r' -> gets >+= \ (n,_) ->
returnES (normFunc $ (AFunc f a v (extractFuncType n r') r'))
inferFunc _ a@(AFunc _ _ _ _ (AExternal _)) = returnES a
--- Infer the type for a rule.
inferRule :: TypeEnv -> ARule TypeExpr -> TIM (ARule TypeExpr)
inferRule env (ARule vs e) = ARule vs `liftES` infer env e
inferRule _ e@(AExternal _) = returnES e
--- Infers the types in the given expression.
---
--- @param env - the type environment to use for type lookups
--- @param ex - the expression
--- @param n - the next fresh TVar number
--- @return the inferred expression or an error inside an TIM
--- carrying the next fresh TVar number
infer :: TypeEnv -> AExpr TypeExpr -> TIM (AExpr TypeExpr)
infer k e = genTypeEqs k e >+= \t ->
checkFailure (unify (fromTypeEqs t)) >+= \ sigma ->
returnES (substExpr sigma e)
--- Converts a unification error into a string error.
checkFailure :: Either UnificationError Subst -> TIM Subst
checkFailure (Left err) = failES (showUnificationError err)
checkFailure (Right sub) = returnES sub
--- Generates a function type from the given rule. Traverses the list of
--- parameter variable indices in order and searches for the variable's
--- type in the rule's expression. If a type is found, it becomes the type
--- of that parameter. If no type is found, the parameter is given a fresh
--- type variable as its type (hence the maximum type variable index). The
--- top level expression's type becomes the function's return type.
---
--- @param n - the maximum type variable index found in the rule's expression,
--- plus one
--- @param rule - the rule to generate a function type for
--- @return the function type
extractFuncType :: Int -> ARule TypeExpr -> TypeExpr
extractFuncType _ (ARule [] e) = exprType e
extractFuncType n (ARule (i:is) e) = case extractVarType i e of
Nothing -> FuncType (TVar n) (extractFuncType (n + 1) (ARule is e))
Just t -> FuncType t (extractFuncType n (ARule is e))
--- Searches the expression for the type of the variable with the given
--- index.
---
--- @param n - the index of the variable to look for
--- @param e - the expression to search in
--- @return the variable's type or Nothing
extractVarType :: VarIndex -> AExpr TypeExpr -> Maybe TypeExpr
extractVarType n (AVar t i) | n == i = Just t
| otherwise = Nothing
extractVarType _ (ALit _ _) = Nothing
extractVarType n (AComb _ _ _ es) = foldr (<|>) Nothing
$ map (extractVarType n) es
extractVarType n (ALet _ bs e) = foldr (<|>) (extractVarType n e)
$ map (extractVarType n . snd) bs
extractVarType n (AFree _ vs e) = lookup n vs <|> extractVarType n e
extractVarType n (AOr _ a b) = extractVarType n a <|> extractVarType n b
extractVarType n (ACase _ _ e bs) = foldr (<|>) (extractVarType n e)
$ map extractVarTypeBranch bs
where extractVarTypeBranch (ABranch _ ex) = extractVarType n ex
extractVarType n (ATyped _ e _) = extractVarType n e
(<|>) :: Maybe a -> Maybe a -> Maybe a
Nothing <|> r = r
l@(Just _) <|> _ = l
-- ---------------------------------------------------------------------------
-- Functions for normalization of type variables.
-- Renumbers type variables in a function starting from 0.
-- ---------------------------------------------------------------------------
-- We need to keep the next variable number to assign
-- and a mapping from existing variable numbers to newly assigned ones.
type NormState = (Int, FM Int Int)
type NormStateM a = ES () NormState a
--- Normalizes the type variable numbers in the given function.
--- The parameters of the function are always the first types to be
--- renumbered so they are assigned the lowest numbers.
---
--- @param func - the function to renumber
--- @return the renumbered function
normFunc :: AFuncDecl TypeExpr -> AFuncDecl TypeExpr
normFunc (AFunc f a v t (ARule vs e)) = case evalES norm (0, emptyFM (<)) of
Left _ -> error "Inference.normFunc"
Right fd -> fd
where norm = normType t >+= \t' ->
normExpr e >+= \e' ->
returnES (AFunc f a v t' (ARule vs e'))
normFunc a@(AFunc _ _ _ _ (AExternal _)) = a
--- Recursively normalizes type variable numbers in the given type expression.
--- State is managed using the state monad, see normExpr for details.
---
--- @param type - the type expression to normalize
--- @return the normalized type expression
normType :: TypeExpr -> NormStateM (TypeExpr)
normType (TVar i)
= gets >+= \(n, fm) -> case lookupFM fm i of
Nothing -> puts (n + 1, addToFM fm i n) >+ returnES (TVar n)
Just n' -> returnES (TVar n')
normType (TCons q tys) = TCons q `liftES` mapES normType tys
normType (FuncType a b) = liftES2 FuncType (normType a) (normType b)
--- Normalizes type variable numbers in an expression. The next number
--- to assign and a map from existing variable numbers to newly assigned
--- ones are managed using the state monad.
---
--- @param state - the current state
--- @param expr - the expression to normalize
--- @return the new state and normalized expression inside the state monad
normExpr :: AExpr TypeExpr -> NormStateM (AExpr TypeExpr)
normExpr (AVar t v) = normType t >+= \t' -> returnES (AVar t' v)
normExpr (ALit t l) = normType t >+= \t' -> returnES (ALit t' l)
normExpr (AComb t ct f es) = normType t >+= \t' ->
mapES normExpr es >+= \es' ->
returnES (AComb t' ct f es')
normExpr (ALet t ds e) = normType t >+= \t' ->
mapES normBinding ds >+= \ds' ->
normExpr e >+= \e' ->
returnES (ALet t' ds' e')
where normBinding (v, x) = normExpr x >+= \x' -> returnES (v, x')
normExpr (AOr t a b) = normType t >+= \t' ->
normExpr a >+= \a' ->
normExpr b >+= \b' ->
returnES (AOr t' a' b')
normExpr (ACase t ct e bs) = normType t >+= \t' ->
normExpr e >+= \e' ->
mapES normBranch bs >+= \bs' ->
returnES (ACase t' ct e' bs')
normExpr (AFree t vs e) = normType t >+= \t' ->
mapES normVar vs >+= \vs' ->
normExpr e >+= \e' ->
returnES (AFree t' vs' e')
where normVar (v, tv) = normType tv >+= \t' -> returnES (v, t')
normExpr (ATyped t e te) = normType t >+= \t' ->
normExpr e >+= \e' ->
returnES (ATyped t' e' te)
--- Normalizes type variable numbers in a branch. State is managed
--- using the state monad, see normExpr for details.
---
--- @param state - the current state
--- @param branch - the branch to normalize
--- @return the new state and normalized branch inside the state monad
normBranch :: ABranchExpr TypeExpr -> NormStateM (ABranchExpr TypeExpr)
normBranch (ABranch p e) = liftES2 ABranch (normPattern p) (normExpr e)
where
normPattern (APattern t c vs) = normType t >+= \t' ->
returnES (APattern t' c vs)
normPattern (ALPattern t l) = normType t >+= \t' ->
returnES (ALPattern t' l)
-- ---------------------------------------------------------------------------
-- Functions for generating type equations
-- ---------------------------------------------------------------------------
--- Type equations
type TypeEqs = [(TypeExpr, TypeExpr)]
--- Smart constructor for type equation
(=.=) :: TypeExpr -> TypeExpr -> (TypeExpr, TypeExpr)
ty1 =.= ty2 = (ty1, ty2)
showTypeEqs :: TypeEqs -> String
showTypeEqs = unlines . map showEquation
where showEquation (l, r) = show l ++ " =.= " ++ show r
--- Recursively generate equations for the unifier from an expression.
---
--- @param env - the type environment
--- @param n - the next fresh TVar number
--- @param ex - the expression
--- @return a list of equations or an error inside an TIM carrying
--- the next free TVar number
genTypeEqs :: TypeEnv -> AExpr TypeExpr -> TIM TypeEqs
-- Recursively generate equations for each argument expression and
-- match the types of the argument expressions to the types expected by
-- the function or constructor.
-- Whatever is left must be the result type of the call.
genTypeEqs env (AComb ty _ f es)
= concatMapES (genTypeEqs env) es ++=
(lookupTypeRename env f >+= \t -> returnES (matchArgs ty t es))
-- Generate equations for the subject and the branches.
genTypeEqs env (ACase ty _ e bs)
= concatMapES (genBranchTypeEqs env ty e) bs ++= genTypeEqs env e
-- No equations to generate.
genTypeEqs _ (AVar _ _) = returnES []
-- The type of the expression is equal to the type of the literal.
genTypeEqs _ (ALit ty l) = returnES [ty =.= literalType l]
-- Recursively generate equations for each of the argument expressions.
-- The type of the expression must be equal to the types
-- of both argument expressions.
-- The types of the argument expressions must be equal to each other.
genTypeEqs env (AOr ty a b)
= genTypeEqs env a ++= genTypeEqs env b ++=
returnES [exprType a =.= ty, exprType b =.= ty]
-- Generate equations for all bound expressions and for the inner expression.
-- Equate the type of each occurence of a bound variable
-- in the inner expression or some bound expression to the type of
-- the expression which the variable is bound to.
-- The type of the expression itself must be equal to the type of the inner
-- expression.
genTypeEqs env (ALet ty bs e)
= let bvartypes = map (\(v, b) -> (v, exprType b)) bs
in concatMapES (genVarPairs env bvartypes) (e : map snd bs) ++=
concatMapES (genTypeEqs env) (map snd bs) ++=
genTypeEqs env e ++= returnES [ty =.= exprType e]
-- Generate equations for the inner expression.
-- The type of the expression itself must be equal
-- to the type of the inner expression.
genTypeEqs env (AFree ty _ e)
= genTypeEqs env e ++= returnES [ty =.= exprType e]
-- Recursively generate equations for each of the argument expression.
-- The type of the expression must be equal to the type of the
-- argument expression. In addition, it must be also equal to the given type.
genTypeEqs env (ATyped ty e ty')
= genTypeEqs env e ++= returnES [exprType e =.= ty, exprType e =.= ty']
--- Matches the given parameter expressions to the given type.
--- Returns a list of equation pairs. The "leftovers" are assigned
--- to the TypeExpr given as the first parameter.
--- May be used on FuncCall, FuncPartCall, ConsCall and ConsPartCall.
---
--- @param t - the type to assign the "leftover" type from the call to
--- @param f - the function type to match to
--- @param ps - the parameter expressions
--- @return a list of equations
matchArgs :: TypeExpr -> TypeExpr -> [AExpr TypeExpr] -> TypeEqs
matchArgs e a [] = [e =.= a]
matchArgs e (FuncType a b) (p:ps) = (exprType p =.= a) : matchArgs e b ps
--- Generate equation pairs for a branch.
---
--- This consists of:
--- - generating equations for the branch's expresson
--- - equating the type of the branch's expression to the type of the
--- overall case expression
--- - for constructor patterns:
--- - equating all occurences of variables bound by the
--- deconstruction process inside the branch's expression to the
--- corresponding types of the arguments expected by the constructor
--- - equating the type of the pattern to whatever is left after
--- matching the constructor's argument types
--- to the deconstructionvariables
--- (should always be the type of the constructor's datatype)
--- - for literal patterns: equating the type of the pattern to
--- the type of the literal
--- - equating the type of the case's subject to the type of the pattern
---
--- @param env - the type environment
--- @param ct - the parent case expression's type
--- @param subj - the case's subject expression
--- @param b - the branch
--- @return a list of equations or an error inside an TIM carrying
--- the next fresh TVar number
genBranchTypeEqs :: TypeEnv -> TypeExpr -> AExpr TypeExpr
-> ABranchExpr TypeExpr -> TIM TypeEqs