// <http://www.gnu.org/licenses/>.
#include "rust-expand-visitor.h"
+#include "rust-proc-macro.h"
#include "rust-attributes.h"
#include "rust-ast.h"
#include "rust-type.h"
void
ExpandVisitor::expand_outer_attribute (T &item, AST::SimplePath &path)
{
- // FIXME: Implement outer attribute expansion
+ // FIXME: Retrieve path from segments + local use statements instead of string
+ proc_expander.expand_attribute_proc_macro (item, path);
}
template <typename T>
void
ExpandVisitor::expand_inner_attribute (T &item, AST::SimplePath &path)
{
- // TODO: Warn about instability ?
- // FIXME: Implement expansion for that particular path
+ // FIXME: Retrieve path from segments + local use statements instead of string
+ proc_expander.expand_attribute_proc_macro (item, path);
}
template <typename T>
#include "rust-ast-visitor.h"
#include "rust-macro-expand.h"
+#include "rust-proc-macro.h"
namespace Rust {
class ExpandVisitor : public AST::ASTVisitor
{
public:
- ExpandVisitor (MacroExpander &expander) : expander (expander) {}
+ ExpandVisitor (MacroExpander &expander, ProcMacroExpander &proc_expander)
+ : expander (expander), proc_expander (proc_expander)
+ {}
/* Expand all of the macro invocations currently contained in a crate */
void go (AST::Crate &crate);
private:
MacroExpander &expander;
+ ProcMacroExpander &proc_expander;
};
} // namespace Rust
array->macros + array->length);
}
+void
+ProcMacroExpander::import_proc_macros (std::string extern_crate)
+{
+ auto path = session.extern_crates.find (extern_crate);
+ if (path == session.extern_crates.end ())
+ {
+ // Extern crate path is not available.
+ // FIXME: Emit error
+ rust_error_at (Location (), "Cannot find requested proc macro crate");
+ gcc_unreachable ();
+ }
+ auto macros = load_macros (path->second);
+
+ std::string prefix = extern_crate + "::";
+ for (auto ¯o : macros)
+ {
+ switch (macro.tag)
+ {
+ case ProcMacro::CUSTOM_DERIVE:
+ rust_debug ("Found one derive proc macro.");
+ mappings->insert_derive_proc_macro (
+ std::make_pair (extern_crate,
+ macro.payload.custom_derive.trait_name),
+ macro.payload.custom_derive);
+ break;
+ case ProcMacro::ATTR:
+ rust_debug ("Found one attribute proc macro.");
+ mappings->insert_attribute_proc_macro (
+ std::make_pair (extern_crate, macro.payload.attribute.name),
+ macro.payload.attribute);
+ break;
+ case ProcMacro::BANG:
+ rust_debug ("Found one bang proc macro.");
+ mappings->insert_bang_proc_macro (
+ std::make_pair (extern_crate, macro.payload.bang.name),
+ macro.payload.bang);
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ }
+}
+
} // namespace Rust
#ifndef RUST_PROC_MACRO_H
#define RUST_PROC_MACRO_H
+#include <string>
+#include "rust-hir-map.h"
+#include "rust-name-resolver.h"
+#include "rust-session-manager.h"
+#include "rust-ast.h"
+#include "rust-ast-collector.h"
+#include "rust-token-converter.h"
#include "libproc_macro/proc_macro.h"
namespace Rust {
const std::vector<ProcMacro::Procmacro>
load_macros (std::string path);
+class ProcMacroExpander
+{
+public:
+ ProcMacroExpander (Session &session)
+ : session (session), has_changed_flag (false),
+ resolver (Resolver::Resolver::get ()),
+ mappings (Analysis::Mappings::get ())
+
+ {}
+
+ ~ProcMacroExpander () = default;
+
+ void import_proc_macros (std::string extern_crate);
+
+ template <typename T>
+ void expand_derive_proc_macro (T &item, std::string &trait_name)
+ {}
+
+ template <typename T>
+ void expand_bang_proc_macro (T &item, AST::SimplePath &path)
+ {}
+
+ template <typename T>
+ void expand_attribute_proc_macro (T &item, AST::SimplePath &path)
+ {
+ ProcMacro::Attribute macro;
+
+ std::string crate = path.get_segments ()[0].get_segment_name ();
+ std::string name = path.get_segments ()[1].get_segment_name ();
+ if (!mappings->lookup_attribute_proc_macro (std::make_pair (crate, name),
+ macro))
+ {
+ // FIXME: Resolve this path segment instead of taking it directly.
+ import_proc_macros (crate);
+ }
+
+ if (!mappings->lookup_attribute_proc_macro (std::make_pair (crate, name),
+ macro))
+ {
+ rust_error_at (Location (), "procedural macro %s not found",
+ name.c_str ());
+ rust_assert (false);
+ }
+ // FIXME: Attach result back to the ast
+ std::vector<TokenPtr> tokens;
+ AST::TokenCollector collector (tokens);
+
+ collector.visit (item);
+
+ std::vector<const_TokenPtr> vec;
+ for (auto i : collector.collect_tokens ())
+ {
+ vec.push_back (std::const_pointer_cast<Token> (i));
+ }
+
+ // FIXME: Handle attributes
+ macro.macro (ProcMacro::TokenStream::make_tokenstream (), convert (vec));
+ }
+
+ bool has_changed () const { return has_changed_flag; }
+
+ void reset_changed_state () { has_changed_flag = false; }
+
+private:
+ Session &session;
+ bool has_changed_flag;
+
+public:
+ Resolver::Resolver *resolver;
+ Analysis::Mappings *mappings;
+};
+
} // namespace Rust
#endif /* ! RUST_PROC_MACRO_H */
/* expand by calling cxtctxt object's monotonic_expander's expand_crate
* method. */
MacroExpander expander (crate, cfg, *this);
+ ProcMacroExpander proc_expander (*this);
while (!fixed_point_reached && iterations < cfg.recursion_limit)
{
CfgStrip ().go (crate);
Resolver::EarlyNameResolver ().go (crate);
- ExpandVisitor (expander).go (crate);
+ ExpandVisitor (expander, proc_expander).go (crate);
fixed_point_reached = !expander.has_changed ();
expander.reset_changed_state ();
{"rustc_builtin_macro", EXPANSION},
{"path", EXPANSION},
{"macro_use", NAME_RESOLUTION},
+ {"macro_export", NAME_RESOLUTION},
// FIXME: This is not implemented yet, see
// https://github.com/Rust-GCC/gccrs/issues/1475
{"target_feature", CODE_GENERATION},
return exportedMacros;
}
+void
+Mappings::insert_derive_proc_macro (
+ std::pair<std::string, std::string> hierarchy, ProcMacro::CustomDerive macro)
+{
+ auto it = procmacroDeriveMappings.find (hierarchy);
+ rust_assert (it == procmacroDeriveMappings.end ());
+
+ procmacroDeriveMappings[hierarchy] = macro;
+}
+
+void
+Mappings::insert_bang_proc_macro (std::pair<std::string, std::string> hierarchy,
+ ProcMacro::Bang macro)
+{
+ auto it = procmacroBangMappings.find (hierarchy);
+ rust_assert (it == procmacroBangMappings.end ());
+
+ procmacroBangMappings[hierarchy] = macro;
+}
+
+void
+Mappings::insert_attribute_proc_macro (
+ std::pair<std::string, std::string> hierarchy, ProcMacro::Attribute macro)
+{
+ auto it = procmacroAttributeMappings.find (hierarchy);
+ rust_assert (it == procmacroAttributeMappings.end ());
+
+ procmacroAttributeMappings[hierarchy] = macro;
+}
+
+bool
+Mappings::lookup_derive_proc_macro (
+ std::pair<std::string, std::string> hierarchy, ProcMacro::CustomDerive ¯o)
+{
+ auto it = procmacroDeriveMappings.find (hierarchy);
+ if (it == procmacroDeriveMappings.end ())
+ return false;
+
+ macro = it->second;
+ return true;
+}
+
+bool
+Mappings::lookup_bang_proc_macro (std::pair<std::string, std::string> hierarchy,
+ ProcMacro::Bang ¯o)
+{
+ auto it = procmacroBangMappings.find (hierarchy);
+ if (it == procmacroBangMappings.end ())
+ return false;
+
+ macro = it->second;
+ return true;
+}
+
+bool
+Mappings::lookup_attribute_proc_macro (
+ std::pair<std::string, std::string> hierarchy, ProcMacro::Attribute ¯o)
+{
+ auto it = procmacroAttributeMappings.find (hierarchy);
+ if (it == procmacroAttributeMappings.end ())
+ return false;
+
+ macro = it->second;
+ return true;
+}
+
void
Mappings::insert_visibility (NodeId id, Privacy::ModuleVisibility visibility)
{
#include "rust-hir-full-decls.h"
#include "rust-lang-item.h"
#include "rust-privacy-common.h"
+#include "libproc_macro/proc_macro.h"
namespace Rust {
namespace Analysis {
void insert_exported_macro (AST::MacroRulesDefinition &def);
std::vector<NodeId> &get_exported_macros ();
+ void insert_derive_proc_macro (std::pair<std::string, std::string> hierachy,
+ ProcMacro::CustomDerive macro);
+ void insert_bang_proc_macro (std::pair<std::string, std::string> hierachy,
+ ProcMacro::Bang macro);
+ void
+ insert_attribute_proc_macro (std::pair<std::string, std::string> hierachy,
+ ProcMacro::Attribute macro);
+
+ bool lookup_derive_proc_macro (std::pair<std::string, std::string> hierachy,
+ ProcMacro::CustomDerive ¯o);
+ bool lookup_bang_proc_macro (std::pair<std::string, std::string> hierachy,
+ ProcMacro::Bang ¯o);
+ bool
+ lookup_attribute_proc_macro (std::pair<std::string, std::string> hierachy,
+ ProcMacro::Attribute ¯o);
+
void insert_visibility (NodeId id, Privacy::ModuleVisibility visibility);
bool lookup_visibility (NodeId id, Privacy::ModuleVisibility &def);
// all hirid nodes
std::map<CrateNum, std::set<HirId>> hirNodesWithinCrate;
- // macros
+ // MBE macros
std::map<NodeId, AST::MacroRulesDefinition *> macroMappings;
std::map<NodeId, AST::MacroRulesDefinition *> macroInvocations;
std::vector<NodeId> exportedMacros;
+ // Procedural macros
+ std::map<std::pair<std::string, std::string>, ProcMacro::CustomDerive>
+ procmacroDeriveMappings;
+
+ std::map<std::pair<std::string, std::string>, ProcMacro::Bang>
+ procmacroBangMappings;
+
+ std::map<std::pair<std::string, std::string>, ProcMacro::Attribute>
+ procmacroAttributeMappings;
+
// crate names
std::map<CrateNum, std::string> crate_names;