diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index 2ec5b59b9c5..c2692e9fa10 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -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") + } + } + } + } } // ______________________________________________________________________ diff --git a/src/librustc/middle/check_const.rs b/src/librustc/middle/check_const.rs index f9212d1ff7b..4bbedf5fc00 100644 --- a/src/librustc/middle/check_const.rs +++ b/src/librustc/middle/check_const.rs @@ -156,7 +156,6 @@ pub fn check_expr(sess: Session, expr_paren(e) => { check_expr(sess, def_map, method_map, tcx, e, is_const, v); } expr_vstore(_, expr_vstore_slice) | - expr_vstore(_, expr_vstore_fixed(_)) | expr_vec(_, m_imm) | expr_addr_of(m_imm, _) | expr_field(*) | diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs index a25d873af41..d610b007f35 100644 --- a/src/librustc/middle/const_eval.rs +++ b/src/librustc/middle/const_eval.rs @@ -110,7 +110,6 @@ pub fn classify(e: @expr, ast::expr_vstore(e, vstore) => { match vstore { - ast::expr_vstore_fixed(_) | ast::expr_vstore_slice => classify(e, tcx), ast::expr_vstore_uniq | ast::expr_vstore_box | diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 4d6226a5db6..503077e5b06 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -1290,7 +1290,7 @@ fn propagate_through_expr(&self, expr: @expr, succ: LiveNode) self.propagate_through_expr(l, ln) } - expr_log(_, l, r) | + expr_log(l, r) | expr_index(l, r) | expr_binary(_, l, r) => { self.propagate_through_exprs(~[l, r], succ) diff --git a/src/librustc/middle/moves.rs b/src/librustc/middle/moves.rs index f5382d69174..a8749138549 100644 --- a/src/librustc/middle/moves.rs +++ b/src/librustc/middle/moves.rs @@ -567,7 +567,7 @@ fn use_expr(&self, self.consume_block(blk, visitor); } - expr_log(_, a_expr, b_expr) => { + expr_log(a_expr, b_expr) => { self.consume_expr(a_expr, visitor); self.use_expr(b_expr, Read, visitor); } diff --git a/src/librustc/middle/trans/consts.rs b/src/librustc/middle/trans/consts.rs index 1362f97c08e..050fc0dd334 100644 --- a/src/librustc/middle/trans/consts.rs +++ b/src/librustc/middle/trans/consts.rs @@ -466,9 +466,6 @@ fn const_expr_unadjusted(cx: @CrateContext, e: @ast::expr) -> ValueRef { let (v, _, _) = const_vec(cx, e, *es); v } - ast::expr_vstore(e, ast::expr_vstore_fixed(_)) => { - const_expr(cx, e) - } ast::expr_vstore(sub, ast::expr_vstore_slice) => { match sub.node { ast::expr_lit(ref lit) => { diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs index 3e1496692ae..4ee63f8bf33 100644 --- a/src/librustc/middle/trans/expr.rs +++ b/src/librustc/middle/trans/expr.rs @@ -496,7 +496,7 @@ fn trans_rvalue_stmt_unadjusted(bcx: block, expr: @ast::expr) -> block { ast::expr_ret(ex) => { return controlflow::trans_ret(bcx, ex); } - ast::expr_log(_, lvl, a) => { + ast::expr_log(lvl, a) => { return controlflow::trans_log(expr, lvl, bcx, a); } ast::expr_while(cond, ref body) => { @@ -703,9 +703,6 @@ fn trans_rvalue_dps_unadjusted(bcx: block, expr: @ast::expr, ast::expr_vstore(contents, ast::expr_vstore_mut_slice) => { return tvec::trans_slice_vstore(bcx, expr, contents, dest); } - ast::expr_vstore(contents, ast::expr_vstore_fixed(_)) => { - return tvec::trans_fixed_vstore(bcx, expr, contents, dest); - } ast::expr_vec(*) | ast::expr_repeat(*) => { return tvec::trans_fixed_vstore(bcx, expr, expr, dest); } diff --git a/src/librustc/middle/trans/type_use.rs b/src/librustc/middle/trans/type_use.rs index cad2a03f7a1..1d9e57ce8ce 100644 --- a/src/librustc/middle/trans/type_use.rs +++ b/src/librustc/middle/trans/type_use.rs @@ -329,7 +329,7 @@ pub fn mark_for_expr(cx: Context, e: @expr) { type_needs(cx, use_repr, ty::type_autoderef(cx.ccx.tcx, base_ty)); mark_for_method_call(cx, e.id, e.callee_id); } - expr_log(_, _, val) => { + expr_log(_, val) => { node_type_needs(cx, use_tydesc, val.id); } expr_call(f, _, _) => { diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 088d8183d48..58db934160b 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -3114,7 +3114,6 @@ pub fn expr_kind(tcx: ctxt, ast::expr_lit(@codemap::spanned {node: lit_str(_), _}) | ast::expr_vstore(_, ast::expr_vstore_slice) | ast::expr_vstore(_, ast::expr_vstore_mut_slice) | - ast::expr_vstore(_, ast::expr_vstore_fixed(_)) | ast::expr_vec(*) => { RvalueDpsExpr } diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 85efc9fa738..8762cdf516b 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -2366,7 +2366,7 @@ fn check_loop_body(fcx: @mut FnCtxt, } fcx.write_bot(id); } - ast::expr_log(_, lv, e) => { + ast::expr_log(lv, e) => { check_expr_has_type(fcx, lv, ty::mk_mach_uint(tcx, ast::ty_u32)); @@ -3301,14 +3301,6 @@ pub fn ast_expr_vstore_to_vstore(fcx: @mut FnCtxt, v: ast::expr_vstore) -> ty::vstore { match v { - ast::expr_vstore_fixed(None) => ty::vstore_fixed(n), - ast::expr_vstore_fixed(Some(u)) => { - if n != u { - let s = fmt!("fixed-size sequence mismatch: %u vs. %u",u, n); - fcx.ccx.tcx.sess.span_err(e.span,s); - } - ty::vstore_fixed(u) - } ast::expr_vstore_uniq => ty::vstore_uniq, ast::expr_vstore_box | ast::expr_vstore_mut_box => ty::vstore_box, ast::expr_vstore_slice | ast::expr_vstore_mut_slice => { diff --git a/src/libstd/ebml.rs b/src/libstd/ebml.rs index b82616d386a..8b559295819 100644 --- a/src/libstd/ebml.rs +++ b/src/libstd/ebml.rs @@ -335,6 +335,7 @@ fn read_enum(&self, name: &str, f: &fn() -> T) -> T { 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); @@ -344,6 +345,18 @@ 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 { + 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() @@ -397,8 +410,37 @@ fn read_tup_elt(&self, idx: uint, f: &fn() -> T) -> T { debug!("read_tup_elt(idx=%u)", idx); f() } - } + #[cfg(stage0)] + fn read_option(&self, f: &fn() -> T) -> Option { + debug!("read_option()"); + do self.read_enum("Option") || { + do self.read_enum_variant |idx| { + match idx { + 0 => None, + 1 => Some(f()), + _ => fail!(), + } + } + } + } + + #[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!(), + } + } + } + } + } } pub mod writer { @@ -664,9 +706,19 @@ fn emit_field(&self, name: &str, _idx: uint, f: &fn()) { fn emit_tup(&self, _len: uint, f: &fn()) { f() } fn emit_tup_elt(&self, _idx: uint, f: &fn()) { f() } - } + fn emit_option(&self, f: &fn()) { + self.emit_enum("Option", f); + } + fn emit_option_none(&self) { + self.emit_enum_variant("None", 0, 0, || ()) + } + fn emit_option_some(&self, f: &fn()) { + self.emit_enum_variant("Some", 1, 1, f) + } + } } + // ___________________________________________________________________________ // Testing diff --git a/src/libstd/json.rs b/src/libstd/json.rs index 7c9b15bfded..c48b210dca2 100644 --- a/src/libstd/json.rs +++ b/src/libstd/json.rs @@ -119,39 +119,19 @@ fn emit_enum(&self, _name: &str, f: &fn()) { f() } - fn emit_enum_variant(&self, name: &str, _id: uint, _cnt: uint, f: &fn()) { - // encoding of enums is special-cased for Option. Specifically: - // Some(34) => 34 - // None => null - - // other enums are encoded as vectors: + fn emit_enum_variant(&self, name: &str, _id: uint, cnt: uint, f: &fn()) { + // enums are encoded as strings or vectors: + // Bunny => "Bunny" // Kangaroo(34,"William") => ["Kangaroo",[34,"William"]] - // the default expansion for enums is more verbose than I'd like; - // specifically, the inner pair of brackets seems superfluous, - // BUT the design of the enumeration framework and the requirements - // of the special-case for Option mean that a first argument must - // be encoded "naked"--with no commas--and that the option name - // can't be followed by just a comma, because there might not - // be any elements in the tuple. - - // FIXME #4872: this would be more precise and less frightening - // with fully-qualified option names. To get that information, - // we'd have to change the expansion of auto-encode to pass - // those along. - - if (name == ~"Some") { - f(); - } else if (name == ~"None") { - self.wr.write_str(~"null"); + if cnt == 0 { + self.wr.write_str(escape_str(name)); } else { self.wr.write_char('['); self.wr.write_str(escape_str(name)); self.wr.write_char(','); - self.wr.write_char('['); f(); self.wr.write_char(']'); - self.wr.write_char(']'); } } @@ -200,6 +180,10 @@ fn emit_tup(&self, len: uint, f: &fn()) { fn emit_tup_elt(&self, idx: uint, f: &fn()) { self.emit_vec_elt(idx, f) } + + fn emit_option(&self, f: &fn()) { f(); } + fn emit_option_none(&self) { self.emit_nil(); } + fn emit_option_some(&self, f: &fn()) { f(); } } pub struct PrettyEncoder { @@ -250,27 +234,44 @@ fn emit_borrowed(&self, f: &fn()) { f() } fn emit_owned(&self, f: &fn()) { f() } fn emit_managed(&self, f: &fn()) { f() } - fn emit_enum(&self, name: &str, f: &fn()) { - if name != "option" { fail!(~"only supports option enum") } - f() - } - fn emit_enum_variant(&self, _name: &str, id: uint, _cnt: uint, f: &fn()) { - if id == 0 { - self.emit_nil(); + fn emit_enum(&self, _name: &str, f: &fn()) { f() } + fn emit_enum_variant(&self, name: &str, _id: uint, cnt: uint, f: &fn()) { + if cnt == 0 { + self.wr.write_str(escape_str(name)); } else { - f() + self.wr.write_char('['); + self.indent += 2; + self.wr.write_char('\n'); + self.wr.write_str(spaces(self.indent)); + self.wr.write_str(escape_str(name)); + self.wr.write_str(",\n"); + f(); + self.wr.write_char('\n'); + self.indent -= 2; + self.wr.write_str(spaces(self.indent)); + self.wr.write_char(']'); } } - fn emit_enum_variant_arg(&self, _idx: uint, f: &fn()) { + fn emit_enum_variant_arg(&self, idx: uint, f: &fn()) { + if idx != 0 { + self.wr.write_str(",\n"); + } + self.wr.write_str(spaces(self.indent)); f() } - fn emit_borrowed_vec(&self, _len: uint, f: &fn()) { - self.wr.write_char('['); - self.indent += 2; - f(); - self.indent -= 2; - self.wr.write_char(']'); + fn emit_borrowed_vec(&self, len: uint, f: &fn()) { + if len == 0 { + self.wr.write_str("[]"); + } else { + self.wr.write_char('['); + self.indent += 2; + f(); + self.wr.write_char('\n'); + self.indent -= 2; + self.wr.write_str(spaces(self.indent)); + self.wr.write_char(']'); + } } fn emit_owned_vec(&self, len: uint, f: &fn()) { self.emit_borrowed_vec(len, f) @@ -292,11 +293,17 @@ fn emit_rec(&self, f: &fn()) { self.wr.write_char('{'); self.indent += 2; f(); + self.wr.write_char('\n'); self.indent -= 2; + self.wr.write_str(spaces(self.indent)); self.wr.write_char('}'); } - fn emit_struct(&self, _name: &str, _len: uint, f: &fn()) { - self.emit_rec(f) + fn emit_struct(&self, _name: &str, len: uint, f: &fn()) { + if len == 0 { + self.wr.write_str("{}"); + } else { + self.emit_rec(f) + } } fn emit_field(&self, name: &str, idx: uint, f: &fn()) { if idx == 0 { @@ -315,6 +322,10 @@ fn emit_tup(&self, sz: uint, f: &fn()) { fn emit_tup_elt(&self, idx: uint, f: &fn()) { self.emit_vec_elt(idx, f) } + + fn emit_option(&self, f: &fn()) { f(); } + fn emit_option_none(&self) { self.emit_nil(); } + fn emit_option_some(&self, f: &fn()) { f(); } } impl serialize::Encodable for Json { @@ -816,7 +827,7 @@ fn read_owned_str(&self) -> ~str { debug!("read_owned_str"); match *self.pop() { String(ref s) => copy *s, - _ => fail!(~"not a string") + ref json => fail!(fmt!("not a string: %?", *json)) } } @@ -824,7 +835,7 @@ fn read_managed_str(&self) -> @str { debug!("read_managed_str"); match *self.pop() { String(ref s) => s.to_managed(), - _ => fail!(~"not a string") + ref json => fail!(fmt!("not a string: %?", *json)) } } @@ -840,10 +851,10 @@ fn read_managed(&self, f: &fn() -> T) -> T { fn read_enum(&self, name: &str, f: &fn() -> T) -> T { debug!("read_enum(%s)", name); - if name != ~"option" { fail!(~"only supports the option enum") } f() } + #[cfg(stage0)] fn read_enum_variant(&self, f: &fn(uint) -> T) -> T { debug!("read_enum_variant()"); let idx = match *self.peek() { @@ -853,10 +864,32 @@ fn read_enum_variant(&self, f: &fn(uint) -> T) -> T { 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, + ref 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 { @@ -946,6 +979,13 @@ fn read_tup_elt(&self, idx: uint, f: &fn() -> T) -> T { _ => fail!(~"not a list") } } + + fn read_option(&self, f: &fn() -> T) -> Option { + match *self.peek() { + Null => { self.pop(); None } + _ => Some(f()), + } + } } impl Eq for Json { @@ -1195,14 +1235,12 @@ fn to_str(&self) -> ~str { #[cfg(test)] mod tests { + use super::*; + use core::prelude::*; - - use json::*; - use serialize; - - use core::result; use core::hashmap::linear::LinearMap; + use std::serialize::Decodable; fn mk_object(items: &[(~str, Json)]) -> Json { let mut d = ~LinearMap::new(); @@ -1218,45 +1256,89 @@ fn mk_object(items: &[(~str, Json)]) -> Json { #[test] fn test_write_null() { - fail_unless!(to_str(&Null) == ~"null"); + assert_eq!(to_str(&Null), ~"null"); } #[test] fn test_write_number() { - fail_unless!(to_str(&Number(3f)) == ~"3"); - fail_unless!(to_str(&Number(3.1f)) == ~"3.1"); - fail_unless!(to_str(&Number(-1.5f)) == ~"-1.5"); - fail_unless!(to_str(&Number(0.5f)) == ~"0.5"); + assert_eq!(to_str(&Number(3f)), ~"3"); + assert_eq!(to_str(&Number(3.1f)), ~"3.1"); + assert_eq!(to_str(&Number(-1.5f)), ~"-1.5"); + assert_eq!(to_str(&Number(0.5f)), ~"0.5"); } #[test] fn test_write_str() { - fail_unless!(to_str(&String(~"")) == ~"\"\""); - fail_unless!(to_str(&String(~"foo")) == ~"\"foo\""); + assert_eq!(to_str(&String(~"")), ~"\"\""); + assert_eq!(to_str(&String(~"foo")), ~"\"foo\""); } #[test] fn test_write_bool() { - fail_unless!(to_str(&Boolean(true)) == ~"true"); - fail_unless!(to_str(&Boolean(false)) == ~"false"); + assert_eq!(to_str(&Boolean(true)), ~"true"); + assert_eq!(to_str(&Boolean(false)), ~"false"); } #[test] fn test_write_list() { - fail_unless!(to_str(&List(~[])) == ~"[]"); - fail_unless!(to_str(&List(~[Boolean(true)])) == ~"[true]"); - fail_unless!(to_str(&List(~[ + assert_eq!(to_str(&List(~[])), ~"[]"); + assert_eq!(to_str(&List(~[Boolean(true)])), ~"[true]"); + assert_eq!(to_str(&List(~[ Boolean(false), Null, List(~[String(~"foo\nbar"), Number(3.5f)]) - ])) == ~"[false,null,[\"foo\\nbar\",3.5]]"); + ])), ~"[false,null,[\"foo\\nbar\",3.5]]"); + } + + #[test] + fn test_write_list_pretty() { + assert_eq!(to_pretty_str(&List(~[])), ~"[]"); + assert_eq!( + to_pretty_str(&List(~[Boolean(true)])), + ~"\ + [\n \ + true\n\ + ]" + ); + assert_eq!( + to_pretty_str(&List(~[ + Boolean(false), + Null, + List(~[String(~"foo\nbar"), Number(3.5f)]) + ])), + ~"\ + [\n \ + false,\n \ + null,\n \ + [\n \ + \"foo\\nbar\",\n \ + 3.5\n \ + ]\n\ + ]" + ); } #[test] fn test_write_object() { - fail_unless!(to_str(&mk_object(~[])) == ~"{}"); - fail_unless!(to_str(&mk_object(~[(~"a", Boolean(true))])) - == ~"{\"a\":true}"); + assert_eq!(to_str(&mk_object(~[])), ~"{}"); + assert_eq!( + to_str(&mk_object(~[(~"a", Boolean(true))])), + ~"{\"a\":true}" + ); + assert_eq!( + to_str(&mk_object(~[ + (~"b", List(~[ + mk_object(~[(~"c", String(~"\x0c\r"))]), + mk_object(~[(~"d", String(~""))]) + ])) + ])), + ~"{\ + \"b\":[\ + {\"c\":\"\\f\\r\"},\ + {\"d\":\"\"}\ + ]\ + }" + ); let a = mk_object(~[ (~"a", Boolean(true)), (~"b", List(~[ @@ -1266,248 +1348,343 @@ fn test_write_object() { ]); // We can't compare the strings directly because the object fields be // printed in a different order. - let b = result::unwrap(from_str(to_str(&a))); - fail_unless!(a == b); + let b = from_str(to_str(&a)).unwrap(); + assert_eq!(a, b); } #[test] - fn test_write_enum () { - let bw = @io::BytesWriter(); - let bww : @io::Writer = (bw as @io::Writer); - let encoder = (@Encoder(bww) as @serialize::Encoder); - do encoder.emit_enum(~"animal") { - do encoder.emit_enum_variant (~"frog",37,1242) { - // name of frog: - do encoder.emit_enum_variant_arg (0) { - encoder.emit_owned_str(~"Henry") - } - // mass of frog in grams: - do encoder.emit_enum_variant_arg (1) { - encoder.emit_int(349); - } - } - } - assert_eq!(str::from_bytes(bw.bytes), ~"[\"frog\",[\"Henry\",349]]"); + fn test_write_object_pretty() { + assert_eq!(to_pretty_str(&mk_object(~[])), ~"{\n}"); + assert_eq!( + to_pretty_str(&mk_object(~[(~"a", Boolean(true))])), + ~"\ + {\n \ + \"a\": true\n\ + }" + ); + assert_eq!( + to_pretty_str(&mk_object(~[ + (~"b", List(~[ + mk_object(~[(~"c", String(~"\x0c\r"))]), + mk_object(~[(~"d", String(~""))]) + ])) + ])), + ~"\ + {\n \ + \"b\": [\n \ + {\n \ + \"c\": \"\\f\\r\"\n \ + },\n \ + {\n \ + \"d\": \"\"\n \ + }\n \ + ]\n\ + }" + ); + let a = mk_object(~[ + (~"a", Boolean(true)), + (~"b", List(~[ + mk_object(~[(~"c", String(~"\x0c\r"))]), + mk_object(~[(~"d", String(~""))]) + ])) + ]); + // We can't compare the strings directly because the object fields be + // printed in a different order. + let b = from_str(to_str(&a)).unwrap(); + assert_eq!(a, b); + } + + #[auto_encode] + #[auto_decode] + #[deriving(Eq)] + enum Animal { + Dog, + Frog(~str, int) } #[test] - fn test_write_some () { - let bw = @io::BytesWriter(); - let bww : @io::Writer = (bw as @io::Writer); - let encoder = (@Encoder(bww) as @serialize::Encoder); - do encoder.emit_enum(~"Option") { - do encoder.emit_enum_variant (~"Some",37,1242) { - do encoder.emit_enum_variant_arg (0) { - encoder.emit_owned_str(~"jodhpurs") - } - } - } - assert_eq!(str::from_bytes(bw.bytes), ~"\"jodhpurs\""); + fn test_write_enum_no_args() { + let animal = Dog; + + let s = do io::with_str_writer |wr| { + let encoder = Encoder(wr); + animal.encode(&encoder); + }; + assert_eq!(s, ~"\"Dog\""); } #[test] - fn test_write_none () { - let bw = @io::BytesWriter(); - let bww : @io::Writer = (bw as @io::Writer); - let encoder = (@Encoder(bww) as @serialize::Encoder); - do encoder.emit_enum(~"Option") { - do encoder.emit_enum_variant (~"None",37,1242) { - } - } - assert_eq!(str::from_bytes(bw.bytes), ~"null"); + fn test_write_enum_no_args_pretty() { + let animal = Dog; + + let s = do io::with_str_writer |wr| { + let encoder = PrettyEncoder(wr); + animal.encode(&encoder); + }; + assert_eq!(s, ~"\"Dog\""); + } + + #[test] + fn test_write_enum_multiple_args() { + let animal = Frog(~"Henry", 349); + + let s = do io::with_str_writer |wr| { + let encoder = Encoder(wr); + animal.encode(&encoder); + }; + assert_eq!(s, ~"[\"Frog\",\"Henry\",349]"); + } + + #[test] + fn test_write_enum_multiple_args_pretty() { + let animal = Frog(~"Henry", 349); + + let s = do io::with_str_writer |wr| { + let encoder = PrettyEncoder(wr); + animal.encode(&encoder); + }; + assert_eq!( + s, + ~"\ + [\n \ + \"Frog\",\n \ + \"Henry\",\n \ + 349\n\ + ]" + ); + } + + #[test] + fn test_write_some() { + let value = Some(~"jodhpurs"); + let s = do io::with_str_writer |wr| { + let encoder = Encoder(wr); + value.encode(&encoder); + }; + assert_eq!(s, ~"\"jodhpurs\""); + } + + #[test] + fn test_write_some_pretty() { + let value = Some(~"jodhpurs"); + let s = do io::with_str_writer |wr| { + let encoder = PrettyEncoder(wr); + value.encode(&encoder); + }; + assert_eq!(s, ~"\"jodhpurs\""); + } + + #[test] + fn test_write_none() { + let value: Option<~str> = None; + let s = do io::with_str_writer |wr| { + let encoder = Encoder(wr); + value.encode(&encoder); + }; + assert_eq!(s, ~"null"); + } + + #[test] + fn test_write_none_pretty() { + let value: Option<~str> = None; + let s = do io::with_str_writer |wr| { + let encoder = Encoder(wr); + value.encode(&encoder); + }; + assert_eq!(s, ~"null"); } #[test] fn test_trailing_characters() { - fail_unless!(from_str(~"nulla") == + assert_eq!(from_str(~"nulla"), Err(Error {line: 1u, col: 5u, msg: @~"trailing characters"})); - fail_unless!(from_str(~"truea") == + assert_eq!(from_str(~"truea"), Err(Error {line: 1u, col: 5u, msg: @~"trailing characters"})); - fail_unless!(from_str(~"falsea") == + assert_eq!(from_str(~"falsea"), Err(Error {line: 1u, col: 6u, msg: @~"trailing characters"})); - fail_unless!(from_str(~"1a") == + assert_eq!(from_str(~"1a"), Err(Error {line: 1u, col: 2u, msg: @~"trailing characters"})); - fail_unless!(from_str(~"[]a") == + assert_eq!(from_str(~"[]a"), Err(Error {line: 1u, col: 3u, msg: @~"trailing characters"})); - fail_unless!(from_str(~"{}a") == + assert_eq!(from_str(~"{}a"), Err(Error {line: 1u, col: 3u, msg: @~"trailing characters"})); } #[test] fn test_read_identifiers() { - fail_unless!(from_str(~"n") == + assert_eq!(from_str(~"n"), Err(Error {line: 1u, col: 2u, msg: @~"invalid syntax"})); - fail_unless!(from_str(~"nul") == + assert_eq!(from_str(~"nul"), Err(Error {line: 1u, col: 4u, msg: @~"invalid syntax"})); - fail_unless!(from_str(~"t") == + assert_eq!(from_str(~"t"), Err(Error {line: 1u, col: 2u, msg: @~"invalid syntax"})); - fail_unless!(from_str(~"truz") == + assert_eq!(from_str(~"truz"), Err(Error {line: 1u, col: 4u, msg: @~"invalid syntax"})); - fail_unless!(from_str(~"f") == + assert_eq!(from_str(~"f"), Err(Error {line: 1u, col: 2u, msg: @~"invalid syntax"})); - fail_unless!(from_str(~"faz") == + assert_eq!(from_str(~"faz"), Err(Error {line: 1u, col: 3u, msg: @~"invalid syntax"})); - fail_unless!(from_str(~"null") == Ok(Null)); - fail_unless!(from_str(~"true") == Ok(Boolean(true))); - fail_unless!(from_str(~"false") == Ok(Boolean(false))); - fail_unless!(from_str(~" null ") == Ok(Null)); - fail_unless!(from_str(~" true ") == Ok(Boolean(true))); - fail_unless!(from_str(~" false ") == Ok(Boolean(false))); + assert_eq!(from_str(~"null"), Ok(Null)); + assert_eq!(from_str(~"true"), Ok(Boolean(true))); + assert_eq!(from_str(~"false"), Ok(Boolean(false))); + assert_eq!(from_str(~" null "), Ok(Null)); + assert_eq!(from_str(~" true "), Ok(Boolean(true))); + assert_eq!(from_str(~" false "), Ok(Boolean(false))); } #[test] fn test_read_number() { - fail_unless!(from_str(~"+") == + assert_eq!(from_str(~"+"), Err(Error {line: 1u, col: 1u, msg: @~"invalid syntax"})); - fail_unless!(from_str(~".") == + assert_eq!(from_str(~"."), Err(Error {line: 1u, col: 1u, msg: @~"invalid syntax"})); - fail_unless!(from_str(~"-") == + assert_eq!(from_str(~"-"), Err(Error {line: 1u, col: 2u, msg: @~"invalid number"})); - fail_unless!(from_str(~"00") == + assert_eq!(from_str(~"00"), Err(Error {line: 1u, col: 2u, msg: @~"invalid number"})); - fail_unless!(from_str(~"1.") == + assert_eq!(from_str(~"1."), Err(Error {line: 1u, col: 3u, msg: @~"invalid number"})); - fail_unless!(from_str(~"1e") == + assert_eq!(from_str(~"1e"), Err(Error {line: 1u, col: 3u, msg: @~"invalid number"})); - fail_unless!(from_str(~"1e+") == + assert_eq!(from_str(~"1e+"), Err(Error {line: 1u, col: 4u, msg: @~"invalid number"})); - fail_unless!(from_str(~"3") == Ok(Number(3f))); - fail_unless!(from_str(~"3.1") == Ok(Number(3.1f))); - fail_unless!(from_str(~"-1.2") == Ok(Number(-1.2f))); - fail_unless!(from_str(~"0.4") == Ok(Number(0.4f))); - fail_unless!(from_str(~"0.4e5") == Ok(Number(0.4e5f))); - fail_unless!(from_str(~"0.4e+15") == Ok(Number(0.4e15f))); - fail_unless!(from_str(~"0.4e-01") == Ok(Number(0.4e-01f))); - fail_unless!(from_str(~" 3 ") == Ok(Number(3f))); + assert_eq!(from_str(~"3"), Ok(Number(3f))); + assert_eq!(from_str(~"3.1"), Ok(Number(3.1f))); + assert_eq!(from_str(~"-1.2"), Ok(Number(-1.2f))); + assert_eq!(from_str(~"0.4"), Ok(Number(0.4f))); + assert_eq!(from_str(~"0.4e5"), Ok(Number(0.4e5f))); + assert_eq!(from_str(~"0.4e+15"), Ok(Number(0.4e15f))); + assert_eq!(from_str(~"0.4e-01"), Ok(Number(0.4e-01f))); + assert_eq!(from_str(~" 3 "), Ok(Number(3f))); } #[test] fn test_read_str() { - fail_unless!(from_str(~"\"") == + assert_eq!(from_str(~"\""), Err(Error {line: 1u, col: 2u, msg: @~"EOF while parsing string" })); - fail_unless!(from_str(~"\"lol") == + assert_eq!(from_str(~"\"lol"), Err(Error {line: 1u, col: 5u, msg: @~"EOF while parsing string" })); - fail_unless!(from_str(~"\"\"") == Ok(String(~""))); - fail_unless!(from_str(~"\"foo\"") == Ok(String(~"foo"))); - fail_unless!(from_str(~"\"\\\"\"") == Ok(String(~"\""))); - fail_unless!(from_str(~"\"\\b\"") == Ok(String(~"\x08"))); - fail_unless!(from_str(~"\"\\n\"") == Ok(String(~"\n"))); - fail_unless!(from_str(~"\"\\r\"") == Ok(String(~"\r"))); - fail_unless!(from_str(~"\"\\t\"") == Ok(String(~"\t"))); - fail_unless!(from_str(~" \"foo\" ") == Ok(String(~"foo"))); + assert_eq!(from_str(~"\"\""), Ok(String(~""))); + assert_eq!(from_str(~"\"foo\""), Ok(String(~"foo"))); + assert_eq!(from_str(~"\"\\\"\""), Ok(String(~"\""))); + assert_eq!(from_str(~"\"\\b\""), Ok(String(~"\x08"))); + assert_eq!(from_str(~"\"\\n\""), Ok(String(~"\n"))); + assert_eq!(from_str(~"\"\\r\""), Ok(String(~"\r"))); + assert_eq!(from_str(~"\"\\t\""), Ok(String(~"\t"))); + assert_eq!(from_str(~" \"foo\" "), Ok(String(~"foo"))); } #[test] fn test_unicode_hex_escapes_in_str() { - fail_unless!(from_str(~"\"\\u12ab\"") == Ok(String(~"\u12ab"))); - fail_unless!(from_str(~"\"\\uAB12\"") == Ok(String(~"\uAB12"))); + assert_eq!(from_str(~"\"\\u12ab\""), Ok(String(~"\u12ab"))); + assert_eq!(from_str(~"\"\\uAB12\""), Ok(String(~"\uAB12"))); } #[test] fn test_read_list() { - fail_unless!(from_str(~"[") == + assert_eq!(from_str(~"["), Err(Error {line: 1u, col: 2u, msg: @~"EOF while parsing value"})); - fail_unless!(from_str(~"[1") == + assert_eq!(from_str(~"[1"), Err(Error {line: 1u, col: 3u, msg: @~"EOF while parsing list"})); - fail_unless!(from_str(~"[1,") == + assert_eq!(from_str(~"[1,"), Err(Error {line: 1u, col: 4u, msg: @~"EOF while parsing value"})); - fail_unless!(from_str(~"[1,]") == + assert_eq!(from_str(~"[1,]"), Err(Error {line: 1u, col: 4u, msg: @~"invalid syntax"})); - fail_unless!(from_str(~"[6 7]") == + assert_eq!(from_str(~"[6 7]"), Err(Error {line: 1u, col: 4u, msg: @~"expected `,` or `]`"})); - fail_unless!(from_str(~"[]") == Ok(List(~[]))); - fail_unless!(from_str(~"[ ]") == Ok(List(~[]))); - fail_unless!(from_str(~"[true]") == Ok(List(~[Boolean(true)]))); - fail_unless!(from_str(~"[ false ]") == Ok(List(~[Boolean(false)]))); - fail_unless!(from_str(~"[null]") == Ok(List(~[Null]))); - fail_unless!(from_str(~"[3, 1]") == + assert_eq!(from_str(~"[]"), Ok(List(~[]))); + assert_eq!(from_str(~"[ ]"), Ok(List(~[]))); + assert_eq!(from_str(~"[true]"), Ok(List(~[Boolean(true)]))); + assert_eq!(from_str(~"[ false ]"), Ok(List(~[Boolean(false)]))); + assert_eq!(from_str(~"[null]"), Ok(List(~[Null]))); + assert_eq!(from_str(~"[3, 1]"), Ok(List(~[Number(3f), Number(1f)]))); - fail_unless!(from_str(~"\n[3, 2]\n") == + assert_eq!(from_str(~"\n[3, 2]\n"), Ok(List(~[Number(3f), Number(2f)]))); - fail_unless!(from_str(~"[2, [4, 1]]") == + assert_eq!(from_str(~"[2, [4, 1]]"), Ok(List(~[Number(2f), List(~[Number(4f), Number(1f)])]))); } #[test] fn test_read_object() { - fail_unless!(from_str(~"{") == + assert_eq!(from_str(~"{"), Err(Error { line: 1u, col: 2u, msg: @~"EOF while parsing object"})); - fail_unless!(from_str(~"{ ") == + assert_eq!(from_str(~"{ "), Err(Error { line: 1u, col: 3u, msg: @~"EOF while parsing object"})); - fail_unless!(from_str(~"{1") == + assert_eq!(from_str(~"{1"), Err(Error { line: 1u, col: 2u, msg: @~"key must be a string"})); - fail_unless!(from_str(~"{ \"a\"") == + assert_eq!(from_str(~"{ \"a\""), Err(Error { line: 1u, col: 6u, msg: @~"EOF while parsing object"})); - fail_unless!(from_str(~"{\"a\"") == + assert_eq!(from_str(~"{\"a\""), Err(Error { line: 1u, col: 5u, msg: @~"EOF while parsing object"})); - fail_unless!(from_str(~"{\"a\" ") == + assert_eq!(from_str(~"{\"a\" "), Err(Error { line: 1u, col: 6u, msg: @~"EOF while parsing object"})); - fail_unless!(from_str(~"{\"a\" 1") == + assert_eq!(from_str(~"{\"a\" 1"), Err(Error {line: 1u, col: 6u, msg: @~"expected `:`"})); - fail_unless!(from_str(~"{\"a\":") == + assert_eq!(from_str(~"{\"a\":"), Err(Error {line: 1u, col: 6u, msg: @~"EOF while parsing value"})); - fail_unless!(from_str(~"{\"a\":1") == + assert_eq!(from_str(~"{\"a\":1"), Err(Error { line: 1u, col: 7u, msg: @~"EOF while parsing object"})); - fail_unless!(from_str(~"{\"a\":1 1") == + assert_eq!(from_str(~"{\"a\":1 1"), Err(Error {line: 1u, col: 8u, msg: @~"expected `,` or `}`"})); - fail_unless!(from_str(~"{\"a\":1,") == + assert_eq!(from_str(~"{\"a\":1,"), Err(Error { line: 1u, col: 8u, msg: @~"EOF while parsing object"})); - fail_unless!(result::unwrap(from_str(~"{}")) == mk_object(~[])); - fail_unless!(result::unwrap(from_str(~"{\"a\": 3}")) == + assert_eq!(result::unwrap(from_str(~"{}")), mk_object(~[])); + assert_eq!(result::unwrap(from_str(~"{\"a\": 3}")), mk_object(~[(~"a", Number(3.0f))])); - fail_unless!(result::unwrap(from_str( - ~"{ \"a\": null, \"b\" : true }")) == + assert_eq!(result::unwrap(from_str( + ~"{ \"a\": null, \"b\" : true }")), mk_object(~[ (~"a", Null), (~"b", Boolean(true))])); - fail_unless!(result::unwrap( - from_str(~"\n{ \"a\": null, \"b\" : true }\n")) == + assert_eq!(result::unwrap( + from_str(~"\n{ \"a\": null, \"b\" : true }\n")), mk_object(~[ (~"a", Null), (~"b", Boolean(true))])); - fail_unless!(result::unwrap(from_str( - ~"{\"a\" : 1.0 ,\"b\": [ true ]}")) == + assert_eq!(result::unwrap(from_str( + ~"{\"a\" : 1.0 ,\"b\": [ true ]}")), mk_object(~[ (~"a", Number(1.0)), (~"b", List(~[Boolean(true)])) ])); - fail_unless!(result::unwrap(from_str( + assert_eq!(result::unwrap(from_str( ~"{" + ~"\"a\": 1.0, " + ~"\"b\": [" + @@ -1515,7 +1692,7 @@ fn test_read_object() { ~"\"foo\\nbar\", " + ~"{ \"c\": {\"d\": null} } " + ~"]" + - ~"}")) == + ~"}")), mk_object(~[ (~"a", Number(1.0f)), (~"b", List(~[ @@ -1528,9 +1705,37 @@ fn test_read_object() { ])); } + #[test] + fn test_read_none() { + let decoder = Decoder(from_str(~"null").unwrap()); + let value: Option<~str> = Decodable::decode(&decoder); + assert_eq!(value, None); + } + + #[test] + fn test_read_some() { + let decoder = Decoder(from_str(~"\"jodhpurs\"").unwrap()); + let value: Option<~str> = Decodable::decode(&decoder); + assert_eq!(value, Some(~"jodhpurs")); + } + + #[test] + fn test_read_enum_no_args() { + let decoder = Decoder(from_str(~"\"Dog\"").unwrap()); + let value: Animal = Decodable::decode(&decoder); + assert_eq!(value, Dog); + } + + #[test] + fn test_read_enum_multiple_args() { + let decoder = Decoder(from_str(~"[\"Frog\",\"Henry\",349]").unwrap()); + let value: Animal = Decodable::decode(&decoder); + assert_eq!(value, Frog(~"Henry", 349)); + } + #[test] fn test_multiline_errors() { - fail_unless!(from_str(~"{\n \"foo\":\n \"bar\"") == + assert_eq!(from_str(~"{\n \"foo\":\n \"bar\""), Err(Error { line: 3u, col: 8u, diff --git a/src/libstd/prettyprint.rs b/src/libstd/prettyprint.rs index f823d73cf0b..ed4f3e957c0 100644 --- a/src/libstd/prettyprint.rs +++ b/src/libstd/prettyprint.rs @@ -182,4 +182,18 @@ fn emit_tup_elt(&self, idx: uint, f: &fn()) { if idx > 0u { self.wr.write_str(~", "); } f(); } + + fn emit_option(&self, f: &fn()) { + f(); + } + + fn emit_option_none(&self) { + self.wr.write_str("None"); + } + + fn emit_option_some(&self, f: &fn()) { + self.wr.write_str("Some("); + f(); + self.wr.write_char(')'); + } } diff --git a/src/libstd/serialize.rs b/src/libstd/serialize.rs index 326b9e4dc07..02f4a934874 100644 --- a/src/libstd/serialize.rs +++ b/src/libstd/serialize.rs @@ -62,6 +62,11 @@ pub trait Encoder { fn emit_tup(&self, len: uint, f: &fn()); fn emit_tup_elt(&self, idx: uint, f: &fn()); + + // Specialized types: + fn emit_option(&self, f: &fn()); + fn emit_option_none(&self); + fn emit_option_some(&self, f: &fn()); } pub trait Decoder { @@ -87,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; @@ -103,6 +116,9 @@ pub trait Decoder { fn read_tup(&self, sz: uint, f: &fn() -> T) -> T; fn read_tup_elt(&self, idx: uint, f: &fn() -> T) -> T; + + // Specialized types: + fn read_option(&self, f: &fn() -> T) -> Option; } pub trait Encodable { @@ -368,14 +384,10 @@ fn decode(d: &D) -> @[T] { impl> Encodable for Option { fn encode(&self, s: &S) { - do s.emit_enum(~"option") { + do s.emit_option { match *self { - None => do s.emit_enum_variant(~"none", 0u, 0u) { - }, - - Some(ref v) => do s.emit_enum_variant(~"some", 1u, 1u) { - s.emit_enum_variant_arg(0u, || v.encode(s)) - } + None => s.emit_option_none(), + Some(ref v) => s.emit_option_some(|| v.encode(s)), } } } @@ -383,16 +395,7 @@ fn encode(&self, s: &S) { impl> Decodable for Option { fn decode(d: &D) -> Option { - do d.read_enum(~"option") { - do d.read_enum_variant |i| { - match i { - 0 => None, - 1 => Some(d.read_enum_variant_arg( - 0u, || Decodable::decode(d))), - _ => fail!(fmt!("Bad variant for option: %u", i)) - } - } - } + d.read_option(|| Decodable::decode(d)) } } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 12d4e9d5e24..6b788810a79 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -386,7 +386,6 @@ pub enum vstore { #[auto_decode] #[deriving(Eq)] pub enum expr_vstore { - expr_vstore_fixed(Option), // [1,2,3,4] expr_vstore_uniq, // ~[1,2,3,4] expr_vstore_box, // @[1,2,3,4] expr_vstore_mut_box, // @mut [1,2,3,4] @@ -543,12 +542,6 @@ pub struct expr { span: span, } -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] -pub enum log_level { error, debug, log_other } -// 0 = error, 1 = debug, 2 = log_other - #[auto_encode] #[auto_decode] #[deriving(Eq)] @@ -598,7 +591,7 @@ pub enum expr_ { expr_break(Option), expr_again(Option), expr_ret(Option<@expr>), - expr_log(log_level, @expr, @expr), + expr_log(@expr, @expr), expr_inline_asm(@~str, // asm ~[(@~str, @expr)], // inputs diff --git a/src/libsyntax/ext/auto_encode.rs b/src/libsyntax/ext/auto_encode.rs index e81e460e832..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,9 +1186,9 @@ fn mk_enum_deser_body( ) } - #[cfg(test)] mod test { + use core::option::{None, Some}; use std::serialize::Encodable; use std::serialize::Encoder; @@ -1190,6 +1202,9 @@ pub enum call { CallToEmitNil, CallToEmitStruct(~str,uint), CallToEmitField(~str,uint), + CallToEmitOption, + CallToEmitOptionNone, + CallToEmitOptionSome, // all of the ones I was too lazy to handle: CallToOther } @@ -1281,6 +1296,18 @@ fn emit_tup(&self, +_len: uint, f: &fn()) { fn emit_tup_elt(&self, +_idx: uint, f: &fn()) { self.add_unknown_to_log(); f(); } + + fn emit_option(&self, f: &fn()) { + self.add_to_log(CallToEmitOption); + f(); + } + fn emit_option_none(&self) { + self.add_to_log(CallToEmitOptionNone); + } + fn emit_option_some(&self, f: &fn()) { + self.add_to_log(CallToEmitOptionSome); + f(); + } } @@ -1296,13 +1323,58 @@ enum Written { Magazine(~str) } - #[test] fn encode_enum_test () { - assert_eq!(to_call_log(Book(34,44)), - ~[CallToEmitEnum (~"Written"), - CallToEmitEnumVariant (~"Book",0,2), - CallToEmitEnumVariantArg (0), - CallToEmitUint (34), - CallToEmitEnumVariantArg (1), - CallToEmitUint (44)]); - } + #[test] + fn test_encode_enum() { + assert_eq!( + to_call_log(Book(34,44)), + ~[ + CallToEmitEnum(~"Written"), + CallToEmitEnumVariant(~"Book",0,2), + CallToEmitEnumVariantArg(0), + CallToEmitUint(34), + CallToEmitEnumVariantArg(1), + CallToEmitUint(44), + ] + ); + } + + pub struct BPos(uint); + + #[auto_encode] + pub struct HasPos { pos : BPos } + + #[test] + fn test_encode_newtype() { + assert_eq!( + to_call_log(HasPos { pos:BPos(48) }), + ~[ + CallToEmitStruct(~"HasPos",1), + CallToEmitField(~"pos",0), + CallToEmitUint(48), + ] + ); + } + + #[test] + fn test_encode_option() { + let mut v = None; + + assert_eq!( + to_call_log(v), + ~[ + CallToEmitOption, + CallToEmitOptionNone, + ] + ); + + v = Some(54u); + assert_eq!( + to_call_log(v), + ~[ + CallToEmitOption, + CallToEmitOptionSome, + CallToEmitUint(54) + ] + ); + } } diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index ad71441e046..9499f95f0e7 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -152,11 +152,6 @@ pub fn mk_slice_vec_e(cx: @ext_ctxt, sp: span, +exprs: ~[@ast::expr]) mk_vstore_e(cx, sp, mk_base_vec_e(cx, sp, exprs), ast::expr_vstore_slice) } -pub fn mk_fixed_vec_e(cx: @ext_ctxt, sp: span, +exprs: ~[@ast::expr]) - -> @ast::expr { - mk_vstore_e(cx, sp, mk_base_vec_e(cx, sp, exprs), - ast::expr_vstore_fixed(None)) -} pub fn mk_base_str(cx: @ext_ctxt, sp: span, +s: ~str) -> @ast::expr { let lit = ast::lit_str(@s); return mk_lit(cx, sp, lit); diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs index 6044c3ad3d2..a6f078d07b4 100644 --- a/src/libsyntax/ext/quote.rs +++ b/src/libsyntax/ext/quote.rs @@ -42,8 +42,7 @@ pub mod rt { pub use ast::*; pub use parse::token::*; pub use parse::new_parser_from_tts; - pub use codemap::BytePos; - pub use codemap::span; + pub use codemap::{BytePos, span, dummy_spanned}; use print::pprust; use print::pprust::{item_to_str, ty_to_str}; @@ -89,7 +88,7 @@ fn to_source(&self, cx: @ext_ctxt) -> ~str { } } - impl ToSource for ~[@ast::item] { + impl<'self> ToSource for &'self [@ast::item] { fn to_source(&self, cx: @ext_ctxt) -> ~str { str::connect(self.map(|i| i.to_source(cx)), ~"\n\n") } @@ -101,7 +100,7 @@ fn to_source(&self, cx: @ext_ctxt) -> ~str { } } - impl ToSource for ~[@ast::Ty] { + impl<'self> ToSource for &'self [@ast::Ty] { fn to_source(&self, cx: @ext_ctxt) -> ~str { str::connect(self.map(|i| i.to_source(cx)), ~", ") } @@ -119,6 +118,90 @@ fn to_source(&self, cx: @ext_ctxt) -> ~str { } } + impl ToSource for ast::blk { + fn to_source(&self, cx: @ext_ctxt) -> ~str { + pprust::block_to_str(self, cx.parse_sess().interner) + } + } + + impl<'self> ToSource for &'self str { + fn to_source(&self, _cx: @ext_ctxt) -> ~str { + let lit = dummy_spanned(ast::lit_str(@str::from_slice(*self))); + pprust::lit_to_str(@lit) + } + } + + impl ToSource for int { + fn to_source(&self, _cx: @ext_ctxt) -> ~str { + let lit = dummy_spanned(ast::lit_int(*self as i64, ast::ty_i)); + pprust::lit_to_str(@lit) + } + } + + impl ToSource for i8 { + fn to_source(&self, _cx: @ext_ctxt) -> ~str { + let lit = dummy_spanned(ast::lit_int(*self as i64, ast::ty_i8)); + pprust::lit_to_str(@lit) + } + } + + impl ToSource for i16 { + fn to_source(&self, _cx: @ext_ctxt) -> ~str { + let lit = dummy_spanned(ast::lit_int(*self as i64, ast::ty_i16)); + pprust::lit_to_str(@lit) + } + } + + + impl ToSource for i32 { + fn to_source(&self, _cx: @ext_ctxt) -> ~str { + let lit = dummy_spanned(ast::lit_int(*self as i64, ast::ty_i32)); + pprust::lit_to_str(@lit) + } + } + + impl ToSource for i64 { + fn to_source(&self, _cx: @ext_ctxt) -> ~str { + let lit = dummy_spanned(ast::lit_int(*self as i64, ast::ty_i64)); + pprust::lit_to_str(@lit) + } + } + + impl ToSource for uint { + fn to_source(&self, _cx: @ext_ctxt) -> ~str { + let lit = dummy_spanned(ast::lit_uint(*self as u64, ast::ty_u)); + pprust::lit_to_str(@lit) + } + } + + impl ToSource for u8 { + fn to_source(&self, _cx: @ext_ctxt) -> ~str { + let lit = dummy_spanned(ast::lit_uint(*self as u64, ast::ty_u8)); + pprust::lit_to_str(@lit) + } + } + + impl ToSource for u16 { + fn to_source(&self, _cx: @ext_ctxt) -> ~str { + let lit = dummy_spanned(ast::lit_uint(*self as u64, ast::ty_u16)); + pprust::lit_to_str(@lit) + } + } + + impl ToSource for u32 { + fn to_source(&self, _cx: @ext_ctxt) -> ~str { + let lit = dummy_spanned(ast::lit_uint(*self as u64, ast::ty_u32)); + pprust::lit_to_str(@lit) + } + } + + impl ToSource for u64 { + fn to_source(&self, _cx: @ext_ctxt) -> ~str { + let lit = dummy_spanned(ast::lit_uint(*self as u64, ast::ty_u64)); + pprust::lit_to_str(@lit) + } + } + // Alas ... we write these out instead. All redundant. impl ToTokens for ast::ident { @@ -133,7 +216,7 @@ fn to_tokens(&self, cx: @ext_ctxt) -> ~[token_tree] { } } - impl ToTokens for ~[@ast::item] { + impl<'self> ToTokens for &'self [@ast::item] { fn to_tokens(&self, cx: @ext_ctxt) -> ~[token_tree] { cx.parse_tts(self.to_source(cx)) } @@ -145,7 +228,7 @@ fn to_tokens(&self, cx: @ext_ctxt) -> ~[token_tree] { } } - impl ToTokens for ~[@ast::Ty] { + impl<'self> ToTokens for &'self [@ast::Ty] { fn to_tokens(&self, cx: @ext_ctxt) -> ~[token_tree] { cx.parse_tts(self.to_source(cx)) } @@ -163,6 +246,78 @@ fn to_tokens(&self, cx: @ext_ctxt) -> ~[token_tree] { } } + impl ToTokens for ast::blk { + fn to_tokens(&self, cx: @ext_ctxt) -> ~[token_tree] { + cx.parse_tts(self.to_source(cx)) + } + } + + impl<'self> ToTokens for &'self str { + fn to_tokens(&self, cx: @ext_ctxt) -> ~[token_tree] { + cx.parse_tts(self.to_source(cx)) + } + } + + impl ToTokens for int { + fn to_tokens(&self, cx: @ext_ctxt) -> ~[token_tree] { + cx.parse_tts(self.to_source(cx)) + } + } + + impl ToTokens for i8 { + fn to_tokens(&self, cx: @ext_ctxt) -> ~[token_tree] { + cx.parse_tts(self.to_source(cx)) + } + } + + impl ToTokens for i16 { + fn to_tokens(&self, cx: @ext_ctxt) -> ~[token_tree] { + cx.parse_tts(self.to_source(cx)) + } + } + + impl ToTokens for i32 { + fn to_tokens(&self, cx: @ext_ctxt) -> ~[token_tree] { + cx.parse_tts(self.to_source(cx)) + } + } + + impl ToTokens for i64 { + fn to_tokens(&self, cx: @ext_ctxt) -> ~[token_tree] { + cx.parse_tts(self.to_source(cx)) + } + } + + impl ToTokens for uint { + fn to_tokens(&self, cx: @ext_ctxt) -> ~[token_tree] { + cx.parse_tts(self.to_source(cx)) + } + } + + impl ToTokens for u8 { + fn to_tokens(&self, cx: @ext_ctxt) -> ~[token_tree] { + cx.parse_tts(self.to_source(cx)) + } + } + + impl ToTokens for u16 { + fn to_tokens(&self, cx: @ext_ctxt) -> ~[token_tree] { + cx.parse_tts(self.to_source(cx)) + } + } + + impl ToTokens for u32 { + fn to_tokens(&self, cx: @ext_ctxt) -> ~[token_tree] { + cx.parse_tts(self.to_source(cx)) + } + } + + impl ToTokens for u64 { + fn to_tokens(&self, cx: @ext_ctxt) -> ~[token_tree] { + cx.parse_tts(self.to_source(cx)) + } + } + pub trait ExtParseUtils { fn parse_item(&self, s: ~str) -> @ast::item; fn parse_expr(&self, s: ~str) -> @ast::expr; diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 9d4cf4e8939..279d57a291e 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -552,9 +552,8 @@ fn fold_field_(field: field, fld: @ast_fold) -> field { expr_ret(ref e) => { expr_ret(e.map(|x| fld.fold_expr(*x))) } - expr_log(i, lv, e) => { + expr_log(lv, e) => { expr_log( - i, fld.fold_expr(lv), fld.fold_expr(e) ) diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index a0c73668a05..0ddf9111e02 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -326,19 +326,32 @@ mod test { @~"fn foo (x : int) { x; }", ~[], new_parse_sess(None)); - assert_eq!(to_json_str(@tts), - ~"[[\"tt_tok\",[null,[\"IDENT\",[\"fn\",false]]]],\ - [\"tt_tok\",[null,[\"IDENT\",[\"foo\",false]]]],\ - [\"tt_delim\",[[[\"tt_tok\",[null,[\"LPAREN\",[]]]],\ - [\"tt_tok\",[null,[\"IDENT\",[\"x\",false]]]],\ - [\"tt_tok\",[null,[\"COLON\",[]]]],\ - [\"tt_tok\",[null,[\"IDENT\",[\"int\",false]]]],\ - [\"tt_tok\",[null,[\"RPAREN\",[]]]]]]],\ - [\"tt_delim\",[[[\"tt_tok\",[null,[\"LBRACE\",[]]]],\ - [\"tt_tok\",[null,[\"IDENT\",[\"x\",false]]]],\ - [\"tt_tok\",[null,[\"SEMI\",[]]]],\ - [\"tt_tok\",[null,[\"RBRACE\",[]]]]]]]]" - ); + assert_eq!( + to_json_str(@tts), + ~"[\ + [\"tt_tok\",null,[\"IDENT\",\"fn\",false]],\ + [\"tt_tok\",null,[\"IDENT\",\"foo\",false]],\ + [\ + \"tt_delim\",\ + [\ + [\"tt_tok\",null,\"LPAREN\"],\ + [\"tt_tok\",null,[\"IDENT\",\"x\",false]],\ + [\"tt_tok\",null,\"COLON\"],\ + [\"tt_tok\",null,[\"IDENT\",\"int\",false]],\ + [\"tt_tok\",null,\"RPAREN\"]\ + ]\ + ],\ + [\ + \"tt_delim\",\ + [\ + [\"tt_tok\",null,\"LBRACE\"],\ + [\"tt_tok\",null,[\"IDENT\",\"x\",false]],\ + [\"tt_tok\",null,\"SEMI\"],\ + [\"tt_tok\",null,\"RBRACE\"]\ + ]\ + ]\ + ]" + ); let ast1 = new_parser_from_tts(new_parse_sess(None),~[],tts) .parse_item(~[]); let ast2 = parse_item_from_source_str( diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index c2e7ecacd20..6ca91791ffd 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -28,7 +28,7 @@ use ast::{expr_method_call, expr_paren, expr_path, expr_repeat}; use ast::{expr_ret, expr_swap, expr_struct, expr_tup, expr_unary}; use ast::{expr_vec, expr_vstore, expr_vstore_mut_box, expr_inline_asm}; -use ast::{expr_vstore_fixed, expr_vstore_slice, expr_vstore_box}; +use ast::{expr_vstore_slice, expr_vstore_box}; use ast::{expr_vstore_mut_slice, expr_while, extern_fn, field, fn_decl}; use ast::{expr_vstore_uniq, TyClosure, TyBareFn, Onceness, Once, Many}; use ast::{foreign_item, foreign_item_const, foreign_item_fn, foreign_mod}; @@ -1223,7 +1223,7 @@ fn parse_bottom_expr(&self) -> @expr { let lvl = self.parse_expr(); self.expect(&token::COMMA); let e = self.parse_expr(); - ex = expr_log(ast::log_other, lvl, e); + ex = expr_log(lvl, e); hi = self.span.hi; self.expect(&token::RPAREN); } else if self.eat_keyword(&~"return") { @@ -2721,8 +2721,9 @@ fn parse_optional_ty_param_bounds(&self) -> @OptVec { } self.bump(); } - token::IDENT(*) => { + token::MOD_SEP | token::IDENT(*) => { let maybe_bound = match *self.token { + token::MOD_SEP => None, token::IDENT(copy sid, _) => { match *self.id_to_str(sid) { ~"send" | @@ -2750,7 +2751,7 @@ fn parse_optional_ty_param_bounds(&self) -> @OptVec { result.push(bound); } None => { - let ty = self.parse_ty(false); + let ty = self.parse_ty(true); result.push(TraitTyParamBound(ty)); } } @@ -3099,14 +3100,6 @@ fn parse_item_trait(&self) -> item_info { // impl Foo { ... } // impl ToStr for ~[T] { ... } fn parse_item_impl(&self, visibility: ast::visibility) -> item_info { - fn wrap_path(p: &Parser, pt: @path) -> @Ty { - @Ty { - id: p.get_id(), - node: ty_path(pt, p.get_id()), - span: pt.span, - } - } - // First, parse type parameters if necessary. let generics = self.parse_generics(); diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 9fffed7074b..cb142ef3f54 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -325,7 +325,7 @@ pub fn commasep(s: @ps, b: breaks, elts: &[IN], op: &fn(@ps, IN)) { pub fn commasep_cmnt(s: @ps, b: breaks, elts: &[IN], op: &fn(@ps, IN), get_span: &fn(IN) -> codemap::span) { box(s, 0u, b); - let len = vec::len::(elts); + let len = elts.len(); let mut i = 0u; for elts.each |elt| { maybe_print_comment(s, get_span(*elt).hi); @@ -1029,8 +1029,6 @@ pub fn print_vstore(s: @ps, t: ast::vstore) { pub fn print_expr_vstore(s: @ps, t: ast::expr_vstore) { match t { - ast::expr_vstore_fixed(Some(i)) => word(s.s, fmt!("%u", i)), - ast::expr_vstore_fixed(None) => word(s.s, ~"_"), ast::expr_vstore_uniq => word(s.s, ~"~"), ast::expr_vstore_box => word(s.s, ~"@"), ast::expr_vstore_mut_box => { @@ -1105,16 +1103,9 @@ fn print_field(s: @ps, field: ast::field) { let ann_node = node_expr(s, expr); (s.ann.pre)(ann_node); match expr.node { - ast::expr_vstore(e, v) => match v { - ast::expr_vstore_fixed(_) => { - print_expr(s, e); - word(s.s, ~"/"); - print_expr_vstore(s, v); - } - _ => { - print_expr_vstore(s, v); - print_expr(s, e); - } + ast::expr_vstore(e, v) => { + print_expr_vstore(s, v); + print_expr(s, e); }, ast::expr_vec(ref exprs, mutbl) => { ibox(s, indent_unit); @@ -1391,20 +1382,14 @@ fn print_field(s: @ps, field: ast::field) { _ => () } } - ast::expr_log(lvl, lexp, expr) => { - match lvl { - ast::debug => { word_nbsp(s, ~"log"); print_expr(s, expr); } - ast::error => { word_nbsp(s, ~"log_err"); print_expr(s, expr); } - ast::log_other => { - word_nbsp(s, ~"log"); - popen(s); - print_expr(s, lexp); - word(s.s, ~","); - space_if_not_bol(s); - print_expr(s, expr); - pclose(s); - } - } + ast::expr_log(lexp, expr) => { + word(s.s, ~"__log"); + popen(s); + print_expr(s, lexp); + word(s.s, ~","); + space_if_not_bol(s); + print_expr(s, expr); + pclose(s); } ast::expr_inline_asm(a, in, out, c, v, _) => { if v { @@ -2139,7 +2124,7 @@ pub fn print_comment(s: @ps, cmnt: comments::cmnt) { } } -pub fn print_string(s: @ps, st: ~str) { +pub fn print_string(s: @ps, st: &str) { word(s.s, ~"\""); word(s.s, str::escape_default(st)); word(s.s, ~"\""); diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index a159c98d21b..2bdf26fba58 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -559,7 +559,7 @@ pub fn visit_expr(ex: @expr, e: E, v: vt) { expr_break(_) => (), expr_again(_) => (), expr_ret(eo) => visit_expr_opt(eo, e, v), - expr_log(_, lv, x) => { + expr_log(lv, x) => { (v.visit_expr)(lv, e, v); (v.visit_expr)(x, e, v); } diff --git a/src/test/run-pass/issue-5572.rs b/src/test/run-pass/issue-5572.rs new file mode 100644 index 00000000000..d0db5e5cb3c --- /dev/null +++ b/src/test/run-pass/issue-5572.rs @@ -0,0 +1,3 @@ +fn foo(t: T) { } + +fn main() { }