{-# LANGUAGE TypeFamilies #-}
module Agda.TypeChecking.Patterns.Abstract where
import qualified Data.List as List
import Data.Void
import qualified Agda.Syntax.Abstract as A
import Agda.Syntax.Abstract.Pattern
import Agda.Syntax.Abstract.Views
import Agda.Syntax.Concrete (FieldAssignment')
import Agda.Syntax.Common
import Agda.Syntax.Info as A
import Agda.Syntax.Internal as I
import Agda.Syntax.Literal
import Agda.Syntax.Position
import Agda.TypeChecking.Monad
import Agda.TypeChecking.Monad.Builtin
import Agda.Utils.Impossible
expandLitPattern :: A.Pattern -> TCM A.Pattern
expandLitPattern :: Pattern -> TCM Pattern
expandLitPattern Pattern
p = case Pattern -> ([Name], Pattern)
asView Pattern
p of
([Name]
xs, A.LitP (LitNat Range
r Integer
n))
| Integer
n Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
< Integer
0 -> TCM Pattern
forall a. TCMT IO a
negLit
| Integer
n Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
> Integer
20 -> TCM Pattern
forall a. TCMT IO a
tooBig
| Bool
otherwise -> do
Con ConHead
z ConInfo
_ Elims
_ <- TCMT IO Term
forall (m :: * -> *).
(HasBuiltins m, MonadError TCErr m, MonadTCEnv m, ReadTCState m) =>
m Term
primZero
Con ConHead
s ConInfo
_ Elims
_ <- TCMT IO Term
forall (m :: * -> *).
(HasBuiltins m, MonadError TCErr m, MonadTCEnv m, ReadTCState m) =>
m Term
primSuc
let zero :: Pattern
zero = ConPatInfo -> AmbiguousQName -> NAPs Expr -> Pattern
forall e. ConPatInfo -> AmbiguousQName -> NAPs e -> Pattern' e
A.ConP ConPatInfo
cinfo (QName -> AmbiguousQName
unambiguous (QName -> AmbiguousQName) -> QName -> AmbiguousQName
forall a b. (a -> b) -> a -> b
$ Range -> QName -> QName
forall t. SetRange t => Range -> t -> t
setRange Range
r (QName -> QName) -> QName -> QName
forall a b. (a -> b) -> a -> b
$ ConHead -> QName
conName ConHead
z) []
suc :: Pattern -> Pattern
suc Pattern
p = ConPatInfo -> AmbiguousQName -> NAPs Expr -> Pattern
forall e. ConPatInfo -> AmbiguousQName -> NAPs e -> Pattern' e
A.ConP ConPatInfo
cinfo (QName -> AmbiguousQName
unambiguous (QName -> AmbiguousQName) -> QName -> AmbiguousQName
forall a b. (a -> b) -> a -> b
$ Range -> QName -> QName
forall t. SetRange t => Range -> t -> t
setRange Range
r (QName -> QName) -> QName -> QName
forall a b. (a -> b) -> a -> b
$ ConHead -> QName
conName ConHead
s) [Pattern -> NamedArg Pattern
forall a. a -> NamedArg a
defaultNamedArg Pattern
p]
info :: PatInfo
info = Range -> PatInfo
A.PatRange Range
r
cinfo :: ConPatInfo
cinfo = ConInfo -> PatInfo -> ConPatLazy -> ConPatInfo
A.ConPatInfo ConInfo
ConOCon PatInfo
info ConPatLazy
ConPatEager
p' :: Pattern
p' = ((Pattern -> Pattern) -> Pattern -> Pattern)
-> Pattern -> [Pattern -> Pattern] -> Pattern
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (Pattern -> Pattern) -> Pattern -> Pattern
forall a b. (a -> b) -> a -> b
($) Pattern
zero ([Pattern -> Pattern] -> Pattern)
-> [Pattern -> Pattern] -> Pattern
forall a b. (a -> b) -> a -> b
$ Integer -> (Pattern -> Pattern) -> [Pattern -> Pattern]
forall i a. Integral i => i -> a -> [a]
List.genericReplicate Integer
n Pattern -> Pattern
suc
Pattern -> TCM Pattern
forall (m :: * -> *) a. Monad m => a -> m a
return (Pattern -> TCM Pattern) -> Pattern -> TCM Pattern
forall a b. (a -> b) -> a -> b
$ (BindName -> Pattern -> Pattern)
-> Pattern -> [BindName] -> Pattern
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (PatInfo -> BindName -> Pattern -> Pattern
forall e. PatInfo -> BindName -> Pattern' e -> Pattern' e
A.AsP PatInfo
info) Pattern
p' ((Name -> BindName) -> [Name] -> [BindName]
forall a b. (a -> b) -> [a] -> [b]
map Name -> BindName
A.mkBindName [Name]
xs)
([Name], Pattern)
_ -> Pattern -> TCM Pattern
forall (m :: * -> *) a. Monad m => a -> m a
return Pattern
p
where
tooBig :: TCMT IO a
tooBig = TypeError -> TCMT IO a
forall (m :: * -> *) a.
(MonadTCEnv m, ReadTCState m, MonadError TCErr m) =>
TypeError -> m a
typeError (TypeError -> TCMT IO a) -> TypeError -> TCMT IO a
forall a b. (a -> b) -> a -> b
$ String -> TypeError
GenericError (String -> TypeError) -> String -> TypeError
forall a b. (a -> b) -> a -> b
$
String
"Matching on natural number literals is done by expanding " String -> String -> String
forall a. [a] -> [a] -> [a]
++
String
"the literal to the corresponding constructor pattern, so " String -> String -> String
forall a. [a] -> [a] -> [a]
++
String
"you probably don't want to do it this way."
negLit :: TCMT IO a
negLit = TypeError -> TCMT IO a
forall (m :: * -> *) a.
(MonadTCEnv m, ReadTCState m, MonadError TCErr m) =>
TypeError -> m a
typeError (TypeError -> TCMT IO a) -> TypeError -> TCMT IO a
forall a b. (a -> b) -> a -> b
$ String -> TypeError
GenericError (String -> TypeError) -> String -> TypeError
forall a b. (a -> b) -> a -> b
$
String
"Negative literals are not supported in patterns"
expandPatternSynonyms' :: forall e. A.Pattern' e -> TCM (A.Pattern' e)
expandPatternSynonyms' :: Pattern' e -> TCM (Pattern' e)
expandPatternSynonyms' = (Pattern' e -> TCM (Pattern' e)) -> Pattern' e -> TCM (Pattern' e)
forall a b (m :: * -> *).
(APatternLike a b, Monad m) =>
(Pattern' a -> m (Pattern' a)) -> b -> m b
postTraverseAPatternM ((Pattern' e -> TCM (Pattern' e))
-> Pattern' e -> TCM (Pattern' e))
-> (Pattern' e -> TCM (Pattern' e))
-> Pattern' e
-> TCM (Pattern' e)
forall a b. (a -> b) -> a -> b
$ \case
A.PatternSynP PatInfo
i AmbiguousQName
x NAPs e
as -> PatInfo -> TCM (Pattern' e) -> TCM (Pattern' e)
forall (tcm :: * -> *) x a.
(MonadTCM tcm, ReadTCState tcm, MonadDebug tcm, HasRange x) =>
x -> tcm a -> tcm a
setCurrentRange PatInfo
i (TCM (Pattern' e) -> TCM (Pattern' e))
-> TCM (Pattern' e) -> TCM (Pattern' e)
forall a b. (a -> b) -> a -> b
$ do
([Arg Name]
ns, Pattern' Void
p) <- KillRangeT ([Arg Name], Pattern' Void)
forall a. KillRange a => KillRangeT a
killRange KillRangeT ([Arg Name], Pattern' Void)
-> TCMT IO ([Arg Name], Pattern' Void)
-> TCMT IO ([Arg Name], Pattern' Void)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> AmbiguousQName -> TCMT IO ([Arg Name], Pattern' Void)
lookupPatternSyn AmbiguousQName
x
Pattern' e
p <- Pattern' e -> TCM (Pattern' e)
forall e. Pattern' e -> TCM (Pattern' e)
expandPatternSynonyms' (Pattern' Void -> Pattern' e
forall (f :: * -> *) a. Functor f => f Void -> f a
vacuous Pattern' Void
p :: A.Pattern' e)
case (Range -> Pattern' e)
-> Range
-> [Arg Name]
-> NAPs e
-> Maybe ([(Name, Pattern' e)], [Arg Name])
forall a.
HasRange a =>
(Range -> a)
-> Range
-> [Arg Name]
-> [NamedArg a]
-> Maybe ([(Name, a)], [Arg Name])
A.insertImplicitPatSynArgs (PatInfo -> Pattern' e
forall e. PatInfo -> Pattern' e
A.WildP (PatInfo -> Pattern' e)
-> (Range -> PatInfo) -> Range -> Pattern' e
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Range -> PatInfo
PatRange) (AmbiguousQName -> Range
forall t. HasRange t => t -> Range
getRange AmbiguousQName
x) [Arg Name]
ns NAPs e
as of
Maybe ([(Name, Pattern' e)], [Arg Name])
Nothing -> TypeError -> TCM (Pattern' e)
forall (m :: * -> *) a.
(MonadTCEnv m, ReadTCState m, MonadError TCErr m) =>
TypeError -> m a
typeError (TypeError -> TCM (Pattern' e)) -> TypeError -> TCM (Pattern' e)
forall a b. (a -> b) -> a -> b
$ AmbiguousQName -> TypeError
BadArgumentsToPatternSynonym AmbiguousQName
x
Just ([(Name, Pattern' e)]
_, Arg Name
_:[Arg Name]
_) -> TypeError -> TCM (Pattern' e)
forall (m :: * -> *) a.
(MonadTCEnv m, ReadTCState m, MonadError TCErr m) =>
TypeError -> m a
typeError (TypeError -> TCM (Pattern' e)) -> TypeError -> TCM (Pattern' e)
forall a b. (a -> b) -> a -> b
$ AmbiguousQName -> TypeError
TooFewArgumentsToPatternSynonym AmbiguousQName
x
Just ([(Name, Pattern' e)]
s, []) -> do
let subE :: p -> a
subE p
_ = a
forall a. HasCallStack => a
__IMPOSSIBLE__
Pattern' e -> TCM (Pattern' e)
forall (m :: * -> *) a. Monad m => a -> m a
return (Pattern' e -> TCM (Pattern' e)) -> Pattern' e -> TCM (Pattern' e)
forall a b. (a -> b) -> a -> b
$ Range -> Pattern' e -> Pattern' e
forall t. SetRange t => Range -> t -> t
setRange (PatInfo -> Range
forall t. HasRange t => t -> Range
getRange PatInfo
i) (Pattern' e -> Pattern' e) -> Pattern' e -> Pattern' e
forall a b. (a -> b) -> a -> b
$ (e -> e) -> [(Name, Pattern' e)] -> Pattern' e -> Pattern' e
forall e.
(e -> e) -> [(Name, Pattern' e)] -> Pattern' e -> Pattern' e
substPattern' e -> e
forall p a. p -> a
subE [(Name, Pattern' e)]
s Pattern' e
p
Pattern' e
p -> Pattern' e -> TCM (Pattern' e)
forall (m :: * -> *) a. Monad m => a -> m a
return Pattern' e
p
class ExpandPatternSynonyms a where
expandPatternSynonyms :: a -> TCM a
default expandPatternSynonyms
:: (Traversable f, ExpandPatternSynonyms b, f b ~ a) => a -> TCM a
expandPatternSynonyms = (b -> TCMT IO b) -> f b -> TCMT IO (f b)
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse b -> TCMT IO b
forall a. ExpandPatternSynonyms a => a -> TCM a
expandPatternSynonyms
instance ExpandPatternSynonyms a => ExpandPatternSynonyms (Maybe a) where
instance ExpandPatternSynonyms a => ExpandPatternSynonyms [a] where
instance ExpandPatternSynonyms a => ExpandPatternSynonyms (Arg a) where
instance ExpandPatternSynonyms a => ExpandPatternSynonyms (Named n a) where
instance ExpandPatternSynonyms a => ExpandPatternSynonyms (FieldAssignment' a) where
instance ExpandPatternSynonyms (A.Pattern' e) where
expandPatternSynonyms :: Pattern' e -> TCM (Pattern' e)
expandPatternSynonyms = Pattern' e -> TCM (Pattern' e)
forall e. Pattern' e -> TCM (Pattern' e)
expandPatternSynonyms'