Skip to content

Commit

Permalink
libnixf: fix various missing child node cases (#373)
Browse files Browse the repository at this point in the history
  • Loading branch information
inclyc authored Mar 29, 2024
2 parents 5b6889a + 2f76226 commit f39e6c2
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 6 deletions.
15 changes: 11 additions & 4 deletions libnixf/include/nixf/Basic/Nodes/Expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ class ExprCall : public Expr {

[[nodiscard]] ChildVector children() const override {
ChildVector Children;
Children.reserve(Args.size());
Children.reserve(Args.size() + 1);
Children.emplace_back(Fn.get());
for (const auto &Member : Args) {
Children.emplace_back(Member.get());
}
Expand Down Expand Up @@ -157,19 +158,25 @@ class ExprLet : public Expr {
};

class ExprWith : public Expr {
std::shared_ptr<Misc> KwWith;
std::shared_ptr<Misc> TokSemi;
std::shared_ptr<Expr> With;
std::shared_ptr<Expr> E;

public:
ExprWith(LexerCursorRange Range, std::shared_ptr<Expr> With,
ExprWith(LexerCursorRange Range, std::shared_ptr<Misc> KwWith,
std::shared_ptr<Misc> TokSemi, std::shared_ptr<Expr> With,
std::shared_ptr<Expr> E)
: Expr(NK_ExprWith, Range), With(std::move(With)), E(std::move(E)) {}
: Expr(NK_ExprWith, Range), KwWith(std::move(KwWith)),
TokSemi(std::move(TokSemi)), With(std::move(With)), E(std::move(E)) {}

[[nodiscard]] const Misc &kwWith() const { return *KwWith; }
[[nodiscard]] const Misc *tokSemi() const { return TokSemi.get(); }
[[nodiscard]] Expr *with() const { return With.get(); }
[[nodiscard]] Expr *expr() const { return E.get(); }

[[nodiscard]] ChildVector children() const override {
return {With.get(), E.get()};
return {KwWith.get(), TokSemi.get(), With.get(), E.get()};
}
};

Expand Down
11 changes: 9 additions & 2 deletions libnixf/include/nixf/Basic/Nodes/Simple.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,14 @@ class InterpolatedParts : public Node {
return Fragments[0].escaped();
}

[[nodiscard]] ChildVector children() const override { return {}; }
[[nodiscard]] ChildVector children() const override {
ChildVector Children;
for (const auto &Frag : Fragments) {
if (Frag.kind() == InterpolablePart::SPK_Interpolation)
Children.emplace_back(&Frag.interpolation());
}
return Children;
}
};

class ExprString : public Expr {
Expand All @@ -130,7 +137,7 @@ class ExprString : public Expr {
return Parts->literal();
}

[[nodiscard]] ChildVector children() const override { return {}; }
[[nodiscard]] ChildVector children() const override { return {Parts.get()}; }
};

class ExprPath : public Expr {
Expand Down
5 changes: 5 additions & 0 deletions libnixf/src/Parse/ParseExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,8 @@ std::shared_ptr<ExprWith> Parser::parseExprWith() {
assert(TokWith.kind() == tok_kw_with && "token should be tok_kw_with");

consume(); // with

auto KwWith = std::make_shared<Misc>(TokWith.range());
assert(LastToken && "LastToken should be set after consume()");

auto SyncSemi = withSync(tok_semi_colon);
Expand All @@ -294,9 +296,11 @@ std::shared_ptr<ExprWith> Parser::parseExprWith() {
ExpSemi.diag().note(Note::NK_ToMachThis, TokWith.range())
<< std::string(tok::spelling(tok_kw_with));
return std::make_shared<ExprWith>(LexerCursorRange{LCur, LastToken->rCur()},
std::move(KwWith), /*TokSemi*/ nullptr,
std::move(With), /*E=*/nullptr);
}

auto TokSemi = std::make_shared<Misc>(ExpSemi.tok().range());
consume(); // ;

auto E = parseExpr();
Expand All @@ -305,6 +309,7 @@ std::shared_ptr<ExprWith> Parser::parseExprWith() {
diagNullExpr(Diags, LastToken->rCur(), "with body");

return std::make_shared<ExprWith>(LexerCursorRange{LCur, LastToken->rCur()},
std::move(KwWith), std::move(TokSemi),
std::move(With), std::move(E));
}

Expand Down
17 changes: 17 additions & 0 deletions libnixf/test/Basic/Nodes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,21 @@ TEST(Node, InterpolateLiteralFalse) {
ASSERT_FALSE(Parts.isLiteral());
}

TEST(Node, ExprCall_Children) {
auto Src = "foo bar baz"sv;
std::vector<Diagnostic> Diag;
auto Root = parse(Src, Diag);

ASSERT_EQ(Root->children().size(), 3);
}

TEST(Node, ExprString_Children) {
auto Src = R"("foo${baz}")"sv;
std::vector<Diagnostic> Diag;
auto Root = parse(Src, Diag);

ASSERT_EQ(Root->children().size(), 1);
ASSERT_EQ(Root->children()[0]->children().size(), 1);
}

} // namespace

0 comments on commit f39e6c2

Please sign in to comment.