diff options
| author | Erick Tryzelaar <erick.tryzelaar@gmail.com> | 2013-03-26 18:46:48 -0700 |
|---|---|---|
| committer | Erick Tryzelaar <erick.tryzelaar@gmail.com> | 2013-03-27 07:04:13 -0700 |
| commit | 4d6dcefcbb8688b69dd80bc7382a2f593c3b08d8 (patch) | |
| tree | 0c688bb5af8a87ec2566e0d88da9b031e539e625 /src | |
| parent | 478e4498b76178dc0031f88f0d5ee31c5f804d0b (diff) | |
| download | rust-4d6dcefcbb8688b69dd80bc7382a2f593c3b08d8.tar.gz rust-4d6dcefcbb8688b69dd80bc7382a2f593c3b08d8.zip | |
std: Decode::read_enum_variant should pass in the variant names
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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/librustc/middle/astencode.rs | 39 | ||||
| -rw-r--r-- | src/libstd/ebml.rs | 30 | ||||
| -rw-r--r-- | src/libstd/json.rs | 27 | ||||
| -rw-r--r-- | src/libstd/serialize.rs | 8 | ||||
| -rw-r--r-- | src/libsyntax/ext/auto_encode.rs | 17 |
5 files changed, 116 insertions, 5 deletions
diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index 1e1dde33037..7b4d1034f74 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -681,6 +681,7 @@ impl vtable_decoder_helpers for reader::Decoder { @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 @@ impl vtable_decoder_helpers for reader::Decoder { } } } + + #[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") + } + } + } + } } // ______________________________________________________________________ diff --git a/src/libstd/ebml.rs b/src/libstd/ebml.rs index 90389602bc4..60a00bee0ac 100644 --- a/src/libstd/ebml.rs +++ b/src/libstd/ebml.rs @@ -337,6 +337,7 @@ pub mod reader { 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 @@ pub mod reader { } } + #[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 @@ pub mod reader { 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 @@ pub mod reader { } } } + + #[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!(), + } + } + } + } } } diff --git a/src/libstd/json.rs b/src/libstd/json.rs index bb1102be9f7..dc9f629d7e2 100644 --- a/src/libstd/json.rs +++ b/src/libstd/json.rs @@ -855,6 +855,7 @@ impl<'self> serialize::Decoder for Decoder<'self> { 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 @@ impl<'self> serialize::Decoder for Decoder<'self> { 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 { diff --git a/src/libstd/serialize.rs b/src/libstd/serialize.rs index 69977c6e4fe..02f4a934874 100644 --- a/src/libstd/serialize.rs +++ b/src/libstd/serialize.rs @@ -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; diff --git a/src/libsyntax/ext/auto_encode.rs b/src/libsyntax/ext/auto_encode.rs index bafd2bb6adb..2a112f106a8 100644 --- a/src/libsyntax/ext/auto_encode.rs +++ b/src/libsyntax/ext/auto_encode.rs @@ -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}; |
