implement deserialization, rename mk_mem_buffer() to mem_buffer()
This commit is contained in:
@@ -221,10 +221,10 @@ fn under(n: uint, it: fn(uint)) {
|
|||||||
while i < n { it(i); i += 1u; }
|
while i < n { it(i); i += 1u; }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn devnull() -> io::writer { io::mem_buffer_writer(io::mk_mem_buffer()) }
|
fn devnull() -> io::writer { io::mem_buffer_writer(io::mem_buffer()) }
|
||||||
|
|
||||||
fn as_str(f: fn@(io::writer)) -> str {
|
fn as_str(f: fn@(io::writer)) -> str {
|
||||||
let buf = io::mk_mem_buffer();
|
let buf = io::mem_buffer();
|
||||||
f(io::mem_buffer_writer(buf));
|
f(io::mem_buffer_writer(buf));
|
||||||
io::mem_buffer_str(buf)
|
io::mem_buffer_str(buf)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ export uint, u8, u16, u32, u64;
|
|||||||
export float, f32, f64;
|
export float, f32, f64;
|
||||||
export box, char, str, ptr, vec, bool;
|
export box, char, str, ptr, vec, bool;
|
||||||
export either, option, result, iter;
|
export either, option, result, iter;
|
||||||
export libc, os, ctypes, io, run, rand, sys, unsafe, logging, serialization;
|
export libc, os, io, run, rand, sys, unsafe, logging, serialization;
|
||||||
export comm, task, future;
|
export comm, task, future;
|
||||||
export extfmt;
|
export extfmt;
|
||||||
export tuple;
|
export tuple;
|
||||||
|
|||||||
@@ -543,7 +543,7 @@ impl of writer for mem_buffer {
|
|||||||
fn flush() -> int { 0 }
|
fn flush() -> int { 0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mk_mem_buffer() -> mem_buffer {
|
fn mem_buffer() -> mem_buffer {
|
||||||
@{mutable buf: [mutable], mutable pos: 0u}
|
@{mutable buf: [mutable], mutable pos: 0u}
|
||||||
}
|
}
|
||||||
fn mem_buffer_writer(b: mem_buffer) -> writer { b as writer }
|
fn mem_buffer_writer(b: mem_buffer) -> writer { b as writer }
|
||||||
@@ -554,14 +554,14 @@ fn mem_buffer_str(b: mem_buffer) -> str {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn with_str_writer(f: fn(writer)) -> str {
|
fn with_str_writer(f: fn(writer)) -> str {
|
||||||
let buf = mk_mem_buffer();
|
let buf = mem_buffer();
|
||||||
let wr = mem_buffer_writer(buf);
|
let wr = mem_buffer_writer(buf);
|
||||||
f(wr);
|
f(wr);
|
||||||
io::mem_buffer_str(buf)
|
io::mem_buffer_str(buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_buf_writer(f: fn(writer)) -> [u8] {
|
fn with_buf_writer(f: fn(writer)) -> [u8] {
|
||||||
let buf = mk_mem_buffer();
|
let buf = mem_buffer();
|
||||||
let wr = mem_buffer_writer(buf);
|
let wr = mem_buffer_writer(buf);
|
||||||
f(wr);
|
f(wr);
|
||||||
io::mem_buffer_buf(buf)
|
io::mem_buffer_buf(buf)
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ fn emit_from_vec<S: serializer, T>(s: S, v: [T], f: fn(T)) {
|
|||||||
|
|
||||||
fn read_to_vec<D: deserializer, T>(d: D, f: fn() -> T) -> [T] {
|
fn read_to_vec<D: deserializer, T>(d: D, f: fn() -> T) -> [T] {
|
||||||
d.read_vec {|len|
|
d.read_vec {|len|
|
||||||
vec::init_fn(len) {|i|
|
vec::from_fn(len) {|i|
|
||||||
d.read_vec_elt(i) {|| f() }
|
d.read_vec_elt(i) {|| f() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ export grow_fn;
|
|||||||
export grow_set;
|
export grow_set;
|
||||||
export map;
|
export map;
|
||||||
export map2;
|
export map2;
|
||||||
|
export flat_map;
|
||||||
export filter_map;
|
export filter_map;
|
||||||
export filter;
|
export filter;
|
||||||
export concat;
|
export concat;
|
||||||
|
|||||||
@@ -5,3 +5,8 @@ Deprecated in favor of core::serialization."];
|
|||||||
use core;
|
use core;
|
||||||
import list::list;
|
import list::list;
|
||||||
import ebml::writer;
|
import ebml::writer;
|
||||||
|
|
||||||
|
import core::serialization::{serializer,deserializer};
|
||||||
|
|
||||||
|
export serializer;
|
||||||
|
export deserializer;
|
||||||
|
|||||||
@@ -189,7 +189,7 @@ fn print_failures(st: console_test_state) {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_sort_failures_before_printing_them() {
|
fn should_sort_failures_before_printing_them() {
|
||||||
let buffer = io::mk_mem_buffer();
|
let buffer = io::mem_buffer();
|
||||||
let writer = io::mem_buffer_writer(buffer);
|
let writer = io::mem_buffer_writer(buffer);
|
||||||
|
|
||||||
let test_a = {
|
let test_a = {
|
||||||
|
|||||||
@@ -948,7 +948,7 @@ fn mk_ctxt() -> fake_ext_ctxt {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
fn roundtrip(in_item: @ast::item) {
|
fn roundtrip(in_item: @ast::item) {
|
||||||
#debug["in_item = %s", pprust::item_to_str(in_item)];
|
#debug["in_item = %s", pprust::item_to_str(in_item)];
|
||||||
let mbuf = io::mk_mem_buffer();
|
let mbuf = io::mem_buffer();
|
||||||
let ebml_w = ebml::writer(io::mem_buffer_writer(mbuf));
|
let ebml_w = ebml::writer(io::mem_buffer_writer(mbuf));
|
||||||
encode_item_ast(ebml_w, in_item);
|
encode_item_ast(ebml_w, in_item);
|
||||||
let ebml_doc = ebml::new_doc(@io::mem_buffer_buf(mbuf));
|
let ebml_doc = ebml::new_doc(@io::mem_buffer_buf(mbuf));
|
||||||
|
|||||||
@@ -745,7 +745,7 @@ fn encode_metadata(cx: crate_ctxt, crate: @crate) -> [u8] {
|
|||||||
type_abbrevs: abbrevs,
|
type_abbrevs: abbrevs,
|
||||||
reachable: reachable};
|
reachable: reachable};
|
||||||
|
|
||||||
let buf = io::mk_mem_buffer();
|
let buf = io::mem_buffer();
|
||||||
let buf_w = io::mem_buffer_writer(buf);
|
let buf_w = io::mem_buffer_writer(buf);
|
||||||
let ebml_w = ebml::writer(buf_w);
|
let ebml_w = ebml::writer(buf_w);
|
||||||
|
|
||||||
@@ -779,7 +779,7 @@ fn encode_metadata(cx: crate_ctxt, crate: @crate) -> [u8] {
|
|||||||
// Get the encoded string for a type
|
// Get the encoded string for a type
|
||||||
fn encoded_ty(tcx: ty::ctxt, t: ty::t) -> str {
|
fn encoded_ty(tcx: ty::ctxt, t: ty::t) -> str {
|
||||||
let cx = @{ds: def_to_str, tcx: tcx, abbrevs: tyencode::ac_no_abbrevs};
|
let cx = @{ds: def_to_str, tcx: tcx, abbrevs: tyencode::ac_no_abbrevs};
|
||||||
let buf = io::mk_mem_buffer();
|
let buf = io::mem_buffer();
|
||||||
tyencode::enc_ty(io::mem_buffer_writer(buf), cx, t);
|
tyencode::enc_ty(io::mem_buffer_writer(buf), cx, t);
|
||||||
ret io::mem_buffer_str(buf);
|
ret io::mem_buffer_str(buf);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ fn enc_ty(w: io::writer, cx: @ctxt, t: ty::t) {
|
|||||||
let result_str = alt cx.tcx.short_names_cache.find(t) {
|
let result_str = alt cx.tcx.short_names_cache.find(t) {
|
||||||
some(s) { *s }
|
some(s) { *s }
|
||||||
none {
|
none {
|
||||||
let buf = io::mk_mem_buffer();
|
let buf = io::mem_buffer();
|
||||||
enc_sty(io::mem_buffer_writer(buf), cx, ty::get(t).struct);
|
enc_sty(io::mem_buffer_writer(buf), cx, ty::get(t).struct);
|
||||||
cx.tcx.short_names_cache.insert(t, @io::mem_buffer_str(buf));
|
cx.tcx.short_names_cache.insert(t, @io::mem_buffer_str(buf));
|
||||||
io::mem_buffer_str(buf)
|
io::mem_buffer_str(buf)
|
||||||
|
|||||||
@@ -87,10 +87,8 @@ import front::attr;
|
|||||||
|
|
||||||
export expand;
|
export expand;
|
||||||
|
|
||||||
enum ser_cx = @{
|
type ser_tps_map = map::hashmap<str, fn@(@ast::expr) -> [@ast::stmt]>;
|
||||||
ext_cx: ext_ctxt,
|
type deser_tps_map = map::hashmap<str, fn@() -> @ast::expr>;
|
||||||
tps: map::hashmap<str, fn@(@ast::expr) -> [@ast::stmt]>
|
|
||||||
};
|
|
||||||
|
|
||||||
fn expand(cx: ext_ctxt,
|
fn expand(cx: ext_ctxt,
|
||||||
span: span,
|
span: span,
|
||||||
@@ -136,20 +134,10 @@ impl helpers for ext_ctxt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn ty_path(span: span, strs: [str]) -> @ast::ty {
|
fn ty_path(span: span, strs: [str]) -> @ast::ty {
|
||||||
@{node: ast::ty_path(self.path(span, strs), self.next_id()),
|
@{id: self.next_id(),
|
||||||
|
node: ast::ty_path(self.path(span, strs), self.next_id()),
|
||||||
span: span}
|
span: span}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl helpers for ser_cx {
|
|
||||||
fn session() -> session { self.ext_cx.session() }
|
|
||||||
fn next_id() -> ast::node_id { self.ext_cx.next_id() }
|
|
||||||
fn path(span: span, strs: [str]) -> @ast::path {
|
|
||||||
self.ext_cx.path(span, strs)
|
|
||||||
}
|
|
||||||
fn ty_path(span: span, strs: [str]) -> @ast::ty {
|
|
||||||
self.ext_cx.ty_path(span, strs)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn ty_fn(span: span,
|
fn ty_fn(span: span,
|
||||||
-input_tys: [@ast::ty],
|
-input_tys: [@ast::ty],
|
||||||
@@ -161,7 +149,8 @@ impl helpers for ser_cx {
|
|||||||
id: self.next_id()}
|
id: self.next_id()}
|
||||||
};
|
};
|
||||||
|
|
||||||
@{node: ast::ty_fn(ast::proto_any, {inputs: args,
|
@{id: self.next_id(),
|
||||||
|
node: ast::ty_fn(ast::proto_any, {inputs: args,
|
||||||
output: output,
|
output: output,
|
||||||
purity: ast::impure_fn,
|
purity: ast::impure_fn,
|
||||||
cf: ast::return_val,
|
cf: ast::return_val,
|
||||||
@@ -170,7 +159,7 @@ impl helpers for ser_cx {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn ty_nil(span: span) -> @ast::ty {
|
fn ty_nil(span: span) -> @ast::ty {
|
||||||
@{node: ast::ty_nil, span: span}
|
@{id: self.next_id(), node: ast::ty_nil, span: span}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expr(span: span, node: ast::expr_) -> @ast::expr {
|
fn expr(span: span, node: ast::expr_) -> @ast::expr {
|
||||||
@@ -190,6 +179,15 @@ impl helpers for ser_cx {
|
|||||||
span: span}
|
span: span}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn expr_blk(expr: @ast::expr) -> ast::blk {
|
||||||
|
{node: {view_items: [],
|
||||||
|
stmts: [],
|
||||||
|
expr: some(expr),
|
||||||
|
id: self.next_id(),
|
||||||
|
rules: ast::default_blk},
|
||||||
|
span: expr.span}
|
||||||
|
}
|
||||||
|
|
||||||
fn binder_pat(span: span, nm: str) -> @ast::pat {
|
fn binder_pat(span: span, nm: str) -> @ast::pat {
|
||||||
let path = @{node: {global: false,
|
let path = @{node: {global: false,
|
||||||
idents: [nm],
|
idents: [nm],
|
||||||
@@ -231,30 +229,28 @@ impl helpers for ser_cx {
|
|||||||
fn lambda(blk: ast::blk) -> @ast::expr {
|
fn lambda(blk: ast::blk) -> @ast::expr {
|
||||||
let ext_cx = self;
|
let ext_cx = self;
|
||||||
let blk_e = self.expr(blk.span, ast::expr_block(blk));
|
let blk_e = self.expr(blk.span, ast::expr_block(blk));
|
||||||
#ast(expr){{|| $(blk_e) }}
|
#ast{ {|| $(blk_e) } }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn clone_folder() -> fold::ast_fold {
|
||||||
|
fold::make_fold({
|
||||||
|
new_id: {|_id| self.next_id()}
|
||||||
|
with *fold::default_ast_fold()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clone(v: @ast::expr) -> @ast::expr {
|
fn clone(v: @ast::expr) -> @ast::expr {
|
||||||
let fld = fold::make_fold({
|
let fld = self.clone_folder();
|
||||||
new_id: {|_id| self.next_id()}
|
|
||||||
with *fold::default_ast_fold()
|
|
||||||
});
|
|
||||||
fld.fold_expr(v)
|
fld.fold_expr(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clone_ty(v: @ast::ty) -> @ast::ty {
|
fn clone_ty(v: @ast::ty) -> @ast::ty {
|
||||||
let fld = fold::make_fold({
|
let fld = self.clone_folder();
|
||||||
new_id: {|_id| self.next_id()}
|
|
||||||
with *fold::default_ast_fold()
|
|
||||||
});
|
|
||||||
fld.fold_ty(v)
|
fld.fold_ty(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clone_ty_param(v: ast::ty_param) -> ast::ty_param {
|
fn clone_ty_param(v: ast::ty_param) -> ast::ty_param {
|
||||||
let fld = fold::make_fold({
|
let fld = self.clone_folder();
|
||||||
new_id: {|_id| self.next_id()}
|
|
||||||
with *fold::default_ast_fold()
|
|
||||||
});
|
|
||||||
fold::fold_ty_param(v, fld)
|
fold::fold_ty_param(v, fld)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -276,10 +272,10 @@ impl helpers for ser_cx {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_path(cx: ser_cx, path: @ast::path,
|
fn ser_path(cx: ext_ctxt, tps: ser_tps_map, path: @ast::path,
|
||||||
-s: @ast::expr, -v: @ast::expr)
|
-s: @ast::expr, -v: @ast::expr)
|
||||||
-> [@ast::stmt] {
|
-> [@ast::stmt] {
|
||||||
let ext_cx = cx.ext_cx;
|
let ext_cx = cx; // required for #ast{}
|
||||||
|
|
||||||
// We want to take a path like a::b::c<...> and generate a call
|
// We want to take a path like a::b::c<...> and generate a call
|
||||||
// like a::b::c::serialize(s, ...), as described above.
|
// like a::b::c::serialize(s, ...), as described above.
|
||||||
@@ -291,11 +287,10 @@ fn serialize_path(cx: ser_cx, path: @ast::path,
|
|||||||
cx.path(path.span, path.node.idents + ["serialize"])));
|
cx.path(path.span, path.node.idents + ["serialize"])));
|
||||||
|
|
||||||
let ty_args = vec::map(path.node.types) {|ty|
|
let ty_args = vec::map(path.node.types) {|ty|
|
||||||
let sv_stmts = serialize_ty(cx, ty, cx.clone(s), #ast(expr){__v});
|
let sv_stmts = ser_ty(cx, tps, ty, cx.clone(s), #ast{ __v });
|
||||||
let sv = cx.expr(path.span,
|
let sv = cx.expr(path.span,
|
||||||
ast::expr_block(cx.blk(path.span,
|
ast::expr_block(cx.blk(path.span, sv_stmts)));
|
||||||
sv_stmts)));
|
cx.at(ty.span, #ast{ {|__v| $(sv)} })
|
||||||
cx.at(ty.span, #ast(expr){{|__v| $(sv)}})
|
|
||||||
};
|
};
|
||||||
|
|
||||||
[cx.stmt(
|
[cx.stmt(
|
||||||
@@ -304,7 +299,8 @@ fn serialize_path(cx: ser_cx, path: @ast::path,
|
|||||||
ast::expr_call(callee, [s, v] + ty_args, false)))]
|
ast::expr_call(callee, [s, v] + ty_args, false)))]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_variant(cx: ser_cx,
|
fn ser_variant(cx: ext_ctxt,
|
||||||
|
tps: ser_tps_map,
|
||||||
tys: [@ast::ty],
|
tys: [@ast::ty],
|
||||||
span: span,
|
span: span,
|
||||||
-s: @ast::expr,
|
-s: @ast::expr,
|
||||||
@@ -312,17 +308,17 @@ fn serialize_variant(cx: ser_cx,
|
|||||||
bodyfn: fn(-@ast::expr, ast::blk) -> @ast::expr,
|
bodyfn: fn(-@ast::expr, ast::blk) -> @ast::expr,
|
||||||
argfn: fn(-@ast::expr, uint, ast::blk) -> @ast::expr)
|
argfn: fn(-@ast::expr, uint, ast::blk) -> @ast::expr)
|
||||||
-> ast::arm {
|
-> ast::arm {
|
||||||
let vnames = vec::init_fn(vec::len(tys)) {|i| #fmt["__v%u", i]};
|
let vnames = vec::from_fn(vec::len(tys)) {|i| #fmt["__v%u", i]};
|
||||||
let pats = vec::init_fn(vec::len(tys)) {|i|
|
let pats = vec::from_fn(vec::len(tys)) {|i|
|
||||||
cx.binder_pat(tys[i].span, vnames[i])
|
cx.binder_pat(tys[i].span, vnames[i])
|
||||||
};
|
};
|
||||||
let pat: @ast::pat = @{id: cx.next_id(), node: pfn(pats), span: span};
|
let pat: @ast::pat = @{id: cx.next_id(), node: pfn(pats), span: span};
|
||||||
let stmts = vec::init_fn(vec::len(tys)) {|i|
|
let stmts = vec::from_fn(vec::len(tys)) {|i|
|
||||||
let v = cx.var_ref(span, vnames[i]);
|
let v = cx.var_ref(span, vnames[i]);
|
||||||
let arg_blk =
|
let arg_blk =
|
||||||
cx.blk(
|
cx.blk(
|
||||||
span,
|
span,
|
||||||
serialize_ty(cx, tys[i], cx.clone(s), v));
|
ser_ty(cx, tps, tys[i], cx.clone(s), v));
|
||||||
cx.stmt(argfn(cx.clone(s), i, arg_blk))
|
cx.stmt(argfn(cx.clone(s), i, arg_blk))
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -332,29 +328,35 @@ fn serialize_variant(cx: ser_cx,
|
|||||||
{pats: [pat], guard: none, body: body}
|
{pats: [pat], guard: none, body: body}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_ty(cx: ser_cx, ty: @ast::ty, -s: @ast::expr, -v: @ast::expr)
|
fn ser_lambda(cx: ext_ctxt, tps: ser_tps_map, ty: @ast::ty,
|
||||||
|
-s: @ast::expr, -v: @ast::expr) -> @ast::expr {
|
||||||
|
cx.lambda(cx.blk(ty.span, ser_ty(cx, tps, ty, s, v)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ser_ty(cx: ext_ctxt, tps: ser_tps_map,
|
||||||
|
ty: @ast::ty, -s: @ast::expr, -v: @ast::expr)
|
||||||
-> [@ast::stmt] {
|
-> [@ast::stmt] {
|
||||||
|
|
||||||
fn ty_lambda(cx: ser_cx, ty: @ast::ty, -s: @ast::expr, -v: @ast::expr)
|
let ext_cx = cx; // required for #ast{}
|
||||||
-> @ast::expr {
|
|
||||||
cx.lambda(cx.blk(ty.span, serialize_ty(cx, ty, s, v)))
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
let ext_cx = cx.ext_cx;
|
|
||||||
|
|
||||||
alt ty.node {
|
alt ty.node {
|
||||||
ast::ty_nil | ast::ty_bot {
|
ast::ty_nil {
|
||||||
|
[#ast[stmt]{$(s).emit_nil()}]
|
||||||
|
}
|
||||||
|
|
||||||
|
ast::ty_bot {
|
||||||
|
cx.session().span_err(
|
||||||
|
ty.span, #fmt["Cannot serialize bottom type"]);
|
||||||
[]
|
[]
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::ty_box(mt) {
|
ast::ty_box(mt) {
|
||||||
let l = ty_lambda(cx, mt.ty, cx.clone(s), #ast(expr){*$(v)});
|
let l = ser_lambda(cx, tps, mt.ty, cx.clone(s), #ast{ *$(v) });
|
||||||
[#ast(stmt){$(s).emit_box($(l));}]
|
[#ast(stmt){$(s).emit_box($(l));}]
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::ty_uniq(mt) {
|
ast::ty_uniq(mt) {
|
||||||
let l = ty_lambda(cx, mt.ty, cx.clone(s), #ast(expr){*$(v)});
|
let l = ser_lambda(cx, tps, mt.ty, cx.clone(s), #ast{ *$(v) });
|
||||||
[#ast(stmt){$(s).emit_uniq($(l));}]
|
[#ast(stmt){$(s).emit_uniq($(l));}]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -365,7 +367,7 @@ fn serialize_ty(cx: ser_cx, ty: @ast::ty, -s: @ast::expr, -v: @ast::expr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ast::ty_rec(flds) {
|
ast::ty_rec(flds) {
|
||||||
let fld_stmts = vec::init_fn(vec::len(flds)) {|fidx|
|
let fld_stmts = vec::from_fn(vec::len(flds)) {|fidx|
|
||||||
let fld = flds[fidx];
|
let fld = flds[fidx];
|
||||||
let vf = cx.expr(fld.span,
|
let vf = cx.expr(fld.span,
|
||||||
ast::expr_field(cx.clone(v),
|
ast::expr_field(cx.clone(v),
|
||||||
@@ -374,7 +376,7 @@ fn serialize_ty(cx: ser_cx, ty: @ast::ty, -s: @ast::expr, -v: @ast::expr)
|
|||||||
let s = cx.clone(s);
|
let s = cx.clone(s);
|
||||||
let f = cx.lit_str(fld.span, fld.node.ident);
|
let f = cx.lit_str(fld.span, fld.node.ident);
|
||||||
let i = cx.lit_uint(fld.span, fidx);
|
let i = cx.lit_uint(fld.span, fidx);
|
||||||
let l = ty_lambda(cx, fld.node.mt.ty, cx.clone(s), vf);
|
let l = ser_lambda(cx, tps, fld.node.mt.ty, cx.clone(s), vf);
|
||||||
#ast(stmt){$(s).emit_rec_field($(f), $(i), $(l));}
|
#ast(stmt){$(s).emit_rec_field($(f), $(i), $(l));}
|
||||||
};
|
};
|
||||||
let fld_lambda = cx.lambda(cx.blk(ty.span, fld_stmts));
|
let fld_lambda = cx.lambda(cx.blk(ty.span, fld_stmts));
|
||||||
@@ -397,9 +399,9 @@ fn serialize_ty(cx: ser_cx, ty: @ast::ty, -s: @ast::expr, -v: @ast::expr)
|
|||||||
// };
|
// };
|
||||||
|
|
||||||
let arms = [
|
let arms = [
|
||||||
serialize_variant(
|
ser_variant(
|
||||||
|
|
||||||
cx, tys, ty.span, s,
|
cx, tps, tys, ty.span, s,
|
||||||
|
|
||||||
// Generate pattern (v1, v2, v3)
|
// Generate pattern (v1, v2, v3)
|
||||||
{|pats| ast::pat_tup(pats)},
|
{|pats| ast::pat_tup(pats)},
|
||||||
@@ -408,18 +410,14 @@ fn serialize_ty(cx: ser_cx, ty: @ast::ty, -s: @ast::expr, -v: @ast::expr)
|
|||||||
{|-s, blk|
|
{|-s, blk|
|
||||||
let sz = cx.lit_uint(ty.span, vec::len(tys));
|
let sz = cx.lit_uint(ty.span, vec::len(tys));
|
||||||
let body = cx.lambda(blk);
|
let body = cx.lambda(blk);
|
||||||
#ast[expr]{
|
#ast{ $(s).emit_tup($(sz), $(body)) }
|
||||||
$(s).emit_tup($(sz), $(body))
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// Generate s.emit_tup_elt(i, {|| blk })
|
// Generate s.emit_tup_elt(i, {|| blk })
|
||||||
{|-s, i, blk|
|
{|-s, i, blk|
|
||||||
let idx = cx.lit_uint(ty.span, i);
|
let idx = cx.lit_uint(ty.span, i);
|
||||||
let body = cx.lambda(blk);
|
let body = cx.lambda(blk);
|
||||||
#ast[expr]{
|
#ast{ $(s).emit_tup_elt($(idx), $(body)) }
|
||||||
$(s).emit_tup_elt($(idx), $(body))
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
];
|
];
|
||||||
[cx.alt_stmt(arms, ty.span, v)]
|
[cx.alt_stmt(arms, ty.span, v)]
|
||||||
@@ -430,17 +428,17 @@ fn serialize_ty(cx: ser_cx, ty: @ast::ty, -s: @ast::expr, -v: @ast::expr)
|
|||||||
vec::is_empty(path.node.types) {
|
vec::is_empty(path.node.types) {
|
||||||
let ident = path.node.idents[0];
|
let ident = path.node.idents[0];
|
||||||
|
|
||||||
alt cx.tps.find(ident) {
|
alt tps.find(ident) {
|
||||||
some(f) { f(v) }
|
some(f) { f(v) }
|
||||||
none { serialize_path(cx, path, s, v) }
|
none { ser_path(cx, tps, path, s, v) }
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
serialize_path(cx, path, s, v)
|
ser_path(cx, tps, path, s, v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::ty_constr(ty, _) {
|
ast::ty_constr(ty, _) {
|
||||||
serialize_ty(cx, ty, s, v)
|
ser_ty(cx, tps, ty, s, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::ty_mac(_) {
|
ast::ty_mac(_) {
|
||||||
@@ -462,12 +460,10 @@ fn serialize_ty(cx: ser_cx, ty: @ast::ty, -s: @ast::expr, -v: @ast::expr)
|
|||||||
ast::expr_block(
|
ast::expr_block(
|
||||||
cx.blk(
|
cx.blk(
|
||||||
ty.span,
|
ty.span,
|
||||||
serialize_ty(
|
ser_ty(
|
||||||
cx, mt.ty,
|
cx, tps, mt.ty,
|
||||||
cx.clone(s),
|
cx.clone(s),
|
||||||
cx.at(
|
cx.at(ty.span, #ast{ __e })))));
|
||||||
ty.span,
|
|
||||||
#ast(expr){__e})))));
|
|
||||||
|
|
||||||
[#ast(stmt){
|
[#ast(stmt){
|
||||||
core::serialization::emit_from_vec($(s), $(v), {|__e| $(ser_e) })
|
core::serialization::emit_from_vec($(s), $(v), {|__e| $(ser_e) })
|
||||||
@@ -476,12 +472,12 @@ fn serialize_ty(cx: ser_cx, ty: @ast::ty, -s: @ast::expr, -v: @ast::expr)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mk_ser_fn(ext_cx: ext_ctxt, span: span,
|
fn mk_ser_fn(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])
|
f: fn(ext_ctxt, ser_tps_map, @ast::ty,
|
||||||
|
-@ast::expr, -@ast::expr) -> [@ast::stmt])
|
||||||
-> @ast::item {
|
-> @ast::item {
|
||||||
|
let ext_cx = cx; // required for #ast
|
||||||
let cx = ser_cx(@{ext_cx: ext_cx, tps: map::new_str_hash()});
|
|
||||||
|
|
||||||
let tp_inputs =
|
let tp_inputs =
|
||||||
vec::map(tps, {|tp|
|
vec::map(tps, {|tp|
|
||||||
@@ -500,14 +496,15 @@ fn mk_ser_fn(ext_cx: ext_ctxt, span: span,
|
|||||||
ident: "__s",
|
ident: "__s",
|
||||||
id: cx.next_id()},
|
id: cx.next_id()},
|
||||||
{mode: ast::expl(ast::by_ref),
|
{mode: ast::expl(ast::by_ref),
|
||||||
ty: cx.clone_ty(v_ty),
|
ty: v_ty,
|
||||||
ident: "__v",
|
ident: "__v",
|
||||||
id: cx.next_id()}]
|
id: cx.next_id()}]
|
||||||
+ tp_inputs;
|
+ tp_inputs;
|
||||||
|
|
||||||
|
let tps_map = map::new_str_hash();
|
||||||
vec::iter2(tps, tp_inputs) {|tp, arg|
|
vec::iter2(tps, tp_inputs) {|tp, arg|
|
||||||
let arg_ident = arg.ident;
|
let arg_ident = arg.ident;
|
||||||
cx.tps.insert(
|
tps_map.insert(
|
||||||
tp.ident,
|
tp.ident,
|
||||||
fn@(v: @ast::expr) -> [@ast::stmt] {
|
fn@(v: @ast::expr) -> [@ast::stmt] {
|
||||||
let f = cx.var_ref(span, arg_ident);
|
let f = cx.var_ref(span, arg_ident);
|
||||||
@@ -526,11 +523,12 @@ fn mk_ser_fn(ext_cx: ext_ctxt, span: span,
|
|||||||
bounds: ser_bnds}] +
|
bounds: ser_bnds}] +
|
||||||
vec::map(tps) {|tp| cx.clone_ty_param(tp) };
|
vec::map(tps) {|tp| cx.clone_ty_param(tp) };
|
||||||
|
|
||||||
let ser_output: @ast::ty = @{node: ast::ty_nil,
|
let ser_output: @ast::ty = @{id: cx.next_id(),
|
||||||
|
node: ast::ty_nil,
|
||||||
span: span};
|
span: span};
|
||||||
|
|
||||||
let ser_blk = cx.blk(span,
|
let ser_blk = cx.blk(span,
|
||||||
f(cx, v_ty, #ast(expr){__s}, #ast(expr){__v}));
|
f(cx, tps_map, v_ty, #ast{ __s }, #ast{ __v }));
|
||||||
|
|
||||||
@{ident: "serialize",
|
@{ident: "serialize",
|
||||||
attrs: [],
|
attrs: [],
|
||||||
@@ -545,54 +543,241 @@ fn mk_ser_fn(ext_cx: ext_ctxt, span: span,
|
|||||||
span: span}
|
span: span}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ty_module(ext_cx: ext_ctxt, name: str, ty: @ast::ty, tps: [ast::ty_param])
|
// ______________________________________________________________________
|
||||||
|
|
||||||
|
fn deser_path(cx: ext_ctxt, tps: deser_tps_map, path: @ast::path,
|
||||||
|
-d: @ast::expr) -> @ast::expr {
|
||||||
|
// We want to take a path like a::b::c<...> and generate a call
|
||||||
|
// like a::b::c::deserialize(d, ...), as described above.
|
||||||
|
|
||||||
|
let callee =
|
||||||
|
cx.expr(
|
||||||
|
path.span,
|
||||||
|
ast::expr_path(
|
||||||
|
cx.path(path.span, path.node.idents + ["deserialize"])));
|
||||||
|
|
||||||
|
let ty_args = vec::map(path.node.types) {|ty|
|
||||||
|
let dv_expr = deser_ty(cx, tps, ty, cx.clone(d));
|
||||||
|
cx.lambda(cx.expr_blk(dv_expr))
|
||||||
|
};
|
||||||
|
|
||||||
|
cx.expr(path.span, ast::expr_call(callee, [d] + ty_args, false))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deser_lambda(cx: ext_ctxt, tps: deser_tps_map, ty: @ast::ty,
|
||||||
|
-d: @ast::expr) -> @ast::expr {
|
||||||
|
cx.lambda(cx.expr_blk(deser_ty(cx, tps, ty, d)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deser_ty(cx: ext_ctxt, tps: deser_tps_map,
|
||||||
|
ty: @ast::ty, -d: @ast::expr) -> @ast::expr {
|
||||||
|
|
||||||
|
let ext_cx = cx; // required for #ast{}
|
||||||
|
|
||||||
|
alt ty.node {
|
||||||
|
ast::ty_nil {
|
||||||
|
#ast{ $(d).read_nil() }
|
||||||
|
}
|
||||||
|
|
||||||
|
ast::ty_bot {
|
||||||
|
#ast{ fail }
|
||||||
|
}
|
||||||
|
|
||||||
|
ast::ty_box(mt) {
|
||||||
|
let l = deser_lambda(cx, tps, mt.ty, cx.clone(d));
|
||||||
|
#ast{ @$(d).read_box($(l)) }
|
||||||
|
}
|
||||||
|
|
||||||
|
ast::ty_uniq(mt) {
|
||||||
|
let l = deser_lambda(cx, tps, mt.ty, cx.clone(d));
|
||||||
|
#ast{ ~$(d).read_uniq($(l)) }
|
||||||
|
}
|
||||||
|
|
||||||
|
ast::ty_ptr(_) | ast::ty_rptr(_, _) {
|
||||||
|
#ast{ fail }
|
||||||
|
}
|
||||||
|
|
||||||
|
ast::ty_rec(flds) {
|
||||||
|
let fields = vec::from_fn(vec::len(flds)) {|fidx|
|
||||||
|
let fld = flds[fidx];
|
||||||
|
let d = cx.clone(d);
|
||||||
|
let f = cx.lit_str(fld.span, fld.node.ident);
|
||||||
|
let i = cx.lit_uint(fld.span, fidx);
|
||||||
|
let l = deser_lambda(cx, tps, fld.node.mt.ty, cx.clone(d));
|
||||||
|
{node: {mutbl: fld.node.mt.mutbl,
|
||||||
|
ident: fld.node.ident,
|
||||||
|
expr: #ast{ $(d).read_rec_field($(f), $(i), $(l))} },
|
||||||
|
span: fld.span}
|
||||||
|
};
|
||||||
|
let fld_expr = cx.expr(ty.span, ast::expr_rec(fields, none));
|
||||||
|
let fld_lambda = cx.lambda(cx.expr_blk(fld_expr));
|
||||||
|
#ast{ $(d).read_rec($(fld_lambda)) }
|
||||||
|
}
|
||||||
|
|
||||||
|
ast::ty_fn(_, _) {
|
||||||
|
#ast{ fail }
|
||||||
|
}
|
||||||
|
|
||||||
|
ast::ty_tup(tys) {
|
||||||
|
// Generate code like
|
||||||
|
//
|
||||||
|
// d.read_tup(3u) {||
|
||||||
|
// (d.read_tup_elt(0u, {||...}),
|
||||||
|
// d.read_tup_elt(1u, {||...}),
|
||||||
|
// d.read_tup_elt(2u, {||...}))
|
||||||
|
// }
|
||||||
|
|
||||||
|
let arg_exprs = vec::from_fn(vec::len(tys)) {|i|
|
||||||
|
let idx = cx.lit_uint(ty.span, i);
|
||||||
|
let body = deser_lambda(cx, tps, tys[i], cx.clone(d));
|
||||||
|
#ast{ $(d).read_tup_elt($(idx), $(body)) }
|
||||||
|
};
|
||||||
|
let body =
|
||||||
|
cx.lambda(cx.expr_blk(
|
||||||
|
cx.expr(ty.span, ast::expr_tup(arg_exprs))));
|
||||||
|
let sz = cx.lit_uint(ty.span, vec::len(tys));
|
||||||
|
#ast{ $(d).read_tup($(sz), $(body)) }
|
||||||
|
}
|
||||||
|
|
||||||
|
ast::ty_path(path, _) {
|
||||||
|
if vec::len(path.node.idents) == 1u &&
|
||||||
|
vec::is_empty(path.node.types) {
|
||||||
|
let ident = path.node.idents[0];
|
||||||
|
|
||||||
|
alt tps.find(ident) {
|
||||||
|
some(f) { f() }
|
||||||
|
none { deser_path(cx, tps, path, d) }
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
deser_path(cx, tps, path, d)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ast::ty_constr(ty, constrs) {
|
||||||
|
deser_ty(cx, tps, ty, d)
|
||||||
|
}
|
||||||
|
|
||||||
|
ast::ty_mac(_) {
|
||||||
|
#ast{ fail }
|
||||||
|
}
|
||||||
|
|
||||||
|
ast::ty_infer {
|
||||||
|
#ast{ fail }
|
||||||
|
}
|
||||||
|
|
||||||
|
ast::ty_vec(mt) {
|
||||||
|
let l = deser_lambda(cx, tps, mt.ty, cx.clone(d));
|
||||||
|
#ast{ core::serialization::read_to_vec($(d), $(l)) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mk_deser_fn(cx: ext_ctxt, span: span,
|
||||||
|
-v_ty: @ast::ty, tps: [ast::ty_param],
|
||||||
|
f: fn(ext_ctxt, deser_tps_map,
|
||||||
|
@ast::ty, -@ast::expr) -> @ast::expr)
|
||||||
|
-> @ast::item {
|
||||||
|
let ext_cx = cx; // required for #ast
|
||||||
|
|
||||||
|
let tp_inputs =
|
||||||
|
vec::map(tps, {|tp|
|
||||||
|
{mode: ast::expl(ast::by_ref),
|
||||||
|
ty: cx.ty_fn(span,
|
||||||
|
[],
|
||||||
|
cx.ty_path(span, [tp.ident])),
|
||||||
|
ident: "__d" + tp.ident,
|
||||||
|
id: cx.next_id()}});
|
||||||
|
|
||||||
|
#debug["tp_inputs = %?", tp_inputs];
|
||||||
|
|
||||||
|
let deser_inputs: [ast::arg] =
|
||||||
|
[{mode: ast::expl(ast::by_ref),
|
||||||
|
ty: cx.ty_path(span, ["__D"]),
|
||||||
|
ident: "__d",
|
||||||
|
id: cx.next_id()}]
|
||||||
|
+ tp_inputs;
|
||||||
|
|
||||||
|
let tps_map = map::new_str_hash();
|
||||||
|
vec::iter2(tps, tp_inputs) {|tp, arg|
|
||||||
|
let arg_ident = arg.ident;
|
||||||
|
tps_map.insert(
|
||||||
|
tp.ident,
|
||||||
|
fn@() -> @ast::expr {
|
||||||
|
let f = cx.var_ref(span, arg_ident);
|
||||||
|
#ast{ $(f)() }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let deser_bnds = @[ast::bound_iface(cx.ty_path(span,
|
||||||
|
["serialization",
|
||||||
|
"deserializer"]))];
|
||||||
|
|
||||||
|
let deser_tps: [ast::ty_param] =
|
||||||
|
[{ident: "__D",
|
||||||
|
id: cx.next_id(),
|
||||||
|
bounds: deser_bnds}] +
|
||||||
|
vec::map(tps) {|tp| cx.clone_ty_param(tp) };
|
||||||
|
|
||||||
|
let deser_blk = cx.expr_blk(f(cx, tps_map, v_ty, #ast(expr){__d}));
|
||||||
|
|
||||||
|
@{ident: "deserialize",
|
||||||
|
attrs: [],
|
||||||
|
id: cx.next_id(),
|
||||||
|
node: ast::item_fn({inputs: deser_inputs,
|
||||||
|
output: v_ty,
|
||||||
|
purity: ast::impure_fn,
|
||||||
|
cf: ast::return_val,
|
||||||
|
constraints: []},
|
||||||
|
deser_tps,
|
||||||
|
deser_blk),
|
||||||
|
span: span}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ty_module(cx: ext_ctxt, name: str, ty: @ast::ty, tps: [ast::ty_param])
|
||||||
-> @ast::item {
|
-> @ast::item {
|
||||||
|
|
||||||
let span = ty.span;
|
let span = ty.span;
|
||||||
let ser_fn = mk_ser_fn(ext_cx, span, ty, tps, serialize_ty);
|
let ser_fn = mk_ser_fn(cx, span, cx.clone_ty(ty), tps, ser_ty);
|
||||||
|
let deser_fn = mk_deser_fn(cx, span, cx.clone_ty(ty), tps, deser_ty);
|
||||||
|
|
||||||
// Return a module containing the serialization and deserialization
|
// Return a module containing the serialization and deserialization
|
||||||
// functions:
|
// functions:
|
||||||
@{ident: name,
|
@{ident: name,
|
||||||
attrs: [],
|
attrs: [],
|
||||||
id: ext_cx.session().next_node_id(),
|
id: cx.next_id(),
|
||||||
node: ast::item_mod({view_items: [],
|
node: ast::item_mod({view_items: [],
|
||||||
items: [ser_fn]}),
|
items: [ser_fn, deser_fn]}),
|
||||||
span: span}
|
span: span}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn enum_module(ext_cx: ext_ctxt, name: str, span: span,
|
fn ser_enum(cx: ext_ctxt, tps: ser_tps_map, e_name: str,
|
||||||
variants: [ast::variant], tps: [ast::ty_param])
|
e_span: span, variants: [ast::variant],
|
||||||
-> @ast::item {
|
_ty: @ast::ty, -s: @ast::expr, -v: @ast::expr) -> [@ast::stmt] {
|
||||||
|
let ext_cx = cx;
|
||||||
let ty = ext_cx.ty_path(span, [name]);
|
let arms = vec::from_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];
|
let variant = variants[vidx];
|
||||||
let span = variant.span;
|
let v_span = variant.span;
|
||||||
let name = variant.node.name;
|
let v_name = variant.node.name;
|
||||||
let variant_tys = vec::map(variant.node.args) {|a| a.ty };
|
let variant_tys = vec::map(variant.node.args) {|a| a.ty };
|
||||||
|
|
||||||
serialize_variant(
|
ser_variant(
|
||||||
cx, variant_tys, span, cx.clone(s),
|
cx, tps, variant_tys, v_span, cx.clone(s),
|
||||||
|
|
||||||
// Generate pattern var(v1, v2, v3)
|
// Generate pattern var(v1, v2, v3)
|
||||||
{|pats|
|
{|pats|
|
||||||
if vec::is_empty(pats) {
|
if vec::is_empty(pats) {
|
||||||
ast::pat_ident(cx.path(span, [name]), none)
|
ast::pat_ident(cx.path(v_span, [v_name]), none)
|
||||||
} else {
|
} else {
|
||||||
ast::pat_enum(cx.path(span, [name]), pats)
|
ast::pat_enum(cx.path(v_span, [v_name]), pats)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// Generate body s.emit_enum_variant("foo", 0u,
|
// Generate body s.emit_enum_variant("foo", 0u,
|
||||||
// 3u, {|| blk })
|
// 3u, {|| blk })
|
||||||
{|-s, blk|
|
{|-s, blk|
|
||||||
let v_name = cx.lit_str(span, name);
|
let v_name = cx.lit_str(v_span, v_name);
|
||||||
let v_id = cx.lit_uint(span, vidx);
|
let v_id = cx.lit_uint(v_span, vidx);
|
||||||
let sz = cx.lit_uint(span, vec::len(variant_tys));
|
let sz = cx.lit_uint(v_span, vec::len(variant_tys));
|
||||||
let body = cx.lambda(blk);
|
let body = cx.lambda(blk);
|
||||||
#ast[expr]{
|
#ast[expr]{
|
||||||
$(s).emit_enum_variant($(v_name), $(v_id),
|
$(s).emit_enum_variant($(v_name), $(v_id),
|
||||||
@@ -602,20 +787,70 @@ fn enum_module(ext_cx: ext_ctxt, name: str, span: span,
|
|||||||
|
|
||||||
// Generate s.emit_enum_variant_arg(i, {|| blk })
|
// Generate s.emit_enum_variant_arg(i, {|| blk })
|
||||||
{|-s, i, blk|
|
{|-s, i, blk|
|
||||||
let idx = cx.lit_uint(span, i);
|
let idx = cx.lit_uint(v_span, i);
|
||||||
let body = cx.lambda(blk);
|
let body = cx.lambda(blk);
|
||||||
#ast[expr]{
|
#ast[expr]{
|
||||||
$(s).emit_enum_variant_arg($(idx), $(body))
|
$(s).emit_enum_variant_arg($(idx), $(body))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
});
|
};
|
||||||
[cx.alt_stmt(arms, span, v)]
|
let lam = cx.lambda(cx.blk(e_span, [cx.alt_stmt(arms, e_span, v)]));
|
||||||
|
let e_name = cx.lit_str(e_span, e_name);
|
||||||
|
[#ast(stmt){ $(s).emit_enum($(e_name), $(lam)) }]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deser_enum(cx: ext_ctxt, tps: deser_tps_map, e_name: str,
|
||||||
|
e_span: span, variants: [ast::variant],
|
||||||
|
_ty: @ast::ty, -d: @ast::expr) -> @ast::expr {
|
||||||
|
let ext_cx = cx;
|
||||||
|
let arms: [ast::arm] = vec::from_fn(vec::len(variants)) {|vidx|
|
||||||
|
let variant = variants[vidx];
|
||||||
|
let v_span = variant.span;
|
||||||
|
let v_name = variant.node.name;
|
||||||
|
let tys = vec::map(variant.node.args) {|a| a.ty };
|
||||||
|
|
||||||
|
let arg_exprs = vec::from_fn(vec::len(tys)) {|i|
|
||||||
|
let idx = cx.lit_uint(v_span, i);
|
||||||
|
let body = deser_lambda(cx, tps, tys[i], cx.clone(d));
|
||||||
|
#ast{ $(d).read_enum_variant_arg($(idx), $(body)) }
|
||||||
};
|
};
|
||||||
|
|
||||||
@{ident: name,
|
let body =
|
||||||
attrs: [],
|
cx.expr(v_span, ast::expr_call(
|
||||||
id: ext_cx.session().next_node_id(),
|
cx.var_ref(v_span, v_name), arg_exprs, false));
|
||||||
node: ast::item_mod({view_items: [],
|
|
||||||
items: [ser_fn]}),
|
{pats: [@{id: cx.next_id(),
|
||||||
span: span}
|
node: ast::pat_lit(cx.lit_uint(v_span, vidx)),
|
||||||
|
span: v_span}],
|
||||||
|
guard: none,
|
||||||
|
body: cx.expr_blk(body)}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Generate code like:
|
||||||
|
let e_name = cx.lit_str(e_span, e_name);
|
||||||
|
let alt_expr = cx.expr(e_span,
|
||||||
|
ast::expr_alt(#ast{__i}, arms, ast::alt_check));
|
||||||
|
let var_lambda = #ast{ {|__i| $(alt_expr)} };
|
||||||
|
let read_var = #ast{ $(cx.clone(d)).read_enum_variant($(var_lambda)) };
|
||||||
|
let read_lambda = cx.lambda(cx.expr_blk(read_var));
|
||||||
|
#ast{ $(d).read_enum($(e_name), $(read_lambda)) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn enum_module(cx: ext_ctxt, e_name: str, e_span: span,
|
||||||
|
variants: [ast::variant], tps: [ast::ty_param])
|
||||||
|
-> @ast::item {
|
||||||
|
let ty = cx.ty_path(e_span, [e_name]);
|
||||||
|
let ser_fn =
|
||||||
|
mk_ser_fn(cx, e_span, cx.clone_ty(ty), tps,
|
||||||
|
ser_enum(_, _, e_name, e_span, variants, _, _, _));
|
||||||
|
let deser_fn =
|
||||||
|
mk_deser_fn(cx, e_span, ty, tps,
|
||||||
|
deser_enum(_, _, e_name, e_span, variants, _, _));
|
||||||
|
|
||||||
|
@{ident: e_name,
|
||||||
|
attrs: [],
|
||||||
|
id: cx.next_id(),
|
||||||
|
node: ast::item_mod({view_items: [],
|
||||||
|
items: [ser_fn, deser_fn]}),
|
||||||
|
span: e_span}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ fn path_to_str(&&p: @ast::path) -> str {
|
|||||||
|
|
||||||
fn fun_to_str(decl: ast::fn_decl, name: ast::ident,
|
fn fun_to_str(decl: ast::fn_decl, name: ast::ident,
|
||||||
params: [ast::ty_param]) -> str {
|
params: [ast::ty_param]) -> str {
|
||||||
let buffer = io::mk_mem_buffer();
|
let buffer = io::mem_buffer();
|
||||||
let s = rust_printer(io::mem_buffer_writer(buffer));
|
let s = rust_printer(io::mem_buffer_writer(buffer));
|
||||||
print_fn(s, decl, name, params);
|
print_fn(s, decl, name, params);
|
||||||
end(s); // Close the head box
|
end(s); // Close the head box
|
||||||
@@ -124,7 +124,7 @@ fn test_fun_to_str() {
|
|||||||
|
|
||||||
fn res_to_str(decl: ast::fn_decl, name: ast::ident,
|
fn res_to_str(decl: ast::fn_decl, name: ast::ident,
|
||||||
params: [ast::ty_param]) -> str {
|
params: [ast::ty_param]) -> str {
|
||||||
let buffer = io::mk_mem_buffer();
|
let buffer = io::mem_buffer();
|
||||||
let s = rust_printer(io::mem_buffer_writer(buffer));
|
let s = rust_printer(io::mem_buffer_writer(buffer));
|
||||||
print_res(s, decl, name, params);
|
print_res(s, decl, name, params);
|
||||||
end(s); // Close the head box
|
end(s); // Close the head box
|
||||||
@@ -155,7 +155,7 @@ fn test_res_to_str() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn block_to_str(blk: ast::blk) -> str {
|
fn block_to_str(blk: ast::blk) -> str {
|
||||||
let buffer = io::mk_mem_buffer();
|
let buffer = io::mem_buffer();
|
||||||
let s = rust_printer(io::mem_buffer_writer(buffer));
|
let s = rust_printer(io::mem_buffer_writer(buffer));
|
||||||
// containing cbox, will be closed by print-block at }
|
// containing cbox, will be closed by print-block at }
|
||||||
cbox(s, indent_unit);
|
cbox(s, indent_unit);
|
||||||
@@ -1700,7 +1700,7 @@ fn escape_str(st: str, to_escape: char) -> str {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn to_str<T>(t: T, f: fn@(ps, T)) -> str {
|
fn to_str<T>(t: T, f: fn@(ps, T)) -> str {
|
||||||
let buffer = io::mk_mem_buffer();
|
let buffer = io::mem_buffer();
|
||||||
let s = rust_printer(io::mem_buffer_writer(buffer));
|
let s = rust_printer(io::mem_buffer_writer(buffer));
|
||||||
f(s, t);
|
f(s, t);
|
||||||
eof(s.s);
|
eof(s.s);
|
||||||
|
|||||||
32
src/test/auxiliary/auto_serialize_lib.rs
Normal file
32
src/test/auxiliary/auto_serialize_lib.rs
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
#[link(name="auto_serialize_lib", vers="0.0")];
|
||||||
|
|
||||||
|
use std;
|
||||||
|
import std::ebml;
|
||||||
|
import io::writer;
|
||||||
|
|
||||||
|
fn test_ser_and_deser<A>(a1: A,
|
||||||
|
expected: str,
|
||||||
|
ebml_ser_fn: fn(ebml::writer, A),
|
||||||
|
ebml_deser_fn: fn(ebml::ebml_deserializer) -> A,
|
||||||
|
io_ser_fn: fn(io::writer, A)) {
|
||||||
|
|
||||||
|
// check the pretty printer:
|
||||||
|
io_ser_fn(io::stdout(), a1);
|
||||||
|
let s = io::with_str_writer {|w| io_ser_fn(w, a1) };
|
||||||
|
#debug["s == %?", s];
|
||||||
|
assert s == expected;
|
||||||
|
|
||||||
|
// check the EBML serializer:
|
||||||
|
let buf = io::mem_buffer();
|
||||||
|
let w = ebml::writer(buf as io::writer);
|
||||||
|
ebml_ser_fn(w, a1);
|
||||||
|
let d = ebml::new_doc(@io::mem_buffer_buf(buf));
|
||||||
|
let a2 = ebml_deser_fn(ebml::ebml_deserializer(d));
|
||||||
|
io::print("\na1 = ");
|
||||||
|
io_ser_fn(io::stdout(), a1);
|
||||||
|
io::print("\na2 = ");
|
||||||
|
io_ser_fn(io::stdout(), a2);
|
||||||
|
io::print("\n");
|
||||||
|
assert a1 == a2;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#[link(name="cci_impl_lib", vers="0.0")];
|
||||||
|
|
||||||
impl helpers for uint {
|
impl helpers for uint {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to(v: uint, f: fn(uint)) {
|
fn to(v: uint, f: fn(uint)) {
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#[link(name="cci_iter_lib", vers="0.0")];
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn iter<T>(v: [T], f: fn(T)) {
|
fn iter<T>(v: [T], f: fn(T)) {
|
||||||
let i = 0u;
|
let i = 0u;
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#[link(name="cci_no_inline_lib", vers="0.0")];
|
||||||
|
|
||||||
// same as cci_iter_lib, more-or-less, but not marked inline
|
// same as cci_iter_lib, more-or-less, but not marked inline
|
||||||
fn iter(v: [uint], f: fn(uint)) {
|
fn iter(v: [uint], f: fn(uint)) {
|
||||||
let i = 0u;
|
let i = 0u;
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#[link(name="native_lib", vers="0.0")];
|
||||||
|
|
||||||
native mod rustrt {
|
native mod rustrt {
|
||||||
fn last_os_error() -> str;
|
fn last_os_error() -> str;
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,12 @@
|
|||||||
|
// aux-build:auto_serialize_lib.rs
|
||||||
|
// xfail-fast:aux-build currently incompatible
|
||||||
|
|
||||||
use std;
|
use std;
|
||||||
|
use auto_serialize_lib;
|
||||||
import std::prettyprint::serializer;
|
import std::prettyprint::serializer;
|
||||||
import std::io;
|
import std::ebml::serializer;
|
||||||
|
import std::ebml::deserializer;
|
||||||
|
import auto_serialize_lib::*;
|
||||||
|
|
||||||
#[auto_serialize]
|
#[auto_serialize]
|
||||||
enum expr {
|
enum expr {
|
||||||
@@ -10,10 +16,11 @@ enum expr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let ex = @plus(@minus(@val(3u), @val(10u)),
|
test_ser_and_deser(plus(@minus(@val(3u), @val(10u)),
|
||||||
@plus(@val(22u), @val(5u)));
|
@plus(@val(22u), @val(5u))),
|
||||||
let s = io::with_str_writer {|w| expr::serialize(w, *ex)};
|
"plus(@minus(@val(3u), @val(10u)), \
|
||||||
#debug["s == %?", s];
|
@plus(@val(22u), @val(5u)))",
|
||||||
assert s == "plus(@minus(@val(3u), @val(10u)), \
|
expr::serialize(_, _),
|
||||||
@plus(@val(22u), @val(5u)))";
|
expr::deserialize(_),
|
||||||
|
expr::serialize(_, _));
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,12 @@
|
|||||||
|
// aux-build:auto_serialize_lib.rs
|
||||||
|
// xfail-fast:aux-build currently incompatible
|
||||||
|
|
||||||
use std;
|
use std;
|
||||||
|
use auto_serialize_lib;
|
||||||
import std::prettyprint::serializer;
|
import std::prettyprint::serializer;
|
||||||
import std::io;
|
import std::ebml::serializer;
|
||||||
|
import std::ebml::deserializer;
|
||||||
|
import auto_serialize_lib::*;
|
||||||
|
|
||||||
// Test where we link various types used by name.
|
// Test where we link various types used by name.
|
||||||
|
|
||||||
@@ -11,9 +17,9 @@ type spanned<T> = {lo: uint, hi: uint, node: T};
|
|||||||
type spanned_uint = spanned<uint>;
|
type spanned_uint = spanned<uint>;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let x: spanned_uint = {lo: 0u, hi: 5u, node: 22u};
|
test_ser_and_deser({lo: 0u, hi: 5u, node: 22u},
|
||||||
spanned_uint::serialize(io::stdout(), x);
|
"{lo: 0u, hi: 5u, node: 22u}",
|
||||||
let s = io::with_str_writer {|w| spanned_uint::serialize(w, x)};
|
spanned_uint::serialize(_, _),
|
||||||
#debug["s == %?", s];
|
spanned_uint::deserialize(_),
|
||||||
assert s == "{lo: 0u, hi: 5u, node: 22u}";
|
spanned_uint::serialize(_, _));
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,12 @@
|
|||||||
|
// aux-build:auto_serialize_lib.rs
|
||||||
|
// xfail-fast:aux-build currently incompatible
|
||||||
|
|
||||||
use std;
|
use std;
|
||||||
|
use auto_serialize_lib;
|
||||||
import std::prettyprint::serializer;
|
import std::prettyprint::serializer;
|
||||||
import std::io;
|
import std::ebml::serializer;
|
||||||
|
import std::ebml::deserializer;
|
||||||
|
import auto_serialize_lib::*;
|
||||||
|
|
||||||
// Test where we link various types used by name.
|
// Test where we link various types used by name.
|
||||||
|
|
||||||
@@ -14,9 +20,9 @@ type some_rec = {v: uint_vec};
|
|||||||
enum an_enum = some_rec;
|
enum an_enum = some_rec;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let x = an_enum({v: [1u, 2u, 3u]});
|
test_ser_and_deser(an_enum({v: [1u, 2u, 3u]}),
|
||||||
an_enum::serialize(io::stdout(), x);
|
"an_enum({v: [1u, 2u, 3u]})",
|
||||||
let s = io::with_str_writer {|w| an_enum::serialize(w, x)};
|
an_enum::serialize(_, _),
|
||||||
#debug["s == %?", s];
|
an_enum::deserialize(_),
|
||||||
assert s == "an_enum({v: [1u, 2u, 3u]})";
|
an_enum::serialize(_, _));
|
||||||
}
|
}
|
||||||
@@ -1,12 +1,20 @@
|
|||||||
|
// aux-build:auto_serialize_lib.rs
|
||||||
|
// xfail-fast:aux-build currently incompatible
|
||||||
|
|
||||||
use std;
|
use std;
|
||||||
|
use auto_serialize_lib;
|
||||||
import std::prettyprint::serializer;
|
import std::prettyprint::serializer;
|
||||||
import std::io;
|
import std::ebml::serializer;
|
||||||
|
import std::ebml::deserializer;
|
||||||
|
import auto_serialize_lib::*;
|
||||||
|
|
||||||
#[auto_serialize]
|
#[auto_serialize]
|
||||||
type point = {x: uint, y: uint};
|
type point = {x: uint, y: uint};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let s = io::with_str_writer {|w| point::serialize(w, {x: 3u, y: 5u}) };
|
test_ser_and_deser({x: 3u, y: 5u},
|
||||||
#debug["s == %?", s];
|
"{x: 3u, y: 5u}",
|
||||||
assert s == "{x: 3u, y: 5u}";
|
point::serialize(_, _),
|
||||||
|
point::deserialize(_),
|
||||||
|
point::serialize(_, _));
|
||||||
}
|
}
|
||||||
@@ -1,13 +1,20 @@
|
|||||||
|
// aux-build:auto_serialize_lib.rs
|
||||||
|
// xfail-fast:aux-build currently incompatible
|
||||||
|
|
||||||
use std;
|
use std;
|
||||||
|
use auto_serialize_lib;
|
||||||
import std::prettyprint::serializer;
|
import std::prettyprint::serializer;
|
||||||
import std::io;
|
import std::ebml::serializer;
|
||||||
|
import std::ebml::deserializer;
|
||||||
|
import auto_serialize_lib::*;
|
||||||
|
|
||||||
#[auto_serialize]
|
#[auto_serialize]
|
||||||
type uint_vec = [uint];
|
type uint_vec = [uint];
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let ex = [1u, 2u, 3u];
|
test_ser_and_deser([1u, 2u, 3u],
|
||||||
let s = io::with_str_writer {|w| uint_vec::serialize(w, ex)};
|
"[1u, 2u, 3u]",
|
||||||
#debug["s == %?", s];
|
uint_vec::serialize(_, _),
|
||||||
assert s == "[1u, 2u, 3u]";
|
uint_vec::deserialize(_),
|
||||||
|
uint_vec::serialize(_, _));
|
||||||
}
|
}
|
||||||
@@ -100,7 +100,7 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn check_pp<T>(expr: T, f: fn(pprust::ps, T), expect: str) {
|
fn check_pp<T>(expr: T, f: fn(pprust::ps, T), expect: str) {
|
||||||
let buf = mk_mem_buffer();
|
let buf = mem_buffer();
|
||||||
let pp = pprust::rust_printer(buf as io::writer);
|
let pp = pprust::rust_printer(buf as io::writer);
|
||||||
f(pp, expr);
|
f(pp, expr);
|
||||||
pp::eof(pp.s);
|
pp::eof(pp.s);
|
||||||
|
|||||||
Reference in New Issue
Block a user