aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust/expand
diff options
context:
space:
mode:
authorArthur Cohen <arthur.cohen@embecosm.com>2024-02-29 14:53:05 +0100
committerCohenArthur <arthur.cohen@embecosm.com>2024-03-19 17:37:38 +0000
commit36aeecfb22d42649b2b1101a96b1d389e439757c (patch)
tree8c4f82fbfe33cb2d8d22c390dd49e974f1cb6c39 /gcc/rust/expand
parent246b6316c0e1320cba90bae676675686890168a8 (diff)
downloadgcc-36aeecfb22d42649b2b1101a96b1d389e439757c.zip
gcc-36aeecfb22d42649b2b1101a96b1d389e439757c.tar.gz
gcc-36aeecfb22d42649b2b1101a96b1d389e439757c.tar.bz2
format-args: Add basic expansion of unnamed Display::fmt arguments.
gcc/rust/ChangeLog: * ast/rust-ast-builder.h: Rename AST::AstBuilder -> AST::Builder * ast/rust-ast-builder.cc: Likewise. * expand/rust-derive.cc: Use new AST::Builder name. * expand/rust-derive.h: Likewise. * ast/rust-builtin-ast-nodes.h: Add required getters. * expand/rust-expand-format-args.cc (format_arg): New. (get_trait_name): New. (expand_format_args): Properly expand basic format_args!() invocations. * expand/rust-expand-format-args.h (expand_format_args): Fix signature. * expand/rust-macro-builtins.cc (MacroBuiltin::format_args_handler): Call into expand_format_args().
Diffstat (limited to 'gcc/rust/expand')
-rw-r--r--gcc/rust/expand/rust-derive.cc2
-rw-r--r--gcc/rust/expand/rust-derive.h2
-rw-r--r--gcc/rust/expand/rust-expand-format-args.cc107
-rw-r--r--gcc/rust/expand/rust-expand-format-args.h5
-rw-r--r--gcc/rust/expand/rust-macro-builtins.cc23
5 files changed, 124 insertions, 15 deletions
diff --git a/gcc/rust/expand/rust-derive.cc b/gcc/rust/expand/rust-derive.cc
index e9927df..4177004 100644
--- a/gcc/rust/expand/rust-derive.cc
+++ b/gcc/rust/expand/rust-derive.cc
@@ -24,7 +24,7 @@ namespace Rust {
namespace AST {
DeriveVisitor::DeriveVisitor (location_t loc)
- : loc (loc), builder (AstBuilder (loc))
+ : loc (loc), builder (Builder (loc))
{}
std::unique_ptr<Item>
diff --git a/gcc/rust/expand/rust-derive.h b/gcc/rust/expand/rust-derive.h
index cbe5bbb..48f6594 100644
--- a/gcc/rust/expand/rust-derive.h
+++ b/gcc/rust/expand/rust-derive.h
@@ -41,7 +41,7 @@ protected:
DeriveVisitor (location_t loc);
location_t loc;
- AstBuilder builder;
+ Builder builder;
private:
// the 4 "allowed" visitors, which a derive-visitor can specify and override
diff --git a/gcc/rust/expand/rust-expand-format-args.cc b/gcc/rust/expand/rust-expand-format-args.cc
index 276ffd5..3f76344 100644
--- a/gcc/rust/expand/rust-expand-format-args.cc
+++ b/gcc/rust/expand/rust-expand-format-args.cc
@@ -17,27 +17,122 @@
// <http://www.gnu.org/licenses/>.
#include "rust-expand-format-args.h"
+#include "rust-ast-fragment.h"
+#include "rust-ast.h"
#include "rust-builtin-ast-nodes.h"
+#include "rust-ast-builder.h"
+#include "rust-diagnostics.h"
+#include "rust-expr.h"
+#include "rust-fmt.h"
+#include "rust-path.h"
+#include "rust-system.h"
+#include "rust-token.h"
namespace Rust {
+namespace Fmt {
+
+static std::unique_ptr<AST::Expr>
+format_arg (const AST::Builder &builder, std::unique_ptr<AST::Expr> &&to_format,
+ const std::string &trait)
+{
+ auto formatter_fn = std::unique_ptr<AST::Expr> (new AST::PathInExpression (
+ builder.path_in_expression ({"core", "fmt", trait, "fmt"})));
+
+ auto path = std::unique_ptr<AST::Expr> (new AST::PathInExpression (
+ builder.path_in_expression ({"core", "fmt", "ArgumentV1", "new"})));
+
+ auto args = std::vector<std::unique_ptr<AST::Expr>> ();
+ args.emplace_back (std::move (to_format));
+ args.emplace_back (std::move (formatter_fn));
+
+ return builder.call (std::move (path), std::move (args));
+}
+
+const std::string &
+get_trait_name (ffi::FormatSpec format_specifier)
+{
+ static const std::unordered_map<std::string, std::string> spec_map = {
+ {"", "Display"}, {"?", "Debug"}, {"e", "LowerExp"},
+ {"E", "UpperExp"}, {"o", "Octal"}, {"p", "Pointer"},
+ {"b", "Binary"}, {"x", "LowerHex"}, {"X", "UpperHex"},
+ };
+
+ auto it = spec_map.find (format_specifier.ty.to_string ());
+
+ if (it == spec_map.end ())
+ rust_unreachable ();
+
+ return it->second;
+}
tl::optional<AST::Fragment>
-expand_format_args (AST::FormatArgs &fmt)
+expand_format_args (AST::FormatArgs &fmt,
+ std::vector<std::unique_ptr<AST::Token>> &&tokens)
{
+ auto loc = fmt.get_locus ();
+ auto builder = AST::Builder (loc);
+ auto &arguments = fmt.get_arguments ();
+
+ auto static_pieces = std::vector<std::unique_ptr<AST::Expr>> ();
+ auto args
+ = std::vector<std::pair<std::unique_ptr<AST::Expr>, ffi::FormatSpec>> ();
+
for (const auto &node : fmt.get_template ().get_pieces ())
{
switch (node.tag)
{
- case Fmt::ffi::Piece::Tag::String:
- // rust_debug ("[ARTHUR]: %s", node.string._0.c_str ());
+ case ffi::Piece::Tag::String:
+ static_pieces.emplace_back (
+ builder.literal_string (node.string._0.to_string ()));
+ break;
+ case ffi::Piece::Tag::NextArgument: {
+ auto next_argument = node.next_argument._0;
+ switch (node.next_argument._0.position.tag)
+ {
+ case ffi::Position::Tag::ArgumentImplicitlyIs: {
+ auto idx = next_argument.position.argument_implicitly_is._0;
+ auto trait = next_argument.format;
+ auto arg = arguments.at (idx);
+
+ // FIXME(Arthur): This API sucks
+ rust_assert (arg.get_kind ().kind
+ == AST::FormatArgumentKind::Kind::Normal);
- case Fmt::ffi::Piece::Tag::NextArgument:
- rust_debug ("[ARTHUR]: NextArgument");
+ args.push_back ({arg.get_expr ().clone_expr (), trait});
+ }
+ break;
+ case ffi::Position::Tag::ArgumentIs:
+ case ffi::Position::Tag::ArgumentNamed:
+ rust_sorry_at (loc, "unhandled argument position specifier");
+ break;
+ }
+ }
break;
}
}
- return tl::nullopt;
+ auto args_array = std::vector<std::unique_ptr<AST::Expr>> ();
+ for (auto &&arg : args)
+ args_array.emplace_back (format_arg (builder,
+ builder.ref (std::move (arg.first)),
+ get_trait_name (arg.second)));
+
+ auto pieces = builder.ref (builder.array (std::move (static_pieces)));
+ auto args_slice = builder.ref (builder.array (std::move (args_array)));
+
+ auto final_path = make_unique<AST::PathInExpression> (
+ builder.path_in_expression ({"core", "fmt", "Arguments", "new_v1"}));
+ auto final_args = std::vector<std::unique_ptr<AST::Expr>> ();
+ final_args.emplace_back (std::move (pieces));
+ final_args.emplace_back (std::move (args_slice));
+
+ auto final_call
+ = builder.call (std::move (final_path), std::move (final_args));
+
+ auto node = AST::SingleASTNode (std::move (final_call));
+
+ return AST::Fragment ({node}, std::move (tokens));
}
+} // namespace Fmt
} // namespace Rust
diff --git a/gcc/rust/expand/rust-expand-format-args.h b/gcc/rust/expand/rust-expand-format-args.h
index 1481f36..0a17de5 100644
--- a/gcc/rust/expand/rust-expand-format-args.h
+++ b/gcc/rust/expand/rust-expand-format-args.h
@@ -23,10 +23,13 @@
#include "rust-ast-fragment.h"
namespace Rust {
+namespace Fmt {
tl::optional<AST::Fragment>
-expand_format_args (AST::FormatArgs &fmt);
+expand_format_args (AST::FormatArgs &fmt,
+ std::vector<std::unique_ptr<AST::Token>> &&tokens);
+} // namespace Fmt
} // namespace Rust
#endif //! RUST_EXPAND_FORMAT_ARGS_H
diff --git a/gcc/rust/expand/rust-macro-builtins.cc b/gcc/rust/expand/rust-macro-builtins.cc
index 8cf3205..112713a 100644
--- a/gcc/rust/expand/rust-macro-builtins.cc
+++ b/gcc/rust/expand/rust-macro-builtins.cc
@@ -20,6 +20,7 @@
#include "libproc_macro_internal/tokenstream.h"
#include "rust-ast-full-decls.h"
#include "rust-builtin-ast-nodes.h"
+#include "rust-expand-format-args.h"
#include "rust-token-converter.h"
#include "rust-system.h"
#include "rust-macro-builtins.h"
@@ -1102,13 +1103,23 @@ MacroBuiltin::format_args_handler (location_t invoc_locus,
// TODO: we now need to take care of creating `unfinished_literal`? this is
// for creating the `template`
- auto fmt_args_node = new AST::FormatArgs (invoc_locus, std::move (pieces),
- std::move (input->args));
- auto node = std::unique_ptr<AST::Expr> (fmt_args_node);
- auto single_node = AST::SingleASTNode (std::move (node));
+ auto fmt_args_node = AST::FormatArgs (invoc_locus, std::move (pieces),
+ std::move (input->args));
- return AST::Fragment ({std::move (single_node)},
- invoc.get_delim_tok_tree ().to_token_stream ());
+ auto expanded
+ = Fmt::expand_format_args (fmt_args_node,
+ invoc.get_delim_tok_tree ().to_token_stream ());
+
+ if (!expanded.has_value ())
+ return AST::Fragment::create_error ();
+
+ return *expanded;
+
+ // auto node = std::unique_ptr<AST::Expr> (fmt_args_node);
+ // auto single_node = AST::SingleASTNode (std::move (node));
+
+ // return AST::Fragment ({std::move (single_node)},
+ // invoc.get_delim_tok_tree ().to_token_stream ());
}
tl::optional<AST::Fragment>