summaryrefslogtreecommitdiff
path: root/src/expand/derive.cpp
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2018-06-24 19:39:58 +0800
committerJohn Hodge <tpg@mutabah.net>2018-06-24 20:04:08 +0800
commitb03d61ed130dad6fa88a3beb4c32e48f86fdf84e (patch)
treeaa4c4559dd489baa8493ae05fa1cffe9b0198266 /src/expand/derive.cpp
parented5ab79df31720e8c9635f834ccd44bbef700266 (diff)
downloadmrust-b03d61ed130dad6fa88a3beb4c32e48f86fdf84e.tar.gz
Expand derive - Slight restructure to allow Copy/Clone magic
Diffstat (limited to 'src/expand/derive.cpp')
-rw-r--r--src/expand/derive.cpp225
1 files changed, 123 insertions, 102 deletions
diff --git a/src/expand/derive.cpp b/src/expand/derive.cpp
index f7c8fabc..5e97c888 100644
--- a/src/expand/derive.cpp
+++ b/src/expand/derive.cpp
@@ -63,13 +63,19 @@ static inline AST::ExprNodeP mk_exprnodep(AST::ExprNode* en){ return AST::ExprNo
//#define NEWNODE(type, ...) mk_exprnodep(new type(__VA_ARGS__))
#define NEWNODE(type, ...) mk_exprnodep(new AST::ExprNode_##type(__VA_ARGS__))
+struct DeriveOpts
+{
+ ::std::string core_name;
+ const ::std::vector<::AST::Attribute>& derive_items;
+};
+
/// Interface for derive handlers
struct Deriver
{
virtual const char* trait_name() const = 0;
- virtual AST::Impl handle_item(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, const AST::Struct& str) const = 0;
- virtual AST::Impl handle_item(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, const AST::Enum& enm) const = 0;
- virtual AST::Impl handle_item(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, const AST::Union& unn) const {
+ virtual AST::Impl handle_item(Span sp, const DeriveOpts& opts, const AST::GenericParams& p, const TypeRef& type, const AST::Struct& str) const = 0;
+ virtual AST::Impl handle_item(Span sp, const DeriveOpts& opts, const AST::GenericParams& p, const TypeRef& type, const AST::Enum& enm) const = 0;
+ virtual AST::Impl handle_item(Span sp, const DeriveOpts& opts, const AST::GenericParams& p, const TypeRef& type, const AST::Union& unn) const {
ERROR(sp, E0000, "Cannot derive(" << trait_name() << ") on union");
}
@@ -311,7 +317,7 @@ class Deriver_Debug:
public:
const char* trait_name() const override { return "Debug"; }
- AST::Impl handle_item(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, const AST::Struct& str) const override
+ AST::Impl handle_item(Span sp, const DeriveOpts& opts, const AST::GenericParams& p, const TypeRef& type, const AST::Struct& str) const override
{
const ::std::string& name = type.path().nodes().back().name();
@@ -372,9 +378,9 @@ public:
)
)
- return this->make_ret(sp, core_name, p, type, this->get_field_bounds(str), mv$(node));
+ return this->make_ret(sp, opts.core_name, p, type, this->get_field_bounds(str), mv$(node));
}
- AST::Impl handle_item(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, const AST::Enum& enm) const override
+ AST::Impl handle_item(Span sp, const DeriveOpts& opts, 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() = base_path.nodes().back().name();
@@ -463,7 +469,7 @@ public:
mv$(arms)
);
- return this->make_ret(sp, core_name, p, type, this->get_field_bounds(enm), mv$(node));
+ return this->make_ret(sp, opts.core_name, p, type, this->get_field_bounds(enm), mv$(node));
}
} g_derive_debug;
@@ -503,7 +509,7 @@ class Deriver_PartialEq:
public:
const char* trait_name() const override { return "PartialEq"; }
- AST::Impl handle_item(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, const AST::Struct& str) const override
+ AST::Impl handle_item(Span sp, const DeriveOpts& opts, const AST::GenericParams& p, const TypeRef& type, const AST::Struct& str) const override
{
::std::vector<AST::ExprNodeP> nodes;
@@ -513,7 +519,7 @@ public:
(Struct,
for( const auto& fld : e.ents )
{
- nodes.push_back(this->compare_and_ret( sp, core_name,
+ nodes.push_back(this->compare_and_ret( sp, opts.core_name,
NEWNODE(Field, NEWNODE(NamedValue, AST::Path("self")), fld.m_name),
NEWNODE(Field, NEWNODE(NamedValue, AST::Path("v" )), fld.m_name)
));
@@ -523,7 +529,7 @@ public:
for( unsigned int idx = 0; idx < e.ents.size(); idx ++ )
{
auto fld_name = FMT(idx);
- nodes.push_back(this->compare_and_ret( sp, core_name,
+ nodes.push_back(this->compare_and_ret( sp, opts.core_name,
NEWNODE(Field, NEWNODE(NamedValue, AST::Path("self")), fld_name),
NEWNODE(Field, NEWNODE(NamedValue, AST::Path("v" )), fld_name)
));
@@ -532,10 +538,10 @@ public:
)
nodes.push_back( NEWNODE(Bool, true) );
- return this->make_ret(sp, core_name, p, type, this->get_field_bounds(str), NEWNODE(Block, mv$(nodes)));
+ return this->make_ret(sp, opts.core_name, p, type, this->get_field_bounds(str), NEWNODE(Block, mv$(nodes)));
}
- AST::Impl handle_item(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, const AST::Enum& enm) const override
+ AST::Impl handle_item(Span sp, const DeriveOpts& opts, 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();
@@ -564,7 +570,7 @@ public:
auto name_b = FMT("b" << idx);
pats_a.push_back( ::AST::Pattern(::AST::Pattern::TagBind(), sp, name_a, ::AST::PatternBinding::Type::REF) );
pats_b.push_back( ::AST::Pattern(::AST::Pattern::TagBind(), sp, name_b, ::AST::PatternBinding::Type::REF) );
- nodes.push_back(this->compare_and_ret(sp, core_name,
+ nodes.push_back(this->compare_and_ret(sp, opts.core_name,
NEWNODE(NamedValue, AST::Path(name_a)),
NEWNODE(NamedValue, AST::Path(name_b))
));
@@ -586,7 +592,7 @@ public:
auto name_b = FMT("b" << fld.m_name);
pats_a.push_back( ::std::make_pair(fld.m_name, ::AST::Pattern(::AST::Pattern::TagBind(), sp, name_a, ::AST::PatternBinding::Type::REF)) );
pats_b.push_back( ::std::make_pair(fld.m_name, ::AST::Pattern(::AST::Pattern::TagBind(), sp, name_b, ::AST::PatternBinding::Type::REF)) );
- nodes.push_back(this->compare_and_ret(sp, core_name,
+ nodes.push_back(this->compare_and_ret(sp, opts.core_name,
NEWNODE(NamedValue, AST::Path(name_a)),
NEWNODE(NamedValue, AST::Path(name_b))
));
@@ -626,7 +632,7 @@ public:
::std::vector<AST::ExprNodeP> vals;
vals.push_back( NEWNODE(NamedValue, AST::Path("self")) );
vals.push_back( NEWNODE(NamedValue, AST::Path("v")) );
- return this->make_ret(sp, core_name, p, type, this->get_field_bounds(enm), NEWNODE(Match,
+ return this->make_ret(sp, opts.core_name, p, type, this->get_field_bounds(enm), NEWNODE(Match,
NEWNODE(Tuple, mv$(vals)),
mv$(arms)
));
@@ -711,7 +717,7 @@ class Deriver_PartialOrd:
public:
const char* trait_name() const override { return "PartialOrd"; }
- AST::Impl handle_item(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, const AST::Struct& str) const override
+ AST::Impl handle_item(Span sp, const DeriveOpts& opts, const AST::GenericParams& p, const TypeRef& type, const AST::Struct& str) const override
{
::std::vector<AST::ExprNodeP> nodes;
@@ -721,7 +727,7 @@ public:
(Struct,
for( const auto& fld : e.ents )
{
- nodes.push_back(this->make_compare_and_ret( sp, core_name,
+ nodes.push_back(this->make_compare_and_ret( sp, opts.core_name,
NEWNODE(Field, NEWNODE(NamedValue, AST::Path("self")), fld.m_name),
NEWNODE(Field, NEWNODE(NamedValue, AST::Path("v" )), fld.m_name)
));
@@ -731,19 +737,19 @@ public:
for( unsigned int idx = 0; idx < e.ents.size(); idx ++ )
{
auto fld_name = FMT(idx);
- nodes.push_back(this->make_compare_and_ret( sp, core_name,
+ nodes.push_back(this->make_compare_and_ret( sp, opts.core_name,
NEWNODE(Field, NEWNODE(NamedValue, AST::Path("self")), fld_name),
NEWNODE(Field, NEWNODE(NamedValue, AST::Path("v" )), fld_name)
));
}
)
)
- nodes.push_back( this->make_ret_equal(core_name) );
+ nodes.push_back( this->make_ret_equal(opts.core_name) );
- return this->make_ret(sp, core_name, p, type, this->get_field_bounds(str), NEWNODE(Block, mv$(nodes)));
+ return this->make_ret(sp, opts.core_name, p, type, this->get_field_bounds(str), NEWNODE(Block, mv$(nodes)));
}
- AST::Impl handle_item(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, const AST::Enum& enm) const override
+ AST::Impl handle_item(Span sp, const DeriveOpts& opts, 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();
@@ -757,7 +763,7 @@ public:
TU_MATCH(::AST::EnumVariantData, (v.m_data), (e),
(Value,
- code = this->make_ret_equal(core_name);
+ code = this->make_ret_equal(opts.core_name);
pat_a = AST::Pattern(AST::Pattern::TagValue(), sp, AST::Pattern::Value::make_Named(base_path + v.m_name));
pat_b = AST::Pattern(AST::Pattern::TagValue(), sp, AST::Pattern::Value::make_Named(base_path + v.m_name));
),
@@ -773,13 +779,13 @@ public:
pats_a.push_back( ::AST::Pattern(::AST::Pattern::TagBind(), sp, name_a, ::AST::PatternBinding::Type::REF) );
pats_b.push_back( ::AST::Pattern(::AST::Pattern::TagBind(), sp, name_b, ::AST::PatternBinding::Type::REF) );
- nodes.push_back(this->make_compare_and_ret( sp, core_name,
+ nodes.push_back(this->make_compare_and_ret( sp, opts.core_name,
NEWNODE(Deref, NEWNODE(NamedValue, AST::Path(name_a))),
NEWNODE(Deref, NEWNODE(NamedValue, AST::Path(name_b)))
));
}
- nodes.push_back( this->make_ret_equal(core_name) );
+ nodes.push_back( this->make_ret_equal(opts.core_name) );
pat_a = AST::Pattern(AST::Pattern::TagNamedTuple(), sp, base_path + v.m_name, mv$(pats_a));
pat_b = AST::Pattern(AST::Pattern::TagNamedTuple(), sp, base_path + v.m_name, mv$(pats_b));
code = NEWNODE(Block, mv$(nodes));
@@ -796,13 +802,13 @@ public:
pats_a.push_back( ::std::make_pair(fld.m_name, ::AST::Pattern(::AST::Pattern::TagBind(), sp, name_a, ::AST::PatternBinding::Type::REF)) );
pats_b.push_back( ::std::make_pair(fld.m_name, ::AST::Pattern(::AST::Pattern::TagBind(), sp, name_b, ::AST::PatternBinding::Type::REF)) );
- nodes.push_back(this->make_compare_and_ret( sp, core_name,
+ nodes.push_back(this->make_compare_and_ret( sp, opts.core_name,
NEWNODE(Deref, NEWNODE(NamedValue, AST::Path(name_a))),
NEWNODE(Deref, NEWNODE(NamedValue, AST::Path(name_b)))
));
}
- nodes.push_back( this->make_ret_equal(core_name) );
+ nodes.push_back( this->make_ret_equal(opts.core_name) );
pat_a = AST::Pattern(AST::Pattern::TagStruct(), sp, base_path + v.m_name, mv$(pats_a), true);
pat_b = AST::Pattern(AST::Pattern::TagStruct(), sp, base_path + v.m_name, mv$(pats_b), true);
code = NEWNODE(Block, mv$(nodes));
@@ -862,9 +868,9 @@ public:
pats.push_back( AST::Pattern(AST::Pattern::TagTuple(), sp, mv$(tuple_pats)) );
}
- auto code = NEWNODE(CallPath, this->get_path(core_name, "option", "Option", "Some"),
+ auto code = NEWNODE(CallPath, this->get_path(opts.core_name, "option", "Option", "Some"),
::make_vec1(
- NEWNODE(NamedValue, this->get_path(core_name, "cmp", "Ordering", (a < b ? "Less" : "Greater")))
+ NEWNODE(NamedValue, this->get_path(opts.core_name, "cmp", "Ordering", (a < b ? "Less" : "Greater")))
)
);
@@ -879,7 +885,7 @@ public:
::std::vector<AST::ExprNodeP> vals;
vals.push_back( NEWNODE(NamedValue, AST::Path("self")) );
vals.push_back( NEWNODE(NamedValue, AST::Path("v")) );
- return this->make_ret(sp, core_name, p, type, this->get_field_bounds(enm), NEWNODE(Match,
+ return this->make_ret(sp, opts.core_name, p, type, this->get_field_bounds(enm), NEWNODE(Match,
NEWNODE(Tuple, mv$(vals)),
mv$(arms)
));
@@ -927,9 +933,9 @@ class Deriver_Eq:
public:
const char* trait_name() const override { return "Eq"; }
- AST::Impl handle_item(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, const AST::Struct& str) const override
+ AST::Impl handle_item(Span sp, const DeriveOpts& opts, const AST::GenericParams& p, const TypeRef& type, const AST::Struct& str) const override
{
- const AST::Path assert_method_path = this->get_trait_path(core_name) + "assert_receiver_is_total_eq";
+ const AST::Path assert_method_path = this->get_trait_path(opts.core_name) + "assert_receiver_is_total_eq";
::std::vector<AST::ExprNodeP> nodes;
TU_MATCH(AST::StructData, (str.m_data), (e),
@@ -949,12 +955,12 @@ public:
)
)
- return this->make_ret(sp, core_name, p, type, this->get_field_bounds(str), NEWNODE(Block, mv$(nodes)));
+ return this->make_ret(sp, opts.core_name, p, type, this->get_field_bounds(str), NEWNODE(Block, mv$(nodes)));
}
- AST::Impl handle_item(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, const AST::Enum& enm) const override
+ AST::Impl handle_item(Span sp, const DeriveOpts& opts, const AST::GenericParams& p, const TypeRef& type, const AST::Enum& enm) const override
{
- const AST::Path assert_method_path = this->get_trait_path(core_name) + "assert_receiver_is_total_eq";
+ const AST::Path assert_method_path = this->get_trait_path(opts.core_name) + "assert_receiver_is_total_eq";
AST::Path base_path = type.m_data.as_Path().path;
base_path.nodes().back().args() = ::AST::PathParams();
@@ -1010,16 +1016,16 @@ public:
));
}
- return this->make_ret(sp, core_name, p, type, this->get_field_bounds(enm), NEWNODE(Match,
+ return this->make_ret(sp, opts.core_name, p, type, this->get_field_bounds(enm), NEWNODE(Match,
NEWNODE(NamedValue, AST::Path("self")),
mv$(arms)
));
}
- AST::Impl handle_item(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, const AST::Union& unn) const override
+ AST::Impl handle_item(Span sp, const DeriveOpts& opts, const AST::GenericParams& p, const TypeRef& type, const AST::Union& unn) const override
{
// Eq is just a marker, so it's valid to derive for union
- const AST::Path assert_method_path = this->get_trait_path(core_name) + "assert_receiver_is_total_eq";
+ const AST::Path assert_method_path = this->get_trait_path(opts.core_name) + "assert_receiver_is_total_eq";
::std::vector<AST::ExprNodeP> nodes;
for( const auto& fld : unn.m_variants )
@@ -1027,7 +1033,7 @@ public:
nodes.push_back( this->assert_is_eq(assert_method_path, this->field(fld.m_name)) );
}
- return this->make_ret(sp, core_name, p, type, this->get_field_bounds(unn), NEWNODE(Block, mv$(nodes)));
+ return this->make_ret(sp, opts.core_name, p, type, this->get_field_bounds(unn), NEWNODE(Block, mv$(nodes)));
}
} g_derive_eq;
@@ -1098,7 +1104,7 @@ class Deriver_Ord:
public:
const char* trait_name() const override { return "Ord"; }
- AST::Impl handle_item(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, const AST::Struct& str) const override
+ AST::Impl handle_item(Span sp, const DeriveOpts& opts, const AST::GenericParams& p, const TypeRef& type, const AST::Struct& str) const override
{
::std::vector<AST::ExprNodeP> nodes;
@@ -1108,7 +1114,7 @@ public:
(Struct,
for( const auto& fld : e.ents )
{
- nodes.push_back(this->make_compare_and_ret( sp, core_name,
+ nodes.push_back(this->make_compare_and_ret( sp, opts.core_name,
NEWNODE(Field, NEWNODE(NamedValue, AST::Path("self")), fld.m_name),
NEWNODE(Field, NEWNODE(NamedValue, AST::Path("v" )), fld.m_name)
));
@@ -1118,19 +1124,19 @@ public:
for( unsigned int idx = 0; idx < e.ents.size(); idx ++ )
{
auto fld_name = FMT(idx);
- nodes.push_back(this->make_compare_and_ret( sp, core_name,
+ nodes.push_back(this->make_compare_and_ret( sp, opts.core_name,
NEWNODE(Field, NEWNODE(NamedValue, AST::Path("self")), fld_name),
NEWNODE(Field, NEWNODE(NamedValue, AST::Path("v" )), fld_name)
));
}
)
)
- nodes.push_back( this->make_ret_equal(core_name) );
+ nodes.push_back( this->make_ret_equal(opts.core_name) );
- return this->make_ret(sp, core_name, p, type, this->get_field_bounds(str), NEWNODE(Block, mv$(nodes)));
+ return this->make_ret(sp, opts.core_name, p, type, this->get_field_bounds(str), NEWNODE(Block, mv$(nodes)));
}
- AST::Impl handle_item(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, const AST::Enum& enm) const override
+ AST::Impl handle_item(Span sp, const DeriveOpts& opts, 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();
@@ -1144,7 +1150,7 @@ public:
TU_MATCH(::AST::EnumVariantData, (v.m_data), (e),
(Value,
- code = this->make_ret_equal(core_name);
+ code = this->make_ret_equal(opts.core_name);
pat_a = AST::Pattern(AST::Pattern::TagValue(), sp, AST::Pattern::Value::make_Named(base_path + v.m_name));
pat_b = AST::Pattern(AST::Pattern::TagValue(), sp, AST::Pattern::Value::make_Named(base_path + v.m_name));
),
@@ -1160,13 +1166,13 @@ public:
pats_a.push_back( ::AST::Pattern(::AST::Pattern::TagBind(), sp, name_a, ::AST::PatternBinding::Type::REF) );
pats_b.push_back( ::AST::Pattern(::AST::Pattern::TagBind(), sp, name_b, ::AST::PatternBinding::Type::REF) );
- nodes.push_back(this->make_compare_and_ret( sp, core_name,
+ nodes.push_back(this->make_compare_and_ret( sp, opts.core_name,
NEWNODE(NamedValue, AST::Path(name_a)),
NEWNODE(NamedValue, AST::Path(name_b))
));
}
- nodes.push_back( this->make_ret_equal(core_name) );
+ nodes.push_back( this->make_ret_equal(opts.core_name) );
pat_a = AST::Pattern(AST::Pattern::TagNamedTuple(), sp, base_path + v.m_name, mv$(pats_a));
pat_b = AST::Pattern(AST::Pattern::TagNamedTuple(), sp, base_path + v.m_name, mv$(pats_b));
code = NEWNODE(Block, mv$(nodes));
@@ -1183,13 +1189,13 @@ public:
pats_a.push_back( ::std::make_pair(fld.m_name, ::AST::Pattern(::AST::Pattern::TagBind(), sp, name_a, ::AST::PatternBinding::Type::REF)) );
pats_b.push_back( ::std::make_pair(fld.m_name, ::AST::Pattern(::AST::Pattern::TagBind(), sp, name_b, ::AST::PatternBinding::Type::REF)) );
- nodes.push_back(this->make_compare_and_ret( sp, core_name,
+ nodes.push_back(this->make_compare_and_ret( sp, opts.core_name,
NEWNODE(NamedValue, AST::Path(name_a)),
NEWNODE(NamedValue, AST::Path(name_b))
));
}
- nodes.push_back( this->make_ret_equal(core_name) );
+ nodes.push_back( this->make_ret_equal(opts.core_name) );
pat_a = AST::Pattern(AST::Pattern::TagStruct(), sp, base_path + v.m_name, mv$(pats_a), true);
pat_b = AST::Pattern(AST::Pattern::TagStruct(), sp, base_path + v.m_name, mv$(pats_b), true);
code = NEWNODE(Block, mv$(nodes));
@@ -1247,7 +1253,7 @@ public:
pats.push_back( AST::Pattern(AST::Pattern::TagTuple(), sp, mv$(tuple_pats)) );
}
- auto code = NEWNODE(NamedValue, this->get_path(core_name, "cmp", "Ordering", (a < b ? "Less" : "Greater")));
+ auto code = NEWNODE(NamedValue, this->get_path(opts.core_name, "cmp", "Ordering", (a < b ? "Less" : "Greater")));
arms.push_back(AST::ExprNode_Match_Arm(
mv$(pats),
@@ -1260,7 +1266,7 @@ public:
::std::vector<AST::ExprNodeP> vals;
vals.push_back( NEWNODE(NamedValue, AST::Path("self")) );
vals.push_back( NEWNODE(NamedValue, AST::Path("v")) );
- return this->make_ret(sp, core_name, p, type, this->get_field_bounds(enm), NEWNODE(Match,
+ return this->make_ret(sp, opts.core_name, p, type, this->get_field_bounds(enm), NEWNODE(Match,
NEWNODE(Tuple, mv$(vals)),
mv$(arms)
));
@@ -1299,6 +1305,7 @@ class Deriver_Clone:
return mv$(rv);
}
AST::ExprNodeP clone_val_ref(const ::std::string& core_name, AST::ExprNodeP val) const {
+ // TODO: Hack for zero-sized arrays? (Not a 1.19 feature)
return NEWNODE(CallPath,
this->get_method_path(core_name),
vec$( NEWNODE(UniOp, AST::ExprNode_UniOp::REF, mv$(val) ) )
@@ -1317,7 +1324,7 @@ class Deriver_Clone:
public:
const char* trait_name() const override { return "Clone"; }
- AST::Impl handle_item(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, const AST::Struct& str) const override
+ AST::Impl handle_item(Span sp, const DeriveOpts& opts, const AST::GenericParams& p, const TypeRef& type, const AST::Struct& str) const override
{
const AST::Path& ty_path = type.m_data.as_Path().path;
::std::vector<AST::ExprNodeP> nodes;
@@ -1330,7 +1337,7 @@ public:
::AST::ExprNode_StructLiteral::t_values vals;
for( const auto& fld : e.ents )
{
- vals.push_back({ {}, fld.m_name, this->clone_val_ref(core_name, this->field(fld.m_name)) });
+ vals.push_back({ {}, fld.m_name, this->clone_val_ref(opts.core_name, this->field(fld.m_name)) });
}
nodes.push_back( NEWNODE(StructLiteral, ty_path, nullptr, mv$(vals)) );
),
@@ -1338,16 +1345,16 @@ public:
::std::vector<AST::ExprNodeP> vals;
for( unsigned int idx = 0; idx < e.ents.size(); idx ++ )
{
- vals.push_back( this->clone_val_ref(core_name, this->field(FMT(idx))) );
+ vals.push_back( this->clone_val_ref(opts.core_name, this->field(FMT(idx))) );
}
nodes.push_back( NEWNODE(CallPath, AST::Path(ty_path), mv$(vals)) );
)
)
- return this->make_ret(sp, core_name, p, type, this->get_field_bounds(str), NEWNODE(Block, mv$(nodes)));
+ return this->make_ret(sp, opts.core_name, p, type, this->get_field_bounds(str), NEWNODE(Block, mv$(nodes)));
}
- AST::Impl handle_item(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, const AST::Enum& enm) const override
+ AST::Impl handle_item(Span sp, const DeriveOpts& opts, 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();
@@ -1371,7 +1378,7 @@ public:
{
auto name_a = FMT("a" << idx);
pats_a.push_back( ::AST::Pattern(::AST::Pattern::TagBind(), sp, name_a, ::AST::PatternBinding::Type::REF) );
- nodes.push_back( this->clone_val_direct(core_name, NEWNODE(NamedValue, AST::Path(name_a))) );
+ nodes.push_back( this->clone_val_direct(opts.core_name, NEWNODE(NamedValue, AST::Path(name_a))) );
}
pat_a = AST::Pattern(AST::Pattern::TagNamedTuple(), sp, base_path + v.m_name, mv$(pats_a));
@@ -1385,7 +1392,7 @@ public:
{
auto name_a = FMT("a" << fld.m_name);
pats_a.push_back( ::std::make_pair(fld.m_name, ::AST::Pattern(::AST::Pattern::TagBind(), sp, name_a, ::AST::PatternBinding::Type::REF)) );
- vals.push_back({ {}, fld.m_name, this->clone_val_direct(core_name, NEWNODE(NamedValue, AST::Path(name_a))) });
+ vals.push_back({ {}, fld.m_name, this->clone_val_direct(opts.core_name, NEWNODE(NamedValue, AST::Path(name_a))) });
}
pat_a = AST::Pattern(AST::Pattern::TagStruct(), sp, base_path + v.m_name, mv$(pats_a), true);
@@ -1403,23 +1410,32 @@ public:
));
}
- return this->make_ret(sp, core_name, p, type, this->get_field_bounds(enm), NEWNODE(Match,
+ return this->make_ret(sp, opts.core_name, p, type, this->get_field_bounds(enm), NEWNODE(Match,
NEWNODE(NamedValue, AST::Path("self")),
mv$(arms)
));
}
- AST::Impl handle_item(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, const AST::Union& unn) const override
+ AST::Impl handle_item(Span sp, const DeriveOpts& opts, const AST::GenericParams& p, const TypeRef& type, const AST::Union& unn) const override
{
- // Clone on a union can only be a bitwise copy. (TODO: This requires Copy)
- auto ret = this->make_ret(sp, core_name, p, type, this->get_field_bounds(unn), NEWNODE(Deref,
+ return make_copy_clone(sp, opts, p, type, this->get_field_bounds(unn));
+ }
+private:
+ AST::Impl make_copy_clone(Span sp, const DeriveOpts& opts, const AST::GenericParams& p, const TypeRef& type, ::std::vector<TypeRef> field_bounds) const
+ {
+ // Clone on a union can only be a bitwise copy.
+ // - This requires a Copy impl. That's up to the user
+ auto ret = this->make_ret(sp, opts.core_name, p, type, ::std::move(field_bounds), NEWNODE(Deref,
NEWNODE(NamedValue, AST::Path("self"))
));
+ // TODO: What if the type is only conditionally copy? (generic over something)
+ // - Could abuse specialisation support...
+ // TODO: Are these bounds needed?
for(auto& b : ret.def().params().bounds())
{
auto& be = b.as_IsTrait();
- be.trait = AST::Path(core_name, { AST::PathNode("marker", {}), AST::PathNode("Copy", {}) });
+ be.trait = AST::Path(opts.core_name, { AST::PathNode("marker", {}), AST::PathNode("Copy", {}) });
}
return ret;
@@ -1446,18 +1462,18 @@ class Deriver_Copy:
public:
const char* trait_name() const override { return "Copy"; }
- AST::Impl handle_item(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, const AST::Struct& str) const override
+ AST::Impl handle_item(Span sp, const DeriveOpts& opts, const AST::GenericParams& p, const TypeRef& type, const AST::Struct& str) const override
{
- return this->make_ret(sp, core_name, p, type, this->get_field_bounds(str), nullptr);
+ return this->make_ret(sp, opts.core_name, p, type, this->get_field_bounds(str), nullptr);
}
- AST::Impl handle_item(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, const AST::Enum& enm) const override
+ AST::Impl handle_item(Span sp, const DeriveOpts& opts, const AST::GenericParams& p, const TypeRef& type, const AST::Enum& enm) const override
{
- return this->make_ret(sp, core_name, p, type, this->get_field_bounds(enm), nullptr);
+ return this->make_ret(sp, opts.core_name, p, type, this->get_field_bounds(enm), nullptr);
}
- AST::Impl handle_item(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, const AST::Union& unn) const override
+ AST::Impl handle_item(Span sp, const DeriveOpts& opts, const AST::GenericParams& p, const TypeRef& type, const AST::Union& unn) const override
{
- return this->make_ret(sp, core_name, p, type, this->get_field_bounds(unn), nullptr);
+ return this->make_ret(sp, opts.core_name, p, type, this->get_field_bounds(unn), nullptr);
}
} g_derive_copy;
@@ -1500,7 +1516,7 @@ class Deriver_Default:
public:
const char* trait_name() const override { return "Default"; }
- AST::Impl handle_item(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, const AST::Struct& str) const override
+ AST::Impl handle_item(Span sp, const DeriveOpts& opts, const AST::GenericParams& p, const TypeRef& type, const AST::Struct& str) const override
{
const AST::Path& ty_path = type.m_data.as_Path().path;
::std::vector<AST::ExprNodeP> nodes;
@@ -1513,7 +1529,7 @@ public:
::AST::ExprNode_StructLiteral::t_values vals;
for( const auto& fld : e.ents )
{
- vals.push_back({ {}, fld.m_name, this->default_call(core_name) });
+ vals.push_back({ {}, fld.m_name, this->default_call(opts.core_name) });
}
nodes.push_back( NEWNODE(StructLiteral, ty_path, nullptr, mv$(vals)) );
),
@@ -1521,16 +1537,16 @@ public:
::std::vector<AST::ExprNodeP> vals;
for( unsigned int idx = 0; idx < e.ents.size(); idx ++ )
{
- vals.push_back( this->default_call(core_name) );
+ vals.push_back( this->default_call(opts.core_name) );
}
nodes.push_back( NEWNODE(CallPath, AST::Path(ty_path), mv$(vals)) );
)
)
- return this->make_ret(sp, core_name, p, type, this->get_field_bounds(str), NEWNODE(Block, mv$(nodes)));
+ return this->make_ret(sp, opts.core_name, p, type, this->get_field_bounds(str), NEWNODE(Block, mv$(nodes)));
}
- AST::Impl handle_item(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, const AST::Enum& enm) const override
+ AST::Impl handle_item(Span sp, const DeriveOpts& opts, const AST::GenericParams& p, const TypeRef& type, const AST::Enum& enm) const override
{
ERROR(sp, E0000, "Default cannot be derived for enums");
}
@@ -1592,7 +1608,7 @@ class Deriver_Hash:
public:
const char* trait_name() const override { return "Hash"; }
- AST::Impl handle_item(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, const AST::Struct& str) const override
+ AST::Impl handle_item(Span sp, const DeriveOpts& opts, const AST::GenericParams& p, const TypeRef& type, const AST::Struct& str) const override
{
::std::vector<AST::ExprNodeP> nodes;
@@ -1602,21 +1618,21 @@ public:
(Struct,
for( const auto& fld : e.ents )
{
- nodes.push_back( this->hash_val_ref(core_name, this->field(fld.m_name)) );
+ nodes.push_back( this->hash_val_ref(opts.core_name, this->field(fld.m_name)) );
}
),
(Tuple,
for( unsigned int idx = 0; idx < e.ents.size(); idx ++ )
{
- nodes.push_back( this->hash_val_ref(core_name, this->field(FMT(idx))) );
+ nodes.push_back( this->hash_val_ref(opts.core_name, this->field(FMT(idx))) );
}
)
)
- return this->make_ret(sp, core_name, p, type, this->get_field_bounds(str), NEWNODE(Block, mv$(nodes)));
+ return this->make_ret(sp, opts.core_name, p, type, this->get_field_bounds(str), NEWNODE(Block, mv$(nodes)));
}
- AST::Impl handle_item(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, const AST::Enum& enm) const override
+ AST::Impl handle_item(Span sp, const DeriveOpts& opts, 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();
@@ -1628,7 +1644,7 @@ public:
AST::ExprNodeP code;
AST::Pattern pat_a;
- auto var_idx_hash = this->hash_val_ref( core_name, NEWNODE(Integer, var_idx, CORETYPE_UINT) );
+ auto var_idx_hash = this->hash_val_ref( opts.core_name, NEWNODE(Integer, var_idx, CORETYPE_UINT) );
TU_MATCH(::AST::EnumVariantData, (v.m_data), (e),
(Value,
@@ -1644,7 +1660,7 @@ public:
{
auto name_a = FMT("a" << idx);
pats_a.push_back( ::AST::Pattern(::AST::Pattern::TagBind(), sp, name_a, ::AST::PatternBinding::Type::REF) );
- nodes.push_back( this->hash_val_direct(core_name, NEWNODE(NamedValue, AST::Path(name_a))) );
+ nodes.push_back( this->hash_val_direct(opts.core_name, NEWNODE(NamedValue, AST::Path(name_a))) );
}
pat_a = AST::Pattern(AST::Pattern::TagNamedTuple(), sp, base_path + v.m_name, mv$(pats_a));
@@ -1659,7 +1675,7 @@ public:
{
auto name_a = FMT("a" << fld.m_name);
pats_a.push_back( ::std::make_pair(fld.m_name, ::AST::Pattern(::AST::Pattern::TagBind(), sp, name_a, ::AST::PatternBinding::Type::REF)) );
- nodes.push_back( this->hash_val_direct(core_name, NEWNODE(NamedValue, AST::Path(name_a))) );
+ nodes.push_back( this->hash_val_direct(opts.core_name, NEWNODE(NamedValue, AST::Path(name_a))) );
}
pat_a = AST::Pattern(AST::Pattern::TagStruct(), sp, base_path + v.m_name, mv$(pats_a), true);
@@ -1677,7 +1693,7 @@ public:
));
}
- return this->make_ret(sp, core_name, p, type, this->get_field_bounds(enm), NEWNODE(Match,
+ return this->make_ret(sp, opts.core_name, p, type, this->get_field_bounds(enm), NEWNODE(Match,
NEWNODE(NamedValue, AST::Path("self")),
mv$(arms)
));
@@ -1752,7 +1768,7 @@ class Deriver_RustcEncodable:
public:
const char* trait_name() const override { return "RustcEncodable"; }
- AST::Impl handle_item(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, const AST::Struct& str) const override
+ AST::Impl handle_item(Span sp, const DeriveOpts& opts, const AST::GenericParams& p, const TypeRef& type, const AST::Struct& str) const override
{
const ::std::string& struct_name = type.m_data.as_Path().path.nodes().back().name();
@@ -1782,13 +1798,13 @@ public:
)
)
- nodes.push_back( this->get_val_ok(core_name) );
+ nodes.push_back( this->get_val_ok(opts.core_name) );
auto closure = this->enc_closure( sp, NEWNODE(Block, mv$(nodes)) );
::AST::ExprNodeP node;
TU_MATCH(AST::StructData, (str.m_data), (e),
(Unit,
- node = get_val_ok(core_name);
+ node = get_val_ok(opts.core_name);
),
(Struct,
node = NEWNODE(CallPath,
@@ -1804,10 +1820,10 @@ public:
)
)
- return this->make_ret(sp, core_name, p, type, this->get_field_bounds(str), mv$(node));
+ return this->make_ret(sp, opts.core_name, p, type, this->get_field_bounds(str), mv$(node));
}
- AST::Impl handle_item(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, const AST::Enum& enm) const override
+ AST::Impl handle_item(Span sp, const DeriveOpts& opts, 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();
@@ -1827,7 +1843,7 @@ public:
NEWNODE(String, v.m_name),
NEWNODE(Integer, var_idx, CORETYPE_UINT),
NEWNODE(Integer, 0, CORETYPE_UINT),
- this->enc_closure(sp, this->get_val_ok(core_name))
+ this->enc_closure(sp, this->get_val_ok(opts.core_name))
)
);
pat_a = AST::Pattern(AST::Pattern::TagValue(), sp, AST::Pattern::Value::make_Named(base_path + v.m_name));
@@ -1848,7 +1864,7 @@ public:
)
) );
}
- nodes.push_back( this->get_val_ok(core_name) );
+ nodes.push_back( this->get_val_ok(opts.core_name) );
code = NEWNODE(CallPath, this->get_trait_path_Encoder() + "emit_enum_variant",
vec$(
@@ -1881,7 +1897,7 @@ public:
) );
idx ++;
}
- nodes.push_back( this->get_val_ok(core_name) );
+ nodes.push_back( this->get_val_ok(opts.core_name) );
pat_a = AST::Pattern(AST::Pattern::TagStruct(), sp, base_path + v.m_name, mv$(pats_a), true);
code = NEWNODE(CallPath, this->get_trait_path_Encoder() + "emit_enum_struct_variant",
@@ -1913,7 +1929,7 @@ public:
vec$( NEWNODE(NamedValue, AST::Path("s")), NEWNODE(String, enum_name), this->enc_closure(sp, mv$(node_match)) )
);
- return this->make_ret(sp, core_name, p, type, this->get_field_bounds(enm), mv$(node));
+ return this->make_ret(sp, opts.core_name, p, type, this->get_field_bounds(enm), mv$(node));
}
} g_derive_rustc_encodable;
@@ -1994,7 +2010,7 @@ class Deriver_RustcDecodable:
public:
const char* trait_name() const override { return "RustcDecodable"; }
- AST::Impl handle_item(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, const AST::Struct& str) const override
+ AST::Impl handle_item(Span sp, const DeriveOpts& opts, const AST::GenericParams& p, const TypeRef& type, const AST::Struct& str) const override
{
AST::Path base_path = type.m_data.as_Path().path;
const ::std::string& struct_name = type.m_data.as_Path().path.nodes().back().name();
@@ -2029,14 +2045,14 @@ public:
)
)
- auto closure = this->dec_closure( sp, this->get_val_ok(core_name, mv$(node_v)) );
+ auto closure = this->dec_closure( sp, this->get_val_ok(opts.core_name, mv$(node_v)) );
auto args = vec$( NEWNODE(NamedValue, AST::Path("d")), NEWNODE(String, struct_name), AST::ExprNodeP(), mv$(closure) );
::AST::ExprNodeP node;
TU_MATCH(AST::StructData, (str.m_data), (e),
(Unit,
- node = this->get_val_ok(core_name, NEWNODE(NamedValue, mv$(base_path)));
+ node = this->get_val_ok(opts.core_name, NEWNODE(NamedValue, mv$(base_path)));
),
(Struct,
assert( !args[2] );
@@ -2050,10 +2066,10 @@ public:
)
)
- return this->make_ret(sp, core_name, p, type, this->get_field_bounds(str), mv$(node));
+ return this->make_ret(sp, opts.core_name, p, type, this->get_field_bounds(str), mv$(node));
}
- AST::Impl handle_item(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, const AST::Enum& enm) const override
+ AST::Impl handle_item(Span sp, const DeriveOpts& opts, 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();
@@ -2117,7 +2133,7 @@ public:
arms.push_back(AST::ExprNode_Match_Arm(
mv$(pats),
nullptr,
- this->get_val_ok(core_name, mv$(code))
+ this->get_val_ok(opts.core_name, mv$(code))
));
var_name_strs.push_back( NEWNODE(String, v.m_name) );
}
@@ -2127,7 +2143,7 @@ public:
arms.push_back(AST::ExprNode_Match_Arm(
::make_vec1( AST::Pattern() ),
nullptr,
- this->get_val_err_str(core_name, "enum value unknown")
+ this->get_val_err_str(opts.core_name, "enum value unknown")
));
}
@@ -2155,7 +2171,7 @@ public:
vec$( NEWNODE(NamedValue, AST::Path("d")), NEWNODE(String, enum_name), this->dec_closure(sp, mv$(node_rev)) )
);
- return this->make_ret(sp, core_name, p, type, this->get_field_bounds(enm), mv$(node));
+ return this->make_ret(sp, opts.core_name, p, type, this->get_field_bounds(enm), mv$(node));
}
} g_derive_rustc_decodable;
@@ -2199,13 +2215,18 @@ static void derive_item(const Span& sp, const AST::Crate& crate, AST::Module& mo
types_args.m_types.push_back( TypeRef(TypeRef::TagArg(), sp, param.name()) );
}
+ DeriveOpts opts = {
+ (crate.m_load_std == ::AST::Crate::LOAD_NONE ? "" : "core"),
+ attr.items()
+ };
+
::std::vector< ::std::string> missing_handlers;
for( const auto& trait : attr.items() )
{
DEBUG("- " << trait.name());
auto dp = find_impl(trait.name());
if( dp ) {
- mod.add_item(false, "", dp->handle_item(sp, (crate.m_load_std == ::AST::Crate::LOAD_NONE ? "" : "core"), params, type, item), {} );
+ mod.add_item(false, "", dp->handle_item(sp, opts, params, type, item), {} );
continue ;
}
@@ -2261,7 +2282,7 @@ public:
TODO(sp, "Handle #[derive] for other item types - " << i.tag_str());
),
(None,
- //
+ // Ignore, it's been deleted
),
(Union,
derive_item(sp, crate, mod, attr, path, e);