diff options
author | Arthur Cohen <arthur.cohen@embecosm.com> | 2024-02-29 14:53:05 +0100 |
---|---|---|
committer | CohenArthur <arthur.cohen@embecosm.com> | 2024-03-19 17:37:38 +0000 |
commit | 36aeecfb22d42649b2b1101a96b1d389e439757c (patch) | |
tree | 8c4f82fbfe33cb2d8d22c390dd49e974f1cb6c39 /gcc/rust/expand | |
parent | 246b6316c0e1320cba90bae676675686890168a8 (diff) | |
download | gcc-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.cc | 2 | ||||
-rw-r--r-- | gcc/rust/expand/rust-derive.h | 2 | ||||
-rw-r--r-- | gcc/rust/expand/rust-expand-format-args.cc | 107 | ||||
-rw-r--r-- | gcc/rust/expand/rust-expand-format-args.h | 5 | ||||
-rw-r--r-- | gcc/rust/expand/rust-macro-builtins.cc | 23 |
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> |