about summary refs log tree commit diff
path: root/src/libsyntax/ext
diff options
context:
space:
mode:
authorSean McArthur <sean.monstar@gmail.com>2014-03-18 10:58:26 -0700
committerSean McArthur <sean.monstar@gmail.com>2014-03-27 17:41:55 -0700
commitf1739b14a1346419a4598339aee32aab07e0d12e (patch)
tree1f22c1cc492f9729cd1420654f97f3b511938369 /src/libsyntax/ext
parent13dafa09f1a80b8b50f41cab42ac2bfd24dfa6b9 (diff)
downloadrust-f1739b14a1346419a4598339aee32aab07e0d12e.tar.gz
rust-f1739b14a1346419a4598339aee32aab07e0d12e.zip
serialize: use Result
All of Decoder and Encoder's methods now return a Result.

Encodable.encode() and Decodable.decode() return a Result as well.

fixes #12292
Diffstat (limited to 'src/libsyntax/ext')
-rw-r--r--src/libsyntax/ext/build.rs48
-rw-r--r--src/libsyntax/ext/deriving/decodable.rs30
-rw-r--r--src/libsyntax/ext/deriving/encodable.rs40
3 files changed, 103 insertions, 15 deletions
diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index bdb16f176c0..1c2c63cd919 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -142,6 +142,10 @@ pub trait AstBuilder {
     fn expr_fail(&self, span: Span, msg: InternedString) -> @ast::Expr;
     fn expr_unreachable(&self, span: Span) -> @ast::Expr;
 
+    fn expr_ok(&self, span: Span, expr: @ast::Expr) -> @ast::Expr;
+    fn expr_err(&self, span: Span, expr: @ast::Expr) -> @ast::Expr;
+    fn expr_try(&self, span: Span, head: @ast::Expr) -> @ast::Expr;
+
     fn pat(&self, span: Span, pat: ast::Pat_) -> @ast::Pat;
     fn pat_wild(&self, span: Span) -> @ast::Pat;
     fn pat_lit(&self, span: Span, expr: @ast::Expr) -> @ast::Pat;
@@ -638,6 +642,50 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
                            "internal error: entered unreachable code"))
     }
 
+    fn expr_ok(&self, sp: Span, expr: @ast::Expr) -> @ast::Expr {
+        let ok = vec!(
+            self.ident_of("std"),
+            self.ident_of("result"),
+            self.ident_of("Ok"));
+        self.expr_call_global(sp, ok, vec!(expr))
+    }
+
+    fn expr_err(&self, sp: Span, expr: @ast::Expr) -> @ast::Expr {
+        let err = vec!(
+            self.ident_of("std"),
+            self.ident_of("result"),
+            self.ident_of("Err"));
+        self.expr_call_global(sp, err, vec!(expr))
+    }
+
+    fn expr_try(&self, sp: Span, head: @ast::Expr) -> @ast::Expr {
+        let ok = self.ident_of("Ok");
+        let ok_path = self.path_ident(sp, ok);
+        let err = self.ident_of("Err");
+        let err_path = self.path_ident(sp, err);
+
+        let binding_variable = self.ident_of("__try_var");
+        let binding_pat = self.pat_ident(sp, binding_variable);
+        let binding_expr = self.expr_ident(sp, binding_variable);
+
+        // Ok(__try_var) pattern
+        let ok_pat = self.pat_enum(sp, ok_path, vec!(binding_pat));
+
+        // Err(__try_var)  (pattern and expression resp.)
+        let err_pat = self.pat_enum(sp, err_path, vec!(binding_pat));
+        let err_inner_expr = self.expr_call_ident(sp, err, vec!(binding_expr));
+        // return Err(__try_var)
+        let err_expr = self.expr(sp, ast::ExprRet(Some(err_inner_expr)));
+
+        // Ok(__try_var) => __try_var
+        let ok_arm = self.arm(sp, vec!(ok_pat), binding_expr);
+        // Err(__try_var) => return Err(__try_var)
+        let err_arm = self.arm(sp, vec!(err_pat), err_expr);
+
+        // match head { Ok() => ..., Err() => ... }
+        self.expr_match(sp, head, vec!(ok_arm, err_arm))
+    }
+
 
     fn pat(&self, span: Span, pat: ast::Pat_) -> @ast::Pat {
         @ast::Pat { id: ast::DUMMY_NODE_ID, node: pat, span: span }
diff --git a/src/libsyntax/ext/deriving/decodable.rs b/src/libsyntax/ext/deriving/decodable.rs
index 4c9a58c46f7..579de82c8db 100644
--- a/src/libsyntax/ext/deriving/decodable.rs
+++ b/src/libsyntax/ext/deriving/decodable.rs
@@ -30,11 +30,15 @@ pub fn expand_deriving_decodable(cx: &mut ExtCtxt,
         span: span,
         attributes: Vec::new(),
         path: Path::new_(vec!("serialize", "Decodable"), None,
-                         vec!(~Literal(Path::new_local("__D"))), true),
+                         vec!(~Literal(Path::new_local("__D")),
+                              ~Literal(Path::new_local("__E"))), true),
         additional_bounds: Vec::new(),
         generics: LifetimeBounds {
             lifetimes: Vec::new(),
-            bounds: vec!(("__D", vec!(Path::new(vec!("serialize", "Decoder"))))),
+            bounds: vec!(("__D", vec!(Path::new_(
+                            vec!("serialize", "Decoder"), None,
+                            vec!(~Literal(Path::new_local("__E"))), true))),
+                         ("__E", vec!()))
         },
         methods: vec!(
             MethodDef {
@@ -43,7 +47,8 @@ pub fn expand_deriving_decodable(cx: &mut ExtCtxt,
                 explicit_self: None,
                 args: vec!(Ptr(~Literal(Path::new_local("__D")),
                             Borrowed(None, MutMutable))),
-                ret_ty: Self,
+                ret_ty: Literal(Path::new_(vec!("std", "result", "Result"), None,
+                                          vec!(~Self, ~Literal(Path::new_local("__E"))), true)),
                 inline: false,
                 const_nonmatching: true,
                 combine_substructure: decodable_substructure,
@@ -78,11 +83,13 @@ fn decodable_substructure(cx: &mut ExtCtxt, trait_span: Span,
                                               substr.type_ident,
                                               summary,
                                               |cx, span, name, field| {
-                cx.expr_method_call(span, blkdecoder, read_struct_field,
-                                    vec!(cx.expr_str(span, name),
-                                      cx.expr_uint(span, field),
-                                      lambdadecode))
+                cx.expr_try(span,
+                    cx.expr_method_call(span, blkdecoder, read_struct_field,
+                                        vec!(cx.expr_str(span, name),
+                                          cx.expr_uint(span, field),
+                                          lambdadecode)))
             });
+            let result = cx.expr_ok(trait_span, result);
             cx.expr_method_call(trait_span,
                                 decoder,
                                 cx.ident_of("read_struct"),
@@ -108,8 +115,9 @@ fn decodable_substructure(cx: &mut ExtCtxt, trait_span: Span,
                                                    parts,
                                                    |cx, span, _, field| {
                     let idx = cx.expr_uint(span, field);
-                    cx.expr_method_call(span, blkdecoder, rvariant_arg,
-                                        vec!(idx, lambdadecode))
+                    cx.expr_try(span,
+                        cx.expr_method_call(span, blkdecoder, rvariant_arg,
+                                            vec!(idx, lambdadecode)))
                 });
 
                 arms.push(cx.arm(v_span,
@@ -119,7 +127,9 @@ fn decodable_substructure(cx: &mut ExtCtxt, trait_span: Span,
 
             arms.push(cx.arm_unreachable(trait_span));
 
-            let result = cx.expr_match(trait_span, cx.expr_ident(trait_span, variant), arms);
+            let result = cx.expr_ok(trait_span,
+                                    cx.expr_match(trait_span,
+                                                  cx.expr_ident(trait_span, variant), arms));
             let lambda = cx.lambda_expr(trait_span, vec!(blkarg, variant), result);
             let variant_vec = cx.expr_vec(trait_span, variants);
             let result = cx.expr_method_call(trait_span, blkdecoder,
diff --git a/src/libsyntax/ext/deriving/encodable.rs b/src/libsyntax/ext/deriving/encodable.rs
index 2fa6ec6888b..90ea8701562 100644
--- a/src/libsyntax/ext/deriving/encodable.rs
+++ b/src/libsyntax/ext/deriving/encodable.rs
@@ -82,7 +82,7 @@ would yield functions like:
 ```
 */
 
-use ast::{MetaItem, Item, Expr, MutMutable};
+use ast::{MetaItem, Item, Expr, ExprRet, MutMutable, LitNil};
 use codemap::Span;
 use ext::base::ExtCtxt;
 use ext::build::AstBuilder;
@@ -98,20 +98,28 @@ pub fn expand_deriving_encodable(cx: &mut ExtCtxt,
         span: span,
         attributes: Vec::new(),
         path: Path::new_(vec!("serialize", "Encodable"), None,
-                         vec!(~Literal(Path::new_local("__E"))), true),
+                         vec!(~Literal(Path::new_local("__S")),
+                              ~Literal(Path::new_local("__E"))), true),
         additional_bounds: Vec::new(),
         generics: LifetimeBounds {
             lifetimes: Vec::new(),
-            bounds: vec!(("__E", vec!(Path::new(vec!("serialize", "Encoder"))))),
+            bounds: vec!(("__S", vec!(Path::new_(
+                            vec!("serialize", "Encoder"), None,
+                            vec!(~Literal(Path::new_local("__E"))), true))),
+                         ("__E", vec!()))
         },
         methods: vec!(
             MethodDef {
                 name: "encode",
                 generics: LifetimeBounds::empty(),
                 explicit_self: borrowed_explicit_self(),
-                args: vec!(Ptr(~Literal(Path::new_local("__E")),
+                args: vec!(Ptr(~Literal(Path::new_local("__S")),
                             Borrowed(None, MutMutable))),
-                ret_ty: nil_ty(),
+                ret_ty: Literal(Path::new_(vec!("std", "result", "Result"),
+                                           None,
+                                           vec!(~Tuple(Vec::new()),
+                                                ~Literal(Path::new_local("__E"))),
+                                           true)),
                 inline: false,
                 const_nonmatching: true,
                 combine_substructure: encodable_substructure,
@@ -133,6 +141,7 @@ fn encodable_substructure(cx: &mut ExtCtxt, trait_span: Span,
         Struct(ref fields) => {
             let emit_struct_field = cx.ident_of("emit_struct_field");
             let mut stmts = Vec::new();
+            let last = fields.len() - 1;
             for (i, &FieldInfo {
                     name,
                     self_,
@@ -152,6 +161,13 @@ fn encodable_substructure(cx: &mut ExtCtxt, trait_span: Span,
                                                vec!(cx.expr_str(span, name),
                                                  cx.expr_uint(span, i),
                                                  lambda));
+
+                // last call doesn't need a try!
+                let call = if i != last {
+                    cx.expr_try(span, call)
+                } else {
+                    cx.expr(span, ExprRet(Some(call)))
+                };
                 stmts.push(cx.stmt_expr(call));
             }
 
@@ -175,6 +191,7 @@ fn encodable_substructure(cx: &mut ExtCtxt, trait_span: Span,
             let encoder = cx.expr_ident(trait_span, blkarg);
             let emit_variant_arg = cx.ident_of("emit_enum_variant_arg");
             let mut stmts = Vec::new();
+            let last = fields.len() - 1;
             for (i, &FieldInfo { self_, span, .. }) in fields.iter().enumerate() {
                 let enc = cx.expr_method_call(span, self_, encode, vec!(blkencoder));
                 let lambda = cx.lambda_expr_1(span, enc, blkarg);
@@ -182,9 +199,22 @@ fn encodable_substructure(cx: &mut ExtCtxt, trait_span: Span,
                                                emit_variant_arg,
                                                vec!(cx.expr_uint(span, i),
                                                  lambda));
+                let call = if i != last {
+                    cx.expr_try(span, call)
+                } else {
+                    cx.expr(span, ExprRet(Some(call)))
+                };
                 stmts.push(cx.stmt_expr(call));
             }
 
+            // enums with no fields need to return Ok()
+            if stmts.len() == 0 {
+                let ret_ok = cx.expr(trait_span,
+                                     ExprRet(Some(cx.expr_ok(trait_span,
+                                                             cx.expr_lit(trait_span, LitNil)))));
+                stmts.push(cx.stmt_expr(ret_ok));
+            }
+
             let blk = cx.lambda_stmts_1(trait_span, stmts, blkarg);
             let name = cx.expr_str(trait_span, token::get_ident(variant.node.name));
             let call = cx.expr_method_call(trait_span, blkencoder,