Add cs_fold1 for better derives
This commit is contained in:
parent
59ee333a0e
commit
44efb05edf
1 changed files with 92 additions and 17 deletions
|
@ -1676,21 +1676,14 @@ impl<'a> TraitDef<'a> {
|
||||||
|
|
||||||
// helpful premade recipes
|
// helpful premade recipes
|
||||||
|
|
||||||
/// Fold the fields. `use_foldl` controls whether this is done
|
pub fn cs_fold_fields<'a, F>(use_foldl: bool,
|
||||||
/// left-to-right (`true`) or right-to-left (`false`).
|
|
||||||
pub fn cs_fold<F>(use_foldl: bool,
|
|
||||||
mut f: F,
|
mut f: F,
|
||||||
base: P<Expr>,
|
base: P<Expr>,
|
||||||
mut enum_nonmatch_f: EnumNonMatchCollapsedFunc,
|
|
||||||
cx: &mut ExtCtxt,
|
cx: &mut ExtCtxt,
|
||||||
trait_span: Span,
|
all_fields: &[FieldInfo<'a>])
|
||||||
substructure: &Substructure)
|
|
||||||
-> P<Expr>
|
-> P<Expr>
|
||||||
where F: FnMut(&mut ExtCtxt, Span, P<Expr>, P<Expr>, &[P<Expr>]) -> P<Expr>
|
where F: FnMut(&mut ExtCtxt, Span, P<Expr>, P<Expr>, &[P<Expr>]) -> P<Expr>
|
||||||
{
|
{
|
||||||
match *substructure.fields {
|
|
||||||
EnumMatching(.., ref all_fields) |
|
|
||||||
Struct(_, ref all_fields) => {
|
|
||||||
if use_foldl {
|
if use_foldl {
|
||||||
all_fields.iter().fold(base, |old, field| {
|
all_fields.iter().fold(base, |old, field| {
|
||||||
f(cx, field.span, old, field.self_.clone(), &field.other)
|
f(cx, field.span, old, field.self_.clone(), &field.other)
|
||||||
|
@ -1700,17 +1693,99 @@ pub fn cs_fold<F>(use_foldl: bool,
|
||||||
f(cx, field.span, old, field.self_.clone(), &field.other)
|
f(cx, field.span, old, field.self_.clone(), &field.other)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn cs_fold_enumnonmatch(mut enum_nonmatch_f: EnumNonMatchCollapsedFunc,
|
||||||
|
cx: &mut ExtCtxt,
|
||||||
|
trait_span: Span,
|
||||||
|
substructure: &Substructure)
|
||||||
|
-> P<Expr>
|
||||||
|
{
|
||||||
|
match *substructure.fields {
|
||||||
EnumNonMatchingCollapsed(ref all_args, _, tuple) => {
|
EnumNonMatchingCollapsed(ref all_args, _, tuple) => {
|
||||||
enum_nonmatch_f(cx,
|
enum_nonmatch_f(cx,
|
||||||
trait_span,
|
trait_span,
|
||||||
(&all_args[..], tuple),
|
(&all_args[..], tuple),
|
||||||
substructure.nonself_args)
|
substructure.nonself_args)
|
||||||
}
|
}
|
||||||
StaticEnum(..) | StaticStruct(..) => cx.span_bug(trait_span, "static function in `derive`"),
|
_ => cx.span_bug(trait_span, "cs_fold_enumnonmatch expected an EnumNonMatchingCollapsed")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn cs_fold_static(cx: &mut ExtCtxt,
|
||||||
|
trait_span: Span)
|
||||||
|
-> P<Expr>
|
||||||
|
{
|
||||||
|
cx.span_bug(trait_span, "static function in `derive`")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Fold the fields. `use_foldl` controls whether this is done
|
||||||
|
/// left-to-right (`true`) or right-to-left (`false`).
|
||||||
|
pub fn cs_fold<F>(use_foldl: bool,
|
||||||
|
f: F,
|
||||||
|
base: P<Expr>,
|
||||||
|
enum_nonmatch_f: EnumNonMatchCollapsedFunc,
|
||||||
|
cx: &mut ExtCtxt,
|
||||||
|
trait_span: Span,
|
||||||
|
substructure: &Substructure)
|
||||||
|
-> P<Expr>
|
||||||
|
where F: FnMut(&mut ExtCtxt, Span, P<Expr>, P<Expr>, &[P<Expr>]) -> P<Expr>
|
||||||
|
{
|
||||||
|
match *substructure.fields {
|
||||||
|
EnumMatching(.., ref all_fields) |
|
||||||
|
Struct(_, ref all_fields) => {
|
||||||
|
cs_fold_fields(use_foldl, f, base, cx, all_fields)
|
||||||
|
}
|
||||||
|
EnumNonMatchingCollapsed(..) => {
|
||||||
|
cs_fold_enumnonmatch(enum_nonmatch_f, cx, trait_span, substructure)
|
||||||
|
}
|
||||||
|
StaticEnum(..) | StaticStruct(..) => {
|
||||||
|
cs_fold_static(cx, trait_span)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Special version of `cs_fold` that uses the result of a function call on the first field
|
||||||
|
/// as the base case when is at least 1 field, and the usual base case when there are zero fields.
|
||||||
|
pub fn cs_fold1<F, B>(use_foldl: bool,
|
||||||
|
f: F,
|
||||||
|
mut b: B,
|
||||||
|
enum_nonmatch_f: EnumNonMatchCollapsedFunc,
|
||||||
|
cx: &mut ExtCtxt,
|
||||||
|
trait_span: Span,
|
||||||
|
substructure: &Substructure)
|
||||||
|
-> P<Expr>
|
||||||
|
where F: FnMut(&mut ExtCtxt, Span, P<Expr>, P<Expr>, &[P<Expr>]) -> P<Expr>,
|
||||||
|
B: FnMut(&mut ExtCtxt, Option<(Span, P<Expr>, &[P<Expr>])>) -> P<Expr>
|
||||||
|
{
|
||||||
|
match *substructure.fields {
|
||||||
|
EnumMatching(.., ref all_fields) |
|
||||||
|
Struct(_, ref all_fields) => {
|
||||||
|
let (base, all_fields) = match (all_fields.is_empty(), use_foldl) {
|
||||||
|
(false, true) => {
|
||||||
|
let field = &all_fields[0];
|
||||||
|
let args = (field.span, field.self_.clone(), &field.other[..]);
|
||||||
|
(b(cx, Some(args)), &all_fields[1..])
|
||||||
|
}
|
||||||
|
(false, false) => {
|
||||||
|
let idx = all_fields.len() - 1;
|
||||||
|
let field = &all_fields[idx];
|
||||||
|
let args = (field.span, field.self_.clone(), &field.other[..]);
|
||||||
|
(b(cx, Some(args)), &all_fields[..idx])
|
||||||
|
}
|
||||||
|
(true, _) => (b(cx, None), &all_fields[..])
|
||||||
|
};
|
||||||
|
|
||||||
|
cs_fold_fields(use_foldl, f, base, cx, all_fields)
|
||||||
|
}
|
||||||
|
EnumNonMatchingCollapsed(..) => {
|
||||||
|
cs_fold_enumnonmatch(enum_nonmatch_f, cx, trait_span, substructure)
|
||||||
|
}
|
||||||
|
StaticEnum(..) | StaticStruct(..) => {
|
||||||
|
cs_fold_static(cx, trait_span)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Call the method that is being derived on all the fields, and then
|
/// Call the method that is being derived on all the fields, and then
|
||||||
/// process the collected results. i.e.
|
/// process the collected results. i.e.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue