Commit Graph

160 Commits

Author SHA1 Message Date
Martin Atkins
4e18e3a8a8 zcl: allow nil Variables in EvalContext
it's acceptable to have "Variables" set to nil in an EvalContext, if
a particular scope has no variables at all. If _no_ contexts in the
chain have non-nil variables, this is considered to mean that variables
are not allowed at all, which produces a different error message.
2017-06-16 07:15:14 -07:00
Martin Atkins
4ab33cdce0 zclsyntax: "expanding" function arguments
This syntax func(arg...) allows the final argument to be a sequence-typed
value that then expands to be one argument for each element of the
value.

This allows applications to define variadic functions where that's
user-friendly while still allowing users to pass tuples to those functions
in situations where the args are chosen dynamically.
2017-06-15 08:18:00 -07:00
Martin Atkins
fa06f40141 zclsyntax: ForExpr.Value implementation for object construction
The tuple path is not yet implemented and will panic.
2017-06-14 08:56:28 -07:00
Martin Atkins
0cf39f0f62 zclsyntax: FIXME to support parent ctx in function call 2017-06-14 08:54:53 -07:00
Martin Atkins
9340e6da4e zcl: TraverseAbs through parent scopes
An EvalContext can have a parent, so it's necessary to walk up until
the root is reached in case a parent scope defines the name we're
looking for.
2017-06-14 08:54:12 -07:00
Martin Atkins
51945b4e0c zclsyntax: In Variables, don't return traversals in child scopes
The purpose of the Variables function is to tell a calling application
what symbols need to be present in the _root_ scope, so it would be
unhelpful to include child scope traversals. Child scopes are populated
by the nodes that create them, and are thus not interesting to the
calling application (for this purpose, at least).
2017-06-14 08:03:32 -07:00
Martin Atkins
bdfe5c1b11 zclsyntax: visit both LHS and RHS of binary op in walk
Due to a typo, it was previously visiting LHS twice, and destroying the
RHS by overwriting it by LHS.
2017-06-14 07:29:37 -07:00
Martin Atkins
6c7802d404 zclsyntax: Parsing of ForExpr
The ForExpr is essentially a list/map comprehension, allowing projecting
one expression into another. From a syntactic standpoint it's the most
complex structure we've dealt with so far, with many separate parts.

The tests introduced here are not exhaustive but illustrate that the
basic mechanism is working.
2017-06-13 08:53:33 -07:00
Martin Atkins
5ad092067b zclsyntax: Ellipsis and "fat arrow" tokens
These will be used in the "for" expression, and later ellipsis will also
be used within calls to expand tuples as args.
2017-06-13 08:50:20 -07:00
Martin Atkins
e0c5f51bd5 zclsyntax: "Keyword" type
This is a helper for recognizing identifiers that are actually keywords.
2017-06-13 08:43:03 -07:00
Martin Atkins
54fcc09ed4 zclsyntax: AST node for the "for" expression
This expression is used to project collections into other collections.
2017-06-13 08:42:36 -07:00
Martin Atkins
b878a4ef98 json: parse strings as zclsyntax templates
This is the same idea as our existing HIL template support, but uses the
zclsyntax template parser instead of HIL's parser.
2017-06-12 07:25:09 -07:00
Martin Atkins
a0be779c9c zclsyntax: operation failure diagnostics apply to whole expr 2017-06-12 07:14:09 -07:00
Martin Atkins
9be04673c3 zclsyntax: UnaryOpExpr.Value 2017-06-12 07:13:17 -07:00
Martin Atkins
e709d7bcc0 zclsyntax: operations are now pointers to a struct value
Previously operations were an enum, but we've ended up needing to store
a collection of values against each, so an operation being a pointer to
a struct feels more natural.

This in turn allows us to more easily fix the return types of the
operations, so that we don't need to do any unusual work to understand
that (for example) arithmetic always returns a number.
2017-06-12 07:09:24 -07:00
Martin Atkins
c332084224 zclsyntax: BinaryOpExpr.Value 2017-06-11 18:55:27 -07:00
Martin Atkins
09f9e6c8e8 zclsyntax: deal with template unwrapping at eval time
Previously we were detecting the exactly-one-part case at parse time and
skipping the TemplateExpr node in the AST, but this was problematic
because we then misaligned the source range for the expression to the
_content_ of the quotes, rather than including the quotes themselves.

As well as producing confusing diagnostics, this also caused problems for
zclwrite since it relies on source ranges to map our AST back onto the
source tokens it came from.
2017-06-11 08:39:40 -07:00
Martin Atkins
e571ec5810 zcl: Range.String should not be a pointer method
We don't usually use ranges as pointers, except in diagnostics.
2017-06-11 08:37:28 -07:00
Martin Atkins
5477fecfad zclsyntax: require newlines after block items
Previously we tolerated EOF as an alias for newline, but a file without
a newline at the end is a edge case primarily limited to contrived
examples in unit tests, and requiring it simplifies tasks such as code
generation in zclwrite, since we can always assume that every block item
comes with a built-in line terminator.
2017-06-09 08:19:47 -07:00
Martin Atkins
755fe38505 zclsyntax: peeker pretends single-line comments are newlines
When we're skipping comments but retaining newlines, we need to do some
slight-of-hand because single-line comment tokens contain the newline
that terminates them (for simpler handling of lead doc comments) but our
parsing can be newline-sensitive.

To allow for this, as a special case we transform single-line comment
tokens into newlines when in this situation, thus allowing parser code
to just worry about the newlines and skip over the comments.
2017-06-09 07:19:25 -07:00
Martin Atkins
c88641b147 zclwrite: absorb lead comments into attributes
The native parser's ranges don't include any surrounding comments, so we
need to do a little more work to pick them out of the surrounding token
sequences.

This just takes care of _lead_ comments, which are those that appear as
whole line comments above the item in question. Line comments, which
appear after the item on the same line, will follow in a later commit.
2017-06-08 09:04:27 -07:00
Martin Atkins
34be20cc5d zclsyntax: ScopeTraversalExpr.Value implementation, and tests 2017-06-05 08:02:54 -07:00
Martin Atkins
68aa56c795 zcl: Implement Traversal.TraverseAbs 2017-06-05 07:55:33 -07:00
Martin Atkins
ace387f5f9 zclsyntax: evaluation of relative traversal and index nodes 2017-06-05 07:41:02 -07:00
Martin Atkins
b604827bb2 zcl: Automatically convert key types when indexing
For example, if a map is indexed with a number then we'll automatically
convert it to string before attempting to use it as an index.
2017-06-05 07:39:14 -07:00
Martin Atkins
36eacf5110 zcl: Factor the index operation out into its own function
Indexing is pretty fundamental and it's also non-trivial, so having this
exposed will make it easier for it to be implemented consistently across
many different callers, including within calling applications.
2017-06-05 07:31:59 -07:00
Martin Atkins
0266334560 zclsyntax: handle case where functions are not allowed
Previously this would panic.
2017-06-05 07:31:09 -07:00
Martin Atkins
bca573d3d0 zclsyntax: parsing of the index operator
This can either be a traversal or a first-class node depending on whether
the given expression is a literal. This exception is made to allow
applications to conditionally populate only part of a potentially-large
collection if the config is only requesting one or two distinct indices.

In particular, it allows the following to be considered a single traversal
from the scope:

    foo.bar[0].baz
2017-06-05 07:09:04 -07:00
Martin Atkins
8fc5bd5141 zclsyntax: run stringer after other generators
stringer is more sensitive to certain errors than other generators, so
by running it last we give the other generators a chance to get things
straight before we ask stringer to run.
2017-06-05 07:04:26 -07:00
Martin Atkins
b5471b9715 zclsyntax: beginnings of parsing traversal operators
Traversal operators are the operators that can appear after a value
to traverse into the data structure that value represents. So far only
the attribute access operator is implemented.
2017-06-04 18:41:16 -07:00
Martin Atkins
0d0404867c zclsyntax: RelativeTraversalExpr
This is similar to ScopeTraversalExpr, but it traverses relative to the
result of another expression rather than relative to a variable in the
scope.
2017-06-04 18:40:15 -07:00
Martin Atkins
6f2bd0009c zclsyntax: parsing and evaluation for object constructors 2017-06-04 16:14:02 -07:00
Martin Atkins
cac847b163 zclsyntax: separate tokens for assign = and equality test == 2017-06-04 16:00:40 -07:00
Martin Atkins
c3f4694e06 zclsyntax: parsing and evaluation of tuple constructors 2017-06-04 14:22:51 -07:00
Martin Atkins
4488df0cd8 zclsyntax: create comma tokens in the scanner 2017-06-04 14:22:27 -07:00
Martin Atkins
c9c2a2bd16 zclsyntax: Implement the ContextString interface on our Nav
This allows tooling to get a string describing the context of a particular
offset into the file. This is used, for example, to provide context
above the source code snippets in console-printed diagnostic messages.
2017-06-04 09:52:16 -07:00
Martin Atkins
6f1cf4465d zcl: Range.ContainsOffset should not have pointer receiver 2017-06-04 09:37:37 -07:00
Martin Atkins
e100bf4723 zclsyntax: generate lexer diagnostics
There are certain tokens that are _never_ valid, so we might as well
catch them early in the Lex... functions rather than having to handle
them in many different contexts within the parser.

Unfortunately for now when such errors occur they tend to be echoed by
more confusing errors coming from the parser, but we'll accept that for
now.
2017-06-04 07:34:26 -07:00
Martin Atkins
c9ac91aa84 Add MissingItemRange to zcl.BodyContent
This allows code that only deals with BodyContent (post-decoding) to
still be able to report on missing items within the associated body while
providing a suitable source location.
2017-06-03 16:46:49 -07:00
Martin Atkins
cad3e7957f zclsyntax: Body.Content and Body.PartialContent 2017-06-03 09:04:16 -07:00
Martin Atkins
f9da844479 hclhil: use "Subject" rather than "Context" in structure diagnostics 2017-06-03 08:14:09 -07:00
Martin Atkins
da1f9950a6 zclsyntax: Body.JustAttributes implementation 2017-06-03 07:29:48 -07:00
Martin Atkins
aacf36abfd zclsyntax: permit arbitrary newlines inside template interpolations 2017-06-03 06:57:28 -07:00
Martin Atkins
c15eb86349 zclsyntax: require block definitions to end with a newline
Previously we ostensibly allowed block {}block {}, but now we'll reject
that.
2017-06-02 08:19:11 -07:00
Martin Atkins
4d6dbdbb37 zclsyntax: parsing of attributes within bodies 2017-06-02 08:12:33 -07:00
Martin Atkins
a1368a4d4d zclsyntax: parsing of function call expressions 2017-06-02 07:55:03 -07:00
Martin Atkins
e66e6a5f51 zclsyntax: add TokenComma TokenType 2017-06-02 07:40:42 -07:00
Martin Atkins
6052cb9938 zclsyntax: parse expressions in newline-ignoring mode
This applies both two the whole of bare expressions and to any nested
expressions within parentheses. The latter means that an attribute value
can span over multiple lines if it's wrapped in parens:

    foo = (
        1 + 2 + 3 + 4 + 5
    )
2017-06-02 07:26:45 -07:00
Martin Atkins
302487ce0f zclsyntax: template interpolation trimming
The ~ character can be used at the start and end of interpolation
sequences to trim off whitespace in neighboring literals, with the goal
of allowing extra whitespace to be included for readability without
including it in the resulting string.
2017-06-01 08:43:59 -07:00
Martin Atkins
fdfdfc4f3d zclsyntax: scan correctly closing ~} markers
Previously we were failing to return back to template-scanning mode due
to decrementing "braces" too early, causing the remainder of the template
to be scanned as if it were an expression.
2017-06-01 08:36:48 -07:00