diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index 1e1dde330378..7b4d1034f74e 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 90389602bc4a..60a00bee0acb 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(&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(&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(&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(&self, f: &fn() -> T) -> Option { debug!("read_option()"); do self.read_enum("Option") || { @@ -412,6 +426,22 @@ pub mod reader { } } } + + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn read_option(&self, f: &fn() -> T) -> Option { + 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 bb1102be9f74..dc9f629d7e23 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(&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(&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(&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(&self, f: &fn(uint) -> T) -> T { diff --git a/src/libstd/serialize.rs b/src/libstd/serialize.rs index 69977c6e4fe0..02f4a9348743 100644 --- a/src/libstd/serialize.rs +++ b/src/libstd/serialize.rs @@ -92,7 +92,15 @@ pub trait Decoder { // Compound types: fn read_enum(&self, name: &str, f: &fn() -> T) -> T; + + #[cfg(stage0)] fn read_enum_variant(&self, f: &fn(uint) -> T) -> T; + + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn read_enum_variant(&self, names: &[&str], f: &fn(uint) -> T) -> T; + fn read_enum_variant_arg(&self, idx: uint, f: &fn() -> T) -> T; fn read_owned(&self, f: &fn() -> T) -> T; diff --git a/src/libsyntax/ext/auto_encode.rs b/src/libsyntax/ext/auto_encode.rs index bafd2bb6adbc..2a112f106a85 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};