Copyright | (c) Alec Theriault 2017-2018 |
---|---|
License | BSD-style |
Maintainer | alec.theriault@gmail.com |
Stability | experimental |
Portability | portable |
Safe Haskell | None |
Language | Haskell2010 |
This module provides functions for turning ASTs into values of type Token
. These values can then be
rendered into concrete string types using functions from the prettyprinter
package. This has some
advantages over printing plain old strings:
- Backend independent: you can use a variety of existing backends to efficiently render to all
sorts of formats like
Text
,String
, HTML, and terminal. Dynamic layouts: the AST will render differently depending on the desired page width
>>>
:set -XTypeApplications -XOverloadedStrings
>>>
import Language.Rust.Parser
>>>
import Data.Text.Prettyprint.Doc.Util ( putDocW )
>>>
let src = parse' @(SourceFile Span) "fn foo(x: i32, y: i32, z: i32) -> i32 { x - y + z }"
>>>
let doc = pretty' src <> "\n"
>>>
putDocW 80 doc
fn foo(x: i32, y: i32, z: i32) -> i32 { x - y + z }>>>
putDocW 10 doc
fn foo( x: i32, y: i32, z: i32, ) -> i32 { x - y + z }- Annotations: Depending on the backend you are using to render the
Token
, annotations can determine colours, styling, links, etc.
The examples below assume the following GHCi flag and import:
>>>
:set -XOverloadedStrings
>>>
import Language.Rust.Syntax.AST
Synopsis
- pretty :: (Resolve a, Pretty a) => a -> Either ResolveFail (Doc b)
- pretty' :: (Resolve a, Pretty a) => a -> Doc b
- prettyAnnotated :: (Resolve (f a), PrettyAnnotated f) => f a -> Either ResolveFail (Doc a)
- prettyAnnotated' :: (Resolve (f a), PrettyAnnotated f) => f a -> Doc a
- writeSourceFile :: (Monoid a, Typeable a) => Handle -> SourceFile a -> IO ()
- writeTokens :: Handle -> [Spanned Token] -> IO ()
- class Pretty a where
- prettyUnresolved :: a -> Doc b
- class PrettyAnnotated p where
- prettyAnnUnresolved :: p a -> Doc a
- data Doc ann
- class Resolve a where
- resolve :: a -> Either ResolveFail a
- resolve' :: a -> a
- resolveVerbose :: a -> (a, Severity, [Issue])
- data ResolveFail = ResolveFail [Dynamic] String
- data Issue = Issue {}
- data Severity
- = Clean
- | Warning
- | Correction
- | Error
Printing
pretty :: (Resolve a, Pretty a) => a -> Either ResolveFail (Doc b) Source #
Resolve (see the Resolve
typeclass) and pretty print something.
>>>
let one = Lit [] (Int Dec 1 Unsuffixed ()) ()
>>>
let two = Lit [] (Int Dec 2 Unsuffixed ()) ()
>>>
let three = Lit [] (Int Dec 3 Unsuffixed ()) ()
>>>
let bogusVar = PathExpr [] Nothing (Path False [PathSegment "let" Nothing ()] ()) ()
>>>
pretty (Binary [] MulOp (Binary [] AddOp one two ()) three ())
Right (1 + 2) * 3>>>
pretty (Binary [] AddOp one bogusVar ())
Left (invalid AST (identifier `let' is a keyword))
pretty' :: (Resolve a, Pretty a) => a -> Doc b Source #
Same as pretty
, but throws a ResolveFail
exception on invalid ASTs. This function is
intended for situations in which you are already stuck catching exceptions - otherwise you should
prefer pretty
.
>>>
let one = Lit [] (Int Dec 1 Unsuffixed ()) ()
>>>
let two = Lit [] (Int Dec 2 Unsuffixed ()) ()
>>>
let three = Lit [] (Int Dec 3 Unsuffixed ()) ()
>>>
let bogusVar = PathExpr [] Nothing (Path False [PathSegment "let" Nothing ()] ()) ()
>>>
pretty' (Binary [] MulOp (Binary [] AddOp one two ()) three ())
(1 + 2) * 3>>>
pretty' (Binary [] AddOp one bogusVar ())
*** Exception: invalid AST (identifier `let' is a keyword))
prettyAnnotated :: (Resolve (f a), PrettyAnnotated f) => f a -> Either ResolveFail (Doc a) Source #
Resolve (see the Resolve
typeclass) and pretty print something with annotations. Read more
about annotations in Data.Text.Prettyprint.Doc.
fmap Data.Text.Prettyprint.Doc.noAnnotate . prettyAnnotated = pretty
prettyAnnotated' :: (Resolve (f a), PrettyAnnotated f) => f a -> Doc a Source #
Same as prettyAnnotated
, but throws a ResolveFail
exception on invalid ASTs. This function
is intended for situations in which you are already stuck catching exceptions - otherwise you
should prefer prettyAnnotated
.
Data.Text.Prettyprint.Doc.noAnnotate . prettyAnnotated' = pretty'
writeSourceFile :: (Monoid a, Typeable a) => Handle -> SourceFile a -> IO () Source #
Given a handle to a file, write a SourceFile
in with a desired width of 100 characters.
writeTokens :: Handle -> [Spanned Token] -> IO () Source #
Given a handle to a file, write a SourceFile
in with a desired width of 100 characters.
The Span
associated with the tokens (if present) will be used as a hint for laying out and
spacing the tokens.
Describes things that can be pretty printed.
prettyUnresolved :: a -> Doc b Source #
Pretty print the given value without resolving it.
Instances
class PrettyAnnotated p where Source #
Similar to Pretty
, but for types which are parametrized over an annotation type.
prettyAnnUnresolved :: p a -> Doc a Source #
Pretty print the given value without resolving it, adding annotations in the Token
whenever
possible.
Instances
The abstract data type
represents pretty documents that have
been annotated with data of type Doc
annann
.
More specifically, a value of type
represents a non-empty set of
possible layouts of a document. The layout functions select one of these
possibilities, taking into account things like the width of the output
document.Doc
The annotation is an arbitrary piece of data associated with (part of) a document. Annotations may be used by the rendering backends in order to display output differently, such as
- color information (e.g. when rendering to the terminal)
- mouseover text (e.g. when rendering to rich HTML)
- whether to show something or not (to allow simple or detailed versions)
The simplest way to display a Doc
is via the Show
class.
>>>
putStrLn (show (vsep ["hello", "world"]))
hello world
Instances
Resolving
class Resolve a where Source #
Since it is possible to have well-typed Haskell expressions which represent invalid Rust ASTs,
it is convenient to fix, warn, or fail ASTs before printing them. The Resolve
typeclass
provides such a facility.
A non-exhaustive list of the more obvious issues it covers:
- missing parens
- invalid identifiers
- invalid paths (for example, generic arguments on a module path)
- inner attributes on things that support only outer attributes (and vice-versa)
resolveM
resolve :: a -> Either ResolveFail a Source #
Convert some value to its resolved form. Informally, resolving a value involves checking that its invariants hold and, if they don't, report an error message or adjust the value so that the invariant holds.
A value of a type satsifying Parse
and Pretty
is resolved if
is an identity
operation on it. We further expect that parse
. pretty
resolve
be an identity operation on any output of
parse
.
Same as resolve
, but throws a ResolveFail
exception if it cannot resolve. Although
this function should not be used, it summarizes nicely the laws around Resolve
:
parse' . pretty' . resolve' == id
resolve' . parse' = parse'
resolveVerbose :: a -> (a, Severity, [Issue]) Source #
Instances
Error reporting
data ResolveFail Source #
Exceptions that occur during resolving. Unlike parse errors, we don't have positional information. Instead, we try to provide some context via a list of syntax trees which let you "zoom out" from the problematic node.
Instances
Show ResolveFail Source # | Does not show context information |
Defined in Language.Rust.Pretty.Resolve showsPrec :: Int -> ResolveFail -> ShowS # show :: ResolveFail -> String # showList :: [ResolveFail] -> ShowS # | |
Exception ResolveFail Source # | |
Defined in Language.Rust.Pretty.Resolve |
Localized information about an issue in a syntax tree.
Issue | |
|
Diagnostic for how severe an Issue
is.
Clean | Everything is normal (this variant is returned when there was nothing to resolve) |
Warning | There is something fishy looking (AST is valid, but may not be what you expect) |
Correction | The AST was invalid, but in a way that could be corrected |
Error | The AST was invalid in some way that could not be automatically fixed |
Instances
Bounded Severity Source # | |
Enum Severity Source # | |
Defined in Language.Rust.Pretty.Resolve | |
Eq Severity Source # | |
Ord Severity Source # | |
Defined in Language.Rust.Pretty.Resolve | |
Show Severity Source # | |