diff options
author | omkar-mohanty <franzohouser@gmail.com> | 2023-02-16 10:10:24 +0530 |
---|---|---|
committer | CohenArthur <arthur.cohen@embecosm.com> | 2023-02-28 12:45:10 +0000 |
commit | 5c2ed969a2d58217797cf2e938c0f833a50d7cb4 (patch) | |
tree | 1d77bc7d33d4817231eed267165a4908e20aa530 /gcc/rust | |
parent | ce43f55e9976929f9ff2388c8971a65afd24e26d (diff) | |
download | gcc-5c2ed969a2d58217797cf2e938c0f833a50d7cb4.zip gcc-5c2ed969a2d58217797cf2e938c0f833a50d7cb4.tar.gz gcc-5c2ed969a2d58217797cf2e938c0f833a50d7cb4.tar.bz2 |
Implement and test include_str eager expansion
builtins: Implement eager expansion for include_str!()
gcc/rust/ChangeLog:
* expand/rust-macro-builtins.cc
(MacroBuiltin::include_str_handler): eager expansion
(make_macro_path_str): macto to string
(parse_single_string_literal): check for eager invocation
(MacroBuiltin::assert_handler): eager expansion
(MacroBuiltin::include_bytes_handler): eager expansion
(MacroBuiltin::include_str_handler): eager expansion
(MacroBuiltin::compile_error_handler): eager expansion
(MacroBuiltin::include_handler): eager expansion
gcc/testsuite/ChangeLog:
* rust/compile/builtin_macro_eager3.rs: New test.
Signed-off-by: omkar-mohanty <franzohouser@gmail.com>
Diffstat (limited to 'gcc/rust')
-rw-r--r-- | gcc/rust/expand/rust-macro-builtins.cc | 160 |
1 files changed, 110 insertions, 50 deletions
diff --git a/gcc/rust/expand/rust-macro-builtins.cc b/gcc/rust/expand/rust-macro-builtins.cc index cf90b38..d7f1578 100644 --- a/gcc/rust/expand/rust-macro-builtins.cc +++ b/gcc/rust/expand/rust-macro-builtins.cc @@ -16,42 +16,24 @@ // along with GCC; see the file COPYING3. If not see // <http://www.gnu.org/licenses/>. +#include "rust-system.h" #include "rust-macro-builtins.h" +#include "rust-ast-fragment.h" #include "rust-ast.h" +#include "rust-attribute-visitor.h" #include "rust-diagnostics.h" +#include "rust-early-name-resolver.h" #include "rust-expr.h" -#include "rust-session-manager.h" -#include "rust-macro-invoc-lexer.h" #include "rust-lex.h" +#include "rust-macro-invoc-lexer.h" +#include "rust-macro.h" #include "rust-parse.h" -#include "rust-early-name-resolver.h" -#include "rust-attribute-visitor.h" +#include "rust-session-manager.h" namespace Rust { namespace { - -/** - * Shorthand function for creating unique_ptr tokens - */ -static std::unique_ptr<AST::Token> -make_token (const TokenPtr tok) -{ - return std::unique_ptr<AST::Token> (new AST::Token (tok)); -} - -std::unique_ptr<AST::Expr> -make_string (Location locus, std::string value) -{ - return std::unique_ptr<AST::Expr> ( - new AST::LiteralExpr (value, AST::Literal::STRING, - PrimitiveCoreType::CORETYPE_STR, {}, locus)); -} - -// TODO: Is this correct? -static AST::Fragment -make_eager_builtin_invocation ( - AST::BuiltinMacro kind, Location locus, AST::DelimTokenTree arguments, - std::vector<std::unique_ptr<AST::MacroInvocation>> &&pending_invocations) +std::string +make_macro_path_str (AST::BuiltinMacro kind) { std::string path_str; @@ -93,6 +75,48 @@ make_eager_builtin_invocation ( break; } + return path_str; +} + +static std::vector<std::unique_ptr<AST::MacroInvocation>> +check_for_eager_invocations ( + std::vector<std::unique_ptr<AST::Expr>> &expressions) +{ + std::vector<std::unique_ptr<AST::MacroInvocation>> pending; + + for (auto &expr : expressions) + if (expr->get_ast_kind () == AST::Kind::MACRO_INVOCATION) + pending.emplace_back (std::unique_ptr<AST::MacroInvocation> ( + static_cast<AST::MacroInvocation *> (expr->clone_expr ().release ()))); + + return pending; +} + +/** + * Shorthand function for creating unique_ptr tokens + */ +static std::unique_ptr<AST::Token> +make_token (const TokenPtr tok) +{ + return std::unique_ptr<AST::Token> (new AST::Token (tok)); +} + +std::unique_ptr<AST::Expr> +make_string (Location locus, std::string value) +{ + return std::unique_ptr<AST::Expr> ( + new AST::LiteralExpr (value, AST::Literal::STRING, + PrimitiveCoreType::CORETYPE_STR, {}, locus)); +} + +// TODO: Is this correct? +static AST::Fragment +make_eager_builtin_invocation ( + AST::BuiltinMacro kind, Location locus, AST::DelimTokenTree arguments, + std::vector<std::unique_ptr<AST::MacroInvocation>> &&pending_invocations) +{ + auto path_str = make_macro_path_str (kind); + std::unique_ptr<AST::Expr> node = AST::MacroInvocation::Builtin ( kind, AST::MacroInvocData (AST::SimplePath ( @@ -195,8 +219,9 @@ 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. */ -std::unique_ptr<AST::LiteralExpr> -parse_single_string_literal (AST::DelimTokenTree &invoc_token_tree, +std::unique_ptr<AST::Expr> +parse_single_string_literal (AST::BuiltinMacro kind, + AST::DelimTokenTree &invoc_token_tree, Location invoc_locus, MacroExpander *expander) { MacroInvocLexer lex (invoc_token_tree.to_token_stream ()); @@ -205,6 +230,7 @@ parse_single_string_literal (AST::DelimTokenTree &invoc_token_tree, auto last_token_id = macro_end_token (invoc_token_tree, parser); std::unique_ptr<AST::LiteralExpr> lit_expr = nullptr; + std::unique_ptr<AST::MacroInvocation> macro_invoc = nullptr; if (parser.peek_current_token ()->get_id () == STRING_LITERAL) { @@ -219,11 +245,42 @@ parse_single_string_literal (AST::DelimTokenTree &invoc_token_tree, else if (parser.peek_current_token ()->get_id () == last_token_id) rust_error_at (invoc_locus, "macro takes 1 argument"); else - rust_error_at (invoc_locus, "argument must be a string literal"); + { + macro_invoc = parser.parse_macro_invocation (AST::AttrVec ()); + + parser.maybe_skip_token (COMMA); + if (parser.peek_current_token ()->get_id () != last_token_id) + { + lit_expr = nullptr; + rust_error_at (invoc_locus, "macro takes 1 argument"); + } + + if (macro_invoc != nullptr) + { + auto path_str = make_macro_path_str (kind); + + auto pending_invocations + = std::vector<std::unique_ptr<AST::MacroInvocation>> (); + + pending_invocations.push_back (std::move (macro_invoc)); + + return AST::MacroInvocation::Builtin ( + kind, + AST::MacroInvocData (AST::SimplePath ({AST::SimplePathSegment ( + path_str, invoc_locus)}), + std::move (invoc_token_tree)), + {}, invoc_locus, std::move (pending_invocations)); + } + else + { + rust_error_at (invoc_locus, "argument must be a string literal or a " + "macro which expands to a string"); + } + } parser.skip_token (last_token_id); - return lit_expr; + return std::unique_ptr<AST::Expr> (std::move (lit_expr)); } /* Treat PATH as a path relative to the source file currently being @@ -278,7 +335,7 @@ load_file_bytes (const char *filename) } // namespace AST::Fragment -MacroBuiltin::assert_handler (Location, AST::MacroInvocData &) +MacroBuiltin::assert_handler (Location invoc_locus, AST::MacroInvocData &invoc) { rust_debug ("assert!() called"); @@ -323,11 +380,14 @@ MacroBuiltin::include_bytes_handler (Location invoc_locus, /* Get target filename from the macro invocation, which is treated as a path relative to the include!-ing file (currently being compiled). */ auto lit_expr - = parse_single_string_literal (invoc.get_delim_tok_tree (), invoc_locus, + = parse_single_string_literal (AST::BuiltinMacro::IncludeBytes, + invoc.get_delim_tok_tree (), invoc_locus, invoc.get_expander ()); if (lit_expr == nullptr) return AST::Fragment::create_error (); + rust_assert (lit_expr->is_literal ()); + std::string target_filename = source_relative_path (lit_expr->as_string (), invoc_locus); @@ -379,11 +439,19 @@ MacroBuiltin::include_str_handler (Location invoc_locus, /* Get target filename from the macro invocation, which is treated as a path relative to the include!-ing file (currently being compiled). */ auto lit_expr - = parse_single_string_literal (invoc.get_delim_tok_tree (), invoc_locus, + = parse_single_string_literal (AST::BuiltinMacro::IncludeStr, + invoc.get_delim_tok_tree (), invoc_locus, invoc.get_expander ()); if (lit_expr == nullptr) return AST::Fragment::create_error (); + if (!lit_expr->is_literal ()) + { + auto token_tree = invoc.get_delim_tok_tree (); + return AST::Fragment ({AST::SingleASTNode (std::move (lit_expr))}, + token_tree.to_token_stream ()); + } + std::string target_filename = source_relative_path (lit_expr->as_string (), invoc_locus); @@ -453,31 +521,20 @@ MacroBuiltin::compile_error_handler (Location invoc_locus, AST::MacroInvocData &invoc) { auto lit_expr - = parse_single_string_literal (invoc.get_delim_tok_tree (), invoc_locus, + = parse_single_string_literal (AST::BuiltinMacro::CompileError, + invoc.get_delim_tok_tree (), invoc_locus, invoc.get_expander ()); if (lit_expr == nullptr) return AST::Fragment::create_error (); + rust_assert (lit_expr->is_literal ()); + std::string error_string = lit_expr->as_string (); rust_error_at (invoc_locus, "%s", error_string.c_str ()); return AST::Fragment::create_error (); } -static std::vector<std::unique_ptr<AST::MacroInvocation>> -check_for_eager_invocations ( - std::vector<std::unique_ptr<AST::Expr>> &expressions) -{ - std::vector<std::unique_ptr<AST::MacroInvocation>> pending; - - for (auto &expr : expressions) - if (expr->get_ast_kind () == AST::Kind::MACRO_INVOCATION) - pending.emplace_back (std::unique_ptr<AST::MacroInvocation> ( - static_cast<AST::MacroInvocation *> (expr->clone_expr ().release ()))); - - return pending; -} - /* Expand builtin macro concat!(), which joins all the literal parameters into a string with no delimiter. */ @@ -707,11 +764,14 @@ MacroBuiltin::include_handler (Location invoc_locus, AST::MacroInvocData &invoc) /* Get target filename from the macro invocation, which is treated as a path relative to the include!-ing file (currently being compiled). */ auto lit_expr - = parse_single_string_literal (invoc.get_delim_tok_tree (), invoc_locus, + = parse_single_string_literal (AST::BuiltinMacro::Include, + invoc.get_delim_tok_tree (), invoc_locus, invoc.get_expander ()); if (lit_expr == nullptr) return AST::Fragment::create_error (); + rust_assert (lit_expr->is_literal ()); + std::string filename = source_relative_path (lit_expr->as_string (), invoc_locus); auto target_filename |