This commit is contained in:
crumbtoo
2024-02-29 09:52:08 -07:00
parent 16f7f51fb8
commit c026f6f8f9
4 changed files with 102 additions and 38 deletions

View File

@@ -14,6 +14,9 @@ module Compiler.RlpcError
-- * Located Comonad -- * Located Comonad
, Located(..) , Located(..)
, SrcSpan(..) , SrcSpan(..)
-- * Common error messages
, undefinedVariableErr
) )
where where
---------------------------------------------------------------------------------- ----------------------------------------------------------------------------------
@@ -74,3 +77,8 @@ debugMsg tag e = MsgEnvelope
, _msgSeverity = SevDebug tag , _msgSeverity = SevDebug tag
} }
undefinedVariableErr :: Text -> RlpcError
undefinedVariableErr n = Text
[ "Variable not in scope: `" <> n <> "'."
]

View File

@@ -38,7 +38,7 @@ module Core.Syntax
, HasRHS(_rhs), HasLHS(_lhs) , HasRHS(_rhs), HasLHS(_lhs)
, _BindingF, _MkVar , _BindingF, _MkVar
-- ** Classy optics -- ** Classy optics
, HasBinders(..), HasArrowStops(..) , HasBinders(..), HasArrowStops(..), HasApplicants1(..), HasApplicants(..)
) )
where where
---------------------------------------------------------------------------------- ----------------------------------------------------------------------------------
@@ -577,23 +577,34 @@ deriving instance Lift b => Lift (Program b)
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
-- class HasApplicants s t a b | s -> a, t -> b, s b -> t, t a -> s where class HasApplicants1 s t a b | s -> a, t -> b, s b -> t, t a -> s where
-- applicants :: Traversal s t a b applicants1 :: Traversal s t a b
-- instance HasApplicants (ExprF b (Fix (ExprF b))) (ExprF b (Fix (ExprF b))) class HasApplicants s t a b | s -> a, t -> b, s b -> t, t a -> s where
applicants :: Traversal s t a b
instance HasApplicants1 Type Type Type Type where
applicants1 k (TyApp f x) = TyApp <$> applicants1 k f <*> k x
applicants1 k x = k x
instance HasApplicants Type Type Type Type where
applicants k (TyApp f x) = TyApp <$> applicants k f <*> k x
applicants k x = pure x
-- instance HasArguments (ExprF b (Fix (ExprF b))) (ExprF b (Fix (ExprF b)))
-- (Fix (ExprF b)) (Fix (ExprF b)) where -- (Fix (ExprF b)) (Fix (ExprF b)) where
-- applicants k (AppF f x) = AppF <$> applicants k f <*> k x -- arguments k (AppF f x) = AppF <$> arguments k f <*> k x
-- applicants k x = unwrapFix <$> k (wrapFix x) -- arguments k x = unwrapFix <$> k (wrapFix x)
-- instance HasApplicants (f (Fix f)) (f (Fix f)) (Fix f) (Fix f) -- instance HasArguments (f (Fix f)) (f (Fix f)) (Fix f) (Fix f)
-- => HasApplicants (Fix f) (Fix f) (Fix f) (Fix f) where -- => HasArguments (Fix f) (Fix f) (Fix f) (Fix f) where
-- applicants :: forall g. Applicative g -- arguments :: forall g. Applicative g
-- => LensLike' g (Fix f) (Fix f) -- => LensLike' g (Fix f) (Fix f)
-- applicants k (Fix f) = Fix <$> applicants k f -- arguments k (Fix f) = Fix <$> arguments k f
-- applicants :: Traversal' (Expr b) (Expr b) -- arguments :: Traversal' (Expr b) (Expr b)
-- applicants k (App f x) = App <$> applicants k f <*> k x -- arguments k (App f x) = App <$> arguments k f <*> k x
-- applicants k x = k x -- arguments k x = k x
class HasBinders s t a b | s -> a, t -> b, s b -> t, t a -> s where class HasBinders s t a b | s -> a, t -> b, s b -> t, t a -> s where
binders :: Traversal s t a b binders :: Traversal s t a b

View File

@@ -14,6 +14,9 @@ import Data.Foldable
import Data.List.Extra import Data.List.Extra
import Control.Monad.Utils import Control.Monad.Utils
import Control.Monad import Control.Monad
import Data.Text qualified as T
import Data.Pretty
import Text.Printf
import Control.Comonad import Control.Comonad
import Control.Comonad.Cofree import Control.Comonad.Cofree
@@ -24,6 +27,7 @@ import Control.Lens hiding ((:<))
import Control.Lens.Unsound import Control.Lens.Unsound
import Compiler.RLPC import Compiler.RLPC
import Compiler.RlpcError
import Core import Core
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
@@ -46,12 +50,27 @@ lint = undefined
type ET = Cofree (ExprF Var) Type type ET = Cofree (ExprF Var) Type
type SysF = Either TypeError type SysF = Either SystemFError
data TypeError = TypeErrorUndefinedVariable Name data SystemFError = SystemFErrorUndefinedVariable Name
| TypeErrorKindMismatch Kind Kind | SystemFErrorKindMismatch Kind Kind
| TypeErrorCouldNotMatch Type Type | SystemFErrorCouldNotMatch Type Type
deriving Show deriving Show
instance IsRlpcError SystemFError where
liftRlpcError = \case
SystemFErrorUndefinedVariable n ->
undefinedVariableErr n
SystemFErrorKindMismatch k k' ->
Text [ T.pack $ printf "Could not match kind `%s' with `%s'"
(pretty k) (pretty k')
]
SystemFErrorCouldNotMatch t t' ->
Text [ T.pack $ printf "Could not match type `%s' with `%s'"
(pretty t) (pretty t')
]
justLintCoreExpr = fmap (fmap (prettyPrec appPrec1)) . lintE demoContext
lintE :: Gamma -> Expr Var -> SysF ET lintE :: Gamma -> Expr Var -> SysF ET
lintE g = \case lintE g = \case
@@ -97,7 +116,7 @@ lintE g = \case
g' = supplementVars vs g g' = supplementVars vs g
checkBind v@(MkVar n t) e = case lintE g' e of checkBind v@(MkVar n t) e = case lintE g' e of
Right (t' :< e') | t == t' -> Right (BindingF v e') Right (t' :< e') | t == t' -> Right (BindingF v e')
| otherwise -> Left (TypeErrorCouldNotMatch t t') | otherwise -> Left (SystemFErrorCouldNotMatch t t')
Left e -> Left e Left e -> Left e
Let NonRec bs e -> do Let NonRec bs e -> do
(g',bs') <- mapAccumLM checkBind g bs (g',bs') <- mapAccumLM checkBind g bs
@@ -109,38 +128,50 @@ lintE g = \case
checkBind g (BindingF v@(n :^ t) e) = case lintE g (wrapFix e) of checkBind g (BindingF v@(n :^ t) e) = case lintE g (wrapFix e) of
Right (t' :< e') Right (t' :< e')
| t == t' -> Right (supplementVar n t g, BindingF v e') | t == t' -> Right (supplementVar n t g, BindingF v e')
| otherwise -> Left (TypeErrorCouldNotMatch t t') | otherwise -> Left (SystemFErrorCouldNotMatch t t')
Left e -> Left e Left e -> Left e
Case e as -> do Case e as -> do
(ts,as') <- unzip <$> checkAlt `traverse` as e'@(et :< _) <- lintE g e
unless (allSame ts) $ (ts,as') <- unzip <$> checkAlt et `traverse` as
Left (error "unifica oh my god fix this later") case allUnify ts of
e' <- lintE g e Just err -> Left err
pure $ head ts :< CaseF e' as' Nothing -> pure $ head ts :< CaseF e' as'
where where
checkAlt :: Alter Var -> SysF (Type, AlterF Var ET) checkAlt :: Type -> Alter Var -> SysF (Type, AlterF Var ET)
checkAlt (AlterF (AltData con) bs e) = do checkAlt scrutineeType (AlterF (AltData con) bs e) = do
ct <- lookupVar g con ct <- lookupVar g con
zipWithM_ fzip bs (ct ^.. arrowStops) ct' <- foldrMOf applicants (elimForall g) ct scrutineeType
zipWithM_ fzip bs (ct' ^.. arrowStops)
(t :< e') <- lintE (supplementVars (varsToPairs bs) g) (wrapFix e) (t :< e') <- lintE (supplementVars (varsToPairs bs) g) (wrapFix e)
pure (t, AlterF (AltData con) bs e') pure (t, AlterF (AltData con) bs e')
where where
fzip (MkVar _ t) t' fzip (MkVar _ t) t'
| t == t' = Right () | t == t' = Right ()
| otherwise = Left (TypeErrorCouldNotMatch t t') | otherwise = Left (SystemFErrorCouldNotMatch t t')
unforall :: Type -> Type allUnify :: [Type] -> Maybe SystemFError
unforall (TyForall _ m) = m allUnify [] = Nothing
unforall m = m allUnify [t] = Nothing
allUnify (t:t':ts)
| t == t' = allUnify ts
| otherwise = Just (SystemFErrorCouldNotMatch t t')
elimForall :: Gamma -> Type -> Type -> SysF Type
elimForall g t (TyForall (n :^ k) m) = do
k' <- kindOf g t
case k == k' of
True -> pure $ subst n t m
False -> Left $ SystemFErrorKindMismatch k k'
elimForall _ m _ = pure m
varsToPairs :: [Var] -> [(Name, Type)] varsToPairs :: [Var] -> [(Name, Type)]
varsToPairs = toListOf (each . _MkVar) varsToPairs = toListOf (each . _MkVar)
checkAgainst :: Gamma -> Var -> Expr Var -> SysF ET checkAgainst :: Gamma -> Var -> Expr Var -> SysF ET
checkAgainst g v@(MkVar n t) e = case lintE g e of checkAgainst g v@(MkVar n t) e = case lintE g e of
Right e'@(t' :< _) | t == t' -> Right e' Right e'@(t' :< _) | t == t' -> Right e'
| otherwise -> Left (TypeErrorCouldNotMatch t t') | otherwise -> Left (SystemFErrorCouldNotMatch t t')
Left a -> Left a Left a -> Left a
supplementVars :: [(Name, Type)] -> Gamma -> Gamma supplementVars :: [(Name, Type)] -> Gamma -> Gamma
@@ -174,17 +205,17 @@ kindOf _ e = error (show e)
lookupCon :: Gamma -> Name -> SysF Kind lookupCon :: Gamma -> Name -> SysF Kind
lookupCon g n = case g ^. gammaTyCons . at n of lookupCon g n = case g ^. gammaTyCons . at n of
Just k -> Right k Just k -> Right k
Nothing -> Left (TypeErrorUndefinedVariable n) Nothing -> Left (SystemFErrorUndefinedVariable n)
lookupVar :: Gamma -> Name -> SysF Type lookupVar :: Gamma -> Name -> SysF Type
lookupVar g n = case g ^. gammaVars . at n of lookupVar g n = case g ^. gammaVars . at n of
Just t -> Right t Just t -> Right t
Nothing -> Left (TypeErrorUndefinedVariable n) Nothing -> Left (SystemFErrorUndefinedVariable n)
lookupTyVar :: Gamma -> Name -> SysF Kind lookupTyVar :: Gamma -> Name -> SysF Kind
lookupTyVar g n = case g ^. gammaTyVars . at n of lookupTyVar g n = case g ^. gammaTyVars . at n of
Just k -> Right k Just k -> Right k
Nothing -> Left (TypeErrorUndefinedVariable n) Nothing -> Left (SystemFErrorUndefinedVariable n)
demoContext :: Gamma demoContext :: Gamma
demoContext = Gamma demoContext = Gamma

View File

@@ -1,3 +1,4 @@
{-# LANGUAGE QuantifiedConstraints #-}
module Data.Pretty module Data.Pretty
( Pretty(..) ( Pretty(..)
, rpretty , rpretty
@@ -18,10 +19,13 @@ import Text.PrettyPrint hiding ((<>))
import Text.PrettyPrint.HughesPJ hiding ((<>)) import Text.PrettyPrint.HughesPJ hiding ((<>))
import Text.Printf import Text.Printf
import Data.String (IsString(..)) import Data.String (IsString(..))
import Data.Text.Lens import Data.Text.Lens hiding ((:<))
import Data.Monoid import Data.Monoid
import Data.Text qualified as T
import Control.Lens import Control.Lens
-- instances
import Control.Comonad.Cofree
import Data.Text qualified as T
---------------------------------------------------------------------------------- ----------------------------------------------------------------------------------
class Pretty a where class Pretty a where
@@ -48,6 +52,9 @@ instance (Show a) => Pretty (Showing a) where
deriving via Showing Int instance Pretty Int deriving via Showing Int instance Pretty Int
class (forall a. Pretty a => Pretty (f a)) => Pretty1 f where
liftPrettyPrec :: (Int -> a -> Doc) -> f a -> Doc
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
ttext :: Pretty t => t -> Doc ttext :: Pretty t => t -> Doc
@@ -75,3 +82,10 @@ appPrec, appPrec1 :: Int
appPrec = 10 appPrec = 10
appPrec1 = 11 appPrec1 = 11
instance PrintfArg Doc where
formatArg d fmt
| fmtChar (vFmt 'D' fmt) == 'D' = formatString (render d) fmt'
| otherwise = errorBadFormat $ fmtChar fmt
where
fmt' = fmt { fmtChar = 's', fmtPrecision = Nothing }