{-# LANGUAGE CPP #-} {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE UndecidableInstances #-} -- for: LensNamed name (Arg a) {-| Some common syntactic entities are defined in this module. -} module Agda.Syntax.Common where import Control.DeepSeq import Data.ByteString.Char8 (ByteString) import qualified Data.ByteString.Char8 as ByteString import Data.Foldable import Data.Hashable (Hashable(..)) import qualified Data.Strict.Maybe as Strict import Data.Semigroup hiding (Arg) import Data.Traversable import Data.Data (Data) import Data.Word import Data.IntSet (IntSet) import qualified Data.IntSet as IntSet import GHC.Generics (Generic) import Agda.Syntax.Position import Agda.Utils.Functor import Agda.Utils.Lens import Agda.Utils.PartialOrd import Agda.Utils.POMonoid import Agda.Utils.Pretty hiding ((<>)) #include "undefined.h" import Agda.Utils.Impossible --------------------------------------------------------------------------- -- * Delayed --------------------------------------------------------------------------- -- | Used to specify whether something should be delayed. data Delayed = Delayed | NotDelayed deriving (Data, Show, Eq, Ord) instance KillRange Delayed where killRange = id --------------------------------------------------------------------------- -- * File --------------------------------------------------------------------------- data FileType = AgdaFileType | MdFileType | RstFileType | TexFileType | OrgFileType deriving (Data, Eq, Ord, Show) instance Pretty FileType where pretty = \case AgdaFileType -> "Agda" MdFileType -> "Markdown" RstFileType -> "ReStructedText" TexFileType -> "LaTeX" OrgFileType -> "org-mode" --------------------------------------------------------------------------- -- * Eta-equality --------------------------------------------------------------------------- data HasEta = NoEta | YesEta deriving (Data, Show, Eq, Ord) instance HasRange HasEta where getRange _ = noRange instance KillRange HasEta where killRange = id instance NFData HasEta where rnf NoEta = () rnf YesEta = () --------------------------------------------------------------------------- -- * Induction --------------------------------------------------------------------------- data Induction = Inductive | CoInductive deriving (Data, Eq, Ord, Show) instance Pretty Induction where pretty Inductive = "inductive" pretty CoInductive = "coinductive" instance HasRange Induction where getRange _ = noRange instance KillRange Induction where killRange = id instance NFData Induction where rnf Inductive = () rnf CoInductive = () --------------------------------------------------------------------------- -- * Hiding --------------------------------------------------------------------------- data Overlappable = YesOverlap | NoOverlap deriving (Data, Show, Eq, Ord) data Hiding = Hidden | Instance Overlappable | NotHidden deriving (Data, Show, Eq, Ord) instance Pretty Hiding where pretty = \case Hidden -> "hidden" NotHidden -> "visible" Instance{} -> "instance" -- | Just for the 'Hiding' instance. Should never combine different -- overlapping. instance Semigroup Overlappable where NoOverlap <> NoOverlap = NoOverlap YesOverlap <> YesOverlap = YesOverlap _ <> _ = __IMPOSSIBLE__ -- | 'Hiding' is an idempotent partial monoid, with unit 'NotHidden'. -- 'Instance' and 'NotHidden' are incompatible. instance Semigroup Hiding where NotHidden <> h = h h <> NotHidden = h Hidden <> Hidden = Hidden Instance o <> Instance o' = Instance (o <> o') _ <> _ = __IMPOSSIBLE__ instance Monoid Overlappable where mempty = NoOverlap mappend = (<>) instance Monoid Hiding where mempty = NotHidden mappend = (<>) instance KillRange Hiding where killRange = id instance NFData Overlappable where rnf NoOverlap = () rnf YesOverlap = () instance NFData Hiding where rnf Hidden = () rnf (Instance o) = rnf o rnf NotHidden = () -- | Decorating something with 'Hiding' information. data WithHiding a = WithHiding { whHiding :: !Hiding , whThing :: a } deriving (Data, Eq, Ord, Show, Functor, Foldable, Traversable) instance Decoration WithHiding where traverseF f (WithHiding h a) = WithHiding h <$> f a instance Applicative WithHiding where pure = WithHiding mempty WithHiding h f <*> WithHiding h' a = WithHiding (mappend h h') (f a) instance HasRange a => HasRange (WithHiding a) where getRange = getRange . dget instance SetRange a => SetRange (WithHiding a) where setRange = fmap . setRange instance KillRange a => KillRange (WithHiding a) where killRange = fmap killRange instance NFData a => NFData (WithHiding a) where rnf (WithHiding _ a) = rnf a -- | 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 instance LensHiding (WithHiding a) where getHiding (WithHiding h _) = h setHiding h (WithHiding _ a) = WithHiding h a mapHiding f (WithHiding h a) = WithHiding (f h) a -- | Monoidal composition of 'Hiding' information in some data. mergeHiding :: LensHiding a => WithHiding a -> a mergeHiding (WithHiding h a) = mapHiding (mappend h) a -- | '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 -- | 'Hidden' arguments are @hidden@. hidden :: LensHiding a => a -> Bool hidden a = getHiding a == Hidden hide :: LensHiding a => a -> a hide = setHiding Hidden hideOrKeepInstance :: LensHiding a => a -> a hideOrKeepInstance x = case getHiding x of Hidden -> x Instance{} -> x NotHidden -> setHiding Hidden x makeInstance :: LensHiding a => a -> a makeInstance = makeInstance' NoOverlap makeInstance' :: LensHiding a => Overlappable -> a -> a makeInstance' o = setHiding (Instance o) isOverlappable :: LensHiding a => a -> Bool isOverlappable x = case getHiding x of Instance YesOverlap -> True _ -> False isInstance :: LensHiding a => a -> Bool isInstance x = case getHiding x of Instance{} -> True _ -> False -- | Ignores 'Overlappable'. sameHiding :: (LensHiding a, LensHiding b) => a -> b -> Bool sameHiding x y = case (getHiding x, getHiding y) of (Instance{}, Instance{}) -> True (hx, hy) -> hx == hy --------------------------------------------------------------------------- -- * Modalities --------------------------------------------------------------------------- -- | We have a tuple of modalities, which might not be fully orthogonal. -- For instance, irrelevant stuff is also run-time irrelevant. data Modality = Modality { modRelevance :: Relevance -- ^ Legacy irrelevance. -- See Pfenning, LiCS 2001; Abel/Vezzosi/Winterhalter, ICFP 2017. , modQuantity :: Quantity -- ^ Cardinality / runtime erasure. -- See Conor McBride, I got plenty o' nutting, Wadlerfest 2016. -- See Bob Atkey, Syntax and Semantics of Quantitative Type Theory, LiCS 2018. } deriving (Data, Eq, Ord, Show, Generic) defaultModality :: Modality defaultModality = Modality defaultRelevance defaultQuantity -- | Pointwise composition. instance Semigroup Modality where Modality r q <> Modality r' q' = Modality (r <> r') (q <> q') -- | Pointwise unit. instance Monoid Modality where mempty = Modality mempty mempty mappend = (<>) -- | Dominance ordering. instance PartialOrd Modality where comparable (Modality r q) (Modality r' q') = comparable (r, q) (r', q') instance POSemigroup Modality where instance POMonoid Modality where instance LeftClosedPOMonoid Modality where inverseCompose = inverseComposeModality -- | @m `moreUsableModality` m'@ means that an @m@ can be used -- where ever an @m'@ is required. moreUsableModality :: Modality -> Modality -> Bool moreUsableModality m m' = related m POLE m' usableModality :: LensModality a => a -> Bool usableModality a = usableRelevance m && usableQuantity m where m = getModality a composeModality :: Modality -> Modality -> Modality composeModality = (<>) -- | Compose with modality flag from the left. -- This function is e.g. used to update the modality information -- on pattern variables @a@ after a match against something of modality @q@. applyModality :: LensModality a => Modality -> a -> a applyModality m = mapModality (m `composeModality`) -- | @inverseComposeModality r x@ returns the least modality @y@ -- such that forall @x@, @y@ we have -- @x \`moreUsableModality\` (r \`composeModality\` y)@ -- iff -- @(r \`inverseComposeModality\` x) \`moreUsableModality\` y@ (Galois connection). inverseComposeModality :: Modality -> Modality -> Modality inverseComposeModality (Modality r q) (Modality r' q') = Modality (r `inverseComposeRelevance` r') (q `inverseComposeQuantity` q') -- | Left division by a 'Modality'. -- Used e.g. to modify context when going into a @m@ argument. inverseApplyModality :: LensModality a => Modality -> a -> a inverseApplyModality m = mapModality (m `inverseComposeModality`) -- boilerplate instances instance KillRange Modality where killRange = id instance NFData Modality where -- Lens stuff lModRelevance :: Lens' Relevance Modality lModRelevance f m = f (modRelevance m) <&> \ r -> m { modRelevance = r } lModQuantity :: Lens' Quantity Modality lModQuantity f m = f (modQuantity m) <&> \ q -> m { modQuantity = q } class LensModality a where getModality :: a -> Modality setModality :: Modality -> a -> a setModality = mapModality . const mapModality :: (Modality -> Modality) -> a -> a mapModality f a = setModality (f $ getModality a) a instance LensModality Modality where getModality = id setModality = const mapModality = id instance LensRelevance Modality where getRelevance = modRelevance setRelevance h m = m { modRelevance = h } mapRelevance f m = m { modRelevance = f (modRelevance m) } instance LensQuantity Modality where getQuantity = modQuantity setQuantity h m = m { modQuantity = h } mapQuantity f m = m { modQuantity = f (modQuantity m) } -- default accessors for Relevance getRelevanceMod :: LensModality a => LensGet Relevance a getRelevanceMod = getRelevance . getModality setRelevanceMod :: LensModality a => LensSet Relevance a setRelevanceMod = mapModality . setRelevance mapRelevanceMod :: LensModality a => LensMap Relevance a mapRelevanceMod = mapModality . mapRelevance -- default accessors for Quantity getQuantityMod :: LensModality a => LensGet Quantity a getQuantityMod = getQuantity . getModality setQuantityMod :: LensModality a => LensSet Quantity a setQuantityMod = mapModality . setQuantity mapQuantityMod :: LensModality a => LensMap Quantity a mapQuantityMod = mapModality . mapQuantity --------------------------------------------------------------------------- -- * Quantities --------------------------------------------------------------------------- -- | Quantity for linearity. -- -- A quantity is a set of natural numbers, indicating possible semantic -- uses of a variable. A singleton set @{n}@ requires that the -- corresponding variable is used exactly @n@ times. -- data Quantity = Quantity0 -- ^ Zero uses @{0}@, erased at runtime. | Quantity1 -- ^ Linear use @{1}@ (could be updated destructively). -- Mostly TODO (needs postponable constraints between quantities to compute uses). | Quantityω -- ^ Unrestricted use @ℕ@. deriving (Data, Show, Generic, Eq, Enum, Bounded, Ord) -- @Ord@ instance in case @Quantity@ is used in keys for maps etc. defaultQuantity :: Quantity defaultQuantity = Quantityω -- | Composition of quantities (multiplication). -- -- 'Quantity0' is dominant. -- 'Quantity1' is neutral. -- instance Semigroup Quantity where Quantity1 <> q = q q <> Quantity1 = q Quantity0 <> _ = Quantity0 _ <> Quantity0 = Quantity0 Quantityω <> _ = Quantityω -- _ <> Quantityω = Quantityω -- redundant -- | In the absense of finite quantities besides 0, ω is the unit. -- Otherwise, 1 is the unit. instance Monoid Quantity where mempty = Quantity1 mappend = (<>) -- | Note that the order is @ω ≤ 0,1@, more options is smaller. instance PartialOrd Quantity where comparable = curry $ \case (q, q') | q == q' -> POEQ -- ω is least (Quantityω, _) -> POLT (_, Quantityω) -> POGT -- others are uncomparable _ -> POAny instance POSemigroup Quantity where instance POMonoid Quantity where instance LeftClosedPOMonoid Quantity where inverseCompose = inverseComposeQuantity -- | @m `moreUsableQuantity` m'@ means that an @m@ can be used -- where ever an @m'@ is required. moreQuantity :: Quantity -> Quantity -> Bool moreQuantity m m' = related m POLE m' -- | A thing of quantity 0 is unusable, all others are usable. usableQuantity :: LensQuantity a => a -> Bool usableQuantity a = getQuantity a /= Quantity0 composeQuantity :: Quantity -> Quantity -> Quantity composeQuantity = (<>) -- | Compose with quantity flag from the left. -- This function is e.g. used to update the quantity information -- on pattern variables @a@ after a match against something of quantity @q@. applyQuantity :: LensQuantity a => Quantity -> a -> a applyQuantity q = mapQuantity (q `composeQuantity`) -- | @inverseComposeQuantity r x@ returns the least quantity @y@ -- such that forall @x@, @y@ we have -- @x \`moreQuantity\` (r \`composeQuantity\` y)@ -- iff -- @(r \`inverseComposeQuantity\` x) \`moreQuantity\` y@ (Galois connection). inverseComposeQuantity :: Quantity -> Quantity -> Quantity inverseComposeQuantity q x = case (q, x) of (Quantity1 , x) -> x -- going to linear arg: nothing changes (Quantity0 , x) -> Quantityω -- going to erased arg: every thing usable (Quantityω , Quantityω) -> Quantityω (Quantityω , _) -> Quantity0 -- linear resources are unusable as arguments to unrestricted functions -- | Left division by a 'Quantity'. -- Used e.g. to modify context when going into a @q@ argument. inverseApplyQuantity :: LensQuantity a => Quantity -> a -> a inverseApplyQuantity q = mapQuantity (q `inverseComposeQuantity`) -- boilerplate instances class LensQuantity a where getQuantity :: a -> Quantity setQuantity :: Quantity -> a -> a setQuantity = mapQuantity . const mapQuantity :: (Quantity -> Quantity) -> a -> a mapQuantity f a = setQuantity (f $ getQuantity a) a instance LensQuantity Quantity where getQuantity = id setQuantity = const mapQuantity = id instance KillRange Quantity where killRange = id instance NFData Quantity where rnf Quantity0 = () rnf Quantity1 = () rnf Quantityω = () --------------------------------------------------------------------------- -- * 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. deriving (Data, Show, Eq, Enum, Bounded, Generic) allRelevances :: [Relevance] allRelevances = [minBound..maxBound] defaultRelevance :: Relevance defaultRelevance = Relevant instance KillRange Relevance where killRange rel = rel -- no range to kill instance NFData Relevance where rnf Relevant = () rnf NonStrict = () rnf Irrelevant = () -- | 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 isNonStrict :: LensRelevance a => a -> Bool isNonStrict a = getRelevance a == NonStrict -- | Information ordering. -- @Relevant \`moreRelevant\` -- NonStrict \`moreRelevant\` -- Irrelevant@ moreRelevant :: Relevance -> Relevance -> Bool moreRelevant = (<=) -- | More relevant is smaller. instance Ord Relevance where compare = curry $ \case (r, r') | r == r' -> EQ -- top (_, Irrelevant) -> LT (Irrelevant, _) -> GT -- bottom (Relevant, _) -> LT (_, Relevant) -> GT -- redundant case (NonStrict,NonStrict) -> EQ -- | More relevant is smaller. instance PartialOrd Relevance where comparable = comparableOrd -- | @usableRelevance rel == False@ iff we cannot use a variable of @rel@. usableRelevance :: LensRelevance a => a -> Bool usableRelevance a = case getRelevance a of Irrelevant -> False NonStrict -> False Relevant -> True -- | 'Relevance' composition. -- 'Irrelevant' is dominant, 'Relevant' is neutral. composeRelevance :: Relevance -> Relevance -> Relevance composeRelevance r r' = case (r, r') of (Irrelevant, _) -> Irrelevant (_, Irrelevant) -> Irrelevant (NonStrict, _) -> NonStrict (_, NonStrict) -> NonStrict (Relevant, Relevant) -> Relevant -- | Compose with relevance flag from the left. -- This function is e.g. used to update the relevance information -- on pattern variables @a@ after a match against something @rel@. applyRelevance :: LensRelevance a => Relevance -> a -> a applyRelevance rel = mapRelevance (rel `composeRelevance`) -- | @inverseComposeRelevance r x@ returns the most irrelevant @y@ -- such that forall @x@, @y@ we have -- @x \`moreRelevant\` (r \`composeRelevance\` y)@ -- iff -- @(r \`inverseComposeRelevance\` x) \`moreRelevant\` y@ (Galois connection). inverseComposeRelevance :: Relevance -> Relevance -> Relevance inverseComposeRelevance r x = case (r, x) of (Relevant , x) -> x -- going to relevant arg.: nothing changes -- because Relevant is comp.-neutral (Irrelevant, x) -> Relevant -- going irrelevant: every thing usable (NonStrict , Irrelevant) -> Irrelevant -- otherwise: irrelevant things remain unusable (NonStrict , _) -> Relevant -- but @NonStrict@s become usable -- | Left division by a 'Relevance'. -- Used e.g. to modify context when going into a @rel@ argument. inverseApplyRelevance :: LensRelevance a => Relevance -> a -> a inverseApplyRelevance rel = mapRelevance (rel `inverseComposeRelevance`) -- | 'Relevance' forms a semigroup under composition. instance Semigroup Relevance where (<>) = composeRelevance -- | 'Relevant' is the unit. instance Monoid Relevance where mempty = Relevant mappend = (<>) instance POSemigroup Relevance where instance POMonoid Relevance where instance LeftClosedPOMonoid Relevance where inverseCompose = inverseComposeRelevance -- | Irrelevant function arguments may appear non-strictly in the codomain type. irrToNonStrict :: Relevance -> Relevance irrToNonStrict Irrelevant = NonStrict irrToNonStrict rel = rel -- | Applied when working on types (unless --experimental-irrelevance). nonStrictToRel :: Relevance -> Relevance nonStrictToRel NonStrict = Relevant nonStrictToRel rel = rel nonStrictToIrr :: Relevance -> Relevance nonStrictToIrr NonStrict = Irrelevant nonStrictToIrr rel = rel --------------------------------------------------------------------------- -- * Origin of arguments (user-written, inserted or reflected) --------------------------------------------------------------------------- -- | Origin of arguments. data Origin = UserWritten -- ^ From the source file / user input. (Preserve!) | Inserted -- ^ E.g. inserted hidden arguments. | Reflected -- ^ Produced by the reflection machinery. | CaseSplit -- ^ Produced by an interactive case split. | Substitution -- ^ Named application produced to represent a substitution. E.g. "?0 (x = n)" instead of "?0 n" deriving (Data, Show, Eq, Ord) instance KillRange Origin where killRange = id instance NFData Origin where rnf UserWritten = () rnf Inserted = () rnf Reflected = () rnf CaseSplit = () rnf Substitution = () -- | Decorating something with 'Origin' information. data WithOrigin a = WithOrigin { woOrigin :: !Origin , woThing :: a } deriving (Data, Eq, Ord, Show, Functor, Foldable, Traversable) instance Decoration WithOrigin where traverseF f (WithOrigin h a) = WithOrigin h <$> f a instance HasRange a => HasRange (WithOrigin a) where getRange = getRange . dget instance SetRange a => SetRange (WithOrigin a) where setRange = fmap . setRange instance KillRange a => KillRange (WithOrigin a) where killRange = fmap killRange instance NFData a => NFData (WithOrigin a) where rnf (WithOrigin _ a) = rnf a -- | A lens to access the 'Origin' attribute in data structures. -- Minimal implementation: @getOrigin@ and one of @setOrigin@ or @mapOrigin@. class LensOrigin a where getOrigin :: a -> Origin setOrigin :: Origin -> a -> a setOrigin o = mapOrigin (const o) mapOrigin :: (Origin -> Origin) -> a -> a mapOrigin f a = setOrigin (f $ getOrigin a) a instance LensOrigin Origin where getOrigin = id setOrigin = const mapOrigin = id instance LensOrigin (WithOrigin a) where getOrigin (WithOrigin h _) = h setOrigin h (WithOrigin _ a) = WithOrigin h a mapOrigin f (WithOrigin h a) = WithOrigin (f h) a ----------------------------------------------------------------------------- -- * Free variable annotations ----------------------------------------------------------------------------- data FreeVariables = UnknownFVs | KnownFVs IntSet deriving (Data, Eq, Ord, Show) instance Semigroup FreeVariables where UnknownFVs <> _ = UnknownFVs _ <> UnknownFVs = UnknownFVs KnownFVs vs1 <> KnownFVs vs2 = KnownFVs (IntSet.union vs1 vs2) instance Monoid FreeVariables where mempty = KnownFVs IntSet.empty mappend = (<>) instance NFData FreeVariables where rnf UnknownFVs = () rnf (KnownFVs fv) = rnf fv unknownFreeVariables :: FreeVariables unknownFreeVariables = UnknownFVs noFreeVariables :: FreeVariables noFreeVariables = mempty oneFreeVariable :: Int -> FreeVariables oneFreeVariable = KnownFVs . IntSet.singleton freeVariablesFromList :: [Int] -> FreeVariables freeVariablesFromList = mconcat . map oneFreeVariable -- | A lens to access the 'FreeVariables' attribute in data structures. -- Minimal implementation: @getFreeVariables@ and one of @setFreeVariables@ or @mapFreeVariables@. class LensFreeVariables a where getFreeVariables :: a -> FreeVariables setFreeVariables :: FreeVariables -> a -> a setFreeVariables o = mapFreeVariables (const o) mapFreeVariables :: (FreeVariables -> FreeVariables) -> a -> a mapFreeVariables f a = setFreeVariables (f $ getFreeVariables a) a instance LensFreeVariables FreeVariables where getFreeVariables = id setFreeVariables = const mapFreeVariables = id hasNoFreeVariables :: LensFreeVariables a => a -> Bool hasNoFreeVariables x = case getFreeVariables x of UnknownFVs -> False KnownFVs fv -> IntSet.null fv --------------------------------------------------------------------------- -- * Argument decoration --------------------------------------------------------------------------- -- | A function argument can be hidden and/or irrelevant. data ArgInfo = ArgInfo { argInfoHiding :: Hiding , argInfoModality :: Modality , argInfoOrigin :: Origin , argInfoFreeVariables :: FreeVariables } deriving (Data, Eq, Ord, Show) instance KillRange ArgInfo where killRange i = i -- There are no ranges in ArgInfo's class LensArgInfo a where getArgInfo :: a -> ArgInfo setArgInfo :: ArgInfo -> a -> a setArgInfo ai = mapArgInfo (const ai) mapArgInfo :: (ArgInfo -> ArgInfo) -> a -> a mapArgInfo f a = setArgInfo (f $ getArgInfo a) a instance LensArgInfo ArgInfo where getArgInfo = id setArgInfo = const mapArgInfo = id instance NFData ArgInfo where rnf (ArgInfo a b c d) = rnf a `seq` rnf b `seq` rnf c `seq` rnf d instance LensHiding ArgInfo where getHiding = argInfoHiding setHiding h ai = ai { argInfoHiding = h } mapHiding f ai = ai { argInfoHiding = f (argInfoHiding ai) } instance LensModality ArgInfo where getModality = argInfoModality setModality m ai = ai { argInfoModality = m } mapModality f ai = ai { argInfoModality = f (argInfoModality ai) } instance LensOrigin ArgInfo where getOrigin = argInfoOrigin setOrigin o ai = ai { argInfoOrigin = o } mapOrigin f ai = ai { argInfoOrigin = f (argInfoOrigin ai) } instance LensFreeVariables ArgInfo where getFreeVariables = argInfoFreeVariables setFreeVariables o ai = ai { argInfoFreeVariables = o } mapFreeVariables f ai = ai { argInfoFreeVariables = f (argInfoFreeVariables ai) } -- inherited instances instance LensRelevance ArgInfo where getRelevance = getRelevanceMod setRelevance = setRelevanceMod mapRelevance = mapRelevanceMod instance LensQuantity ArgInfo where getQuantity = getQuantityMod setQuantity = setQuantityMod mapQuantity = mapQuantityMod defaultArgInfo :: ArgInfo defaultArgInfo = ArgInfo { argInfoHiding = NotHidden , argInfoModality = defaultModality , argInfoOrigin = UserWritten , argInfoFreeVariables = UnknownFVs } -- Accessing through ArgInfo -- default accessors for Hiding getHidingArgInfo :: LensArgInfo a => LensGet Hiding a getHidingArgInfo = getHiding . getArgInfo setHidingArgInfo :: LensArgInfo a => LensSet Hiding a setHidingArgInfo = mapArgInfo . setHiding mapHidingArgInfo :: LensArgInfo a => LensMap Hiding a mapHidingArgInfo = mapArgInfo . mapHiding -- default accessors for Modality getModalityArgInfo :: LensArgInfo a => LensGet Modality a getModalityArgInfo = getModality . getArgInfo setModalityArgInfo :: LensArgInfo a => LensSet Modality a setModalityArgInfo = mapArgInfo . setModality mapModalityArgInfo :: LensArgInfo a => LensMap Modality a mapModalityArgInfo = mapArgInfo . mapModality -- default accessors for Origin getOriginArgInfo :: LensArgInfo a => LensGet Origin a getOriginArgInfo = getOrigin . getArgInfo setOriginArgInfo :: LensArgInfo a => LensSet Origin a setOriginArgInfo = mapArgInfo . setOrigin mapOriginArgInfo :: LensArgInfo a => LensMap Origin a mapOriginArgInfo = mapArgInfo . mapOrigin -- default accessors for FreeVariables getFreeVariablesArgInfo :: LensArgInfo a => LensGet FreeVariables a getFreeVariablesArgInfo = getFreeVariables . getArgInfo setFreeVariablesArgInfo :: LensArgInfo a => LensSet FreeVariables a setFreeVariablesArgInfo = mapArgInfo . setFreeVariables mapFreeVariablesArgInfo :: LensArgInfo a => LensMap FreeVariables a mapFreeVariablesArgInfo = mapArgInfo . mapFreeVariables --------------------------------------------------------------------------- -- * Arguments --------------------------------------------------------------------------- data Arg e = Arg { argInfo :: ArgInfo , unArg :: e } deriving (Data, Ord, Show, Functor, Foldable, Traversable) instance Decoration Arg where traverseF f (Arg ai a) = Arg ai <$> f a instance HasRange a => HasRange (Arg a) where getRange = getRange . unArg instance SetRange a => SetRange (Arg a) where setRange r = fmap $ setRange r instance KillRange a => KillRange (Arg a) where killRange (Arg info a) = killRange2 Arg info a -- | Ignores 'Quantity', 'Relevance', 'Origin', and 'FreeVariables'. -- Ignores content of argument if 'Irrelevant'. -- instance Eq a => Eq (Arg a) where Arg (ArgInfo h1 m1 _ _) x1 == Arg (ArgInfo h2 m2 _ _) x2 = h1 == h2 && (isIrrelevant m1 || isIrrelevant m2 || x1 == x2) -- Andreas, 2017-10-04, issue #2775, ignore irrelevant arguments during with-abstraction. -- This is a hack, we should not use '(==)' in with-abstraction -- and more generally not use it on Syntax. -- Andrea: except for caching. -- instance Show a => Show (Arg a) where -- show (Arg (ArgInfo h (Modality r q) o fv) a) = showFVs fv $ showQ q $ showR r $ showO o $ showH h $ show a -- where -- showH Hidden s = "{" ++ s ++ "}" -- showH NotHidden s = "(" ++ s ++ ")" -- showH (Instance o) s = showOv o ++ "{{" ++ s ++ "}}" -- where showOv YesOverlap = "overlap " -- showOv NoOverlap = "" -- showR r s = case r of -- Irrelevant -> "." ++ s -- NonStrict -> "?" ++ s -- Relevant -> "r" ++ s -- Andreas: I want to see it explicitly -- showQ q s = case q of -- Quantity0 -> "0" ++ s -- Quantity1 -> "1" ++ s -- Quantityω -> "ω" ++ s -- showO o s = case o of -- UserWritten -> "u" ++ s -- Inserted -> "i" ++ s -- Reflected -> "g" ++ s -- generated by reflection -- CaseSplit -> "c" ++ s -- generated by case split -- Substitution -> "s" ++ s -- showFVs UnknownFVs s = s -- showFVs (KnownFVs fv) s = "fv" ++ show (IntSet.toList fv) ++ s -- -- defined in Concrete.Pretty -- instance Pretty a => Pretty (Arg a) where -- pretty (Arg (ArgInfo h (Modality r q) o fv) a) = prettyFVs fv $ prettyQ q $ prettyR r $ prettyO o $ prettyH h $ pretty a -- where -- prettyH Hidden s = "{" <> s <> "}" -- prettyH NotHidden s = "(" <> s <> ")" -- prettyH (Instance o) s = prettyOv o <> "{{" <> s <> "}}" -- where prettyOv YesOverlap = "overlap " -- prettyOv NoOverlap = "" -- prettyR r s = case r of -- Irrelevant -> "." <> s -- NonStrict -> "?" <> s -- Relevant -> "r" <> s -- Andreas: I want to see it explicitly -- prettyQ q s = case q of -- Quantity0 -> "0" <> s -- Quantity1 -> "1" <> s -- Quantityω -> "ω" <> s -- prettyO o s = case o of -- UserWritten -> "u" <> s -- Inserted -> "i" <> s -- Reflected -> "g" <> s -- generated by reflection -- CaseSplit -> "c" <> s -- generated by case split -- Substitution -> "s" <> s -- prettyFVs UnknownFVs s = s -- prettyFVs (KnownFVs fv) s = "fv" <> pretty (IntSet.toList fv) <> s instance NFData e => NFData (Arg e) where rnf (Arg a b) = rnf a `seq` rnf b instance LensArgInfo (Arg a) where getArgInfo = argInfo setArgInfo ai arg = arg { argInfo = ai } mapArgInfo f arg = arg { argInfo = f $ argInfo arg } -- The other lenses are defined through LensArgInfo instance LensHiding (Arg e) where getHiding = getHidingArgInfo setHiding = setHidingArgInfo mapHiding = mapHidingArgInfo instance LensModality (Arg e) where getModality = getModalityArgInfo setModality = setModalityArgInfo mapModality = mapModalityArgInfo instance LensOrigin (Arg e) where getOrigin = getOriginArgInfo setOrigin = setOriginArgInfo mapOrigin = mapOriginArgInfo instance LensFreeVariables (Arg e) where getFreeVariables = getFreeVariablesArgInfo setFreeVariables = setFreeVariablesArgInfo mapFreeVariables = mapFreeVariablesArgInfo -- Since we have LensModality, we get relevance and quantity by default instance LensRelevance (Arg e) where getRelevance = getRelevanceMod setRelevance = setRelevanceMod mapRelevance = mapRelevanceMod instance LensQuantity (Arg e) where getQuantity = getQuantityMod setQuantity = setQuantityMod mapQuantity = mapQuantityMod defaultArg :: a -> Arg a defaultArg = Arg defaultArgInfo -- | @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 b] -> [Arg a] xs `withArgsFrom` args = zipWith (\x arg -> fmap (const x) arg) xs args withNamedArgsFrom :: [a] -> [NamedArg b] -> [NamedArg 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. -- -- [ cubical ] When @domFinite = True@ for the domain of a 'Pi' -- type, the elements should be compared by tabulating the domain type. -- Only supported in case the domain type is primIsOne, to obtain -- the correct equality for partial elements. data Dom e = Dom { domInfo :: ArgInfo , domFinite :: !Bool , domName :: Maybe RString , unDom :: e } deriving (Data, Ord, Show, Functor, Foldable, Traversable) instance Decoration Dom where traverseF f (Dom ai b x a) = Dom ai b x <$> f a instance HasRange a => HasRange (Dom a) where getRange = getRange . unDom instance KillRange a => KillRange (Dom a) where killRange (Dom info b x a) = killRange4 Dom info b x a -- | Ignores 'Origin' and 'FreeVariables'. instance Eq a => Eq (Dom a) where Dom (ArgInfo h1 m1 _ _) b1 s1 x1 == Dom (ArgInfo h2 m2 _ _) b2 s2 x2 = (h1, m1, b1, s1, x1) == (h2, m2, b2, s2, x2) -- instance Show a => Show (Dom a) where -- show = show . argFromDom instance LensArgInfo (Dom e) where getArgInfo = domInfo setArgInfo ai dom = dom { domInfo = ai } mapArgInfo f dom = dom { domInfo = f $ domInfo dom } -- The other lenses are defined through LensArgInfo instance LensHiding (Dom e) where getHiding = getHidingArgInfo setHiding = setHidingArgInfo mapHiding = mapHidingArgInfo instance LensModality (Dom e) where getModality = getModalityArgInfo setModality = setModalityArgInfo mapModality = mapModalityArgInfo instance LensOrigin (Dom e) where getOrigin = getOriginArgInfo setOrigin = setOriginArgInfo mapOrigin = mapOriginArgInfo instance LensFreeVariables (Dom e) where getFreeVariables = getFreeVariablesArgInfo setFreeVariables = setFreeVariablesArgInfo mapFreeVariables = mapFreeVariablesArgInfo -- Since we have LensModality, we get relevance and quantity by default instance LensRelevance (Dom e) where getRelevance = getRelevanceMod setRelevance = setRelevanceMod mapRelevance = mapRelevanceMod instance LensQuantity (Dom e) where getQuantity = getQuantityMod setQuantity = setQuantityMod mapQuantity = mapQuantityMod argFromDom :: Dom a -> Arg a argFromDom (Dom i _ _ a) = Arg i a namedArgFromDom :: Dom a -> NamedArg a namedArgFromDom (Dom i _ s a) = Arg i $ Named s a domFromArg :: Arg a -> Dom a domFromArg (Arg i a) = Dom i False Nothing a domFromNamedArg :: NamedArg a -> Dom a domFromNamedArg (Arg i a) = Dom i False (nameOf a) (namedThing a) defaultDom :: a -> Dom a defaultDom = defaultArgDom defaultArgInfo defaultArgDom :: ArgInfo -> a -> Dom a defaultArgDom info x = Dom info False Nothing x defaultNamedArgDom :: ArgInfo -> String -> a -> Dom a defaultNamedArgDom info s = Dom info False (Just $ unranged s) --------------------------------------------------------------------------- -- * Named arguments --------------------------------------------------------------------------- -- | Something potentially carrying a name. data Named name a = Named { nameOf :: Maybe name , namedThing :: a } deriving (Eq, Ord, Show, Data, 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 -- | Accessor/editor for the 'nameOf' component. class LensNamed name a | a -> name where lensNamed :: Lens' (Maybe name) a instance LensNamed name (Named name a) where lensNamed f (Named mn a) = f mn <&> \ mn' -> Named mn' a getNameOf :: LensNamed name a => a -> Maybe name getNameOf a = a ^. lensNamed setNameOf :: LensNamed name a => Maybe name -> a -> a setNameOf = set lensNamed mapNameOf :: LensNamed name a => (Maybe name -> Maybe name) -> a -> a mapNameOf = over lensNamed -- Lenses lift through decorations: -- instance (Decoration f, LensNamed name a) => LensNamed name (f a) where instance LensNamed name a => LensNamed name (Arg a) where lensNamed = traverseF . lensNamed -- Standard instances for 'Named': 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 SetRange a => SetRange (Named name a) where setRange r = fmap $ setRange r instance (KillRange name, KillRange a) => KillRange (Named name a) where killRange (Named n a) = Named (killRange n) (killRange a) -- instance Show a => Show (Named_ a) where -- show (Named Nothing a) = show a -- show (Named (Just n) a) = rawNameToString (rangedThing n) ++ " = " ++ show a -- -- Defined in Concrete.Pretty -- instance Pretty a => Pretty (Named_ a) where -- pretty (Named Nothing a) = pretty a -- pretty (Named (Just n) a) = text (rawNameToString (rangedThing n)) <+> "=" <+> pretty a instance (NFData name, NFData a) => NFData (Named name a) where rnf (Named a b) = rnf a `seq` rnf b -- | Only 'Hidden' arguments can have names. type NamedArg a = Arg (Named_ a) -- | Get the content of a 'NamedArg'. namedArg :: NamedArg a -> a namedArg = namedThing . unArg defaultNamedArg :: a -> NamedArg a defaultNamedArg = unnamedArg defaultArgInfo unnamedArg :: ArgInfo -> a -> NamedArg a unnamedArg info = Arg info . unnamed -- | The functor instance for 'NamedArg' would be ambiguous, -- so we give it another name here. updateNamedArg :: (a -> b) -> NamedArg a -> NamedArg b updateNamedArg = fmap . fmap -- | @setNamedArg a b = updateNamedArg (const b) a@ setNamedArg :: NamedArg a -> b -> NamedArg b setNamedArg a b = (b <$) <$> a --------------------------------------------------------------------------- -- * Range decoration. --------------------------------------------------------------------------- -- | Thing with range info. data Ranged a = Ranged { rangeOf :: Range , rangedThing :: a } deriving (Data, Show, Functor, Foldable, Traversable) -- | Thing with no range info. unranged :: a -> Ranged a unranged = Ranged noRange instance Pretty a => Pretty (Ranged a) where pretty = pretty . rangedThing -- 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 -- | Ranges are not forced. instance NFData a => NFData (Ranged a) where rnf (Ranged _ a) = rnf a --------------------------------------------------------------------------- -- * 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 --------------------------------------------------------------------------- -- * Further constructor and projection info --------------------------------------------------------------------------- -- | Where does the 'ConP' or 'Con' come from? data ConOrigin = ConOSystem -- ^ Inserted by system or expanded from an implicit pattern. | ConOCon -- ^ User wrote a constructor (pattern). | ConORec -- ^ User wrote a record (pattern). | ConOSplit -- ^ Generated by interactive case splitting. deriving (Data, Show, Eq, Ord, Enum, Bounded) instance KillRange ConOrigin where killRange = id -- | Prefer user-written over system-inserted. bestConInfo :: ConOrigin -> ConOrigin -> ConOrigin bestConInfo ConOSystem o = o bestConInfo o _ = o -- | Where does a projection come from? data ProjOrigin = ProjPrefix -- ^ User wrote a prefix projection. | ProjPostfix -- ^ User wrote a postfix projection. | ProjSystem -- ^ Projection was generated by the system. deriving (Data, Show, Eq, Ord, Enum, Bounded) instance KillRange ProjOrigin where killRange = id data DataOrRecord = IsData | IsRecord deriving (Data, Eq, Ord, Show) --------------------------------------------------------------------------- -- * Infixity, access, abstract, etc. --------------------------------------------------------------------------- -- | Functions can be defined in both infix and prefix style. See -- 'Agda.Syntax.Concrete.LHS'. data IsInfix = InfixDef | PrefixDef deriving (Data, Show, Eq, Ord) -- | Access modifier. data Access = PrivateAccess Origin -- ^ Store the 'Origin' of the private block that lead to this qualifier. -- This is needed for more faithful printing of declarations. | PublicAccess | OnlyQualified -- ^ Visible from outside, but not exported when opening the module -- Used for qualified constructors. deriving (Data, Show, Eq, Ord) instance Pretty Access where pretty = text . \case PrivateAccess _ -> "private" PublicAccess -> "public" OnlyQualified -> "only-qualified" instance NFData Access where rnf _ = () instance HasRange Access where getRange _ = noRange instance KillRange Access where killRange = id -- | Abstract or concrete data IsAbstract = AbstractDef | ConcreteDef deriving (Data, Show, Eq, Ord) instance KillRange IsAbstract where killRange = id -- | Is this definition eligible for instance search? data IsInstance = InstanceDef | NotInstanceDef deriving (Data, Show, Eq, Ord) instance KillRange IsInstance where killRange = id instance HasRange IsInstance where getRange _ = noRange instance NFData IsInstance where rnf InstanceDef = () rnf NotInstanceDef = () -- | Is this a macro definition? data IsMacro = MacroDef | NotMacroDef deriving (Data, Show, Eq, Ord) instance KillRange IsMacro where killRange = id instance HasRange IsMacro where getRange _ = noRange type Nat = Int type Arity = Nat --------------------------------------------------------------------------- -- * NameId --------------------------------------------------------------------------- -- | The unique identifier of a name. Second argument is the top-level module -- identifier. data NameId = NameId {-# UNPACK #-} !Word64 {-# UNPACK #-} !Word64 deriving (Eq, Ord, Data, Generic, Show) instance KillRange NameId where killRange = id instance Pretty NameId where pretty (NameId n m) = text $ show n ++ "@" ++ show m 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 NFData NameId where rnf (NameId _ _) = () instance Hashable NameId where {-# INLINE hashWithSalt #-} hashWithSalt salt (NameId n m) = hashWithSalt salt (n, m) --------------------------------------------------------------------------- -- * Meta variables --------------------------------------------------------------------------- -- | A meta variable identifier is just a natural number. -- newtype MetaId = MetaId { metaId :: Nat } deriving (Eq, Ord, Num, Real, Enum, Integral, Data) instance Pretty MetaId where pretty (MetaId n) = text $ "_" ++ show n -- | Show non-record version of this newtype. instance Show MetaId where showsPrec p (MetaId n) = showParen (p > 0) $ showString "MetaId " . shows n instance NFData MetaId where rnf (MetaId x) = rnf x newtype Constr a = Constr a ------------------------------------------------------------------------ -- * Placeholders (used to parse sections) ------------------------------------------------------------------------ -- | The position of a name part or underscore in a name. data PositionInName = Beginning -- ^ The following underscore is at the beginning of the name: -- @_foo@. | Middle -- ^ The following underscore is in the middle of the name: -- @foo_bar@. | End -- ^ The following underscore is at the end of the name: @foo_@. deriving (Show, Eq, Ord, Data) -- | Placeholders are used to represent the underscores in a section. data MaybePlaceholder e = Placeholder !PositionInName | NoPlaceholder !(Strict.Maybe PositionInName) e -- ^ The second argument is used only (but not always) for name -- parts other than underscores. deriving (Data, Eq, Ord, Functor, Foldable, Traversable, Show) -- | An abbreviation: @noPlaceholder = 'NoPlaceholder' -- 'Strict.Nothing'@. noPlaceholder :: e -> MaybePlaceholder e noPlaceholder = NoPlaceholder Strict.Nothing instance HasRange a => HasRange (MaybePlaceholder a) where getRange Placeholder{} = noRange getRange (NoPlaceholder _ e) = getRange e instance KillRange a => KillRange (MaybePlaceholder a) where killRange p@Placeholder{} = p killRange (NoPlaceholder p e) = killRange1 (NoPlaceholder p) e instance NFData a => NFData (MaybePlaceholder a) where rnf (Placeholder _) = () rnf (NoPlaceholder _ a) = rnf a --------------------------------------------------------------------------- -- * Interaction meta variables --------------------------------------------------------------------------- newtype InteractionId = InteractionId { interactionId :: Nat } deriving ( Eq , Ord , Show , Num , Integral , Real , Enum , Data ) instance Pretty InteractionId where pretty (InteractionId i) = text $ "?" ++ show i instance KillRange InteractionId where killRange = id ----------------------------------------------------------------------------- -- * Import directive ----------------------------------------------------------------------------- -- | The things you are allowed to say when you shuffle names between name -- spaces (i.e. in @import@, @namespace@, or @open@ declarations). data ImportDirective' n m = ImportDirective { importDirRange :: Range , using :: Using' n m , hiding :: [ImportedName' n m] , impRenaming :: [Renaming' n m] , publicOpen :: Bool -- ^ Only for @open@. Exports the opened names from the current module. } deriving (Data, Eq) data Using' n m = UseEverything | Using [ImportedName' n m] deriving (Data, Eq) instance Semigroup (Using' n m) where UseEverything <> u = u u <> UseEverything = u Using xs <> Using ys = Using (xs ++ ys) instance Monoid (Using' n m) where mempty = UseEverything mappend = (<>) -- | Default is directive is @private@ (use everything, but do not export). defaultImportDir :: ImportDirective' n m defaultImportDir = ImportDirective noRange UseEverything [] [] False isDefaultImportDir :: ImportDirective' n m -> Bool isDefaultImportDir (ImportDirective _ UseEverything [] [] False) = True isDefaultImportDir _ = False -- | An imported name can be a module or a defined name. data ImportedName' n m = ImportedModule m -- ^ Imported module name of type @m@. | ImportedName n -- ^ Imported name of type @n@. deriving (Data, Eq, Ord, Show) setImportedName :: ImportedName' a a -> a -> ImportedName' a a setImportedName (ImportedName x) y = ImportedName y setImportedName (ImportedModule x) y = ImportedModule y -- -- Defined in Concrete.Pretty -- instance (Pretty n, Pretty m) => Pretty (ImportedName' n m) where -- pretty (ImportedModule x) = "module" <+> pretty x -- pretty (ImportedName x) = pretty x -- instance (Show n, Show m) => Show (ImportedName' n m) where -- show (ImportedModule x) = "module " ++ show x -- show (ImportedName x) = show x data Renaming' n m = Renaming { renFrom :: ImportedName' n m -- ^ Rename from this name. , renTo :: ImportedName' n m -- ^ To this one. Must be same kind as 'renFrom'. , renToRange :: Range -- ^ The range of the \"to\" keyword. Retained for highlighting purposes. } deriving (Data, Eq) -- ** HasRange instances instance (HasRange a, HasRange b) => HasRange (ImportDirective' a b) where getRange = importDirRange instance (HasRange a, HasRange b) => HasRange (Using' a b) where getRange (Using xs) = getRange xs getRange UseEverything = noRange instance (HasRange a, HasRange b) => HasRange (Renaming' a b) where getRange r = getRange (renFrom r, renTo r) instance (HasRange a, HasRange b) => HasRange (ImportedName' a b) where getRange (ImportedName x) = getRange x getRange (ImportedModule x) = getRange x -- ** KillRange instances instance (KillRange a, KillRange b) => KillRange (ImportDirective' a b) where killRange (ImportDirective _ u h r p) = killRange3 (\u h r -> ImportDirective noRange u h r p) u h r instance (KillRange a, KillRange b) => KillRange (Using' a b) where killRange (Using i) = killRange1 Using i killRange UseEverything = UseEverything instance (KillRange a, KillRange b) => KillRange (Renaming' a b) where killRange (Renaming i n _) = killRange2 (\i n -> Renaming i n noRange) i n instance (KillRange a, KillRange b) => KillRange (ImportedName' a b) where killRange (ImportedModule n) = killRange1 ImportedModule n killRange (ImportedName n) = killRange1 ImportedName n -- ** NFData instances -- | Ranges are not forced. instance (NFData a, NFData b) => NFData (ImportDirective' a b) where rnf (ImportDirective _ a b c _) = rnf a `seq` rnf b `seq` rnf c instance (NFData a, NFData b) => NFData (Using' a b) where rnf UseEverything = () rnf (Using a) = rnf a -- | Ranges are not forced. instance (NFData a, NFData b) => NFData (Renaming' a b) where rnf (Renaming a b _) = rnf a `seq` rnf b instance (NFData a, NFData b) => NFData (ImportedName' a b) where rnf (ImportedModule a) = rnf a rnf (ImportedName a) = rnf a ----------------------------------------------------------------------------- -- * Termination ----------------------------------------------------------------------------- -- | Termination check? (Default = TerminationCheck). 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 (Data, Show, Eq, Functor) instance KillRange m => KillRange (TerminationCheck m) where killRange (TerminationMeasure _ m) = TerminationMeasure noRange (killRange m) killRange t = t instance NFData a => NFData (TerminationCheck a) where rnf TerminationCheck = () rnf NoTerminationCheck = () rnf NonTerminating = () rnf Terminating = () rnf (TerminationMeasure _ a) = rnf a ----------------------------------------------------------------------------- -- * Positivity ----------------------------------------------------------------------------- -- | Positivity check? (Default = True). type PositivityCheck = Bool ----------------------------------------------------------------------------- -- * Universe checking ----------------------------------------------------------------------------- -- | Universe check? (Default is yes). data UniverseCheck = YesUniverseCheck | NoUniverseCheck deriving (Eq, Ord, Show, Bounded, Enum, Data) instance KillRange UniverseCheck where killRange = id