Skip to content

Commit 1b5fc50

Browse files
committed
---
yaml --- r: 148983 b: refs/heads/try2 c: 6a8b3ae h: refs/heads/master i: 148981: 537dc9f 148979: 6331e58 148975: 79d144c v: v3
1 parent 25bf6f7 commit 1b5fc50

File tree

4 files changed

+183
-1
lines changed

4 files changed

+183
-1
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ refs/heads/snap-stage3: 78a7676898d9f80ab540c6df5d4c9ce35bb50463
55
refs/heads/try: 519addf6277dbafccbb4159db4b710c37eaa2ec5
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/ndm: f3868061cd7988080c30d6d5bf352a5a5fe2460b
8-
refs/heads/try2: 5d63910f90afcb601a765bba6bd4bb8d52ebef81
8+
refs/heads/try2: 6a8b3ae22fbf514d6dc920abebe478e95c38e3ad
99
refs/heads/dist-snap: ba4081a5a8573875fed17545846f6f6902c8ba8d
1010
refs/tags/release-0.2: c870d2dffb391e14efb05aa27898f1f6333a9596
1111
refs/tags/release-0.3: b5f0d0f648d9a6153664837026ba1be43d3e2503

branches/try2/src/libsyntax/ext/deriving/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ pub mod encodable;
2828
pub mod decodable;
2929
pub mod rand;
3030
pub mod to_str;
31+
pub mod show;
3132
pub mod zero;
3233
pub mod default;
3334
pub mod primitive;
@@ -83,6 +84,7 @@ pub fn expand_meta_deriving(cx: &mut ExtCtxt,
8384
"Rand" => expand!(rand::expand_deriving_rand),
8485

8586
"ToStr" => expand!(to_str::expand_deriving_to_str),
87+
"Show" => expand!(show::expand_deriving_show),
8688

8789
"Zero" => expand!(zero::expand_deriving_zero),
8890
"Default" => expand!(default::expand_deriving_default),
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
use ast;
12+
use ast::{MetaItem, Item, Expr};
13+
use codemap::Span;
14+
use ext::format;
15+
use ext::base::ExtCtxt;
16+
use ext::build::AstBuilder;
17+
use ext::deriving::generic::*;
18+
19+
use parse::token;
20+
21+
use std::hashmap::HashMap;
22+
23+
pub fn expand_deriving_show(cx: &mut ExtCtxt,
24+
span: Span,
25+
mitem: @MetaItem,
26+
in_items: ~[@Item])
27+
-> ~[@Item] {
28+
// &mut ::std::fmt::Formatter
29+
let fmtr = Ptr(~Literal(Path::new(~["std", "fmt", "Formatter"])),
30+
Borrowed(None, ast::MutMutable));
31+
32+
let trait_def = TraitDef {
33+
cx: cx, span: span,
34+
35+
path: Path::new(~["std", "fmt", "Show"]),
36+
additional_bounds: ~[],
37+
generics: LifetimeBounds::empty(),
38+
methods: ~[
39+
MethodDef {
40+
name: "fmt",
41+
generics: LifetimeBounds::empty(),
42+
explicit_self: borrowed_explicit_self(),
43+
args: ~[fmtr],
44+
ret_ty: Literal(Path::new(~["std", "fmt", "Result"])),
45+
inline: false,
46+
const_nonmatching: false,
47+
combine_substructure: show_substructure
48+
}
49+
]
50+
};
51+
trait_def.expand(mitem, in_items)
52+
}
53+
54+
// we construct a format string and then defer to std::fmt, since that
55+
// knows what's up with formatting at so on.
56+
fn show_substructure(cx: &mut ExtCtxt, span: Span,
57+
substr: &Substructure) -> @Expr {
58+
// build `<name>`, `<name>({}, {}, ...)` or `<name> { <field>: {},
59+
// <field>: {}, ... }` based on the "shape".
60+
//
61+
// Easy start: they all start with the name.
62+
let name = match *substr.fields {
63+
Struct(_) => substr.type_ident,
64+
EnumMatching(_, v, _) => v.node.name,
65+
66+
EnumNonMatching(..) | StaticStruct(..) | StaticEnum(..) => {
67+
cx.span_bug(span, "nonsensical .fields in `#[deriving(Show)]`")
68+
}
69+
};
70+
71+
let mut format_string = token::get_ident(name.name).get().to_owned();
72+
// the internal fields we're actually formatting
73+
let mut exprs = ~[];
74+
75+
// Getting harder... making the format string:
76+
match *substr.fields {
77+
// unit struct/nullary variant: no work necessary!
78+
Struct([]) | EnumMatching(_, _, []) => {}
79+
80+
Struct(ref fields) | EnumMatching(_, _, ref fields) => {
81+
if fields[0].name.is_none() {
82+
// tuple struct/"normal" variant
83+
84+
format_string.push_str("(");
85+
86+
for (i, field) in fields.iter().enumerate() {
87+
if i != 0 { format_string.push_str(", "); }
88+
89+
format_string.push_str("{}");
90+
91+
exprs.push(field.self_);
92+
}
93+
94+
format_string.push_str(")");
95+
} else {
96+
// normal struct/struct variant
97+
98+
format_string.push_str(" \\{");
99+
100+
for (i, field) in fields.iter().enumerate() {
101+
if i != 0 { format_string.push_str(","); }
102+
103+
let name = token::get_ident(field.name.unwrap().name);
104+
format_string.push_str(" ");
105+
format_string.push_str(name.get());
106+
format_string.push_str(": {}");
107+
108+
exprs.push(field.self_);
109+
}
110+
111+
format_string.push_str(" \\}");
112+
}
113+
}
114+
_ => unreachable!()
115+
}
116+
117+
// AST construction!
118+
// we're basically calling
119+
//
120+
// format_arg!(|__args| ::std::fmt::write(fmt.buf, __args), "<format_string>", exprs...)
121+
//
122+
// but doing it directly via ext::format.
123+
let formatter = substr.nonself_args[0];
124+
let buf = cx.expr_field_access(span, formatter, cx.ident_of("buf"));
125+
126+
let std_write = ~[cx.ident_of("std"), cx.ident_of("fmt"), cx.ident_of("write")];
127+
let args = cx.ident_of("__args");
128+
let write_call = cx.expr_call_global(span, std_write, ~[buf, cx.expr_ident(span, args)]);
129+
let format_closure = cx.lambda_expr(span, ~[args], write_call);
130+
131+
let s = token::intern_and_get_ident(format_string);
132+
let format_string = cx.expr_str(span, s);
133+
134+
// phew, not our responsibility any more!
135+
format::expand_preparsed_format_args(cx, span,
136+
format_closure,
137+
format_string, exprs, HashMap::new())
138+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#[feature(struct_variant, macro_rules)];
12+
13+
#[deriving(Show)]
14+
struct Unit;
15+
16+
#[deriving(Show)]
17+
struct Tuple(int, uint);
18+
19+
#[deriving(Show)]
20+
struct Struct { x: int, y: uint }
21+
22+
#[deriving(Show)]
23+
enum Enum {
24+
Nullary,
25+
Variant(int, uint),
26+
StructVariant { x: int, y : uint }
27+
}
28+
29+
macro_rules! t {
30+
($x:expr, $expected:expr) => {
31+
assert_eq!(format!("{}", $x), $expected.to_owned())
32+
}
33+
}
34+
35+
pub fn main() {
36+
t!(Unit, "Unit");
37+
t!(Tuple(1, 2), "Tuple(1, 2)");
38+
t!(Struct { x: 1, y: 2 }, "Struct { x: 1, y: 2 }");
39+
t!(Nullary, "Nullary");
40+
t!(Variant(1, 2), "Variant(1, 2)");
41+
t!(StructVariant { x: 1, y: 2 }, "StructVariant { x: 1, y: 2 }");
42+
}

0 commit comments

Comments
 (0)