haskell-names

Name resolution library for Haskell http://documentup.com/haskell-suite/haskell-names

Version on this page:0.5.2
LTS Haskell 8.5:0.8.0
Stackage Nightly 2017-02-11:0.8.0
Latest on Hackage:0.8.0
BSD3 licensed by Philipp Schuster, Roman Cheplyaka, Lennart Augustsson
Maintained by Philipp Schuster

Module documentation for 0.5.2

There are no documented modules for this package.

haskell-names Build Status

haskell-names does name and module resolution for haskell-src-exts AST.

Namely, it can do the following:

  • For a list of modules, compute the list of symbols each module exports. This is called resolve.
  • For each name in a module, figure out what it refers to — whether it's bound locally (say, by a where clause) or globally (and then give its origin). This is called annotate.

Installation

If you're building a development version, then you might also need to install a development version of haskell-src-exts.

Environments

An environment is a map from module name to list of symbols the module exports. Symbols are for example types, classes, functions etc. We persist these lists in a JSON format. For example, here are a couple of entries from Prelude.names:

[
  {
    "name": "map",
    "entity": "value",
    "module": "GHC.Base"
  },
  {
    "name": "IO",
    "entity": "newtype",
    "module": "GHC.Types"
  },
  ...
]

As you see, each entity is annotated with the module where it was originally defined. Additionally, class methods, field selectors, and data constructors are annotated with the class or type they belong to.

haskell-names provides functions readSymbols and writeSymbols to read and write interface files.

Name resolution

The annotate function annotates the given module with scoping information.

Its essence is described in the article Open your name resolution.

Example

Let's say you have a module and you want to find out whether it uses Prelude.head.

module Main where

import Language.Haskell.Exts.Annotated (
  fromParseResult, parseModuleWithMode, defaultParseMode,
  parseFilename, prettyPrint, srcInfoSpan)
import Language.Haskell.Exts (
  Name(Ident), ModuleName(ModuleName))
import Language.Haskell.Names (
  loadBase, annotate, symbolName,
  Scoped(Scoped), NameInfo(GlobalSymbol))

import qualified Data.Map as Map (
  lookup)

import Data.Maybe (
  fromMaybe, listToMaybe)
import Data.List (
  nub)
import qualified Data.Foldable as Foldable (
  toList)
import Control.Monad (
  forM_, guard)

main :: IO ()
main = do

  -- read the program's source from stdin
  source <- getContents

  -- parse the program (using haskell-src-exts)
  let ast = fromParseResult (
        parseModuleWithMode defaultParseMode {parseFilename="stdin"} source)

  -- get base environment
  baseEnvironment <- loadBase

  -- get symbols defined in prelude
  let preludeSymbols = fromMaybe (error "Prelude not found") (
        Map.lookup (ModuleName "Prelude") baseEnvironment)

  -- find a Prelude symbol with name 'head' using the List monad
  let headSymbol = fromMaybe (error "Prelude.head not found") (
        listToMaybe (do
          preludeSymbol <- preludeSymbols
          guard (symbolName preludeSymbol == Ident "head")
          return preludeSymbol))

  -- annotate the AST
  let annotatedAST = annotate baseEnvironment ast

  -- get all annotations
  let annotations = Foldable.toList annotatedAST

  -- filter head Usages in List monad and remove duplicates
  let headUsages = nub (do
        Scoped (GlobalSymbol globalSymbol _) location <- annotations
        guard (globalSymbol == headSymbol)
        return location)

  case headUsages of
    [] ->
      putStrLn "Congratulations! Your code doesn't use Prelude.head"
    _ -> forM_ headUsages (\location ->
      putStrLn ("Prelude.head is used at " ++ (prettyPrint (srcInfoSpan location))))

Example invocation

% ./find-heads 
one = head [1]
^D
Prelude.head is used at stdin: (1:7) - (1:11)

% ./find-heads
import Prelude hiding (head)
import Data.Text

f = head (pack "foo")
^D
Congratulations! Your code doesn't use Prelude.head

API documentation

The core module you need is [Language.Haskell.Names][]

Other modules are more experimental, less documented, and you probably don't need them anyway.

Known issues

See the list of all issues.

  • haskell-names doesn't perform validation yet. If a module is not valid Haskell, then the behaviour is undefined. See the issues marked as validation.
  • Symbol fixities are not recorded (#1)
  • Type variables are not resolved (#2)
  • Arrows are not fully supported (#8)

Maintainers

Philipp Schuster is the primary maintainer.

Adam Bergmark is the backup maintainer. Please get in touch with him if the primary maintainer cannot be reached.

Changes

Changes

Version 0.8.0

  • Relax bounds on aeson
  • Relax bounds on transformers
  • Bugfixes
  • Use haskell-src-exts 1.18

Version 0.7.0

  • Improve annotation performance

Version 0.6.0

  • Use haskell-src-exts 1.17
  • Remove dependency on haskell-packages

Version 0.5.3

  • Compatibility with GHC 7.8.4

Version 0.5.2

  • Handle more syntactic constructs

Version 0.5.1

  • Resolve associated types
  • Resolve fixity declarations
  • Resolve classes and instances
  • Various bugfixes

Version 0.5.0

  • Unify type-level and value-level symbols
  • Remove fixities from symbol type
  • Properly annotate classes and instances
  • Inline original name into symbol type
  • Remove original package from symbol type
  • Annotate symbol references with the way they are referenced

Version 0.4.1

  • Export types defined by top level data family declarations
  • Update to haskell-src-exts 1.16

Version 0.4

Replace data-lens with data-lens-light

Version 0.3.3.2

Remove the upper version bound on Cabal

Version 0.3.3.1

Update to work with haskell-src-exts 1.15

Version 0.3.3

  • Expose Language.Haskell.Names.ModuleSymbols.getTopDecls
  • Define a Monoid instance for LocalSymbolTable.Table
  • Support for parallel list comprehensions

Version 0.3.2.8

Introduce a lower dependency bound on tasty-golden in the test suite

Version 0.3.2.7

type-eq is fixed; depend on the new version

Version 0.3.2.6

Work around a regression in type-eq

Version 0.3.2.5

Relax pretty-show version bound

Version 0.3.2.4

Make haskell-names build GHC 7.8

Version 0.3.2.3

Include interfaces for array

Version 0.3.2.2

Allow pretty-show-1.6.2 in the test suite

Version 0.3.2.1

Use pretty-show-1.6.1 in the test suite

Version 0.3.2

  • Export getDeclHead from Language.Haskell.Names.SyntaxUtils
  • Annotate QNames in export lists
  • Update the bundled library interfaces (they were broken in earlier 0.3.* versions because of the interface format change)

Version 0.3.1

  • Documentation improvements
  • Add rfoldMap
  • Relax Cabal dependency constraint to include Cabal-1.14

Version 0.3

This release brings support for record puns and wildcards.

Interface file format changes

For field selectors, the new field constructors is added. It contains a list of constructors that contain that field.

API changes

  • The sv_constructors field is added to SymSelector
  • Add Language.Haskell.Names.SyntaxUtils.stringToName
  • The class GetBound is moved to a new module, Language.Haskell.Names.GetBound. Its method, getBound, now has a new argument, the global symbol table
  • NameInfo got two more constructors to annotate wildcards, RecPatWildcard and RecExpWildcard
  • Scope now has a new field of type WcNames, which can be accessed through the wcNames lens. This is needed for record wildcards resolution.
  • Add field selectors to GName
  • Don't export GName and OrigName from GlobalSymbolTable

Version 0.2.1

  • Fix a bug where global symbols were annotated as local
  • Make the code compile with aeson-0.6.2.0

Version 0.2

  • Proper annotations for types and binding sites. NameContext now has a few new constructors.
  • Properly support n+k patterns
  • Expose the Alg datatype for open name resolution
  • Expose the HasOrigName class

Version 0.1.2

Restore compatibility with Cabal 1.16

Version 0.1.1

Dummy release to force rebuild on hackage (now that haskell-src-exts 1.14 is released).

comments powered byDisqus