diff options
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | src/ast/ast.hpp | 4 | ||||
-rw-r--r-- | src/ast/crate.hpp | 4 | ||||
-rw-r--r-- | src/expand/derive.cpp | 30 | ||||
-rw-r--r-- | src/hir/hir.hpp | 5 | ||||
-rw-r--r-- | src/include/main_bindings.hpp | 1 | ||||
-rw-r--r-- | src/main.cpp | 21 | ||||
-rw-r--r-- | src/trans/trans_list.hpp | 6 |
8 files changed, 66 insertions, 7 deletions
@@ -43,6 +43,7 @@ CPPFLAGS := -I src/include/ -I src/ CXXFLAGS += -Wno-pessimizing-move CXXFLAGS += -Wno-misleading-indentation #CXXFLAGS += -Wno-unused-private-field +CXXFLAGS += -Wno-unknown-warning-option # - Flags to pass to all mrustc invocations @@ -87,6 +88,7 @@ OBJ += expand/include.o OBJ += expand/env.o OBJ += expand/test.o OBJ += expand/rustc_diagnostics.o +OBJ += expand/proc_macro.o OBJ += expand/test_harness.o OBJ += macro_rules/mod.o macro_rules/eval.o macro_rules/parse.o OBJ += resolve/use.o resolve/index.o resolve/absolute.o diff --git a/src/ast/ast.hpp b/src/ast/ast.hpp index 2ef17718..6b729f8c 100644 --- a/src/ast/ast.hpp +++ b/src/ast/ast.hpp @@ -534,6 +534,10 @@ public: ::std::unordered_map< ::std::string, IndexEnt > m_type_items; ::std::unordered_map< ::std::string, IndexEnt > m_value_items; + // List of macros imported from other modules (via #[macro_use], includes proc macros) + // - First value is an absolute path to the macro (including crate name) + ::std::vector<::std::pair< ::std::vector<::std::string>, const MacroRules* >> m_macro_imports; + public: Module() {} Module(::AST::Path path): diff --git a/src/ast/crate.hpp b/src/ast/crate.hpp index 1723868c..67b4915e 100644 --- a/src/ast/crate.hpp +++ b/src/ast/crate.hpp @@ -43,12 +43,16 @@ public: bool m_test_harness = false; ::std::vector<TestDesc> m_tests; + // Procedural macros! + ::std::vector<::std::pair< ::std::string, ::AST::Path>> m_proc_macros; + enum class Type { Unknown, RustLib, RustDylib, CDylib, Executable, + ProcMacro, // Procedural macro } m_crate_type = Type::Unknown; enum LoadStd { LOAD_STD, diff --git a/src/expand/derive.cpp b/src/expand/derive.cpp index ac9842a7..9d8169ad 100644 --- a/src/expand/derive.cpp +++ b/src/expand/derive.cpp @@ -11,6 +11,8 @@ #include "../ast/expr.hpp" #include "../ast/crate.hpp" #include <hir/hir.hpp> // ABI_RUST +#include <parse/common.hpp> // Parse_ModRoot_Items +#include "proc_macro.hpp" template<typename T> static inline ::std::vector<T> vec$(T v1) { @@ -2205,17 +2207,33 @@ static void derive_item(const Span& sp, const AST::Crate& crate, AST::Module& mo { DEBUG("- " << trait.name()); auto dp = find_impl(trait.name()); - if( !dp ) { - DEBUG("> No handler for " << trait.name()); - missing_handlers.push_back( trait.name() ); - fail = true; + if( dp ) { + mod.add_item(false, "", dp->handle_item(sp, (crate.m_load_std == ::AST::Crate::LOAD_NONE ? "" : "core"), params, type, item), {} ); continue ; } - // TODO: Support macros 1.1 custom derive + // Support custom derive + auto mac_name = FMT("deriving#" << trait.name()); // - Requires support all through the chain. + for(const auto& mac_path : mod.m_macro_imports) + { + if( mac_path.first.back() == mac_name ) + { + if( mac_path.second ) { + // macro_rules! based derive? + TODO(sp, "Custom derive using macro_rules?"); + } + else { + // proc_macro - Invoke the handler. + auto lex = ProcMacro_Invoke(sp, crate, mac_path.first, path.nodes().back().name(), item); + Parse_ModRoot_Items(*lex, mod); + } + } + } - mod.add_item(false, "", dp->handle_item(sp, (crate.m_load_std == ::AST::Crate::LOAD_NONE ? "" : "core"), params, type, item), {} ); + DEBUG("> No handler for " << trait.name()); + missing_handlers.push_back( trait.name() ); + fail = true; } if( fail ) { diff --git a/src/hir/hir.hpp b/src/hir/hir.hpp index 72b8d7dc..a04fd1da 100644 --- a/src/hir/hir.hpp +++ b/src/hir/hir.hpp @@ -470,12 +470,17 @@ public: /// Macros exported by this crate ::std::unordered_map< ::std::string, ::MacroRulesPtr > m_exported_macros; + /// Procedural macros presented + ::std::vector<::HIR::SimplePath> m_proc_macros; /// Language items avaliable through this crate (includes ones from loaded externs) ::std::unordered_map< ::std::string, ::HIR::SimplePath> m_lang_items; + /// Referenced crates ::std::unordered_map< ::std::string, ExternCrate> m_ext_crates; + /// Referenced system libraries ::std::vector<ExternLibrary> m_ext_libs; + /// Extra paths for the linker ::std::vector<::std::string> m_link_paths; /// Method called to populate runtime state after deserialisation diff --git a/src/include/main_bindings.hpp b/src/include/main_bindings.hpp index 184f266f..ee8f4c54 100644 --- a/src/include/main_bindings.hpp +++ b/src/include/main_bindings.hpp @@ -17,6 +17,7 @@ extern AST::Crate Parse_Crate(::std::string mainfile); extern void Expand(::AST::Crate& crate); extern void Expand_TestHarness(::AST::Crate& crate); +extern void Expand_ProcMacro(::AST::Crate& crate); /// Process #[] decorators extern void Process_Decorators(AST::Crate& crate); diff --git a/src/main.cpp b/src/main.cpp index 20c525d5..7769b4bc 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -258,6 +258,11 @@ int main(int argc, char *argv[]) } crate.m_crate_type = crate_type; + if( crate.m_crate_type == ::AST::Crate::Type::ProcMacro ) + { + Expand_ProcMacro(crate); + } + auto crate_name = params.crate_name; if( crate_name == "" ) { @@ -557,6 +562,18 @@ int main(int argc, char *argv[]) case ::AST::Crate::Type::CDylib: // Generate a .so/.dll break; + case ::AST::Crate::Type::ProcMacro: { + // Needs: An executable (the actual macro handler), metadata (for `extern crate foo;`) + // Can just emit the metadata and do miri? + // - Requires MIR for EVERYTHING, not feasable. + TransList items = CompilePhase<TransList>("Trans Enumerate", [&]() { return Trans_Enumerate_Public(*hir_crate); }); + CompilePhaseV("Trans Codegen", [&]() { Trans_Codegen(params.outfile + ".o", trans_opt, *hir_crate, items, false); }); + + TransList items2 = CompilePhase<TransList>("Trans Enumerate", [&]() { return Trans_Enumerate_Main(*hir_crate); }); + CompilePhaseV("Trans Codegen", [&]() { Trans_Codegen(params.outfile + "-plugin", trans_opt, *hir_crate, items2, true); }); + + CompilePhaseV("HIR Serialise", [&]() { HIR_Serialise(params.outfile, *hir_crate); }); + break; } case ::AST::Crate::Type::Executable: // Generate a binary // - Enumerate items for translation @@ -759,6 +776,9 @@ ProgramParams::ProgramParams(int argc, char *argv[]) else if( strcmp(type_str, "bin") == 0 ) { this->crate_type = ::AST::Crate::Type::Executable; } + else if( strcmp(type_str, "proc-macro") == 0 ) { + this->crate_type = ::AST::Crate::Type::ProcMacro; + } else { ::std::cerr << "Unknown value for --crate-type" << ::std::endl; exit(1); @@ -897,4 +917,3 @@ ProgramParams::ProgramParams(int argc, char *argv[]) os << ::std::dec; return os; } - diff --git a/src/trans/trans_list.hpp b/src/trans/trans_list.hpp index 86284172..2ef876d6 100644 --- a/src/trans/trans_list.hpp +++ b/src/trans/trans_list.hpp @@ -55,6 +55,12 @@ struct TransList_Static class TransList { public: + TransList() = default; + TransList(TransList&&) = default; + TransList(const TransList&) = delete; + TransList& operator=(TransList&&) = default; + TransList& operator=(const TransList&) = delete; + ::std::map< ::HIR::Path, ::std::unique_ptr<TransList_Function> > m_functions; ::std::map< ::HIR::Path, ::std::unique_ptr<TransList_Static> > m_statics; ::std::map< ::HIR::Path, Trans_Params> m_vtables; |