From b9501cbe2624a80365e33550fc92035620a64e7b Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Wed, 18 Jan 2023 12:23:03 +0100 Subject: [PATCH] macro: Allow builtin `MacroInvocation`s within the AST This commit turns AST::MacroInvocation into a sum type. The class can now represent a regular macro invocation (lazily expanded) or a builtin one (eagerly expanded) gcc/rust/ChangeLog: * expand/rust-macro-builtins.cc (make_macro_invocation): Add short hand function for returning fragments containing macro invocations. (MacroBuiltin::compile_error_handler): Add explanation for eager invocation --- gcc/rust/expand/rust-macro-builtins.cc | 72 +++++++++++++++++++++++++- 1 file changed, 71 insertions(+), 1 deletion(-) diff --git a/gcc/rust/expand/rust-macro-builtins.cc b/gcc/rust/expand/rust-macro-builtins.cc index f6ddb1a803ef..11b5d5fbc9dd 100644 --- a/gcc/rust/expand/rust-macro-builtins.cc +++ b/gcc/rust/expand/rust-macro-builtins.cc @@ -37,8 +37,39 @@ make_string (Location locus, std::string value) PrimitiveCoreType::CORETYPE_STR, {}, locus)); } -/* Match the end token of a macro given the start delimiter of the macro */ +// TODO: Is this correct? +static std::unique_ptr +make_macro_invocation (AST::BuiltinMacro kind, AST::DelimTokenTree arguments) +{ + std::string path_str; + + switch (kind) + { + case AST::BuiltinMacro::Assert: + case AST::BuiltinMacro::File: + case AST::BuiltinMacro::Line: + case AST::BuiltinMacro::Column: + case AST::BuiltinMacro::IncludeBytes: + case AST::BuiltinMacro::IncludeStr: + case AST::BuiltinMacro::CompileError: + case AST::BuiltinMacro::Concat: + path_str = "concat"; + break; + case AST::BuiltinMacro::Env: + case AST::BuiltinMacro::Cfg: + case AST::BuiltinMacro::Include: + break; + } + return AST::MacroInvocation::builtin ( + kind, + AST::MacroInvocData (AST::SimplePath ( + {AST::SimplePathSegment (path_str, Location ())}), + std::move (arguments)), + {}, Location ()); +} + +/* Match the end token of a macro given the start delimiter of the macro */ static inline TokenId macro_end_token (AST::DelimTokenTree &invoc_token_tree, Parser &parser) @@ -386,6 +417,45 @@ MacroBuiltin::compile_error_handler (Location invoc_locus, /* Expand builtin macro concat!(), which joins all the literal parameters into a string with no delimiter. */ +// This is a weird one. We want to do something where, if something cannot be +// expanded yet (i.e. macro invocation?) we return the whole MacroInvocation +// node again but expanded as much as possible. +// Is that possible? How do we do that? +// +// Let's take a few examples: +// +// 1. concat!(1, 2, true); +// 2. concat!(a!(), 2, true); +// 3. concat!(concat!(1, false), 2, true); +// 4. concat!(concat!(1, a!()), 2, true); +// +// 1. We simply want to return the new fragment: "12true" +// 2. We want to return `concat!(a_expanded, 2, true)` as a fragment +// 3. We want to return `concat!(1, false, 2, true)` +// 4. We want to return `concat!(concat!(1, a_expanded), 2, true); +// +// How do we do that? +// +// For each (un)expanded fragment: we check if it is expanded fully +// +// 1. What is expanded fully? +// 2. How to check? +// +// If it is expanded fully and not a literal, then we error out. +// Otherwise we simply emplace it back and keep going. +// +// In the second case, we must mark that this concat invocation still has some +// expansion to do: This allows us to return a `MacroInvocation { ... }` as an +// AST fragment, instead of a completed string. +// +// This means that we must change all the `try_expand_many_*` APIs and so on to +// return some sort of index or way to signify that we might want to reuse some +// bits and pieces of the original token tree. +// +// Now, before that: How do we resolve the names used in a builtin macro +// invocation? +// Do we split the two passes of parsing the token tree and then expanding it? +// Can we do that easily? AST::Fragment MacroBuiltin::concat_handler (Location invoc_locus, AST::MacroInvocData &invoc) { -- 2.47.2