Files
swift-mirror/include/swift/Syntax/SyntaxNodes.h.gyb
Alex Hoppen 3fb5dd1c68 [libSyntax] Create SyntaxRef, which uses SyntaxDataRef internally
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())
```
2021-03-11 19:34:49 +01:00

206 lines
6.4 KiB
C++

%{
# -*- mode: C++ -*-
from gyb_syntax_support import *
NODE_MAP = create_node_map()
# Ignore the following admonition; it applies to the resulting .h file only
}%
//// Automatically Generated From SyntaxNodes.h.gyb.
//// Do Not Edit Directly!
//===---------------- SyntaxNodes.h - Syntax Node definitions -------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_SYNTAX_NODES_H
#define SWIFT_SYNTAX_NODES_H
#include "swift/Syntax/Syntax.h"
#include "swift/Syntax/SyntaxCollection.h"
#include "swift/Syntax/TokenSyntax.h"
#include "swift/Syntax/UnknownSyntax.h"
namespace swift {
namespace syntax {
% # Emit the non-collection classes first, then emit the collection classes
% # that reference these classes.
% for node in SYNTAX_NODES:
% if not node.is_syntax_collection():
class ${node.name};
class ${node.name}Ref;
% end
% end
% for node in SYNTAX_NODES:
% if node.is_syntax_collection():
using ${node.name} =
SyntaxCollection<SyntaxKind::${node.syntax_kind},
${node.collection_element_type}>;
using ${node.name}Ref =
SyntaxCollectionRef<SyntaxKind::${node.syntax_kind},
${node.collection_element_type}Ref>;
% end
% end
% for node in SYNTAX_NODES:
% if not node.is_syntax_collection():
% qualifier = "" if node.is_base() else "final"
% for line in dedented_lines(node.description):
/// ${line}
% end
class ${node.name} ${qualifier} : public ${node.base_type} {
% if node.is_buildable():
friend class ${node.name}Builder;
% end
void validate() const;
public:
% if node.children:
enum Cursor : uint32_t {
% for child in node.children:
${child.name},
% end
};
% end
${node.name}(const RC<const SyntaxData> &Data) : ${node.base_type}(Data) {
this->validate();
}
% for child in node.children:
% for line in dedented_lines(child.description):
/// ${line}
% end
% if child.is_optional:
llvm::Optional<${child.type_name}> get${child.name}() const;
% else:
${child.type_name} get${child.name}() const;
% end
% child_node = NODE_MAP.get(child.syntax_kind)
% if child_node and child_node.is_syntax_collection():
% child_elt = child.collection_element_name
% child_elt_type = child_node.collection_element_type
% if not child_elt:
% raise Exception("'collection_element_name' should be set for '%s' of '%s'" % (child.name, node.name))
% end
/// Adds the provided `${child_elt}` to the node's `${child.name}`
/// collection. The new raw node will be created in the same arena as this
/// node.
/// - param element: The new `${child_elt}` to add to the node's
/// `${child.name}` collection.
/// - returns: A copy of the receiver with the provided `${child_elt}`
/// appended to its `${child.name}` collection.
${node.name} add${child_elt}(${child_elt_type} ${child_elt});
% end
/// Returns a copy of the receiver with its `${child.name}` replaced. The new
/// raw node will be created in the same arena as this node.
/// - param newChild: The new `${child.name}` to replace the node's
/// current `${child.name}`, if present.
${node.name}
with${child.name}(llvm::Optional<${child.type_name}> New${child.type_name});
% end
static bool kindof(SyntaxKind Kind) {
% if node.is_base():
return is${node.syntax_kind}Kind(Kind);
% else:
return Kind == SyntaxKind::${node.syntax_kind};
% end
}
static bool classof(const Syntax *S) {
return kindof(S->getKind());
}
};
/// See doc comment on \c SyntaxDataRef for more details.
class ${node.name}Ref ${qualifier} : public ${node.base_type}Ref {
friend class ${node.name}; // Non-Ref node is a friend so it can call validate
public:
% if node.children:
using Cursor = ${node.name}::Cursor; // Use same cursor as non-Ref node.
% end
explicit ${node.name}Ref(const SyntaxDataRef *Data) : ${node.base_type}Ref(Data) {
this->validate();
}
/// Create a \c ${node.name}Ref node, but don't validate it. Useful if the
/// underlying \c SyntaxDataRef is populated later.
/// \c validate should be called after \p Data has been populated.
${node.name}Ref(const SyntaxDataRef *Data, no_validation_t) : ${node.base_type}Ref(Data) {}
/// Demote a \c ${node.name} node to a \c ${node.name}Ref node.
/// The \c ${node.name} node continues to hold the \c SyntaxData and must thus
/// outlive the \c ${node.name}Ref node.
${node.name}Ref(const ${node.name} &Node) : ${node.base_type}Ref(Node.getData().get()) {}
/// Validate the syntax node. This is automatically done when creating a node
/// unless the \c no_validation_t marker is passed.
void validate() const;
% for child in node.children:
% for line in dedented_lines(child.description):
/// ${line}
% end
% if child.is_optional:
inline OptionalOwnedSyntaxRef<${child.type_name}Ref> get${child.name}() const;
% else:
inline OwnedSyntaxRef<${child.type_name}Ref> get${child.name}() const;
% end
% end
static bool kindof(SyntaxKind Kind) {
% if node.is_base():
return is${node.syntax_kind}Kind(Kind);
% else:
return Kind == SyntaxKind::${node.syntax_kind};
% end
}
static bool classof(const SyntaxRef *S) {
return kindof(S->getKind());
}
};
% end
% end
/// Calculating an identifier for all syntax nodes' structures for verification
/// purposes.
const char* getSyntaxStructureVersioningIdentifier();
% for node in SYNTAX_NODES:
% for child in node.children:
% if child.is_optional:
OptionalOwnedSyntaxRef<${child.type_name}Ref> ${node.name}Ref::get${child.name}() const {
OptionalOwnedSyntaxRef<${child.type_name}Ref> Result;
getDataRef()->getChildRef(Cursor::${child.name}, Result.getDataPtr());
return Result;
}
% else:
OwnedSyntaxRef<${child.type_name}Ref> ${node.name}Ref::get${child.name}() const {
OwnedSyntaxRef<${child.type_name}Ref> Result;
getDataRef()->getPresentChildRef(Cursor::${child.name}, Result.getDataPtr());
return Result;
}
% end
% end
% end
}
}
#endif // SWIFT_SYNTAX_NODES_H