Skip to content

Commit

Permalink
Add isChildOptional() method
Browse files Browse the repository at this point in the history
Add method for determining whether child at given index is wrapped in not_null<>.

Rationale:
Passing child that is wrapped in not_null to SyntaxRewriter::remove(),
results in failing not_null assertion. When you remove quite a lot
arbitrary nodes it gets cumbersome to avoid this issue "manually".

Thanks to this isChildOptional(), one can re-implement
visit/visitDefault methods to pass handler information that
node must not be removed.
  • Loading branch information
sgizler committed Jul 22, 2024
1 parent d3982ef commit e150a49
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 0 deletions.
6 changes: 6 additions & 0 deletions include/slang/syntax/SyntaxNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,10 @@ class SLANG_EXPORT SyntaxNode {
/// is compatible with the static type of the object.
static bool isKind(SyntaxKind) { return true; }

/// Derived nodes should implement this and return false if child at provided
/// index is node wrapped in not_null.
static bool isChildOptional(size_t) { return true; }

protected:
explicit SyntaxNode(SyntaxKind kind) : kind(kind) {}

Expand Down Expand Up @@ -287,6 +291,8 @@ class SLANG_EXPORT SyntaxListBase : public SyntaxNode {

static bool isKind(SyntaxKind kind);

static bool isChildOptional(size_t index);

protected:
SyntaxListBase(SyntaxKind kind, size_t childCount) : SyntaxNode(kind), childCount(childCount) {}

Expand Down
28 changes: 28 additions & 0 deletions scripts/syntax_gen.py
Original file line number Diff line number Diff line change
Expand Up @@ -366,11 +366,20 @@ def generateSyntax(builddir, alltypes, kindmap):
else:
outf.write(" static bool isKind(SyntaxKind kind);\n\n")

outf.write(" static bool isChildOptional(size_t index);\n")
outf.write(" TokenOrSyntax getChild(size_t index);\n")
outf.write(" ConstTokenOrSyntax getChild(size_t index) const;\n")
outf.write(" PtrTokenOrSyntax getChildPtr(size_t index);\n")
outf.write(" void setChild(size_t index, TokenOrSyntax child);\n\n")

docf.write(
" @fn static bool slang::syntax::{}::isChildOptional(size_t index);\n".format(
name
)
)
docf.write(
" @brief Returns false if child member (token or syntax node) at the provided index within this struct is a syntax node wrapped in not_null<>\n"
)
docf.write(
" @fn TokenOrSyntax slang::syntax::{}::getChild(size_t index)\n".format(
name
Expand Down Expand Up @@ -483,6 +492,24 @@ def generateSyntax(builddir, alltypes, kindmap):
cppf.write("}\n\n")

if v.members or v.final != "":
cppf.write("bool {}::isChildOptional(size_t index) {{\n".format(k))
if v.combinedMembers:
cppf.write(" switch (index) {\n")

index = 0
for m in v.combinedMembers:
if m[1] in v.notNullMembers:
cppf.write(" case {}: return false;\n".format(index))
index += 1

cppf.write(" default: return true;\n")
cppf.write(" }\n")
else:
cppf.write(" (void)index;\n")
cppf.write(" return true;\n")

cppf.write("}\n\n")

for returnType in (
"TokenOrSyntax",
"ConstTokenOrSyntax",
Expand Down Expand Up @@ -660,6 +687,7 @@ def generateSyntax(builddir, alltypes, kindmap):
outf.write(
" static bool isKind(SyntaxKind kind) { return kind == SyntaxKind::Unknown; }\n"
)
outf.write(" static bool isChildOptional(size_t) { return true; }\n")
outf.write(" TokenOrSyntax getChild(size_t) { return nullptr; }\n")
outf.write(" ConstTokenOrSyntax getChild(size_t) const { return nullptr; }\n")
outf.write(" PtrTokenOrSyntax getChildPtr(size_t) { return nullptr; }\n")
Expand Down
5 changes: 5 additions & 0 deletions source/syntax/SyntaxNode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -216,4 +216,9 @@ bool SyntaxListBase::isKind(SyntaxKind kind) {
}
}

bool SyntaxListBase::isChildOptional(size_t index) {
(void)index;
return true;
}

} // namespace slang::syntax

0 comments on commit e150a49

Please sign in to comment.