| Copyright | (c) Alec Theriault 2017-2018 |
|---|---|
| License | BSD-style |
| Maintainer | alec.theriault@gmail.com |
| Stability | experimental |
| Portability | portable |
| Safe Haskell | None |
| Language | Haskell2010 |
Language.Rust.Pretty.Resolve
Description
NOTE: the following uses hithero unimplemented antiquoting syntax
An AST and its text form should be completely isomorphic, with parse and pretty being the
functions allowing you to go back and forth between these forms. Unfortunately, this cannot really
be the case. The AST form can express programs which cannot be literally pretty printed and still
make sense. Sometimes, extra parens or semicolons need to be added.
Simple example
For example, consider the following interaction
>>>import Language.Rust.Quote>>>import Language.Rust.Pretty>>>:set -XQuasiQuotes>>>x = [expr| 2 + 3 |]>>>y = [expr| 1 * $x |]>>>pretty y0 * 1 + 2
The problem is that we haven't introduced the paren AST node (which we would have gotten had we
parsed 1 * (2 + 3). This is where resolve steps in.
>>>Right y' = resolve y>>>pretty y'0 * (1 + 2)
More involved example
From the above, it is tempting to say: your pretty printer should be smarter! However, things are not always so simple. Consider the less obvious example:
>>>fnBody = [expr| { let y = x; x += 1; y } + x |]>>>fn = [item| fn foo(mut x: i32) -> i32 { $fnBody } |]>>>pretty fnfn foo(mut x: i32) -> i32 { { let y = x; x += 1; y } + x }
This is clearly not the desired output - this won't compile with rustc because of an invariant in
blocks: if the block ends in an expression, that expression cannot start with a block. To fix this,
we call resolve on the AST before pretty printing it.
>>>Right fn' = resolve fn>>>pretty fn'fn foo(mut x: i32) -> i32 { ({ let y = x; x += 1; y }) + x }
And now we have generated valid code.
Synopsis
- class Resolve a where
- resolve :: a -> Either ResolveFail a
- resolve' :: a -> a
- resolveVerbose :: a -> (a, Severity, [Issue])
- data Issue = Issue {}
- data Severity
- = Clean
- | Warning
- | Correction
- | Error
- data ResolveFail = ResolveFail [Dynamic] String
Documentation
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)
Minimal complete definition
resolveM
Methods
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 . prettyresolve 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
Localized information about an issue in a syntax tree.
Constructors
| Issue | |
Fields
| |
Diagnostic for how severe an Issue is.
Constructors
| 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 # | |
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.
Constructors
| ResolveFail [Dynamic] String |
Instances
| Show ResolveFail Source # | Does not show context information |
Defined in Language.Rust.Pretty.Resolve Methods showsPrec :: Int -> ResolveFail -> ShowS # show :: ResolveFail -> String # showList :: [ResolveFail] -> ShowS # | |
| Exception ResolveFail Source # | |
Defined in Language.Rust.Pretty.Resolve Methods toException :: ResolveFail -> SomeException # fromException :: SomeException -> Maybe ResolveFail # displayException :: ResolveFail -> String # | |