This commit improves the pretty printing and adds support for
antiquotes. It also fixes an issue with the parser that caused `[if true
then false else true]` to parse successfully, even though that is not a
valid nix expression.
The pretty printer now produces a lot more readable output and also
supports operator precedences.
The changes to the AST are:
* strings are no longer atomic, because they may contain other
expressions in the form of antiquotes. For strings, the new type
NString is introduced and the constructor NStr is added to NExprF
* the unused NVar constructor of NExprF is removed
* operators are now represented uniformly so that the pretty printer
can lookup information about operators (in particular, associativity
and precedence)
* the NArgs constructor is removed. The first argument of the NAbs
constructor now directly represents the lambda arguments.
* the select and the hasattr operator are moved into NExpr because
they are special (they only accept a selector as second argument, and
select also supports 'or')
The list of operators is now in Types.hs and Parser.hs re-uses that list
to build the parser. This is required because the pretty printer and
parser both need access to operator precedences.
Parser and evaluator also support dynamic attributes and attributes with
dots now. As an example, `let b.a = 3; b.c = { e = {}; }; b.c.e.${"f"} =
4; in b` is parsed and evaluated correctly. As a side effect, NSym
values now don't evaluate to themselves anymore, but instead to the
value retrieved by looking up the variable in the current environment.
Support for evaluating `inherit` bindings was removed because it was
broken before (`{ inherit a; }` would evaluate to a set where the
attribute `a` had the value `NSym a`, not the value of `a`).
The manual Show instances for the AST were replaced by derived
ones, because the manual instances often resulted in output were it was
difficult to determine the missing parentheses.
lambda arguments can be parsed without using try at all:
First, we decide if we have a set or an identifier. If we have a set,
there are two cases:
* the lambda argument is a plain set (not followed by an `@` character)
* or the set is optionally followed by `@<identifier>`, in which
case the argument is a <right at> pattern.
If we got an identifier, we can do a similar thing, there are also two
cases:
* plain identifier: not followed by `@`.
* the idenfitifier is followed by `@<set>`. In this case, the argument
is a <left at> pattern.
Avoiding excess use of try should improve performance and lead to better
error messages.
When parsing '{ inherit a; }' without this fix, the `scopedInherit`
parser would be tried first. Because this parser already consumes the
`inherit` keyword, it won't backtrack anymore and the non-scoped
`inherit` parser will never be tried, so we get a parse failure which is
of course not correct.
The solution is to first parse `inherit` (in both cases) and then decide
whether it is a scoped import or not by looking for a following '('.
trifecta should not parse reserved words as identifiers. Before
this commit, `in` would parse as an identifier name and thus
`let a = b; in c` fails to parse.
Two points which are not clear from the manual, where this patch follows
the grammar.y bison implementation:
- The presence of parens in the first argument distinguishes the scoped
inherit
- inherit has the same syntax in sets as in let