haskell-names-0.6.0: src/Language/Haskell/Names/Types.hs
{-# LANGUAGE DeriveDataTypeable, DeriveFunctor, DeriveFoldable,
DeriveTraversable, StandaloneDeriving, CPP #-}
module Language.Haskell.Names.Types where
import Language.Haskell.Exts
import qualified Language.Haskell.Exts.Annotated as Ann
import Data.Typeable
import Data.Data
import Data.Foldable as F
import Data.Traversable
import Data.Map (Map)
import Text.Printf
-- | Information about an entity. Carries at least the module it was originally
-- declared in and its name.
data Symbol
= Value
{ symbolModule :: ModuleName
, symbolName :: Name
}
-- ^ value or function
| Method
{ symbolModule :: ModuleName
, symbolName :: Name
, className :: Name
}
-- ^ class method
| Selector
{ symbolModule :: ModuleName
, symbolName :: Name
, typeName :: Name
, constructors :: [Name]
}
-- ^ record field selector
| Constructor
{ symbolModule :: ModuleName
, symbolName :: Name
, typeName :: Name
}
-- ^ data constructor
| Type
{ symbolModule :: ModuleName
, symbolName :: Name
}
-- ^ type synonym
| Data
{ symbolModule :: ModuleName
, symbolName :: Name
}
-- ^ data type
| NewType
{ symbolModule :: ModuleName
, symbolName :: Name
}
-- ^ newtype
| TypeFam
{ symbolModule :: ModuleName
, symbolName :: Name
, associate :: Maybe Name
}
-- ^ type family
| DataFam
{ symbolModule :: ModuleName
, symbolName :: Name
, associate :: Maybe Name
}
-- ^ data family
| Class
{ symbolModule :: ModuleName
, symbolName :: Name
}
-- ^ type class
deriving (Eq, Ord, Show, Data, Typeable)
-- | A map from module name to list of symbols it exports.
type Environment = Map ModuleName [Symbol]
-- | A pair of the name information and original annotation. Used as an
-- annotation type for AST.
data Scoped l = Scoped (NameInfo l) l
deriving (Functor, Foldable, Traversable, Show, Typeable, Data, Eq, Ord)
-- | Information about the names used in an AST.
data NameInfo l
= GlobalSymbol Symbol QName
-- ^ global entitiy and the way it is referenced
| LocalValue SrcLoc
-- ^ local value, and location where it is bound
| TypeVar SrcLoc
-- ^ type variable, and location where it is bound
| ValueBinder
-- ^ here the value name is bound
| TypeBinder
-- ^ here the type name is defined
| Import (Map QName [Symbol])
-- ^ @import@ declaration, and the table of symbols that it
-- introduces
| ImportPart [Symbol]
-- ^ part of an @import@ declaration
| Export [Symbol]
-- ^ part of an @export@ declaration
| RecPatWildcard [Symbol]
-- ^ wildcard in a record pattern. The list contains resolved names
-- of the fields that are brought in scope by this pattern.
| RecExpWildcard [(Name, NameInfo l)]
-- ^ wildcard in a record construction expression. The list contains
-- resolved names of the fields and information about values
-- assigned to those fields.
| None
-- ^ no annotation
| ScopeError (Error l)
-- ^ scope error
deriving (Functor, Foldable, Traversable, Show, Typeable, Data, Eq, Ord)
-- | Errors during name resolution.
data Error l
= ENotInScope (Ann.QName l) -- FIXME annotate with namespace (types/values)
-- ^ name is not in scope
| EAmbiguous (Ann.QName l) [Symbol]
-- ^ name is ambiguous
| ETypeAsClass (Ann.QName l)
-- ^ type is used where a type class is expected
| EClassAsType (Ann.QName l)
-- ^ type class is used where a type is expected
| ENotExported
(Maybe (Ann.Name l)) --
(Ann.Name l) --
(Ann.ModuleName l)
-- ^ Attempt to explicitly import a name which is not exported (or,
-- possibly, does not even exist). For example:
--
-- >import Prelude(Bool(Right))
--
-- The fields are:
--
-- 1. optional parent in the import list, e.g. @Bool@ in @Bool(Right)@
--
-- 2. the name which is not exported
--
-- 3. the module which does not export the name
| EModNotFound (Ann.ModuleName l)
-- ^ module not found
| EInternal String
-- ^ internal error
deriving (Data, Typeable, Show, Functor, Foldable, Traversable, Eq, Ord)
-- | Pretty print a symbol.
ppSymbol :: Symbol -> String
ppSymbol symbol = prettyPrint (symbolModule symbol) ++ "." ++ prettyPrint (symbolName symbol)
-- | Display an error.
--
-- Note: can span multiple lines; the trailing newline is included.
ppError :: Ann.SrcInfo l => Error l -> String
ppError e =
case e of
ENotInScope qn -> printf "%s: not in scope: %s\n"
(ppLoc qn)
(prettyPrint qn)
EAmbiguous qn names ->
printf "%s: ambiguous name %s\nIt may refer to:\n"
(ppLoc qn)
(prettyPrint qn)
++
F.concat (map (printf " %s\n" . ppSymbol) names)
ETypeAsClass qn ->
printf "%s: type %s is used where a class is expected\n"
(ppLoc qn)
(prettyPrint qn)
EClassAsType qn ->
printf "%s: class %s is used where a type is expected\n"
(ppLoc qn)
(prettyPrint qn)
ENotExported _mbParent name mod ->
printf "%s: %s does not export %s\n"
(ppLoc name)
(prettyPrint mod)
(prettyPrint name)
-- FIXME: make use of mbParent
EModNotFound mod ->
printf "%s: module not found: %s\n"
(ppLoc mod)
(prettyPrint mod)
EInternal s -> printf "Internal error: %s\n" s
where
ppLoc :: (Ann.Annotated a, Ann.SrcInfo l) => a l -> String
ppLoc = prettyPrint . Ann.getPointLoc . Ann.ann
instance (Ann.SrcInfo l) => Ann.SrcInfo (Scoped l) where
toSrcInfo l1 ss l2 = Scoped None $ Ann.toSrcInfo l1 ss l2
fromSrcInfo = Scoped None . Ann.fromSrcInfo
getPointLoc = Ann.getPointLoc . sLoc
fileName = Ann.fileName . sLoc
startLine = Ann.startLine . sLoc
startColumn = Ann.startColumn . sLoc
sLoc :: Scoped l -> l
sLoc (Scoped _ l) = l