diff --git a/libnixf/include/nixf/Basic/Nodes/Expr.h b/libnixf/include/nixf/Basic/Nodes/Expr.h index 344491864..b22c60b10 100644 --- a/libnixf/include/nixf/Basic/Nodes/Expr.h +++ b/libnixf/include/nixf/Basic/Nodes/Expr.h @@ -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()); } @@ -157,19 +158,25 @@ class ExprLet : public Expr { }; class ExprWith : public Expr { + std::shared_ptr KwWith; + std::shared_ptr TokSemi; std::shared_ptr With; std::shared_ptr E; public: - ExprWith(LexerCursorRange Range, std::shared_ptr With, + ExprWith(LexerCursorRange Range, std::shared_ptr KwWith, + std::shared_ptr TokSemi, std::shared_ptr With, std::shared_ptr 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()}; } }; diff --git a/libnixf/include/nixf/Basic/Nodes/Simple.h b/libnixf/include/nixf/Basic/Nodes/Simple.h index a2f99ab30..0dce92190 100644 --- a/libnixf/include/nixf/Basic/Nodes/Simple.h +++ b/libnixf/include/nixf/Basic/Nodes/Simple.h @@ -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 { @@ -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 { diff --git a/libnixf/src/Parse/ParseExpr.cpp b/libnixf/src/Parse/ParseExpr.cpp index 1d7a5c0ab..654528661 100644 --- a/libnixf/src/Parse/ParseExpr.cpp +++ b/libnixf/src/Parse/ParseExpr.cpp @@ -280,6 +280,8 @@ std::shared_ptr Parser::parseExprWith() { assert(TokWith.kind() == tok_kw_with && "token should be tok_kw_with"); consume(); // with + + auto KwWith = std::make_shared(TokWith.range()); assert(LastToken && "LastToken should be set after consume()"); auto SyncSemi = withSync(tok_semi_colon); @@ -294,9 +296,11 @@ std::shared_ptr Parser::parseExprWith() { ExpSemi.diag().note(Note::NK_ToMachThis, TokWith.range()) << std::string(tok::spelling(tok_kw_with)); return std::make_shared(LexerCursorRange{LCur, LastToken->rCur()}, + std::move(KwWith), /*TokSemi*/ nullptr, std::move(With), /*E=*/nullptr); } + auto TokSemi = std::make_shared(ExpSemi.tok().range()); consume(); // ; auto E = parseExpr(); @@ -305,6 +309,7 @@ std::shared_ptr Parser::parseExprWith() { diagNullExpr(Diags, LastToken->rCur(), "with body"); return std::make_shared(LexerCursorRange{LCur, LastToken->rCur()}, + std::move(KwWith), std::move(TokSemi), std::move(With), std::move(E)); } diff --git a/libnixf/test/Basic/Nodes.cpp b/libnixf/test/Basic/Nodes.cpp index 0ed3c9e0f..385db1247 100644 --- a/libnixf/test/Basic/Nodes.cpp +++ b/libnixf/test/Basic/Nodes.cpp @@ -36,4 +36,21 @@ TEST(Node, InterpolateLiteralFalse) { ASSERT_FALSE(Parts.isLiteral()); } +TEST(Node, ExprCall_Children) { + auto Src = "foo bar baz"sv; + std::vector Diag; + auto Root = parse(Src, Diag); + + ASSERT_EQ(Root->children().size(), 3); +} + +TEST(Node, ExprString_Children) { + auto Src = R"("foo${baz}")"sv; + std::vector Diag; + auto Root = parse(Src, Diag); + + ASSERT_EQ(Root->children().size(), 1); + ASSERT_EQ(Root->children()[0]->children().size(), 1); +} + } // namespace