diff options
| author | bors <bors@rust-lang.org> | 2014-02-07 20:46:30 -0800 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2014-02-07 20:46:30 -0800 |
| commit | dde2e0b3865ba040261d2078db371adbefb32506 (patch) | |
| tree | f7e98095e05ec7f5be10dd73f7e307f3e0921c5d /src/libsyntax | |
| parent | 80c6c73647cc3294c587d8089d6628d8969f0b71 (diff) | |
| parent | b89afe2af7bdd9b65836b278c6e0322a8f91fb07 (diff) | |
| download | rust-dde2e0b3865ba040261d2078db371adbefb32506.tar.gz rust-dde2e0b3865ba040261d2078db371adbefb32506.zip | |
auto merge of #12066 : huonw/rust/show2, r=alexcrichton
- Convert the formatting traits to `&self` rather than `_: &Self`
- Rejig `syntax::ext::{format,deriving}` a little in preparation
- Implement `#[deriving(Show)]`
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/ext/base.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/clone.rs | 6 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/cmp/eq.rs | 6 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/cmp/ord.rs | 4 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/cmp/totaleq.rs | 4 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/cmp/totalord.rs | 12 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/decodable.rs | 23 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/default.rs | 4 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/encodable.rs | 4 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/generic.rs | 32 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/iter_bytes.rs | 4 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/mod.rs | 20 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/primitive.rs | 4 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/rand.rs | 11 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/show.rs | 138 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/to_str.rs | 4 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/zero.rs | 4 | ||||
| -rw-r--r-- | src/libsyntax/ext/format.rs | 166 | ||||
| -rw-r--r-- | src/libsyntax/parse/token.rs | 4 |
19 files changed, 298 insertions, 154 deletions
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 800eda64d51..848f4ba3871 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -36,7 +36,7 @@ pub struct MacroDef { } pub type ItemDecorator = - fn(&ExtCtxt, Span, @ast::MetaItem, ~[@ast::Item]) -> ~[@ast::Item]; + fn(&mut ExtCtxt, Span, @ast::MetaItem, ~[@ast::Item]) -> ~[@ast::Item]; pub struct BasicMacroExpander { expander: MacroExpanderFn, diff --git a/src/libsyntax/ext/deriving/clone.rs b/src/libsyntax/ext/deriving/clone.rs index 567b89d3453..17361240628 100644 --- a/src/libsyntax/ext/deriving/clone.rs +++ b/src/libsyntax/ext/deriving/clone.rs @@ -14,7 +14,7 @@ use ext::base::ExtCtxt; use ext::build::AstBuilder; use ext::deriving::generic::*; -pub fn expand_deriving_clone(cx: &ExtCtxt, +pub fn expand_deriving_clone(cx: &mut ExtCtxt, span: Span, mitem: @MetaItem, in_items: ~[@Item]) @@ -42,7 +42,7 @@ pub fn expand_deriving_clone(cx: &ExtCtxt, trait_def.expand(mitem, in_items) } -pub fn expand_deriving_deep_clone(cx: &ExtCtxt, +pub fn expand_deriving_deep_clone(cx: &mut ExtCtxt, span: Span, mitem: @MetaItem, in_items: ~[@Item]) @@ -74,7 +74,7 @@ pub fn expand_deriving_deep_clone(cx: &ExtCtxt, fn cs_clone( name: &str, - cx: &ExtCtxt, trait_span: Span, + cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) -> @Expr { let clone_ident = substr.method_ident; let ctor_ident; diff --git a/src/libsyntax/ext/deriving/cmp/eq.rs b/src/libsyntax/ext/deriving/cmp/eq.rs index 99b5163214a..a469c4a960b 100644 --- a/src/libsyntax/ext/deriving/cmp/eq.rs +++ b/src/libsyntax/ext/deriving/cmp/eq.rs @@ -14,17 +14,17 @@ use ext::base::ExtCtxt; use ext::build::AstBuilder; use ext::deriving::generic::*; -pub fn expand_deriving_eq(cx: &ExtCtxt, +pub fn expand_deriving_eq(cx: &mut ExtCtxt, span: Span, mitem: @MetaItem, in_items: ~[@Item]) -> ~[@Item] { // structures are equal if all fields are equal, and non equal, if // any fields are not equal or if the enum variants are different - fn cs_eq(cx: &ExtCtxt, span: Span, substr: &Substructure) -> @Expr { + fn cs_eq(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> @Expr { cs_and(|cx, span, _, _| cx.expr_bool(span, false), cx, span, substr) } - fn cs_ne(cx: &ExtCtxt, span: Span, substr: &Substructure) -> @Expr { + fn cs_ne(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> @Expr { cs_or(|cx, span, _, _| cx.expr_bool(span, true), cx, span, substr) } diff --git a/src/libsyntax/ext/deriving/cmp/ord.rs b/src/libsyntax/ext/deriving/cmp/ord.rs index 5a02d8eead8..83f623e3066 100644 --- a/src/libsyntax/ext/deriving/cmp/ord.rs +++ b/src/libsyntax/ext/deriving/cmp/ord.rs @@ -15,7 +15,7 @@ use ext::base::ExtCtxt; use ext::build::AstBuilder; use ext::deriving::generic::*; -pub fn expand_deriving_ord(cx: &ExtCtxt, +pub fn expand_deriving_ord(cx: &mut ExtCtxt, span: Span, mitem: @MetaItem, in_items: ~[@Item]) -> ~[@Item] { @@ -51,7 +51,7 @@ pub fn expand_deriving_ord(cx: &ExtCtxt, } /// Strict inequality. -fn cs_op(less: bool, equal: bool, cx: &ExtCtxt, span: Span, substr: &Substructure) -> @Expr { +fn cs_op(less: bool, equal: bool, cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> @Expr { let op = if less {ast::BiLt} else {ast::BiGt}; cs_fold( false, // need foldr, diff --git a/src/libsyntax/ext/deriving/cmp/totaleq.rs b/src/libsyntax/ext/deriving/cmp/totaleq.rs index 6a1aaeb2f9e..0a38a2ce30d 100644 --- a/src/libsyntax/ext/deriving/cmp/totaleq.rs +++ b/src/libsyntax/ext/deriving/cmp/totaleq.rs @@ -14,11 +14,11 @@ use ext::base::ExtCtxt; use ext::build::AstBuilder; use ext::deriving::generic::*; -pub fn expand_deriving_totaleq(cx: &ExtCtxt, +pub fn expand_deriving_totaleq(cx: &mut ExtCtxt, span: Span, mitem: @MetaItem, in_items: ~[@Item]) -> ~[@Item] { - fn cs_equals(cx: &ExtCtxt, span: Span, substr: &Substructure) -> @Expr { + fn cs_equals(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> @Expr { cs_and(|cx, span, _, _| cx.expr_bool(span, false), cx, span, substr) } diff --git a/src/libsyntax/ext/deriving/cmp/totalord.rs b/src/libsyntax/ext/deriving/cmp/totalord.rs index f1e360f20ba..27a766c0e75 100644 --- a/src/libsyntax/ext/deriving/cmp/totalord.rs +++ b/src/libsyntax/ext/deriving/cmp/totalord.rs @@ -16,7 +16,7 @@ use ext::build::AstBuilder; use ext::deriving::generic::*; use std::cmp::{Ordering, Equal, Less, Greater}; -pub fn expand_deriving_totalord(cx: &ExtCtxt, +pub fn expand_deriving_totalord(cx: &mut ExtCtxt, span: Span, mitem: @MetaItem, in_items: ~[@Item]) -> ~[@Item] { @@ -44,7 +44,7 @@ pub fn expand_deriving_totalord(cx: &ExtCtxt, } -pub fn ordering_const(cx: &ExtCtxt, span: Span, cnst: Ordering) -> ast::Path { +pub fn ordering_const(cx: &mut ExtCtxt, span: Span, cnst: Ordering) -> ast::Path { let cnst = match cnst { Less => "Less", Equal => "Equal", @@ -56,7 +56,7 @@ pub fn ordering_const(cx: &ExtCtxt, span: Span, cnst: Ordering) -> ast::Path { cx.ident_of(cnst)]) } -pub fn cs_cmp(cx: &ExtCtxt, span: Span, +pub fn cs_cmp(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> @Expr { let test_id = cx.ident_of("__test"); let equals_path = ordering_const(cx, span, Equal); @@ -106,8 +106,10 @@ pub fn cs_cmp(cx: &ExtCtxt, span: Span, // an earlier nonmatching variant is Less than a // later one. [(self_var, _, _), - (other_var, _, _)] => cx.expr_path(ordering_const(cx, span, - self_var.cmp(&other_var))), + (other_var, _, _)] => { + let order = ordering_const(cx, span, self_var.cmp(&other_var)); + cx.expr_path(order) + } _ => cx.span_bug(span, "Not exactly 2 arguments in `deriving(TotalOrd)`") } }, diff --git a/src/libsyntax/ext/deriving/decodable.rs b/src/libsyntax/ext/deriving/decodable.rs index ad7b3a2e950..7324500a8a0 100644 --- a/src/libsyntax/ext/deriving/decodable.rs +++ b/src/libsyntax/ext/deriving/decodable.rs @@ -21,7 +21,7 @@ use ext::deriving::generic::*; use parse::token::InternedString; use parse::token; -pub fn expand_deriving_decodable(cx: &ExtCtxt, +pub fn expand_deriving_decodable(cx: &mut ExtCtxt, span: Span, mitem: @MetaItem, in_items: ~[@Item]) -> ~[@Item] { @@ -53,7 +53,7 @@ pub fn expand_deriving_decodable(cx: &ExtCtxt, trait_def.expand(mitem, in_items) } -fn decodable_substructure(cx: &ExtCtxt, trait_span: Span, +fn decodable_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) -> @Expr { let decoder = substr.nonself_args[0]; let recurse = ~[cx.ident_of("serialize"), @@ -77,7 +77,7 @@ fn decodable_substructure(cx: &ExtCtxt, trait_span: Span, trait_span, substr.type_ident, summary, - |span, name, field| { + |cx, span, name, field| { cx.expr_method_call(span, blkdecoder, read_struct_field, ~[cx.expr_str(span, name), cx.expr_uint(span, field), @@ -108,10 +108,10 @@ fn decodable_substructure(cx: &ExtCtxt, trait_span: Span, v_span, name, parts, - |span, _, field| { + |cx, span, _, field| { + let idx = cx.expr_uint(span, field); cx.expr_method_call(span, blkdecoder, rvariant_arg, - ~[cx.expr_uint(span, field), - lambdadecode]) + ~[idx, lambdadecode]) }); arms.push(cx.arm(v_span, @@ -143,11 +143,11 @@ fn decodable_substructure(cx: &ExtCtxt, trait_span: Span, /// Create a decoder for a single enum variant/struct: /// - `outer_pat_ident` is the name of this enum variant/struct /// - `getarg` should retrieve the `uint`-th field with name `@str`. -fn decode_static_fields(cx: &ExtCtxt, +fn decode_static_fields(cx: &mut ExtCtxt, trait_span: Span, outer_pat_ident: Ident, fields: &StaticFields, - getarg: |Span, InternedString, uint| -> @Expr) + getarg: |&mut ExtCtxt, Span, InternedString, uint| -> @Expr) -> @Expr { match *fields { Unnamed(ref fields) => { @@ -155,7 +155,7 @@ fn decode_static_fields(cx: &ExtCtxt, cx.expr_ident(trait_span, outer_pat_ident) } else { let fields = fields.iter().enumerate().map(|(i, &span)| { - getarg(span, + getarg(cx, span, token::intern_and_get_ident(format!("_field{}", i)), i) @@ -167,9 +167,8 @@ fn decode_static_fields(cx: &ExtCtxt, Named(ref fields) => { // use the field's span to get nicer error messages. let fields = fields.iter().enumerate().map(|(i, &(name, span))| { - cx.field_imm(span, - name, - getarg(span, token::get_ident(name.name), i)) + let arg = getarg(cx, span, token::get_ident(name.name), i); + cx.field_imm(span, name, arg) }).collect(); cx.expr_struct_ident(trait_span, outer_pat_ident, fields) } diff --git a/src/libsyntax/ext/deriving/default.rs b/src/libsyntax/ext/deriving/default.rs index 22f850d5609..922ee164353 100644 --- a/src/libsyntax/ext/deriving/default.rs +++ b/src/libsyntax/ext/deriving/default.rs @@ -14,7 +14,7 @@ use ext::base::ExtCtxt; use ext::build::AstBuilder; use ext::deriving::generic::*; -pub fn expand_deriving_default(cx: &ExtCtxt, +pub fn expand_deriving_default(cx: &mut ExtCtxt, span: Span, mitem: @MetaItem, in_items: ~[@Item]) @@ -41,7 +41,7 @@ pub fn expand_deriving_default(cx: &ExtCtxt, trait_def.expand(mitem, in_items) } -fn default_substructure(cx: &ExtCtxt, trait_span: Span, substr: &Substructure) -> @Expr { +fn default_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) -> @Expr { let default_ident = ~[ cx.ident_of("std"), cx.ident_of("default"), diff --git a/src/libsyntax/ext/deriving/encodable.rs b/src/libsyntax/ext/deriving/encodable.rs index a44e4af5b6b..4de31adc7f2 100644 --- a/src/libsyntax/ext/deriving/encodable.rs +++ b/src/libsyntax/ext/deriving/encodable.rs @@ -82,7 +82,7 @@ use ext::build::AstBuilder; use ext::deriving::generic::*; use parse::token; -pub fn expand_deriving_encodable(cx: &ExtCtxt, +pub fn expand_deriving_encodable(cx: &mut ExtCtxt, span: Span, mitem: @MetaItem, in_items: ~[@Item]) -> ~[@Item] { @@ -114,7 +114,7 @@ pub fn expand_deriving_encodable(cx: &ExtCtxt, trait_def.expand(mitem, in_items) } -fn encodable_substructure(cx: &ExtCtxt, trait_span: Span, +fn encodable_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) -> @Expr { let encoder = substr.nonself_args[0]; // throw an underscore in front to suppress unused variable warnings diff --git a/src/libsyntax/ext/deriving/generic.rs b/src/libsyntax/ext/deriving/generic.rs index 992ee3175ed..8c06f0b8c8a 100644 --- a/src/libsyntax/ext/deriving/generic.rs +++ b/src/libsyntax/ext/deriving/generic.rs @@ -194,7 +194,7 @@ mod ty; pub struct TraitDef<'a> { /// The extension context - cx: &'a ExtCtxt<'a>, + cx: &'a mut ExtCtxt<'a>, /// The span for the current #[deriving(Foo)] header. span: Span, @@ -304,7 +304,7 @@ Combine the values of all the fields together. The last argument is all the fields of all the structures, see above for details. */ pub type CombineSubstructureFunc<'a> = - 'a |&ExtCtxt, Span, &Substructure| -> @Expr; + 'a |&mut ExtCtxt, Span, &Substructure| -> @Expr; /** Deal with non-matching enum variants, the arguments are a list @@ -312,7 +312,7 @@ representing each variant: (variant index, ast::Variant instance, [variant fields]), and a list of the nonself args of the type */ pub type EnumNonMatchFunc<'a> = - 'a |&ExtCtxt, + 'a |&mut ExtCtxt, Span, &[(uint, P<ast::Variant>, ~[(Span, Option<Ident>, @Expr)])], &[@Expr]| @@ -356,7 +356,7 @@ impl<'a> TraitDef<'a> { fn create_derived_impl(&self, type_ident: Ident, generics: &Generics, methods: ~[@ast::Method]) -> @ast::Item { - let cx = self.cx; + let cx = &*self.cx; let trait_path = self.path.to_path(cx, self.span, type_ident, generics); let mut trait_generics = self.generics.to_generics(cx, self.span, @@ -764,7 +764,7 @@ impl<'a> MethodDef<'a> { matches_so_far: &mut ~[(uint, P<ast::Variant>, ~[(Span, Option<Ident>, @Expr)])], match_count: uint) -> @Expr { - let cx = trait_.cx; + let cx = &trait_.cx; if match_count == self_args.len() { // we've matched against all arguments, so make the final // expression at the bottom of the match tree @@ -990,7 +990,7 @@ impl<'a> TraitDef<'a> { prefix: &str, mutbl: ast::Mutability) -> (@ast::Pat, ~[(Span, Option<Ident>, @Expr)]) { - let cx = self.cx; + let cx = &self.cx; if struct_def.fields.is_empty() { return ( @@ -1050,7 +1050,7 @@ impl<'a> TraitDef<'a> { prefix: &str, mutbl: ast::Mutability) -> (@ast::Pat, ~[(Span, Option<Ident>, @Expr)]) { - let cx = self.cx; + let cx = &*self.cx; let variant_ident = variant.node.name; match variant.node.kind { ast::TupleVariantKind(ref variant_args) => { @@ -1093,10 +1093,10 @@ Fold the fields. `use_foldl` controls whether this is done left-to-right (`true`) or right-to-left (`false`). */ pub fn cs_fold(use_foldl: bool, - f: |&ExtCtxt, Span, @Expr, @Expr, &[@Expr]| -> @Expr, + f: |&mut ExtCtxt, Span, @Expr, @Expr, &[@Expr]| -> @Expr, base: @Expr, enum_nonmatch_f: EnumNonMatchFunc, - cx: &ExtCtxt, + cx: &mut ExtCtxt, trait_span: Span, substructure: &Substructure) -> @Expr { @@ -1132,9 +1132,9 @@ f(cx, span, ~[self_1.method(__arg_1_1, __arg_2_1), ~~~ */ #[inline] -pub fn cs_same_method(f: |&ExtCtxt, Span, ~[@Expr]| -> @Expr, +pub fn cs_same_method(f: |&mut ExtCtxt, Span, ~[@Expr]| -> @Expr, enum_nonmatch_f: EnumNonMatchFunc, - cx: &ExtCtxt, + cx: &mut ExtCtxt, trait_span: Span, substructure: &Substructure) -> @Expr { @@ -1166,10 +1166,10 @@ fields. `use_foldl` controls whether this is done left-to-right */ #[inline] pub fn cs_same_method_fold(use_foldl: bool, - f: |&ExtCtxt, Span, @Expr, @Expr| -> @Expr, + f: |&mut ExtCtxt, Span, @Expr, @Expr| -> @Expr, base: @Expr, enum_nonmatch_f: EnumNonMatchFunc, - cx: &ExtCtxt, + cx: &mut ExtCtxt, trait_span: Span, substructure: &Substructure) -> @Expr { @@ -1196,7 +1196,7 @@ on all the fields. #[inline] pub fn cs_binop(binop: ast::BinOp, base: @Expr, enum_nonmatch_f: EnumNonMatchFunc, - cx: &ExtCtxt, trait_span: Span, + cx: &mut ExtCtxt, trait_span: Span, substructure: &Substructure) -> @Expr { cs_same_method_fold( true, // foldl is good enough @@ -1214,7 +1214,7 @@ pub fn cs_binop(binop: ast::BinOp, base: @Expr, /// cs_binop with binop == or #[inline] pub fn cs_or(enum_nonmatch_f: EnumNonMatchFunc, - cx: &ExtCtxt, span: Span, + cx: &mut ExtCtxt, span: Span, substructure: &Substructure) -> @Expr { cs_binop(ast::BiOr, cx.expr_bool(span, false), enum_nonmatch_f, @@ -1224,7 +1224,7 @@ pub fn cs_or(enum_nonmatch_f: EnumNonMatchFunc, /// cs_binop with binop == and #[inline] pub fn cs_and(enum_nonmatch_f: EnumNonMatchFunc, - cx: &ExtCtxt, span: Span, + cx: &mut ExtCtxt, span: Span, substructure: &Substructure) -> @Expr { cs_binop(ast::BiAnd, cx.expr_bool(span, true), enum_nonmatch_f, diff --git a/src/libsyntax/ext/deriving/iter_bytes.rs b/src/libsyntax/ext/deriving/iter_bytes.rs index d82e1ef1842..53805694725 100644 --- a/src/libsyntax/ext/deriving/iter_bytes.rs +++ b/src/libsyntax/ext/deriving/iter_bytes.rs @@ -15,7 +15,7 @@ use ext::build::AstBuilder; use ext::deriving::generic::*; -pub fn expand_deriving_iter_bytes(cx: &ExtCtxt, +pub fn expand_deriving_iter_bytes(cx: &mut ExtCtxt, span: Span, mitem: @MetaItem, in_items: ~[@Item]) -> ~[@Item] { @@ -45,7 +45,7 @@ pub fn expand_deriving_iter_bytes(cx: &ExtCtxt, trait_def.expand(mitem, in_items) } -fn iter_bytes_substructure(cx: &ExtCtxt, trait_span: Span, substr: &Substructure) -> @Expr { +fn iter_bytes_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) -> @Expr { let (lsb0, f)= match substr.nonself_args { [l, f] => (l, f), _ => cx.span_bug(trait_span, "Incorrect number of arguments in `deriving(IterBytes)`") diff --git a/src/libsyntax/ext/deriving/mod.rs b/src/libsyntax/ext/deriving/mod.rs index 9c487146639..01e31fc5724 100644 --- a/src/libsyntax/ext/deriving/mod.rs +++ b/src/libsyntax/ext/deriving/mod.rs @@ -18,8 +18,7 @@ library. */ -use ast::{EnumDef, Ident, Item, Generics, StructDef}; -use ast::{MetaItem, MetaList, MetaNameValue, MetaWord}; +use ast::{Item, MetaItem, MetaList, MetaNameValue, MetaWord}; use ext::base::ExtCtxt; use codemap::Span; @@ -29,6 +28,7 @@ pub mod encodable; pub mod decodable; pub mod rand; pub mod to_str; +pub mod show; pub mod zero; pub mod default; pub mod primitive; @@ -45,20 +45,7 @@ pub mod totalord; pub mod generic; -pub type ExpandDerivingStructDefFn<'a> = 'a |&ExtCtxt, - Span, - x: &StructDef, - Ident, - y: &Generics| - -> @Item; -pub type ExpandDerivingEnumDefFn<'a> = 'a |&ExtCtxt, - Span, - x: &EnumDef, - Ident, - y: &Generics| - -> @Item; - -pub fn expand_meta_deriving(cx: &ExtCtxt, +pub fn expand_meta_deriving(cx: &mut ExtCtxt, _span: Span, mitem: @MetaItem, in_items: ~[@Item]) @@ -97,6 +84,7 @@ pub fn expand_meta_deriving(cx: &ExtCtxt, "Rand" => expand!(rand::expand_deriving_rand), "ToStr" => expand!(to_str::expand_deriving_to_str), + "Show" => expand!(show::expand_deriving_show), "Zero" => expand!(zero::expand_deriving_zero), "Default" => expand!(default::expand_deriving_default), diff --git a/src/libsyntax/ext/deriving/primitive.rs b/src/libsyntax/ext/deriving/primitive.rs index e2f72e87085..86c46705d81 100644 --- a/src/libsyntax/ext/deriving/primitive.rs +++ b/src/libsyntax/ext/deriving/primitive.rs @@ -16,7 +16,7 @@ use ext::build::AstBuilder; use ext::deriving::generic::*; use parse::token::InternedString; -pub fn expand_deriving_from_primitive(cx: &ExtCtxt, +pub fn expand_deriving_from_primitive(cx: &mut ExtCtxt, span: Span, mitem: @MetaItem, in_items: ~[@Item]) -> ~[@Item] { @@ -65,7 +65,7 @@ pub fn expand_deriving_from_primitive(cx: &ExtCtxt, trait_def.expand(mitem, in_items) } -fn cs_from(name: &str, cx: &ExtCtxt, trait_span: Span, substr: &Substructure) -> @Expr { +fn cs_from(name: &str, cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) -> @Expr { let n = match substr.nonself_args { [n] => n, _ => cx.span_bug(trait_span, "Incorrect number of arguments in `deriving(FromPrimitive)`") diff --git a/src/libsyntax/ext/deriving/rand.rs b/src/libsyntax/ext/deriving/rand.rs index a22822c2ddc..15595f6eddc 100644 --- a/src/libsyntax/ext/deriving/rand.rs +++ b/src/libsyntax/ext/deriving/rand.rs @@ -16,7 +16,7 @@ use ext::build::{AstBuilder}; use ext::deriving::generic::*; use opt_vec; -pub fn expand_deriving_rand(cx: &ExtCtxt, +pub fn expand_deriving_rand(cx: &mut ExtCtxt, span: Span, mitem: @MetaItem, in_items: ~[@Item]) @@ -50,7 +50,7 @@ pub fn expand_deriving_rand(cx: &ExtCtxt, trait_def.expand(mitem, in_items) } -fn rand_substructure(cx: &ExtCtxt, trait_span: Span, substr: &Substructure) -> @Expr { +fn rand_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) -> @Expr { let rng = match substr.nonself_args { [rng] => ~[ rng ], _ => cx.bug("Incorrect number of arguments to `rand` in `deriving(Rand)`") @@ -112,9 +112,8 @@ fn rand_substructure(cx: &ExtCtxt, trait_span: Span, substr: &Substructure) -> @ let i_expr = cx.expr_uint(v_span, i); let pat = cx.pat_lit(v_span, i_expr); - cx.arm(v_span, - ~[ pat ], - rand_thing(cx, v_span, ident, summary, |sp| rand_call(sp))) + let thing = rand_thing(cx, v_span, ident, summary, |sp| rand_call(sp)); + cx.arm(v_span, ~[ pat ], thing) }).collect::<~[ast::Arm]>(); // _ => {} at the end. Should never occur @@ -128,7 +127,7 @@ fn rand_substructure(cx: &ExtCtxt, trait_span: Span, substr: &Substructure) -> @ _ => cx.bug("Non-static method in `deriving(Rand)`") }; - fn rand_thing(cx: &ExtCtxt, + fn rand_thing(cx: &mut ExtCtxt, trait_span: Span, ctor_ident: Ident, summary: &StaticFields, diff --git a/src/libsyntax/ext/deriving/show.rs b/src/libsyntax/ext/deriving/show.rs new file mode 100644 index 00000000000..67cfd151f62 --- /dev/null +++ b/src/libsyntax/ext/deriving/show.rs @@ -0,0 +1,138 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use ast; +use ast::{MetaItem, Item, Expr}; +use codemap::Span; +use ext::format; +use ext::base::ExtCtxt; +use ext::build::AstBuilder; +use ext::deriving::generic::*; + +use parse::token; + +use std::hashmap::HashMap; + +pub fn expand_deriving_show(cx: &mut ExtCtxt, + span: Span, + mitem: @MetaItem, + in_items: ~[@Item]) + -> ~[@Item] { + // &mut ::std::fmt::Formatter + let fmtr = Ptr(~Literal(Path::new(~["std", "fmt", "Formatter"])), + Borrowed(None, ast::MutMutable)); + + let trait_def = TraitDef { + cx: cx, span: span, + + path: Path::new(~["std", "fmt", "Show"]), + additional_bounds: ~[], + generics: LifetimeBounds::empty(), + methods: ~[ + MethodDef { + name: "fmt", + generics: LifetimeBounds::empty(), + explicit_self: borrowed_explicit_self(), + args: ~[fmtr], + ret_ty: Literal(Path::new(~["std", "fmt", "Result"])), + inline: false, + const_nonmatching: false, + combine_substructure: show_substructure + } + ] + }; + trait_def.expand(mitem, in_items) +} + +// we construct a format string and then defer to std::fmt, since that +// knows what's up with formatting at so on. +fn show_substructure(cx: &mut ExtCtxt, span: Span, + substr: &Substructure) -> @Expr { + // build `<name>`, `<name>({}, {}, ...)` or `<name> { <field>: {}, + // <field>: {}, ... }` based on the "shape". + // + // Easy start: they all start with the name. + let name = match *substr.fields { + Struct(_) => substr.type_ident, + EnumMatching(_, v, _) => v.node.name, + + EnumNonMatching(..) | StaticStruct(..) | StaticEnum(..) => { + cx.span_bug(span, "nonsensical .fields in `#[deriving(Show)]`") + } + }; + + let mut format_string = token::get_ident(name.name).get().to_owned(); + // the internal fields we're actually formatting + let mut exprs = ~[]; + + // Getting harder... making the format string: + match *substr.fields { + // unit struct/nullary variant: no work necessary! + Struct([]) | EnumMatching(_, _, []) => {} + + Struct(ref fields) | EnumMatching(_, _, ref fields) => { + if fields[0].name.is_none() { + // tuple struct/"normal" variant + + format_string.push_str("("); + + for (i, field) in fields.iter().enumerate() { + if i != 0 { format_string.push_str(", "); } + + format_string.push_str("{}"); + + exprs.push(field.self_); + } + + format_string.push_str(")"); + } else { + // normal struct/struct variant + + format_string.push_str(" \\{"); + + for (i, field) in fields.iter().enumerate() { + if i != 0 { format_string.push_str(","); } + + let name = token::get_ident(field.name.unwrap().name); + format_string.push_str(" "); + format_string.push_str(name.get()); + format_string.push_str(": {}"); + + exprs.push(field.self_); + } + + format_string.push_str(" \\}"); + } + } + _ => unreachable!() + } + + // AST construction! + // we're basically calling + // + // format_arg!(|__args| ::std::fmt::write(fmt.buf, __args), "<format_string>", exprs...) + // + // but doing it directly via ext::format. + let formatter = substr.nonself_args[0]; + let buf = cx.expr_field_access(span, formatter, cx.ident_of("buf")); + + let std_write = ~[cx.ident_of("std"), cx.ident_of("fmt"), cx.ident_of("write")]; + let args = cx.ident_of("__args"); + let write_call = cx.expr_call_global(span, std_write, ~[buf, cx.expr_ident(span, args)]); + let format_closure = cx.lambda_expr(span, ~[args], write_call); + + let s = token::intern_and_get_ident(format_string); + let format_string = cx.expr_str(span, s); + + // phew, not our responsibility any more! + format::expand_preparsed_format_args(cx, span, + format_closure, + format_string, exprs, HashMap::new()) +} diff --git a/src/libsyntax/ext/deriving/to_str.rs b/src/libsyntax/ext/deriving/to_str.rs index 6101d647ca5..2f50d5ad121 100644 --- a/src/libsyntax/ext/deriving/to_str.rs +++ b/src/libsyntax/ext/deriving/to_str.rs @@ -17,7 +17,7 @@ use ext::deriving::generic::*; use parse::token::InternedString; use parse::token; -pub fn expand_deriving_to_str(cx: &ExtCtxt, +pub fn expand_deriving_to_str(cx: &mut ExtCtxt, span: Span, mitem: @MetaItem, in_items: ~[@Item]) @@ -49,7 +49,7 @@ pub fn expand_deriving_to_str(cx: &ExtCtxt, // doesn't invoke the to_str() method on each field. Hence we mirror // the logic of the repr_to_str() method, but with tweaks to call to_str() // on sub-fields. -fn to_str_substructure(cx: &ExtCtxt, span: Span, substr: &Substructure) +fn to_str_substructure(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> @Expr { let to_str = cx.ident_of("to_str"); diff --git a/src/libsyntax/ext/deriving/zero.rs b/src/libsyntax/ext/deriving/zero.rs index dd99e821620..ecd06b3f49e 100644 --- a/src/libsyntax/ext/deriving/zero.rs +++ b/src/libsyntax/ext/deriving/zero.rs @@ -14,7 +14,7 @@ use ext::base::ExtCtxt; use ext::build::AstBuilder; use ext::deriving::generic::*; -pub fn expand_deriving_zero(cx: &ExtCtxt, +pub fn expand_deriving_zero(cx: &mut ExtCtxt, span: Span, mitem: @MetaItem, in_items: ~[@Item]) @@ -57,7 +57,7 @@ pub fn expand_deriving_zero(cx: &ExtCtxt, trait_def.expand(mitem, in_items) } -fn zero_substructure(cx: &ExtCtxt, trait_span: Span, substr: &Substructure) -> @Expr { +fn zero_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) -> @Expr { let zero_ident = ~[ cx.ident_of("std"), cx.ident_of("num"), diff --git a/src/libsyntax/ext/format.rs b/src/libsyntax/ext/format.rs index 9d2a891bf6b..4bc3b804c7f 100644 --- a/src/libsyntax/ext/format.rs +++ b/src/libsyntax/ext/format.rs @@ -56,78 +56,83 @@ struct Context<'a> { next_arg: uint, } -impl<'a> Context<'a> { - /// Parses the arguments from the given list of tokens, returning None if - /// there's a parse error so we can continue parsing other format! expressions. - fn parse_args(&mut self, sp: Span, tts: &[ast::TokenTree]) - -> (@ast::Expr, Option<@ast::Expr>) { - let mut p = rsparse::new_parser_from_tts(self.ecx.parse_sess(), - self.ecx.cfg(), - tts.to_owned()); - // Parse the leading function expression (maybe a block, maybe a path) - let extra = p.parse_expr(); - if !p.eat(&token::COMMA) { - self.ecx.span_err(sp, "expected token: `,`"); - return (extra, None); - } +/// Parses the arguments from the given list of tokens, returning None +/// if there's a parse error so we can continue parsing other format! +/// expressions. +/// +/// If parsing succeeds, the second return value is: +/// +/// Some((fmtstr, unnamed arguments, named arguments)) +fn parse_args(ecx: &mut ExtCtxt, sp: Span, + tts: &[ast::TokenTree]) -> (@ast::Expr, Option<(@ast::Expr, ~[@ast::Expr], + HashMap<~str, @ast::Expr>)>) { + let mut args = ~[]; + let mut names = HashMap::<~str, @ast::Expr>::new(); + + let mut p = rsparse::new_parser_from_tts(ecx.parse_sess(), + ecx.cfg(), + tts.to_owned()); + // Parse the leading function expression (maybe a block, maybe a path) + let extra = p.parse_expr(); + if !p.eat(&token::COMMA) { + ecx.span_err(sp, "expected token: `,`"); + return (extra, None); + } - if p.token == token::EOF { - self.ecx.span_err(sp, "requires at least a format string argument"); + if p.token == token::EOF { + ecx.span_err(sp, "requires at least a format string argument"); + return (extra, None); + } + let fmtstr = p.parse_expr(); + let mut named = false; + while p.token != token::EOF { + if !p.eat(&token::COMMA) { + ecx.span_err(sp, "expected token: `,`"); return (extra, None); } - let fmtstr = p.parse_expr(); - let mut named = false; - while p.token != token::EOF { - if !p.eat(&token::COMMA) { - self.ecx.span_err(sp, "expected token: `,`"); - return (extra, None); - } - if p.token == token::EOF { break } // accept trailing commas - if named || (token::is_ident(&p.token) && - p.look_ahead(1, |t| *t == token::EQ)) { - named = true; - let ident = match p.token { - token::IDENT(i, _) => { - p.bump(); - i - } - _ if named => { - self.ecx.span_err(p.span, - "expected ident, positional arguments \ - cannot follow named arguments"); - return (extra, None); - } - _ => { - self.ecx.span_err(p.span, - format!("expected ident for named \ - argument, but found `{}`", - p.this_token_to_str())); - return (extra, None); - } - }; - let interned_name = token::get_ident(ident.name); - let name = interned_name.get(); - p.expect(&token::EQ); - let e = p.parse_expr(); - match self.names.find_equiv(&name) { - None => {} - Some(prev) => { - self.ecx.span_err(e.span, format!("duplicate argument \ - named `{}`", name)); - self.ecx.parse_sess.span_diagnostic.span_note( - prev.span, "previously here"); - continue - } + if p.token == token::EOF { break } // accept trailing commas + if named || (token::is_ident(&p.token) && + p.look_ahead(1, |t| *t == token::EQ)) { + named = true; + let ident = match p.token { + token::IDENT(i, _) => { + p.bump(); + i + } + _ if named => { + ecx.span_err(p.span, + "expected ident, positional arguments \ + cannot follow named arguments"); + return (extra, None); + } + _ => { + ecx.span_err(p.span, + format!("expected ident for named argument, but found `{}`", + p.this_token_to_str())); + return (extra, None); + } + }; + let interned_name = token::get_ident(ident.name); + let name = interned_name.get(); + p.expect(&token::EQ); + let e = p.parse_expr(); + match names.find_equiv(&name) { + None => {} + Some(prev) => { + ecx.span_err(e.span, format!("duplicate argument named `{}`", name)); + ecx.parse_sess.span_diagnostic.span_note(prev.span, "previously here"); + continue } - self.names.insert(name.to_str(), e); - } else { - self.args.push(p.parse_expr()); - self.arg_types.push(None); } + names.insert(name.to_str(), e); + } else { + args.push(p.parse_expr()); } - return (extra, Some(fmtstr)); } + return (extra, Some((fmtstr, args, names))); +} +impl<'a> Context<'a> { /// Verifies one piece of a parse string. All errors are not emitted as /// fatal so we can continue giving errors about this and possibly other /// format strings. @@ -758,11 +763,28 @@ impl<'a> Context<'a> { pub fn expand_args(ecx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> base::MacResult { + + match parse_args(ecx, sp, tts) { + (extra, Some((efmt, args, names))) => { + MRExpr(expand_preparsed_format_args(ecx, sp, extra, efmt, args, names)) + } + (_, None) => MRExpr(ecx.expr_uint(sp, 2)) + } +} + +/// Take the various parts of `format_args!(extra, efmt, args..., +/// name=names...)` and construct the appropriate formatting +/// expression. +pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, sp: Span, + extra: @ast::Expr, + efmt: @ast::Expr, args: ~[@ast::Expr], + names: HashMap<~str, @ast::Expr>) -> @ast::Expr { + let arg_types = vec::from_fn(args.len(), |_| None); let mut cx = Context { ecx: ecx, - args: ~[], - arg_types: ~[], - names: HashMap::new(), + args: args, + arg_types: arg_types, + names: names, name_positions: HashMap::new(), name_types: HashMap::new(), nest_level: 0, @@ -771,10 +793,6 @@ pub fn expand_args(ecx: &mut ExtCtxt, sp: Span, method_statics: ~[], fmtsp: sp, }; - let (extra, efmt) = match cx.parse_args(sp, tts) { - (extra, Some(e)) => (extra, e), - (_, None) => { return MRExpr(cx.ecx.expr_uint(sp, 2)); } - }; cx.fmtsp = efmt.span; // Be sure to recursively expand macros just in case the format string uses // a macro to build the format expression. @@ -783,7 +801,7 @@ pub fn expand_args(ecx: &mut ExtCtxt, sp: Span, expr, "format argument must be a string literal.") { Some((fmt, _)) => fmt, - None => return MacResult::dummy_expr() + None => return efmt }; let mut parser = parse::Parser::new(fmt.get()); @@ -801,7 +819,7 @@ pub fn expand_args(ecx: &mut ExtCtxt, sp: Span, match parser.errors.shift() { Some(error) => { cx.ecx.span_err(efmt.span, "invalid format string: " + error); - return MRExpr(efmt); + return efmt; } None => {} } @@ -818,5 +836,5 @@ pub fn expand_args(ecx: &mut ExtCtxt, sp: Span, } } - MRExpr(cx.to_expr(extra)) + cx.to_expr(extra) } diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 090774ec76f..d32411b4f05 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -588,8 +588,8 @@ impl BytesContainer for InternedString { } impl fmt::Show for InternedString { - fn fmt(obj: &InternedString, f: &mut fmt::Formatter) -> fmt::Result { - write!(f.buf, "{}", obj.string.as_slice()) + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f.buf, "{}", self.string.as_slice()) } } |
