]> git.lizzy.rs Git - rust.git/commitdiff
std: Decode::read_enum_variant should pass in the variant names
authorErick Tryzelaar <erick.tryzelaar@gmail.com>
Wed, 27 Mar 2013 01:46:48 +0000 (18:46 -0700)
committerErick Tryzelaar <erick.tryzelaar@gmail.com>
Wed, 27 Mar 2013 14:04:13 +0000 (07:04 -0700)
Because the json::Decoder uses the string variant name, we need a
way to correlate the string to the enum index. This passes in a
static &[&str] to read_enum_variant, which allows the json::Decoder
to know which branch it's trying to process.

src/librustc/middle/astencode.rs
src/libstd/ebml.rs
src/libstd/json.rs
src/libstd/serialize.rs
src/libsyntax/ext/auto_encode.rs

index 1e1dde3303788710bdd5a1d67cab4726016c4faa..7b4d1034f74eb040e7a7c4a370d434a8a091dbae 100644 (file)
@@ -681,6 +681,7 @@ fn read_vtable_res(&self, xcx: @ExtendedDecodeContext)
         @self.read_to_vec(|| self.read_vtable_origin(xcx) )
     }
 
+    #[cfg(stage0)]
     fn read_vtable_origin(&self, xcx: @ExtendedDecodeContext)
         -> typeck::vtable_origin {
         do self.read_enum(~"vtable_origin") {
@@ -715,6 +716,44 @@ fn read_vtable_origin(&self, xcx: @ExtendedDecodeContext)
             }
         }
     }
+
+    #[cfg(stage1)]
+    #[cfg(stage2)]
+    #[cfg(stage3)]
+    fn read_vtable_origin(&self, xcx: @ExtendedDecodeContext)
+        -> typeck::vtable_origin {
+        do self.read_enum("vtable_origin") {
+            do self.read_enum_variant(["vtable_static", "vtable_param"]) |i| {
+                match i {
+                  0 => {
+                    typeck::vtable_static(
+                        do self.read_enum_variant_arg(0u) {
+                            self.read_def_id(xcx)
+                        },
+                        do self.read_enum_variant_arg(1u) {
+                            self.read_tys(xcx)
+                        },
+                        do self.read_enum_variant_arg(2u) {
+                            self.read_vtable_res(xcx)
+                        }
+                    )
+                  }
+                  1 => {
+                    typeck::vtable_param(
+                        do self.read_enum_variant_arg(0u) {
+                            self.read_uint()
+                        },
+                        do self.read_enum_variant_arg(1u) {
+                            self.read_uint()
+                        }
+                    )
+                  }
+                  // hard to avoid - user input
+                  _ => fail!(~"bad enum variant")
+                }
+            }
+        }
+    }
 }
 
 // ______________________________________________________________________
index 90389602bc4a24b5a5533b8ce806c5e7be8118bf..60a00bee0acba4a9c6ff82b0407017fc9ea90abc 100644 (file)
@@ -337,6 +337,7 @@ fn read_enum<T>(&self, name: &str, f: &fn() -> T) -> T {
             self.push_doc(self.next_doc(EsEnum), f)
         }
 
+        #[cfg(stage0)]
         fn read_enum_variant<T>(&self, f: &fn(uint) -> T) -> T {
             debug!("read_enum_variant()");
             let idx = self._next_uint(EsEnumVid);
@@ -346,6 +347,18 @@ fn read_enum_variant<T>(&self, f: &fn(uint) -> T) -> T {
             }
         }
 
+        #[cfg(stage1)]
+        #[cfg(stage2)]
+        #[cfg(stage3)]
+        fn read_enum_variant<T>(&self, _names: &[&str], f: &fn(uint) -> T) -> T {
+            debug!("read_enum_variant()");
+            let idx = self._next_uint(EsEnumVid);
+            debug!("  idx=%u", idx);
+            do self.push_doc(self.next_doc(EsEnumBody)) {
+                f(idx)
+            }
+        }
+
         fn read_enum_variant_arg<T>(&self, idx: uint, f: &fn() -> T) -> T {
             debug!("read_enum_variant_arg(idx=%u)", idx);
             f()
@@ -400,6 +413,7 @@ fn read_tup_elt<T>(&self, idx: uint, f: &fn() -> T) -> T {
             f()
         }
 
+        #[cfg(stage0)]
         fn read_option<T>(&self, f: &fn() -> T) -> Option<T> {
             debug!("read_option()");
             do self.read_enum("Option") || {
@@ -412,6 +426,22 @@ fn read_option<T>(&self, f: &fn() -> T) -> Option<T> {
                 }
             }
         }
+
+        #[cfg(stage1)]
+        #[cfg(stage2)]
+        #[cfg(stage3)]
+        fn read_option<T>(&self, f: &fn() -> T) -> Option<T> {
+            debug!("read_option()");
+            do self.read_enum("Option") || {
+                do self.read_enum_variant(["None", "Some"]) |idx| {
+                    match idx {
+                        0 => None,
+                        1 => Some(f()),
+                        _ => fail!(),
+                    }
+                }
+            }
+        }
     }
 }
 
index bb1102be9f7401d7f7b9c64135e92677689dfffe..dc9f629d7e231173a4cdf451ffecab5f32916af7 100644 (file)
@@ -855,6 +855,7 @@ fn read_enum<T>(&self, name: &str, f: &fn() -> T) -> T {
         f()
     }
 
+    #[cfg(stage0)]
     fn read_enum_variant<T>(&self, f: &fn(uint) -> T) -> T {
         debug!("read_enum_variant()");
         let idx = match *self.peek() {
@@ -864,10 +865,32 @@ fn read_enum_variant<T>(&self, f: &fn(uint) -> T) -> T {
         f(idx)
     }
 
+    #[cfg(stage1)]
+    #[cfg(stage2)]
+    #[cfg(stage3)]
+    fn read_enum_variant<T>(&self, names: &[&str], f: &fn(uint) -> T) -> T {
+        debug!("read_enum_variant(names=%?)", names);
+        let name = match *self.peek() {
+            String(ref s) => s,
+            List([String(ref s), .. _]) => s,
+            json => fail!(fmt!("invalid variant: %?", json)),
+        };
+        let idx = match vec::position(names, |n| str::eq_slice(*n, *name)) {
+            Some(idx) => idx,
+            None => fail!(fmt!("Unknown variant name: %?", name)),
+        };
+        f(idx)
+    }
+
     fn read_enum_variant_arg<T>(&self, idx: uint, f: &fn() -> T) -> T {
         debug!("read_enum_variant_arg(idx=%u)", idx);
-        if idx != 0 { fail!(~"unknown index") }
-        f()
+        match *self.peek() {
+            List(ref list) => {
+                self.stack.push(&list[idx + 1]);
+                f()
+            }
+            ref json => fail!(fmt!("not a list: %?", json)),
+        }
     }
 
     fn read_owned_vec<T>(&self, f: &fn(uint) -> T) -> T {
index 69977c6e4fe0181cc4a3528a0f06ed75adf16419..02f4a934874325bc73ab582ecc2e4fdb624a4b53 100644 (file)
@@ -92,7 +92,15 @@ pub trait Decoder {
 
     // Compound types:
     fn read_enum<T>(&self, name: &str, f: &fn() -> T) -> T;
+
+    #[cfg(stage0)]
     fn read_enum_variant<T>(&self, f: &fn(uint) -> T) -> T;
+
+    #[cfg(stage1)]
+    #[cfg(stage2)]
+    #[cfg(stage3)]
+    fn read_enum_variant<T>(&self, names: &[&str], f: &fn(uint) -> T) -> T;
+
     fn read_enum_variant_arg<T>(&self, idx: uint, f: &fn() -> T) -> T;
 
     fn read_owned<T>(&self, f: &fn() -> T) -> T;
index bafd2bb6adbcd3181812a2ed28f1364ac473dc4c..2a112f106a850b43f9eb1a46b309b5b4b362ba73 100644 (file)
@@ -1059,6 +1059,18 @@ fn mk_enum_deser_body(
     name: ast::ident,
     variants: ~[ast::variant]
 ) -> @ast::expr {
+    let expr_arm_names = build::mk_base_vec_e(
+        ext_cx,
+        span,
+         do variants.map |variant| {
+            build::mk_base_str(
+                ext_cx,
+                span,
+                ext_cx.str_of(variant.node.name)
+            )
+        }
+    );
+
     let mut arms = do variants.mapi |v_idx, variant| {
         let body = match variant.node.kind {
             ast::tuple_variant_kind(ref args) => {
@@ -1152,13 +1164,13 @@ fn mk_enum_deser_body(
         )
     );
 
-    // ast for `__d.read_enum_variant($(expr_lambda))`
+    // ast for `__d.read_enum_variant($expr_arm_names, $(expr_lambda))`
     let expr_lambda = ext_cx.lambda_expr(
         ext_cx.expr_method_call(
             span,
             ext_cx.expr_var(span, ~"__d"),
             ext_cx.ident_of(~"read_enum_variant"),
-            ~[expr_lambda]
+            ~[expr_arm_names, expr_lambda]
         )
     );
 
@@ -1174,7 +1186,6 @@ fn mk_enum_deser_body(
     )
 }
 
-
 #[cfg(test)]
 mod test {
     use core::option::{None, Some};