summary refs log tree commit diff
path: root/src/libsyntax/ext
diff options
context:
space:
mode:
authorErick Tryzelaar <erick.tryzelaar@gmail.com>2012-09-26 21:35:13 -0700
committerNiko Matsakis <niko@alum.mit.edu>2012-10-01 20:43:59 -0700
commit81423a3866fb6cd4cadd28ed49273d7e22d48c17 (patch)
tree28bbbf3b65f82dc7554c8b7371ed46f8a381c75e /src/libsyntax/ext
parent0a950f394dbe3275c4879dc1f26f78a096f93e28 (diff)
downloadrust-81423a3866fb6cd4cadd28ed49273d7e22d48c17.tar.gz
rust-81423a3866fb6cd4cadd28ed49273d7e22d48c17.zip
Add deserializable and more types to serialization2
Diffstat (limited to 'src/libsyntax/ext')
-rw-r--r--src/libsyntax/ext/auto_serialize2.rs189
1 files changed, 128 insertions, 61 deletions
diff --git a/src/libsyntax/ext/auto_serialize2.rs b/src/libsyntax/ext/auto_serialize2.rs
index 099ba67713f..d4a1a448936 100644
--- a/src/libsyntax/ext/auto_serialize2.rs
+++ b/src/libsyntax/ext/auto_serialize2.rs
@@ -9,14 +9,16 @@ For example, a type like:
 
     type node_id = uint;
 
-would generate two functions like:
+would generate two implementations like:
 
     impl node_id: Serializable {
-        fn serialize<S: Serializer>(s: S) {
+        fn serialize<S: Serializer>(s: &S) {
             s.emit_uint(self)
         }
+    }
 
-        static fn deserialize<D: Deserializer>(d: D) -> node_id {
+    impl node_id: Deserializable {
+        static fn deserialize<D: Deserializer>(d: &D) -> node_id {
             d.read_uint()
         }
     }
@@ -29,18 +31,20 @@ references other non-built-in types.  A type definition like:
 would yield functions like:
 
     impl<T: Serializable> spanned<T>: Serializable {
-        fn serialize<S: Serializer>(s: S) {
+        fn serialize<S: Serializer>(s: &S) {
             do s.emit_rec {
-                s.emit_rec_field("node", 0, self.node.serialize(s));
-                s.emit_rec_field("span", 1, self.span.serialize(s));
+                s.emit_field("node", 0, self.node.serialize(s));
+                s.emit_field("span", 1, self.span.serialize(s));
             }
         }
+    }
 
-        static fn deserialize<D: Deserializer>(d: D) -> spanned<T> {
+    impl<T: Deserializable> spanned<T>: Deserializable {
+        static fn deserialize<D: Deserializer>(d: &D) -> spanned<T> {
             do d.read_rec {
                 {
-                    node: d.read_rec_field(~"node", 0, || deserialize(d)),
-                    span: d.read_rec_field(~"span", 1, || deserialize(d)),
+                    node: d.read_field(~"node", 0, || deserialize(d)),
+                    span: d.read_field(~"span", 1, || deserialize(d)),
                 }
             }
         }
@@ -87,22 +91,22 @@ fn expand(cx: ext_ctxt,
     do vec::flat_map(in_items) |item| {
         match item.node {
             ast::item_ty(@{node: ast::ty_rec(fields), _}, tps) => {
-                ~[
-                    filter_attrs(*item),
-                    mk_rec_impl(cx, item.span, item.ident, fields, tps),
-                ]
+                vec::append(
+                    ~[filter_attrs(*item)],
+                    mk_rec_impl(cx, item.span, item.ident, fields, tps)
+                )
             },
             ast::item_class(@{ fields, _}, tps) => {
-                ~[
-                    filter_attrs(*item),
-                    mk_struct_impl(cx, item.span, item.ident, fields, tps),
-                ]
+                vec::append(
+                    ~[filter_attrs(*item)],
+                    mk_struct_impl(cx, item.span, item.ident, fields, tps)
+                )
             },
             ast::item_enum(enum_def, tps) => {
-                ~[
-                    filter_attrs(*item),
-                    mk_enum_impl(cx, item.span, item.ident, enum_def, tps),
-                ]
+                vec::append(
+                    ~[filter_attrs(*item)],
+                    mk_enum_impl(cx, item.span, item.ident, enum_def, tps)
+                )
             },
             _ => {
                 cx.span_err(span, ~"#[auto_serialize2] can only be applied \
@@ -152,22 +156,11 @@ fn mk_impl(
     cx: ext_ctxt,
     span: span,
     ident: ast::ident,
+    path: @ast::path,
     tps: ~[ast::ty_param],
-    ser_body: @ast::expr,
-    deser_body: @ast::expr
+    f: fn(@ast::ty) -> @ast::method
 ) -> @ast::item {
-    // Make a path to the std::serialization2::Serializable trait.
-    let path = cx.path(
-        span,
-        ~[
-            cx.ident_of(~"std"),
-            cx.ident_of(~"serialization2"),
-            cx.ident_of(~"Serializable"),
-        ]
-    );
-
-    // All the type parameters need to bound to
-    // std::serialization::Serializable.
+    // All the type parameters need to bound to the trait.
     let trait_tps = do tps.map |tp| {
         let t_bound = ast::bound_trait(@{
             id: cx.next_id(),
@@ -194,23 +187,72 @@ fn mk_impl(
         tps.map(|tp| cx.ty_path(span, ~[tp.ident], ~[]))
     );
 
-    let methods = ~[
-        mk_ser_method(cx, span, cx.expr_blk(ser_body)),
-        mk_deser_method(cx, span, ty, cx.expr_blk(deser_body)),
-    ];
-
     @{
         // This is a new-style impl declaration.
         // XXX: clownshoes
         ident: ast::token::special_idents::clownshoes_extensions,
         attrs: ~[],
         id: cx.next_id(),
-        node: ast::item_impl(trait_tps, opt_trait, ty, methods),
+        node: ast::item_impl(trait_tps, opt_trait, ty, ~[f(ty)]),
         vis: ast::public,
         span: span,
     }
 }
 
+fn mk_ser_impl(
+    cx: ext_ctxt,
+    span: span,
+    ident: ast::ident,
+    tps: ~[ast::ty_param],
+    body: @ast::expr
+) -> @ast::item {
+    // Make a path to the std::serialization2::Serializable trait.
+    let path = cx.path(
+        span,
+        ~[
+            cx.ident_of(~"std"),
+            cx.ident_of(~"serialization2"),
+            cx.ident_of(~"Serializable"),
+        ]
+    );
+
+    mk_impl(
+        cx,
+        span,
+        ident,
+        path,
+        tps,
+        |_ty| mk_ser_method(cx, span, cx.expr_blk(body))
+    )
+}
+
+fn mk_deser_impl(
+    cx: ext_ctxt,
+    span: span,
+    ident: ast::ident,
+    tps: ~[ast::ty_param],
+    body: @ast::expr
+) -> @ast::item {
+    // Make a path to the std::serialization2::Deserializable trait.
+    let path = cx.path(
+        span,
+        ~[
+            cx.ident_of(~"std"),
+            cx.ident_of(~"serialization2"),
+            cx.ident_of(~"Deserializable"),
+        ]
+    );
+
+    mk_impl(
+        cx,
+        span,
+        ident,
+        path,
+        tps,
+        |ty| mk_deser_method(cx, span, ty, cx.expr_blk(body))
+    )
+}
+
 fn mk_ser_method(
     cx: ext_ctxt,
     span: span,
@@ -352,7 +394,7 @@ fn mk_rec_impl(
     ident: ast::ident,
     fields: ~[ast::ty_field],
     tps: ~[ast::ty_param]
-) -> @ast::item {
+) -> ~[@ast::item] {
     // Records and structs don't have the same fields types, but they share
     // enough that if we extract the right subfields out we can share the
     // serialization generator code.
@@ -365,11 +407,26 @@ fn mk_rec_impl(
     };
 
     let ser_body = mk_ser_fields(cx, span, fields);
+
+    // ast for `__s.emit_rec($(ser_body))`
+    let ser_body = cx.expr_call(
+        span,
+        cx.expr_field(
+            span,
+            cx.expr_var(span, ~"__s"),
+            cx.ident_of(~"emit_rec")
+        ),
+        ~[ser_body]
+    );
+
     let deser_body = do mk_deser_fields(cx, span, fields) |fields| {
          cx.expr(span, ast::expr_rec(fields, None))
     };
 
-    mk_impl(cx, span, ident, tps, ser_body, deser_body)
+    ~[
+        mk_ser_impl(cx, span, ident, tps, ser_body),
+        mk_deser_impl(cx, span, ident, tps, deser_body),
+    ]
 }
 
 fn mk_struct_impl(
@@ -378,7 +435,7 @@ fn mk_struct_impl(
     ident: ast::ident,
     fields: ~[@ast::struct_field],
     tps: ~[ast::ty_param]
-) -> @ast::item {
+) -> ~[@ast::item] {
     // Records and structs don't have the same fields types, but they share
     // enough that if we extract the right subfields out we can share the
     // serialization generator code.
@@ -400,11 +457,26 @@ fn mk_struct_impl(
     };
 
     let ser_body = mk_ser_fields(cx, span, fields);
+
+    // ast for `__s.emit_struct($(name), $(ser_body))`
+    let ser_body = cx.expr_call(
+        span,
+        cx.expr_field(
+            span,
+            cx.expr_var(span, ~"__s"),
+            cx.ident_of(~"emit_struct")
+        ),
+        ~[cx.lit_str(span, @cx.str_of(ident)), ser_body]
+    );
+
     let deser_body = do mk_deser_fields(cx, span, fields) |fields| {
         cx.expr(span, ast::expr_struct(cx.path(span, ~[ident]), fields, None))
     };
 
-    mk_impl(cx, span, ident, tps, ser_body, deser_body)
+    ~[
+        mk_ser_impl(cx, span, ident, tps, ser_body),
+        mk_deser_impl(cx, span, ident, tps, deser_body),
+    ]
 }
 
 fn mk_ser_fields(
@@ -430,14 +502,14 @@ fn mk_ser_fields(
             )
         );
 
-        // ast for `__s.emit_rec_field($(name), $(idx), $(expr_lambda))`
+        // ast for `__s.emit_field($(name), $(idx), $(expr_lambda))`
         cx.stmt(
             cx.expr_call(
                 span,
                 cx.expr_field(
                     span,
                     cx.expr_var(span, ~"__s"),
-                    cx.ident_of(~"emit_rec_field")
+                    cx.ident_of(~"emit_field")
                 ),
                 ~[
                     cx.lit_str(span, @cx.str_of(field.ident)),
@@ -448,16 +520,8 @@ fn mk_ser_fields(
         )
     };
 
-    // ast for `__s.emit_rec(|| $(stmts))`
-    cx.expr_call(
-        span,
-        cx.expr_field(
-            span,
-            cx.expr_var(span, ~"__s"),
-            cx.ident_of(~"emit_rec")
-        ),
-        ~[cx.lambda_stmts(span, stmts)]
-    )
+    // ast for `|| $(stmts)`
+    cx.lambda_stmts(span, stmts)
 }
 
 fn mk_deser_fields(
@@ -482,13 +546,13 @@ fn mk_deser_fields(
             )
         );
 
-        // ast for `__d.read_rec_field($(name), $(idx), $(expr_lambda))`
+        // ast for `__d.read_field($(name), $(idx), $(expr_lambda))`
         let expr: @ast::expr = cx.expr_call(
             span,
             cx.expr_field(
                 span,
                 cx.expr_var(span, ~"__d"),
-                cx.ident_of(~"read_rec_field")
+                cx.ident_of(~"read_field")
             ),
             ~[
                 cx.lit_str(span, @cx.str_of(field.ident)),
@@ -521,7 +585,7 @@ fn mk_enum_impl(
     ident: ast::ident,
     enum_def: ast::enum_def,
     tps: ~[ast::ty_param]
-) -> @ast::item {
+) -> ~[@ast::item] {
     let ser_body = mk_enum_ser_body(
         cx,
         span,
@@ -536,7 +600,10 @@ fn mk_enum_impl(
         enum_def.variants
     );
 
-    mk_impl(cx, span, ident, tps, ser_body, deser_body)
+    ~[
+        mk_ser_impl(cx, span, ident, tps, ser_body),
+        mk_deser_impl(cx, span, ident, tps, deser_body),
+    ]
 }
 
 fn ser_variant(