1{-| Names in the concrete syntax are just strings (or lists of strings for 2 qualified names). 3-} 4module Agda.Syntax.Concrete.Name where 5 6import Control.DeepSeq 7 8import Data.ByteString.Char8 (ByteString) 9import Data.Function 10import qualified Data.Foldable as Fold 11import qualified Data.List as List 12import Data.Data (Data) 13 14import GHC.Generics (Generic) 15 16import System.FilePath 17 18import Agda.Syntax.Common 19import Agda.Syntax.Concrete.Glyph 20import Agda.Syntax.Position 21 22import Agda.Utils.FileName 23import Agda.Utils.Lens 24import Agda.Utils.List (last1) 25import Agda.Utils.List1 (List1, pattern (:|), (<|)) 26import qualified Agda.Utils.List1 as List1 27import Agda.Utils.Pretty 28import Agda.Utils.Singleton 29import Agda.Utils.Size 30import Agda.Utils.Suffix 31 32import Agda.Utils.Impossible 33 34{-| A name is a non-empty list of alternating 'Id's and 'Hole's. A normal name 35 is represented by a singleton list, and operators are represented by a list 36 with 'Hole's where the arguments should go. For instance: @[Hole,Id "+",Hole]@ 37 is infix addition. 38 39 Equality and ordering on @Name@s are defined to ignore range so same names 40 in different locations are equal. 41-} 42data Name 43 = Name -- ^ A (mixfix) identifier. 44 { nameRange :: Range 45 , nameInScope :: NameInScope 46 , nameNameParts :: NameParts 47 } 48 | NoName -- ^ @_@. 49 { nameRange :: Range 50 , nameId :: NameId 51 } 52 deriving Data 53 54type NameParts = List1 NamePart 55 56-- | An open mixfix identifier is either prefix, infix, or suffix. 57-- That is to say: at least one of its extremities is a @Hole@ 58 59isOpenMixfix :: Name -> Bool 60isOpenMixfix = \case 61 Name _ _ (x :| x' : xs) -> x == Hole || last1 x' xs == Hole 62 _ -> False 63 64instance Underscore Name where 65 underscore = NoName noRange __IMPOSSIBLE__ 66 isUnderscore NoName{} = True 67 isUnderscore (Name {nameNameParts = Id x :| []}) = isUnderscore x 68 isUnderscore _ = False 69 70-- | Mixfix identifiers are composed of words and holes, 71-- e.g. @_+_@ or @if_then_else_@ or @[_/_]@. 72data NamePart 73 = Hole -- ^ @_@ part. 74 | Id RawName -- ^ Identifier part. 75 deriving (Data, Generic) 76 77-- | Define equality on @Name@ to ignore range so same names in different 78-- locations are equal. 79-- 80-- Is there a reason not to do this? -Jeff 81-- 82-- No. But there are tons of reasons to do it. For instance, when using 83-- names as keys in maps you really don't want to have to get the range 84-- right to be able to do a lookup. -Ulf 85 86instance Eq Name where 87 Name _ _ xs == Name _ _ ys = xs == ys 88 NoName _ i == NoName _ j = i == j 89 _ == _ = False 90 91instance Ord Name where 92 compare (Name _ _ xs) (Name _ _ ys) = compare xs ys 93 compare (NoName _ i) (NoName _ j) = compare i j 94 compare (NoName {}) (Name {}) = LT 95 compare (Name {}) (NoName {}) = GT 96 97instance Eq NamePart where 98 Hole == Hole = True 99 Id s1 == Id s2 = s1 == s2 100 _ == _ = False 101 102instance Ord NamePart where 103 compare Hole Hole = EQ 104 compare Hole (Id {}) = LT 105 compare (Id {}) Hole = GT 106 compare (Id s1) (Id s2) = compare s1 s2 107 108-- | @QName@ is a list of namespaces and the name of the constant. 109-- For the moment assumes namespaces are just @Name@s and not 110-- explicitly applied modules. 111-- Also assumes namespaces are generative by just using derived 112-- equality. We will have to define an equality instance to 113-- non-generative namespaces (as well as having some sort of 114-- lookup table for namespace names). 115data QName 116 = Qual Name QName -- ^ @A.rest@. 117 | QName Name -- ^ @x@. 118 deriving (Data, Eq, Ord) 119 120instance Underscore QName where 121 underscore = QName underscore 122 isUnderscore (QName x) = isUnderscore x 123 isUnderscore Qual{} = False 124 125-- | Top-level module names. Used in connection with the file system. 126-- 127-- Invariant: The list must not be empty. 128 129data TopLevelModuleName = TopLevelModuleName 130 { moduleNameRange :: Range 131 , moduleNameParts :: List1 String 132 } 133 deriving (Show, Data, Generic) 134 135instance Eq TopLevelModuleName where (==) = (==) `on` moduleNameParts 136instance Ord TopLevelModuleName where compare = compare `on` moduleNameParts 137instance Sized TopLevelModuleName where size = size . moduleNameParts 138 139------------------------------------------------------------------------ 140-- * Constructing simple 'Name's. 141------------------------------------------------------------------------ 142 143-- | Create an ordinary 'InScope' name. 144simpleName :: RawName -> Name 145simpleName = Name noRange InScope . singleton . Id 146 147-- | Create a binary operator name in scope. 148simpleBinaryOperator :: RawName -> Name 149simpleBinaryOperator s = Name noRange InScope $ Hole :| Id s : Hole : [] 150 151-- | Create an ordinary 'InScope' name containing a single 'Hole'. 152simpleHole :: Name 153simpleHole = Name noRange InScope $ singleton Hole 154 155------------------------------------------------------------------------ 156-- * Operations on 'Name' and 'NamePart' 157------------------------------------------------------------------------ 158 159-- | Don't use on 'NoName{}'. 160lensNameParts :: Lens' NameParts Name 161lensNameParts f = \case 162 n@Name{} -> f (nameNameParts n) <&> \ ps -> n { nameNameParts = ps } 163 NoName{} -> __IMPOSSIBLE__ 164 165nameToRawName :: Name -> RawName 166nameToRawName = prettyShow 167 168nameParts :: Name -> NameParts 169nameParts (Name _ _ ps) = ps 170nameParts (NoName _ _) = singleton $ Id "_" -- To not return an empty list 171 172nameStringParts :: Name -> [RawName] 173nameStringParts n = [ s | Id s <- List1.toList $ nameParts n ] 174 175-- | Parse a string to parts of a concrete name. 176-- 177-- Note: @stringNameParts "_" == [Id "_"] == nameParts NoName{}@ 178 179stringNameParts :: String -> NameParts 180stringNameParts "" = singleton $ Id "_" -- NoName 181stringNameParts "_" = singleton $ Id "_" -- NoName 182stringNameParts s = List1.fromList $ loop s 183 where 184 loop "" = [] 185 loop ('_':s) = Hole : loop s 186 loop s | (x, s') <- break (== '_') s = Id (stringToRawName x) : loop s' 187 188-- | Number of holes in a 'Name' (i.e., arity of a mixfix-operator). 189class NumHoles a where 190 numHoles :: a -> Int 191 192instance NumHoles NameParts where 193 numHoles = length . List1.filter (== Hole) 194 195instance NumHoles Name where 196 numHoles NoName{} = 0 197 numHoles (Name { nameNameParts = parts }) = numHoles parts 198 199instance NumHoles QName where 200 numHoles (QName x) = numHoles x 201 numHoles (Qual _ x) = numHoles x 202 203-- | Is the name an operator? 204-- Needs at least 2 'NamePart's. 205isOperator :: Name -> Bool 206isOperator = \case 207 Name _ _ (_ :| _ : _) -> True 208 _ -> False 209 210isHole :: NamePart -> Bool 211isHole Hole = True 212isHole _ = False 213 214isPrefix, isPostfix, isInfix, isNonfix :: Name -> Bool 215isPrefix x = not (isHole (List1.head xs)) && isHole (List1.last xs) where xs = nameParts x 216isPostfix x = isHole (List1.head xs) && not (isHole (List1.last xs)) where xs = nameParts x 217isInfix x = isHole (List1.head xs) && isHole (List1.last xs) where xs = nameParts x 218isNonfix x = not (isHole (List1.head xs)) && not (isHole (List1.last xs)) where xs = nameParts x 219 220 221------------------------------------------------------------------------ 222-- * Keeping track of which names are (not) in scope 223------------------------------------------------------------------------ 224 225data NameInScope = InScope | NotInScope 226 deriving (Eq, Show, Data) 227 228class LensInScope a where 229 lensInScope :: Lens' NameInScope a 230 231 isInScope :: a -> NameInScope 232 isInScope x = x ^. lensInScope 233 234 mapInScope :: (NameInScope -> NameInScope) -> a -> a 235 mapInScope = over lensInScope 236 237 setInScope :: a -> a 238 setInScope = mapInScope $ const InScope 239 240 setNotInScope :: a -> a 241 setNotInScope = mapInScope $ const NotInScope 242 243instance LensInScope NameInScope where 244 lensInScope = id 245 246instance LensInScope Name where 247 lensInScope f = \case 248 n@Name{ nameInScope = nis } -> (\nis' -> n { nameInScope = nis' }) <$> f nis 249 n@NoName{} -> n <$ f InScope 250 251instance LensInScope QName where 252 lensInScope f = \case 253 Qual x xs -> (`Qual` xs) <$> lensInScope f x 254 QName x -> QName <$> lensInScope f x 255 256------------------------------------------------------------------------ 257-- * Generating fresh names 258------------------------------------------------------------------------ 259 260-- | Method by which to generate fresh unshadowed names. 261data FreshNameMode 262 = UnicodeSubscript 263 -- ^ Append an integer Unicode subscript: x, x₁, x₂, … 264 | AsciiCounter 265 -- ^ Append an integer ASCII counter: x, x1, x2, … 266 267 -- Note that @Agda.Utils.Suffix@ supports an additional style, @Prime@, but 268 -- we currently only encounter it when extending an existing name of that 269 -- format, (x', x'', …), not for an initially-generated permutation. There's 270 -- no reason we couldn't, except that we currently choose between 271 -- subscript/counter styles based on the --no-unicode mode rather than any 272 -- finer-grained option. 273 -- | PrimeTickCount 274 -- ^ Append an ASCII prime/apostrophe: x, x', x'', … 275 276nextRawName :: FreshNameMode -> RawName -> RawName 277nextRawName freshNameMode s = addSuffix root (maybe initialSuffix nextSuffix suffix) 278 where 279 (root, suffix) = suffixView s 280 initialSuffix = case freshNameMode of 281 UnicodeSubscript -> Subscript 1 282 AsciiCounter -> Index 1 283 284-- | Get the next version of the concrete name. For instance, 285-- @nextName "x" = "x₁"@. The name must not be a 'NoName'. 286nextName :: FreshNameMode -> Name -> Name 287nextName freshNameMode x@Name{} = setNotInScope $ over (lensNameParts . lastIdPart) (nextRawName freshNameMode) x 288nextName _ NoName{} = __IMPOSSIBLE__ 289 290-- | Zoom on the last non-hole in a name. 291lastIdPart :: Lens' RawName NameParts 292lastIdPart f = loop 293 where 294 loop = \case 295 Id s :| [] -> f s <&> \ s -> Id s :| [] 296 Id s :| [Hole] -> f s <&> \ s -> Id s :| [Hole] 297 p1 :| p2 : ps -> (p1 <|) <$> loop (p2 :| ps) 298 Hole :| [] -> __IMPOSSIBLE__ 299 300-- | Get the first version of the concrete name that does not satisfy 301-- the given predicate. 302firstNonTakenName :: FreshNameMode -> (Name -> Bool) -> Name -> Name 303firstNonTakenName freshNameMode taken x = 304 if taken x 305 then firstNonTakenName freshNameMode taken (nextName freshNameMode x) 306 else x 307 308-- | Lens for accessing and modifying the suffix of a name. 309-- The suffix of a @NoName@ is always @Nothing@, and should not be 310-- changed. 311nameSuffix :: Lens' (Maybe Suffix) Name 312nameSuffix (f :: Maybe Suffix -> f (Maybe Suffix)) = \case 313 314 n@NoName{} -> f Nothing <&> \case 315 Nothing -> n 316 Just {} -> __IMPOSSIBLE__ 317 318 n@Name{} -> lensNameParts (lastIdPart idSuf) n 319 where 320 idSuf s = 321 let (root, suffix) = suffixView s 322 in maybe root (addSuffix root) <$> (f suffix) 323 324-- | Split a name into a base name plus a suffix. 325nameSuffixView :: Name -> (Maybe Suffix, Name) 326nameSuffixView = nameSuffix (,Nothing) 327 328-- | Replaces the suffix of a name. Unless the suffix is @Nothing@, 329-- the name should not be @NoName@. 330setNameSuffix :: Maybe Suffix -> Name -> Name 331setNameSuffix = set nameSuffix 332 333-- | Get a raw version of the name with all suffixes removed. For 334-- instance, @nameRoot "x₁₂₃" = "x"@. 335nameRoot :: Name -> RawName 336nameRoot x = nameToRawName $ snd $ nameSuffixView x 337 338sameRoot :: Name -> Name -> Bool 339sameRoot = (==) `on` nameRoot 340 341------------------------------------------------------------------------ 342-- * Operations on qualified names 343------------------------------------------------------------------------ 344 345-- | Lens for the unqualified part of a QName 346lensQNameName :: Lens' Name QName 347lensQNameName f (QName n) = QName <$> f n 348lensQNameName f (Qual m n) = Qual m <$> lensQNameName f n 349 350-- | @qualify A.B x == A.B.x@ 351qualify :: QName -> Name -> QName 352qualify (QName m) x = Qual m (QName x) 353qualify (Qual m m') x = Qual m $ qualify m' x 354 355-- | @unqualify A.B.x == x@ 356-- 357-- The range is preserved. 358unqualify :: QName -> Name 359unqualify q = unqualify' q `withRangeOf` q 360 where 361 unqualify' (QName x) = x 362 unqualify' (Qual _ x) = unqualify' x 363 364-- | @qnameParts A.B.x = [A, B, x]@ 365qnameParts :: QName -> List1 Name 366qnameParts (Qual x q) = x <| qnameParts q 367qnameParts (QName x) = singleton x 368 369-- | Is the name (un)qualified? 370 371isQualified :: QName -> Bool 372isQualified Qual{} = True 373isQualified QName{} = False 374 375isUnqualified :: QName -> Maybe Name 376isUnqualified Qual{} = Nothing 377isUnqualified (QName n) = Just n 378 379------------------------------------------------------------------------ 380-- * Operations on 'TopLevelModuleName' 381------------------------------------------------------------------------ 382 383-- | Turns a qualified name into a 'TopLevelModuleName'. The qualified 384-- name is assumed to represent a top-level module name. 385 386toTopLevelModuleName :: QName -> TopLevelModuleName 387toTopLevelModuleName q = TopLevelModuleName (getRange q) $ 388 fmap nameToRawName $ qnameParts q 389 390-- | Turns a top-level module name into a file name with the given 391-- suffix. 392 393moduleNameToFileName :: TopLevelModuleName -> String -> FilePath 394moduleNameToFileName (TopLevelModuleName _ ms) ext = 395 joinPath (List1.init ms) </> List1.last ms <.> ext 396 397-- | Finds the current project's \"root\" directory, given a project 398-- file and the corresponding top-level module name. 399-- 400-- Example: If the module \"A.B.C\" is located in the file 401-- \"/foo/A/B/C.agda\", then the root is \"/foo/\". 402-- 403-- Precondition: The module name must be well-formed. 404 405projectRoot :: AbsolutePath -> TopLevelModuleName -> AbsolutePath 406projectRoot file (TopLevelModuleName _ m) = 407 mkAbsolute $ 408 iterate takeDirectory (filePath file) !! length m 409 410------------------------------------------------------------------------ 411-- * No name stuff 412------------------------------------------------------------------------ 413 414-- | @noName_ = 'noName' 'noRange'@ 415noName_ :: Name 416noName_ = noName noRange 417 418noName :: Range -> Name 419noName r = NoName r (NameId 0 noModuleNameHash) 420 421-- | Check whether a name is the empty name "_". 422class IsNoName a where 423 isNoName :: a -> Bool 424 425 default isNoName :: (Foldable t, IsNoName b, t b ~ a) => a -> Bool 426 isNoName = Fold.all isNoName 427 428instance IsNoName String where 429 isNoName = isUnderscore 430 431instance IsNoName ByteString where 432 isNoName = isUnderscore 433 434instance IsNoName Name where 435 isNoName = \case 436 NoName{} -> True 437 Name _ _ (Hole :| []) -> True 438 Name _ _ (Id x :| []) -> isNoName x 439 _ -> False 440 441instance IsNoName QName where 442 isNoName (QName x) = isNoName x 443 isNoName Qual{} = False -- M.A._ does not qualify as empty name 444 445instance IsNoName a => IsNoName (Ranged a) where 446instance IsNoName a => IsNoName (WithOrigin a) where 447 448-- no instance for TopLevelModuleName 449 450------------------------------------------------------------------------ 451-- * Showing names 452------------------------------------------------------------------------ 453 454deriving instance Show Name 455deriving instance Show NamePart 456deriving instance Show QName 457 458------------------------------------------------------------------------ 459-- * Printing names 460------------------------------------------------------------------------ 461 462instance Pretty Name where 463 pretty (Name _ _ xs) = hcat $ fmap pretty xs 464 pretty (NoName _ _) = "_" 465 466instance Pretty NamePart where 467 pretty Hole = "_" 468 pretty (Id s) = text $ rawNameToString s 469 470instance Pretty QName where 471 pretty (Qual m x) 472 | isUnderscore m = pretty x -- don't print anonymous modules 473 | otherwise = pretty m <> "." <> pretty x 474 pretty (QName x) = pretty x 475 476instance Pretty TopLevelModuleName where 477 pretty (TopLevelModuleName _ ms) = text $ List.intercalate "." $ List1.toList ms 478 479------------------------------------------------------------------------ 480-- * Range instances 481------------------------------------------------------------------------ 482 483instance HasRange Name where 484 getRange (Name r _ _ps) = r 485 getRange (NoName r _) = r 486 487instance HasRange QName where 488 getRange (QName x) = getRange x 489 getRange (Qual n x) = fuseRange n x 490 491instance HasRange TopLevelModuleName where 492 getRange = moduleNameRange 493 494instance SetRange Name where 495 setRange r (Name _ nis ps) = Name r nis ps 496 setRange r (NoName _ i) = NoName r i 497 498instance SetRange QName where 499 setRange r (QName x) = QName (setRange r x) 500 setRange r (Qual n x) = Qual (setRange r n) (setRange r x) 501 502instance SetRange TopLevelModuleName where 503 setRange r (TopLevelModuleName _ x) = TopLevelModuleName r x 504 505instance KillRange QName where 506 killRange (QName x) = QName $ killRange x 507 killRange (Qual n x) = killRange n `Qual` killRange x 508 509instance KillRange Name where 510 killRange (Name r nis ps) = Name (killRange r) nis ps 511 killRange (NoName r i) = NoName (killRange r) i 512 513instance KillRange TopLevelModuleName where 514 killRange (TopLevelModuleName _ x) = TopLevelModuleName noRange x 515 516------------------------------------------------------------------------ 517-- * NFData instances 518------------------------------------------------------------------------ 519 520instance NFData NameInScope where 521 rnf InScope = () 522 rnf NotInScope = () 523 524-- | Ranges are not forced. 525 526instance NFData Name where 527 rnf (Name _ nis ns) = rnf nis `seq` rnf ns 528 rnf (NoName _ n) = rnf n 529 530instance NFData NamePart where 531 rnf Hole = () 532 rnf (Id s) = rnf s 533 534instance NFData QName where 535 rnf (Qual a b) = rnf a `seq` rnf b 536 rnf (QName a) = rnf a 537 538instance NFData TopLevelModuleName 539