diff options
| author | bors <bors@rust-lang.org> | 2013-06-22 17:13:51 -0700 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2013-06-22 17:13:51 -0700 |
| commit | fc83d82fec5bc338ffa4aaf00ca2aef6bfd473a4 (patch) | |
| tree | efbdac2a1b9c2f2f29551d33f8cc5dc61f4e565b /src/libsyntax/ext | |
| parent | 0739c6b5a00372e6c7ed2f9bdafea8a8c0e383a6 (diff) | |
| parent | 30d755957a0f2cc3be3b355671da79cdf34fd50a (diff) | |
| download | rust-fc83d82fec5bc338ffa4aaf00ca2aef6bfd473a4.tar.gz rust-fc83d82fec5bc338ffa4aaf00ca2aef6bfd473a4.zip | |
auto merge of #7204 : alexcrichton/rust/deriving-to-string, r=pcwalton
Closes #7180 and #7179.
Before, the `deriving(ToStr)` attribute was essentially `fmt!("%?")`. This changes it to recursively invoke `to_str()` on fields instead of relying on `fmt!`-style things. This seems more natural to me and what should actually be expected.
Diffstat (limited to 'src/libsyntax/ext')
| -rw-r--r-- | src/libsyntax/ext/deriving/to_str.rs | 75 |
1 files changed, 64 insertions, 11 deletions
diff --git a/src/libsyntax/ext/deriving/to_str.rs b/src/libsyntax/ext/deriving/to_str.rs index 41be3a775c1..4cd168b12c0 100644 --- a/src/libsyntax/ext/deriving/to_str.rs +++ b/src/libsyntax/ext/deriving/to_str.rs @@ -10,6 +10,7 @@ use core::prelude::*; +use ast; use ast::{meta_item, item, expr}; use codemap::span; use ext::base::ExtCtxt; @@ -40,16 +41,68 @@ pub fn expand_deriving_to_str(cx: @ExtCtxt, trait_def.expand(cx, span, mitem, in_items) } -fn to_str_substructure(cx: @ExtCtxt, span: span, substr: &Substructure) -> @expr { - match substr.self_args { - [self_obj] => { - let self_addr = cx.expr_addr_of(span, self_obj); - cx.expr_call_global(span, - ~[cx.ident_of("std"), - cx.ident_of("sys"), - cx.ident_of("log_str")], - ~[self_addr]) +// It used to be the case that this deriving implementation invoked +// std::sys::log_str, but this isn't sufficient because it doesn't invoke the +// to_str() method on each field. Hence we mirror the logic of the log_str() +// method, but with tweaks to call to_str() on sub-fields. +fn to_str_substructure(cx: @ExtCtxt, span: span, + substr: &Substructure) -> @expr { + let to_str = cx.ident_of("to_str"); + + let doit = |start: &str, end: @str, name: ast::ident, + fields: &[(Option<ast::ident>, @expr, ~[@expr])]| { + if fields.len() == 0 { + cx.expr_str_uniq(span, cx.str_of(name)) + } else { + let buf = cx.ident_of("buf"); + let start = cx.str_of(name) + start; + let init = cx.expr_str_uniq(span, start.to_managed()); + let mut stmts = ~[cx.stmt_let(span, true, buf, init)]; + let push_str = cx.ident_of("push_str"); + + let push = |s: @expr| { + let ebuf = cx.expr_ident(span, buf); + let call = cx.expr_method_call(span, ebuf, push_str, ~[s]); + stmts.push(cx.stmt_expr(call)); + }; + + for fields.iter().enumerate().advance |(i, &(name, e, _))| { + if i > 0 { + push(cx.expr_str(span, @", ")); + } + match name { + None => {} + Some(id) => { + let name = cx.str_of(id) + ": "; + push(cx.expr_str(span, name.to_managed())); + } + } + push(cx.expr_method_call(span, e, to_str, ~[])); + } + push(cx.expr_str(span, end)); + + cx.expr_blk(cx.blk(span, stmts, Some(cx.expr_ident(span, buf)))) + } + }; + + return match *substr.fields { + Struct(ref fields) => { + if fields.len() == 0 || fields[0].n0_ref().is_none() { + doit("(", @")", substr.type_ident, *fields) + } else { + doit("{", @"}", substr.type_ident, *fields) + } } - _ => cx.span_bug(span, "Invalid number of arguments in `deriving(ToStr)`") - } + + EnumMatching(_, variant, ref fields) => { + match variant.node.kind { + ast::tuple_variant_kind(*) => + doit("(", @")", variant.node.name, *fields), + ast::struct_variant_kind(*) => + doit("{", @"}", variant.node.name, *fields), + } + } + + _ => cx.bug("expected Struct or EnumMatching in deriving(ToStr)") + }; } |
