1 // Copyright (C) 2024 Free Software Foundation, Inc.
3 // This file is part of GCC.
5 // GCC is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU General Public License as published by the Free
7 // Software Foundation; either version 3, or (at your option) any later
10 // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 // You should have received a copy of the GNU General Public License
16 // along with GCC; see the file COPYING3. If not see
17 // <http://www.gnu.org/licenses/>.
19 #ifndef RUST_AST_BUILTIN_NODES_H
20 #define RUST_AST_BUILTIN_NODES_H
22 #include "rust-system.h"
31 // Definitions, from rustc's `FormatArgs` AST struct
32 // https://github.com/rust-lang/rust/blob/1be468815c/compiler/rustc_ast/src/format.rs
34 // format_args!("hello {abc:.xyz$}!!", abc="world");
35 // └──────────────────────────────────────────────┘
38 // format_args!("hello {abc:.xyz$}!!", abc="world");
42 // format_args!("hello {abc:.xyz$}!!", abc="world");
43 // └───────────────────┘
46 // format_args!("hello {abc:.xyz$}!!", abc="world");
47 // └────┘└─────────┘└┘
50 // format_args!("hello {abc:.xyz$}!!", abc="world");
54 // format_args!("hello {abc:.xyz$}!!", abc="world");
58 // format_args!("hello {abc:.xyz$}!!", abc="world");
60 // positions (could be names, numbers, empty, or `*`)
62 // FIXME: Merge with the class below this one?
63 class FormatArgumentKind
73 Identifier
&get_ident ()
75 rust_assert (kind
== Kind::Captured
|| kind
== Kind::Named
);
77 return ident
.value ();
80 FormatArgumentKind (Kind kind
, tl::optional
<Identifier
> ident
)
81 : kind (kind
), ident (ident
)
84 FormatArgumentKind (const FormatArgumentKind
&other
)
90 FormatArgumentKind
operator= (const FormatArgumentKind
&other
)
99 tl::optional
<Identifier
> ident
;
105 static FormatArgument
normal (std::unique_ptr
<Expr
> expr
)
107 return FormatArgument (FormatArgumentKind::Kind::Normal
, tl::nullopt
,
111 static FormatArgument
named (Identifier ident
, std::unique_ptr
<Expr
> expr
)
113 return FormatArgument (FormatArgumentKind::Kind::Named
, ident
,
117 static FormatArgument
captured (Identifier ident
, std::unique_ptr
<Expr
> expr
)
119 return FormatArgument (FormatArgumentKind::Kind::Captured
, ident
,
123 FormatArgument (const FormatArgument
&other
)
124 : kind (other
.kind
), expr (other
.expr
->clone_expr ())
127 FormatArgument
operator= (const FormatArgument
&other
)
130 expr
= other
.expr
->clone_expr ();
135 FormatArgumentKind
get_kind () const { return kind
; }
136 const Expr
&get_expr () const { return *expr
; }
139 FormatArgument (FormatArgumentKind::Kind kind
, tl::optional
<Identifier
> ident
,
140 std::unique_ptr
<Expr
> expr
)
141 : kind (FormatArgumentKind (kind
, ident
)), expr (std::move (expr
))
144 FormatArgumentKind kind
;
145 std::unique_ptr
<Expr
> expr
;
148 class FormatArguments
151 FormatArguments () {}
152 FormatArguments (FormatArguments
&&) = default;
153 FormatArguments (const FormatArguments
&other
)
155 args
= std::vector
<FormatArgument
> ();
156 args
.reserve (other
.args
.size ());
158 for (const auto &arg
: other
.args
)
159 args
.emplace_back (arg
);
162 FormatArguments
&operator= (const FormatArguments
&other
) = default;
164 void push (FormatArgument
&&elt
) { args
.emplace_back (std::move (elt
)); }
165 const FormatArgument
at (size_t idx
) const { return args
.at (idx
); }
168 std::vector
<FormatArgument
> args
;
171 // TODO: Format documentation better
172 // Having a separate AST node for `format_args!()` expansion allows some
173 // important optimizations which help reduce generated code a lot. For example,
174 // turning `format_args!("a {} {} {}", 15, "hey", 'a')` directly into
175 // `format_args!("a 15 hey a")`, since all arguments are literals. Or,
176 // flattening imbricated `format_args!()` calls: `format_args!("heyo {}",
177 // format_args!("result: {}", some_result))` -> `format_args!("heyo result: {}",
179 // FIXME: Move to rust-macro.h
180 class FormatArgs
: public Expr
189 FormatArgs (location_t loc
, Fmt::Pieces
&&template_str
,
190 FormatArguments
&&arguments
)
191 : loc (loc
), template_pieces (std::move (template_str
)),
192 arguments (std::move (arguments
))
195 FormatArgs (FormatArgs
&&other
) = default;
196 FormatArgs (const FormatArgs
&other
) = default;
197 FormatArgs
&operator= (const FormatArgs
&other
) = default;
199 void accept_vis (AST::ASTVisitor
&vis
) override
;
201 const Fmt::Pieces
&get_template () const { return template_pieces
; }
202 const FormatArguments
&get_arguments () const { return arguments
; }
203 virtual location_t
get_locus () const override
;
207 // FIXME: This probably needs to be a separate type - it is one in rustc's
208 // expansion of format_args!(). There is extra handling associated with it.
209 // we can maybe do that in rust-fmt.cc? in collect_pieces()? like do the
210 // transformation into something we can handle better
211 Fmt::Pieces template_pieces
;
212 FormatArguments arguments
;
214 bool marked_for_strip
= false;
217 virtual std::string
as_string () const override
;
218 virtual bool is_expr_without_block () const override
;
219 virtual void mark_for_strip () override
;
220 virtual bool is_marked_for_strip () const override
;
221 virtual std::vector
<Attribute
> &get_outer_attrs () override
;
222 virtual void set_outer_attrs (std::vector
<Attribute
>) override
;
223 virtual Expr
*clone_expr_impl () const override
;
229 #endif // ! RUST_AST_BUILTIN_NODES_H