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