summaryrefslogtreecommitdiff
path: root/libraries
diff options
context:
space:
mode:
Diffstat (limited to 'libraries')
-rw-r--r--libraries/ghc-boot/GHC/Lexeme.hs32
-rw-r--r--libraries/ghc-boot/GHC/PackageDb.hs (renamed from libraries/bin-package-db/GHC/PackageDb.hs)0
-rw-r--r--libraries/ghc-boot/LICENSE (renamed from libraries/bin-package-db/LICENSE)0
-rw-r--r--libraries/ghc-boot/ghc-boot.cabal (renamed from libraries/bin-package-db/bin-package-db.cabal)21
-rw-r--r--libraries/template-haskell/Language/Haskell/TH.hs1
-rw-r--r--libraries/template-haskell/Language/Haskell/TH/Syntax.hs69
-rw-r--r--libraries/template-haskell/changelog.md8
-rw-r--r--libraries/template-haskell/template-haskell.cabal1
8 files changed, 109 insertions, 23 deletions
diff --git a/libraries/ghc-boot/GHC/Lexeme.hs b/libraries/ghc-boot/GHC/Lexeme.hs
new file mode 100644
index 0000000000..677c9a65e6
--- /dev/null
+++ b/libraries/ghc-boot/GHC/Lexeme.hs
@@ -0,0 +1,32 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module : GHC.Lexeme
+-- Copyright : (c) The GHC Team
+--
+-- Maintainer : ghc-devs@haskell.org
+-- Portability : portable
+--
+-- Functions to evaluate whether or not a string is a valid identifier.
+--
+module GHC.Lexeme (
+ -- * Lexical characteristics of Haskell names
+ startsVarSym, startsVarId, startsConSym, startsConId,
+ startsVarSymASCII, isVarSymChar
+ ) where
+
+import Data.Char
+
+startsVarSym, startsVarId, startsConSym, startsConId :: Char -> Bool
+startsVarSym c = startsVarSymASCII c || (ord c > 0x7f && isSymbol c) -- Infix Ids
+startsConSym c = c == ':' -- Infix data constructors
+startsVarId c = c == '_' || case generalCategory c of -- Ordinary Ids
+ LowercaseLetter -> True
+ OtherLetter -> True -- See #1103
+ _ -> False
+startsConId c = isUpper c || c == '(' -- Ordinary type constructors and data constructors
+
+startsVarSymASCII :: Char -> Bool
+startsVarSymASCII c = c `elem` "!#$%&*+./<=>?@\\^|~-"
+
+isVarSymChar :: Char -> Bool
+isVarSymChar c = c == ':' || startsVarSym c
diff --git a/libraries/bin-package-db/GHC/PackageDb.hs b/libraries/ghc-boot/GHC/PackageDb.hs
index 672b7ebbe3..672b7ebbe3 100644
--- a/libraries/bin-package-db/GHC/PackageDb.hs
+++ b/libraries/ghc-boot/GHC/PackageDb.hs
diff --git a/libraries/bin-package-db/LICENSE b/libraries/ghc-boot/LICENSE
index b5059b71f6..b5059b71f6 100644
--- a/libraries/bin-package-db/LICENSE
+++ b/libraries/ghc-boot/LICENSE
diff --git a/libraries/bin-package-db/bin-package-db.cabal b/libraries/ghc-boot/ghc-boot.cabal
index a54fe16449..98929b7f83 100644
--- a/libraries/bin-package-db/bin-package-db.cabal
+++ b/libraries/ghc-boot/ghc-boot.cabal
@@ -1,17 +1,17 @@
-name: bin-package-db
+name: ghc-boot
version: 0.0.0.0
license: BSD3
maintainer: ghc-devs@haskell.org
bug-reports: glasgow-haskell-bugs@haskell.org
-synopsis: The GHC compiler's view of the GHC package database format
-description: This library is shared between GHC and ghc-pkg and is used by
- GHC to read package databases.
+synopsis: Shared functionality between GHC and its boot libraries
+description: This library is shared between GHC, ghc-pkg, and other boot
+ libraries.
.
- It only deals with the subset of the package database that the
- compiler cares about: modules paths etc and not package
- metadata like description, authors etc. It is thus not a
- library interface to ghc-pkg and is *not* suitable for
- modifying GHC package databases.
+ A note about "GHC.PackageDb": it only deals with the subset of
+ the package database that the compiler cares about: modules
+ paths etc and not package metadata like description, authors
+ etc. It is thus not a library interface to ghc-pkg and is *not*
+ suitable for modifying GHC package databases.
.
The package database format and this library are constructed in
such a way that while ghc-pkg depends on Cabal, the GHC library
@@ -22,7 +22,7 @@ build-type: Simple
source-repository head
type: git
location: http://git.haskell.org/ghc.git
- subdir: libraries/bin-package-db
+ subdir: libraries/ghc-boot
Library
default-language: Haskell2010
@@ -34,6 +34,7 @@ Library
TypeSynonymInstances
exposed-modules:
+ GHC.Lexeme
GHC.PackageDb
build-depends: base >= 4 && < 5,
diff --git a/libraries/template-haskell/Language/Haskell/TH.hs b/libraries/template-haskell/Language/Haskell/TH.hs
index bce8bf5ddb..49038816e7 100644
--- a/libraries/template-haskell/Language/Haskell/TH.hs
+++ b/libraries/template-haskell/Language/Haskell/TH.hs
@@ -51,6 +51,7 @@ module Language.Haskell.TH(
nameBase, -- :: Name -> String
nameModule, -- :: Name -> Maybe String
namePackage, -- :: Name -> Maybe String
+ nameSpace, -- :: Name -> Maybe NameSpace
-- ** Built-in names
tupleTypeName, tupleDataName, -- Int -> Name
unboxedTupleTypeName, unboxedTupleDataName, -- :: Int -> Name
diff --git a/libraries/template-haskell/Language/Haskell/TH/Syntax.hs b/libraries/template-haskell/Language/Haskell/TH/Syntax.hs
index b64dfffb93..97c379d407 100644
--- a/libraries/template-haskell/Language/Haskell/TH/Syntax.hs
+++ b/libraries/template-haskell/Language/Haskell/TH/Syntax.hs
@@ -38,6 +38,7 @@ import Data.Int
import Data.Word
import Data.Ratio
import GHC.Generics ( Generic )
+import GHC.Lexeme ( startsVarSym, startsVarId )
#ifdef HAS_NATURAL
import Numeric.Natural
@@ -645,10 +646,10 @@ dataToQa mkCon mkLit appCon antiQ t =
Nothing ->
case constrRep constr of
AlgConstr _ ->
- appCon (mkCon conName) conArgs
+ appCon (mkCon funOrConName) conArgs
where
- conName :: Name
- conName =
+ funOrConName :: Name
+ funOrConName =
case showConstr constr of
"(:)" -> Name (mkOccName ":")
(NameG DataName
@@ -662,13 +663,23 @@ dataToQa mkCon mkLit appCon antiQ t =
(NameG DataName
(mkPkgName "ghc-prim")
(mkModName "GHC.Tuple"))
- con -> mkNameG_d (tyConPackage tycon)
- (tyConModule tycon)
- con
+ -- It is possible for a Data instance to be defined such
+ -- that toConstr uses a Constr defined using a function,
+ -- not a data constructor. In such a case, we must take
+ -- care to build the Name using mkNameG_v (for values),
+ -- not mkNameG_d (for data constructors).
+ -- See Trac #10796.
+ fun@(x:_) | startsVarSym x || startsVarId x
+ -> mkNameG_v tyconPkg tyconMod fun
+ con -> mkNameG_d tyconPkg tyconMod con
where
tycon :: TyCon
tycon = (typeRepTyCon . typeOf) t
+ tyconPkg, tyconMod :: String
+ tyconPkg = tyConPackage tycon
+ tyconMod = tyConModule tycon
+
conArgs :: [Q q]
conArgs = gmapQ (dataToQa mkCon mkLit appCon antiQ) t
IntConstr n ->
@@ -691,8 +702,17 @@ dataToExpQ :: Data a
=> (forall b . Data b => b -> Maybe (Q Exp))
-> a
-> Q Exp
-dataToExpQ = dataToQa conE litE (foldl appE)
- where conE s = return (ConE s)
+dataToExpQ = dataToQa varOrConE litE (foldl appE)
+ where
+ -- Make sure that VarE is used if the Constr value relies on a
+ -- function underneath the surface (instead of a constructor).
+ -- See Trac #10796.
+ varOrConE s =
+ case nameSpace s of
+ Just VarName -> return (VarE s)
+ Just DataName -> return (ConE s)
+ _ -> fail $ "Can't construct an expression from name "
+ ++ showName s
appE x y = do { a <- x; b <- y; return (AppE a b)}
litE c = return (LitE c)
@@ -710,8 +730,13 @@ dataToPatQ :: Data a
-> Q Pat
dataToPatQ = dataToQa id litP conP
where litP l = return (LitP l)
- conP n ps = do ps' <- sequence ps
- return (ConP n ps')
+ conP n ps =
+ case nameSpace n of
+ Just DataName -> do
+ ps' <- sequence ps
+ return (ConP n ps')
+ _ -> fail $ "Can't construct a pattern from name "
+ ++ showName n
-----------------------------------------------------
-- Names and uniques
@@ -855,13 +880,13 @@ data NameFlavour
-- An original name (occurrences only, not binders)
-- Need the namespace too to be sure which
-- thing we are naming
- deriving ( Typeable, Data, Eq, Ord, Generic )
+ deriving ( Typeable, Data, Eq, Ord, Show, Generic )
data NameSpace = VarName -- ^ Variables
| DataName -- ^ Data constructors
| TcClsName -- ^ Type constructors and classes; Haskell has them
-- in the same name space for now.
- deriving( Eq, Ord, Data, Typeable, Generic )
+ deriving( Eq, Ord, Show, Data, Typeable, Generic )
type Uniq = Int
@@ -907,6 +932,26 @@ namePackage :: Name -> Maybe String
namePackage (Name _ (NameG _ p _)) = Just (pkgString p)
namePackage _ = Nothing
+-- | Returns whether a name represents an occurrence of a top-level variable
+-- ('VarName'), data constructor ('DataName'), type constructor, or type class
+-- ('TcClsName'). If we can't be sure, it returns 'Nothing'.
+--
+-- ==== __Examples__
+--
+-- >>> nameSpace 'Prelude.id
+-- Just VarName
+-- >>> nameSpace (mkName "id")
+-- Nothing -- only works for top-level variable names
+-- >>> nameSpace 'Data.Maybe.Just
+-- Just DataName
+-- >>> nameSpace ''Data.Maybe.Maybe
+-- Just TcClsName
+-- >>> nameSpace ''Data.Ord.Ord
+-- Just TcClsName
+nameSpace :: Name -> Maybe NameSpace
+nameSpace (Name _ (NameG ns _ _)) = Just ns
+nameSpace _ = Nothing
+
{- |
Generate a capturable name. Occurrences of such names will be
resolved according to the Haskell scoping rules at the occurrence
diff --git a/libraries/template-haskell/changelog.md b/libraries/template-haskell/changelog.md
index fb701abf47..e4edf63f42 100644
--- a/libraries/template-haskell/changelog.md
+++ b/libraries/template-haskell/changelog.md
@@ -10,7 +10,13 @@
according to the fixities of the operators. The `ParensT` constructor can be
used to explicitly group expressions.
- * Add `namePackage`
+ * Add `namePackage` and `nameSpace`
+
+ * Make `dataToQa` and `dataToExpQ` able to handle `Data` instances whose
+ `toConstr` implementation relies on a function instead of a data
+ constructor (#10796)
+
+ * Add `Show` instances for `NameFlavour` and `NameSpace`
* TODO: document API changes and important bugfixes
diff --git a/libraries/template-haskell/template-haskell.cabal b/libraries/template-haskell/template-haskell.cabal
index 4bfd1a96a7..dd31604e95 100644
--- a/libraries/template-haskell/template-haskell.cabal
+++ b/libraries/template-haskell/template-haskell.cabal
@@ -48,6 +48,7 @@ Library
build-depends:
base >= 4.6 && < 4.9,
+ ghc-boot,
pretty == 1.1.*
-- We need to set the package key to template-haskell (without a