first (functional) version of the auto_serialize syntax ext
This commit is contained in:
parent
06c8acdd31
commit
d91742294f
19 changed files with 851 additions and 536 deletions
|
@ -31,7 +31,7 @@ export uint, u8, u16, u32, u64;
|
|||
export float, f32, f64;
|
||||
export box, char, str, ptr, vec, bool;
|
||||
export either, option, result, iter;
|
||||
export libc, os, io, run, rand, sys, unsafe, logging;
|
||||
export libc, os, ctypes, io, run, rand, sys, unsafe, logging, serialization;
|
||||
export comm, task, future;
|
||||
export extfmt;
|
||||
export tuple;
|
||||
|
@ -88,6 +88,7 @@ mod cmath;
|
|||
mod sys;
|
||||
mod unsafe;
|
||||
mod logging;
|
||||
mod serialization;
|
||||
|
||||
// Concurrency
|
||||
mod comm;
|
||||
|
|
116
src/libcore/serialization.rs
Normal file
116
src/libcore/serialization.rs
Normal file
|
@ -0,0 +1,116 @@
|
|||
export serializer;
|
||||
export serializer_helpers;
|
||||
export deserializer;
|
||||
export deserializer_helpers;
|
||||
|
||||
/*
|
||||
Core serialization interfaces.
|
||||
*/
|
||||
|
||||
iface serializer {
|
||||
// Primitive types:
|
||||
fn emit_nil();
|
||||
fn emit_uint(v: uint);
|
||||
fn emit_u64(v: u64);
|
||||
fn emit_u32(v: u32);
|
||||
fn emit_u16(v: u16);
|
||||
fn emit_u8(v: u8);
|
||||
fn emit_int(v: int);
|
||||
fn emit_i64(v: i64);
|
||||
fn emit_i32(v: i32);
|
||||
fn emit_i16(v: i16);
|
||||
fn emit_i8(v: i8);
|
||||
fn emit_bool(v: bool);
|
||||
fn emit_float(v: float);
|
||||
fn emit_f64(v: f64);
|
||||
fn emit_f32(v: f32);
|
||||
fn emit_str(v: str);
|
||||
|
||||
// Compound types:
|
||||
fn emit_enum(name: str, f: fn());
|
||||
fn emit_enum_variant(v_name: str, v_id: uint, sz: uint, f: fn());
|
||||
fn emit_enum_variant_arg(idx: uint, f: fn());
|
||||
fn emit_vec(len: uint, f: fn());
|
||||
fn emit_vec_elt(idx: uint, f: fn());
|
||||
fn emit_box(f: fn());
|
||||
fn emit_uniq(f: fn());
|
||||
fn emit_rec(f: fn());
|
||||
fn emit_rec_field(f_name: str, f_idx: uint, f: fn());
|
||||
fn emit_tup(sz: uint, f: fn());
|
||||
fn emit_tup_elt(idx: uint, f: fn());
|
||||
}
|
||||
|
||||
iface deserializer {
|
||||
// Primitive types:
|
||||
fn read_nil() -> ();
|
||||
|
||||
fn read_uint() -> uint;
|
||||
fn read_u64() -> u64;
|
||||
fn read_u32() -> u32;
|
||||
fn read_u16() -> u16;
|
||||
fn read_u8() -> u8;
|
||||
|
||||
fn read_int() -> int;
|
||||
fn read_i64() -> i64;
|
||||
fn read_i32() -> i32;
|
||||
fn read_i16() -> i16;
|
||||
fn read_i8() -> i8;
|
||||
|
||||
|
||||
fn read_bool() -> bool;
|
||||
|
||||
fn read_str() -> str;
|
||||
|
||||
fn read_f64() -> f64;
|
||||
fn read_f32() -> f32;
|
||||
fn read_float() -> float;
|
||||
|
||||
// Compound types:
|
||||
fn read_enum<T:copy>(name: str, f: fn() -> T) -> T;
|
||||
fn read_enum_variant<T:copy>(f: fn(uint) -> T) -> T;
|
||||
fn read_enum_variant_arg<T:copy>(idx: uint, f: fn() -> T) -> T;
|
||||
fn read_vec<T:copy>(f: fn(uint) -> T) -> T;
|
||||
fn read_vec_elt<T:copy>(idx: uint, f: fn() -> T) -> T;
|
||||
fn read_box<T:copy>(f: fn() -> T) -> T;
|
||||
fn read_uniq<T:copy>(f: fn() -> T) -> T;
|
||||
fn read_rec<T:copy>(f: fn() -> T) -> T;
|
||||
fn read_rec_field<T:copy>(f_name: str, f_idx: uint, f: fn() -> T) -> T;
|
||||
fn read_tup<T:copy>(sz: uint, f: fn() -> T) -> T;
|
||||
fn read_tup_elt<T:copy>(idx: uint, f: fn() -> T) -> T;
|
||||
}
|
||||
|
||||
// ___________________________________________________________________________
|
||||
// Helper routines
|
||||
//
|
||||
// These should eventually be coded as traits.
|
||||
|
||||
fn emit_from_vec<S: serializer, T>(s: S, v: [T], f: fn(T)) {
|
||||
s.emit_vec(vec::len(v)) {||
|
||||
vec::iteri(v) {|i,e|
|
||||
s.emit_vec_elt(i) {||
|
||||
f(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn read_to_vec<D: deserializer, T>(d: D, f: fn() -> T) -> [T] {
|
||||
d.read_vec {|len|
|
||||
vec::init_fn(len) {|i|
|
||||
d.read_vec_elt(i) {|| f() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl serializer_helpers<S: serializer> for S {
|
||||
fn emit_from_vec<T>(v: [T], f: fn(T)) {
|
||||
emit_from_vec(self, v, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl deserializer_helpers<D: deserializer> for D {
|
||||
fn read_to_vec<T>(f: fn() -> T) -> [T] {
|
||||
read_to_vec(self, f)
|
||||
}
|
||||
}
|
||||
|
|
@ -192,6 +192,14 @@ fn compl(i: uint) -> uint {
|
|||
max_value ^ i
|
||||
}
|
||||
|
||||
fn serialize<S: serialization::serializer>(s: S, v: uint) {
|
||||
s.emit_uint(v);
|
||||
}
|
||||
|
||||
fn deserialize<D: serialization::deserializer>(d: D) -> uint {
|
||||
d.read_uint()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
|
|
|
@ -406,7 +406,7 @@ fn map<T, U>(v: [T], f: fn(T) -> U) -> [U] {
|
|||
}
|
||||
|
||||
fn flat_map<T, U>(v: [T], f: fn(T) -> [U]) -> [U] {
|
||||
let result = [];
|
||||
let mut result = [];
|
||||
for elem: T in v { result += f(elem); }
|
||||
ret result;
|
||||
}
|
||||
|
|
|
@ -25,6 +25,9 @@ export doc_as_i16;
|
|||
export doc_as_i32;
|
||||
export doc_as_i64;
|
||||
export writer;
|
||||
export serializer;
|
||||
export ebml_deserializer;
|
||||
export deserializer;
|
||||
|
||||
type ebml_tag = {id: uint, size: uint};
|
||||
|
||||
|
@ -273,3 +276,314 @@ impl writer for writer {
|
|||
|
||||
// TODO: optionally perform "relaxations" on end_tag to more efficiently
|
||||
// encode sizes; this is a fixed point iteration
|
||||
|
||||
// Set to true to generate more debugging in EBML serialization.
|
||||
// Totally lame approach.
|
||||
const debug: bool = true;
|
||||
|
||||
enum ebml_serializer_tag {
|
||||
es_uint, es_u64, es_u32, es_u16, es_u8,
|
||||
es_int, es_i64, es_i32, es_i16, es_i8,
|
||||
es_bool,
|
||||
es_str,
|
||||
es_f64, es_f32, es_float,
|
||||
es_enum, es_enum_vid, es_enum_body,
|
||||
es_vec, es_vec_len, es_vec_elt,
|
||||
|
||||
es_label // Used only when debugging
|
||||
}
|
||||
|
||||
impl serializer of core::serialization::serializer for ebml::writer {
|
||||
fn emit_nil() {}
|
||||
|
||||
// used internally to emit things like the vector length and so on
|
||||
fn _emit_tagged_uint(t: ebml_serializer_tag, v: uint) {
|
||||
assert v <= 0xFFFF_FFFF_u;
|
||||
self.wr_tagged_u32(t as uint, v as u32);
|
||||
}
|
||||
|
||||
fn _emit_label(label: str) {
|
||||
// There are various strings that we have access to, such as
|
||||
// the name of a record field, which do not actually appear in
|
||||
// the serialized EBML (normally). This is just for
|
||||
// efficiency. When debugging, though, we can emit such
|
||||
// labels and then they will be checked by deserializer to
|
||||
// try and check failures more quickly.
|
||||
if debug { self.wr_tagged_str(es_label as uint, label) }
|
||||
}
|
||||
|
||||
fn emit_uint(v: uint) { self.wr_tagged_u64(es_uint as uint, v as u64); }
|
||||
fn emit_u64(v: u64) { self.wr_tagged_u64(es_u64 as uint, v); }
|
||||
fn emit_u32(v: u32) { self.wr_tagged_u32(es_u32 as uint, v); }
|
||||
fn emit_u16(v: u16) { self.wr_tagged_u16(es_u16 as uint, v); }
|
||||
fn emit_u8(v: u8) { self.wr_tagged_u8 (es_u8 as uint, v); }
|
||||
|
||||
fn emit_int(v: int) { self.wr_tagged_i64(es_int as uint, v as i64); }
|
||||
fn emit_i64(v: i64) { self.wr_tagged_i64(es_i64 as uint, v); }
|
||||
fn emit_i32(v: i32) { self.wr_tagged_i32(es_i32 as uint, v); }
|
||||
fn emit_i16(v: i16) { self.wr_tagged_i16(es_i16 as uint, v); }
|
||||
fn emit_i8(v: i8) { self.wr_tagged_i8 (es_i8 as uint, v); }
|
||||
|
||||
fn emit_bool(v: bool) { self.wr_tagged_u8(es_bool as uint, v as u8) }
|
||||
|
||||
fn emit_f64(_v: f64) { fail "TODO"; }
|
||||
fn emit_f32(_v: f32) { fail "TODO"; }
|
||||
fn emit_float(_v: float) { fail "TODO"; }
|
||||
|
||||
fn emit_str(v: str) { self.wr_tagged_str(es_str as uint, v) }
|
||||
|
||||
fn emit_enum(name: str, f: fn()) {
|
||||
self._emit_label(name);
|
||||
self.wr_tag(es_enum as uint, f)
|
||||
}
|
||||
fn emit_enum_variant(_v_name: str, v_id: uint, _cnt: uint, f: fn()) {
|
||||
self._emit_tagged_uint(es_enum_vid, v_id);
|
||||
self.wr_tag(es_enum_body as uint, f)
|
||||
}
|
||||
fn emit_enum_variant_arg(_idx: uint, f: fn()) { f() }
|
||||
|
||||
fn emit_vec(len: uint, f: fn()) {
|
||||
self.wr_tag(es_vec as uint) {||
|
||||
self._emit_tagged_uint(es_vec_len, len);
|
||||
f()
|
||||
}
|
||||
}
|
||||
|
||||
fn emit_vec_elt(_idx: uint, f: fn()) {
|
||||
self.wr_tag(es_vec_elt as uint, f)
|
||||
}
|
||||
|
||||
fn emit_box(f: fn()) { f() }
|
||||
fn emit_uniq(f: fn()) { f() }
|
||||
fn emit_rec(f: fn()) { f() }
|
||||
fn emit_rec_field(f_name: str, _f_idx: uint, f: fn()) {
|
||||
self._emit_label(f_name);
|
||||
f()
|
||||
}
|
||||
fn emit_tup(_sz: uint, f: fn()) { f() }
|
||||
fn emit_tup_elt(_idx: uint, f: fn()) { f() }
|
||||
}
|
||||
|
||||
type ebml_deserializer = {mutable parent: ebml::doc,
|
||||
mutable pos: uint};
|
||||
|
||||
fn ebml_deserializer(d: ebml::doc) -> ebml_deserializer {
|
||||
{mutable parent: d, mutable pos: d.start}
|
||||
}
|
||||
|
||||
impl deserializer of core::serialization::deserializer for ebml_deserializer {
|
||||
fn _check_label(lbl: str) {
|
||||
if self.pos < self.parent.end {
|
||||
let {tag: r_tag, doc: r_doc} =
|
||||
ebml::doc_at(self.parent.data, self.pos);
|
||||
if r_tag == (es_label as uint) {
|
||||
self.pos = r_doc.end;
|
||||
let str = ebml::doc_as_str(r_doc);
|
||||
if lbl != str {
|
||||
fail #fmt["Expected label %s but found %s", lbl, str];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn next_doc(exp_tag: ebml_serializer_tag) -> ebml::doc {
|
||||
#debug[". next_doc(exp_tag=%?)", exp_tag];
|
||||
if self.pos >= self.parent.end {
|
||||
fail "no more documents in current node!";
|
||||
}
|
||||
let {tag: r_tag, doc: r_doc} =
|
||||
ebml::doc_at(self.parent.data, self.pos);
|
||||
#debug["self.parent=%?-%? self.pos=%? r_tag=%? r_doc=%?-%?",
|
||||
self.parent.start, self.parent.end, self.pos,
|
||||
r_tag, r_doc.start, r_doc.end];
|
||||
if r_tag != (exp_tag as uint) {
|
||||
fail #fmt["expected EMBL doc with tag %? but found tag %?",
|
||||
exp_tag, r_tag];
|
||||
}
|
||||
if r_doc.end > self.parent.end {
|
||||
fail #fmt["invalid EBML, child extends to 0x%x, parent to 0x%x",
|
||||
r_doc.end, self.parent.end];
|
||||
}
|
||||
self.pos = r_doc.end;
|
||||
ret r_doc;
|
||||
}
|
||||
|
||||
fn push_doc<T: copy>(d: ebml::doc, f: fn() -> T) -> T{
|
||||
let old_parent = self.parent;
|
||||
let old_pos = self.pos;
|
||||
self.parent = d;
|
||||
self.pos = d.start;
|
||||
let r = f();
|
||||
self.parent = old_parent;
|
||||
self.pos = old_pos;
|
||||
ret r;
|
||||
}
|
||||
|
||||
fn _next_uint(exp_tag: ebml_serializer_tag) -> uint {
|
||||
let r = ebml::doc_as_u32(self.next_doc(exp_tag));
|
||||
#debug["_next_uint exp_tag=%? result=%?", exp_tag, r];
|
||||
ret r as uint;
|
||||
}
|
||||
|
||||
fn read_nil() -> () { () }
|
||||
|
||||
fn read_u64() -> u64 { ebml::doc_as_u64(self.next_doc(es_u64)) }
|
||||
fn read_u32() -> u32 { ebml::doc_as_u32(self.next_doc(es_u32)) }
|
||||
fn read_u16() -> u16 { ebml::doc_as_u16(self.next_doc(es_u16)) }
|
||||
fn read_u8 () -> u8 { ebml::doc_as_u8 (self.next_doc(es_u8 )) }
|
||||
fn read_uint() -> uint {
|
||||
let v = ebml::doc_as_u64(self.next_doc(es_uint));
|
||||
if v > (core::uint::max_value as u64) {
|
||||
fail #fmt["uint %? too large for this architecture", v];
|
||||
}
|
||||
ret v as uint;
|
||||
}
|
||||
|
||||
fn read_i64() -> i64 { ebml::doc_as_u64(self.next_doc(es_i64)) as i64 }
|
||||
fn read_i32() -> i32 { ebml::doc_as_u32(self.next_doc(es_i32)) as i32 }
|
||||
fn read_i16() -> i16 { ebml::doc_as_u16(self.next_doc(es_i16)) as i16 }
|
||||
fn read_i8 () -> i8 { ebml::doc_as_u8 (self.next_doc(es_i8 )) as i8 }
|
||||
fn read_int() -> int {
|
||||
let v = ebml::doc_as_u64(self.next_doc(es_int)) as i64;
|
||||
if v > (int::max_value as i64) || v < (int::min_value as i64) {
|
||||
fail #fmt["int %? out of range for this architecture", v];
|
||||
}
|
||||
ret v as int;
|
||||
}
|
||||
|
||||
fn read_bool() -> bool { ebml::doc_as_u8(self.next_doc(es_bool)) as bool }
|
||||
|
||||
fn read_f64() -> f64 { fail "read_f64()"; }
|
||||
fn read_f32() -> f32 { fail "read_f32()"; }
|
||||
fn read_float() -> float { fail "read_float()"; }
|
||||
|
||||
fn read_str() -> str { ebml::doc_as_str(self.next_doc(es_str)) }
|
||||
|
||||
// Compound types:
|
||||
fn read_enum<T:copy>(name: str, f: fn() -> T) -> T {
|
||||
#debug["read_enum(%s)", name];
|
||||
self._check_label(name);
|
||||
self.push_doc(self.next_doc(es_enum), f)
|
||||
}
|
||||
|
||||
fn read_enum_variant<T:copy>(f: fn(uint) -> T) -> T {
|
||||
#debug["read_enum_variant()"];
|
||||
let idx = self._next_uint(es_enum_vid);
|
||||
#debug[" idx=%u", idx];
|
||||
self.push_doc(self.next_doc(es_enum_body)) {||
|
||||
f(idx)
|
||||
}
|
||||
}
|
||||
|
||||
fn read_enum_variant_arg<T:copy>(idx: uint, f: fn() -> T) -> T {
|
||||
#debug["read_enum_variant_arg(idx=%u)", idx];
|
||||
f()
|
||||
}
|
||||
|
||||
fn read_vec<T:copy>(f: fn(uint) -> T) -> T {
|
||||
#debug["read_vec()"];
|
||||
self.push_doc(self.next_doc(es_vec)) {||
|
||||
let len = self._next_uint(es_vec_len);
|
||||
#debug[" len=%u", len];
|
||||
f(len)
|
||||
}
|
||||
}
|
||||
|
||||
fn read_vec_elt<T:copy>(idx: uint, f: fn() -> T) -> T {
|
||||
#debug["read_vec_elt(idx=%u)", idx];
|
||||
self.push_doc(self.next_doc(es_vec_elt), f)
|
||||
}
|
||||
|
||||
fn read_box<T:copy>(f: fn() -> T) -> T {
|
||||
#debug["read_box()"];
|
||||
f()
|
||||
}
|
||||
|
||||
fn read_uniq<T:copy>(f: fn() -> T) -> T {
|
||||
#debug["read_uniq()"];
|
||||
f()
|
||||
}
|
||||
|
||||
fn read_rec<T:copy>(f: fn() -> T) -> T {
|
||||
#debug["read_rec()"];
|
||||
f()
|
||||
}
|
||||
|
||||
fn read_rec_field<T:copy>(f_name: str, f_idx: uint, f: fn() -> T) -> T {
|
||||
#debug["read_rec_field(%s, idx=%u)", f_name, f_idx];
|
||||
self._check_label(f_name);
|
||||
f()
|
||||
}
|
||||
|
||||
fn read_tup<T:copy>(sz: uint, f: fn() -> T) -> T {
|
||||
#debug["read_tup(sz=%u)", sz];
|
||||
f()
|
||||
}
|
||||
|
||||
fn read_tup_elt<T:copy>(idx: uint, f: fn() -> T) -> T {
|
||||
#debug["read_tup_elt(idx=%u)", idx];
|
||||
f()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ___________________________________________________________________________
|
||||
// Testing
|
||||
|
||||
#[test]
|
||||
fn test_option_int() {
|
||||
fn serialize_1<S: serialization::serializer>(s: S, v: int) {
|
||||
s.emit_i64(v as i64);
|
||||
}
|
||||
|
||||
fn serialize_0<S: serialization::serializer>(s: S, v: option<int>) {
|
||||
s.emit_enum("core::option::t") {||
|
||||
alt v {
|
||||
none {
|
||||
s.emit_enum_variant("core::option::none", 0u, 0u) {||}
|
||||
}
|
||||
some(v0) {
|
||||
s.emit_enum_variant("core::option::some", 1u, 1u) {||
|
||||
s.emit_enum_variant_arg(0u) {|| serialize_1(s, v0) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn deserialize_1<S: serialization::deserializer>(s: S) -> int {
|
||||
s.read_i64() as int
|
||||
}
|
||||
|
||||
fn deserialize_0<S: serialization::deserializer>(s: S) -> option<int> {
|
||||
s.read_enum("core::option::t") {||
|
||||
s.read_enum_variant {|i|
|
||||
alt check i {
|
||||
0u { none }
|
||||
1u {
|
||||
let v0 = s.read_enum_variant_arg(0u) {||
|
||||
deserialize_1(s)
|
||||
};
|
||||
some(v0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn test_v(v: option<int>) {
|
||||
#debug["v == %?", v];
|
||||
let mbuf = io::mem_buffer();
|
||||
let ebml_w = ebml::writer(io::mem_buffer_writer(mbuf));
|
||||
serialize_0(ebml_w, v);
|
||||
let ebml_doc = ebml::new_doc(@io::mem_buffer_buf(mbuf));
|
||||
let deser = ebml_deserializer(ebml_doc);
|
||||
let v1 = deserialize_0(deser);
|
||||
#debug["v1 == %?", v1];
|
||||
assert v == v1;
|
||||
}
|
||||
|
||||
test_v(some(22));
|
||||
test_v(none);
|
||||
test_v(some(3));
|
||||
}
|
||||
|
|
130
src/libstd/prettyprint.rs
Normal file
130
src/libstd/prettyprint.rs
Normal file
|
@ -0,0 +1,130 @@
|
|||
import io::writer;
|
||||
import io::writer_util;
|
||||
import serialization::serializer;
|
||||
|
||||
impl of serializer for writer {
|
||||
fn emit_nil() {
|
||||
self.write_str("()")
|
||||
}
|
||||
|
||||
fn emit_uint(v: uint) {
|
||||
self.write_str(#fmt["%?u", v]);
|
||||
}
|
||||
|
||||
fn emit_u64(v: u64) {
|
||||
self.write_str(#fmt["%?_u64", v]);
|
||||
}
|
||||
|
||||
fn emit_u32(v: u32) {
|
||||
self.write_str(#fmt["%?_u32", v]);
|
||||
}
|
||||
|
||||
fn emit_u16(v: u16) {
|
||||
self.write_str(#fmt["%?_u16", v]);
|
||||
}
|
||||
|
||||
fn emit_u8(v: u8) {
|
||||
self.write_str(#fmt["%?_u8", v]);
|
||||
}
|
||||
|
||||
fn emit_int(v: int) {
|
||||
self.write_str(#fmt["%?", v]);
|
||||
}
|
||||
|
||||
fn emit_i64(v: i64) {
|
||||
self.write_str(#fmt["%?_i64", v]);
|
||||
}
|
||||
|
||||
fn emit_i32(v: i32) {
|
||||
self.write_str(#fmt["%?_i32", v]);
|
||||
}
|
||||
|
||||
fn emit_i16(v: i16) {
|
||||
self.write_str(#fmt["%?_i16", v]);
|
||||
}
|
||||
|
||||
fn emit_i8(v: i8) {
|
||||
self.write_str(#fmt["%?_i8", v]);
|
||||
}
|
||||
|
||||
fn emit_bool(v: bool) {
|
||||
self.write_str(#fmt["%b", v]);
|
||||
}
|
||||
|
||||
fn emit_float(v: float) {
|
||||
self.write_str(#fmt["%?_f", v]);
|
||||
}
|
||||
|
||||
fn emit_f64(v: f64) {
|
||||
self.write_str(#fmt["%?_f64", v]);
|
||||
}
|
||||
|
||||
fn emit_f32(v: f32) {
|
||||
self.write_str(#fmt["%?_f32", v]);
|
||||
}
|
||||
|
||||
fn emit_str(v: str) {
|
||||
self.write_str(#fmt["%?", v]);
|
||||
}
|
||||
|
||||
fn emit_enum(_name: str, f: fn()) {
|
||||
f();
|
||||
}
|
||||
|
||||
fn emit_enum_variant(v_name: str, _v_id: uint, _sz: uint, f: fn()) {
|
||||
self.write_str(v_name);
|
||||
self.write_str("(");
|
||||
f();
|
||||
self.write_str(")");
|
||||
}
|
||||
|
||||
fn emit_enum_variant_arg(idx: uint, f: fn()) {
|
||||
if idx > 0u { self.write_str(", "); }
|
||||
f();
|
||||
}
|
||||
|
||||
fn emit_vec(_len: uint, f: fn()) {
|
||||
self.write_str("[");
|
||||
f();
|
||||
self.write_str("]");
|
||||
}
|
||||
|
||||
fn emit_vec_elt(idx: uint, f: fn()) {
|
||||
if idx > 0u { self.write_str(", "); }
|
||||
f();
|
||||
}
|
||||
|
||||
fn emit_box(f: fn()) {
|
||||
self.write_str("@");
|
||||
f();
|
||||
}
|
||||
|
||||
fn emit_uniq(f: fn()) {
|
||||
self.write_str("~");
|
||||
f();
|
||||
}
|
||||
|
||||
fn emit_rec(f: fn()) {
|
||||
self.write_str("{");
|
||||
f();
|
||||
self.write_str("}");
|
||||
}
|
||||
|
||||
fn emit_rec_field(f_name: str, f_idx: uint, f: fn()) {
|
||||
if f_idx > 0u { self.write_str(", "); }
|
||||
self.write_str(f_name);
|
||||
self.write_str(": ");
|
||||
f();
|
||||
}
|
||||
|
||||
fn emit_tup(_sz: uint, f: fn()) {
|
||||
self.write_str("(");
|
||||
f();
|
||||
self.write_str(")");
|
||||
}
|
||||
|
||||
fn emit_tup_elt(idx: uint, f: fn()) {
|
||||
if idx > 0u { self.write_str(", "); }
|
||||
f();
|
||||
}
|
||||
}
|
|
@ -1,416 +1,7 @@
|
|||
#[doc = "Support code for serialization."];
|
||||
#[doc = "Support code for serialization.
|
||||
|
||||
Deprecated in favor of core::serialization."];
|
||||
|
||||
use core;
|
||||
import list::list;
|
||||
import ebml::writer;
|
||||
|
||||
// Set to true to generate more debugging in EBML serialization.
|
||||
// Totally lame approach.
|
||||
const debug: bool = true;
|
||||
|
||||
iface serializer {
|
||||
// Primitive types:
|
||||
fn emit_nil();
|
||||
fn emit_uint(v: uint);
|
||||
fn emit_u64(v: u64);
|
||||
fn emit_u32(v: u32);
|
||||
fn emit_u16(v: u16);
|
||||
fn emit_u8(v: u8);
|
||||
fn emit_int(v: int);
|
||||
fn emit_i64(v: i64);
|
||||
fn emit_i32(v: i32);
|
||||
fn emit_i16(v: i16);
|
||||
fn emit_i8(v: i8);
|
||||
fn emit_bool(v: bool);
|
||||
fn emit_float(v: float);
|
||||
fn emit_f64(v: f64);
|
||||
fn emit_f32(v: f32);
|
||||
fn emit_str(v: str);
|
||||
|
||||
// Compound types:
|
||||
fn emit_enum(name: str, f: fn());
|
||||
fn emit_enum_variant(v_name: str, v_id: uint, sz: uint, f: fn());
|
||||
fn emit_enum_variant_arg(idx: uint, f: fn());
|
||||
fn emit_vec(len: uint, f: fn());
|
||||
fn emit_vec_elt(idx: uint, f: fn());
|
||||
fn emit_box(f: fn());
|
||||
fn emit_uniq(f: fn());
|
||||
fn emit_rec(f: fn());
|
||||
fn emit_rec_field(f_name: str, f_idx: uint, f: fn());
|
||||
fn emit_tup(sz: uint, f: fn());
|
||||
fn emit_tup_elt(idx: uint, f: fn());
|
||||
}
|
||||
|
||||
iface deserializer {
|
||||
// Primitive types:
|
||||
fn read_nil() -> ();
|
||||
|
||||
fn read_uint() -> uint;
|
||||
fn read_u64() -> u64;
|
||||
fn read_u32() -> u32;
|
||||
fn read_u16() -> u16;
|
||||
fn read_u8() -> u8;
|
||||
|
||||
fn read_int() -> int;
|
||||
fn read_i64() -> i64;
|
||||
fn read_i32() -> i32;
|
||||
fn read_i16() -> i16;
|
||||
fn read_i8() -> i8;
|
||||
|
||||
|
||||
fn read_bool() -> bool;
|
||||
|
||||
fn read_str() -> str;
|
||||
|
||||
fn read_f64() -> f64;
|
||||
fn read_f32() -> f32;
|
||||
fn read_float() -> float;
|
||||
|
||||
// Compound types:
|
||||
fn read_enum<T:copy>(name: str, f: fn() -> T) -> T;
|
||||
fn read_enum_variant<T:copy>(f: fn(uint) -> T) -> T;
|
||||
fn read_enum_variant_arg<T:copy>(idx: uint, f: fn() -> T) -> T;
|
||||
fn read_vec<T:copy>(f: fn(uint) -> T) -> T;
|
||||
fn read_vec_elt<T:copy>(idx: uint, f: fn() -> T) -> T;
|
||||
fn read_box<T:copy>(f: fn() -> T) -> T;
|
||||
fn read_uniq<T:copy>(f: fn() -> T) -> T;
|
||||
fn read_rec<T:copy>(f: fn() -> T) -> T;
|
||||
fn read_rec_field<T:copy>(f_name: str, f_idx: uint, f: fn() -> T) -> T;
|
||||
fn read_tup<T:copy>(sz: uint, f: fn() -> T) -> T;
|
||||
fn read_tup_elt<T:copy>(idx: uint, f: fn() -> T) -> T;
|
||||
}
|
||||
|
||||
enum ebml_serializer_tag {
|
||||
es_uint, es_u64, es_u32, es_u16, es_u8,
|
||||
es_int, es_i64, es_i32, es_i16, es_i8,
|
||||
es_bool,
|
||||
es_str,
|
||||
es_f64, es_f32, es_float,
|
||||
es_enum, es_enum_vid, es_enum_body,
|
||||
es_vec, es_vec_len, es_vec_elt,
|
||||
|
||||
es_label // Used only when debugging
|
||||
}
|
||||
|
||||
impl of serializer for ebml::writer {
|
||||
fn emit_nil() {}
|
||||
|
||||
// used internally to emit things like the vector length and so on
|
||||
fn _emit_tagged_uint(t: ebml_serializer_tag, v: uint) {
|
||||
assert v <= 0xFFFF_FFFF_u;
|
||||
self.wr_tagged_u32(t as uint, v as u32);
|
||||
}
|
||||
|
||||
fn _emit_label(label: str) {
|
||||
// There are various strings that we have access to, such as
|
||||
// the name of a record field, which do not actually appear in
|
||||
// the serialized EBML (normally). This is just for
|
||||
// efficiency. When debugging, though, we can emit such
|
||||
// labels and then they will be checked by deserializer to
|
||||
// try and check failures more quickly.
|
||||
if debug { self.wr_tagged_str(es_label as uint, label) }
|
||||
}
|
||||
|
||||
fn emit_uint(v: uint) { self.wr_tagged_u64(es_uint as uint, v as u64); }
|
||||
fn emit_u64(v: u64) { self.wr_tagged_u64(es_u64 as uint, v); }
|
||||
fn emit_u32(v: u32) { self.wr_tagged_u32(es_u32 as uint, v); }
|
||||
fn emit_u16(v: u16) { self.wr_tagged_u16(es_u16 as uint, v); }
|
||||
fn emit_u8(v: u8) { self.wr_tagged_u8 (es_u8 as uint, v); }
|
||||
|
||||
fn emit_int(v: int) { self.wr_tagged_i64(es_int as uint, v as i64); }
|
||||
fn emit_i64(v: i64) { self.wr_tagged_i64(es_i64 as uint, v); }
|
||||
fn emit_i32(v: i32) { self.wr_tagged_i32(es_i32 as uint, v); }
|
||||
fn emit_i16(v: i16) { self.wr_tagged_i16(es_i16 as uint, v); }
|
||||
fn emit_i8(v: i8) { self.wr_tagged_i8 (es_i8 as uint, v); }
|
||||
|
||||
fn emit_bool(v: bool) { self.wr_tagged_u8(es_bool as uint, v as u8) }
|
||||
|
||||
fn emit_f64(_v: f64) { fail "TODO"; }
|
||||
fn emit_f32(_v: f32) { fail "TODO"; }
|
||||
fn emit_float(_v: float) { fail "TODO"; }
|
||||
|
||||
fn emit_str(v: str) { self.wr_tagged_str(es_str as uint, v) }
|
||||
|
||||
fn emit_enum(name: str, f: fn()) {
|
||||
self._emit_label(name);
|
||||
self.wr_tag(es_enum as uint, f)
|
||||
}
|
||||
fn emit_enum_variant(_v_name: str, v_id: uint, _cnt: uint, f: fn()) {
|
||||
self._emit_tagged_uint(es_enum_vid, v_id);
|
||||
self.wr_tag(es_enum_body as uint, f)
|
||||
}
|
||||
fn emit_enum_variant_arg(_idx: uint, f: fn()) { f() }
|
||||
|
||||
fn emit_vec(len: uint, f: fn()) {
|
||||
self.wr_tag(es_vec as uint) {||
|
||||
self._emit_tagged_uint(es_vec_len, len);
|
||||
f()
|
||||
}
|
||||
}
|
||||
|
||||
fn emit_vec_elt(_idx: uint, f: fn()) {
|
||||
self.wr_tag(es_vec_elt as uint, f)
|
||||
}
|
||||
|
||||
fn emit_box(f: fn()) { f() }
|
||||
fn emit_uniq(f: fn()) { f() }
|
||||
fn emit_rec(f: fn()) { f() }
|
||||
fn emit_rec_field(f_name: str, _f_idx: uint, f: fn()) {
|
||||
self._emit_label(f_name);
|
||||
f()
|
||||
}
|
||||
fn emit_tup(_sz: uint, f: fn()) { f() }
|
||||
fn emit_tup_elt(_idx: uint, f: fn()) { f() }
|
||||
}
|
||||
|
||||
type ebml_deserializer = {mutable parent: ebml::doc,
|
||||
mutable pos: uint};
|
||||
|
||||
fn ebml_deserializer(d: ebml::doc) -> ebml_deserializer {
|
||||
{mutable parent: d, mutable pos: d.start}
|
||||
}
|
||||
|
||||
impl of deserializer for ebml_deserializer {
|
||||
fn _check_label(lbl: str) {
|
||||
if self.pos < self.parent.end {
|
||||
let {tag: r_tag, doc: r_doc} =
|
||||
ebml::doc_at(self.parent.data, self.pos);
|
||||
if r_tag == (es_label as uint) {
|
||||
self.pos = r_doc.end;
|
||||
let str = ebml::doc_as_str(r_doc);
|
||||
if lbl != str {
|
||||
fail #fmt["Expected label %s but found %s", lbl, str];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn next_doc(exp_tag: ebml_serializer_tag) -> ebml::doc {
|
||||
#debug[". next_doc(exp_tag=%?)", exp_tag];
|
||||
if self.pos >= self.parent.end {
|
||||
fail "no more documents in current node!";
|
||||
}
|
||||
let {tag: r_tag, doc: r_doc} =
|
||||
ebml::doc_at(self.parent.data, self.pos);
|
||||
#debug["self.parent=%?-%? self.pos=%? r_tag=%? r_doc=%?-%?",
|
||||
self.parent.start, self.parent.end, self.pos,
|
||||
r_tag, r_doc.start, r_doc.end];
|
||||
if r_tag != (exp_tag as uint) {
|
||||
fail #fmt["expected EMBL doc with tag %? but found tag %?",
|
||||
exp_tag, r_tag];
|
||||
}
|
||||
if r_doc.end > self.parent.end {
|
||||
fail #fmt["invalid EBML, child extends to 0x%x, parent to 0x%x",
|
||||
r_doc.end, self.parent.end];
|
||||
}
|
||||
self.pos = r_doc.end;
|
||||
ret r_doc;
|
||||
}
|
||||
|
||||
fn push_doc<T: copy>(d: ebml::doc, f: fn() -> T) -> T{
|
||||
let old_parent = self.parent;
|
||||
let old_pos = self.pos;
|
||||
self.parent = d;
|
||||
self.pos = d.start;
|
||||
let r = f();
|
||||
self.parent = old_parent;
|
||||
self.pos = old_pos;
|
||||
ret r;
|
||||
}
|
||||
|
||||
fn _next_uint(exp_tag: ebml_serializer_tag) -> uint {
|
||||
let r = ebml::doc_as_u32(self.next_doc(exp_tag));
|
||||
#debug["_next_uint exp_tag=%? result=%?", exp_tag, r];
|
||||
ret r as uint;
|
||||
}
|
||||
|
||||
fn read_nil() -> () { () }
|
||||
|
||||
fn read_u64() -> u64 { ebml::doc_as_u64(self.next_doc(es_u64)) }
|
||||
fn read_u32() -> u32 { ebml::doc_as_u32(self.next_doc(es_u32)) }
|
||||
fn read_u16() -> u16 { ebml::doc_as_u16(self.next_doc(es_u16)) }
|
||||
fn read_u8 () -> u8 { ebml::doc_as_u8 (self.next_doc(es_u8 )) }
|
||||
fn read_uint() -> uint {
|
||||
let v = ebml::doc_as_u64(self.next_doc(es_uint));
|
||||
if v > (uint::max_value as u64) {
|
||||
fail #fmt["uint %? too large for this architecture", v];
|
||||
}
|
||||
ret v as uint;
|
||||
}
|
||||
|
||||
fn read_i64() -> i64 { ebml::doc_as_u64(self.next_doc(es_i64)) as i64 }
|
||||
fn read_i32() -> i32 { ebml::doc_as_u32(self.next_doc(es_i32)) as i32 }
|
||||
fn read_i16() -> i16 { ebml::doc_as_u16(self.next_doc(es_i16)) as i16 }
|
||||
fn read_i8 () -> i8 { ebml::doc_as_u8 (self.next_doc(es_i8 )) as i8 }
|
||||
fn read_int() -> int {
|
||||
let v = ebml::doc_as_u64(self.next_doc(es_int)) as i64;
|
||||
if v > (int::max_value as i64) || v < (int::min_value as i64) {
|
||||
fail #fmt["int %? out of range for this architecture", v];
|
||||
}
|
||||
ret v as int;
|
||||
}
|
||||
|
||||
fn read_bool() -> bool { ebml::doc_as_u8(self.next_doc(es_bool)) as bool }
|
||||
|
||||
fn read_f64() -> f64 { fail "read_f64()"; }
|
||||
fn read_f32() -> f32 { fail "read_f32()"; }
|
||||
fn read_float() -> float { fail "read_float()"; }
|
||||
|
||||
fn read_str() -> str { ebml::doc_as_str(self.next_doc(es_str)) }
|
||||
|
||||
// Compound types:
|
||||
fn read_enum<T:copy>(name: str, f: fn() -> T) -> T {
|
||||
#debug["read_enum(%s)", name];
|
||||
self._check_label(name);
|
||||
self.push_doc(self.next_doc(es_enum), f)
|
||||
}
|
||||
|
||||
fn read_enum_variant<T:copy>(f: fn(uint) -> T) -> T {
|
||||
#debug["read_enum_variant()"];
|
||||
let idx = self._next_uint(es_enum_vid);
|
||||
#debug[" idx=%u", idx];
|
||||
self.push_doc(self.next_doc(es_enum_body)) {||
|
||||
f(idx)
|
||||
}
|
||||
}
|
||||
|
||||
fn read_enum_variant_arg<T:copy>(idx: uint, f: fn() -> T) -> T {
|
||||
#debug["read_enum_variant_arg(idx=%u)", idx];
|
||||
f()
|
||||
}
|
||||
|
||||
fn read_vec<T:copy>(f: fn(uint) -> T) -> T {
|
||||
#debug["read_vec()"];
|
||||
self.push_doc(self.next_doc(es_vec)) {||
|
||||
let len = self._next_uint(es_vec_len);
|
||||
#debug[" len=%u", len];
|
||||
f(len)
|
||||
}
|
||||
}
|
||||
|
||||
fn read_vec_elt<T:copy>(idx: uint, f: fn() -> T) -> T {
|
||||
#debug["read_vec_elt(idx=%u)", idx];
|
||||
self.push_doc(self.next_doc(es_vec_elt), f)
|
||||
}
|
||||
|
||||
fn read_box<T:copy>(f: fn() -> T) -> T {
|
||||
#debug["read_box()"];
|
||||
f()
|
||||
}
|
||||
|
||||
fn read_uniq<T:copy>(f: fn() -> T) -> T {
|
||||
#debug["read_uniq()"];
|
||||
f()
|
||||
}
|
||||
|
||||
fn read_rec<T:copy>(f: fn() -> T) -> T {
|
||||
#debug["read_rec()"];
|
||||
f()
|
||||
}
|
||||
|
||||
fn read_rec_field<T:copy>(f_name: str, f_idx: uint, f: fn() -> T) -> T {
|
||||
#debug["read_rec_field(%s, idx=%u)", f_name, f_idx];
|
||||
self._check_label(f_name);
|
||||
f()
|
||||
}
|
||||
|
||||
fn read_tup<T:copy>(sz: uint, f: fn() -> T) -> T {
|
||||
#debug["read_tup(sz=%u)", sz];
|
||||
f()
|
||||
}
|
||||
|
||||
fn read_tup_elt<T:copy>(idx: uint, f: fn() -> T) -> T {
|
||||
#debug["read_tup_elt(idx=%u)", idx];
|
||||
f()
|
||||
}
|
||||
}
|
||||
|
||||
// ___________________________________________________________________________
|
||||
// Helper routines
|
||||
//
|
||||
// These should eventually be coded as traits.
|
||||
|
||||
impl serializer_helpers<S: serializer> for S {
|
||||
fn emit_from_vec<T>(v: [T], f: fn(T)) {
|
||||
self.emit_vec(vec::len(v)) {||
|
||||
vec::iteri(v) {|i,e|
|
||||
self.emit_vec_elt(i) {||
|
||||
f(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl deserializer_helpers<D: deserializer> for D {
|
||||
fn read_to_vec<T>(f: fn() -> T) -> [T] {
|
||||
self.read_vec {|len|
|
||||
let v = [];
|
||||
vec::reserve(v, len);
|
||||
uint::range(0u, len) {|i|
|
||||
self.read_vec_elt(i) {|| v += [f()] }
|
||||
}
|
||||
v
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ___________________________________________________________________________
|
||||
// Testing
|
||||
|
||||
#[test]
|
||||
fn test_option_int() {
|
||||
fn serialize_1<S: serializer>(s: S, v: int) {
|
||||
s.emit_i64(v as i64);
|
||||
}
|
||||
|
||||
fn serialize_0<S: serializer>(s: S, v: option<int>) {
|
||||
s.emit_enum("core::option::t") {||
|
||||
alt v {
|
||||
none {
|
||||
s.emit_enum_variant("core::option::none", 0u, 0u) {||}
|
||||
}
|
||||
some(v0) {
|
||||
s.emit_enum_variant("core::option::some", 1u, 1u) {||
|
||||
s.emit_enum_variant_arg(0u) {|| serialize_1(s, v0) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn deserialize_1<S: deserializer>(s: S) -> int {
|
||||
s.read_i64() as int
|
||||
}
|
||||
|
||||
fn deserialize_0<S: deserializer>(s: S) -> option<int> {
|
||||
s.read_enum("core::option::t") {||
|
||||
s.read_enum_variant {|i|
|
||||
alt check i {
|
||||
0u { none }
|
||||
1u {
|
||||
let v0 = s.read_enum_variant_arg(0u) {||
|
||||
deserialize_1(s)
|
||||
};
|
||||
some(v0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn test_v(v: option<int>) {
|
||||
#debug["v == %?", v];
|
||||
let mbuf = io::mk_mem_buffer();
|
||||
let ebml_w = ebml::writer(io::mem_buffer_writer(mbuf));
|
||||
serialize_0(ebml_w, v);
|
||||
let ebml_doc = ebml::new_doc(@io::mem_buffer_buf(mbuf));
|
||||
let deser = ebml_deserializer(ebml_doc);
|
||||
let v1 = deserialize_0(deser);
|
||||
#debug["v1 == %?", v1];
|
||||
assert v == v1;
|
||||
}
|
||||
|
||||
test_v(some(22));
|
||||
test_v(none);
|
||||
test_v(some(3));
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ export net, uv;
|
|||
export c_vec, four, tri, util;
|
||||
export bitv, deque, fun_treemap, list, map, smallintmap, sort, treemap, ufind;
|
||||
export rope;
|
||||
export ebml, dbg, getopts, json, rand, sha1, term, time;
|
||||
export ebml, dbg, getopts, json, rand, sha1, term, time, prettyprint;
|
||||
export test, tempfile, serialization;
|
||||
|
||||
|
||||
|
@ -55,6 +55,7 @@ mod md4;
|
|||
mod tempfile;
|
||||
mod term;
|
||||
mod time;
|
||||
mod prettyprint;
|
||||
|
||||
#[cfg(unicode)]
|
||||
mod unicode;
|
||||
|
|
|
@ -15,7 +15,8 @@ import io::{reader_util, writer_util};
|
|||
import getopts::{optopt, optmulti, optflag, optflagopt, opt_present};
|
||||
import back::{x86, x86_64};
|
||||
|
||||
enum pp_mode { ppm_normal, ppm_expanded, ppm_typed, ppm_identified, }
|
||||
enum pp_mode {ppm_normal, ppm_expanded, ppm_typed, ppm_identified,
|
||||
ppm_expanded_identified }
|
||||
|
||||
fn default_configuration(sess: session, argv0: str, input: str) ->
|
||||
ast::crate_cfg {
|
||||
|
@ -253,7 +254,7 @@ fn pretty_print_input(sess: session, cfg: ast::crate_cfg, input: str,
|
|||
// from stdin, we're going to just suck the source into a string
|
||||
// so both the parser and pretty-printer can use it.
|
||||
let upto = alt ppm {
|
||||
ppm_expanded { cu_expand }
|
||||
ppm_expanded | ppm_expanded_identified { cu_expand }
|
||||
ppm_typed { cu_typeck }
|
||||
_ { cu_parse }
|
||||
};
|
||||
|
@ -265,7 +266,7 @@ fn pretty_print_input(sess: session, cfg: ast::crate_cfg, input: str,
|
|||
ann = {pre: ann_paren_for_expr,
|
||||
post: bind ann_typed_post(option::get(tcx), _)};
|
||||
}
|
||||
ppm_identified {
|
||||
ppm_identified | ppm_expanded_identified {
|
||||
ann = {pre: ann_paren_for_expr, post: ann_identified_post};
|
||||
}
|
||||
ppm_expanded | ppm_normal {}
|
||||
|
@ -498,7 +499,11 @@ fn parse_pretty(sess: session, &&name: str) -> pp_mode {
|
|||
ret ppm_expanded;
|
||||
} else if str::eq(name, "typed") {
|
||||
ret ppm_typed;
|
||||
} else if str::eq(name, "identified") { ret ppm_identified; }
|
||||
} else if str::eq(name, "expanded,identified") {
|
||||
ret ppm_expanded_identified;
|
||||
} else if str::eq(name, "identified") {
|
||||
ret ppm_identified;
|
||||
}
|
||||
sess.fatal("argument to `pretty` must be one of `normal`, `typed`, or " +
|
||||
"`identified`");
|
||||
}
|
||||
|
|
|
@ -6,12 +6,13 @@ import syntax::ast_util::inlined_item_methods;
|
|||
import syntax::codemap::span;
|
||||
import std::ebml;
|
||||
import std::ebml::writer;
|
||||
import std::ebml::serializer;
|
||||
import std::ebml::deserializer;
|
||||
import std::map::hashmap;
|
||||
import std::serialization;
|
||||
import std::serialization::serializer;
|
||||
import std::serialization::deserializer;
|
||||
import std::serialization::serializer_helpers;
|
||||
import std::serialization::deserializer_helpers;
|
||||
import serialization::serializer;
|
||||
import serialization::deserializer;
|
||||
import serialization::serializer_helpers;
|
||||
import serialization::deserializer_helpers;
|
||||
import std::smallintmap::map;
|
||||
import middle::trans::common::maps;
|
||||
import middle::{ty, typeck, last_use, ast_map};
|
||||
|
@ -243,7 +244,7 @@ fn encode_id_range(ebml_w: ebml::writer, id_range: id_range) {
|
|||
|
||||
fn decode_id_range(par_doc: ebml::doc) -> id_range {
|
||||
let range_doc = par_doc[c::tag_id_range];
|
||||
let dsr = serialization::ebml_deserializer(range_doc);
|
||||
let dsr = ebml::ebml_deserializer(range_doc);
|
||||
dsr.read_tup(2u) {||
|
||||
{min: dsr.read_tup_elt(0u) {|| dsr.read_int() },
|
||||
max: dsr.read_tup_elt(1u) {|| dsr.read_int() }}
|
||||
|
@ -368,7 +369,7 @@ fn simplify_ast(ii: ast::inlined_item) -> ast::inlined_item {
|
|||
|
||||
fn decode_ast(par_doc: ebml::doc) -> ast::inlined_item {
|
||||
let chi_doc = par_doc[c::tag_tree];
|
||||
let d = serialization::ebml_deserializer(chi_doc);
|
||||
let d = ebml::ebml_deserializer(chi_doc);
|
||||
astencode_gen::deserialize_syntax_ast_inlined_item(d)
|
||||
}
|
||||
|
||||
|
@ -398,7 +399,7 @@ fn encode_def(ebml_w: ebml::writer, def: ast::def) {
|
|||
}
|
||||
|
||||
fn decode_def(xcx: extended_decode_ctxt, doc: ebml::doc) -> ast::def {
|
||||
let dsr = serialization::ebml_deserializer(doc);
|
||||
let dsr = ebml::ebml_deserializer(doc);
|
||||
let def = astencode_gen::deserialize_syntax_ast_def(dsr);
|
||||
def.tr(xcx)
|
||||
}
|
||||
|
@ -445,7 +446,7 @@ fn encode_freevar_entry(ebml_w: ebml::writer, fv: freevar_entry) {
|
|||
astencode_gen::serialize_middle_freevars_freevar_entry(ebml_w, fv)
|
||||
}
|
||||
|
||||
impl helper for serialization::ebml_deserializer {
|
||||
impl helper for ebml::ebml_deserializer {
|
||||
fn read_freevar_entry(xcx: extended_decode_ctxt) -> freevar_entry {
|
||||
let fv =
|
||||
astencode_gen::deserialize_middle_freevars_freevar_entry(self);
|
||||
|
@ -466,7 +467,7 @@ fn encode_method_origin(ebml_w: ebml::writer, mo: method_origin) {
|
|||
astencode_gen::serialize_middle_typeck_method_origin(ebml_w, mo)
|
||||
}
|
||||
|
||||
impl helper for serialization::ebml_deserializer {
|
||||
impl helper for ebml::ebml_deserializer {
|
||||
fn read_method_origin(xcx: extended_decode_ctxt) -> method_origin {
|
||||
let fv = astencode_gen::deserialize_middle_typeck_method_origin(self);
|
||||
fv.tr(xcx)
|
||||
|
@ -559,7 +560,7 @@ fn encode_dict_origin(ecx: @e::encode_ctxt,
|
|||
|
||||
}
|
||||
|
||||
impl helpers for serialization::ebml_deserializer {
|
||||
impl helpers for ebml::ebml_deserializer {
|
||||
fn read_dict_res(xcx: extended_decode_ctxt) -> typeck::dict_res {
|
||||
@self.read_to_vec {|| self.read_dict_origin(xcx) }
|
||||
}
|
||||
|
@ -800,7 +801,7 @@ impl decoder for ebml::doc {
|
|||
}
|
||||
}
|
||||
|
||||
impl decoder for serialization::ebml_deserializer {
|
||||
impl decoder for ebml::ebml_deserializer {
|
||||
fn read_ty(xcx: extended_decode_ctxt) -> ty::t {
|
||||
tydecode::parse_ty_data(
|
||||
self.parent.data, xcx.dcx.cdata.cnum, self.pos, xcx.dcx.tcx,
|
||||
|
@ -850,7 +851,7 @@ fn decode_side_tables(xcx: extended_decode_ctxt,
|
|||
dcx.maps.copy_map.insert(id, ());
|
||||
} else {
|
||||
let val_doc = entry_doc[c::tag_table_val];
|
||||
let val_dsr = serialization::ebml_deserializer(val_doc);
|
||||
let val_dsr = ebml::ebml_deserializer(val_doc);
|
||||
if tag == (c::tag_table_def as uint) {
|
||||
let def = decode_def(xcx, val_doc);
|
||||
dcx.tcx.def_map.insert(id, def);
|
||||
|
@ -903,7 +904,7 @@ fn encode_item_ast(ebml_w: ebml::writer, item: @ast::item) {
|
|||
#[cfg(test)]
|
||||
fn decode_item_ast(par_doc: ebml::doc) -> @ast::item {
|
||||
let chi_doc = par_doc[c::tag_tree];
|
||||
let d = serialization::ebml_deserializer(chi_doc);
|
||||
let d = ebml::ebml_deserializer(chi_doc);
|
||||
@astencode_gen::deserialize_syntax_ast_item(d)
|
||||
}
|
||||
|
||||
|
|
|
@ -306,6 +306,9 @@ fn ast_ty_to_ty(tcx: ty::ctxt, mode: mode, &&ast_ty: @ast::ty) -> ty::t {
|
|||
for ast_ty: @ast::ty in args {
|
||||
param_bindings += [do_ast_ty_to_ty(tcx, use_site, mode, ast_ty)];
|
||||
}
|
||||
#debug("substituting(%s into %s)",
|
||||
str::concat(vec::map(param_bindings, {|t| ty_to_str(tcx, t)})),
|
||||
ty_to_str(tcx, ty_param_bounds_and_ty.ty));
|
||||
let typ =
|
||||
ty::substitute_type_params(tcx, param_bindings,
|
||||
ty_param_bounds_and_ty.ty);
|
||||
|
|
|
@ -82,26 +82,39 @@ import base::*;
|
|||
import driver::session::session;
|
||||
import codemap::span;
|
||||
import std::map;
|
||||
import std::map::hashmap;
|
||||
import front::attr;
|
||||
|
||||
export expand_auto_serialize;
|
||||
export expand;
|
||||
|
||||
enum ser_cx = {
|
||||
enum ser_cx = @{
|
||||
ext_cx: ext_ctxt,
|
||||
tps: map::map<str, fn@(@ast::expr) -> [@ast::stmt]>
|
||||
tps: map::hashmap<str, fn@(@ast::expr) -> [@ast::stmt]>
|
||||
};
|
||||
|
||||
fn expand_auto_serialize(cx: ext_ctxt,
|
||||
fn expand(cx: ext_ctxt,
|
||||
span: span,
|
||||
_mitem: ast::meta_item,
|
||||
in_items: [@ast::item]) -> [@ast::item] {
|
||||
fn not_auto_serialize(a: ast::attribute) -> bool {
|
||||
attr::get_attr_name(a) != "auto_serialize"
|
||||
}
|
||||
|
||||
fn filter_attrs(item: @ast::item) -> @ast::item {
|
||||
@{attrs: vec::filter(item.attrs, not_auto_serialize)
|
||||
with *item}
|
||||
}
|
||||
|
||||
vec::flat_map(in_items) {|in_item|
|
||||
alt in_item.node {
|
||||
ast::item_ty(ty, tps) {
|
||||
[in_item, ty_module(cx, in_item.ident, copy ty, tps)]
|
||||
[filter_attrs(in_item),
|
||||
ty_module(cx, in_item.ident, ty, tps)]
|
||||
}
|
||||
|
||||
ast::item_enum(variants, tps) {
|
||||
[in_item, enum_module(cx, in_item.ident, variants, tps)]
|
||||
[filter_attrs(in_item),
|
||||
enum_module(cx, in_item.ident, in_item.span, variants, tps)]
|
||||
}
|
||||
|
||||
_ {
|
||||
|
@ -118,9 +131,7 @@ impl helpers for ext_ctxt {
|
|||
fn next_id() -> ast::node_id { self.session().next_node_id() }
|
||||
|
||||
fn path(span: span, strs: [str]) -> @ast::path {
|
||||
@{node: {global: false,
|
||||
idents: strs + ["serialize"],
|
||||
types: []},
|
||||
@{node: {global: false, idents: strs, types: []},
|
||||
span: span}
|
||||
}
|
||||
|
||||
|
@ -140,6 +151,28 @@ impl helpers for ser_cx {
|
|||
self.ext_cx.ty_path(span, strs)
|
||||
}
|
||||
|
||||
fn ty_fn(span: span,
|
||||
-input_tys: [@ast::ty],
|
||||
-output: @ast::ty) -> @ast::ty {
|
||||
let args = vec::map(input_tys) {|ty|
|
||||
{mode: ast::expl(ast::by_ref),
|
||||
ty: ty,
|
||||
ident: "",
|
||||
id: self.next_id()}
|
||||
};
|
||||
|
||||
@{node: ast::ty_fn(ast::proto_any, {inputs: args,
|
||||
output: output,
|
||||
purity: ast::impure_fn,
|
||||
cf: ast::return_val,
|
||||
constraints: []}),
|
||||
span: span}
|
||||
}
|
||||
|
||||
fn ty_nil(span: span) -> @ast::ty {
|
||||
@{node: ast::ty_nil, span: span}
|
||||
}
|
||||
|
||||
fn expr(span: span, node: ast::expr_) -> @ast::expr {
|
||||
@{id: self.next_id(), node: node, span: span}
|
||||
}
|
||||
|
@ -195,8 +228,9 @@ impl helpers for ser_cx {
|
|||
span: span}))
|
||||
}
|
||||
|
||||
fn lambda(-blk: @ast::blk) -> @ast::expr {
|
||||
let blk_e = cx.expr(blk.span, expr_block(blk));
|
||||
fn lambda(blk: ast::blk) -> @ast::expr {
|
||||
let ext_cx = self;
|
||||
let blk_e = self.expr(blk.span, ast::expr_block(blk));
|
||||
#ast(expr){{|| $(blk_e) }}
|
||||
}
|
||||
|
||||
|
@ -208,6 +242,14 @@ impl helpers for ser_cx {
|
|||
fld.fold_expr(v)
|
||||
}
|
||||
|
||||
fn clone_ty(v: @ast::ty) -> @ast::ty {
|
||||
let fld = fold::make_fold({
|
||||
new_id: {|_id| self.next_id()}
|
||||
with *fold::default_ast_fold()
|
||||
});
|
||||
fld.fold_ty(v)
|
||||
}
|
||||
|
||||
fn clone_ty_param(v: ast::ty_param) -> ast::ty_param {
|
||||
let fld = fold::make_fold({
|
||||
new_id: {|_id| self.next_id()}
|
||||
|
@ -249,14 +291,17 @@ fn serialize_path(cx: ser_cx, path: @ast::path,
|
|||
cx.path(path.span, path.node.idents + ["serialize"])));
|
||||
|
||||
let ty_args = vec::map(path.node.types) {|ty|
|
||||
let sv = serialize_ty(cx, ty, s, #ast(expr){"__v"});
|
||||
cx.at(ty.span, #ast(expr){"{|__v| $(sv)}"})
|
||||
let sv_stmts = serialize_ty(cx, ty, cx.clone(s), #ast(expr){__v});
|
||||
let sv = cx.expr(path.span,
|
||||
ast::expr_block(cx.blk(path.span,
|
||||
sv_stmts)));
|
||||
cx.at(ty.span, #ast(expr){{|__v| $(sv)}})
|
||||
};
|
||||
|
||||
[cx.stmt(
|
||||
cx.expr(
|
||||
path.span,
|
||||
ast::expr_call(callee, [s] + ty_args + [v], false)))]
|
||||
ast::expr_call(callee, [s, v] + ty_args, false)))]
|
||||
}
|
||||
|
||||
fn serialize_variant(cx: ser_cx,
|
||||
|
@ -264,8 +309,8 @@ fn serialize_variant(cx: ser_cx,
|
|||
span: span,
|
||||
-s: @ast::expr,
|
||||
pfn: fn([@ast::pat]) -> ast::pat_,
|
||||
bodyfn: fn(-@ast::expr, @ast::blk) -> @ast::expr,
|
||||
argfn: fn(-@ast::expr, uint, @ast::blk) -> @ast::expr)
|
||||
bodyfn: fn(-@ast::expr, ast::blk) -> @ast::expr,
|
||||
argfn: fn(-@ast::expr, uint, ast::blk) -> @ast::expr)
|
||||
-> ast::arm {
|
||||
let vnames = vec::init_fn(vec::len(tys)) {|i| #fmt["__v%u", i]};
|
||||
let pats = vec::init_fn(vec::len(tys)) {|i|
|
||||
|
@ -281,7 +326,7 @@ fn serialize_variant(cx: ser_cx,
|
|||
cx.stmt(argfn(cx.clone(s), i, arg_blk))
|
||||
};
|
||||
|
||||
let body_blk = cx.blk(span, vec::concat(stmts));
|
||||
let body_blk = cx.blk(span, stmts);
|
||||
let body = cx.blk(span, [cx.stmt(bodyfn(s, body_blk))]);
|
||||
|
||||
{pats: [pat], guard: none, body: body}
|
||||
|
@ -289,6 +334,13 @@ fn serialize_variant(cx: ser_cx,
|
|||
|
||||
fn serialize_ty(cx: ser_cx, ty: @ast::ty, -s: @ast::expr, -v: @ast::expr)
|
||||
-> [@ast::stmt] {
|
||||
|
||||
fn ty_lambda(cx: ser_cx, ty: @ast::ty, -s: @ast::expr, -v: @ast::expr)
|
||||
-> @ast::expr {
|
||||
cx.lambda(cx.blk(ty.span, serialize_ty(cx, ty, s, v)))
|
||||
}
|
||||
|
||||
|
||||
let ext_cx = cx.ext_cx;
|
||||
|
||||
alt ty.node {
|
||||
|
@ -296,19 +348,37 @@ fn serialize_ty(cx: ser_cx, ty: @ast::ty, -s: @ast::expr, -v: @ast::expr)
|
|||
[]
|
||||
}
|
||||
|
||||
ast::ty_box(mt) |
|
||||
ast::ty_uniq(mt) |
|
||||
ast::ty_ptr(mt) {
|
||||
serialize_ty(cx, mt.ty, s, #ast(expr){"*$(v)"})
|
||||
ast::ty_box(mt) {
|
||||
let l = ty_lambda(cx, mt.ty, cx.clone(s), #ast(expr){*$(v)});
|
||||
[#ast(stmt){$(s).emit_box($(l));}]
|
||||
}
|
||||
|
||||
ast::ty_uniq(mt) {
|
||||
let l = ty_lambda(cx, mt.ty, cx.clone(s), #ast(expr){*$(v)});
|
||||
[#ast(stmt){$(s).emit_uniq($(l));}]
|
||||
}
|
||||
|
||||
ast::ty_ptr(_) | ast::ty_rptr(_, _) {
|
||||
cx.session().span_err(
|
||||
ty.span, #fmt["Cannot serialize pointer types"]);
|
||||
[]
|
||||
}
|
||||
|
||||
ast::ty_rec(flds) {
|
||||
vec::flat_map(flds) {|fld|
|
||||
let vf = cx.expr(
|
||||
fld.span,
|
||||
ast::expr_field(cx.clone(v), fld.node.ident, []));
|
||||
serialize_ty(cx, fld.node.mt.ty, cx.clone(s), vf)
|
||||
}
|
||||
let fld_stmts = vec::init_fn(vec::len(flds)) {|fidx|
|
||||
let fld = flds[fidx];
|
||||
let vf = cx.expr(fld.span,
|
||||
ast::expr_field(cx.clone(v),
|
||||
fld.node.ident,
|
||||
[]));
|
||||
let s = cx.clone(s);
|
||||
let f = cx.lit_str(fld.span, fld.node.ident);
|
||||
let i = cx.lit_uint(fld.span, fidx);
|
||||
let l = ty_lambda(cx, fld.node.mt.ty, cx.clone(s), vf);
|
||||
#ast(stmt){$(s).emit_rec_field($(f), $(i), $(l));}
|
||||
};
|
||||
let fld_lambda = cx.lambda(cx.blk(ty.span, fld_stmts));
|
||||
[#ast(stmt){$(s).emit_rec($(fld_lambda));}]
|
||||
}
|
||||
|
||||
ast::ty_fn(_, _) {
|
||||
|
@ -335,7 +405,7 @@ fn serialize_ty(cx: ser_cx, ty: @ast::ty, -s: @ast::expr, -v: @ast::expr)
|
|||
{|pats| ast::pat_tup(pats)},
|
||||
|
||||
// Generate body s.emit_tup(3, {|| blk })
|
||||
{|-s, -blk|
|
||||
{|-s, blk|
|
||||
let sz = cx.lit_uint(ty.span, vec::len(tys));
|
||||
let body = cx.lambda(blk);
|
||||
#ast[expr]{
|
||||
|
@ -344,7 +414,7 @@ fn serialize_ty(cx: ser_cx, ty: @ast::ty, -s: @ast::expr, -v: @ast::expr)
|
|||
},
|
||||
|
||||
// Generate s.emit_tup_elt(i, {|| blk })
|
||||
{|-s, i, -blk|
|
||||
{|-s, i, blk|
|
||||
let idx = cx.lit_uint(ty.span, i);
|
||||
let body = cx.lambda(blk);
|
||||
#ast[expr]{
|
||||
|
@ -399,57 +469,55 @@ fn serialize_ty(cx: ser_cx, ty: @ast::ty, -s: @ast::expr, -v: @ast::expr)
|
|||
ty.span,
|
||||
#ast(expr){__e})))));
|
||||
|
||||
[cx.stmt(
|
||||
cx.expr(
|
||||
ty.span,
|
||||
ast::expr_call(
|
||||
#ast(expr){$(s).emit_from_vec},
|
||||
[#ast(expr){{|__e| $(ser_e)}}],
|
||||
false)))]
|
||||
[#ast(stmt){
|
||||
core::serialization::emit_from_vec($(s), $(v), {|__e| $(ser_e) })
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn mk_ser_fn(ext_cx: ext_ctxt, span: span,
|
||||
-v_ty: @ast::ty, tps: [ast::ty_param],
|
||||
v_ty: @ast::ty, tps: [ast::ty_param],
|
||||
f: fn(ser_cx, @ast::ty, -@ast::expr, -@ast::expr) -> [@ast::stmt])
|
||||
-> @ast::item {
|
||||
|
||||
let cx = ser_cx({ext_cx: ext_cx, tps: map::new_str_hash()});
|
||||
let cx = ser_cx(@{ext_cx: ext_cx, tps: map::new_str_hash()});
|
||||
|
||||
let tp_inputs =
|
||||
vec::map(tps, {|tp|
|
||||
{mode: ast::expl(ast::by_ref),
|
||||
ty: cx.ty_path(span, [tp.ident]),
|
||||
ty: cx.ty_fn(span,
|
||||
[cx.ty_path(span, [tp.ident])],
|
||||
cx.ty_nil(span)),
|
||||
ident: "__s" + tp.ident,
|
||||
id: cx.next_id()}});
|
||||
|
||||
#debug["tp_inputs = %?", tp_inputs];
|
||||
|
||||
let ser_inputs: [ast::arg] =
|
||||
[{mode: ast::expl(ast::by_ref),
|
||||
ty: cx.ty_path(span, ["__S"]),
|
||||
ident: "__s",
|
||||
id: cx.next_id()},
|
||||
{mode: ast::expl(ast::by_ref),
|
||||
ty: v_ty,
|
||||
ty: cx.clone_ty(v_ty),
|
||||
ident: "__v",
|
||||
id: cx.next_id()}]
|
||||
+ tp_inputs;
|
||||
|
||||
vec::iter2(tps, ser_inputs) {|tp, arg|
|
||||
vec::iter2(tps, tp_inputs) {|tp, arg|
|
||||
let arg_ident = arg.ident;
|
||||
cx.tps.insert(
|
||||
tp.ident,
|
||||
fn@(v: @ast::expr) -> [@ast::stmt] {
|
||||
let f = cx.var_ref(span, arg_ident);
|
||||
[cx.stmt(
|
||||
cx.expr(
|
||||
span,
|
||||
ast::expr_call(f, [v], false)))]
|
||||
#debug["serializing type arg %s", arg_ident];
|
||||
[#ast(stmt){$(f)($(v));}]
|
||||
});
|
||||
}
|
||||
|
||||
let ser_bnds = @[ast::bound_iface(cx.ty_path(span,
|
||||
["__std", "serialization",
|
||||
["serialization",
|
||||
"serializer"]))];
|
||||
|
||||
let ser_tps: [ast::ty_param] =
|
||||
|
@ -462,7 +530,7 @@ fn mk_ser_fn(ext_cx: ext_ctxt, span: span,
|
|||
span: span};
|
||||
|
||||
let ser_blk = cx.blk(span,
|
||||
f(cx, v_ty, #ast(expr){"__s"}, #ast(expr){"__v"}));
|
||||
f(cx, v_ty, #ast(expr){__s}, #ast(expr){__v}));
|
||||
|
||||
@{ident: "serialize",
|
||||
attrs: [],
|
||||
|
@ -477,7 +545,7 @@ fn mk_ser_fn(ext_cx: ext_ctxt, span: span,
|
|||
span: span}
|
||||
}
|
||||
|
||||
fn ty_module(ext_cx: ext_ctxt, name: str, -ty: @ast::ty, tps: [ast::ty_param])
|
||||
fn ty_module(ext_cx: ext_ctxt, name: str, ty: @ast::ty, tps: [ast::ty_param])
|
||||
-> @ast::item {
|
||||
|
||||
let span = ty.span;
|
||||
|
@ -497,62 +565,51 @@ fn enum_module(ext_cx: ext_ctxt, name: str, span: span,
|
|||
variants: [ast::variant], tps: [ast::ty_param])
|
||||
-> @ast::item {
|
||||
|
||||
let span = ty.span;
|
||||
let ty = ext_cx.ty_path(span, [name]);
|
||||
let ser_fn = mk_ser_fn(ext_cx, span, ty, tps) {|cx, ty, s, v|
|
||||
let arms = vec::init_fn(vec::len(variants)) {|vidx|
|
||||
let ser_fn = mk_ser_fn(ext_cx, span, ty, tps) {|cx, _ty, s, v|
|
||||
let arms = vec::init_fn(
|
||||
vec::len(variants),
|
||||
fn&(vidx: uint) -> ast::arm {
|
||||
let variant = variants[vidx];
|
||||
|
||||
if vec::is_empty(variant.args) {
|
||||
// degenerate case.
|
||||
let pat = {id: cx.next_id(),
|
||||
node: ast::pat_ident(cx.path(variant.ident), none),
|
||||
Span: variant.span};
|
||||
//#ast(expr){
|
||||
// $(s).emit_enum_variant(X, Y, SZ) {||
|
||||
// };
|
||||
//}
|
||||
}
|
||||
|
||||
let variant_tys = vec::map(variant.args) {|a| a.ty };
|
||||
let span = variant.span;
|
||||
let name = variant.node.name;
|
||||
let variant_tys = vec::map(variant.node.args) {|a| a.ty };
|
||||
|
||||
serialize_variant(
|
||||
cx, variant_tys, variant.span, cx.clone(s),
|
||||
cx, variant_tys, span, cx.clone(s),
|
||||
|
||||
// Generate pattern var(v1, v2, v3)
|
||||
{|pats|
|
||||
let pat = {id: cx.next_id(),
|
||||
node: ast::pat_enum(cx.path(variant.ident)),
|
||||
span: variant.span};
|
||||
|
||||
{id: cx.next_id(),
|
||||
node: expr_call(s, [v_name,
|
||||
v_id,
|
||||
sz,
|
||||
f], false),
|
||||
span: variant.span}
|
||||
if vec::is_empty(pats) {
|
||||
ast::pat_ident(cx.path(span, [name]), none)
|
||||
} else {
|
||||
ast::pat_enum(cx.path(span, [name]), pats)
|
||||
}
|
||||
},
|
||||
|
||||
// Generate body s.emit_enum_variant("foo", 0u, 3u, {|| blk })
|
||||
{|-s, -blk|
|
||||
let v_name = cx.lit_str(variant.span, variant.ident);
|
||||
let v_id = cx.lit_uint(variant.span, vidx);
|
||||
let sz = cx.lit_uint(variant.span, vec::len(variant_tys));
|
||||
// Generate body s.emit_enum_variant("foo", 0u,
|
||||
// 3u, {|| blk })
|
||||
{|-s, blk|
|
||||
let v_name = cx.lit_str(span, name);
|
||||
let v_id = cx.lit_uint(span, vidx);
|
||||
let sz = cx.lit_uint(span, vec::len(variant_tys));
|
||||
let body = cx.lambda(blk);
|
||||
#ast[expr]{
|
||||
$(s).emit_enum_variant($(v_name), $(v_id), $(sz), $(body))
|
||||
$(s).emit_enum_variant($(v_name), $(v_id),
|
||||
$(sz), $(body))
|
||||
}
|
||||
},
|
||||
|
||||
// Generate s.emit_enum_variant_arg(i, {|| blk })
|
||||
{|-s, i, -blk|
|
||||
let idx = cx.lit_uint(i);
|
||||
{|-s, i, blk|
|
||||
let idx = cx.lit_uint(span, i);
|
||||
let body = cx.lambda(blk);
|
||||
#ast[expr]{
|
||||
$(s).emit_enum_variant_arg($(idx), $(body))
|
||||
}
|
||||
})
|
||||
};
|
||||
});
|
||||
[cx.alt_stmt(arms, span, v)]
|
||||
};
|
||||
|
||||
@{ident: name,
|
||||
|
|
|
@ -27,6 +27,8 @@ fn syntax_expander_table() -> hashmap<str, syntax_extension> {
|
|||
{normal({expander: f, span: none})}
|
||||
let syntax_expanders = new_str_hash::<syntax_extension>();
|
||||
syntax_expanders.insert("fmt", builtin(ext::fmt::expand_syntax_ext));
|
||||
syntax_expanders.insert("auto_serialize",
|
||||
item_decorator(ext::auto_serialize::expand));
|
||||
syntax_expanders.insert("env", builtin(ext::env::expand_syntax_ext));
|
||||
syntax_expanders.insert("macro",
|
||||
macro_defining(ext::simplext::add_new_extension));
|
||||
|
|
|
@ -193,6 +193,7 @@ fn finish<T: qq_helper>
|
|||
{
|
||||
let cm = ecx.session().parse_sess.cm;
|
||||
let str = @codemap::span_to_snippet(body.span, cm);
|
||||
#debug["qquote--str==%?", str];
|
||||
let fname = codemap::mk_substr_filename(cm, body.span);
|
||||
let node = parse_from_source_str
|
||||
(f, fname, codemap::fss_internal(body.span), str,
|
||||
|
|
19
src/test/run-pass/auto_serialize_enum.rs
Normal file
19
src/test/run-pass/auto_serialize_enum.rs
Normal file
|
@ -0,0 +1,19 @@
|
|||
use std;
|
||||
import std::prettyprint::serializer;
|
||||
import std::io;
|
||||
|
||||
#[auto_serialize]
|
||||
enum expr {
|
||||
val(uint),
|
||||
plus(@expr, @expr),
|
||||
minus(@expr, @expr)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let ex = @plus(@minus(@val(3u), @val(10u)),
|
||||
@plus(@val(22u), @val(5u)));
|
||||
let s = io::with_str_writer {|w| expr::serialize(w, *ex)};
|
||||
#debug["s == %?", s];
|
||||
assert s == "plus(@minus(@val(3u), @val(10u)), \
|
||||
@plus(@val(22u), @val(5u)))";
|
||||
}
|
19
src/test/run-pass/auto_serialize_gen.rs
Normal file
19
src/test/run-pass/auto_serialize_gen.rs
Normal file
|
@ -0,0 +1,19 @@
|
|||
use std;
|
||||
import std::prettyprint::serializer;
|
||||
import std::io;
|
||||
|
||||
// Test where we link various types used by name.
|
||||
|
||||
#[auto_serialize]
|
||||
type spanned<T> = {lo: uint, hi: uint, node: T};
|
||||
|
||||
#[auto_serialize]
|
||||
type spanned_uint = spanned<uint>;
|
||||
|
||||
fn main() {
|
||||
let x: spanned_uint = {lo: 0u, hi: 5u, node: 22u};
|
||||
spanned_uint::serialize(io::stdout(), x);
|
||||
let s = io::with_str_writer {|w| spanned_uint::serialize(w, x)};
|
||||
#debug["s == %?", s];
|
||||
assert s == "{lo: 0u, hi: 5u, node: 22u}";
|
||||
}
|
22
src/test/run-pass/auto_serialize_link.rs
Normal file
22
src/test/run-pass/auto_serialize_link.rs
Normal file
|
@ -0,0 +1,22 @@
|
|||
use std;
|
||||
import std::prettyprint::serializer;
|
||||
import std::io;
|
||||
|
||||
// Test where we link various types used by name.
|
||||
|
||||
#[auto_serialize]
|
||||
type uint_vec = [uint];
|
||||
|
||||
#[auto_serialize]
|
||||
type some_rec = {v: uint_vec};
|
||||
|
||||
#[auto_serialize]
|
||||
enum an_enum = some_rec;
|
||||
|
||||
fn main() {
|
||||
let x = an_enum({v: [1u, 2u, 3u]});
|
||||
an_enum::serialize(io::stdout(), x);
|
||||
let s = io::with_str_writer {|w| an_enum::serialize(w, x)};
|
||||
#debug["s == %?", s];
|
||||
assert s == "an_enum({v: [1u, 2u, 3u]})";
|
||||
}
|
12
src/test/run-pass/auto_serialize_rec.rs
Normal file
12
src/test/run-pass/auto_serialize_rec.rs
Normal file
|
@ -0,0 +1,12 @@
|
|||
use std;
|
||||
import std::prettyprint::serializer;
|
||||
import std::io;
|
||||
|
||||
#[auto_serialize]
|
||||
type point = {x: uint, y: uint};
|
||||
|
||||
fn main() {
|
||||
let s = io::with_str_writer {|w| point::serialize(w, {x: 3u, y: 5u}) };
|
||||
#debug["s == %?", s];
|
||||
assert s == "{x: 3u, y: 5u}";
|
||||
}
|
13
src/test/run-pass/auto_serialize_vec.rs
Normal file
13
src/test/run-pass/auto_serialize_vec.rs
Normal file
|
@ -0,0 +1,13 @@
|
|||
use std;
|
||||
import std::prettyprint::serializer;
|
||||
import std::io;
|
||||
|
||||
#[auto_serialize]
|
||||
type uint_vec = [uint];
|
||||
|
||||
fn main() {
|
||||
let ex = [1u, 2u, 3u];
|
||||
let s = io::with_str_writer {|w| uint_vec::serialize(w, ex)};
|
||||
#debug["s == %?", s];
|
||||
assert s == "[1u, 2u, 3u]";
|
||||
}
|
Loading…
Reference in a new issue