From f6c69a1089e2246156e65c0173a14306935733f3 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sun, 13 Mar 2016 09:36:24 +0800 Subject: Expand - Move synexts/*.cpp to expand/ --- src/expand/derive.cpp | 165 ++++++++++++++++++++++++++++++++++++++++++++++ src/expand/lang_item.cpp | 104 +++++++++++++++++++++++++++++ src/synexts/derive.cpp | 165 ---------------------------------------------- src/synexts/lang_item.cpp | 104 ----------------------------- 4 files changed, 269 insertions(+), 269 deletions(-) create mode 100644 src/expand/derive.cpp create mode 100644 src/expand/lang_item.cpp delete mode 100644 src/synexts/derive.cpp delete mode 100644 src/synexts/lang_item.cpp (limited to 'src') diff --git a/src/expand/derive.cpp b/src/expand/derive.cpp new file mode 100644 index 00000000..e4c10f4e --- /dev/null +++ b/src/expand/derive.cpp @@ -0,0 +1,165 @@ + +#include +#include "../common.hpp" +#include "../ast/ast.hpp" +#include "../ast/expr.hpp" + +template +static inline ::std::vector vec$(T v1) { + ::std::vector tmp; + tmp.push_back( mv$(v1) ); + return mv$(tmp); +} +template +static inline ::std::vector vec$(T v1, T v2) { + ::std::vector tmp; + tmp.push_back( mv$(v1) ); + tmp.push_back( mv$(v2) ); + return mv$(tmp); +} + +static inline AST::ExprNodeP mk_exprnodep(AST::ExprNode* en){ return AST::ExprNodeP(en); } +#define NEWNODE(type, ...) mk_exprnodep(new type(__VA_ARGS__)) + +/// Interface for derive handlers +struct Deriver +{ + virtual AST::Impl handle_item(const AST::GenericParams& params, const TypeRef& type, const AST::Struct& str) const = 0; +}; + +/// 'Debug' derive handler +class Deriver_Debug: + public Deriver +{ + //static AST::ExprNodeP _print_l(::std::string val) + //{ + // return NEWNODE(AST::ExprNode_CallMethod, + // NEWNODE(AST::ExprNode_NamedValue, AST::Path("f")), + // AST::PathNode("write_str",{}), + // { NEWNODE(AST::ExprNode_String, mv$(val)) } + // ); + //} + //static AST::ExprNodeP _try(AST::ExprNodeP expr) + //{ + // throw CompileError::Todo("derive(Debug) - _try"); + //} + +public: + AST::Impl handle_item(const AST::GenericParams& p, const TypeRef& type, const AST::Struct& str) const override + { + // TODO: be correct herhe and use "core" as the crate name + // - Requires handling the crate_name crate attribute correctly + const AST::Path debug_trait("", { AST::PathNode("fmt", {}), AST::PathNode("Debug", {}) }); + const TypeRef ret_type(AST::Path("", {AST::PathNode("fmt",{}), AST::PathNode("Result",{})}) ); + const TypeRef f_type(TypeRef::TagReference(), true, + TypeRef(AST::Path("", {AST::PathNode("fmt",{}), AST::PathNode("Formatter", {})})) + ); + const ::std::string& name = type.path().nodes().back().name(); + + // Generate code for Debug + AST::ExprNodeP node; + node = NEWNODE(AST::ExprNode_NamedValue, AST::Path("f")); + node = NEWNODE(AST::ExprNode_CallMethod, + mv$(node), AST::PathNode("debug_struct",{}), + vec$( NEWNODE(AST::ExprNode_String, name) ) + ); + for( const auto& fld : str.fields() ) + { + node = NEWNODE(AST::ExprNode_CallMethod, + mv$(node), AST::PathNode("field",{}), + vec$( + NEWNODE(AST::ExprNode_String, fld.name), + NEWNODE(AST::ExprNode_UniOp, AST::ExprNode_UniOp::REF, + NEWNODE(AST::ExprNode_Field, + NEWNODE(AST::ExprNode_NamedValue, AST::Path("self")), + fld.name + ) + ) + ) + ); + } + node = NEWNODE(AST::ExprNode_CallMethod, mv$(node), AST::PathNode("finish",{}), {}); + + DEBUG("node = " << *node); + + AST::Function fcn( + AST::GenericParams(), + ret_type, + vec$( + ::std::make_pair( AST::Pattern(AST::Pattern::TagBind(), "self"), TypeRef(TypeRef::TagReference(), false, TypeRef("Self")) ), + ::std::make_pair( AST::Pattern(AST::Pattern::TagBind(), "f"), f_type ) + ) + ); + fcn.set_code( NEWNODE(AST::ExprNode_Block, vec$(mv$(node)), ::std::unique_ptr()) ); + + AST::Impl rv( AST::MetaItems(), p, type, debug_trait ); + rv.add_function(false, "fmt", mv$(fcn)); + return mv$(rv); + } +} g_derive_debug; + + +// -------------------------------------------------------------------- +// Select and dispatch the correct derive() handler +// -------------------------------------------------------------------- +static const Deriver* find_impl(const ::std::string& trait_name) +{ + if( trait_name == "Debug" ) + return &g_derive_debug; + else + return nullptr; +} + +template +static void derive_item(AST::Module& mod, const AST::MetaItem& attr, const AST::Path& path, const T& item) +{ + if( !attr.has_sub_items() ) { + //throw CompileError::Generic("#[derive()] requires a list of known traits to derive"); + return ; + } + + DEBUG("path = " << path); + bool fail = false; + + const auto& params = item.params(); + TypeRef type(path); + for( const auto& param : params.ty_params() ) + type.path().nodes().back().args().push_back( TypeRef(TypeRef::TagArg(), param.name()) ); + + for( const auto& trait : attr.items() ) + { + DEBUG("- " << trait.name()); + auto dp = find_impl(trait.name()); + if( !dp ) { + DEBUG("> No handler for " << trait.name()); + fail = true; + continue ; + } + + mod.add_impl( dp->handle_item(params, type, item) ); + } + + if( fail ) { + //throw CompileError::Generic("Failed to #[dervie]"); + } +} + +class Decorator_Derive: + public ExpandDecorator +{ +public: + AttrStage stage() const override { return AttrStage::LatePost; } + void handle(const AST::MetaItem& attr, ::AST::Crate& crate, const AST::Path& path, AST::Module& mod, AST::Item& i) const override + { + TU_MATCH_DEF(::AST::Item, (i), (e), + ( + ), + (Struct, + derive_item(mod, attr, path, e.e); + ) + ) + } +}; + +STATIC_DECORATOR("derive", Decorator_Derive) + diff --git a/src/expand/lang_item.cpp b/src/expand/lang_item.cpp new file mode 100644 index 00000000..3df3a54f --- /dev/null +++ b/src/expand/lang_item.cpp @@ -0,0 +1,104 @@ +/* + * MRustC - Rust Compiler + * - By John Hodge (Mutabah/thePowersGang) + * + * synexts/lang_item.cpp + * - Binds language items to #[lang_item] tagged items + */ +#include +#include "../common.hpp" +#include "../ast/ast.hpp" +#include "../ast/crate.hpp" + + +void handle_lang_item(AST::Crate& crate, const AST::Path& path, const ::std::string& name, AST::eItemType type) +{ + if(name == "phantom_fn") { + crate.m_lang_item_PhantomFn = AST::Path(path); + crate.m_lang_item_PhantomFn.nodes().back().args() = { TypeRef("A"), TypeRef("B") }; + } + else if( name == "send" ) { + // Don't care, Send is fully library in mrustc + } + else if( name == "sync" ) { + // Don't care, Sync is fully library in mrustc + } + else if( name == "sized" ) { + DEBUG("Bind 'sized' to " << path); + } + else if( name == "copy" ) { + DEBUG("Bind 'copy' to " << path); + } + // ops traits + else if( name == "drop" ) { DEBUG("Bind '"< -#include "../common.hpp" -#include "../ast/ast.hpp" -#include "../ast/expr.hpp" - -template -static inline ::std::vector vec$(T v1) { - ::std::vector tmp; - tmp.push_back( mv$(v1) ); - return mv$(tmp); -} -template -static inline ::std::vector vec$(T v1, T v2) { - ::std::vector tmp; - tmp.push_back( mv$(v1) ); - tmp.push_back( mv$(v2) ); - return mv$(tmp); -} - -static inline AST::ExprNodeP mk_exprnodep(AST::ExprNode* en){ return AST::ExprNodeP(en); } -#define NEWNODE(type, ...) mk_exprnodep(new type(__VA_ARGS__)) - -/// Interface for derive handlers -struct Deriver -{ - virtual AST::Impl handle_item(const AST::GenericParams& params, const TypeRef& type, const AST::Struct& str) const = 0; -}; - -/// 'Debug' derive handler -class Deriver_Debug: - public Deriver -{ - //static AST::ExprNodeP _print_l(::std::string val) - //{ - // return NEWNODE(AST::ExprNode_CallMethod, - // NEWNODE(AST::ExprNode_NamedValue, AST::Path("f")), - // AST::PathNode("write_str",{}), - // { NEWNODE(AST::ExprNode_String, mv$(val)) } - // ); - //} - //static AST::ExprNodeP _try(AST::ExprNodeP expr) - //{ - // throw CompileError::Todo("derive(Debug) - _try"); - //} - -public: - AST::Impl handle_item(const AST::GenericParams& p, const TypeRef& type, const AST::Struct& str) const override - { - // TODO: be correct herhe and use "core" as the crate name - // - Requires handling the crate_name crate attribute correctly - const AST::Path debug_trait("", { AST::PathNode("fmt", {}), AST::PathNode("Debug", {}) }); - const TypeRef ret_type(AST::Path("", {AST::PathNode("fmt",{}), AST::PathNode("Result",{})}) ); - const TypeRef f_type(TypeRef::TagReference(), true, - TypeRef(AST::Path("", {AST::PathNode("fmt",{}), AST::PathNode("Formatter", {})})) - ); - const ::std::string& name = type.path().nodes().back().name(); - - // Generate code for Debug - AST::ExprNodeP node; - node = NEWNODE(AST::ExprNode_NamedValue, AST::Path("f")); - node = NEWNODE(AST::ExprNode_CallMethod, - mv$(node), AST::PathNode("debug_struct",{}), - vec$( NEWNODE(AST::ExprNode_String, name) ) - ); - for( const auto& fld : str.fields() ) - { - node = NEWNODE(AST::ExprNode_CallMethod, - mv$(node), AST::PathNode("field",{}), - vec$( - NEWNODE(AST::ExprNode_String, fld.name), - NEWNODE(AST::ExprNode_UniOp, AST::ExprNode_UniOp::REF, - NEWNODE(AST::ExprNode_Field, - NEWNODE(AST::ExprNode_NamedValue, AST::Path("self")), - fld.name - ) - ) - ) - ); - } - node = NEWNODE(AST::ExprNode_CallMethod, mv$(node), AST::PathNode("finish",{}), {}); - - DEBUG("node = " << *node); - - AST::Function fcn( - AST::GenericParams(), - ret_type, - vec$( - ::std::make_pair( AST::Pattern(AST::Pattern::TagBind(), "self"), TypeRef(TypeRef::TagReference(), false, TypeRef("Self")) ), - ::std::make_pair( AST::Pattern(AST::Pattern::TagBind(), "f"), f_type ) - ) - ); - fcn.set_code( NEWNODE(AST::ExprNode_Block, vec$(mv$(node)), ::std::unique_ptr()) ); - - AST::Impl rv( AST::MetaItems(), p, type, debug_trait ); - rv.add_function(false, "fmt", mv$(fcn)); - return mv$(rv); - } -} g_derive_debug; - - -// -------------------------------------------------------------------- -// Select and dispatch the correct derive() handler -// -------------------------------------------------------------------- -static const Deriver* find_impl(const ::std::string& trait_name) -{ - if( trait_name == "Debug" ) - return &g_derive_debug; - else - return nullptr; -} - -template -static void derive_item(AST::Module& mod, const AST::MetaItem& attr, const AST::Path& path, const T& item) -{ - if( !attr.has_sub_items() ) { - //throw CompileError::Generic("#[derive()] requires a list of known traits to derive"); - return ; - } - - DEBUG("path = " << path); - bool fail = false; - - const auto& params = item.params(); - TypeRef type(path); - for( const auto& param : params.ty_params() ) - type.path().nodes().back().args().push_back( TypeRef(TypeRef::TagArg(), param.name()) ); - - for( const auto& trait : attr.items() ) - { - DEBUG("- " << trait.name()); - auto dp = find_impl(trait.name()); - if( !dp ) { - DEBUG("> No handler for " << trait.name()); - fail = true; - continue ; - } - - mod.add_impl( dp->handle_item(params, type, item) ); - } - - if( fail ) { - //throw CompileError::Generic("Failed to #[dervie]"); - } -} - -class Decorator_Derive: - public ExpandDecorator -{ -public: - AttrStage stage() const override { return AttrStage::LatePost; } - void handle(const AST::MetaItem& attr, ::AST::Crate& crate, const AST::Path& path, AST::Module& mod, AST::Item& i) const override - { - TU_MATCH_DEF(::AST::Item, (i), (e), - ( - ), - (Struct, - derive_item(mod, attr, path, e.e); - ) - ) - } -}; - -STATIC_DECORATOR("derive", Decorator_Derive) - diff --git a/src/synexts/lang_item.cpp b/src/synexts/lang_item.cpp deleted file mode 100644 index 3df3a54f..00000000 --- a/src/synexts/lang_item.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/* - * MRustC - Rust Compiler - * - By John Hodge (Mutabah/thePowersGang) - * - * synexts/lang_item.cpp - * - Binds language items to #[lang_item] tagged items - */ -#include -#include "../common.hpp" -#include "../ast/ast.hpp" -#include "../ast/crate.hpp" - - -void handle_lang_item(AST::Crate& crate, const AST::Path& path, const ::std::string& name, AST::eItemType type) -{ - if(name == "phantom_fn") { - crate.m_lang_item_PhantomFn = AST::Path(path); - crate.m_lang_item_PhantomFn.nodes().back().args() = { TypeRef("A"), TypeRef("B") }; - } - else if( name == "send" ) { - // Don't care, Send is fully library in mrustc - } - else if( name == "sync" ) { - // Don't care, Sync is fully library in mrustc - } - else if( name == "sized" ) { - DEBUG("Bind 'sized' to " << path); - } - else if( name == "copy" ) { - DEBUG("Bind 'copy' to " << path); - } - // ops traits - else if( name == "drop" ) { DEBUG("Bind '"<