summaryrefslogtreecommitdiff
path: root/src/expand/derive.cpp
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2016-07-07 07:09:53 +1000
committerJohn Hodge <tpg@mutabah.net>2016-07-07 07:09:53 +1000
commit5d059f8d8342e65b80f4bb41d827e8585cd5408b (patch)
tree2a2e3c4f0786887daf9d4f606fa87408ab0fb397 /src/expand/derive.cpp
parentd03c31318ac1dc03094a690046cbc93ab5b39f51 (diff)
downloadmrust-5d059f8d8342e65b80f4bb41d827e8585cd5408b.tar.gz
Expand - PartialEq derive hacking up
Diffstat (limited to 'src/expand/derive.cpp')
-rw-r--r--src/expand/derive.cpp193
1 files changed, 181 insertions, 12 deletions
diff --git a/src/expand/derive.cpp b/src/expand/derive.cpp
index aec3de51..7b50ef30 100644
--- a/src/expand/derive.cpp
+++ b/src/expand/derive.cpp
@@ -25,6 +25,7 @@ static inline AST::ExprNodeP mk_exprnodep(AST::ExprNode* en){ return AST::ExprNo
struct Deriver
{
virtual AST::Impl handle_item(Span sp, const AST::GenericParams& params, const TypeRef& type, const AST::Struct& str) const = 0;
+ virtual AST::Impl handle_item(Span sp, const AST::GenericParams& p, const TypeRef& type, const AST::Enum& enm) const = 0;
};
/// 'Debug' derive handler
@@ -44,16 +45,36 @@ class Deriver_Debug:
// throw CompileError::Todo("derive(Debug) - _try");
//}
-public:
- AST::Impl handle_item(Span sp, const AST::GenericParams& p, const TypeRef& type, const AST::Struct& str) const override
+ AST::Impl make_ret(Span sp, const AST::GenericParams& p, const TypeRef& type, AST::ExprNodeP node) const
{
- // 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 AST::Path debug_trait = AST::Path("", { AST::PathNode("fmt", {}), AST::PathNode("Debug", {}) });
const TypeRef ret_type(sp, AST::Path("", {AST::PathNode("fmt",{}), AST::PathNode("Result",{})}) );
const TypeRef f_type(TypeRef::TagReference(), sp, true,
TypeRef(sp, AST::Path("", {AST::PathNode("fmt",{}), AST::PathNode("Formatter", {})}))
);
+
+ DEBUG("node = " << *node);
+
+ AST::Function fcn(
+ AST::GenericParams(),
+ ret_type,
+ vec$(
+ ::std::make_pair( AST::Pattern(AST::Pattern::TagBind(), "self"), TypeRef(TypeRef::TagReference(), sp, false, TypeRef("Self", 0xFFFF)) ),
+ ::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::Module>()) );
+
+ AST::Impl rv( AST::ImplDef( sp, AST::MetaItems(), p, make_spanned(sp, debug_trait), type ) );
+ rv.add_function(false, "fmt", mv$(fcn));
+ return mv$(rv);
+ }
+
+public:
+ AST::Impl handle_item(Span sp, 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 ::std::string& name = type.path().nodes().back().name();
// Generate code for Debug
@@ -106,24 +127,164 @@ public:
)
)
- DEBUG("node = " << *node);
+ return this->make_ret(sp, p, type, mv$(node));
+ }
+ AST::Impl handle_item(Span sp, const AST::GenericParams& p, const TypeRef& type, const AST::Enum& enm) const override
+ {
+ ::std::vector< AST::ExprNode_Match_Arm> arms;
+ //for(const auto& v : enm.variants())
+ //{
+ // TODO: Debug for enums
+ //}
+ AST::ExprNodeP node = NEWNODE(AST::ExprNode_Match,
+ NEWNODE(AST::ExprNode_NamedValue, AST::Path("self")),
+ mv$(arms)
+ );
+
+ return this->make_ret(sp, p, type, mv$(node));
+ }
+} g_derive_debug;
+
+class Deriver_PartialEq:
+ public Deriver
+{
+ AST::Impl make_ret(Span sp, const AST::GenericParams& p, const TypeRef& type, AST::ExprNodeP node) const
+ {
+ const AST::Path trait_path("", { AST::PathNode("cmp", {}), AST::PathNode("PartialEq", {}) });
AST::Function fcn(
AST::GenericParams(),
- ret_type,
+ TypeRef(sp, CORETYPE_BOOL),
vec$(
::std::make_pair( AST::Pattern(AST::Pattern::TagBind(), "self"), TypeRef(TypeRef::TagReference(), sp, false, TypeRef("Self", 0xFFFF)) ),
- ::std::make_pair( AST::Pattern(AST::Pattern::TagBind(), "f"), f_type )
+ ::std::make_pair( AST::Pattern(AST::Pattern::TagBind(), "v"), TypeRef(TypeRef::TagReference(), sp, false, TypeRef("Self", 0xFFFF)) )
)
);
fcn.set_code( NEWNODE(AST::ExprNode_Block, vec$(mv$(node)), ::std::unique_ptr<AST::Module>()) );
- AST::Impl rv( AST::ImplDef( sp, AST::MetaItems(), p, make_spanned(sp, debug_trait), type ) );
- rv.add_function(false, "fmt", mv$(fcn));
+ AST::GenericParams params = p;
+ for(const auto& typ : params.ty_params())
+ {
+ params.bounds().push_back( ::AST::GenericBound::make_IsTrait({ TypeRef(typ.name()), {}, trait_path }) );
+ }
+
+ AST::Impl rv( AST::ImplDef( sp, AST::MetaItems(), mv$(params), make_spanned(sp, trait_path), type ) );
+ rv.add_function(false, "eq", mv$(fcn));
return mv$(rv);
}
-} g_derive_debug;
+public:
+ AST::Impl handle_item(Span sp, const AST::GenericParams& p, const TypeRef& type, const AST::Struct& str) const override
+ {
+ ::std::vector<AST::ExprNodeP> nodes;
+
+ TU_MATCH(AST::StructData, (str.m_data), (e),
+ (Struct,
+ for( const auto& fld : e.ents )
+ {
+ nodes.push_back(NEWNODE(AST::ExprNode_If,
+ NEWNODE(AST::ExprNode_BinOp, AST::ExprNode_BinOp::CMPNEQU,
+ NEWNODE(AST::ExprNode_Field, NEWNODE(AST::ExprNode_NamedValue, AST::Path("self")), fld.m_name),
+ NEWNODE(AST::ExprNode_Field, NEWNODE(AST::ExprNode_NamedValue, AST::Path("v")), fld.m_name)
+ ),
+ NEWNODE(AST::ExprNode_Flow, AST::ExprNode_Flow::RETURN, "", NEWNODE(AST::ExprNode_Bool, false)),
+ nullptr
+ ));
+ }
+ ),
+ (Tuple,
+ for( unsigned int idx = 0; idx < e.ents.size(); idx ++ )
+ {
+ auto fld_name = FMT(idx);
+ nodes.push_back(NEWNODE(AST::ExprNode_If,
+ NEWNODE(AST::ExprNode_BinOp, AST::ExprNode_BinOp::CMPNEQU,
+ NEWNODE(AST::ExprNode_Field, NEWNODE(AST::ExprNode_NamedValue, AST::Path("self")), fld_name),
+ NEWNODE(AST::ExprNode_Field, NEWNODE(AST::ExprNode_NamedValue, AST::Path("v")), fld_name)
+ ),
+ NEWNODE(AST::ExprNode_Flow, AST::ExprNode_Flow::RETURN, "", NEWNODE(AST::ExprNode_Bool, false)),
+ nullptr
+ ));
+ }
+ )
+ )
+ nodes.push_back( NEWNODE(AST::ExprNode_Bool, true) );
+
+ return this->make_ret(sp, p, type, NEWNODE(AST::ExprNode_Block, mv$(nodes), nullptr));
+ }
+
+ AST::Impl handle_item(Span sp, const AST::GenericParams& p, const TypeRef& type, const AST::Enum& enm) const override
+ {
+ AST::Path base_path = type.m_data.as_Path().path;
+ base_path.nodes().back().args() = ::AST::PathParams();
+ ::std::vector<AST::ExprNode_Match_Arm> arms;
+
+ // TODO: PartialEq for enums
+ for(const auto& v : enm.variants())
+ {
+ AST::ExprNodeP code;
+ AST::Pattern pat_a;
+ AST::Pattern pat_b;
+
+ TU_MATCH(::AST::EnumVariantData, (v.m_data), (e),
+ (Value,
+ code = NEWNODE(AST::ExprNode_Bool, true);
+ pat_a = AST::Pattern(AST::Pattern::TagValue(), AST::Pattern::Value::make_Named(base_path + v.m_name));
+ pat_b = AST::Pattern(AST::Pattern::TagValue(), AST::Pattern::Value::make_Named(base_path + v.m_name));
+ ),
+ (Tuple,
+ if( e.m_sub_types.size() == 0 )
+ {
+ code = NEWNODE(AST::ExprNode_Bool, true);
+ pat_a = AST::Pattern(AST::Pattern::TagValue(), AST::Pattern::Value::make_Named(base_path + v.m_name));
+ pat_b = AST::Pattern(AST::Pattern::TagValue(), AST::Pattern::Value::make_Named(base_path + v.m_name));
+ }
+ else
+ {
+ ::std::vector< AST::Pattern> pats_a;
+ ::std::vector< AST::Pattern> pats_b;
+ ::std::vector<AST::ExprNodeP> nodes;
+
+ nodes.push_back( NEWNODE(AST::ExprNode_Bool, true) );
+ pat_a = AST::Pattern(AST::Pattern::TagEnumVariant(), base_path + v.m_name, mv$(pats_a));
+ pat_b = AST::Pattern(AST::Pattern::TagEnumVariant(), base_path + v.m_name, mv$(pats_b));
+ code = NEWNODE(AST::ExprNode_Block, mv$(nodes), nullptr);
+ }
+ ),
+ (Struct,
+ ::std::vector< ::std::pair<std::string, AST::Pattern> > pats_a;
+ ::std::vector< ::std::pair<std::string, AST::Pattern> > pats_b;
+ ::std::vector<AST::ExprNodeP> nodes;
+
+ nodes.push_back( NEWNODE(AST::ExprNode_Bool, true) );
+ pat_a = AST::Pattern(AST::Pattern::TagStruct(), base_path + v.m_name, mv$(pats_a), true);
+ pat_b = AST::Pattern(AST::Pattern::TagStruct(), base_path + v.m_name, mv$(pats_b), true);
+ code = NEWNODE(AST::ExprNode_Block, mv$(nodes), nullptr);
+ )
+ )
+
+ ::std::vector< AST::Pattern> pats;
+ {
+ ::std::vector< AST::Pattern> tuple_pats;
+ tuple_pats.push_back( AST::Pattern(AST::Pattern::TagReference(), mv$(pat_a)) );
+ tuple_pats.push_back( AST::Pattern(AST::Pattern::TagReference(), mv$(pat_b)) );
+ pats.push_back( AST::Pattern(AST::Pattern::TagTuple(), mv$(tuple_pats)) );
+ }
+
+ arms.push_back(AST::ExprNode_Match_Arm(
+ mv$(pats),
+ nullptr,
+ mv$(code)
+ ));
+ }
+ ::std::vector<AST::ExprNodeP> vals;
+ vals.push_back( NEWNODE(AST::ExprNode_NamedValue, AST::Path("self")) );
+ vals.push_back( NEWNODE(AST::ExprNode_NamedValue, AST::Path("v")) );
+ return this->make_ret(sp, p, type, NEWNODE(AST::ExprNode_Match,
+ NEWNODE(AST::ExprNode_Tuple, mv$(vals)),
+ mv$(arms)
+ ));
+ }
+} g_derive_partialeq;
// --------------------------------------------------------------------
// Select and dispatch the correct derive() handler
@@ -132,6 +293,8 @@ static const Deriver* find_impl(const ::std::string& trait_name)
{
if( trait_name == "Debug" )
return &g_derive_debug;
+ else if( trait_name == "PartialEq" )
+ return &g_derive_partialeq;
else
return nullptr;
}
@@ -154,12 +317,14 @@ static void derive_item(const Span& sp, AST::Module& mod, const AST::MetaItem& a
types_args.m_types.push_back( TypeRef(TypeRef::TagArg(), param.name()) );
}
+ ::std::vector< ::std::string> missing_handlers;
for( const auto& trait : attr.items() )
{
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;
continue ;
}
@@ -168,7 +333,7 @@ static void derive_item(const Span& sp, AST::Module& mod, const AST::MetaItem& a
}
if( fail ) {
- //throw CompileError::Generic("Failed to #[dervie]");
+ //ERROR(sp, E0000, "Failed to apply #[derive] - Missing handlers for " << missing_handlers);
}
}
@@ -181,6 +346,10 @@ public:
{
TU_MATCH_DEF(::AST::Item, (i), (e),
(
+ TODO(sp, "Handle #[derive] for other item types");
+ ),
+ (Enum,
+ derive_item(sp, mod, attr, path, e);
),
(Struct,
derive_item(sp, mod, attr, path, e);