about summary refs log tree commit diff
path: root/src/libsyntax/ext
diff options
context:
space:
mode:
authorErick Tryzelaar <erick.tryzelaar@gmail.com>2012-10-01 07:22:18 -0700
committerNiko Matsakis <niko@alum.mit.edu>2012-10-01 20:44:30 -0700
commitc46b6f9efbbb00706a62d86a9afc4fd59bc13c12 (patch)
tree00b054e7028238a9f6afb3125a95cbdea6d775a5 /src/libsyntax/ext
parent8fc3088b2aba397c0f561ce978b2d4a47f8a9eab (diff)
auto_serialize2 should deserialize structs using read_struct
Diffstat (limited to 'src/libsyntax/ext')
-rw-r--r--src/libsyntax/ext/auto_serialize2.rs163
1 files changed, 106 insertions, 57 deletions
diff --git a/src/libsyntax/ext/auto_serialize2.rs b/src/libsyntax/ext/auto_serialize2.rs
index d4a1a448936..bec0d6c973d 100644
--- a/src/libsyntax/ext/auto_serialize2.rs
+++ b/src/libsyntax/ext/auto_serialize2.rs
@@ -7,25 +7,33 @@ companion module with the same name as the item.
 
 For example, a type like:
 
-    type node_id = uint;
+    #[auto_serialize2]
+    struct Node {id: uint}
 
 would generate two implementations like:
 
-    impl node_id: Serializable {
+    impl Node: Serializable {
         fn serialize<S: Serializer>(s: &S) {
-            s.emit_uint(self)
+            do s.emit_struct("Node") {
+                s.emit_field("id", 0, || s.emit_uint(self))
+            }
         }
     }
 
     impl node_id: Deserializable {
-        static fn deserialize<D: Deserializer>(d: &D) -> node_id {
-            d.read_uint()
+        static fn deserialize<D: Deserializer>(d: &D) -> Node {
+            do d.read_struct("Node") {
+                Node {
+                    id: d.read_field(~"x", 0, || deserialize(d))
+                }
+            }
         }
     }
 
 Other interesting scenarios are whe the item has type parameters or
 references other non-built-in types.  A type definition like:
 
+    #[auto_serialize2]
     type spanned<T> = {node: T, span: span};
 
 would yield functions like:
@@ -33,8 +41,8 @@ would yield functions like:
     impl<T: Serializable> spanned<T>: Serializable {
         fn serialize<S: Serializer>(s: &S) {
             do s.emit_rec {
-                s.emit_field("node", 0, self.node.serialize(s));
-                s.emit_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));
             }
         }
     }
@@ -395,20 +403,11 @@ fn mk_rec_impl(
     fields: ~[ast::ty_field],
     tps: ~[ast::ty_param]
 ) -> ~[@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.
-    let fields = do fields.map |field| {
-        {
-            span: field.span,
-            ident: field.node.ident,
-            mutbl: field.node.mt.mutbl,
-        }
-    };
+    let fields = mk_rec_fields(fields);
+    let ser_fields = mk_ser_fields(cx, span, fields);
+    let deser_fields = mk_deser_fields(cx, span, fields);
 
-    let ser_body = mk_ser_fields(cx, span, fields);
-
-    // ast for `__s.emit_rec($(ser_body))`
+    // ast for `__s.emit_rec(|| $(ser_fields))`
     let ser_body = cx.expr_call(
         span,
         cx.expr_field(
@@ -416,12 +415,26 @@ fn mk_rec_impl(
             cx.expr_var(span, ~"__s"),
             cx.ident_of(~"emit_rec")
         ),
-        ~[ser_body]
+        ~[cx.lambda_stmts(span, ser_fields)]
     );
 
-    let deser_body = do mk_deser_fields(cx, span, fields) |fields| {
-         cx.expr(span, ast::expr_rec(fields, None))
-    };
+    // ast for `read_rec(|| $(deser_fields))`
+    let deser_body = cx.expr_call(
+        span,
+        cx.expr_field(
+            span,
+            cx.expr_var(span, ~"__d"),
+            cx.ident_of(~"read_rec")
+        ),
+        ~[
+            cx.lambda_expr(
+                cx.expr(
+                    span,
+                    ast::expr_rec(deser_fields, None)
+                )
+            )
+        ]
+    );
 
     ~[
         mk_ser_impl(cx, span, ident, tps, ser_body),
@@ -436,29 +449,11 @@ fn mk_struct_impl(
     fields: ~[@ast::struct_field],
     tps: ~[ast::ty_param]
 ) -> ~[@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.
-    let fields = do fields.map |field| {
-        let (ident, mutbl) = match field.node.kind {
-            ast::named_field(ident, mutbl, _) => (ident, mutbl),
-            _ => fail ~"[auto_serialize2] does not support \
-                        unnamed fields",
-        };
-
-        {
-            span: field.span,
-            ident: ident,
-            mutbl: match mutbl {
-                ast::class_mutable => ast::m_mutbl,
-                ast::class_immutable => ast::m_imm,
-            },
-        }
-    };
+    let fields = mk_struct_fields(fields);
+    let ser_fields = mk_ser_fields(cx, span, fields);
+    let deser_fields = mk_deser_fields(cx, span, fields);
 
-    let ser_body = mk_ser_fields(cx, span, fields);
-
-    // ast for `__s.emit_struct($(name), $(ser_body))`
+    // ast for `__s.emit_struct($(name), || $(ser_fields))`
     let ser_body = cx.expr_call(
         span,
         cx.expr_field(
@@ -466,12 +461,35 @@ fn mk_struct_impl(
             cx.expr_var(span, ~"__s"),
             cx.ident_of(~"emit_struct")
         ),
-        ~[cx.lit_str(span, @cx.str_of(ident)), ser_body]
+        ~[
+            cx.lit_str(span, @cx.str_of(ident)),
+            cx.lambda_stmts(span, ser_fields),
+        ]
     );
 
-    let deser_body = do mk_deser_fields(cx, span, fields) |fields| {
-        cx.expr(span, ast::expr_struct(cx.path(span, ~[ident]), fields, None))
-    };
+    // ast for `read_struct($(name), || $(deser_fields))`
+    let deser_body = cx.expr_call(
+        span,
+        cx.expr_field(
+            span,
+            cx.expr_var(span, ~"__d"),
+            cx.ident_of(~"read_struct")
+        ),
+        ~[
+            cx.lit_str(span, @cx.str_of(ident)),
+            cx.lambda_expr(
+                span,
+                cx.expr(
+                    span,
+                    ast::expr_struct(
+                        cx.path(span, ~[ident]),
+                        deser_fields
+                        None
+                    )
+                )
+            ),
+        ]
+    )
 
     ~[
         mk_ser_impl(cx, span, ident, tps, ser_body),
@@ -479,12 +497,46 @@ fn mk_struct_impl(
     ]
 }
 
+// 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.
+type field = { span: span, ident: ast::ident, mutbl: ast::mutability };
+
+fn mk_rec_fields(fields: ~[ast::ty_field]) -> ~[field] {
+    do fields.map |field| {
+        {
+            span: field.span,
+            ident: field.node.ident,
+            mutbl: field.node.mt.mutbl,
+        }
+    }
+}
+
+fn mk_struct_fields(fields: ~[@ast::struct_field]) -> ~[field] {
+    do fields.map |field| {
+        let (ident, mutbl) = match field.node.kind {
+            ast::named_field(ident, mutbl, _) => (ident, mutbl),
+            _ => fail ~"[auto_serialize2] does not support \
+                        unnamed fields",
+        };
+
+        {
+            span: field.span,
+            ident: ident,
+            mutbl: match mutbl {
+                ast::class_mutable => ast::m_mutbl,
+                ast::class_immutable => ast::m_imm,
+            },
+        }
+    }
+}
+
 fn mk_ser_fields(
     cx: ext_ctxt,
     span: span,
-    fields: ~[{ span: span, ident: ast::ident, mutbl: ast::mutability }]
-) -> @ast::expr {
-    let stmts = do fields.mapi |idx, field| {
+    fields: ~[field]
+) -> ~[@ast::stmt] {
+    do fields.mapi |idx, field| {
         // ast for `|| self.$(name).serialize(__s)`
         let expr_lambda = cx.lambda_expr(
             cx.expr_call(
@@ -518,10 +570,7 @@ fn mk_ser_fields(
                 ]
             )
         )
-    };
-
-    // ast for `|| $(stmts)`
-    cx.lambda_stmts(span, stmts)
+    }
 }
 
 fn mk_deser_fields(