gcc/rust/ChangeLog: * expand/rust-macro-builtins.cc (format_args_maker): New function. (try_expand_many_expr): Add comment about reworking function. (MacroBuiltin::format_args_handler): Add newline parameter. * expand/rust-macro-builtins.h: Likewise. --- gcc/rust/expand/rust-macro-builtins.cc | 69 +++++++++++++++++++++++--- gcc/rust/expand/rust-macro-builtins.h | 4 +- 2 files changed, 65 insertions(+), 8 deletions(-)
diff --git a/gcc/rust/expand/rust-macro-builtins.cc b/gcc/rust/expand/rust-macro-builtins.cc index f103759acdd..9e6716c5975 100644 --- a/gcc/rust/expand/rust-macro-builtins.cc +++ b/gcc/rust/expand/rust-macro-builtins.cc @@ -17,6 +17,8 @@ // <http://www.gnu.org/licenses/>. #include "libproc_macro_internal/tokenstream.h" +#include "rust-ast-full-decls.h" +#include "rust-builtin-ast-nodes.h" #include "rust-token-converter.h" #include "rust-system.h" #include "rust-macro-builtins.h" @@ -78,6 +80,14 @@ const BiMap<std::string, BuiltinMacro> MacroBuiltin::builtins = {{ }}; +AST::MacroTranscriberFunc +format_args_maker (AST::FormatArgs::Newline nl) +{ + return [nl] (location_t loc, AST::MacroInvocData &invoc) { + return MacroBuiltin::format_args_handler (loc, invoc, nl); + }; +} + std::unordered_map<std::string, AST::MacroTranscriberFunc> MacroBuiltin::builtin_transcribers = { {"assert", MacroBuiltin::assert_handler}, @@ -92,10 +102,10 @@ std::unordered_map<std::string, AST::MacroTranscriberFunc> {"env", MacroBuiltin::env_handler}, {"cfg", MacroBuiltin::cfg_handler}, {"include", MacroBuiltin::include_handler}, - {"format_args", MacroBuiltin::format_args_handler}, + {"format_args", format_args_maker (AST::FormatArgs::Newline::No)}, + {"format_args_nl", format_args_maker (AST::FormatArgs::Newline::Yes)}, /* Unimplemented macro builtins */ {"option_env", MacroBuiltin::sorry}, - {"format_args_nl", MacroBuiltin::sorry}, {"concat_idents", MacroBuiltin::sorry}, {"module_path", MacroBuiltin::sorry}, {"asm", MacroBuiltin::sorry}, @@ -286,6 +296,8 @@ try_expand_many_expr (Parser<MacroInvocLexer> &parser, and return the LiteralExpr for it. Allow for an optional trailing comma, but otherwise enforce that these are the only tokens. */ +// FIXME(Arthur): This function needs a rework - it should not emit errors, it +// should probably be smaller std::unique_ptr<AST::Expr> parse_single_string_literal (BuiltinMacro kind, AST::DelimTokenTree &invoc_token_tree, @@ -946,17 +958,31 @@ MacroBuiltin::stringify_handler (location_t invoc_locus, tl::optional<AST::Fragment> MacroBuiltin::format_args_handler (location_t invoc_locus, - AST::MacroInvocData &invoc) + AST::MacroInvocData &invoc, + AST::FormatArgs::Newline nl) { + // Remove the delimiters from the macro invocation: + // the invoc data for `format_args!(fmt, arg1, arg2)` is `(fmt, arg1, arg2)`, + // so we pop the front and back to remove the parentheses (or curly brackets, + // or brackets) auto tokens = invoc.get_delim_tok_tree ().to_token_stream (); tokens.erase (tokens.begin ()); tokens.pop_back (); - std::stringstream stream; - for (const auto &tok : tokens) - stream << tok->as_string () << ' '; + auto append_newline = nl == AST::FormatArgs::Newline::Yes ? true : false; + auto fmt_arg + = parse_single_string_literal (append_newline ? BuiltinMacro::FormatArgsNl + : BuiltinMacro::FormatArgs, + invoc.get_delim_tok_tree (), invoc_locus, + invoc.get_expander ()); - rust_debug ("[ARTHU]: `%s`", stream.str ().c_str ()); + if (!fmt_arg->is_literal ()) + { + rust_sorry_at ( + invoc_locus, + "cannot yet use eager macro invocations as format strings"); + return AST::Fragment::create_empty (); + } // FIXME: We need to handle this // // if it is not a literal, it's an eager macro invocation - return it @@ -967,8 +993,37 @@ MacroBuiltin::format_args_handler (location_t invoc_locus, // token_tree.to_token_stream ()); // } + auto fmt_str = static_cast<AST::LiteralExpr &> (*fmt_arg.get ()); + + // Switch on the format string to know if the string is raw or cooked + switch (fmt_str.get_lit_type ()) + { + // case AST::Literal::RAW_STRING: + case AST::Literal::STRING: + break; + case AST::Literal::CHAR: + case AST::Literal::BYTE: + case AST::Literal::BYTE_STRING: + case AST::Literal::INT: + case AST::Literal::FLOAT: + case AST::Literal::BOOL: + case AST::Literal::ERROR: + rust_unreachable (); + } + + std::stringstream stream; + for (const auto &tok : tokens) + stream << tok->as_string () << ' '; + + rust_debug ("[ARTHUR]: `%s`", stream.str ().c_str ()); + auto pieces = Fmt::Pieces::collect (stream.str ()); + // TODO: + // do the transformation into an AST::FormatArgs node + // return that + // expand it during lowering + return AST::Fragment::create_empty (); } diff --git a/gcc/rust/expand/rust-macro-builtins.h b/gcc/rust/expand/rust-macro-builtins.h index 1d6b30b5933..62961561716 100644 --- a/gcc/rust/expand/rust-macro-builtins.h +++ b/gcc/rust/expand/rust-macro-builtins.h @@ -20,6 +20,7 @@ #define RUST_MACRO_BUILTINS_H #include "rust-ast.h" +#include "rust-builtin-ast-nodes.h" #include "rust-ast-fragment.h" #include "rust-location.h" #include "bi-map.h" @@ -158,7 +159,8 @@ public: AST::MacroInvocData &invoc); static tl::optional<AST::Fragment> - format_args_handler (location_t invoc_locus, AST::MacroInvocData &invoc); + format_args_handler (location_t invoc_locus, AST::MacroInvocData &invoc, + AST::FormatArgs::Newline nl); static tl::optional<AST::Fragment> sorry (location_t invoc_locus, AST::MacroInvocData &invoc); -- 2.45.2