1
Fork 0

auto merge of #5578 : erickt/rust/incoming, r=jbclements,erickt

Hey folks,

This patch series does some work on the json decoder, specifically with auto decoding of enums. Previously, we would take this code:

```
enum A {
    B,
    C(~str, uint)
}
```

and would encode a value of this enum to either `["B", []]` or `["C", ["D", 123]]`. I've changed this to `"B"` or `["C", "D", 123]`. This matches the style of the O'Caml json library [json-wheel](http://mjambon.com/json-wheel.html). I've added tests to make sure all this work.

In order to make this change, I added passing a `&[&str]` vec to `Decode::emit_enum_variant` so the json decoder can convert the name of a variant into it's position. I also changed the impl of `Encodable` for `Option<T>` to have the right upper casing.

I also did some work on the parser, which allows for `fn foo<T: ::cmp::Eq>() { ... }` statements (#5572), fixed the pretty printer properly expanding `debug!("...")` expressions, and removed `ast::expr_vstore_fixed`, which doesn't appear to be used anymore.
This commit is contained in:
bors 2013-03-27 21:51:53 -07:00
commit 84ddff3909
24 changed files with 820 additions and 316 deletions

View file

@ -681,6 +681,7 @@ impl vtable_decoder_helpers for reader::Decoder {
@self.read_to_vec(|| self.read_vtable_origin(xcx) ) @self.read_to_vec(|| self.read_vtable_origin(xcx) )
} }
#[cfg(stage0)]
fn read_vtable_origin(&self, xcx: @ExtendedDecodeContext) fn read_vtable_origin(&self, xcx: @ExtendedDecodeContext)
-> typeck::vtable_origin { -> typeck::vtable_origin {
do self.read_enum(~"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")
}
}
}
}
} }
// ______________________________________________________________________ // ______________________________________________________________________

View file

@ -156,7 +156,6 @@ pub fn check_expr(sess: Session,
expr_paren(e) => { check_expr(sess, def_map, method_map, expr_paren(e) => { check_expr(sess, def_map, method_map,
tcx, e, is_const, v); } tcx, e, is_const, v); }
expr_vstore(_, expr_vstore_slice) | expr_vstore(_, expr_vstore_slice) |
expr_vstore(_, expr_vstore_fixed(_)) |
expr_vec(_, m_imm) | expr_vec(_, m_imm) |
expr_addr_of(m_imm, _) | expr_addr_of(m_imm, _) |
expr_field(*) | expr_field(*) |

View file

@ -110,7 +110,6 @@ pub fn classify(e: @expr,
ast::expr_vstore(e, vstore) => { ast::expr_vstore(e, vstore) => {
match vstore { match vstore {
ast::expr_vstore_fixed(_) |
ast::expr_vstore_slice => classify(e, tcx), ast::expr_vstore_slice => classify(e, tcx),
ast::expr_vstore_uniq | ast::expr_vstore_uniq |
ast::expr_vstore_box | ast::expr_vstore_box |

View file

@ -1290,7 +1290,7 @@ pub impl Liveness {
self.propagate_through_expr(l, ln) self.propagate_through_expr(l, ln)
} }
expr_log(_, l, r) | expr_log(l, r) |
expr_index(l, r) | expr_index(l, r) |
expr_binary(_, l, r) => { expr_binary(_, l, r) => {
self.propagate_through_exprs(~[l, r], succ) self.propagate_through_exprs(~[l, r], succ)

View file

@ -567,7 +567,7 @@ pub impl VisitContext {
self.consume_block(blk, visitor); self.consume_block(blk, visitor);
} }
expr_log(_, a_expr, b_expr) => { expr_log(a_expr, b_expr) => {
self.consume_expr(a_expr, visitor); self.consume_expr(a_expr, visitor);
self.use_expr(b_expr, Read, visitor); self.use_expr(b_expr, Read, visitor);
} }

View file

@ -466,9 +466,6 @@ fn const_expr_unadjusted(cx: @CrateContext, e: @ast::expr) -> ValueRef {
let (v, _, _) = const_vec(cx, e, *es); let (v, _, _) = const_vec(cx, e, *es);
v v
} }
ast::expr_vstore(e, ast::expr_vstore_fixed(_)) => {
const_expr(cx, e)
}
ast::expr_vstore(sub, ast::expr_vstore_slice) => { ast::expr_vstore(sub, ast::expr_vstore_slice) => {
match sub.node { match sub.node {
ast::expr_lit(ref lit) => { ast::expr_lit(ref lit) => {

View file

@ -496,7 +496,7 @@ fn trans_rvalue_stmt_unadjusted(bcx: block, expr: @ast::expr) -> block {
ast::expr_ret(ex) => { ast::expr_ret(ex) => {
return controlflow::trans_ret(bcx, 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); return controlflow::trans_log(expr, lvl, bcx, a);
} }
ast::expr_while(cond, ref body) => { 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) => { ast::expr_vstore(contents, ast::expr_vstore_mut_slice) => {
return tvec::trans_slice_vstore(bcx, expr, contents, dest); 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(*) => { ast::expr_vec(*) | ast::expr_repeat(*) => {
return tvec::trans_fixed_vstore(bcx, expr, expr, dest); return tvec::trans_fixed_vstore(bcx, expr, expr, dest);
} }

View file

@ -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)); type_needs(cx, use_repr, ty::type_autoderef(cx.ccx.tcx, base_ty));
mark_for_method_call(cx, e.id, e.callee_id); mark_for_method_call(cx, e.id, e.callee_id);
} }
expr_log(_, _, val) => { expr_log(_, val) => {
node_type_needs(cx, use_tydesc, val.id); node_type_needs(cx, use_tydesc, val.id);
} }
expr_call(f, _, _) => { expr_call(f, _, _) => {

View file

@ -3114,7 +3114,6 @@ pub fn expr_kind(tcx: ctxt,
ast::expr_lit(@codemap::spanned {node: lit_str(_), _}) | ast::expr_lit(@codemap::spanned {node: lit_str(_), _}) |
ast::expr_vstore(_, ast::expr_vstore_slice) | ast::expr_vstore(_, ast::expr_vstore_slice) |
ast::expr_vstore(_, ast::expr_vstore_mut_slice) | ast::expr_vstore(_, ast::expr_vstore_mut_slice) |
ast::expr_vstore(_, ast::expr_vstore_fixed(_)) |
ast::expr_vec(*) => { ast::expr_vec(*) => {
RvalueDpsExpr RvalueDpsExpr
} }

View file

@ -2366,7 +2366,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
} }
fcx.write_bot(id); fcx.write_bot(id);
} }
ast::expr_log(_, lv, e) => { ast::expr_log(lv, e) => {
check_expr_has_type(fcx, lv, check_expr_has_type(fcx, lv,
ty::mk_mach_uint(tcx, ast::ty_u32)); 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) v: ast::expr_vstore)
-> ty::vstore { -> ty::vstore {
match v { 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_uniq => ty::vstore_uniq,
ast::expr_vstore_box | ast::expr_vstore_mut_box => ty::vstore_box, ast::expr_vstore_box | ast::expr_vstore_mut_box => ty::vstore_box,
ast::expr_vstore_slice | ast::expr_vstore_mut_slice => { ast::expr_vstore_slice | ast::expr_vstore_mut_slice => {

View file

@ -335,6 +335,7 @@ pub mod reader {
self.push_doc(self.next_doc(EsEnum), f) self.push_doc(self.next_doc(EsEnum), f)
} }
#[cfg(stage0)]
fn read_enum_variant<T>(&self, f: &fn(uint) -> T) -> T { fn read_enum_variant<T>(&self, f: &fn(uint) -> T) -> T {
debug!("read_enum_variant()"); debug!("read_enum_variant()");
let idx = self._next_uint(EsEnumVid); let idx = self._next_uint(EsEnumVid);
@ -344,6 +345,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 { fn read_enum_variant_arg<T>(&self, idx: uint, f: &fn() -> T) -> T {
debug!("read_enum_variant_arg(idx=%u)", idx); debug!("read_enum_variant_arg(idx=%u)", idx);
f() f()
@ -397,8 +410,37 @@ pub mod reader {
debug!("read_tup_elt(idx=%u)", idx); debug!("read_tup_elt(idx=%u)", idx);
f() f()
} }
#[cfg(stage0)]
fn read_option<T>(&self, f: &fn() -> T) -> Option<T> {
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<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!(),
}
}
}
}
}
} }
pub mod writer { pub mod writer {
@ -664,9 +706,19 @@ pub mod writer {
fn emit_tup(&self, _len: uint, f: &fn()) { f() } fn emit_tup(&self, _len: uint, f: &fn()) { f() }
fn emit_tup_elt(&self, _idx: 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 // Testing

View file

@ -119,39 +119,19 @@ impl serialize::Encoder for Encoder {
f() f()
} }
fn emit_enum_variant(&self, name: &str, _id: uint, _cnt: uint, f: &fn()) { fn emit_enum_variant(&self, name: &str, _id: uint, cnt: uint, f: &fn()) {
// encoding of enums is special-cased for Option. Specifically: // enums are encoded as strings or vectors:
// Some(34) => 34 // Bunny => "Bunny"
// None => null
// other enums are encoded as vectors:
// Kangaroo(34,"William") => ["Kangaroo",[34,"William"]] // Kangaroo(34,"William") => ["Kangaroo",[34,"William"]]
// the default expansion for enums is more verbose than I'd like; if cnt == 0 {
// specifically, the inner pair of brackets seems superfluous, self.wr.write_str(escape_str(name));
// 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");
} else { } else {
self.wr.write_char('['); self.wr.write_char('[');
self.wr.write_str(escape_str(name)); self.wr.write_str(escape_str(name));
self.wr.write_char(','); self.wr.write_char(',');
self.wr.write_char('[');
f(); f();
self.wr.write_char(']'); self.wr.write_char(']');
self.wr.write_char(']');
} }
} }
@ -200,6 +180,10 @@ impl serialize::Encoder for Encoder {
fn emit_tup_elt(&self, idx: uint, f: &fn()) { fn emit_tup_elt(&self, idx: uint, f: &fn()) {
self.emit_vec_elt(idx, f) 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 { pub struct PrettyEncoder {
@ -250,28 +234,45 @@ impl serialize::Encoder for PrettyEncoder {
fn emit_owned(&self, f: &fn()) { f() } fn emit_owned(&self, f: &fn()) { f() }
fn emit_managed(&self, f: &fn()) { f() } fn emit_managed(&self, f: &fn()) { f() }
fn emit_enum(&self, name: &str, f: &fn()) { fn emit_enum(&self, _name: &str, f: &fn()) { f() }
if name != "option" { fail!(~"only supports option enum") } fn emit_enum_variant(&self, name: &str, _id: uint, cnt: uint, f: &fn()) {
f() if cnt == 0 {
} self.wr.write_str(escape_str(name));
fn emit_enum_variant(&self, _name: &str, id: uint, _cnt: uint, f: &fn()) {
if id == 0 {
self.emit_nil();
} else { } 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() f()
} }
fn emit_borrowed_vec(&self, _len: uint, f: &fn()) { fn emit_borrowed_vec(&self, len: uint, f: &fn()) {
if len == 0 {
self.wr.write_str("[]");
} else {
self.wr.write_char('['); self.wr.write_char('[');
self.indent += 2; self.indent += 2;
f(); f();
self.wr.write_char('\n');
self.indent -= 2; self.indent -= 2;
self.wr.write_str(spaces(self.indent));
self.wr.write_char(']'); self.wr.write_char(']');
} }
}
fn emit_owned_vec(&self, len: uint, f: &fn()) { fn emit_owned_vec(&self, len: uint, f: &fn()) {
self.emit_borrowed_vec(len, f) self.emit_borrowed_vec(len, f)
} }
@ -292,12 +293,18 @@ impl serialize::Encoder for PrettyEncoder {
self.wr.write_char('{'); self.wr.write_char('{');
self.indent += 2; self.indent += 2;
f(); f();
self.wr.write_char('\n');
self.indent -= 2; self.indent -= 2;
self.wr.write_str(spaces(self.indent));
self.wr.write_char('}'); self.wr.write_char('}');
} }
fn emit_struct(&self, _name: &str, _len: uint, f: &fn()) { fn emit_struct(&self, _name: &str, len: uint, f: &fn()) {
if len == 0 {
self.wr.write_str("{}");
} else {
self.emit_rec(f) self.emit_rec(f)
} }
}
fn emit_field(&self, name: &str, idx: uint, f: &fn()) { fn emit_field(&self, name: &str, idx: uint, f: &fn()) {
if idx == 0 { if idx == 0 {
self.wr.write_char('\n'); self.wr.write_char('\n');
@ -315,6 +322,10 @@ impl serialize::Encoder for PrettyEncoder {
fn emit_tup_elt(&self, idx: uint, f: &fn()) { fn emit_tup_elt(&self, idx: uint, f: &fn()) {
self.emit_vec_elt(idx, f) 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<S:serialize::Encoder> serialize::Encodable<S> for Json { impl<S:serialize::Encoder> serialize::Encodable<S> for Json {
@ -816,7 +827,7 @@ impl<'self> serialize::Decoder for Decoder<'self> {
debug!("read_owned_str"); debug!("read_owned_str");
match *self.pop() { match *self.pop() {
String(ref s) => copy *s, String(ref s) => copy *s,
_ => fail!(~"not a string") ref json => fail!(fmt!("not a string: %?", *json))
} }
} }
@ -824,7 +835,7 @@ impl<'self> serialize::Decoder for Decoder<'self> {
debug!("read_managed_str"); debug!("read_managed_str");
match *self.pop() { match *self.pop() {
String(ref s) => s.to_managed(), String(ref s) => s.to_managed(),
_ => fail!(~"not a string") ref json => fail!(fmt!("not a string: %?", *json))
} }
} }
@ -840,10 +851,10 @@ impl<'self> serialize::Decoder for Decoder<'self> {
fn read_enum<T>(&self, name: &str, f: &fn() -> T) -> T { fn read_enum<T>(&self, name: &str, f: &fn() -> T) -> T {
debug!("read_enum(%s)", name); debug!("read_enum(%s)", name);
if name != ~"option" { fail!(~"only supports the option enum") }
f() f()
} }
#[cfg(stage0)]
fn read_enum_variant<T>(&self, f: &fn(uint) -> T) -> T { fn read_enum_variant<T>(&self, f: &fn(uint) -> T) -> T {
debug!("read_enum_variant()"); debug!("read_enum_variant()");
let idx = match *self.peek() { let idx = match *self.peek() {
@ -853,11 +864,33 @@ impl<'self> serialize::Decoder for Decoder<'self> {
f(idx) 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,
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<T>(&self, idx: uint, f: &fn() -> T) -> T { fn read_enum_variant_arg<T>(&self, idx: uint, f: &fn() -> T) -> T {
debug!("read_enum_variant_arg(idx=%u)", idx); debug!("read_enum_variant_arg(idx=%u)", idx);
if idx != 0 { fail!(~"unknown index") } match *self.peek() {
List(ref list) => {
self.stack.push(&list[idx + 1]);
f() f()
} }
ref json => fail!(fmt!("not a list: %?", json)),
}
}
fn read_owned_vec<T>(&self, f: &fn(uint) -> T) -> T { fn read_owned_vec<T>(&self, f: &fn(uint) -> T) -> T {
debug!("read_owned_vec()"); debug!("read_owned_vec()");
@ -946,6 +979,13 @@ impl<'self> serialize::Decoder for Decoder<'self> {
_ => fail!(~"not a list") _ => fail!(~"not a list")
} }
} }
fn read_option<T>(&self, f: &fn() -> T) -> Option<T> {
match *self.peek() {
Null => { self.pop(); None }
_ => Some(f()),
}
}
} }
impl Eq for Json { impl Eq for Json {
@ -1195,14 +1235,12 @@ impl to_str::ToStr for Error {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*;
use core::prelude::*; use core::prelude::*;
use json::*;
use serialize;
use core::result;
use core::hashmap::linear::LinearMap; use core::hashmap::linear::LinearMap;
use std::serialize::Decodable;
fn mk_object(items: &[(~str, Json)]) -> Json { fn mk_object(items: &[(~str, Json)]) -> Json {
let mut d = ~LinearMap::new(); let mut d = ~LinearMap::new();
@ -1218,45 +1256,89 @@ mod tests {
#[test] #[test]
fn test_write_null() { fn test_write_null() {
fail_unless!(to_str(&Null) == ~"null"); assert_eq!(to_str(&Null), ~"null");
} }
#[test] #[test]
fn test_write_number() { fn test_write_number() {
fail_unless!(to_str(&Number(3f)) == ~"3"); assert_eq!(to_str(&Number(3f)), ~"3");
fail_unless!(to_str(&Number(3.1f)) == ~"3.1"); assert_eq!(to_str(&Number(3.1f)), ~"3.1");
fail_unless!(to_str(&Number(-1.5f)) == ~"-1.5"); assert_eq!(to_str(&Number(-1.5f)), ~"-1.5");
fail_unless!(to_str(&Number(0.5f)) == ~"0.5"); assert_eq!(to_str(&Number(0.5f)), ~"0.5");
} }
#[test] #[test]
fn test_write_str() { fn test_write_str() {
fail_unless!(to_str(&String(~"")) == ~"\"\""); assert_eq!(to_str(&String(~"")), ~"\"\"");
fail_unless!(to_str(&String(~"foo")) == ~"\"foo\""); assert_eq!(to_str(&String(~"foo")), ~"\"foo\"");
} }
#[test] #[test]
fn test_write_bool() { fn test_write_bool() {
fail_unless!(to_str(&Boolean(true)) == ~"true"); assert_eq!(to_str(&Boolean(true)), ~"true");
fail_unless!(to_str(&Boolean(false)) == ~"false"); assert_eq!(to_str(&Boolean(false)), ~"false");
} }
#[test] #[test]
fn test_write_list() { fn test_write_list() {
fail_unless!(to_str(&List(~[])) == ~"[]"); assert_eq!(to_str(&List(~[])), ~"[]");
fail_unless!(to_str(&List(~[Boolean(true)])) == ~"[true]"); assert_eq!(to_str(&List(~[Boolean(true)])), ~"[true]");
fail_unless!(to_str(&List(~[ assert_eq!(to_str(&List(~[
Boolean(false), Boolean(false),
Null, Null,
List(~[String(~"foo\nbar"), Number(3.5f)]) 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] #[test]
fn test_write_object() { fn test_write_object() {
fail_unless!(to_str(&mk_object(~[])) == ~"{}"); assert_eq!(to_str(&mk_object(~[])), ~"{}");
fail_unless!(to_str(&mk_object(~[(~"a", Boolean(true))])) assert_eq!(
== ~"{\"a\":true}"); 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(~[ let a = mk_object(~[
(~"a", Boolean(true)), (~"a", Boolean(true)),
(~"b", List(~[ (~"b", List(~[
@ -1266,248 +1348,343 @@ mod tests {
]); ]);
// We can't compare the strings directly because the object fields be // We can't compare the strings directly because the object fields be
// printed in a different order. // printed in a different order.
let b = result::unwrap(from_str(to_str(&a))); let b = from_str(to_str(&a)).unwrap();
fail_unless!(a == b); assert_eq!(a, b);
} }
#[test] #[test]
fn test_write_enum () { fn test_write_object_pretty() {
let bw = @io::BytesWriter(); assert_eq!(to_pretty_str(&mk_object(~[])), ~"{\n}");
let bww : @io::Writer = (bw as @io::Writer); assert_eq!(
let encoder = (@Encoder(bww) as @serialize::Encoder); to_pretty_str(&mk_object(~[(~"a", Boolean(true))])),
do encoder.emit_enum(~"animal") { ~"\
do encoder.emit_enum_variant (~"frog",37,1242) { {\n \
// name of frog: \"a\": true\n\
do encoder.emit_enum_variant_arg (0) { }"
encoder.emit_owned_str(~"Henry") );
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);
} }
// mass of frog in grams:
do encoder.emit_enum_variant_arg (1) { #[auto_encode]
encoder.emit_int(349); #[auto_decode]
#[deriving(Eq)]
enum Animal {
Dog,
Frog(~str, int)
} }
#[test]
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_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\"");
} }
assert_eq!(str::from_bytes(bw.bytes), ~"[\"frog\",[\"Henry\",349]]");
#[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] #[test]
fn test_write_some() { fn test_write_some() {
let bw = @io::BytesWriter(); let value = Some(~"jodhpurs");
let bww : @io::Writer = (bw as @io::Writer); let s = do io::with_str_writer |wr| {
let encoder = (@Encoder(bww) as @serialize::Encoder); let encoder = Encoder(wr);
do encoder.emit_enum(~"Option") { value.encode(&encoder);
do encoder.emit_enum_variant (~"Some",37,1242) { };
do encoder.emit_enum_variant_arg (0) { assert_eq!(s, ~"\"jodhpurs\"");
encoder.emit_owned_str(~"jodhpurs")
} }
}
} #[test]
assert_eq!(str::from_bytes(bw.bytes), ~"\"jodhpurs\""); 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] #[test]
fn test_write_none() { fn test_write_none() {
let bw = @io::BytesWriter(); let value: Option<~str> = None;
let bww : @io::Writer = (bw as @io::Writer); let s = do io::with_str_writer |wr| {
let encoder = (@Encoder(bww) as @serialize::Encoder); let encoder = Encoder(wr);
do encoder.emit_enum(~"Option") { value.encode(&encoder);
do encoder.emit_enum_variant (~"None",37,1242) { };
assert_eq!(s, ~"null");
} }
}
assert_eq!(str::from_bytes(bw.bytes), ~"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] #[test]
fn test_trailing_characters() { fn test_trailing_characters() {
fail_unless!(from_str(~"nulla") == assert_eq!(from_str(~"nulla"),
Err(Error {line: 1u, col: 5u, msg: @~"trailing characters"})); 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"})); 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"})); 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"})); 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"})); 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"})); Err(Error {line: 1u, col: 3u, msg: @~"trailing characters"}));
} }
#[test] #[test]
fn test_read_identifiers() { fn test_read_identifiers() {
fail_unless!(from_str(~"n") == assert_eq!(from_str(~"n"),
Err(Error {line: 1u, col: 2u, msg: @~"invalid syntax"})); 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"})); 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"})); 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"})); 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"})); 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"})); Err(Error {line: 1u, col: 3u, msg: @~"invalid syntax"}));
fail_unless!(from_str(~"null") == Ok(Null)); assert_eq!(from_str(~"null"), Ok(Null));
fail_unless!(from_str(~"true") == Ok(Boolean(true))); assert_eq!(from_str(~"true"), Ok(Boolean(true)));
fail_unless!(from_str(~"false") == Ok(Boolean(false))); assert_eq!(from_str(~"false"), Ok(Boolean(false)));
fail_unless!(from_str(~" null ") == Ok(Null)); assert_eq!(from_str(~" null "), Ok(Null));
fail_unless!(from_str(~" true ") == Ok(Boolean(true))); assert_eq!(from_str(~" true "), Ok(Boolean(true)));
fail_unless!(from_str(~" false ") == Ok(Boolean(false))); assert_eq!(from_str(~" false "), Ok(Boolean(false)));
} }
#[test] #[test]
fn test_read_number() { fn test_read_number() {
fail_unless!(from_str(~"+") == assert_eq!(from_str(~"+"),
Err(Error {line: 1u, col: 1u, msg: @~"invalid syntax"})); 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"})); 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"})); 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"})); 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"})); 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"})); 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"})); Err(Error {line: 1u, col: 4u, msg: @~"invalid number"}));
fail_unless!(from_str(~"3") == Ok(Number(3f))); assert_eq!(from_str(~"3"), Ok(Number(3f)));
fail_unless!(from_str(~"3.1") == Ok(Number(3.1f))); assert_eq!(from_str(~"3.1"), Ok(Number(3.1f)));
fail_unless!(from_str(~"-1.2") == Ok(Number(-1.2f))); assert_eq!(from_str(~"-1.2"), Ok(Number(-1.2f)));
fail_unless!(from_str(~"0.4") == Ok(Number(0.4f))); assert_eq!(from_str(~"0.4"), Ok(Number(0.4f)));
fail_unless!(from_str(~"0.4e5") == Ok(Number(0.4e5f))); assert_eq!(from_str(~"0.4e5"), Ok(Number(0.4e5f)));
fail_unless!(from_str(~"0.4e+15") == Ok(Number(0.4e15f))); assert_eq!(from_str(~"0.4e+15"), Ok(Number(0.4e15f)));
fail_unless!(from_str(~"0.4e-01") == Ok(Number(0.4e-01f))); assert_eq!(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)));
} }
#[test] #[test]
fn test_read_str() { fn test_read_str() {
fail_unless!(from_str(~"\"") == assert_eq!(from_str(~"\""),
Err(Error {line: 1u, col: 2u, msg: @~"EOF while parsing string" 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" Err(Error {line: 1u, col: 5u, msg: @~"EOF while parsing string"
})); }));
fail_unless!(from_str(~"\"\"") == Ok(String(~""))); assert_eq!(from_str(~"\"\""), Ok(String(~"")));
fail_unless!(from_str(~"\"foo\"") == Ok(String(~"foo"))); assert_eq!(from_str(~"\"foo\""), Ok(String(~"foo")));
fail_unless!(from_str(~"\"\\\"\"") == Ok(String(~"\""))); assert_eq!(from_str(~"\"\\\"\""), Ok(String(~"\"")));
fail_unless!(from_str(~"\"\\b\"") == Ok(String(~"\x08"))); assert_eq!(from_str(~"\"\\b\""), Ok(String(~"\x08")));
fail_unless!(from_str(~"\"\\n\"") == Ok(String(~"\n"))); assert_eq!(from_str(~"\"\\n\""), Ok(String(~"\n")));
fail_unless!(from_str(~"\"\\r\"") == Ok(String(~"\r"))); assert_eq!(from_str(~"\"\\r\""), Ok(String(~"\r")));
fail_unless!(from_str(~"\"\\t\"") == Ok(String(~"\t"))); assert_eq!(from_str(~"\"\\t\""), Ok(String(~"\t")));
fail_unless!(from_str(~" \"foo\" ") == Ok(String(~"foo"))); assert_eq!(from_str(~" \"foo\" "), Ok(String(~"foo")));
} }
#[test] #[test]
fn test_unicode_hex_escapes_in_str() { fn test_unicode_hex_escapes_in_str() {
fail_unless!(from_str(~"\"\\u12ab\"") == Ok(String(~"\u12ab"))); assert_eq!(from_str(~"\"\\u12ab\""), Ok(String(~"\u12ab")));
fail_unless!(from_str(~"\"\\uAB12\"") == Ok(String(~"\uAB12"))); assert_eq!(from_str(~"\"\\uAB12\""), Ok(String(~"\uAB12")));
} }
#[test] #[test]
fn test_read_list() { fn test_read_list() {
fail_unless!(from_str(~"[") == assert_eq!(from_str(~"["),
Err(Error {line: 1u, col: 2u, msg: @~"EOF while parsing value"})); 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"})); 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"})); 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"})); 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 `]`"})); Err(Error {line: 1u, col: 4u, msg: @~"expected `,` or `]`"}));
fail_unless!(from_str(~"[]") == Ok(List(~[]))); assert_eq!(from_str(~"[]"), Ok(List(~[])));
fail_unless!(from_str(~"[ ]") == Ok(List(~[]))); assert_eq!(from_str(~"[ ]"), Ok(List(~[])));
fail_unless!(from_str(~"[true]") == Ok(List(~[Boolean(true)]))); assert_eq!(from_str(~"[true]"), Ok(List(~[Boolean(true)])));
fail_unless!(from_str(~"[ false ]") == Ok(List(~[Boolean(false)]))); assert_eq!(from_str(~"[ false ]"), Ok(List(~[Boolean(false)])));
fail_unless!(from_str(~"[null]") == Ok(List(~[Null]))); assert_eq!(from_str(~"[null]"), Ok(List(~[Null])));
fail_unless!(from_str(~"[3, 1]") == assert_eq!(from_str(~"[3, 1]"),
Ok(List(~[Number(3f), Number(1f)]))); 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)]))); 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)])]))); Ok(List(~[Number(2f), List(~[Number(4f), Number(1f)])])));
} }
#[test] #[test]
fn test_read_object() { fn test_read_object() {
fail_unless!(from_str(~"{") == assert_eq!(from_str(~"{"),
Err(Error { Err(Error {
line: 1u, line: 1u,
col: 2u, col: 2u,
msg: @~"EOF while parsing object"})); msg: @~"EOF while parsing object"}));
fail_unless!(from_str(~"{ ") == assert_eq!(from_str(~"{ "),
Err(Error { Err(Error {
line: 1u, line: 1u,
col: 3u, col: 3u,
msg: @~"EOF while parsing object"})); msg: @~"EOF while parsing object"}));
fail_unless!(from_str(~"{1") == assert_eq!(from_str(~"{1"),
Err(Error { Err(Error {
line: 1u, line: 1u,
col: 2u, col: 2u,
msg: @~"key must be a string"})); msg: @~"key must be a string"}));
fail_unless!(from_str(~"{ \"a\"") == assert_eq!(from_str(~"{ \"a\""),
Err(Error { Err(Error {
line: 1u, line: 1u,
col: 6u, col: 6u,
msg: @~"EOF while parsing object"})); msg: @~"EOF while parsing object"}));
fail_unless!(from_str(~"{\"a\"") == assert_eq!(from_str(~"{\"a\""),
Err(Error { Err(Error {
line: 1u, line: 1u,
col: 5u, col: 5u,
msg: @~"EOF while parsing object"})); msg: @~"EOF while parsing object"}));
fail_unless!(from_str(~"{\"a\" ") == assert_eq!(from_str(~"{\"a\" "),
Err(Error { Err(Error {
line: 1u, line: 1u,
col: 6u, col: 6u,
msg: @~"EOF while parsing object"})); 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 `:`"})); 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"})); 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 { Err(Error {
line: 1u, line: 1u,
col: 7u, col: 7u,
msg: @~"EOF while parsing object"})); 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 `}`"})); Err(Error {line: 1u, col: 8u, msg: @~"expected `,` or `}`"}));
fail_unless!(from_str(~"{\"a\":1,") == assert_eq!(from_str(~"{\"a\":1,"),
Err(Error { Err(Error {
line: 1u, line: 1u,
col: 8u, col: 8u,
msg: @~"EOF while parsing object"})); msg: @~"EOF while parsing object"}));
fail_unless!(result::unwrap(from_str(~"{}")) == mk_object(~[])); assert_eq!(result::unwrap(from_str(~"{}")), mk_object(~[]));
fail_unless!(result::unwrap(from_str(~"{\"a\": 3}")) == assert_eq!(result::unwrap(from_str(~"{\"a\": 3}")),
mk_object(~[(~"a", Number(3.0f))])); mk_object(~[(~"a", Number(3.0f))]));
fail_unless!(result::unwrap(from_str( assert_eq!(result::unwrap(from_str(
~"{ \"a\": null, \"b\" : true }")) == ~"{ \"a\": null, \"b\" : true }")),
mk_object(~[ mk_object(~[
(~"a", Null), (~"a", Null),
(~"b", Boolean(true))])); (~"b", Boolean(true))]));
fail_unless!(result::unwrap( assert_eq!(result::unwrap(
from_str(~"\n{ \"a\": null, \"b\" : true }\n")) == from_str(~"\n{ \"a\": null, \"b\" : true }\n")),
mk_object(~[ mk_object(~[
(~"a", Null), (~"a", Null),
(~"b", Boolean(true))])); (~"b", Boolean(true))]));
fail_unless!(result::unwrap(from_str( assert_eq!(result::unwrap(from_str(
~"{\"a\" : 1.0 ,\"b\": [ true ]}")) == ~"{\"a\" : 1.0 ,\"b\": [ true ]}")),
mk_object(~[ mk_object(~[
(~"a", Number(1.0)), (~"a", Number(1.0)),
(~"b", List(~[Boolean(true)])) (~"b", List(~[Boolean(true)]))
])); ]));
fail_unless!(result::unwrap(from_str( assert_eq!(result::unwrap(from_str(
~"{" + ~"{" +
~"\"a\": 1.0, " + ~"\"a\": 1.0, " +
~"\"b\": [" + ~"\"b\": [" +
@ -1515,7 +1692,7 @@ mod tests {
~"\"foo\\nbar\", " + ~"\"foo\\nbar\", " +
~"{ \"c\": {\"d\": null} } " + ~"{ \"c\": {\"d\": null} } " +
~"]" + ~"]" +
~"}")) == ~"}")),
mk_object(~[ mk_object(~[
(~"a", Number(1.0f)), (~"a", Number(1.0f)),
(~"b", List(~[ (~"b", List(~[
@ -1528,9 +1705,37 @@ mod tests {
])); ]));
} }
#[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] #[test]
fn test_multiline_errors() { fn test_multiline_errors() {
fail_unless!(from_str(~"{\n \"foo\":\n \"bar\"") == assert_eq!(from_str(~"{\n \"foo\":\n \"bar\""),
Err(Error { Err(Error {
line: 3u, line: 3u,
col: 8u, col: 8u,

View file

@ -182,4 +182,18 @@ impl serialize::Encoder for Serializer {
if idx > 0u { self.wr.write_str(~", "); } if idx > 0u { self.wr.write_str(~", "); }
f(); 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(')');
}
} }

View file

@ -62,6 +62,11 @@ pub trait Encoder {
fn emit_tup(&self, len: uint, f: &fn()); fn emit_tup(&self, len: uint, f: &fn());
fn emit_tup_elt(&self, idx: 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 { pub trait Decoder {
@ -87,7 +92,15 @@ pub trait Decoder {
// Compound types: // Compound types:
fn read_enum<T>(&self, name: &str, f: &fn() -> T) -> T; fn read_enum<T>(&self, name: &str, f: &fn() -> T) -> T;
#[cfg(stage0)]
fn read_enum_variant<T>(&self, f: &fn(uint) -> T) -> T; 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_enum_variant_arg<T>(&self, idx: uint, f: &fn() -> T) -> T;
fn read_owned<T>(&self, f: &fn() -> T) -> T; fn read_owned<T>(&self, f: &fn() -> T) -> T;
@ -103,6 +116,9 @@ pub trait Decoder {
fn read_tup<T>(&self, sz: uint, f: &fn() -> T) -> T; fn read_tup<T>(&self, sz: uint, f: &fn() -> T) -> T;
fn read_tup_elt<T>(&self, idx: uint, f: &fn() -> T) -> T; fn read_tup_elt<T>(&self, idx: uint, f: &fn() -> T) -> T;
// Specialized types:
fn read_option<T>(&self, f: &fn() -> T) -> Option<T>;
} }
pub trait Encodable<S:Encoder> { pub trait Encodable<S:Encoder> {
@ -368,14 +384,10 @@ impl<D:Decoder,T:Decodable<D>> Decodable<D> for @[T] {
impl<S:Encoder,T:Encodable<S>> Encodable<S> for Option<T> { impl<S:Encoder,T:Encodable<S>> Encodable<S> for Option<T> {
fn encode(&self, s: &S) { fn encode(&self, s: &S) {
do s.emit_enum(~"option") { do s.emit_option {
match *self { match *self {
None => do s.emit_enum_variant(~"none", 0u, 0u) { None => s.emit_option_none(),
}, Some(ref v) => s.emit_option_some(|| v.encode(s)),
Some(ref v) => do s.emit_enum_variant(~"some", 1u, 1u) {
s.emit_enum_variant_arg(0u, || v.encode(s))
}
} }
} }
} }
@ -383,16 +395,7 @@ impl<S:Encoder,T:Encodable<S>> Encodable<S> for Option<T> {
impl<D:Decoder,T:Decodable<D>> Decodable<D> for Option<T> { impl<D:Decoder,T:Decodable<D>> Decodable<D> for Option<T> {
fn decode(d: &D) -> Option<T> { fn decode(d: &D) -> Option<T> {
do d.read_enum(~"option") { d.read_option(|| Decodable::decode(d))
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))
}
}
}
} }
} }

View file

@ -386,7 +386,6 @@ pub enum vstore {
#[auto_decode] #[auto_decode]
#[deriving(Eq)] #[deriving(Eq)]
pub enum expr_vstore { pub enum expr_vstore {
expr_vstore_fixed(Option<uint>), // [1,2,3,4]
expr_vstore_uniq, // ~[1,2,3,4] expr_vstore_uniq, // ~[1,2,3,4]
expr_vstore_box, // @[1,2,3,4] expr_vstore_box, // @[1,2,3,4]
expr_vstore_mut_box, // @mut [1,2,3,4] expr_vstore_mut_box, // @mut [1,2,3,4]
@ -543,12 +542,6 @@ pub struct expr {
span: span, 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_encode]
#[auto_decode] #[auto_decode]
#[deriving(Eq)] #[deriving(Eq)]
@ -598,7 +591,7 @@ pub enum expr_ {
expr_break(Option<ident>), expr_break(Option<ident>),
expr_again(Option<ident>), expr_again(Option<ident>),
expr_ret(Option<@expr>), expr_ret(Option<@expr>),
expr_log(log_level, @expr, @expr), expr_log(@expr, @expr),
expr_inline_asm(@~str, // asm expr_inline_asm(@~str, // asm
~[(@~str, @expr)], // inputs ~[(@~str, @expr)], // inputs

View file

@ -1059,6 +1059,18 @@ fn mk_enum_deser_body(
name: ast::ident, name: ast::ident,
variants: ~[ast::variant] variants: ~[ast::variant]
) -> @ast::expr { ) -> @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 mut arms = do variants.mapi |v_idx, variant| {
let body = match variant.node.kind { let body = match variant.node.kind {
ast::tuple_variant_kind(ref args) => { 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( let expr_lambda = ext_cx.lambda_expr(
ext_cx.expr_method_call( ext_cx.expr_method_call(
span, span,
ext_cx.expr_var(span, ~"__d"), ext_cx.expr_var(span, ~"__d"),
ext_cx.ident_of(~"read_enum_variant"), 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)] #[cfg(test)]
mod test { mod test {
use core::option::{None, Some};
use std::serialize::Encodable; use std::serialize::Encodable;
use std::serialize::Encoder; use std::serialize::Encoder;
@ -1190,6 +1202,9 @@ mod test {
CallToEmitNil, CallToEmitNil,
CallToEmitStruct(~str,uint), CallToEmitStruct(~str,uint),
CallToEmitField(~str,uint), CallToEmitField(~str,uint),
CallToEmitOption,
CallToEmitOptionNone,
CallToEmitOptionSome,
// all of the ones I was too lazy to handle: // all of the ones I was too lazy to handle:
CallToOther CallToOther
} }
@ -1281,6 +1296,18 @@ mod test {
fn emit_tup_elt(&self, +_idx: uint, f: &fn()) { fn emit_tup_elt(&self, +_idx: uint, f: &fn()) {
self.add_unknown_to_log(); f(); 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 @@ mod test {
Magazine(~str) Magazine(~str)
} }
#[test] fn encode_enum_test () { #[test]
assert_eq!(to_call_log(Book(34,44)), fn test_encode_enum() {
~[CallToEmitEnum (~"Written"), assert_eq!(
to_call_log(Book(34,44)),
~[
CallToEmitEnum(~"Written"),
CallToEmitEnumVariant(~"Book",0,2), CallToEmitEnumVariant(~"Book",0,2),
CallToEmitEnumVariantArg(0), CallToEmitEnumVariantArg(0),
CallToEmitUint(34), CallToEmitUint(34),
CallToEmitEnumVariantArg(1), CallToEmitEnumVariantArg(1),
CallToEmitUint (44)]); 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)
]
);
} }
} }

View file

@ -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), mk_vstore_e(cx, sp, mk_base_vec_e(cx, sp, exprs),
ast::expr_vstore_slice) 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 { pub fn mk_base_str(cx: @ext_ctxt, sp: span, +s: ~str) -> @ast::expr {
let lit = ast::lit_str(@s); let lit = ast::lit_str(@s);
return mk_lit(cx, sp, lit); return mk_lit(cx, sp, lit);

View file

@ -42,8 +42,7 @@ pub mod rt {
pub use ast::*; pub use ast::*;
pub use parse::token::*; pub use parse::token::*;
pub use parse::new_parser_from_tts; pub use parse::new_parser_from_tts;
pub use codemap::BytePos; pub use codemap::{BytePos, span, dummy_spanned};
pub use codemap::span;
use print::pprust; use print::pprust;
use print::pprust::{item_to_str, ty_to_str}; use print::pprust::{item_to_str, ty_to_str};
@ -89,7 +88,7 @@ pub mod rt {
} }
} }
impl ToSource for ~[@ast::item] { impl<'self> ToSource for &'self [@ast::item] {
fn to_source(&self, cx: @ext_ctxt) -> ~str { fn to_source(&self, cx: @ext_ctxt) -> ~str {
str::connect(self.map(|i| i.to_source(cx)), ~"\n\n") str::connect(self.map(|i| i.to_source(cx)), ~"\n\n")
} }
@ -101,7 +100,7 @@ pub mod rt {
} }
} }
impl ToSource for ~[@ast::Ty] { impl<'self> ToSource for &'self [@ast::Ty] {
fn to_source(&self, cx: @ext_ctxt) -> ~str { fn to_source(&self, cx: @ext_ctxt) -> ~str {
str::connect(self.map(|i| i.to_source(cx)), ~", ") str::connect(self.map(|i| i.to_source(cx)), ~", ")
} }
@ -119,6 +118,90 @@ pub mod rt {
} }
} }
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. // Alas ... we write these out instead. All redundant.
impl ToTokens for ast::ident { impl ToTokens for ast::ident {
@ -133,7 +216,7 @@ pub mod rt {
} }
} }
impl ToTokens for ~[@ast::item] { impl<'self> ToTokens for &'self [@ast::item] {
fn to_tokens(&self, cx: @ext_ctxt) -> ~[token_tree] { fn to_tokens(&self, cx: @ext_ctxt) -> ~[token_tree] {
cx.parse_tts(self.to_source(cx)) cx.parse_tts(self.to_source(cx))
} }
@ -145,7 +228,7 @@ pub mod rt {
} }
} }
impl ToTokens for ~[@ast::Ty] { impl<'self> ToTokens for &'self [@ast::Ty] {
fn to_tokens(&self, cx: @ext_ctxt) -> ~[token_tree] { fn to_tokens(&self, cx: @ext_ctxt) -> ~[token_tree] {
cx.parse_tts(self.to_source(cx)) cx.parse_tts(self.to_source(cx))
} }
@ -163,6 +246,78 @@ pub mod rt {
} }
} }
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 { pub trait ExtParseUtils {
fn parse_item(&self, s: ~str) -> @ast::item; fn parse_item(&self, s: ~str) -> @ast::item;
fn parse_expr(&self, s: ~str) -> @ast::expr; fn parse_expr(&self, s: ~str) -> @ast::expr;

View file

@ -552,9 +552,8 @@ pub fn noop_fold_expr(e: &expr_, fld: @ast_fold) -> expr_ {
expr_ret(ref e) => { expr_ret(ref e) => {
expr_ret(e.map(|x| fld.fold_expr(*x))) expr_ret(e.map(|x| fld.fold_expr(*x)))
} }
expr_log(i, lv, e) => { expr_log(lv, e) => {
expr_log( expr_log(
i,
fld.fold_expr(lv), fld.fold_expr(lv),
fld.fold_expr(e) fld.fold_expr(e)
) )

View file

@ -326,18 +326,31 @@ mod test {
@~"fn foo (x : int) { x; }", @~"fn foo (x : int) { x; }",
~[], ~[],
new_parse_sess(None)); new_parse_sess(None));
assert_eq!(to_json_str(@tts), assert_eq!(
~"[[\"tt_tok\",[null,[\"IDENT\",[\"fn\",false]]]],\ to_json_str(@tts),
[\"tt_tok\",[null,[\"IDENT\",[\"foo\",false]]]],\ ~"[\
[\"tt_delim\",[[[\"tt_tok\",[null,[\"LPAREN\",[]]]],\ [\"tt_tok\",null,[\"IDENT\",\"fn\",false]],\
[\"tt_tok\",[null,[\"IDENT\",[\"x\",false]]]],\ [\"tt_tok\",null,[\"IDENT\",\"foo\",false]],\
[\"tt_tok\",[null,[\"COLON\",[]]]],\ [\
[\"tt_tok\",[null,[\"IDENT\",[\"int\",false]]]],\ \"tt_delim\",\
[\"tt_tok\",[null,[\"RPAREN\",[]]]]]]],\ [\
[\"tt_delim\",[[[\"tt_tok\",[null,[\"LBRACE\",[]]]],\ [\"tt_tok\",null,\"LPAREN\"],\
[\"tt_tok\",[null,[\"IDENT\",[\"x\",false]]]],\ [\"tt_tok\",null,[\"IDENT\",\"x\",false]],\
[\"tt_tok\",[null,[\"SEMI\",[]]]],\ [\"tt_tok\",null,\"COLON\"],\
[\"tt_tok\",[null,[\"RBRACE\",[]]]]]]]]" [\"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) let ast1 = new_parser_from_tts(new_parse_sess(None),~[],tts)
.parse_item(~[]); .parse_item(~[]);

View file

@ -28,7 +28,7 @@ use ast::{expr_lit, expr_log, expr_loop, expr_loop_body, expr_mac};
use ast::{expr_method_call, expr_paren, expr_path, expr_repeat}; 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_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_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_mut_slice, expr_while, extern_fn, field, fn_decl};
use ast::{expr_vstore_uniq, TyClosure, TyBareFn, Onceness, Once, Many}; use ast::{expr_vstore_uniq, TyClosure, TyBareFn, Onceness, Once, Many};
use ast::{foreign_item, foreign_item_const, foreign_item_fn, foreign_mod}; use ast::{foreign_item, foreign_item_const, foreign_item_fn, foreign_mod};
@ -1223,7 +1223,7 @@ pub impl Parser {
let lvl = self.parse_expr(); let lvl = self.parse_expr();
self.expect(&token::COMMA); self.expect(&token::COMMA);
let e = self.parse_expr(); let e = self.parse_expr();
ex = expr_log(ast::log_other, lvl, e); ex = expr_log(lvl, e);
hi = self.span.hi; hi = self.span.hi;
self.expect(&token::RPAREN); self.expect(&token::RPAREN);
} else if self.eat_keyword(&~"return") { } else if self.eat_keyword(&~"return") {
@ -2721,8 +2721,9 @@ pub impl Parser {
} }
self.bump(); self.bump();
} }
token::IDENT(*) => { token::MOD_SEP | token::IDENT(*) => {
let maybe_bound = match *self.token { let maybe_bound = match *self.token {
token::MOD_SEP => None,
token::IDENT(copy sid, _) => { token::IDENT(copy sid, _) => {
match *self.id_to_str(sid) { match *self.id_to_str(sid) {
~"send" | ~"send" |
@ -2750,7 +2751,7 @@ pub impl Parser {
result.push(bound); result.push(bound);
} }
None => { None => {
let ty = self.parse_ty(false); let ty = self.parse_ty(true);
result.push(TraitTyParamBound(ty)); result.push(TraitTyParamBound(ty));
} }
} }
@ -3099,14 +3100,6 @@ pub impl Parser {
// impl<T> Foo { ... } // impl<T> Foo { ... }
// impl<T> ToStr for ~[T] { ... } // impl<T> ToStr for ~[T] { ... }
fn parse_item_impl(&self, visibility: ast::visibility) -> item_info { 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. // First, parse type parameters if necessary.
let generics = self.parse_generics(); let generics = self.parse_generics();

View file

@ -325,7 +325,7 @@ pub fn commasep<IN>(s: @ps, b: breaks, elts: &[IN], op: &fn(@ps, IN)) {
pub fn commasep_cmnt<IN>(s: @ps, b: breaks, elts: &[IN], op: &fn(@ps, IN), pub fn commasep_cmnt<IN>(s: @ps, b: breaks, elts: &[IN], op: &fn(@ps, IN),
get_span: &fn(IN) -> codemap::span) { get_span: &fn(IN) -> codemap::span) {
box(s, 0u, b); box(s, 0u, b);
let len = vec::len::<IN>(elts); let len = elts.len();
let mut i = 0u; let mut i = 0u;
for elts.each |elt| { for elts.each |elt| {
maybe_print_comment(s, get_span(*elt).hi); 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) { pub fn print_expr_vstore(s: @ps, t: ast::expr_vstore) {
match t { 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_uniq => word(s.s, ~"~"),
ast::expr_vstore_box => word(s.s, ~"@"), ast::expr_vstore_box => word(s.s, ~"@"),
ast::expr_vstore_mut_box => { ast::expr_vstore_mut_box => {
@ -1105,16 +1103,9 @@ pub fn print_expr(s: @ps, &&expr: @ast::expr) {
let ann_node = node_expr(s, expr); let ann_node = node_expr(s, expr);
(s.ann.pre)(ann_node); (s.ann.pre)(ann_node);
match expr.node { match expr.node {
ast::expr_vstore(e, v) => match v { ast::expr_vstore(e, v) => {
ast::expr_vstore_fixed(_) => {
print_expr(s, e);
word(s.s, ~"/");
print_expr_vstore(s, v);
}
_ => {
print_expr_vstore(s, v); print_expr_vstore(s, v);
print_expr(s, e); print_expr(s, e);
}
}, },
ast::expr_vec(ref exprs, mutbl) => { ast::expr_vec(ref exprs, mutbl) => {
ibox(s, indent_unit); ibox(s, indent_unit);
@ -1391,12 +1382,8 @@ pub fn print_expr(s: @ps, &&expr: @ast::expr) {
_ => () _ => ()
} }
} }
ast::expr_log(lvl, lexp, expr) => { ast::expr_log(lexp, expr) => {
match lvl { word(s.s, ~"__log");
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); popen(s);
print_expr(s, lexp); print_expr(s, lexp);
word(s.s, ~","); word(s.s, ~",");
@ -1404,8 +1391,6 @@ pub fn print_expr(s: @ps, &&expr: @ast::expr) {
print_expr(s, expr); print_expr(s, expr);
pclose(s); pclose(s);
} }
}
}
ast::expr_inline_asm(a, in, out, c, v, _) => { ast::expr_inline_asm(a, in, out, c, v, _) => {
if v { if v {
word(s.s, ~"__volatile__ asm!"); word(s.s, ~"__volatile__ asm!");
@ -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, ~"\"");
word(s.s, str::escape_default(st)); word(s.s, str::escape_default(st));
word(s.s, ~"\""); word(s.s, ~"\"");

View file

@ -559,7 +559,7 @@ pub fn visit_expr<E>(ex: @expr, e: E, v: vt<E>) {
expr_break(_) => (), expr_break(_) => (),
expr_again(_) => (), expr_again(_) => (),
expr_ret(eo) => visit_expr_opt(eo, e, v), 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)(lv, e, v);
(v.visit_expr)(x, e, v); (v.visit_expr)(x, e, v);
} }

View file

@ -0,0 +1,3 @@
fn foo<T: ::cmp::Eq>(t: T) { }
fn main() { }