module Language.Haskell.Names.Types where
import Language.Haskell.Exts
import Data.Typeable
import Data.Data
import Data.Foldable as F
import Data.Traversable
import Data.Map (Map)
import Text.Printf
data Symbol
= Value
{ symbolModule :: ModuleName ()
, symbolName :: Name ()
}
| Method
{ symbolModule :: ModuleName ()
, symbolName :: Name ()
, className :: Name ()
}
| Selector
{ symbolModule :: ModuleName ()
, symbolName :: Name ()
, typeName :: Name ()
, constructors :: [Name ()]
}
| Constructor
{ symbolModule :: ModuleName ()
, symbolName :: Name ()
, typeName :: Name ()
}
| Type
{ symbolModule :: ModuleName ()
, symbolName :: Name ()
}
| Data
{ symbolModule :: ModuleName ()
, symbolName :: Name ()
}
| NewType
{ symbolModule :: ModuleName ()
, symbolName :: Name ()
}
| TypeFam
{ symbolModule :: ModuleName ()
, symbolName :: Name ()
, associate :: Maybe (Name ())
}
| DataFam
{ symbolModule :: ModuleName ()
, symbolName :: Name ()
, associate :: Maybe (Name ())
}
| Class
{ symbolModule :: ModuleName ()
, symbolName :: Name ()
}
deriving (Eq, Ord, Show, Data, Typeable)
type Environment = Map (ModuleName ()) [Symbol]
data Scoped l = Scoped (NameInfo l) l
deriving (Functor, Foldable, Traversable, Show, Typeable, Data, Eq, Ord)
data NameInfo l
= GlobalSymbol Symbol (QName ())
| LocalValue SrcLoc
| TypeVar SrcLoc
| ValueBinder
| TypeBinder
| Import (Map (QName ()) [Symbol])
| ImportPart [Symbol]
| Export [Symbol]
| RecPatWildcard [Symbol]
| RecExpWildcard [(Name (), NameInfo l)]
| None
| ScopeError (Error l)
deriving (Functor, Foldable, Traversable, Show, Typeable, Data, Eq, Ord)
data Error l
= ENotInScope (QName l)
| EAmbiguous (QName l) [Symbol]
| ETypeAsClass (QName l)
| EClassAsType (QName l)
| ENotExported
(Maybe (Name l))
(Name l)
(ModuleName l)
| EModNotFound (ModuleName l)
| EInternal String
deriving (Data, Typeable, Show, Functor, Foldable, Traversable, Eq, Ord)
ppSymbol :: Symbol -> String
ppSymbol symbol = prettyPrint (symbolModule symbol) ++ "." ++ prettyPrint (symbolName symbol)
ppError :: 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)
EModNotFound mod ->
printf "%s: module not found: %s\n"
(ppLoc mod)
(prettyPrint mod)
EInternal s -> printf "Internal error: %s\n" s
where
ppLoc :: (Annotated a, SrcInfo l) => a l -> String
ppLoc = prettyPrint . getPointLoc . ann
instance (SrcInfo l) => SrcInfo (Scoped l) where
toSrcInfo l1 ss l2 = Scoped None $ toSrcInfo l1 ss l2
fromSrcInfo = Scoped None . fromSrcInfo
getPointLoc = getPointLoc . sLoc
fileName = fileName . sLoc
startLine = startLine . sLoc
startColumn = startColumn . sLoc
sLoc :: Scoped l -> l
sLoc (Scoped _ l) = l