@@ -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 ();
}
@@ -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);