Now that we have a fast SyntaxDataRef, create a corresponding SyntaxRef hierarchy. In contrast to the Syntax, SyntaxRef does *not* own the backing SyntaxDataRef, but merely has a pointer to the SyntaxDataRef.
In addition to the requirements imposed by SyntaxDataRef, the user of the SyntaxRef hierarchy needs to make sure that the backing SyntaxDataRef of a SyntaxRef node stays alive. While this sounds like a lot of requirements, it has performance advantages:
- Passing a SyntaxRef node around is just passing a pointer around.
- When casting a SyntaxRef node, we only need to create a new SyntaxRef (aka. pointer) that points to the same underlying SyntaxDataRef - there's no need to duplicate the SyntaxDataRef.
- As SyntaxDataRef is not ref-counted, there's no ref-counting overhead involved.
Furthermore, the requirements are typically fulfilled. The getChild methods on SyntaxRef return an OwnedSyntaxRef, which stores the SyntaxDataRef. As long as this variable is stored somewhere on the stack, the corresponding SyntaxRef can safely be used for the duration of the stack frame. Even calls like the following are possible, because OwnedSyntaxRef returned by getChild stays alive for the duration of the entire statement.
```
useSyntaxRef(mySyntaxRef.getChild(0).getRef())
```
For syntax nodes that previously didn’t have a `validate` method, the newly added `validate` method is a no-op. This will make validation easier in upcoming generic code.
Instead of having a heap-allocated RefCountedBox to store a SyntaxData's
parent, reference-count SyntaxData itself. This has a couple of
advantages:
- When passing SyntaxData around, only a pointer needs to be passed
instead of the entire struct contents. This is faster.
- We can later introduce a SyntaxDataRef, which behaves similar to
SyntaxData, but delegates the responsibility that the parent stays
alive to the user. While sacrificing guaranteed memory safety, this
means that SyntaxData can then be stack-allocated without any
ref-counting overhead.
Instead, only reference count the SyntaxArena that the RawSyntax nodes
live in. The user of RawSyntax nodes must guarantee that the SyntaxArena
stays alive as long as the RawSyntax nodes are being accessed.
During parse time, the SyntaxTreeCreator holds on to the SyntaxArena
in which it creates RawSyntax nodes. When inspecting a syntax tree,
the root SyntaxData node keeps the SyntaxArena alive. The change should
be mostly invisible to the users of the public libSyntax API.
This change significantly decreases the overall reference-counting
overhead. Since we were not able to free individual RawSyntax nodes
anyway, performing the reference-counting on the level of the
SyntaxArena feels natural.
Instead, reference count the SyntaxData's parent. This has a couple of
advantages:
1. We eliminate a const_cast that was potentially unsafe
2. It more closely resembles the architecture on the Swift side
3. It has the potential to be optimised further if the parent can be
accessed in an unsafe, non-reference-counted way
To represent a type with code completion.
type? '.'? <code-completion-token>
This is "parser only" node which is not exposed to SwiftSyntax.
Using this, defer to set the parsed type to code-completion callbacks.
ParsedSyntaxBuilder has a convenient function to add member to a syntax-collection
child. The function name uses the type name of the collection's members,
which can lead to name collision. This patch renames it.
To ensure SwiftSyntax calls a compatible parser library, this patch sets
up a C API that returns a constant string calculated during compilation time to indicate
the version of syntax node declarations. The same hash will be calculated
in the SwiftSyntax (client) side as well by using the same algorithm.
During runtime, SwiftSyntax will verify its hash value is identical to the
result of calling swiftparse_node_declaration_hash before actual
parsing happens.
This patch only sets the API up. The actual implementation of the
hashing algorithm will come later.
This patch adds a python function to syntax node gyb support called
"check_child_condition". Given a child's definition, this function
generate a C++ closure to check whether a given syntax node can satisfy
the condition of the child node. This function recursively generates code
for node choices too, therefore we don't need to hard code the
condition checking for node choices.
Some structures of syntax nodes can have children choices, e.g. a
dictionary expression can either contain a single ':' token or a list of
key-value pairs.
This patch gives the existing code generation infrastructure a way to
specify such node choices. Node choices are specified under a child
declaration with two constraints: a choice cannot be declared as
optional, and a choice cannot have further recursive choices.
Since we don't have too many node structures with choices, part of the
SyntaxFactory code for these nodes is manually typed.
This patch also teaches AccessorBlock to use node choices.
* Generate libSyntax API
This patch removes the hand-rolled libSyntax API and replaces it with an
API that's entirely automatically generated. This means the API is
guaranteed to be internally stylistically and functionally consistent.