compatible, EId rule for parsing is not working, testing not done yet
This commit is contained in:
parent
914855e20f
commit
3335ab7a57
5 changed files with 146 additions and 141 deletions
|
|
@ -51,7 +51,7 @@ ELit. Exp4 ::= Lit ;
|
||||||
EApp. Exp3 ::= Exp3 Exp4 ;
|
EApp. Exp3 ::= Exp3 Exp4 ;
|
||||||
EAdd. Exp1 ::= Exp1 "+" Exp2 ;
|
EAdd. Exp1 ::= Exp1 "+" Exp2 ;
|
||||||
ELet. Exp ::= "let" LIdent "=" Exp "in" Exp ;
|
ELet. Exp ::= "let" LIdent "=" Exp "in" Exp ;
|
||||||
EAbs. Exp ::= "\\" LIdent "." Exp ;
|
EAbs. Exp ::= "\\" Ident "." Exp ;
|
||||||
ECase. Exp ::= "case" Exp "of" "{" [Inj] "}";
|
ECase. Exp ::= "case" Exp "of" "{" [Inj] "}";
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ import Renamer.Renamer (rename)
|
||||||
import System.Environment (getArgs)
|
import System.Environment (getArgs)
|
||||||
import System.Exit (exitFailure, exitSuccess)
|
import System.Exit (exitFailure, exitSuccess)
|
||||||
|
|
||||||
-- import TypeChecker.TypeChecker (typecheck)
|
import TypeChecker.TypeChecker (typecheck)
|
||||||
|
|
||||||
main :: IO ()
|
main :: IO ()
|
||||||
main =
|
main =
|
||||||
|
|
@ -32,9 +32,9 @@ main' s = do
|
||||||
renamed <- fromRenamerErr . rename $ parsed
|
renamed <- fromRenamerErr . rename $ parsed
|
||||||
putStrLn $ printTree renamed
|
putStrLn $ printTree renamed
|
||||||
|
|
||||||
-- putStrLn "\n-- TypeChecker --"
|
putStrLn "\n-- TypeChecker --"
|
||||||
-- typechecked <- fromTypeCheckerErr $ typecheck renamed
|
typechecked <- fromTypeCheckerErr $ typecheck renamed
|
||||||
-- putStrLn $ show typechecked
|
putStrLn $ printTree typechecked
|
||||||
|
|
||||||
-- putStrLn "\n-- Lambda Lifter --"
|
-- putStrLn "\n-- Lambda Lifter --"
|
||||||
-- let lifted = lambdaLift typechecked
|
-- let lifted = lambdaLift typechecked
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ import Data.Map (Map)
|
||||||
import Data.Map qualified as Map
|
import Data.Map qualified as Map
|
||||||
import Data.Maybe (fromMaybe)
|
import Data.Maybe (fromMaybe)
|
||||||
import Data.Tuple.Extra (dupe)
|
import Data.Tuple.Extra (dupe)
|
||||||
|
import Data.Coerce (coerce)
|
||||||
import Grammar.Abs
|
import Grammar.Abs
|
||||||
|
|
||||||
-- | Rename all variables and local binds
|
-- | Rename all variables and local binds
|
||||||
|
|
@ -30,15 +31,15 @@ rename (Program defs) = Program <$> renameDefs defs
|
||||||
renameDefs :: [Def] -> Either String [Def]
|
renameDefs :: [Def] -> Either String [Def]
|
||||||
renameDefs defs = runIdentity $ runExceptT $ evalStateT (runRn $ mapM renameDef defs) initCxt
|
renameDefs defs = runIdentity $ runExceptT $ evalStateT (runRn $ mapM renameDef defs) initCxt
|
||||||
where
|
where
|
||||||
initNames = Map.fromList [dupe name | DBind (Bind name _ _) <- defs]
|
initNames = Map.fromList [dupe (coerce name) | DBind (Bind name _ _) <- defs]
|
||||||
|
|
||||||
renameDef :: Def -> Rn Def
|
renameDef :: Def -> Rn Def
|
||||||
renameDef = \case
|
renameDef = \case
|
||||||
DSig (Sig name typ) -> DSig . Sig name <$> renameTVars typ
|
DSig (Sig name typ) -> DSig . Sig name <$> renameTVars typ
|
||||||
DBind (Bind name vars rhs) -> do
|
DBind (Bind name vars rhs) -> do
|
||||||
(new_names, vars') <- newNames initNames vars
|
(new_names, vars') <- newNames initNames (coerce vars)
|
||||||
rhs' <- snd <$> renameExp new_names rhs
|
rhs' <- snd <$> renameExp new_names rhs
|
||||||
pure . DBind $ Bind name vars' rhs'
|
pure . DBind $ Bind name (coerce vars') rhs'
|
||||||
DData (Data (Indexed cname types) constrs) -> do
|
DData (Data (Indexed cname types) constrs) -> do
|
||||||
tvars' <- mapM nextNameTVar tvars
|
tvars' <- mapM nextNameTVar tvars
|
||||||
let tvars_lt = zip tvars tvars'
|
let tvars_lt = zip tvars tvars'
|
||||||
|
|
@ -90,11 +91,11 @@ newtype Rn a = Rn {runRn :: StateT Cxt (ExceptT String Identity) a}
|
||||||
deriving (Functor, Applicative, Monad, MonadState Cxt)
|
deriving (Functor, Applicative, Monad, MonadState Cxt)
|
||||||
|
|
||||||
-- | Maps old to new name
|
-- | Maps old to new name
|
||||||
type Names = Map LIdent LIdent
|
type Names = Map Ident Ident
|
||||||
|
|
||||||
renameExp :: Names -> Exp -> Rn (Names, Exp)
|
renameExp :: Names -> Exp -> Rn (Names, Exp)
|
||||||
renameExp old_names = \case
|
renameExp old_names = \case
|
||||||
EId n -> pure (old_names, EId . fromMaybe n $ Map.lookup n old_names)
|
EId n -> pure (coerce old_names, EId . fromMaybe n $ Map.lookup n (coerce old_names))
|
||||||
ELit lit -> pure (old_names, ELit lit)
|
ELit lit -> pure (old_names, ELit lit)
|
||||||
EApp e1 e2 -> do
|
EApp e1 e2 -> do
|
||||||
(env1, e1') <- renameExp old_names e1
|
(env1, e1') <- renameExp old_names e1
|
||||||
|
|
@ -107,14 +108,14 @@ renameExp old_names = \case
|
||||||
|
|
||||||
-- TODO fix shadowing
|
-- TODO fix shadowing
|
||||||
ELet name rhs e -> do
|
ELet name rhs e -> do
|
||||||
(new_names, name') <- newName old_names name
|
(new_names, name') <- newName old_names (coerce name)
|
||||||
(new_names', rhs') <- renameExp new_names rhs
|
(new_names', rhs') <- renameExp new_names rhs
|
||||||
(new_names'', e') <- renameExp new_names' e
|
(new_names'', e') <- renameExp new_names' e
|
||||||
pure (new_names'', ELet name' rhs' e')
|
pure (new_names'', ELet (coerce name') rhs' e')
|
||||||
EAbs par e -> do
|
EAbs par e -> do
|
||||||
(new_names, par') <- newName old_names par
|
(new_names, par') <- newName old_names (coerce par)
|
||||||
(new_names', e') <- renameExp new_names e
|
(new_names', e') <- renameExp new_names e
|
||||||
pure (new_names', EAbs par' e')
|
pure (new_names', EAbs (coerce par') e')
|
||||||
EAnn e t -> do
|
EAnn e t -> do
|
||||||
(new_names, e') <- renameExp old_names e
|
(new_names, e') <- renameExp old_names e
|
||||||
t' <- renameTVars t
|
t' <- renameTVars t
|
||||||
|
|
@ -138,8 +139,8 @@ renameInj ns (Inj init e) = do
|
||||||
renameInit :: Names -> Init -> Rn (Names, Init)
|
renameInit :: Names -> Init -> Rn (Names, Init)
|
||||||
renameInit ns i = case i of
|
renameInit ns i = case i of
|
||||||
InitConstructor cs vars -> do
|
InitConstructor cs vars -> do
|
||||||
(ns_new, vars') <- newNames ns vars
|
(ns_new, vars') <- newNames ns (coerce vars)
|
||||||
return (ns_new, InitConstructor cs vars')
|
return (ns_new, InitConstructor cs (coerce vars'))
|
||||||
rest -> return (ns, rest)
|
rest -> return (ns, rest)
|
||||||
|
|
||||||
renameTVars :: Type -> Rn Type
|
renameTVars :: Type -> Rn Type
|
||||||
|
|
@ -169,26 +170,26 @@ substitute tvar1 tvar2 typ = case typ of
|
||||||
substitute' = substitute tvar1 tvar2
|
substitute' = substitute tvar1 tvar2
|
||||||
|
|
||||||
-- | Create a new name and add it to name environment.
|
-- | Create a new name and add it to name environment.
|
||||||
newName :: Names -> LIdent -> Rn (Names, LIdent)
|
newName :: Names -> Ident -> Rn (Names, Ident)
|
||||||
newName env old_name = do
|
newName env old_name = do
|
||||||
new_name <- makeName old_name
|
new_name <- makeName old_name
|
||||||
pure (Map.insert old_name new_name env, new_name)
|
pure (Map.insert old_name new_name env, new_name)
|
||||||
|
|
||||||
-- | Create multiple names and add them to the name environment
|
-- | Create multiple names and add them to the name environment
|
||||||
newNames :: Names -> [LIdent] -> Rn (Names, [LIdent])
|
newNames :: Names -> [Ident] -> Rn (Names, [Ident])
|
||||||
newNames = mapAccumM newName
|
newNames = mapAccumM newName
|
||||||
|
|
||||||
-- | Annotate name with number and increment the number @prefix ⇒ prefix_number@.
|
-- | Annotate name with number and increment the number @prefix ⇒ prefix_number@.
|
||||||
makeName :: LIdent -> Rn LIdent
|
makeName :: Ident -> Rn Ident
|
||||||
makeName (LIdent prefix) = do
|
makeName (Ident prefix) = do
|
||||||
i <- gets var_counter
|
i <- gets var_counter
|
||||||
let name = LIdent $ prefix ++ "_" ++ show i
|
let name = Ident $ prefix ++ "_" ++ show i
|
||||||
modify $ \cxt -> cxt{var_counter = succ cxt.var_counter}
|
modify $ \cxt -> cxt{var_counter = succ cxt.var_counter}
|
||||||
pure name
|
pure name
|
||||||
|
|
||||||
nextNameTVar :: TVar -> Rn TVar
|
nextNameTVar :: TVar -> Rn TVar
|
||||||
nextNameTVar (MkTVar (LIdent s)) = do
|
nextNameTVar (MkTVar (LIdent s)) = do
|
||||||
i <- gets tvar_counter
|
i <- gets tvar_counter
|
||||||
let tvar = MkTVar . LIdent $ s ++ "_" ++ show i
|
let tvar = MkTVar $ coerce $ s ++ "_" ++ show i
|
||||||
modify $ \cxt -> cxt{tvar_counter = succ cxt.tvar_counter}
|
modify $ \cxt -> cxt{tvar_counter = succ cxt.tvar_counter}
|
||||||
pure tvar
|
pure tvar
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@ checkData d = do
|
||||||
traverse_
|
traverse_
|
||||||
( \(Constructor name' t') ->
|
( \(Constructor name' t') ->
|
||||||
if TIndexed typ == retType t'
|
if TIndexed typ == retType t'
|
||||||
then insertConstr name' t'
|
then insertConstr (coerce name') (toNew t')
|
||||||
else
|
else
|
||||||
throwError $
|
throwError $
|
||||||
unwords
|
unwords
|
||||||
|
|
@ -85,7 +85,7 @@ checkPrg (Program bs) = do
|
||||||
preRun [] = return ()
|
preRun [] = return ()
|
||||||
preRun (x : xs) = case x of
|
preRun (x : xs) = case x of
|
||||||
-- TODO: Check for no overlapping signature definitions
|
-- TODO: Check for no overlapping signature definitions
|
||||||
DSig (Sig n t) -> insertSig n t >> preRun xs
|
DSig (Sig n t) -> insertSig (coerce n) (toNew t) >> preRun xs
|
||||||
DBind (Bind{}) -> preRun xs
|
DBind (Bind{}) -> preRun xs
|
||||||
DData d@(Data _ _) -> checkData d >> preRun xs
|
DData d@(Data _ _) -> checkData d >> preRun xs
|
||||||
|
|
||||||
|
|
@ -100,13 +100,13 @@ checkPrg (Program bs) = do
|
||||||
|
|
||||||
checkBind :: Bind -> Infer T.Bind
|
checkBind :: Bind -> Infer T.Bind
|
||||||
checkBind (Bind name args e) = do
|
checkBind (Bind name args e) = do
|
||||||
let lambda = makeLambda e (reverse args)
|
let lambda = makeLambda e (reverse $ coerce args)
|
||||||
e@(_, t') <- inferExp lambda
|
e@(_, t') <- inferExp lambda
|
||||||
-- TODO: Check for match against existing signatures
|
-- TODO: Check for match against existing signatures
|
||||||
return $ T.Bind (coerce name, t') [] e -- (apply s e)
|
return $ T.Bind (coerce name, t') [] e -- (apply s e)
|
||||||
where
|
where
|
||||||
makeLambda :: Exp -> [LIdent] -> Exp
|
makeLambda :: Exp -> [Ident] -> Exp
|
||||||
makeLambda = foldl (flip EAbs)
|
makeLambda = foldl (flip (EAbs . coerce))
|
||||||
|
|
||||||
{- | Check if two types are considered equal
|
{- | Check if two types are considered equal
|
||||||
For the purpose of the algorithm two polymorphic types are always considered
|
For the purpose of the algorithm two polymorphic types are always considered
|
||||||
|
|
@ -138,7 +138,7 @@ isPoly _ = False
|
||||||
|
|
||||||
inferExp :: Exp -> Infer T.ExpT
|
inferExp :: Exp -> Infer T.ExpT
|
||||||
inferExp e = do
|
inferExp e = do
|
||||||
(s, t, e') <- algoW e
|
(s, (e', t)) <- algoW e
|
||||||
let subbed = apply s t
|
let subbed = apply s t
|
||||||
return $ replace subbed (e', t)
|
return $ replace subbed (e', t)
|
||||||
|
|
||||||
|
|
@ -151,15 +151,18 @@ class NewType a b where
|
||||||
instance NewType Type T.Type where
|
instance NewType Type T.Type where
|
||||||
toNew = \case
|
toNew = \case
|
||||||
TLit i -> T.TLit $ coerce i
|
TLit i -> T.TLit $ coerce i
|
||||||
TVar v -> T.TVar v
|
TVar v -> T.TVar $ toNew v
|
||||||
TFun t1 t2 -> T.TFun (toNew t1) (toNew t2)
|
TFun t1 t2 -> T.TFun (toNew t1) (toNew t2)
|
||||||
TAll b t -> T.TAll b (toNew t)
|
TAll b t -> T.TAll (toNew b) (toNew t)
|
||||||
TIndexed i -> T.TIndexed (toNew i)
|
TIndexed i -> T.TIndexed (toNew i)
|
||||||
TEVar _ -> error "Should not exist after typechecker"
|
TEVar _ -> error "Should not exist after typechecker"
|
||||||
|
|
||||||
instance NewType Indexed T.Indexed where
|
instance NewType Indexed T.Indexed where
|
||||||
toNew (Indexed name vars) = T.Indexed (coerce name) (map toNew vars)
|
toNew (Indexed name vars) = T.Indexed (coerce name) (map toNew vars)
|
||||||
|
|
||||||
|
instance NewType TVar T.TVar where
|
||||||
|
toNew (MkTVar i) = T.MkTVar $ coerce i
|
||||||
|
|
||||||
algoW :: Exp -> Infer (Subst, T.ExpT)
|
algoW :: Exp -> Infer (Subst, T.ExpT)
|
||||||
algoW = \case
|
algoW = \case
|
||||||
-- \| TODO: More testing need to be done. Unsure of the correctness of this
|
-- \| TODO: More testing need to be done. Unsure of the correctness of this
|
||||||
|
|
@ -178,14 +181,14 @@ algoW = \case
|
||||||
applySt s1 $ do
|
applySt s1 $ do
|
||||||
s2 <- unify (toNew t) t'
|
s2 <- unify (toNew t) t'
|
||||||
let comp = s2 `compose` s1
|
let comp = s2 `compose` s1
|
||||||
return (comp, (apply comp e', toNew t))
|
return (comp, apply comp (e', toNew t))
|
||||||
|
|
||||||
-- \| ------------------
|
-- \| ------------------
|
||||||
-- \| Γ ⊢ i : Int, ∅
|
-- \| Γ ⊢ i : Int, ∅
|
||||||
|
|
||||||
ELit lit ->
|
ELit lit ->
|
||||||
let lt = toNew $ litType lit
|
let lt = litType lit
|
||||||
in return (nullSubst, (T.ELit lt lit, lt))
|
in return (nullSubst, (T.ELit lit, lt))
|
||||||
-- \| x : σ ∈ Γ τ = inst(σ)
|
-- \| x : σ ∈ Γ τ = inst(σ)
|
||||||
-- \| ----------------------
|
-- \| ----------------------
|
||||||
-- \| Γ ⊢ x : τ, ∅
|
-- \| Γ ⊢ x : τ, ∅
|
||||||
|
|
@ -193,15 +196,15 @@ algoW = \case
|
||||||
EId i -> do
|
EId i -> do
|
||||||
var <- asks vars
|
var <- asks vars
|
||||||
case M.lookup i var of
|
case M.lookup i var of
|
||||||
Just t -> inst (toNew t) >>= \x -> return (nullSubst, x, T.EId (i, x))
|
Just t -> inst t >>= \(x) -> return (nullSubst, (T.EId (i, x), x))
|
||||||
Nothing -> do
|
Nothing -> do
|
||||||
sig <- gets sigs
|
sig <- gets sigs
|
||||||
case M.lookup i sig of
|
case M.lookup i sig of
|
||||||
Just t -> return (nullSubst, toNew t, T.EId (i, toNew t))
|
Just t -> return (nullSubst, (T.EId (i, t), t))
|
||||||
Nothing -> do
|
Nothing -> do
|
||||||
constr <- gets constructors
|
constr <- gets constructors
|
||||||
case M.lookup i constr of
|
case M.lookup i constr of
|
||||||
Just t -> return (nullSubst, toNew t, T.EId (i, toNew t))
|
Just t -> return (nullSubst, (T.EId (i, t), t))
|
||||||
Nothing ->
|
Nothing ->
|
||||||
throwError $
|
throwError $
|
||||||
"Unbound variable: " ++ show i
|
"Unbound variable: " ++ show i
|
||||||
|
|
@ -212,11 +215,11 @@ algoW = \case
|
||||||
|
|
||||||
EAbs name e -> do
|
EAbs name e -> do
|
||||||
fr <- fresh
|
fr <- fresh
|
||||||
withBinding (coerce name) (Forall [] (toNew fr)) $ do
|
withBinding (coerce name) fr $ do
|
||||||
(s1, t', e') <- algoW e
|
(s1, (e', t')) <- algoW e
|
||||||
let varType = toNew $ apply s1 fr
|
let varType = apply s1 fr
|
||||||
let newArr = T.TFun varType (toNew t')
|
let newArr = T.TFun varType t'
|
||||||
return (s1, newArr, apply s1 $ T.EAbs newArr (coerce name, varType) (e', newArr))
|
return (s1, apply s1 $ (T.EAbs (coerce name, varType) (e', newArr), 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)
|
||||||
|
|
@ -225,17 +228,16 @@ algoW = \case
|
||||||
-- This might be wrong
|
-- This might be wrong
|
||||||
|
|
||||||
EAdd e0 e1 -> do
|
EAdd e0 e1 -> do
|
||||||
(s1, t0, e0') <- algoW e0
|
(s1, (e0', t0)) <- algoW e0
|
||||||
applySt s1 $ do
|
applySt s1 $ do
|
||||||
(s2, t1, e1') <- algoW e1
|
(s2, (e1', t1)) <- algoW e1
|
||||||
-- applySt s2 $ do
|
-- applySt s2 $ do
|
||||||
s3 <- unify (apply s2 t0) (T.TLit "Int")
|
s3 <- unify (apply s2 t0) int
|
||||||
s4 <- unify (apply s3 t1) (T.TLit "Int")
|
s4 <- unify (apply s3 t1) int
|
||||||
let comp = s4 `compose` s3 `compose` s2 `compose` s1
|
let comp = s4 `compose` s3 `compose` s2 `compose` s1
|
||||||
return
|
return
|
||||||
( comp
|
( comp
|
||||||
, T.TLit "Int"
|
, apply comp $ (T.EAdd (e0', t0) (e1', t1), int)
|
||||||
, apply comp $ T.EAdd (T.TLit "Int") (e0', t0) (e1', t1)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
-- \| Γ ⊢ e₀ : τ₀, S₀ S₀Γ ⊢ e₁ : τ₁, S1
|
-- \| Γ ⊢ e₀ : τ₀, S₀ S₀Γ ⊢ e₁ : τ₁, S1
|
||||||
|
|
@ -244,15 +246,15 @@ algoW = \case
|
||||||
-- \| Γ ⊢ e₀ e₁ : S₂τ', S₂S₁S₀
|
-- \| Γ ⊢ e₀ e₁ : S₂τ', S₂S₁S₀
|
||||||
|
|
||||||
EApp e0 e1 -> do
|
EApp e0 e1 -> do
|
||||||
fr <- toNew <$> fresh
|
fr <- fresh
|
||||||
(s0, t0, e0') <- algoW e0
|
(s0, (e0', t0)) <- algoW e0
|
||||||
applySt s0 $ do
|
applySt s0 $ do
|
||||||
(s1, t1, e1') <- algoW e1
|
(s1, (e1', t1)) <- algoW e1
|
||||||
-- applySt s1 $ do
|
-- applySt s1 $ do
|
||||||
s2 <- unify (apply s1 t0) (T.TFun (toNew t1) fr)
|
s2 <- unify (apply s1 t0) (T.TFun t1 fr)
|
||||||
let t = apply s2 fr
|
let t = apply s2 fr
|
||||||
let comp = s2 `compose` s1 `compose` s0
|
let comp = s2 `compose` s1 `compose` s0
|
||||||
return (comp, t, apply comp $ T.EApp t (e0', t0) (e1', t1))
|
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₁
|
||||||
-- \| ----------------------------------------------
|
-- \| ----------------------------------------------
|
||||||
|
|
@ -261,19 +263,21 @@ algoW = \case
|
||||||
-- The bar over S₀ and Γ means "generalize"
|
-- The bar over S₀ and Γ means "generalize"
|
||||||
|
|
||||||
ELet name e0 e1 -> do
|
ELet name e0 e1 -> do
|
||||||
(s1, t1, e0') <- algoW e0
|
(s1, (e0', t1)) <- algoW e0
|
||||||
env <- asks vars
|
env <- asks vars
|
||||||
let t' = generalize (apply s1 env) t1
|
let t' = generalize (apply s1 env) t1
|
||||||
withBinding name t' $ do
|
withBinding (coerce name) t' $ do
|
||||||
(s2, t2, e1') <- algoW e1
|
(s2, (e1', t2)) <- algoW e1
|
||||||
let comp = s2 `compose` s1
|
let comp = s2 `compose` s1
|
||||||
return (comp, t2, apply comp $ T.ELet (T.Bind (name, t2) e0') e1')
|
return (comp, apply comp (T.ELet (T.Bind (coerce name, t2) [] (e0', t1)) (e1', t2), t2))
|
||||||
|
|
||||||
|
-- \| TODO: Add judgement
|
||||||
ECase caseExpr injs -> do
|
ECase caseExpr injs -> do
|
||||||
(sub, t, e') <- 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
|
||||||
let t' = apply comp ret_t
|
let t' = apply comp ret_t
|
||||||
return (comp, t', T.ECase t' e' injs)
|
return (comp, (T.ECase (e', t) injs, t'))
|
||||||
|
|
||||||
-- | Unify two types producing a new substitution
|
-- | Unify two types producing a new substitution
|
||||||
unify :: T.Type -> T.Type -> Infer Subst
|
unify :: T.Type -> T.Type -> Infer Subst
|
||||||
|
|
@ -283,8 +287,8 @@ unify t0 t1 = do
|
||||||
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 $ s1 `compose` s2
|
return $ s1 `compose` s2
|
||||||
(T.TVar t, b) -> occurs b t
|
(T.TVar (T.MkTVar a), t) -> occurs a t
|
||||||
(a, T.TVar t) -> occurs a t
|
(t, T.TVar (T.MkTVar b)) -> occurs b t
|
||||||
(T.TAll _ t, b) -> unify t b
|
(T.TAll _ t, b) -> unify t b
|
||||||
(a, T.TAll _ t) -> unify a t
|
(a, T.TAll _ t) -> unify a t
|
||||||
(T.TLit a, T.TLit b) ->
|
(T.TLit a, T.TLit b) ->
|
||||||
|
|
@ -298,20 +302,20 @@ unify t0 t1 = do
|
||||||
throwError $
|
throwError $
|
||||||
unwords
|
unwords
|
||||||
[ "T.Type constructor:"
|
[ "T.Type constructor:"
|
||||||
, printT . Tree name
|
, printTree name
|
||||||
, "(" ++ printT . Tree t ++ ")"
|
, "(" ++ printTree t ++ ")"
|
||||||
, "does not match with:"
|
, "does not match with:"
|
||||||
, printT . Tree name'
|
, printTree name'
|
||||||
, "(" ++ printT . Tree t' ++ ")"
|
, "(" ++ printTree t' ++ ")"
|
||||||
]
|
]
|
||||||
(a, b) -> do
|
(a, b) -> do
|
||||||
ctx <- ask
|
ctx <- ask
|
||||||
env <- get
|
env <- get
|
||||||
throwError . unwords $
|
throwError . unwords $
|
||||||
[ "T.Type:"
|
[ "T.Type:"
|
||||||
, printT . Tree a
|
, printTree a
|
||||||
, "can't be unified with:"
|
, "can't be unified with:"
|
||||||
, printT . Tree b
|
, printTree b
|
||||||
, "\nCtx:"
|
, "\nCtx:"
|
||||||
, show ctx
|
, show ctx
|
||||||
, "\nEnv:"
|
, "\nEnv:"
|
||||||
|
|
@ -322,7 +326,7 @@ unify t0 t1 = do
|
||||||
I.E. { a = a -> b } is an unsolvable constraint since there is no substitution
|
I.E. { a = a -> b } is an unsolvable constraint since there is no substitution
|
||||||
where these are equal
|
where these are equal
|
||||||
-}
|
-}
|
||||||
occurs :: LIdent -> T.Type -> Infer Subst
|
occurs :: Ident -> T.Type -> Infer Subst
|
||||||
occurs i t@(T.TVar _) = return (M.singleton i t)
|
occurs i t@(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)
|
||||||
|
|
@ -330,26 +334,37 @@ occurs i t =
|
||||||
throwError $
|
throwError $
|
||||||
unwords
|
unwords
|
||||||
[ "Occurs check failed, can't unify"
|
[ "Occurs check failed, can't unify"
|
||||||
, printTree (TVar $ MkTVar i)
|
, printTree (T.TVar $ T.MkTVar i)
|
||||||
, "with"
|
, "with"
|
||||||
, printTree t
|
, printTree t
|
||||||
]
|
]
|
||||||
else return $ 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
|
||||||
generalize :: Map Ident Poly -> Type -> Poly
|
generalize :: Map Ident T.Type -> T.Type -> T.Type
|
||||||
generalize env t = Forall (S.toList $ free t S.\\ free env) t
|
generalize env t = go freeVars $ removeForalls t
|
||||||
|
where
|
||||||
|
freeVars :: [Ident]
|
||||||
|
freeVars = S.toList $ free t S.\\ free env
|
||||||
|
go :: [Ident] -> T.Type -> T.Type
|
||||||
|
go [] t = t
|
||||||
|
go (x : xs) t = T.TAll (T.MkTVar x) (go xs t)
|
||||||
|
removeForalls :: T.Type -> T.Type
|
||||||
|
removeForalls (T.TAll _ t) = removeForalls t
|
||||||
|
removeForalls (T.TFun t1 t2) = T.TFun (removeForalls t1) (removeForalls t2)
|
||||||
|
removeForalls t = t
|
||||||
|
|
||||||
{- | Instantiate a polymorphic type. The free type variables are substituted
|
{- | Instantiate a polymorphic type. The free type variables are substituted
|
||||||
with fresh ones.
|
with fresh ones.
|
||||||
-}
|
-}
|
||||||
inst :: T.Type -> Infer T.Type
|
inst :: T.Type -> Infer T.Type
|
||||||
inst = \case
|
inst = \case
|
||||||
T.TAll bound t -> do
|
T.TAll (T.MkTVar bound) t -> do
|
||||||
fr <- fresh
|
fr <- fresh
|
||||||
let s = M.singleton fr bound
|
let s = M.singleton bound fr
|
||||||
apply s <$> inst t
|
apply s <$> inst t
|
||||||
_ -> undefined
|
T.TFun t1 t2 -> T.TFun <$> inst t1 <*> inst t2
|
||||||
|
rest -> return rest
|
||||||
|
|
||||||
-- | Compose two substitution sets
|
-- | Compose two substitution sets
|
||||||
compose :: Subst -> Subst -> Subst
|
compose :: Subst -> Subst -> Subst
|
||||||
|
|
@ -361,15 +376,15 @@ compose m1 m2 = M.map (apply m1) m2 `M.union` m1
|
||||||
-- | A class representing free variables functions
|
-- | A class representing free variables functions
|
||||||
class FreeVars t where
|
class FreeVars t where
|
||||||
-- | Get all free variables from t
|
-- | Get all free variables from t
|
||||||
free :: t -> Set LIdent
|
free :: t -> Set Ident
|
||||||
|
|
||||||
-- | Apply a substitution to t
|
-- | Apply a substitution to t
|
||||||
apply :: Subst -> t -> t
|
apply :: Subst -> t -> t
|
||||||
|
|
||||||
instance FreeVars T.Type where
|
instance FreeVars T.Type where
|
||||||
free :: T.Type -> Set LIdent
|
free :: T.Type -> Set Ident
|
||||||
free (T.TVar (MkTVar a)) = S.singleton a
|
free (T.TVar (T.MkTVar a)) = S.singleton a
|
||||||
free (T.TAll (MkTVar bound) t) = (S.singleton bound) `S.intersection` free t
|
free (T.TAll (T.MkTVar bound) t) = (S.singleton bound) `S.intersection` free t
|
||||||
free (T.TLit _) = mempty
|
free (T.TLit _) = mempty
|
||||||
free (T.TFun a b) = free a `S.union` free b
|
free (T.TFun a b) = free a `S.union` free b
|
||||||
-- \| Not guaranteed to be correct
|
-- \| Not guaranteed to be correct
|
||||||
|
|
@ -380,53 +395,40 @@ instance FreeVars T.Type where
|
||||||
apply sub t = do
|
apply sub t = do
|
||||||
case t of
|
case t of
|
||||||
T.TLit a -> T.TLit a
|
T.TLit a -> T.TLit a
|
||||||
T.TVar (MkTVar a) -> case M.lookup a sub of
|
T.TVar (T.MkTVar a) -> case M.lookup a sub of
|
||||||
Nothing -> T.TVar (MkTVar a)
|
Nothing -> T.TVar (T.MkTVar $ coerce a)
|
||||||
Just t -> t
|
Just t -> t
|
||||||
T.TAll bound t -> undefined
|
T.TAll bound t -> undefined
|
||||||
T.TFun a b -> T.TFun (apply sub a) (apply sub b)
|
T.TFun a b -> T.TFun (apply sub a) (apply sub b)
|
||||||
T.TIndexed (T.Indexed name a) -> T.TIndexed (T.Indexed name (map (apply sub) a))
|
T.TIndexed (T.Indexed name a) -> T.TIndexed (T.Indexed name (map (apply sub) a))
|
||||||
|
|
||||||
instance FreeVars Poly where
|
instance FreeVars (Map Ident T.Type) where
|
||||||
free :: Poly -> Set LIdent
|
free :: Map Ident T.Type -> Set Ident
|
||||||
free (Forall xs t) = free t S.\\ S.fromList xs
|
|
||||||
apply :: Subst -> Poly -> Poly
|
|
||||||
apply s (Forall xs t) = Forall xs (apply (foldr M.delete s xs) t)
|
|
||||||
|
|
||||||
instance FreeVars (Map LIdent Poly) where
|
|
||||||
free :: Map LIdent Poly -> Set LIdent
|
|
||||||
free m = foldl' S.union S.empty (map free $ M.elems m)
|
free m = foldl' S.union S.empty (map free $ M.elems m)
|
||||||
apply :: Subst -> Map LIdent Poly -> Map LIdent Poly
|
apply :: Subst -> Map Ident T.Type -> Map Ident T.Type
|
||||||
apply s = M.map (apply s)
|
apply s = M.map (apply s)
|
||||||
|
|
||||||
instance FreeVars T.Exp where
|
instance FreeVars T.ExpT where
|
||||||
free :: T.Exp -> Set LIdent
|
free :: T.ExpT -> Set Ident
|
||||||
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.ExpT -> T.ExpT
|
||||||
apply s = \case
|
apply s = \case
|
||||||
T.EId (ident, t) ->
|
(T.EId (i, innerT), outerT) -> (T.EId (i, apply s innerT), apply s outerT)
|
||||||
T.EId (ident, apply s t)
|
(T.ELit lit, t) -> (T.ELit lit, apply s t)
|
||||||
T.ELit t lit ->
|
(T.ELet (T.Bind (ident, t1) args e1) e2, t2) -> (T.ELet (T.Bind (ident, apply s t1) args (apply s e1)) (apply s e2), apply s t2)
|
||||||
T.ELit (apply s t) lit
|
(T.EApp e1 e2, t) -> (T.EApp (apply s e1) (apply s e2), (apply s t))
|
||||||
T.ELet (T.Bind (ident, t) args e1) e2 ->
|
(T.EAdd e1 e2, t) -> (T.EAdd (apply s e1) (apply s e2), (apply s t))
|
||||||
T.ELet (T.Bind (ident, apply s t) args (apply s e1)) (apply s e2)
|
(T.EAbs (ident, t2) e, t1) -> (T.EAbs (ident, apply s t2) (apply s e), (apply s t1))
|
||||||
T.EApp t e1 e2 ->
|
(T.ECase e injs, t) -> (T.ECase (apply s e) (apply s injs), (apply s t))
|
||||||
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.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)
|
|
||||||
|
|
||||||
instance FreeVars T.Inj where
|
instance FreeVars T.Inj where
|
||||||
free :: T.Inj -> Set LIdent
|
free :: T.Inj -> Set Ident
|
||||||
free = undefined
|
free = undefined
|
||||||
apply :: Subst -> T.Inj -> T.Inj
|
apply :: Subst -> T.Inj -> T.Inj
|
||||||
apply s (T.Inj (i, t) e) = T.Inj (i, apply s t) (apply s e)
|
apply s (T.Inj (i, t) e) = T.Inj (i, apply s t) (apply s e)
|
||||||
|
|
||||||
instance FreeVars [T.Inj] where
|
instance FreeVars [T.Inj] where
|
||||||
free :: [T.Inj] -> Set LIdent
|
free :: [T.Inj] -> Set Ident
|
||||||
free = foldl' (\acc x -> free x `S.union` acc) mempty
|
free = foldl' (\acc x -> free x `S.union` acc) mempty
|
||||||
apply s = map (apply s)
|
apply s = map (apply s)
|
||||||
|
|
||||||
|
|
@ -439,33 +441,33 @@ nullSubst :: Subst
|
||||||
nullSubst = M.empty
|
nullSubst = M.empty
|
||||||
|
|
||||||
-- | Generate a new fresh variable and increment the state counter
|
-- | Generate a new fresh variable and increment the state counter
|
||||||
fresh :: Infer Type
|
fresh :: Infer T.Type
|
||||||
fresh = do
|
fresh = do
|
||||||
n <- gets count
|
n <- gets count
|
||||||
modify (\st -> st{count = n + 1})
|
modify (\st -> st{count = n + 1})
|
||||||
return . TVar . MkTVar . LIdent $ show n
|
return . T.TVar . T.MkTVar . Ident $ show n
|
||||||
|
|
||||||
-- | Run the monadic action with an additional binding
|
-- | Run the monadic action with an additional binding
|
||||||
withBinding :: (Monad m, MonadReader Ctx m) => Ident -> Poly -> m a -> m a
|
withBinding :: (Monad m, MonadReader Ctx m) => Ident -> T.Type -> m a -> m a
|
||||||
withBinding i p = local (\st -> st{vars = M.insert i p (vars st)})
|
withBinding i p = local (\st -> st{vars = M.insert i p (vars st)})
|
||||||
|
|
||||||
-- | Run the monadic action with several additional bindings
|
-- | Run the monadic action with several additional bindings
|
||||||
withBindings :: (Monad m, MonadReader Ctx m) => [(Ident, Poly)] -> m a -> m a
|
withBindings :: (Monad m, MonadReader Ctx m) => [(Ident, T.Type)] -> m a -> m a
|
||||||
withBindings xs =
|
withBindings xs =
|
||||||
local (\st -> st{vars = foldl' (flip (uncurry M.insert)) (vars st) xs})
|
local (\st -> st{vars = foldl' (flip (uncurry M.insert)) (vars st) xs})
|
||||||
|
|
||||||
-- | Insert a function signature into the environment
|
-- | Insert a function signature into the environment
|
||||||
insertSig :: LIdent -> Type -> Infer ()
|
insertSig :: Ident -> T.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)})
|
||||||
|
|
||||||
-- | Insert a constructor with its data type
|
-- | Insert a constructor with its data type
|
||||||
insertConstr :: UIdent -> Type -> Infer ()
|
insertConstr :: Ident -> T.Type -> Infer ()
|
||||||
insertConstr i t =
|
insertConstr i t =
|
||||||
modify (\st -> st{constructors = M.insert i t (constructors st)})
|
modify (\st -> st{constructors = M.insert i t (constructors st)})
|
||||||
|
|
||||||
-------- PATTERN MATCHING ---------
|
-------- PATTERN MATCHING ---------
|
||||||
|
|
||||||
checkCase :: Type -> [Inj] -> Infer (Subst, [T.Inj], Type)
|
checkCase :: T.Type -> [Inj] -> Infer (Subst, [T.Inj], T.Type)
|
||||||
checkCase expT injs = do
|
checkCase expT injs = do
|
||||||
(injTs, injs, returns) <- unzip3 <$> mapM checkInj injs
|
(injTs, injs, returns) <- unzip3 <$> mapM checkInj injs
|
||||||
(sub1, _) <-
|
(sub1, _) <-
|
||||||
|
|
@ -487,18 +489,17 @@ checkCase expT injs = do
|
||||||
{- | fst = type of init
|
{- | fst = type of init
|
||||||
| snd = type of expr
|
| snd = type of expr
|
||||||
-}
|
-}
|
||||||
checkInj :: Inj -> Infer (Type, T.Inj, Type)
|
checkInj :: Inj -> Infer (T.Type, T.Inj, T.Type)
|
||||||
checkInj (Inj it expr) = do
|
checkInj (Inj it expr) = do
|
||||||
(initT, vars) <- inferInit it
|
(initT, vars) <- inferInit it
|
||||||
let converted = map (second (Forall [])) vars
|
(e, exprT) <- withBindings vars (inferExp expr)
|
||||||
(exprT, e) <- withBindings converted (inferExp expr)
|
return (initT, T.Inj (it, initT) (e, exprT), exprT)
|
||||||
return (initT, T.Inj (it, initT) e, exprT)
|
|
||||||
|
|
||||||
inferInit :: Init -> Infer (Type, [T.Id])
|
inferInit :: Init -> Infer (T.Type, [T.Id])
|
||||||
inferInit = \case
|
inferInit = \case
|
||||||
InitLit lit -> return (litType lit, mempty)
|
InitLit lit -> return (litType lit, mempty)
|
||||||
InitConstructor fn vars -> do
|
InitConstructor fn vars -> do
|
||||||
gets (M.lookup fn . constructors) >>= \case
|
gets (M.lookup (coerce fn) . constructors) >>= \case
|
||||||
Nothing ->
|
Nothing ->
|
||||||
throwError $
|
throwError $
|
||||||
"Constructor: " ++ printTree fn ++ " does not exist"
|
"Constructor: " ++ printTree fn ++ " does not exist"
|
||||||
|
|
@ -508,14 +509,17 @@ inferInit = \case
|
||||||
Just (vs, ret) ->
|
Just (vs, ret) ->
|
||||||
case length vars `compare` length vs of
|
case length vars `compare` length vs of
|
||||||
EQ -> do
|
EQ -> do
|
||||||
return (ret, zip vars vs)
|
return (ret, zip (coerce vars) vs)
|
||||||
_ -> throwError "Partial pattern match not allowed"
|
_ -> throwError "Partial pattern match not allowed"
|
||||||
InitCatch -> (,mempty) <$> fresh
|
InitCatch -> (,mempty) <$> fresh
|
||||||
|
|
||||||
flattenType :: Type -> [Type]
|
flattenType :: T.Type -> [T.Type]
|
||||||
flattenType (TFun a b) = flattenType a ++ flattenType b
|
flattenType (T.TFun a b) = flattenType a ++ flattenType b
|
||||||
flattenType a = [a]
|
flattenType a = [a]
|
||||||
|
|
||||||
litType :: Lit -> Type
|
litType :: Lit -> T.Type
|
||||||
litType (LInt _) = TLit "Int"
|
litType (LInt _) = int
|
||||||
litType (LChar _) = TLit "Char"
|
litType (LChar _) = char
|
||||||
|
|
||||||
|
int = T.TLit "Int"
|
||||||
|
char = T.TLit "Char"
|
||||||
|
|
|
||||||
|
|
@ -12,9 +12,7 @@ import Grammar.Abs (
|
||||||
Ident (..),
|
Ident (..),
|
||||||
Init (..),
|
Init (..),
|
||||||
Lit (..),
|
Lit (..),
|
||||||
TVar (..),
|
|
||||||
)
|
)
|
||||||
import Grammar.Abs qualified as GA (Type (..))
|
|
||||||
import Grammar.Print
|
import Grammar.Print
|
||||||
import Prelude
|
import Prelude
|
||||||
import Prelude qualified as C (Eq, Ord, Read, Show)
|
import Prelude qualified as C (Eq, Ord, Read, Show)
|
||||||
|
|
@ -23,13 +21,13 @@ import Prelude qualified as C (Eq, Ord, Read, Show)
|
||||||
data Poly = Forall [Ident] Type
|
data Poly = Forall [Ident] Type
|
||||||
deriving (Show)
|
deriving (Show)
|
||||||
|
|
||||||
newtype Ctx = Ctx {vars :: Map Ident Poly}
|
newtype Ctx = Ctx {vars :: Map Ident Type}
|
||||||
deriving (Show)
|
deriving (Show)
|
||||||
|
|
||||||
data Env = Env
|
data Env = Env
|
||||||
{ count :: Int
|
{ count :: Int
|
||||||
, sigs :: Map Ident GA.Type
|
, sigs :: Map Ident Type
|
||||||
, constructors :: Map Ident GA.Type
|
, constructors :: Map Ident Type
|
||||||
}
|
}
|
||||||
deriving (Show)
|
deriving (Show)
|
||||||
|
|
||||||
|
|
@ -41,6 +39,9 @@ type Infer = StateT Env (ReaderT Ctx (ExceptT Error Identity))
|
||||||
newtype Program = Program [Def]
|
newtype Program = Program [Def]
|
||||||
deriving (C.Eq, C.Ord, C.Show, C.Read)
|
deriving (C.Eq, C.Ord, C.Show, C.Read)
|
||||||
|
|
||||||
|
data TVar = MkTVar Ident
|
||||||
|
deriving (Show, Eq, Ord, Read)
|
||||||
|
|
||||||
data Type
|
data Type
|
||||||
= TLit Ident
|
= TLit Ident
|
||||||
| TVar TVar
|
| TVar TVar
|
||||||
|
|
@ -130,7 +131,7 @@ prtIdP i (name, t) =
|
||||||
instance Print Exp where
|
instance Print Exp where
|
||||||
prt i = \case
|
prt i = \case
|
||||||
EId n -> prPrec i 3 $ concatD [prtId 0 n, doc $ showString "\n"]
|
EId n -> prPrec i 3 $ concatD [prtId 0 n, doc $ showString "\n"]
|
||||||
ELit _ lit -> prPrec i 3 $ concatD [prt 0 lit, doc $ showString "\n"]
|
ELit lit -> prPrec i 3 $ concatD [prt 0 lit, doc $ showString "\n"]
|
||||||
ELet bs e ->
|
ELet bs e ->
|
||||||
prPrec i 3 $
|
prPrec i 3 $
|
||||||
concatD
|
concatD
|
||||||
|
|
@ -140,34 +141,31 @@ instance Print Exp where
|
||||||
, prt 0 e
|
, prt 0 e
|
||||||
, doc $ showString "\n"
|
, doc $ showString "\n"
|
||||||
]
|
]
|
||||||
EApp _ e1 e2 ->
|
EApp e1 e2 ->
|
||||||
prPrec i 2 $
|
prPrec i 2 $
|
||||||
concatD
|
concatD
|
||||||
[ prt 2 e1
|
[ prt 2 e1
|
||||||
, prt 3 e2
|
, prt 3 e2
|
||||||
]
|
]
|
||||||
EAdd t e1 e2 ->
|
EAdd e1 e2 ->
|
||||||
prPrec i 1 $
|
prPrec i 1 $
|
||||||
concatD
|
concatD
|
||||||
[ doc $ showString "@"
|
[ doc $ showString "@"
|
||||||
, prt 0 t
|
|
||||||
, prt 1 e1
|
, prt 1 e1
|
||||||
, doc $ showString "+"
|
, doc $ showString "+"
|
||||||
, prt 2 e2
|
, prt 2 e2
|
||||||
, doc $ showString "\n"
|
, doc $ showString "\n"
|
||||||
]
|
]
|
||||||
EAbs t n e ->
|
EAbs n e ->
|
||||||
prPrec i 0 $
|
prPrec i 0 $
|
||||||
concatD
|
concatD
|
||||||
[ doc $ showString "@"
|
[ doc $ showString "@"
|
||||||
, prt 0 t
|
|
||||||
, doc $ showString "\\"
|
|
||||||
, prtId 0 n
|
, prtId 0 n
|
||||||
, doc $ showString "."
|
, doc $ showString "."
|
||||||
, prt 0 e
|
, prt 0 e
|
||||||
, doc $ showString "\n"
|
, doc $ showString "\n"
|
||||||
]
|
]
|
||||||
ECase t exp injs ->
|
ECase exp injs ->
|
||||||
prPrec
|
prPrec
|
||||||
i
|
i
|
||||||
0
|
0
|
||||||
|
|
@ -179,7 +177,6 @@ instance Print Exp where
|
||||||
, prt 0 injs
|
, prt 0 injs
|
||||||
, doc (showString "}")
|
, doc (showString "}")
|
||||||
, doc (showString ":")
|
, doc (showString ":")
|
||||||
, prt 0 t
|
|
||||||
, doc $ showString "\n"
|
, doc $ showString "\n"
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
@ -196,6 +193,9 @@ instance Print [Inj] where
|
||||||
prt _ [x] = concatD [prt 0 x]
|
prt _ [x] = concatD [prt 0 x]
|
||||||
prt _ (x : xs) = concatD [prt 0 x, doc (showString ";"), prt 0 xs]
|
prt _ (x : xs) = concatD [prt 0 x, doc (showString ";"), prt 0 xs]
|
||||||
|
|
||||||
|
instance Print TVar where
|
||||||
|
prt i (MkTVar id) = prt i id
|
||||||
|
|
||||||
instance Print Type where
|
instance Print Type where
|
||||||
prt i = \case
|
prt i = \case
|
||||||
TLit uident -> prPrec i 2 (concatD [prt 0 uident])
|
TLit uident -> prPrec i 2 (concatD [prt 0 uident])
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue