auto merge of #5819 : erickt/rust/incoming, r=erickt
Good morning, This first patch series adds support for `#[deriving(Decodable, Encodable)]`, but does not yet remove `#[auto_encode]` and `#[auto_decode]`. I need a snapshot to remove the old code. Along the way it also extends support for tuple structs and struct enum variants. Also, it includes a minor fix to the pretty printer. We decided a while ago to use 4 spaces to indent a match arm instead of 2. This updates the pretty printer to reflect that.
This commit is contained in:
commit
2f8b36fc16
16 changed files with 1464 additions and 203 deletions
|
|
@ -556,6 +556,7 @@ trait read_method_map_entry_helper {
|
|||
-> method_map_entry;
|
||||
}
|
||||
|
||||
#[cfg(stage0)]
|
||||
fn encode_method_map_entry(ecx: @e::EncodeContext,
|
||||
ebml_w: writer::Encoder,
|
||||
mme: method_map_entry) {
|
||||
|
|
@ -572,7 +573,27 @@ fn encode_method_map_entry(ecx: @e::EncodeContext,
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(stage1)]
|
||||
#[cfg(stage2)]
|
||||
#[cfg(stage3)]
|
||||
fn encode_method_map_entry(ecx: @e::EncodeContext,
|
||||
ebml_w: writer::Encoder,
|
||||
mme: method_map_entry) {
|
||||
do ebml_w.emit_struct("method_map_entry", 3) {
|
||||
do ebml_w.emit_struct_field("self_arg", 0u) {
|
||||
ebml_w.emit_arg(ecx, mme.self_arg);
|
||||
}
|
||||
do ebml_w.emit_struct_field("explicit_self", 2u) {
|
||||
mme.explicit_self.encode(&ebml_w);
|
||||
}
|
||||
do ebml_w.emit_struct_field("origin", 1u) {
|
||||
mme.origin.encode(&ebml_w);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl read_method_map_entry_helper for reader::Decoder {
|
||||
#[cfg(stage0)]
|
||||
fn read_method_map_entry(&self, xcx: @ExtendedDecodeContext)
|
||||
-> method_map_entry {
|
||||
do self.read_struct("method_map_entry", 3) {
|
||||
|
|
@ -592,6 +613,29 @@ impl read_method_map_entry_helper for reader::Decoder {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(stage1)]
|
||||
#[cfg(stage2)]
|
||||
#[cfg(stage3)]
|
||||
fn read_method_map_entry(&self, xcx: @ExtendedDecodeContext)
|
||||
-> method_map_entry {
|
||||
do self.read_struct("method_map_entry", 3) {
|
||||
method_map_entry {
|
||||
self_arg: self.read_struct_field("self_arg", 0u, || {
|
||||
self.read_arg(xcx)
|
||||
}),
|
||||
explicit_self: self.read_struct_field("explicit_self", 2u, || {
|
||||
let self_type: ast::self_ty_ = Decodable::decode(self);
|
||||
self_type
|
||||
}),
|
||||
origin: self.read_struct_field("origin", 1u, || {
|
||||
let method_origin: method_origin =
|
||||
Decodable::decode(self);
|
||||
method_origin.tr(xcx)
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl tr for method_origin {
|
||||
|
|
@ -782,6 +826,7 @@ impl ebml_writer_helpers for writer::Encoder {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(stage0)]
|
||||
fn emit_tpbt(&self, ecx: @e::EncodeContext,
|
||||
tpbt: ty::ty_param_bounds_and_ty) {
|
||||
do self.emit_struct("ty_param_bounds_and_ty", 2) {
|
||||
|
|
@ -804,6 +849,32 @@ impl ebml_writer_helpers for writer::Encoder {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(stage1)]
|
||||
#[cfg(stage2)]
|
||||
#[cfg(stage3)]
|
||||
fn emit_tpbt(&self, ecx: @e::EncodeContext,
|
||||
tpbt: ty::ty_param_bounds_and_ty) {
|
||||
do self.emit_struct("ty_param_bounds_and_ty", 2) {
|
||||
do self.emit_struct_field("generics", 0) {
|
||||
do self.emit_struct("Generics", 2) {
|
||||
do self.emit_struct_field("type_param_defs", 0) {
|
||||
do self.emit_from_vec(*tpbt.generics.type_param_defs)
|
||||
|type_param_def|
|
||||
{
|
||||
self.emit_type_param_def(ecx, type_param_def);
|
||||
}
|
||||
}
|
||||
do self.emit_struct_field("region_param", 1) {
|
||||
tpbt.generics.region_param.encode(self);
|
||||
}
|
||||
}
|
||||
}
|
||||
do self.emit_struct_field("ty", 1) {
|
||||
self.emit_ty(ecx, tpbt.ty);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trait write_tag_and_id {
|
||||
|
|
@ -1053,6 +1124,7 @@ impl ebml_decoder_decoder_helpers for reader::Decoder {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(stage0)]
|
||||
fn read_ty_param_bounds_and_ty(&self, xcx: @ExtendedDecodeContext)
|
||||
-> ty::ty_param_bounds_and_ty
|
||||
{
|
||||
|
|
@ -1075,6 +1147,31 @@ impl ebml_decoder_decoder_helpers for reader::Decoder {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(stage1)]
|
||||
#[cfg(stage2)]
|
||||
#[cfg(stage3)]
|
||||
fn read_ty_param_bounds_and_ty(&self, xcx: @ExtendedDecodeContext)
|
||||
-> ty::ty_param_bounds_and_ty
|
||||
{
|
||||
do self.read_struct("ty_param_bounds_and_ty", 2) {
|
||||
ty::ty_param_bounds_and_ty {
|
||||
generics: do self.read_struct("Generics", 2) {
|
||||
ty::Generics {
|
||||
type_param_defs: self.read_struct_field("type_param_defs", 0, || {
|
||||
@self.read_to_vec(|| self.read_type_param_def(xcx))
|
||||
}),
|
||||
region_param: self.read_struct_field(~"region_param", 1, || {
|
||||
Decodable::decode(self)
|
||||
})
|
||||
}
|
||||
},
|
||||
ty: self.read_struct_field("ty", 1, || {
|
||||
self.read_ty(xcx)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_def_id(&self, xcx: @ExtendedDecodeContext,
|
||||
source: tydecode::DefIdSource,
|
||||
did: ast::def_id) -> ast::def_id {
|
||||
|
|
|
|||
|
|
@ -335,18 +335,18 @@ pub mod reader {
|
|||
f()
|
||||
}
|
||||
|
||||
fn read_seq<T>(&self, f: &fn(uint) -> T) -> T {
|
||||
debug!("read_seq()");
|
||||
do self.push_doc(self.next_doc(EsVec)) {
|
||||
let len = self._next_uint(EsVecLen);
|
||||
debug!(" len=%u", len);
|
||||
f(len)
|
||||
fn read_enum_struct_variant<T>(&self, _names: &[&str], f: &fn(uint) -> T) -> T {
|
||||
debug!("read_enum_struct_variant()");
|
||||
let idx = self._next_uint(EsEnumVid);
|
||||
debug!(" idx=%u", idx);
|
||||
do self.push_doc(self.next_doc(EsEnumBody)) {
|
||||
f(idx)
|
||||
}
|
||||
}
|
||||
|
||||
fn read_seq_elt<T>(&self, idx: uint, f: &fn() -> T) -> T {
|
||||
debug!("read_seq_elt(idx=%u)", idx);
|
||||
self.push_doc(self.next_doc(EsVecElt), f)
|
||||
fn read_enum_struct_variant_field<T>(&self, name: &str, idx: uint, f: &fn() -> T) -> T {
|
||||
debug!("read_enum_struct_variant_arg(name=%?, idx=%u)", name, idx);
|
||||
f()
|
||||
}
|
||||
|
||||
fn read_struct<T>(&self, name: &str, _len: uint, f: &fn() -> T) -> T {
|
||||
|
|
@ -354,12 +354,42 @@ pub mod reader {
|
|||
f()
|
||||
}
|
||||
|
||||
#[cfg(stage0)]
|
||||
fn read_field<T>(&self, name: &str, idx: uint, f: &fn() -> T) -> T {
|
||||
debug!("read_field(name=%s, idx=%u)", name, idx);
|
||||
debug!("read_field(name=%?, idx=%u)", name, idx);
|
||||
self._check_label(name);
|
||||
f()
|
||||
}
|
||||
|
||||
#[cfg(stage1)]
|
||||
#[cfg(stage2)]
|
||||
#[cfg(stage3)]
|
||||
fn read_struct_field<T>(&self, name: &str, idx: uint, f: &fn() -> T) -> T {
|
||||
debug!("read_struct_field(name=%?, idx=%u)", name, idx);
|
||||
self._check_label(name);
|
||||
f()
|
||||
}
|
||||
|
||||
fn read_tuple<T>(&self, f: &fn(uint) -> T) -> T {
|
||||
debug!("read_tuple()");
|
||||
self.read_seq(f)
|
||||
}
|
||||
|
||||
fn read_tuple_arg<T>(&self, idx: uint, f: &fn() -> T) -> T {
|
||||
debug!("read_tuple_arg(idx=%u)", idx);
|
||||
self.read_seq_elt(idx, f)
|
||||
}
|
||||
|
||||
fn read_tuple_struct<T>(&self, name: &str, f: &fn(uint) -> T) -> T {
|
||||
debug!("read_tuple_struct(name=%?)", name);
|
||||
self.read_tuple(f)
|
||||
}
|
||||
|
||||
fn read_tuple_struct_arg<T>(&self, idx: uint, f: &fn() -> T) -> T {
|
||||
debug!("read_tuple_struct_arg(idx=%u)", idx);
|
||||
self.read_tuple_arg(idx, f)
|
||||
}
|
||||
|
||||
fn read_option<T>(&self, f: &fn(bool) -> T) -> T {
|
||||
debug!("read_option()");
|
||||
do self.read_enum("Option") || {
|
||||
|
|
@ -373,6 +403,20 @@ pub mod reader {
|
|||
}
|
||||
}
|
||||
|
||||
fn read_seq<T>(&self, f: &fn(uint) -> T) -> T {
|
||||
debug!("read_seq()");
|
||||
do self.push_doc(self.next_doc(EsVec)) {
|
||||
let len = self._next_uint(EsVecLen);
|
||||
debug!(" len=%u", len);
|
||||
f(len)
|
||||
}
|
||||
}
|
||||
|
||||
fn read_seq_elt<T>(&self, idx: uint, f: &fn() -> T) -> T {
|
||||
debug!("read_seq_elt(idx=%u)", idx);
|
||||
self.push_doc(self.next_doc(EsVecElt), f)
|
||||
}
|
||||
|
||||
fn read_map<T>(&self, _f: &fn(uint) -> T) -> T {
|
||||
debug!("read_map()");
|
||||
fail!(~"read_map is unimplemented");
|
||||
|
|
@ -606,13 +650,53 @@ pub mod writer {
|
|||
self._emit_label(name);
|
||||
self.wr_tag(EsEnum as uint, f)
|
||||
}
|
||||
|
||||
fn emit_enum_variant(&self, _v_name: &str, v_id: uint, _cnt: uint,
|
||||
f: &fn()) {
|
||||
self._emit_tagged_uint(EsEnumVid, v_id);
|
||||
self.wr_tag(EsEnumBody as uint, f)
|
||||
}
|
||||
|
||||
fn emit_enum_variant_arg(&self, _idx: uint, f: &fn()) { f() }
|
||||
|
||||
fn emit_enum_struct_variant(&self, v_name: &str, v_id: uint, cnt: uint, f: &fn()) {
|
||||
self.emit_enum_variant(v_name, v_id, cnt, f)
|
||||
}
|
||||
|
||||
fn emit_enum_struct_variant_field(&self, _f_name: &str, idx: uint, f: &fn()) {
|
||||
self.emit_enum_variant_arg(idx, f)
|
||||
}
|
||||
|
||||
fn emit_struct(&self, _name: &str, _len: uint, f: &fn()) { f() }
|
||||
#[cfg(stage0)]
|
||||
fn emit_field(&self, name: &str, _idx: uint, f: &fn()) {
|
||||
self._emit_label(name);
|
||||
f()
|
||||
}
|
||||
#[cfg(stage1)]
|
||||
#[cfg(stage2)]
|
||||
#[cfg(stage3)]
|
||||
fn emit_struct_field(&self, name: &str, _idx: uint, f: &fn()) {
|
||||
self._emit_label(name);
|
||||
f()
|
||||
}
|
||||
|
||||
fn emit_tuple(&self, len: uint, f: &fn()) { self.emit_seq(len, f) }
|
||||
fn emit_tuple_arg(&self, idx: uint, f: &fn()) { self.emit_seq_elt(idx, f) }
|
||||
|
||||
fn emit_tuple_struct(&self, _name: &str, len: uint, f: &fn()) { self.emit_seq(len, f) }
|
||||
fn emit_tuple_struct_arg(&self, idx: uint, f: &fn()) { self.emit_seq_elt(idx, f) }
|
||||
|
||||
fn emit_option(&self, f: &fn()) {
|
||||
self.emit_enum("Option", f);
|
||||
}
|
||||
fn emit_option_none(&self) {
|
||||
self.emit_enum_variant("None", 0, 0, || ())
|
||||
}
|
||||
fn emit_option_some(&self, f: &fn()) {
|
||||
self.emit_enum_variant("Some", 1, 1, f)
|
||||
}
|
||||
|
||||
fn emit_seq(&self, len: uint, f: &fn()) {
|
||||
do self.wr_tag(EsVec as uint) {
|
||||
self._emit_tagged_uint(EsVecLen, len);
|
||||
|
|
@ -624,22 +708,6 @@ pub mod writer {
|
|||
self.wr_tag(EsVecElt as uint, f)
|
||||
}
|
||||
|
||||
fn emit_struct(&self, _name: &str, _len: uint, f: &fn()) { f() }
|
||||
fn emit_field(&self, name: &str, _idx: uint, f: &fn()) {
|
||||
self._emit_label(name);
|
||||
f()
|
||||
}
|
||||
|
||||
fn emit_option(&self, f: &fn()) {
|
||||
self.emit_enum("Option", f);
|
||||
}
|
||||
fn emit_option_none(&self) {
|
||||
self.emit_enum_variant("None", 0, 0, || ())
|
||||
}
|
||||
fn emit_option_some(&self, f: &fn()) {
|
||||
self.emit_enum_variant("Some", 1, 1, f)
|
||||
}
|
||||
|
||||
fn emit_map(&self, _len: uint, _f: &fn()) {
|
||||
fail!(~"emit_map is unimplemented");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -109,6 +109,7 @@ impl serialize::Encoder for Encoder {
|
|||
fn emit_str(&self, v: &str) { self.wr.write_str(escape_str(v)) }
|
||||
|
||||
fn emit_enum(&self, _name: &str, f: &fn()) { f() }
|
||||
|
||||
fn emit_enum_variant(&self, name: &str, _id: uint, cnt: uint, f: &fn()) {
|
||||
// enums are encoded as strings or vectors:
|
||||
// Bunny => "Bunny"
|
||||
|
|
@ -126,10 +127,50 @@ impl serialize::Encoder for Encoder {
|
|||
}
|
||||
|
||||
fn emit_enum_variant_arg(&self, idx: uint, f: &fn()) {
|
||||
if (idx != 0) {self.wr.write_char(',');}
|
||||
if idx != 0 {self.wr.write_char(',');}
|
||||
f();
|
||||
}
|
||||
|
||||
fn emit_enum_struct_variant(&self, name: &str, id: uint, cnt: uint, f: &fn()) {
|
||||
self.emit_enum_variant(name, id, cnt, f)
|
||||
}
|
||||
|
||||
fn emit_enum_struct_variant_field(&self, _field: &str, idx: uint, f: &fn()) {
|
||||
self.emit_enum_variant_arg(idx, f)
|
||||
}
|
||||
|
||||
fn emit_struct(&self, _name: &str, _len: uint, f: &fn()) {
|
||||
self.wr.write_char('{');
|
||||
f();
|
||||
self.wr.write_char('}');
|
||||
}
|
||||
#[cfg(stage0)]
|
||||
fn emit_field(&self, name: &str, idx: uint, f: &fn()) {
|
||||
if idx != 0 { self.wr.write_char(','); }
|
||||
self.wr.write_str(escape_str(name));
|
||||
self.wr.write_char(':');
|
||||
f();
|
||||
}
|
||||
#[cfg(stage1)]
|
||||
#[cfg(stage2)]
|
||||
#[cfg(stage3)]
|
||||
fn emit_struct_field(&self, name: &str, idx: uint, f: &fn()) {
|
||||
if idx != 0 { self.wr.write_char(','); }
|
||||
self.wr.write_str(escape_str(name));
|
||||
self.wr.write_char(':');
|
||||
f();
|
||||
}
|
||||
|
||||
fn emit_tuple(&self, len: uint, f: &fn()) { self.emit_seq(len, f) }
|
||||
fn emit_tuple_arg(&self, idx: uint, f: &fn()) { self.emit_seq_elt(idx, f) }
|
||||
|
||||
fn emit_tuple_struct(&self, _name: &str, len: uint, f: &fn()) { self.emit_seq(len, f) }
|
||||
fn emit_tuple_struct_arg(&self, idx: uint, f: &fn()) { self.emit_seq_elt(idx, f) }
|
||||
|
||||
fn emit_option(&self, f: &fn()) { f(); }
|
||||
fn emit_option_none(&self) { self.emit_nil(); }
|
||||
fn emit_option_some(&self, f: &fn()) { f(); }
|
||||
|
||||
fn emit_seq(&self, _len: uint, f: &fn()) {
|
||||
self.wr.write_char('[');
|
||||
f();
|
||||
|
|
@ -141,22 +182,6 @@ impl serialize::Encoder for Encoder {
|
|||
f()
|
||||
}
|
||||
|
||||
fn emit_struct(&self, _name: &str, _len: uint, f: &fn()) {
|
||||
self.wr.write_char('{');
|
||||
f();
|
||||
self.wr.write_char('}');
|
||||
}
|
||||
fn emit_field(&self, name: &str, idx: uint, f: &fn()) {
|
||||
if idx != 0 { self.wr.write_char(','); }
|
||||
self.wr.write_str(escape_str(name));
|
||||
self.wr.write_char(':');
|
||||
f();
|
||||
}
|
||||
|
||||
fn emit_option(&self, f: &fn()) { f(); }
|
||||
fn emit_option_none(&self) { self.emit_nil(); }
|
||||
fn emit_option_some(&self, f: &fn()) { f(); }
|
||||
|
||||
fn emit_map(&self, _len: uint, f: &fn()) {
|
||||
self.wr.write_char('{');
|
||||
f();
|
||||
|
|
@ -216,6 +241,7 @@ impl serialize::Encoder for PrettyEncoder {
|
|||
fn emit_str(&self, v: &str) { self.wr.write_str(escape_str(v)); }
|
||||
|
||||
fn emit_enum(&self, _name: &str, f: &fn()) { f() }
|
||||
|
||||
fn emit_enum_variant(&self, name: &str, _id: uint, cnt: uint, f: &fn()) {
|
||||
if cnt == 0 {
|
||||
self.wr.write_str(escape_str(name));
|
||||
|
|
@ -233,6 +259,7 @@ impl serialize::Encoder for PrettyEncoder {
|
|||
self.wr.write_char(']');
|
||||
}
|
||||
}
|
||||
|
||||
fn emit_enum_variant_arg(&self, idx: uint, f: &fn()) {
|
||||
if idx != 0 {
|
||||
self.wr.write_str(",\n");
|
||||
|
|
@ -241,6 +268,65 @@ impl serialize::Encoder for PrettyEncoder {
|
|||
f()
|
||||
}
|
||||
|
||||
fn emit_enum_struct_variant(&self, name: &str, id: uint, cnt: uint, f: &fn()) {
|
||||
self.emit_enum_variant(name, id, cnt, f)
|
||||
}
|
||||
|
||||
fn emit_enum_struct_variant_field(&self, _field: &str, idx: uint, f: &fn()) {
|
||||
self.emit_enum_variant_arg(idx, f)
|
||||
}
|
||||
|
||||
|
||||
fn emit_struct(&self, _name: &str, len: uint, f: &fn()) {
|
||||
if len == 0 {
|
||||
self.wr.write_str("{}");
|
||||
} else {
|
||||
self.wr.write_char('{');
|
||||
self.indent += 2;
|
||||
f();
|
||||
self.wr.write_char('\n');
|
||||
self.indent -= 2;
|
||||
self.wr.write_str(spaces(self.indent));
|
||||
self.wr.write_char('}');
|
||||
}
|
||||
}
|
||||
#[cfg(stage0)]
|
||||
fn emit_field(&self, name: &str, idx: uint, f: &fn()) {
|
||||
if idx == 0 {
|
||||
self.wr.write_char('\n');
|
||||
} else {
|
||||
self.wr.write_str(",\n");
|
||||
}
|
||||
self.wr.write_str(spaces(self.indent));
|
||||
self.wr.write_str(escape_str(name));
|
||||
self.wr.write_str(": ");
|
||||
f();
|
||||
}
|
||||
#[cfg(stage1)]
|
||||
#[cfg(stage2)]
|
||||
#[cfg(stage3)]
|
||||
fn emit_struct_field(&self, name: &str, idx: uint, f: &fn()) {
|
||||
if idx == 0 {
|
||||
self.wr.write_char('\n');
|
||||
} else {
|
||||
self.wr.write_str(",\n");
|
||||
}
|
||||
self.wr.write_str(spaces(self.indent));
|
||||
self.wr.write_str(escape_str(name));
|
||||
self.wr.write_str(": ");
|
||||
f();
|
||||
}
|
||||
|
||||
fn emit_tuple(&self, len: uint, f: &fn()) { self.emit_seq(len, f) }
|
||||
fn emit_tuple_arg(&self, idx: uint, f: &fn()) { self.emit_seq_elt(idx, f) }
|
||||
|
||||
fn emit_tuple_struct(&self, _name: &str, len: uint, f: &fn()) { self.emit_seq(len, f) }
|
||||
fn emit_tuple_struct_arg(&self, idx: uint, f: &fn()) { self.emit_seq_elt(idx, f) }
|
||||
|
||||
fn emit_option(&self, f: &fn()) { f(); }
|
||||
fn emit_option_none(&self) { self.emit_nil(); }
|
||||
fn emit_option_some(&self, f: &fn()) { f(); }
|
||||
|
||||
fn emit_seq(&self, len: uint, f: &fn()) {
|
||||
if len == 0 {
|
||||
self.wr.write_str("[]");
|
||||
|
|
@ -264,35 +350,6 @@ impl serialize::Encoder for PrettyEncoder {
|
|||
f()
|
||||
}
|
||||
|
||||
fn emit_struct(&self, _name: &str, len: uint, f: &fn()) {
|
||||
if len == 0 {
|
||||
self.wr.write_str("{}");
|
||||
} else {
|
||||
self.wr.write_char('{');
|
||||
self.indent += 2;
|
||||
f();
|
||||
self.wr.write_char('\n');
|
||||
self.indent -= 2;
|
||||
self.wr.write_str(spaces(self.indent));
|
||||
self.wr.write_char('}');
|
||||
}
|
||||
}
|
||||
fn emit_field(&self, name: &str, idx: uint, f: &fn()) {
|
||||
if idx == 0 {
|
||||
self.wr.write_char('\n');
|
||||
} else {
|
||||
self.wr.write_str(",\n");
|
||||
}
|
||||
self.wr.write_str(spaces(self.indent));
|
||||
self.wr.write_str(escape_str(name));
|
||||
self.wr.write_str(": ");
|
||||
f();
|
||||
}
|
||||
|
||||
fn emit_option(&self, f: &fn()) { f(); }
|
||||
fn emit_option_none(&self) { self.emit_nil(); }
|
||||
fn emit_option_some(&self, f: &fn()) { f(); }
|
||||
|
||||
fn emit_map(&self, len: uint, f: &fn()) {
|
||||
if len == 0 {
|
||||
self.wr.write_str("{}");
|
||||
|
|
@ -827,6 +884,93 @@ impl serialize::Decoder for Decoder {
|
|||
f()
|
||||
}
|
||||
|
||||
fn read_enum_struct_variant<T>(&self, names: &[&str], f: &fn(uint) -> T) -> T {
|
||||
debug!("read_enum_struct_variant(names=%?)", names);
|
||||
self.read_enum_variant(names, f)
|
||||
}
|
||||
|
||||
|
||||
fn read_enum_struct_variant_field<T>(&self, name: &str, idx: uint, f: &fn() -> T) -> T {
|
||||
debug!("read_enum_struct_variant_field(name=%?, idx=%u)", name, idx);
|
||||
self.read_enum_variant_arg(idx, f)
|
||||
}
|
||||
|
||||
fn read_struct<T>(&self, name: &str, len: uint, f: &fn() -> T) -> T {
|
||||
debug!("read_struct(name=%s, len=%u)", name, len);
|
||||
let value = f();
|
||||
self.stack.pop();
|
||||
value
|
||||
}
|
||||
|
||||
#[cfg(stage0)]
|
||||
fn read_field<T>(&self, name: &str, idx: uint, f: &fn() -> T) -> T {
|
||||
debug!("read_field(name=%?, idx=%u)", name, idx);
|
||||
match self.stack.pop() {
|
||||
Object(obj) => {
|
||||
let mut obj = obj;
|
||||
let value = match obj.pop(&name.to_owned()) {
|
||||
None => fail!(fmt!("no such field: %s", name)),
|
||||
Some(json) => {
|
||||
self.stack.push(json);
|
||||
f()
|
||||
}
|
||||
};
|
||||
self.stack.push(Object(obj));
|
||||
value
|
||||
}
|
||||
value => fail!(fmt!("not an object: %?", value))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(stage1)]
|
||||
#[cfg(stage2)]
|
||||
#[cfg(stage3)]
|
||||
fn read_struct_field<T>(&self, name: &str, idx: uint, f: &fn() -> T) -> T {
|
||||
debug!("read_struct_field(name=%?, idx=%u)", name, idx);
|
||||
match self.stack.pop() {
|
||||
Object(obj) => {
|
||||
let mut obj = obj;
|
||||
let value = match obj.pop(&name.to_owned()) {
|
||||
None => fail!(fmt!("no such field: %s", name)),
|
||||
Some(json) => {
|
||||
self.stack.push(json);
|
||||
f()
|
||||
}
|
||||
};
|
||||
self.stack.push(Object(obj));
|
||||
value
|
||||
}
|
||||
value => fail!(fmt!("not an object: %?", value))
|
||||
}
|
||||
}
|
||||
|
||||
fn read_tuple<T>(&self, f: &fn(uint) -> T) -> T {
|
||||
debug!("read_tuple()");
|
||||
self.read_seq(f)
|
||||
}
|
||||
|
||||
fn read_tuple_arg<T>(&self, idx: uint, f: &fn() -> T) -> T {
|
||||
debug!("read_tuple_arg(idx=%u)", idx);
|
||||
self.read_seq_elt(idx, f)
|
||||
}
|
||||
|
||||
fn read_tuple_struct<T>(&self, name: &str, f: &fn(uint) -> T) -> T {
|
||||
debug!("read_tuple_struct(name=%?)", name);
|
||||
self.read_tuple(f)
|
||||
}
|
||||
|
||||
fn read_tuple_struct_arg<T>(&self, idx: uint, f: &fn() -> T) -> T {
|
||||
debug!("read_tuple_struct_arg(idx=%u)", idx);
|
||||
self.read_tuple_arg(idx, f)
|
||||
}
|
||||
|
||||
fn read_option<T>(&self, f: &fn(bool) -> T) -> T {
|
||||
match self.stack.pop() {
|
||||
Null => f(false),
|
||||
value => { self.stack.push(value); f(true) }
|
||||
}
|
||||
}
|
||||
|
||||
fn read_seq<T>(&self, f: &fn(uint) -> T) -> T {
|
||||
debug!("read_seq()");
|
||||
let len = match self.stack.pop() {
|
||||
|
|
@ -847,39 +991,6 @@ impl serialize::Decoder for Decoder {
|
|||
f()
|
||||
}
|
||||
|
||||
fn read_struct<T>(&self, name: &str, len: uint, f: &fn() -> T) -> T {
|
||||
debug!("read_struct(name=%s, len=%u)", name, len);
|
||||
let value = f();
|
||||
self.stack.pop();
|
||||
value
|
||||
}
|
||||
|
||||
fn read_field<T>(&self, name: &str, idx: uint, f: &fn() -> T) -> T {
|
||||
debug!("read_field(%s, idx=%u)", name, idx);
|
||||
match self.stack.pop() {
|
||||
Object(obj) => {
|
||||
let mut obj = obj;
|
||||
let value = match obj.pop(&name.to_owned()) {
|
||||
None => fail!(fmt!("no such field: %s", name)),
|
||||
Some(json) => {
|
||||
self.stack.push(json);
|
||||
f()
|
||||
}
|
||||
};
|
||||
self.stack.push(Object(obj));
|
||||
value
|
||||
}
|
||||
value => fail!(fmt!("not an object: %?", value))
|
||||
}
|
||||
}
|
||||
|
||||
fn read_option<T>(&self, f: &fn(bool) -> T) -> T {
|
||||
match self.stack.pop() {
|
||||
Null => f(false),
|
||||
value => { self.stack.push(value); f(true) }
|
||||
}
|
||||
}
|
||||
|
||||
fn read_map<T>(&self, f: &fn(uint) -> T) -> T {
|
||||
debug!("read_map()");
|
||||
let len = match self.stack.pop() {
|
||||
|
|
|
|||
|
|
@ -44,22 +44,36 @@ pub trait Encoder {
|
|||
fn emit_str(&self, v: &str);
|
||||
|
||||
// Compound types:
|
||||
|
||||
fn emit_enum(&self, name: &str, f: &fn());
|
||||
fn emit_enum_variant(&self, v_name: &str, v_id: uint, sz: uint, f: &fn());
|
||||
fn emit_enum_variant_arg(&self, idx: uint, f: &fn());
|
||||
|
||||
fn emit_seq(&self, len: uint, f: &fn());
|
||||
fn emit_seq_elt(&self, idx: uint, f: &fn());
|
||||
fn emit_enum_variant(&self, v_name: &str, v_id: uint, len: uint, f: &fn());
|
||||
fn emit_enum_variant_arg(&self, a_idx: uint, f: &fn());
|
||||
|
||||
fn emit_struct(&self, name: &str, _len: uint, f: &fn());
|
||||
fn emit_enum_struct_variant(&self, v_name: &str, v_id: uint, len: uint, f: &fn());
|
||||
fn emit_enum_struct_variant_field(&self, f_name: &str, f_idx: uint, f: &fn());
|
||||
|
||||
fn emit_struct(&self, name: &str, len: uint, f: &fn());
|
||||
#[cfg(stage0)]
|
||||
fn emit_field(&self, f_name: &str, f_idx: uint, f: &fn());
|
||||
#[cfg(stage1)]
|
||||
#[cfg(stage2)]
|
||||
#[cfg(stage3)]
|
||||
fn emit_struct_field(&self, f_name: &str, f_idx: uint, f: &fn());
|
||||
|
||||
fn emit_tuple(&self, len: uint, f: &fn());
|
||||
fn emit_tuple_arg(&self, idx: uint, f: &fn());
|
||||
|
||||
fn emit_tuple_struct(&self, name: &str, len: uint, f: &fn());
|
||||
fn emit_tuple_struct_arg(&self, f_idx: uint, f: &fn());
|
||||
|
||||
// Specialized types:
|
||||
fn emit_option(&self, f: &fn());
|
||||
fn emit_option_none(&self);
|
||||
fn emit_option_some(&self, f: &fn());
|
||||
|
||||
fn emit_seq(&self, len: uint, f: &fn());
|
||||
fn emit_seq_elt(&self, idx: uint, f: &fn());
|
||||
|
||||
fn emit_map(&self, len: uint, f: &fn());
|
||||
fn emit_map_elt_key(&self, idx: uint, f: &fn());
|
||||
fn emit_map_elt_val(&self, idx: uint, f: &fn());
|
||||
|
|
@ -87,18 +101,33 @@ pub trait Decoder {
|
|||
|
||||
// Compound types:
|
||||
fn read_enum<T>(&self, name: &str, f: &fn() -> T) -> T;
|
||||
|
||||
fn read_enum_variant<T>(&self, names: &[&str], f: &fn(uint) -> T) -> T;
|
||||
fn read_enum_variant_arg<T>(&self, idx: uint, f: &fn() -> T) -> T;
|
||||
fn read_enum_variant_arg<T>(&self, a_idx: uint, f: &fn() -> T) -> T;
|
||||
|
||||
fn read_seq<T>(&self, f: &fn(uint) -> T) -> T;
|
||||
fn read_seq_elt<T>(&self, idx: uint, f: &fn() -> T) -> T;
|
||||
fn read_enum_struct_variant<T>(&self, names: &[&str], f: &fn(uint) -> T) -> T;
|
||||
fn read_enum_struct_variant_field<T>(&self, &f_name: &str, f_idx: uint, f: &fn() -> T) -> T;
|
||||
|
||||
fn read_struct<T>(&self, name: &str, _len: uint, f: &fn() -> T) -> T;
|
||||
fn read_field<T>(&self, name: &str, idx: uint, f: &fn() -> T) -> T;
|
||||
fn read_struct<T>(&self, s_name: &str, len: uint, f: &fn() -> T) -> T;
|
||||
#[cfg(stage0)]
|
||||
fn read_field<T>(&self, f_name: &str, f_idx: uint, f: &fn() -> T) -> T;
|
||||
#[cfg(stage1)]
|
||||
#[cfg(stage2)]
|
||||
#[cfg(stage3)]
|
||||
fn read_struct_field<T>(&self, f_name: &str, f_idx: uint, f: &fn() -> T) -> T;
|
||||
|
||||
fn read_tuple<T>(&self, f: &fn(uint) -> T) -> T;
|
||||
fn read_tuple_arg<T>(&self, a_idx: uint, f: &fn() -> T) -> T;
|
||||
|
||||
fn read_tuple_struct<T>(&self, s_name: &str, f: &fn(uint) -> T) -> T;
|
||||
fn read_tuple_struct_arg<T>(&self, a_idx: uint, f: &fn() -> T) -> T;
|
||||
|
||||
// Specialized types:
|
||||
fn read_option<T>(&self, f: &fn(bool) -> T) -> T;
|
||||
|
||||
fn read_seq<T>(&self, f: &fn(uint) -> T) -> T;
|
||||
fn read_seq_elt<T>(&self, idx: uint, f: &fn() -> T) -> T;
|
||||
|
||||
fn read_map<T>(&self, f: &fn(uint) -> T) -> T;
|
||||
fn read_map_elt_key<T>(&self, idx: uint, f: &fn() -> T) -> T;
|
||||
fn read_map_elt_val<T>(&self, idx: uint, f: &fn() -> T) -> T;
|
||||
|
|
|
|||
|
|
@ -732,12 +732,12 @@ fn mk_struct_ser_impl(
|
|||
)
|
||||
);
|
||||
|
||||
// ast for `__s.emit_field($(name), $(idx), $(expr_lambda))`
|
||||
// ast for `__s.emit_struct_field($(name), $(idx), $(expr_lambda))`
|
||||
cx.stmt(
|
||||
cx.expr_method_call(
|
||||
span,
|
||||
cx.expr_var(span, ~"__s"),
|
||||
cx.ident_of(~"emit_field"),
|
||||
cx.ident_of(~"emit_struct_field"),
|
||||
~[
|
||||
cx.lit_str(span, @cx.str_of(field.ident)),
|
||||
cx.lit_uint(span, idx),
|
||||
|
|
@ -786,11 +786,11 @@ fn mk_struct_deser_impl(
|
|||
)
|
||||
);
|
||||
|
||||
// ast for `__d.read_field($(name), $(idx), $(expr_lambda))`
|
||||
// ast for `__d.read_struct_field($(name), $(idx), $(expr_lambda))`
|
||||
let expr: @ast::expr = cx.expr_method_call(
|
||||
span,
|
||||
cx.expr_var(span, ~"__d"),
|
||||
cx.ident_of(~"read_field"),
|
||||
cx.ident_of(~"read_struct_field"),
|
||||
~[
|
||||
cx.lit_str(span, @cx.str_of(field.ident)),
|
||||
cx.lit_uint(span, idx),
|
||||
|
|
@ -1253,20 +1253,35 @@ mod test {
|
|||
self.add_to_log(CallToEmitEnumVariantArg (idx)); f();
|
||||
}
|
||||
|
||||
fn emit_seq(&self, +_len: uint, f: &fn()) {
|
||||
self.add_unknown_to_log(); f();
|
||||
fn emit_enum_struct_variant(&self, name: &str, id: uint, cnt: uint, f: &fn()) {
|
||||
self.emit_enum_variant(name, id, cnt, f)
|
||||
}
|
||||
fn emit_seq_elt(&self, +_idx: uint, f: &fn()) {
|
||||
self.add_unknown_to_log(); f();
|
||||
|
||||
fn emit_enum_struct_variant_field(&self, _name: &str, idx: uint, f: &fn()) {
|
||||
self.emit_enum_variant_arg(idx, f)
|
||||
}
|
||||
|
||||
fn emit_struct(&self, name: &str, +len: uint, f: &fn()) {
|
||||
self.add_to_log(CallToEmitStruct (name.to_str(),len)); f();
|
||||
}
|
||||
fn emit_field(&self, name: &str, +idx: uint, f: &fn()) {
|
||||
fn emit_struct_field(&self, name: &str, +idx: uint, f: &fn()) {
|
||||
self.add_to_log(CallToEmitField (name.to_str(),idx)); f();
|
||||
}
|
||||
|
||||
fn emit_tuple(&self, _len: uint, f: &fn()) {
|
||||
self.add_unknown_to_log(); f();
|
||||
}
|
||||
fn emit_tuple_arg(&self, _idx: uint, f: &fn()) {
|
||||
self.add_unknown_to_log(); f();
|
||||
}
|
||||
|
||||
fn emit_tuple_struct(&self, _name: &str, _len: uint, f: &fn()) {
|
||||
self.add_unknown_to_log(); f();
|
||||
}
|
||||
fn emit_tuple_struct_arg(&self, _idx: uint, f: &fn()) {
|
||||
self.add_unknown_to_log(); f();
|
||||
}
|
||||
|
||||
fn emit_option(&self, f: &fn()) {
|
||||
self.add_to_log(CallToEmitOption);
|
||||
f();
|
||||
|
|
@ -1279,6 +1294,13 @@ mod test {
|
|||
f();
|
||||
}
|
||||
|
||||
fn emit_seq(&self, +_len: uint, f: &fn()) {
|
||||
self.add_unknown_to_log(); f();
|
||||
}
|
||||
fn emit_seq_elt(&self, +_idx: uint, f: &fn()) {
|
||||
self.add_unknown_to_log(); f();
|
||||
}
|
||||
|
||||
fn emit_map(&self, _len: uint, f: &fn()) {
|
||||
self.add_unknown_to_log(); f();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,12 +64,7 @@ pub fn mk_unary(cx: @ext_ctxt, sp: span, op: ast::unop, e: @ast::expr)
|
|||
mk_expr(cx, sp, ast::expr_unary(op, e))
|
||||
}
|
||||
pub fn mk_raw_path(sp: span, +idents: ~[ast::ident]) -> @ast::Path {
|
||||
let p = @ast::Path { span: sp,
|
||||
global: false,
|
||||
idents: idents,
|
||||
rp: None,
|
||||
types: ~[] };
|
||||
return p;
|
||||
mk_raw_path_(sp, idents, ~[])
|
||||
}
|
||||
pub fn mk_raw_path_(sp: span,
|
||||
+idents: ~[ast::ident],
|
||||
|
|
@ -82,11 +77,16 @@ pub fn mk_raw_path_(sp: span,
|
|||
types: types }
|
||||
}
|
||||
pub fn mk_raw_path_global(sp: span, +idents: ~[ast::ident]) -> @ast::Path {
|
||||
mk_raw_path_global_(sp, idents, ~[])
|
||||
}
|
||||
pub fn mk_raw_path_global_(sp: span,
|
||||
+idents: ~[ast::ident],
|
||||
+types: ~[@ast::Ty]) -> @ast::Path {
|
||||
@ast::Path { span: sp,
|
||||
global: true,
|
||||
idents: idents,
|
||||
rp: None,
|
||||
types: ~[] }
|
||||
types: types }
|
||||
}
|
||||
pub fn mk_path(cx: @ext_ctxt, sp: span, +idents: ~[ast::ident])
|
||||
-> @ast::expr {
|
||||
|
|
@ -271,6 +271,36 @@ pub fn mk_simple_block(cx: @ext_ctxt,
|
|||
span: span,
|
||||
}
|
||||
}
|
||||
pub fn mk_lambda_(cx: @ext_ctxt,
|
||||
span: span,
|
||||
fn_decl: ast::fn_decl,
|
||||
blk: ast::blk)
|
||||
-> @ast::expr {
|
||||
mk_expr(cx, span, ast::expr_fn_block(fn_decl, blk))
|
||||
}
|
||||
pub fn mk_lambda(cx: @ext_ctxt,
|
||||
span: span,
|
||||
fn_decl: ast::fn_decl,
|
||||
expr: @ast::expr)
|
||||
-> @ast::expr {
|
||||
let blk = mk_simple_block(cx, span, expr);
|
||||
mk_lambda_(cx, span, fn_decl, blk)
|
||||
}
|
||||
pub fn mk_lambda_stmts(cx: @ext_ctxt,
|
||||
span: span,
|
||||
fn_decl: ast::fn_decl,
|
||||
stmts: ~[@ast::stmt])
|
||||
-> @ast::expr {
|
||||
let blk = mk_block(cx, span, ~[], stmts, None);
|
||||
mk_lambda(cx, span, fn_decl, blk)
|
||||
}
|
||||
pub fn mk_lambda_no_args(cx: @ext_ctxt,
|
||||
span: span,
|
||||
expr: @ast::expr)
|
||||
-> @ast::expr {
|
||||
let fn_decl = mk_fn_decl(~[], mk_ty_infer(cx, span));
|
||||
mk_lambda(cx, span, fn_decl, expr)
|
||||
}
|
||||
pub fn mk_copy(cx: @ext_ctxt, sp: span, e: @ast::expr) -> @ast::expr {
|
||||
mk_expr(cx, sp, ast::expr_copy(e))
|
||||
}
|
||||
|
|
@ -280,11 +310,20 @@ pub fn mk_managed(cx: @ext_ctxt, sp: span, e: @ast::expr) -> @ast::expr {
|
|||
pub fn mk_pat(cx: @ext_ctxt, span: span, +pat: ast::pat_) -> @ast::pat {
|
||||
@ast::pat { id: cx.next_id(), node: pat, span: span }
|
||||
}
|
||||
pub fn mk_pat_wild(cx: @ext_ctxt, span: span) -> @ast::pat {
|
||||
mk_pat(cx, span, ast::pat_wild)
|
||||
}
|
||||
pub fn mk_pat_lit(cx: @ext_ctxt,
|
||||
span: span,
|
||||
expr: @ast::expr) -> @ast::pat {
|
||||
mk_pat(cx, span, ast::pat_lit(expr))
|
||||
}
|
||||
pub fn mk_pat_ident(cx: @ext_ctxt,
|
||||
span: span,
|
||||
ident: ast::ident) -> @ast::pat {
|
||||
mk_pat_ident_with_binding_mode(cx, span, ident, ast::bind_by_copy)
|
||||
}
|
||||
|
||||
pub fn mk_pat_ident_with_binding_mode(cx: @ext_ctxt,
|
||||
span: span,
|
||||
ident: ast::ident,
|
||||
|
|
@ -337,12 +376,35 @@ pub fn mk_ty_path_global(cx: @ext_ctxt,
|
|||
let ty = @ast::Ty { id: cx.next_id(), node: ty, span: span };
|
||||
ty
|
||||
}
|
||||
pub fn mk_ty_rptr(cx: @ext_ctxt,
|
||||
span: span,
|
||||
ty: @ast::Ty,
|
||||
mutbl: ast::mutability)
|
||||
-> @ast::Ty {
|
||||
@ast::Ty {
|
||||
id: cx.next_id(),
|
||||
span: span,
|
||||
node: ast::ty_rptr(
|
||||
None,
|
||||
ast::mt { ty: ty, mutbl: mutbl }
|
||||
),
|
||||
}
|
||||
}
|
||||
pub fn mk_ty_infer(cx: @ext_ctxt, span: span) -> @ast::Ty {
|
||||
@ast::Ty {
|
||||
id: cx.next_id(),
|
||||
node: ast::ty_infer,
|
||||
span: span,
|
||||
}
|
||||
}
|
||||
pub fn mk_trait_ref_global(cx: @ext_ctxt,
|
||||
span: span,
|
||||
+idents: ~[ ast::ident ])
|
||||
-> @ast::trait_ref
|
||||
{
|
||||
let path = build::mk_raw_path_global(span, idents);
|
||||
mk_trait_ref_(cx, build::mk_raw_path_global(span, idents))
|
||||
}
|
||||
pub fn mk_trait_ref_(cx: @ext_ctxt, path: @ast::Path) -> @ast::trait_ref {
|
||||
@ast::trait_ref {
|
||||
path: path,
|
||||
ref_id: cx.next_id()
|
||||
|
|
@ -371,6 +433,16 @@ pub fn mk_arg(cx: @ext_ctxt,
|
|||
pub fn mk_fn_decl(+inputs: ~[ast::arg], output: @ast::Ty) -> ast::fn_decl {
|
||||
ast::fn_decl { inputs: inputs, output: output, cf: ast::return_val }
|
||||
}
|
||||
pub fn mk_trait_ty_param_bound_global(cx: @ext_ctxt,
|
||||
span: span,
|
||||
+idents: ~[ast::ident])
|
||||
-> ast::TyParamBound {
|
||||
ast::TraitTyParamBound(mk_trait_ref_global(cx, span, idents))
|
||||
}
|
||||
pub fn mk_trait_ty_param_bound_(cx: @ext_ctxt,
|
||||
path: @ast::Path) -> ast::TyParamBound {
|
||||
ast::TraitTyParamBound(mk_trait_ref_(cx, path))
|
||||
}
|
||||
pub fn mk_ty_param(cx: @ext_ctxt,
|
||||
ident: ast::ident,
|
||||
bounds: @OptVec<ast::TyParamBound>)
|
||||
|
|
@ -379,8 +451,38 @@ pub fn mk_ty_param(cx: @ext_ctxt,
|
|||
}
|
||||
pub fn mk_lifetime(cx: @ext_ctxt,
|
||||
span: span,
|
||||
ident: ast::ident) -> ast::Lifetime
|
||||
{
|
||||
ident: ast::ident)
|
||||
-> ast::Lifetime {
|
||||
ast::Lifetime { id: cx.next_id(), span: span, ident: ident }
|
||||
}
|
||||
|
||||
pub fn mk_arm(cx: @ext_ctxt,
|
||||
span: span,
|
||||
pats: ~[@ast::pat],
|
||||
expr: @ast::expr)
|
||||
-> ast::arm {
|
||||
ast::arm {
|
||||
pats: pats,
|
||||
guard: None,
|
||||
body: mk_simple_block(cx, span, expr)
|
||||
}
|
||||
}
|
||||
pub fn mk_unreachable(cx: @ext_ctxt, span: span) -> @ast::expr {
|
||||
let loc = cx.codemap().lookup_char_pos(span.lo);
|
||||
mk_call_global(
|
||||
cx,
|
||||
span,
|
||||
~[
|
||||
cx.ident_of(~"core"),
|
||||
cx.ident_of(~"sys"),
|
||||
cx.ident_of(~"begin_unwind"),
|
||||
],
|
||||
~[
|
||||
mk_uniq_str(cx, span, ~"internal error: entered unreachable code"),
|
||||
mk_uniq_str(cx, span, loc.file.name),
|
||||
mk_uint(cx, span, loc.line),
|
||||
]
|
||||
)
|
||||
}
|
||||
pub fn mk_unreachable_arm(cx: @ext_ctxt, span: span) -> ast::arm {
|
||||
mk_arm(cx, span, ~[mk_pat_wild(cx, span)], mk_unreachable(cx, span))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ use ext::build;
|
|||
use ext::deriving::*;
|
||||
use codemap::{span, spanned};
|
||||
use ast_util;
|
||||
use opt_vec;
|
||||
|
||||
use core::uint;
|
||||
|
||||
|
|
@ -48,12 +49,13 @@ fn create_derived_clone_impl(cx: @ext_ctxt,
|
|||
method: @method)
|
||||
-> @item {
|
||||
let methods = [ method ];
|
||||
let trait_path = [
|
||||
let trait_path = ~[
|
||||
cx.ident_of(~"core"),
|
||||
cx.ident_of(~"clone"),
|
||||
cx.ident_of(~"Clone"),
|
||||
];
|
||||
create_derived_impl(cx, span, type_ident, generics, methods, trait_path)
|
||||
let trait_path = build::mk_raw_path_global(span, trait_path);
|
||||
create_derived_impl(cx, span, type_ident, generics, methods, trait_path, opt_vec::Empty)
|
||||
}
|
||||
// Creates a method from the given expression conforming to the signature of
|
||||
// the `clone` method.
|
||||
|
|
@ -188,9 +190,7 @@ fn expand_deriving_clone_struct_method(cx: @ext_ctxt,
|
|||
fields.push(field);
|
||||
}
|
||||
unnamed_field => {
|
||||
cx.span_bug(span,
|
||||
~"unnamed fields in \
|
||||
expand_deriving_clone_struct_method");
|
||||
cx.span_bug(span, ~"unnamed fields in `deriving(Clone)`");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
454
src/libsyntax/ext/deriving/decodable.rs
Normal file
454
src/libsyntax/ext/deriving/decodable.rs
Normal file
|
|
@ -0,0 +1,454 @@
|
|||
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use core::prelude::*;
|
||||
|
||||
use ast;
|
||||
use ast::*;
|
||||
use ext::base::ext_ctxt;
|
||||
use ext::build;
|
||||
use ext::deriving::*;
|
||||
use codemap::{span, spanned};
|
||||
use ast_util;
|
||||
use opt_vec;
|
||||
|
||||
use core::uint;
|
||||
|
||||
pub fn expand_deriving_decodable(
|
||||
cx: @ext_ctxt,
|
||||
span: span,
|
||||
_mitem: @meta_item,
|
||||
in_items: ~[@item]
|
||||
) -> ~[@item] {
|
||||
expand_deriving(
|
||||
cx,
|
||||
span,
|
||||
in_items,
|
||||
expand_deriving_decodable_struct_def,
|
||||
expand_deriving_decodable_enum_def
|
||||
)
|
||||
}
|
||||
|
||||
fn create_derived_decodable_impl(
|
||||
cx: @ext_ctxt,
|
||||
span: span,
|
||||
type_ident: ident,
|
||||
generics: &Generics,
|
||||
method: @method
|
||||
) -> @item {
|
||||
let decoder_ty_param = build::mk_ty_param(
|
||||
cx,
|
||||
cx.ident_of(~"__D"),
|
||||
@opt_vec::with(
|
||||
build::mk_trait_ty_param_bound_global(
|
||||
cx,
|
||||
span,
|
||||
~[
|
||||
cx.ident_of(~"std"),
|
||||
cx.ident_of(~"serialize"),
|
||||
cx.ident_of(~"Decoder"),
|
||||
]
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
// All the type parameters need to bound to the trait.
|
||||
let generic_ty_params = opt_vec::with(decoder_ty_param);
|
||||
|
||||
let methods = [method];
|
||||
let trait_path = build::mk_raw_path_global_(
|
||||
span,
|
||||
~[
|
||||
cx.ident_of(~"std"),
|
||||
cx.ident_of(~"serialize"),
|
||||
cx.ident_of(~"Decodable")
|
||||
],
|
||||
~[
|
||||
build::mk_simple_ty_path(cx, span, cx.ident_of(~"__D"))
|
||||
]
|
||||
);
|
||||
create_derived_impl(
|
||||
cx,
|
||||
span,
|
||||
type_ident,
|
||||
generics,
|
||||
methods,
|
||||
trait_path,
|
||||
generic_ty_params
|
||||
)
|
||||
}
|
||||
|
||||
// Creates a method from the given set of statements conforming to the
|
||||
// signature of the `decodable` method.
|
||||
fn create_decode_method(
|
||||
cx: @ext_ctxt,
|
||||
span: span,
|
||||
type_ident: ast::ident,
|
||||
generics: &Generics,
|
||||
expr: @ast::expr
|
||||
) -> @method {
|
||||
// Create the `e` parameter.
|
||||
let d_arg_type = build::mk_ty_rptr(
|
||||
cx,
|
||||
span,
|
||||
build::mk_simple_ty_path(cx, span, cx.ident_of(~"__D")),
|
||||
ast::m_imm
|
||||
);
|
||||
let d_ident = cx.ident_of(~"__d");
|
||||
let d_arg = build::mk_arg(cx, span, d_ident, d_arg_type);
|
||||
|
||||
// Create the type of the return value.
|
||||
let output_type = create_self_type_with_params(
|
||||
cx,
|
||||
span,
|
||||
type_ident,
|
||||
generics
|
||||
);
|
||||
|
||||
// Create the function declaration.
|
||||
let inputs = ~[d_arg];
|
||||
let fn_decl = build::mk_fn_decl(inputs, output_type);
|
||||
|
||||
// Create the body block.
|
||||
let body_block = build::mk_simple_block(cx, span, expr);
|
||||
|
||||
// Create the method.
|
||||
let self_ty = spanned { node: sty_static, span: span };
|
||||
let method_ident = cx.ident_of(~"decode");
|
||||
@ast::method {
|
||||
ident: method_ident,
|
||||
attrs: ~[],
|
||||
generics: ast_util::empty_generics(),
|
||||
self_ty: self_ty,
|
||||
purity: impure_fn,
|
||||
decl: fn_decl,
|
||||
body: body_block,
|
||||
id: cx.next_id(),
|
||||
span: span,
|
||||
self_id: cx.next_id(),
|
||||
vis: public
|
||||
}
|
||||
}
|
||||
|
||||
fn call_substructure_decode_method(
|
||||
cx: @ext_ctxt,
|
||||
span: span
|
||||
) -> @ast::expr {
|
||||
// Call the substructure method.
|
||||
build::mk_call_(
|
||||
cx,
|
||||
span,
|
||||
build::mk_path_global(
|
||||
cx,
|
||||
span,
|
||||
~[
|
||||
cx.ident_of(~"std"),
|
||||
cx.ident_of(~"serialize"),
|
||||
cx.ident_of(~"Decodable"),
|
||||
cx.ident_of(~"decode"),
|
||||
]
|
||||
),
|
||||
~[
|
||||
build::mk_path(cx, span, ~[cx.ident_of(~"__d")])
|
||||
]
|
||||
)
|
||||
}
|
||||
|
||||
fn expand_deriving_decodable_struct_def(
|
||||
cx: @ext_ctxt,
|
||||
span: span,
|
||||
struct_def: &struct_def,
|
||||
type_ident: ident,
|
||||
generics: &Generics
|
||||
) -> @item {
|
||||
// Create the method.
|
||||
let method = expand_deriving_decodable_struct_method(
|
||||
cx,
|
||||
span,
|
||||
struct_def,
|
||||
type_ident,
|
||||
generics
|
||||
);
|
||||
|
||||
// Create the implementation.
|
||||
create_derived_decodable_impl(
|
||||
cx,
|
||||
span,
|
||||
type_ident,
|
||||
generics,
|
||||
method
|
||||
)
|
||||
}
|
||||
|
||||
fn expand_deriving_decodable_enum_def(
|
||||
cx: @ext_ctxt,
|
||||
span: span,
|
||||
enum_definition: &enum_def,
|
||||
type_ident: ident,
|
||||
generics: &Generics
|
||||
) -> @item {
|
||||
// Create the method.
|
||||
let method = expand_deriving_decodable_enum_method(
|
||||
cx,
|
||||
span,
|
||||
enum_definition,
|
||||
type_ident,
|
||||
generics
|
||||
);
|
||||
|
||||
// Create the implementation.
|
||||
create_derived_decodable_impl(
|
||||
cx,
|
||||
span,
|
||||
type_ident,
|
||||
generics,
|
||||
method
|
||||
)
|
||||
}
|
||||
|
||||
fn create_read_struct_field(
|
||||
cx: @ext_ctxt,
|
||||
span: span,
|
||||
idx: uint,
|
||||
ident: ident
|
||||
) -> build::Field {
|
||||
// Call the substructure method.
|
||||
let decode_expr = call_substructure_decode_method(cx, span);
|
||||
|
||||
let call_expr = build::mk_method_call(
|
||||
cx,
|
||||
span,
|
||||
build::mk_path(cx, span, ~[cx.ident_of(~"__d")]),
|
||||
cx.ident_of(~"read_struct_field"),
|
||||
~[
|
||||
build::mk_base_str(cx, span, cx.str_of(ident)),
|
||||
build::mk_uint(cx, span, idx),
|
||||
build::mk_lambda_no_args(cx, span, decode_expr),
|
||||
]
|
||||
);
|
||||
|
||||
build::Field { ident: ident, ex: call_expr }
|
||||
}
|
||||
|
||||
fn create_read_struct_arg(
|
||||
cx: @ext_ctxt,
|
||||
span: span,
|
||||
idx: uint,
|
||||
ident: ident
|
||||
) -> build::Field {
|
||||
// Call the substructure method.
|
||||
let decode_expr = call_substructure_decode_method(cx, span);
|
||||
|
||||
let call_expr = build::mk_method_call(
|
||||
cx,
|
||||
span,
|
||||
build::mk_path(cx, span, ~[cx.ident_of(~"__d")]),
|
||||
cx.ident_of(~"read_struct_arg"),
|
||||
~[
|
||||
build::mk_uint(cx, span, idx),
|
||||
build::mk_lambda_no_args(cx, span, decode_expr),
|
||||
]
|
||||
);
|
||||
|
||||
build::Field { ident: ident, ex: call_expr }
|
||||
}
|
||||
|
||||
fn expand_deriving_decodable_struct_method(
|
||||
cx: @ext_ctxt,
|
||||
span: span,
|
||||
struct_def: &struct_def,
|
||||
type_ident: ident,
|
||||
generics: &Generics
|
||||
) -> @method {
|
||||
// Create the body of the method.
|
||||
let mut i = 0;
|
||||
let mut fields = ~[];
|
||||
for struct_def.fields.each |struct_field| {
|
||||
match struct_field.node.kind {
|
||||
named_field(ident, _, _) => {
|
||||
fields.push(create_read_struct_field(cx, span, i, ident));
|
||||
}
|
||||
unnamed_field => {
|
||||
cx.span_unimpl(
|
||||
span,
|
||||
~"unnamed fields with `deriving(Decodable)`"
|
||||
);
|
||||
}
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
|
||||
let read_struct_expr = build::mk_method_call(
|
||||
cx,
|
||||
span,
|
||||
build::mk_path(
|
||||
cx,
|
||||
span,
|
||||
~[cx.ident_of(~"__d")]
|
||||
),
|
||||
cx.ident_of(~"read_struct"),
|
||||
~[
|
||||
build::mk_base_str(cx, span, cx.str_of(type_ident)),
|
||||
build::mk_uint(cx, span, fields.len()),
|
||||
build::mk_lambda_no_args(
|
||||
cx,
|
||||
span,
|
||||
build::mk_struct_e(
|
||||
cx,
|
||||
span,
|
||||
~[type_ident],
|
||||
fields
|
||||
)
|
||||
),
|
||||
]
|
||||
);
|
||||
|
||||
// Create the method itself.
|
||||
create_decode_method(cx, span, type_ident, generics, read_struct_expr)
|
||||
}
|
||||
|
||||
fn create_read_variant_arg(
|
||||
cx: @ext_ctxt,
|
||||
span: span,
|
||||
idx: uint,
|
||||
variant: &ast::variant
|
||||
) -> ast::arm {
|
||||
// Create the matching pattern.
|
||||
let pat = build::mk_pat_lit(cx, span, build::mk_uint(cx, span, idx));
|
||||
|
||||
// Feed each argument in this variant to the decode function
|
||||
// as well.
|
||||
let variant_arg_len = variant_arg_count(cx, span, variant);
|
||||
|
||||
let expr = if variant_arg_len == 0 {
|
||||
build::mk_path(cx, span, ~[variant.node.name])
|
||||
} else {
|
||||
// Feed the discriminant to the decode function.
|
||||
let mut args = ~[];
|
||||
|
||||
for uint::range(0, variant_arg_len) |j| {
|
||||
// Call the substructure method.
|
||||
let expr = call_substructure_decode_method(cx, span);
|
||||
|
||||
let call_expr = build::mk_method_call(
|
||||
cx,
|
||||
span,
|
||||
build::mk_path(cx, span, ~[cx.ident_of(~"__d")]),
|
||||
cx.ident_of(~"read_enum_variant_arg"),
|
||||
~[
|
||||
build::mk_uint(cx, span, j),
|
||||
build::mk_lambda_no_args(cx, span, expr),
|
||||
]
|
||||
);
|
||||
|
||||
args.push(call_expr);
|
||||
}
|
||||
|
||||
build::mk_call(
|
||||
cx,
|
||||
span,
|
||||
~[variant.node.name],
|
||||
args
|
||||
)
|
||||
};
|
||||
|
||||
// Create the arm.
|
||||
build::mk_arm(cx, span, ~[pat], expr)
|
||||
}
|
||||
|
||||
fn create_read_enum_variant(
|
||||
cx: @ext_ctxt,
|
||||
span: span,
|
||||
enum_definition: &enum_def
|
||||
) -> @expr {
|
||||
// Create a vector that contains all the variant names.
|
||||
let expr_arm_names = build::mk_base_vec_e(
|
||||
cx,
|
||||
span,
|
||||
do enum_definition.variants.map |variant| {
|
||||
build::mk_base_str(
|
||||
cx,
|
||||
span,
|
||||
cx.str_of(variant.node.name)
|
||||
)
|
||||
}
|
||||
);
|
||||
|
||||
// Create the arms of the match in the method body.
|
||||
let mut arms = do enum_definition.variants.mapi |i, variant| {
|
||||
create_read_variant_arg(cx, span, i, variant)
|
||||
};
|
||||
|
||||
// Add the impossible case arm.
|
||||
arms.push(build::mk_unreachable_arm(cx, span));
|
||||
|
||||
// Create the read_enum_variant expression.
|
||||
build::mk_method_call(
|
||||
cx,
|
||||
span,
|
||||
build::mk_path(cx, span, ~[cx.ident_of(~"__d")]),
|
||||
cx.ident_of(~"read_enum_variant"),
|
||||
~[
|
||||
expr_arm_names,
|
||||
build::mk_lambda(
|
||||
cx,
|
||||
span,
|
||||
build::mk_fn_decl(
|
||||
~[
|
||||
build::mk_arg(
|
||||
cx,
|
||||
span,
|
||||
cx.ident_of(~"__i"),
|
||||
build::mk_ty_infer(cx, span)
|
||||
)
|
||||
],
|
||||
build::mk_ty_infer(cx, span)
|
||||
),
|
||||
build::mk_expr(
|
||||
cx,
|
||||
span,
|
||||
ast::expr_match(
|
||||
build::mk_path(cx, span, ~[cx.ident_of(~"__i")]),
|
||||
arms
|
||||
)
|
||||
)
|
||||
)
|
||||
]
|
||||
)
|
||||
}
|
||||
|
||||
fn expand_deriving_decodable_enum_method(
|
||||
cx: @ext_ctxt,
|
||||
span: span,
|
||||
enum_definition: &enum_def,
|
||||
type_ident: ast::ident,
|
||||
generics: &Generics
|
||||
) -> @method {
|
||||
let read_enum_variant_expr = create_read_enum_variant(
|
||||
cx,
|
||||
span,
|
||||
enum_definition
|
||||
);
|
||||
|
||||
// Create the read_enum expression
|
||||
let read_enum_expr = build::mk_method_call(
|
||||
cx,
|
||||
span,
|
||||
build::mk_path(cx, span, ~[cx.ident_of(~"__d")]),
|
||||
cx.ident_of(~"read_enum"),
|
||||
~[
|
||||
build::mk_base_str(cx, span, cx.str_of(type_ident)),
|
||||
build::mk_lambda_no_args(cx, span, read_enum_variant_expr),
|
||||
]
|
||||
);
|
||||
|
||||
// Create the method.
|
||||
create_decode_method(cx, span, type_ident, generics, read_enum_expr)
|
||||
}
|
||||
388
src/libsyntax/ext/deriving/encodable.rs
Normal file
388
src/libsyntax/ext/deriving/encodable.rs
Normal file
|
|
@ -0,0 +1,388 @@
|
|||
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use core::prelude::*;
|
||||
|
||||
use ast;
|
||||
use ast::*;
|
||||
use ext::base::ext_ctxt;
|
||||
use ext::build;
|
||||
use ext::deriving::*;
|
||||
use codemap::{span, spanned};
|
||||
use ast_util;
|
||||
use opt_vec;
|
||||
|
||||
use core::uint;
|
||||
|
||||
pub fn expand_deriving_encodable(
|
||||
cx: @ext_ctxt,
|
||||
span: span,
|
||||
_mitem: @meta_item,
|
||||
in_items: ~[@item]
|
||||
) -> ~[@item] {
|
||||
expand_deriving(
|
||||
cx,
|
||||
span,
|
||||
in_items,
|
||||
expand_deriving_encodable_struct_def,
|
||||
expand_deriving_encodable_enum_def
|
||||
)
|
||||
}
|
||||
|
||||
fn create_derived_encodable_impl(
|
||||
cx: @ext_ctxt,
|
||||
span: span,
|
||||
type_ident: ident,
|
||||
generics: &Generics,
|
||||
method: @method
|
||||
) -> @item {
|
||||
let encoder_ty_param = build::mk_ty_param(
|
||||
cx,
|
||||
cx.ident_of(~"__E"),
|
||||
@opt_vec::with(
|
||||
build::mk_trait_ty_param_bound_global(
|
||||
cx,
|
||||
span,
|
||||
~[
|
||||
cx.ident_of(~"std"),
|
||||
cx.ident_of(~"serialize"),
|
||||
cx.ident_of(~"Encoder"),
|
||||
]
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
// All the type parameters need to bound to the trait.
|
||||
let generic_ty_params = opt_vec::with(encoder_ty_param);
|
||||
|
||||
let methods = [method];
|
||||
let trait_path = build::mk_raw_path_global_(
|
||||
span,
|
||||
~[
|
||||
cx.ident_of(~"std"),
|
||||
cx.ident_of(~"serialize"),
|
||||
cx.ident_of(~"Encodable")
|
||||
],
|
||||
~[
|
||||
build::mk_simple_ty_path(cx, span, cx.ident_of(~"__E"))
|
||||
]
|
||||
);
|
||||
create_derived_impl(
|
||||
cx,
|
||||
span,
|
||||
type_ident,
|
||||
generics,
|
||||
methods,
|
||||
trait_path,
|
||||
generic_ty_params
|
||||
)
|
||||
}
|
||||
|
||||
// Creates a method from the given set of statements conforming to the
|
||||
// signature of the `encodable` method.
|
||||
fn create_encode_method(
|
||||
cx: @ext_ctxt,
|
||||
span: span,
|
||||
+statements: ~[@stmt]
|
||||
) -> @method {
|
||||
// Create the `e` parameter.
|
||||
let e_arg_type = build::mk_ty_rptr(
|
||||
cx,
|
||||
span,
|
||||
build::mk_simple_ty_path(cx, span, cx.ident_of(~"__E")),
|
||||
ast::m_imm
|
||||
);
|
||||
let e_ident = cx.ident_of(~"__e");
|
||||
let e_arg = build::mk_arg(cx, span, e_ident, e_arg_type);
|
||||
|
||||
// Create the type of the return value.
|
||||
let output_type = @ast::Ty { id: cx.next_id(), node: ty_nil, span: span };
|
||||
|
||||
// Create the function declaration.
|
||||
let inputs = ~[e_arg];
|
||||
let fn_decl = build::mk_fn_decl(inputs, output_type);
|
||||
|
||||
// Create the body block.
|
||||
let body_block = build::mk_block_(cx, span, statements);
|
||||
|
||||
// Create the method.
|
||||
let self_ty = spanned { node: sty_region(None, m_imm), span: span };
|
||||
let method_ident = cx.ident_of(~"encode");
|
||||
@ast::method {
|
||||
ident: method_ident,
|
||||
attrs: ~[],
|
||||
generics: ast_util::empty_generics(),
|
||||
self_ty: self_ty,
|
||||
purity: impure_fn,
|
||||
decl: fn_decl,
|
||||
body: body_block,
|
||||
id: cx.next_id(),
|
||||
span: span,
|
||||
self_id: cx.next_id(),
|
||||
vis: public
|
||||
}
|
||||
}
|
||||
|
||||
fn call_substructure_encode_method(
|
||||
cx: @ext_ctxt,
|
||||
span: span,
|
||||
self_field: @expr
|
||||
) -> @ast::expr {
|
||||
// Gather up the parameters we want to chain along.
|
||||
let e_ident = cx.ident_of(~"__e");
|
||||
let e_expr = build::mk_path(cx, span, ~[e_ident]);
|
||||
|
||||
// Call the substructure method.
|
||||
let encode_ident = cx.ident_of(~"encode");
|
||||
build::mk_method_call(
|
||||
cx,
|
||||
span,
|
||||
self_field,
|
||||
encode_ident,
|
||||
~[e_expr]
|
||||
)
|
||||
}
|
||||
|
||||
fn expand_deriving_encodable_struct_def(
|
||||
cx: @ext_ctxt,
|
||||
span: span,
|
||||
struct_def: &struct_def,
|
||||
type_ident: ident,
|
||||
generics: &Generics
|
||||
) -> @item {
|
||||
// Create the method.
|
||||
let method = expand_deriving_encodable_struct_method(
|
||||
cx,
|
||||
span,
|
||||
type_ident,
|
||||
struct_def
|
||||
);
|
||||
|
||||
// Create the implementation.
|
||||
create_derived_encodable_impl(
|
||||
cx,
|
||||
span,
|
||||
type_ident,
|
||||
generics,
|
||||
method
|
||||
)
|
||||
}
|
||||
|
||||
fn expand_deriving_encodable_enum_def(
|
||||
cx: @ext_ctxt,
|
||||
span: span,
|
||||
enum_definition: &enum_def,
|
||||
type_ident: ident,
|
||||
generics: &Generics
|
||||
) -> @item {
|
||||
// Create the method.
|
||||
let method = expand_deriving_encodable_enum_method(
|
||||
cx,
|
||||
span,
|
||||
type_ident,
|
||||
enum_definition
|
||||
);
|
||||
|
||||
// Create the implementation.
|
||||
create_derived_encodable_impl(
|
||||
cx,
|
||||
span,
|
||||
type_ident,
|
||||
generics,
|
||||
method
|
||||
)
|
||||
}
|
||||
|
||||
fn expand_deriving_encodable_struct_method(
|
||||
cx: @ext_ctxt,
|
||||
span: span,
|
||||
type_ident: ident,
|
||||
struct_def: &struct_def
|
||||
) -> @method {
|
||||
let self_ident = cx.ident_of(~"self");
|
||||
|
||||
// Create the body of the method.
|
||||
let mut idx = 0;
|
||||
let mut statements = ~[];
|
||||
for struct_def.fields.each |struct_field| {
|
||||
match struct_field.node.kind {
|
||||
named_field(ident, _, _) => {
|
||||
// Create the accessor for this field.
|
||||
let self_field = build::mk_access(
|
||||
cx,
|
||||
span,
|
||||
~[self_ident],
|
||||
ident
|
||||
);
|
||||
|
||||
// Call the substructure method.
|
||||
let encode_expr = call_substructure_encode_method(
|
||||
cx,
|
||||
span,
|
||||
self_field
|
||||
);
|
||||
|
||||
let blk_expr = build::mk_lambda(
|
||||
cx,
|
||||
span,
|
||||
build::mk_fn_decl(~[], build::mk_ty_infer(cx, span)),
|
||||
encode_expr
|
||||
);
|
||||
|
||||
let call_expr = build::mk_method_call(
|
||||
cx,
|
||||
span,
|
||||
build::mk_path(cx, span, ~[cx.ident_of(~"__e")]),
|
||||
cx.ident_of(~"emit_struct_field"),
|
||||
~[
|
||||
build::mk_base_str(cx, span, cx.str_of(ident)),
|
||||
build::mk_uint(cx, span, idx),
|
||||
blk_expr
|
||||
]
|
||||
);
|
||||
|
||||
statements.push(build::mk_stmt(cx, span, call_expr));
|
||||
}
|
||||
unnamed_field => {
|
||||
cx.span_unimpl(
|
||||
span,
|
||||
~"unnamed fields with `deriving(Encodable)`"
|
||||
);
|
||||
}
|
||||
}
|
||||
idx += 1;
|
||||
}
|
||||
|
||||
let emit_struct_stmt = build::mk_method_call(
|
||||
cx,
|
||||
span,
|
||||
build::mk_path(
|
||||
cx,
|
||||
span,
|
||||
~[cx.ident_of(~"__e")]
|
||||
),
|
||||
cx.ident_of(~"emit_struct"),
|
||||
~[
|
||||
build::mk_base_str(cx, span, cx.str_of(type_ident)),
|
||||
build::mk_uint(cx, span, statements.len()),
|
||||
build::mk_lambda_stmts(
|
||||
cx,
|
||||
span,
|
||||
build::mk_fn_decl(~[], build::mk_ty_infer(cx, span)),
|
||||
statements
|
||||
),
|
||||
]
|
||||
);
|
||||
|
||||
let statements = ~[build::mk_stmt(cx, span, emit_struct_stmt)];
|
||||
|
||||
// Create the method itself.
|
||||
return create_encode_method(cx, span, statements);
|
||||
}
|
||||
|
||||
fn expand_deriving_encodable_enum_method(
|
||||
cx: @ext_ctxt,
|
||||
span: span,
|
||||
type_ident: ast::ident,
|
||||
enum_definition: &enum_def
|
||||
) -> @method {
|
||||
// Create the arms of the match in the method body.
|
||||
let arms = do enum_definition.variants.mapi |i, variant| {
|
||||
// Create the matching pattern.
|
||||
let pat = create_enum_variant_pattern(cx, span, variant, ~"__self");
|
||||
|
||||
// Feed the discriminant to the encode function.
|
||||
let mut stmts = ~[];
|
||||
|
||||
// Feed each argument in this variant to the encode function
|
||||
// as well.
|
||||
let variant_arg_len = variant_arg_count(cx, span, variant);
|
||||
for uint::range(0, variant_arg_len) |j| {
|
||||
// Create the expression for this field.
|
||||
let field_ident = cx.ident_of(~"__self" + j.to_str());
|
||||
let field = build::mk_path(cx, span, ~[ field_ident ]);
|
||||
|
||||
// Call the substructure method.
|
||||
let expr = call_substructure_encode_method(cx, span, field);
|
||||
|
||||
let blk_expr = build::mk_lambda(
|
||||
cx,
|
||||
span,
|
||||
build::mk_fn_decl(~[], build::mk_ty_infer(cx, span)),
|
||||
expr
|
||||
);
|
||||
|
||||
let call_expr = build::mk_method_call(
|
||||
cx,
|
||||
span,
|
||||
build::mk_path(cx, span, ~[cx.ident_of(~"__e")]),
|
||||
cx.ident_of(~"emit_enum_variant_arg"),
|
||||
~[
|
||||
build::mk_uint(cx, span, j),
|
||||
blk_expr,
|
||||
]
|
||||
);
|
||||
|
||||
stmts.push(build::mk_stmt(cx, span, call_expr));
|
||||
}
|
||||
|
||||
// Create the pattern body.
|
||||
let call_expr = build::mk_method_call(
|
||||
cx,
|
||||
span,
|
||||
build::mk_path(cx, span, ~[cx.ident_of(~"__e")]),
|
||||
cx.ident_of(~"emit_enum_variant"),
|
||||
~[
|
||||
build::mk_base_str(cx, span, cx.str_of(variant.node.name)),
|
||||
build::mk_uint(cx, span, i),
|
||||
build::mk_uint(cx, span, variant_arg_len),
|
||||
build::mk_lambda_stmts(
|
||||
cx,
|
||||
span,
|
||||
build::mk_fn_decl(~[], build::mk_ty_infer(cx, span)),
|
||||
stmts
|
||||
)
|
||||
]
|
||||
);
|
||||
|
||||
let match_body_block = build::mk_simple_block(cx, span, call_expr);
|
||||
|
||||
// Create the arm.
|
||||
ast::arm {
|
||||
pats: ~[pat],
|
||||
guard: None,
|
||||
body: match_body_block,
|
||||
}
|
||||
};
|
||||
|
||||
// Create the method body.
|
||||
let lambda_expr = build::mk_lambda(
|
||||
cx,
|
||||
span,
|
||||
build::mk_fn_decl(~[], build::mk_ty_infer(cx, span)),
|
||||
expand_enum_or_struct_match(cx, span, arms)
|
||||
);
|
||||
|
||||
let call_expr = build::mk_method_call(
|
||||
cx,
|
||||
span,
|
||||
build::mk_path(cx, span, ~[cx.ident_of(~"__e")]),
|
||||
cx.ident_of(~"emit_enum"),
|
||||
~[
|
||||
build::mk_base_str(cx, span, cx.str_of(type_ident)),
|
||||
lambda_expr,
|
||||
]
|
||||
);
|
||||
|
||||
let stmt = build::mk_stmt(cx, span, call_expr);
|
||||
|
||||
// Create the method.
|
||||
create_encode_method(cx, span, ~[stmt])
|
||||
}
|
||||
|
|
@ -17,6 +17,7 @@ use ext::build;
|
|||
use ext::deriving::*;
|
||||
use codemap::{span, spanned};
|
||||
use ast_util;
|
||||
use opt_vec;
|
||||
|
||||
use core::uint;
|
||||
|
||||
|
|
@ -124,12 +125,13 @@ fn create_derived_eq_impl(cx: @ext_ctxt,
|
|||
ne_method: @method)
|
||||
-> @item {
|
||||
let methods = [ eq_method, ne_method ];
|
||||
let trait_path = [
|
||||
let trait_path = ~[
|
||||
cx.ident_of(~"core"),
|
||||
cx.ident_of(~"cmp"),
|
||||
cx.ident_of(~"Eq")
|
||||
];
|
||||
create_derived_impl(cx, span, type_ident, generics, methods, trait_path)
|
||||
let trait_path = build::mk_raw_path_global(span, trait_path);
|
||||
create_derived_impl(cx, span, type_ident, generics, methods, trait_path, opt_vec::Empty)
|
||||
}
|
||||
|
||||
fn call_substructure_eq_method(cx: @ext_ctxt,
|
||||
|
|
@ -289,7 +291,7 @@ fn expand_deriving_eq_struct_method(cx: @ext_ctxt,
|
|||
&mut outer_expr);
|
||||
}
|
||||
unnamed_field => {
|
||||
cx.span_unimpl(span, ~"unnamed fields with `deriving_eq`");
|
||||
cx.span_unimpl(span, ~"unnamed fields with `deriving(Eq)`");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ use ext::build;
|
|||
use ext::deriving::*;
|
||||
use codemap::{span, spanned};
|
||||
use ast_util;
|
||||
use opt_vec;
|
||||
|
||||
use core::uint;
|
||||
|
||||
|
|
@ -49,12 +50,13 @@ fn create_derived_iter_bytes_impl(cx: @ext_ctxt,
|
|||
method: @method)
|
||||
-> @item {
|
||||
let methods = [ method ];
|
||||
let trait_path = [
|
||||
let trait_path = ~[
|
||||
cx.ident_of(~"core"),
|
||||
cx.ident_of(~"to_bytes"),
|
||||
cx.ident_of(~"IterBytes")
|
||||
];
|
||||
create_derived_impl(cx, span, type_ident, generics, methods, trait_path)
|
||||
let trait_path = build::mk_raw_path_global(span, trait_path);
|
||||
create_derived_impl(cx, span, type_ident, generics, methods, trait_path, opt_vec::Empty)
|
||||
}
|
||||
|
||||
// Creates a method from the given set of statements conforming to the
|
||||
|
|
@ -191,7 +193,7 @@ fn expand_deriving_iter_bytes_struct_method(cx: @ext_ctxt,
|
|||
}
|
||||
unnamed_field => {
|
||||
cx.span_unimpl(span,
|
||||
~"unnamed fields with `deriving_iter_bytes`");
|
||||
~"unnamed fields with `deriving(IterBytes)`");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
use core::prelude::*;
|
||||
|
||||
use ast;
|
||||
use ast::{TraitTyParamBound, Ty, bind_by_ref, deref, enum_def};
|
||||
use ast::{Ty, bind_by_ref, deref, enum_def};
|
||||
use ast::{expr, expr_match, ident, item, item_};
|
||||
use ast::{item_enum, item_impl, item_struct, Generics};
|
||||
use ast::{m_imm, meta_item, method};
|
||||
|
|
@ -33,6 +33,8 @@ use core::uint;
|
|||
pub mod clone;
|
||||
pub mod eq;
|
||||
pub mod iter_bytes;
|
||||
pub mod encodable;
|
||||
pub mod decodable;
|
||||
|
||||
type ExpandDerivingStructDefFn<'self> = &'self fn(@ext_ctxt,
|
||||
span,
|
||||
|
|
@ -76,6 +78,10 @@ pub fn expand_meta_deriving(cx: @ext_ctxt,
|
|||
titem, in_items),
|
||||
~"IterBytes" => iter_bytes::expand_deriving_iter_bytes(cx,
|
||||
titem.span, titem, in_items),
|
||||
~"Encodable" => encodable::expand_deriving_encodable(cx,
|
||||
titem.span, titem, in_items),
|
||||
~"Decodable" => decodable::expand_deriving_decodable(cx,
|
||||
titem.span, titem, in_items),
|
||||
tname => {
|
||||
cx.span_err(titem.span, fmt!("unknown \
|
||||
`deriving` trait: `%s`", tname));
|
||||
|
|
@ -153,12 +159,13 @@ pub fn create_self_type_with_params(cx: @ext_ctxt,
|
|||
}
|
||||
|
||||
pub fn create_derived_impl(cx: @ext_ctxt,
|
||||
span: span,
|
||||
type_ident: ident,
|
||||
generics: &Generics,
|
||||
methods: &[@method],
|
||||
trait_path: &[ident])
|
||||
-> @item {
|
||||
span: span,
|
||||
type_ident: ident,
|
||||
generics: &Generics,
|
||||
methods: &[@method],
|
||||
trait_path: @ast::Path,
|
||||
mut impl_ty_params: opt_vec::OptVec<ast::TyParam>)
|
||||
-> @item {
|
||||
/*!
|
||||
*
|
||||
* Given that we are deriving a trait `Tr` for a type `T<'a, ...,
|
||||
|
|
@ -175,29 +182,16 @@ pub fn create_derived_impl(cx: @ext_ctxt,
|
|||
build::mk_lifetime(cx, l.span, l.ident)
|
||||
});
|
||||
|
||||
// Create the type parameters.
|
||||
let impl_ty_params = generics.ty_params.map(|ty_param| {
|
||||
let bound = build::mk_trait_ref_global(cx,
|
||||
span,
|
||||
trait_path.map(|x| *x));
|
||||
let bounds = @opt_vec::with(TraitTyParamBound(bound));
|
||||
build::mk_ty_param(cx, ty_param.ident, bounds)
|
||||
});
|
||||
|
||||
// Create the reference to the trait.
|
||||
let trait_path = ast::Path {
|
||||
span: span,
|
||||
global: true,
|
||||
idents: trait_path.map(|x| *x),
|
||||
rp: None,
|
||||
types: ~[]
|
||||
let trait_ref = build::mk_trait_ref_(cx, trait_path);
|
||||
|
||||
// Create the type parameters.
|
||||
for generics.ty_params.each |ty_param| {
|
||||
let bounds = @opt_vec::with(
|
||||
build::mk_trait_ty_param_bound_(cx, trait_path)
|
||||
);
|
||||
impl_ty_params.push(build::mk_ty_param(cx, ty_param.ident, bounds));
|
||||
};
|
||||
let trait_path = @trait_path;
|
||||
let trait_ref = ast::trait_ref {
|
||||
path: trait_path,
|
||||
ref_id: cx.next_id()
|
||||
};
|
||||
let trait_ref = @trait_ref;
|
||||
|
||||
// Create the type of `self`.
|
||||
let self_type = create_self_type_with_params(cx,
|
||||
|
|
|
|||
|
|
@ -95,7 +95,6 @@ pub fn rust_printer(writer: @io::Writer, intr: @ident_interner) -> @ps {
|
|||
}
|
||||
|
||||
pub static indent_unit: uint = 4u;
|
||||
pub static match_indent_unit: uint = 2u;
|
||||
|
||||
pub static default_columns: uint = 78u;
|
||||
|
||||
|
|
@ -1227,16 +1226,16 @@ pub fn print_expr(s: @ps, &&expr: @ast::expr) {
|
|||
print_block(s, blk);
|
||||
}
|
||||
ast::expr_match(expr, ref arms) => {
|
||||
cbox(s, match_indent_unit);
|
||||
cbox(s, indent_unit);
|
||||
ibox(s, 4);
|
||||
word_nbsp(s, ~"match");
|
||||
print_expr(s, expr);
|
||||
space(s.s);
|
||||
bopen(s);
|
||||
let len = (*arms).len();
|
||||
for (*arms).eachi |i, arm| {
|
||||
let len = arms.len();
|
||||
for arms.eachi |i, arm| {
|
||||
space(s.s);
|
||||
cbox(s, match_indent_unit);
|
||||
cbox(s, indent_unit);
|
||||
ibox(s, 0u);
|
||||
let mut first = true;
|
||||
for arm.pats.each |p| {
|
||||
|
|
@ -1269,7 +1268,7 @@ pub fn print_expr(s: @ps, &&expr: @ast::expr) {
|
|||
ast::expr_block(ref blk) => {
|
||||
// the block will close the pattern's ibox
|
||||
print_block_unclosed_indent(
|
||||
s, blk, match_indent_unit);
|
||||
s, blk, indent_unit);
|
||||
}
|
||||
_ => {
|
||||
end(s); // close the ibox for the pattern
|
||||
|
|
@ -1286,10 +1285,10 @@ pub fn print_expr(s: @ps, &&expr: @ast::expr) {
|
|||
}
|
||||
} else {
|
||||
// the block will close the pattern's ibox
|
||||
print_block_unclosed_indent(s, &arm.body, match_indent_unit);
|
||||
print_block_unclosed_indent(s, &arm.body, indent_unit);
|
||||
}
|
||||
}
|
||||
bclose_(s, expr.span, match_indent_unit);
|
||||
bclose_(s, expr.span, indent_unit);
|
||||
}
|
||||
ast::expr_fn_block(ref decl, ref body) => {
|
||||
// in do/for blocks we don't want to show an empty
|
||||
|
|
|
|||
|
|
@ -17,9 +17,9 @@ fn main() {
|
|||
let x = Some(3);
|
||||
let y =
|
||||
match x {
|
||||
Some(_) =>
|
||||
~"some" + ~"very" + ~"very" + ~"very" + ~"very" + ~"very" + ~"very"
|
||||
+ ~"very" + ~"very" + ~"long" + ~"string",
|
||||
None => ~"none"
|
||||
Some(_) =>
|
||||
~"some" + ~"very" + ~"very" + ~"very" + ~"very" + ~"very" +
|
||||
~"very" + ~"very" + ~"very" + ~"long" + ~"string",
|
||||
None => ~"none"
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ fn main() {
|
|||
let x = Some(3);
|
||||
let _y =
|
||||
match x {
|
||||
Some(_) => ~[~"some(_)", ~"not", ~"SO", ~"long", ~"string"],
|
||||
None => ~[~"none"]
|
||||
Some(_) => ~[~"some(_)", ~"not", ~"SO", ~"long", ~"string"],
|
||||
None => ~[~"none"]
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ use EBWriter = std::ebml::writer;
|
|||
use core::cmp::Eq;
|
||||
use core::io::Writer;
|
||||
use std::ebml;
|
||||
use std::serialize::{Encodable, Decodable};
|
||||
use std::serialize::{Decodable, Encodable};
|
||||
use std::time;
|
||||
|
||||
fn test_ebml<A:
|
||||
|
|
@ -39,8 +39,7 @@ fn test_ebml<A:
|
|||
assert!(*a1 == a2);
|
||||
}
|
||||
|
||||
#[auto_encode]
|
||||
#[auto_decode]
|
||||
#[deriving(Decodable, Encodable)]
|
||||
enum Expr {
|
||||
Val(uint),
|
||||
Plus(@Expr, @Expr),
|
||||
|
|
@ -107,32 +106,26 @@ impl cmp::Eq for CLike {
|
|||
fn ne(&self, other: &CLike) -> bool { !self.eq(other) }
|
||||
}
|
||||
|
||||
#[auto_encode]
|
||||
#[auto_decode]
|
||||
#[deriving(Eq)]
|
||||
#[deriving(Decodable, Encodable, Eq)]
|
||||
struct Spanned<T> {
|
||||
lo: uint,
|
||||
hi: uint,
|
||||
node: T,
|
||||
}
|
||||
|
||||
#[auto_encode]
|
||||
#[auto_decode]
|
||||
#[deriving(Decodable, Encodable)]
|
||||
struct SomeStruct { v: ~[uint] }
|
||||
|
||||
#[auto_encode]
|
||||
#[auto_decode]
|
||||
#[deriving(Decodable, Encodable)]
|
||||
struct Point {x: uint, y: uint}
|
||||
|
||||
#[auto_encode]
|
||||
#[auto_decode]
|
||||
#[deriving(Decodable, Encodable)]
|
||||
enum Quark<T> {
|
||||
Top(T),
|
||||
Bottom(T)
|
||||
}
|
||||
|
||||
#[auto_encode]
|
||||
#[auto_decode]
|
||||
#[deriving(Decodable, Encodable)]
|
||||
enum CLike { A, B, C }
|
||||
|
||||
pub fn main() {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue