{-# LANGUAGE CPP #-} {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveFoldable #-} {-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE DeriveTraversable #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE TypeSynonymInstances #-} {-| Some common syntactic entities are defined in this module. -} module Agda.Syntax.Common where import Control.Applicative import Data.ByteString.Char8 (ByteString) import qualified Data.ByteString.Char8 as ByteString import Data.Foldable import Data.Hashable import Data.Traversable import Data.Typeable (Typeable) import Test.QuickCheck import Agda.Syntax.Position import Agda.Utils.Functor import Agda.Utils.Pretty import Agda.Utils.Size #include "undefined.h" import Agda.Utils.Impossible --------------------------------------------------------------------------- -- * Delayed --------------------------------------------------------------------------- -- | Used to specify whether something should be delayed. data Delayed = Delayed | NotDelayed deriving (Typeable, Show, Eq, Ord) instance KillRange Delayed where killRange = id --------------------------------------------------------------------------- -- * Induction --------------------------------------------------------------------------- data Induction = Inductive | CoInductive deriving (Typeable, Eq, Ord) instance Show Induction where show Inductive = "inductive" show CoInductive = "coinductive" instance HasRange Induction where getRange _ = noRange instance KillRange Induction where killRange = id instance Arbitrary Induction where arbitrary = elements [Inductive, CoInductive] instance CoArbitrary Induction where coarbitrary Inductive = variant 0 coarbitrary CoInductive = variant 1 --------------------------------------------------------------------------- -- * Hiding --------------------------------------------------------------------------- data Hiding = Hidden | Instance | NotHidden deriving (Typeable, Show, Eq, Ord) instance KillRange Hiding where killRange = id -- | A lens to access the 'Hiding' attribute in data structures. -- Minimal implementation: @getHiding@ and one of @setHiding@ or @mapHiding@. class LensHiding a where getHiding :: a -> Hiding setHiding :: Hiding -> a -> a setHiding h = mapHiding (const h) mapHiding :: (Hiding -> Hiding) -> a -> a mapHiding f a = setHiding (f $ getHiding a) a instance LensHiding Hiding where getHiding = id setHiding = const mapHiding = id -- | @isHidden@ does not apply to 'Instance', only to 'Hidden'. isHidden :: LensHiding a => a -> Bool isHidden a = getHiding a == Hidden -- | Visible ('NotHidden') arguments are @notHidden@. (DEPRECATED, use 'visible'.) notHidden :: LensHiding a => a -> Bool notHidden a = getHiding a == NotHidden -- | 'NotHidden' arguments are @visible@. visible :: LensHiding a => a -> Bool visible a = getHiding a == NotHidden -- | 'Instance' and 'Hidden' arguments are @notVisible@. notVisible :: LensHiding a => a -> Bool notVisible a = getHiding a /= NotHidden hide :: LensHiding a => a -> a hide = setHiding Hidden makeInstance :: LensHiding a => a -> a makeInstance = setHiding Instance --------------------------------------------------------------------------- -- * Relevance --------------------------------------------------------------------------- -- | A function argument can be relevant or irrelevant. -- See 'Agda.TypeChecking.Irrelevance'. data Relevance = Relevant -- ^ The argument is (possibly) relevant at compile-time. | NonStrict -- ^ The argument may never flow into evaluation position. -- Therefore, it is irrelevant at run-time. -- It is treated relevantly during equality checking. | Irrelevant -- ^ The argument is irrelevant at compile- and runtime. | Forced -- ^ The argument can be skipped during equality checking -- because its value is already determined by the type. | UnusedArg -- ^ The polarity checker has determined that this argument -- is unused in the definition. It can be skipped during -- equality checking but should be mined for solutions -- of meta-variables with relevance 'UnusedArg' deriving (Typeable, Show, Eq, Enum, Bounded) instance KillRange Relevance where killRange rel = rel -- no range to kill instance Arbitrary Relevance where arbitrary = elements [minBound..maxBound] instance Ord Relevance where (<=) = moreRelevant -- | A lens to access the 'Relevance' attribute in data structures. -- Minimal implementation: @getRelevance@ and one of @setRelevance@ or @mapRelevance@. class LensRelevance a where getRelevance :: a -> Relevance setRelevance :: Relevance -> a -> a setRelevance h = mapRelevance (const h) mapRelevance :: (Relevance -> Relevance) -> a -> a mapRelevance f a = setRelevance (f $ getRelevance a) a instance LensRelevance Relevance where getRelevance = id setRelevance = const mapRelevance = id isRelevant :: LensRelevance a => a -> Bool isRelevant a = getRelevance a == Relevant isIrrelevant :: LensRelevance a => a -> Bool isIrrelevant a = getRelevance a == Irrelevant -- | Information ordering. -- @Relevant \`moreRelevant\` -- UnusedArg \`moreRelevant\` -- Forced \`moreRelevant\` -- NonStrict \`moreRelevant\` -- Irrelevant@ moreRelevant :: Relevance -> Relevance -> Bool moreRelevant r r' = case (r, r') of -- top (_, Irrelevant) -> True (Irrelevant, _) -> False -- bottom (Relevant, _) -> True (_, Relevant) -> False -- second bottom (UnusedArg, _) -> True (_, UnusedArg) -> False -- third bottom (Forced, _) -> True (_, Forced) -> False -- remaining case (NonStrict,NonStrict) -> True --------------------------------------------------------------------------- -- * Argument decoration --------------------------------------------------------------------------- -- | A function argument can be hidden and/or irrelevant. data ArgInfo c = ArgInfo { argInfoHiding :: Hiding , argInfoRelevance :: Relevance , argInfoColors :: [c] } deriving (Typeable, Eq, Ord, Functor, Foldable, Traversable, Show) instance KillRange c => KillRange (ArgInfo c) where killRange (ArgInfo h r cs) = killRange3 ArgInfo h r cs {- FAILED to define a less for ArgInfo, since it is parametrized by c can't instantiate the following to f c = Arg c e since Haskell does not have lambda abstraction class LensArgInfo f where getArgInfo :: f c -> ArgInfo c setArgInfo :: ArgInfo c' -> f c -> f c' setArgInfo ai = mapArgInfo (const ai) mapArgInfo :: (ArgInfo c -> ArgInfo c') -> f c -> f c' mapArgInfo f a = setArgInfo (f $ getArgInfo a) a instance LensArgInfo ArgInfo where getArgInfo = id setArgInfo = const mapArgInfo = id -} {- FAILS because map is too restricted class LensArgInfo c a where getArgInfo :: a -> ArgInfo c setArgInfo :: ArgInfo c -> a -> a setArgInfo ai = mapArgInfo (const ai) mapArgInfo :: (ArgInfo c -> ArgInfo c) -> a -> a mapArgInfo f a = setArgInfo (f $ getArgInfo a) a instance LensArgInfo c (ArgInfo c) where getArgInfo = id setArgInfo = const mapArgInfo = id -} instance LensHiding (ArgInfo c) where getHiding = argInfoHiding setHiding h ai = ai { argInfoHiding = h } mapHiding f ai = ai { argInfoHiding = f (argInfoHiding ai) } instance LensRelevance (ArgInfo c) where getRelevance = argInfoRelevance setRelevance h ai = ai { argInfoRelevance = h } mapRelevance f ai = ai { argInfoRelevance = f (argInfoRelevance ai) } mapArgInfoColors :: ([c] -> [c']) -> ArgInfo c -> ArgInfo c' mapArgInfoColors f info = info { argInfoColors = f $ argInfoColors info } defaultArgInfo :: ArgInfo c defaultArgInfo = ArgInfo { argInfoHiding = NotHidden , argInfoRelevance = Relevant , argInfoColors = [] } --------------------------------------------------------------------------- -- * Arguments --------------------------------------------------------------------------- data Arg c e = Arg { argInfo :: ArgInfo c , unArg :: e } deriving (Typeable, Ord, Functor, Foldable, Traversable) instance Decoration (Arg c) where traverseF f (Arg ai a) = Arg ai <$> f a instance HasRange a => HasRange (Arg c a) where getRange = getRange . unArg instance (KillRange c, KillRange a) => KillRange (Arg c a) where killRange (Arg info a) = killRange2 Arg info a instance Sized a => Sized (Arg c a) where size = size . unArg instance (Eq a, Eq c) => Eq (Arg c a) where Arg (ArgInfo h1 _ cs1) x1 == Arg (ArgInfo h2 _ cs2) x2 = (h1, cs1, x1) == (h2, cs2, x2) instance (Show a, Show c) => Show (Arg c a) where show (Arg (ArgInfo h r cs) x) = showC cs $ showR r $ showH h $ show x where showH Hidden s = "{" ++ s ++ "}" showH NotHidden s = "(" ++ s ++ ")" showH Instance s = "{{" ++ s ++ "}}" showR Irrelevant s = "." ++ s showR NonStrict s = "?" ++ s showR Forced s = "!" ++ s showR UnusedArg s = "k" ++ s -- constant showR Relevant s = "r" ++ s -- Andreas: I want to see it explicitly showC cs s = show cs ++ s instance LensHiding (Arg c e) where getHiding = getHiding . argInfo mapHiding = mapArgInfo . mapHiding instance LensRelevance (Arg c e) where getRelevance = getRelevance . argInfo mapRelevance = mapArgInfo . mapRelevance {- RETIRED hide :: Arg c a -> Arg c a hide = setArgHiding Hidden makeInstance :: Arg c a -> Arg c a makeInstance = setHiding Instance isHiddenArg :: Arg c a -> Bool isHiddenArg arg = argHiding arg /= NotHidden -} mapArgInfo :: (ArgInfo c -> ArgInfo c') -> Arg c a -> Arg c' a mapArgInfo f arg = arg { argInfo = f $ argInfo arg } argColors :: Arg c a -> [c] argColors = argInfoColors . argInfo mapArgColors :: ([c] -> [c']) -> Arg c a -> Arg c' a mapArgColors = mapArgInfo . mapArgInfoColors setArgColors :: [c] -> Arg c' a -> Arg c a setArgColors = mapArgColors . const defaultArg :: a -> Arg c a defaultArg = Arg defaultArgInfo defaultColoredArg :: ([c],a) -> Arg c a defaultColoredArg (cs,a) = setArgColors cs $ defaultArg a noColorArg :: Hiding -> Relevance -> a -> Arg c a noColorArg h r = Arg ArgInfo { argInfoHiding = h , argInfoRelevance = r , argInfoColors = [] } -- | @xs \`withArgsFrom\` args@ translates @xs@ into a list of 'Arg's, -- using the elements in @args@ to fill in the non-'unArg' fields. -- -- Precondition: The two lists should have equal length. withArgsFrom :: [a] -> [Arg c b] -> [Arg c a] xs `withArgsFrom` args = zipWith (\x arg -> fmap (const x) arg) xs args withNamedArgsFrom :: [a] -> [NamedArg c b] -> [NamedArg c a] xs `withNamedArgsFrom` args = zipWith (\x -> fmap (x <$)) xs args --------------------------------------------------------------------------- -- * Names --------------------------------------------------------------------------- class Eq a => Underscore a where underscore :: a isUnderscore :: a -> Bool isUnderscore = (== underscore) instance Underscore String where underscore = "_" instance Underscore ByteString where underscore = ByteString.pack underscore instance Underscore Doc where underscore = text underscore --------------------------------------------------------------------------- -- * Function type domain --------------------------------------------------------------------------- -- | Similar to 'Arg', but we need to distinguish -- an irrelevance annotation in a function domain -- (the domain itself is not irrelevant!) -- from an irrelevant argument. -- -- @Dom@ is used in 'Pi' of internal syntax, in 'Context' and 'Telescope'. -- 'Arg' is used for actual arguments ('Var', 'Con', 'Def' etc.) -- and in 'Abstract' syntax and other situations. data Dom c e = Dom { domInfo :: ArgInfo c , unDom :: e } deriving (Typeable, Eq, Ord, Functor, Foldable, Traversable) instance Decoration (Dom c) where traverseF f (Dom ai a) = Dom ai <$> f a instance HasRange a => HasRange (Dom c a) where getRange = getRange . unDom instance (KillRange c, KillRange a) => KillRange (Dom c a) where killRange (Dom info a) = killRange2 Dom info a instance Sized a => Sized (Dom c a) where size = size . unDom instance (Show a, Show c) => Show (Dom c a) where show = show . argFromDom instance LensHiding (Dom c e) where getHiding = getHiding . domInfo mapHiding = mapDomInfo . mapHiding instance LensRelevance (Dom c e) where getRelevance = getRelevance . domInfo mapRelevance = mapDomInfo . mapRelevance mapDomInfo :: (ArgInfo c -> ArgInfo c') -> Dom c a -> Dom c' a mapDomInfo f arg = arg { domInfo = f $ domInfo arg } domColors :: Dom c a -> [c] domColors = argInfoColors . domInfo argFromDom :: Dom c a -> Arg c a argFromDom (Dom i a) = Arg i a domFromArg :: Arg c a -> Dom c a domFromArg (Arg i a) = Dom i a defaultDom :: a -> Dom c a defaultDom = Dom defaultArgInfo --------------------------------------------------------------------------- -- * Named arguments --------------------------------------------------------------------------- -- | Something potentially carrying a name. data Named name a = Named { nameOf :: Maybe name , namedThing :: a } deriving (Eq, Ord, Typeable, Functor, Foldable, Traversable) -- | Standard naming. type Named_ = Named RString unnamed :: a -> Named name a unnamed = Named Nothing named :: name -> a -> Named name a named = Named . Just instance Decoration (Named name) where traverseF f (Named n a) = Named n <$> f a instance HasRange a => HasRange (Named name a) where getRange = getRange . namedThing instance (KillRange name, KillRange a) => KillRange (Named name a) where killRange (Named n a) = Named (killRange n) (killRange a) instance Sized a => Sized (Named name a) where size = size . namedThing instance Show a => Show (Named_ a) where show (Named Nothing x) = show x show (Named (Just n) x) = rawNameToString (rangedThing n) ++ " = " ++ show x -- | Only 'Hidden' arguments can have names. type NamedArg c a = Arg c (Named_ a) -- | Get the content of a 'NamedArg'. namedArg :: NamedArg c a -> a namedArg = namedThing . unArg defaultNamedArg :: a -> NamedArg c a defaultNamedArg = defaultArg . unnamed -- | The functor instance for 'NamedArg' would be ambiguous, -- so we give it another name here. updateNamedArg :: (a -> b) -> NamedArg c a -> NamedArg c b updateNamedArg = fmap . fmap --------------------------------------------------------------------------- -- * Range decoration. --------------------------------------------------------------------------- -- | Thing with range info. data Ranged a = Ranged { rangeOf :: Range , rangedThing :: a } deriving (Typeable, Functor, Foldable, Traversable) -- | Thing with no range info. unranged :: a -> Ranged a unranged = Ranged noRange instance Show a => Show (Ranged a) where show = show . rangedThing instance Eq a => Eq (Ranged a) where Ranged _ x == Ranged _ y = x == y instance Ord a => Ord (Ranged a) where compare (Ranged _ x) (Ranged _ y) = compare x y instance HasRange (Ranged a) where getRange = rangeOf instance KillRange (Ranged a) where killRange (Ranged _ x) = Ranged noRange x instance Decoration Ranged where traverseF f (Ranged r x) = Ranged r <$> f x --------------------------------------------------------------------------- -- * Raw names (before parsing into name parts). --------------------------------------------------------------------------- -- | A @RawName@ is some sort of string. type RawName = String rawNameToString :: RawName -> String rawNameToString = id stringToRawName :: String -> RawName stringToRawName = id -- | String with range info. type RString = Ranged RawName --------------------------------------------------------------------------- -- * Infixity, access, abstract, etc. --------------------------------------------------------------------------- -- | Functions can be defined in both infix and prefix style. See -- 'Agda.Syntax.Concrete.LHS'. data IsInfix = InfixDef | PrefixDef deriving (Typeable, Show, Eq, Ord) -- | Access modifier. data Access = PrivateAccess | PublicAccess | OnlyQualified -- ^ Visible from outside, but not exported when opening the module -- Used for qualified constructors. deriving (Typeable, Show, Eq, Ord) -- | Abstract or concrete data IsAbstract = AbstractDef | ConcreteDef deriving (Typeable, Show, Eq, Ord) instance KillRange IsAbstract where killRange = id -- | Is this definition eligible for instance search? data IsInstance = InstanceDef | NotInstanceDef deriving (Typeable, Show, Eq, Ord) type Nat = Int type Arity = Nat -- | The unique identifier of a name. Second argument is the top-level module -- identifier. data NameId = NameId Integer Integer deriving (Eq, Ord, Typeable) instance Show NameId where show (NameId x i) = show x ++ "@" ++ show i instance Enum NameId where succ (NameId n m) = NameId (n + 1) m pred (NameId n m) = NameId (n - 1) m toEnum n = __IMPOSSIBLE__ -- should not be used fromEnum (NameId n _) = fromIntegral n instance Hashable NameId where {-# INLINE hashWithSalt #-} hashWithSalt salt (NameId n m) = hashWithSalt salt (n, m) newtype Constr a = Constr a --------------------------------------------------------------------------- -- * Interaction meta variables --------------------------------------------------------------------------- newtype InteractionId = InteractionId { interactionId :: Nat } deriving (Eq,Ord,Num,Integral,Real,Enum) instance Show InteractionId where show (InteractionId x) = "?" ++ show x instance KillRange InteractionId where killRange = id ----------------------------------------------------------------------------- -- * Termination ----------------------------------------------------------------------------- -- | Termination check? (Default = True). data TerminationCheck m = TerminationCheck -- ^ Run the termination checker. | NoTerminationCheck -- ^ Skip termination checking (unsafe). | NonTerminating -- ^ Treat as non-terminating. | Terminating -- ^ Treat as terminating (unsafe). Same effect as 'NoTerminationCheck'. | TerminationMeasure !Range m -- ^ Skip termination checking but use measure instead. deriving (Typeable, Show, Eq, Functor) instance KillRange m => KillRange (TerminationCheck m) where killRange (TerminationMeasure _ m) = TerminationMeasure noRange (killRange m) killRange t = t