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:
commit
84ddff3909
24 changed files with 820 additions and 316 deletions
|
@ -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")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ______________________________________________________________________
|
// ______________________________________________________________________
|
||||||
|
|
|
@ -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(*) |
|
||||||
|
|
|
@ -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 |
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) => {
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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, _, _) => {
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 => {
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
assert_eq!(str::from_bytes(bw.bytes), ~"[\"frog\",[\"Henry\",349]]");
|
Frog(~str, int)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_write_some () {
|
fn test_write_enum_no_args() {
|
||||||
let bw = @io::BytesWriter();
|
let animal = Dog;
|
||||||
let bww : @io::Writer = (bw as @io::Writer);
|
|
||||||
let encoder = (@Encoder(bww) as @serialize::Encoder);
|
let s = do io::with_str_writer |wr| {
|
||||||
do encoder.emit_enum(~"Option") {
|
let encoder = Encoder(wr);
|
||||||
do encoder.emit_enum_variant (~"Some",37,1242) {
|
animal.encode(&encoder);
|
||||||
do encoder.emit_enum_variant_arg (0) {
|
};
|
||||||
encoder.emit_owned_str(~"jodhpurs")
|
assert_eq!(s, ~"\"Dog\"");
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assert_eq!(str::from_bytes(bw.bytes), ~"\"jodhpurs\"");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_write_none () {
|
fn test_write_enum_no_args_pretty() {
|
||||||
let bw = @io::BytesWriter();
|
let animal = Dog;
|
||||||
let bww : @io::Writer = (bw as @io::Writer);
|
|
||||||
let encoder = (@Encoder(bww) as @serialize::Encoder);
|
let s = do io::with_str_writer |wr| {
|
||||||
do encoder.emit_enum(~"Option") {
|
let encoder = PrettyEncoder(wr);
|
||||||
do encoder.emit_enum_variant (~"None",37,1242) {
|
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]");
|
||||||
}
|
}
|
||||||
assert_eq!(str::from_bytes(bw.bytes), ~"null");
|
|
||||||
|
#[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]
|
#[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,
|
||||||
|
|
|
@ -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(')');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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!(
|
||||||
CallToEmitEnumVariant (~"Book",0,2),
|
to_call_log(Book(34,44)),
|
||||||
CallToEmitEnumVariantArg (0),
|
~[
|
||||||
CallToEmitUint (34),
|
CallToEmitEnum(~"Written"),
|
||||||
CallToEmitEnumVariantArg (1),
|
CallToEmitEnumVariant(~"Book",0,2),
|
||||||
CallToEmitUint (44)]);
|
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)
|
||||||
|
]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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)
|
||||||
)
|
)
|
||||||
|
|
|
@ -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(~[]);
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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, ~"\"");
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
3
src/test/run-pass/issue-5572.rs
Normal file
3
src/test/run-pass/issue-5572.rs
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
fn foo<T: ::cmp::Eq>(t: T) { }
|
||||||
|
|
||||||
|
fn main() { }
|
Loading…
Add table
Add a link
Reference in a new issue