module Agda.TypeChecking.Patterns.Abstract where
import Control.Monad.Except
import qualified Data.List as List
import Data.Functor
import Data.Void
import qualified Agda.Syntax.Abstract as A
import Agda.Syntax.Abstract.Pattern
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.Pretty
import Agda.TypeChecking.Warnings (raiseWarningsOnUsage)
import Agda.Utils.Impossible
expandLitPattern
:: (MonadError TCErr m, MonadTCEnv m, ReadTCState m, HasBuiltins m)
=> A.Pattern -> m A.Pattern
expandLitPattern :: forall (m :: * -> *).
(MonadError TCErr m, MonadTCEnv m, ReadTCState m, HasBuiltins m) =>
Pattern -> m Pattern
expandLitPattern = \case
A.LitP PatInfo
info (LitNat Integer
n)
| Integer
n Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
< Integer
0 -> m Pattern
forall {a}. m a
negLit
| Integer
n Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
> Integer
20 -> m Pattern
forall {a}. m a
tooBig
| Bool
otherwise -> do
Con z _ _ <- m Term
forall (m :: * -> *).
(HasBuiltins m, MonadError TCErr m, MonadTCEnv m, ReadTCState m) =>
m Term
primZero
Con s _ _ <- primSuc
let r = PatInfo -> Range
forall a. HasRange a => a -> Range
getRange PatInfo
info
let 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 a. SetRange a => Range -> a -> a
setRange Range
r (QName -> QName) -> QName -> QName
forall a b. (a -> b) -> a -> b
$ ConHead -> QName
conName ConHead
z) []
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 a. SetRange a => Range -> a -> a
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]
cinfo = ConInfo -> PatInfo -> ConPatLazy -> ConPatInfo
A.ConPatInfo ConInfo
ConOCon PatInfo
info ConPatLazy
ConPatEager
return $ foldr ($) zero $ List.genericReplicate n suc
Pattern
p -> Pattern -> m Pattern
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return Pattern
p
where
tooBig :: m a
tooBig = TypeError -> m a
forall (m :: * -> *) a.
(HasCallStack, MonadTCError m) =>
TypeError -> m a
typeError (TypeError -> m a) -> TypeError -> m a
forall a b. (a -> b) -> a -> b
$ [Char] -> TypeError
GenericError ([Char] -> TypeError) -> [Char] -> TypeError
forall a b. (a -> b) -> a -> b
$
[Char]
"Matching on natural number literals is done by expanding " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++
[Char]
"the literal to the corresponding constructor pattern, so " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++
[Char]
"you probably don't want to do it this way."
negLit :: m a
negLit = TypeError -> m a
forall (m :: * -> *) a.
(HasCallStack, MonadTCError m) =>
TypeError -> m a
typeError (TypeError -> m a) -> TypeError -> m a
forall a b. (a -> b) -> a -> b
$ [Char] -> TypeError
GenericError ([Char] -> TypeError) -> [Char] -> TypeError
forall a b. (a -> b) -> a -> b
$
[Char]
"Negative literals are not supported in patterns"
expandPatternSynonyms' :: forall e. A.Pattern' e -> TCM (A.Pattern' e)
expandPatternSynonyms' :: forall e. Pattern' e -> TCM (Pattern' e)
expandPatternSynonyms' = (Pattern' (ADotT (Pattern' e))
-> TCMT IO (Pattern' (ADotT (Pattern' e))))
-> Pattern' e -> TCMT IO (Pattern' e)
forall p (m :: * -> *).
(APatternLike p, Monad m) =>
(Pattern' (ADotT p) -> m (Pattern' (ADotT p))) -> p -> m p
postTraverseAPatternM ((Pattern' (ADotT (Pattern' e))
-> TCMT IO (Pattern' (ADotT (Pattern' e))))
-> Pattern' e -> TCMT IO (Pattern' e))
-> (Pattern' (ADotT (Pattern' e))
-> TCMT IO (Pattern' (ADotT (Pattern' e))))
-> Pattern' e
-> TCMT IO (Pattern' e)
forall a b. (a -> b) -> a -> b
$ \case
A.PatternSynP PatInfo
i AmbiguousQName
x NAPs (ADotT (Pattern' e))
as -> PatInfo
-> TCMT IO (Pattern' (ADotT (Pattern' e)))
-> TCMT IO (Pattern' (ADotT (Pattern' e)))
forall (m :: * -> *) x a.
(MonadTrace m, HasRange x) =>
x -> m a -> m a
setCurrentRange PatInfo
i (TCMT IO (Pattern' (ADotT (Pattern' e)))
-> TCMT IO (Pattern' (ADotT (Pattern' e))))
-> TCMT IO (Pattern' (ADotT (Pattern' e)))
-> TCMT IO (Pattern' (ADotT (Pattern' e)))
forall a b. (a -> b) -> a -> b
$ do
(ns, p) <- KillRangeT PatternSynDefn
forall a. KillRange a => KillRangeT a
killRange KillRangeT PatternSynDefn
-> TCMT IO PatternSynDefn -> TCMT IO PatternSynDefn
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> AmbiguousQName -> TCMT IO PatternSynDefn
lookupPatternSyn AmbiguousQName
x
mapM_ raiseWarningsOnUsage $ A.unAmbQ x
p <- expandPatternSynonyms' (vacuous p :: A.Pattern' e)
reportSDoc "scope.patsyn" 80 $ vcat
[ "calling insertImplicitPatSynArgs"
, "- patsyn parameters: " <+> (text . show) (killRange ns)
, "- patsyn arguments: " <+> (text . show) (fmap (fmap void) as)
]
case A.insertImplicitPatSynArgs (\ Hiding
_h Range
r -> PatInfo -> Pattern' e
forall e. PatInfo -> Pattern' e
A.WildP (Range -> PatInfo
PatRange Range
r)) (getRange x) ns as of
Maybe ([(Name, Pattern' e)], [WithHiding Name])
Nothing -> TypeError -> TCMT IO (Pattern' e)
forall (m :: * -> *) a.
(HasCallStack, MonadTCError m) =>
TypeError -> m a
typeError (TypeError -> TCMT IO (Pattern' e))
-> TypeError -> TCMT IO (Pattern' e)
forall a b. (a -> b) -> a -> b
$ AmbiguousQName -> TypeError
BadArgumentsToPatternSynonym AmbiguousQName
x
Just ([(Name, Pattern' e)]
_, WithHiding Name
_:[WithHiding Name]
_) -> TypeError -> TCMT IO (Pattern' e)
forall (m :: * -> *) a.
(HasCallStack, MonadTCError m) =>
TypeError -> m a
typeError (TypeError -> TCMT IO (Pattern' e))
-> TypeError -> TCMT IO (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 -> TCMT IO (Pattern' e)
forall a. a -> TCMT IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Pattern' e -> TCMT IO (Pattern' e))
-> Pattern' e -> TCMT IO (Pattern' e)
forall a b. (a -> b) -> a -> b
$ Range -> Pattern' e -> Pattern' e
forall a. SetRange a => Range -> a -> a
setRange (PatInfo -> Range
forall a. HasRange a => a -> 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' (ADotT (Pattern' e))
p -> Pattern' e -> TCMT IO (Pattern' e)
forall a. a -> TCMT IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Pattern' e
Pattern' (ADotT (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)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> f a -> f (f b)
traverse b -> TCMT IO b
forall a. ExpandPatternSynonyms a => a -> TCM a
expandPatternSynonyms
instance ExpandPatternSynonyms a => ExpandPatternSynonyms (Maybe a)
instance ExpandPatternSynonyms a => ExpandPatternSynonyms [a]
instance ExpandPatternSynonyms a => ExpandPatternSynonyms (Arg a)
instance ExpandPatternSynonyms a => ExpandPatternSynonyms (Named n a)
instance ExpandPatternSynonyms a => ExpandPatternSynonyms (FieldAssignment' a)
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'