diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index a27336097d0..f3e118461e6 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -20,6 +20,8 @@ impl span: Deserializable { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type spanned = {node: T, span: span}; @@ -76,6 +78,8 @@ type fn_ident = Option; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type path = {span: span, global: bool, idents: ~[ident], @@ -88,6 +92,8 @@ type node_id = int; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type def_id = {crate: crate_num, node: node_id}; impl def_id : cmp::Eq { @@ -102,6 +108,8 @@ const crate_node_id: node_id = 0; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum ty_param_bound { bound_copy, bound_send, @@ -112,10 +120,14 @@ enum ty_param_bound { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type ty_param = {ident: ident, id: node_id, bounds: @~[ty_param_bound]}; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum def { def_fn(def_id, purity), def_static_method(def_id, purity), @@ -296,6 +308,8 @@ type meta_item = spanned; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum meta_item_ { meta_word(~str), meta_list(~str, ~[@meta_item]), @@ -306,6 +320,8 @@ type blk = spanned; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type blk_ = {view_items: ~[@view_item], stmts: ~[@stmt], expr: Option<@expr>, @@ -314,14 +330,20 @@ type blk_ = {view_items: ~[@view_item], #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type pat = {id: node_id, node: pat_, span: span}; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type field_pat = {ident: ident, pat: @pat}; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum binding_mode { bind_by_value, bind_by_move, @@ -379,6 +401,8 @@ impl binding_mode : cmp::Eq { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum pat_ { pat_wild, // A pat_ident may either be a new bound variable, @@ -403,6 +427,8 @@ enum pat_ { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum mutability { m_mutbl, m_imm, m_const, } impl mutability : to_bytes::IterBytes { @@ -420,6 +446,8 @@ impl mutability : cmp::Eq { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum proto { proto_bare, // foreign fn proto_uniq, // fn~ @@ -436,6 +464,8 @@ impl proto : cmp::Eq { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum vstore { // FIXME (#2112): Change uint to @expr (actually only constant exprs) vstore_fixed(Option), // [1,2,3,4]/_ or 4 @@ -446,6 +476,8 @@ enum vstore { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum expr_vstore { // FIXME (#2112): Change uint to @expr (actually only constant exprs) expr_vstore_fixed(Option), // [1,2,3,4]/_ or 4 @@ -463,6 +495,8 @@ pure fn is_blockish(p: ast::proto) -> bool { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum binop { add, subtract, @@ -493,6 +527,8 @@ impl binop : cmp::Eq { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum unop { box(mutability), uniq(mutability), @@ -545,6 +581,8 @@ impl unop : cmp::Eq { // using ty::resolved_T(...). #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum inferable { expl(T), infer(node_id) @@ -585,6 +623,8 @@ impl inferable : cmp::Eq { // "resolved" mode: the real modes. #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum rmode { by_ref, by_val, by_move, by_copy } impl rmode : to_bytes::IterBytes { @@ -608,6 +648,8 @@ type stmt = spanned; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum stmt_ { stmt_decl(@decl, node_id), @@ -620,6 +662,8 @@ enum stmt_ { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum init_op { init_assign, init_move, } impl init_op : cmp::Eq { @@ -644,12 +688,16 @@ impl init_op : cmp::Eq { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type initializer = {op: init_op, expr: @expr}; // FIXME (pending discussion of #1697, #2178...): local should really be // a refinement on pat. #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type local_ = {is_mutbl: bool, ty: @ty, pat: @pat, init: Option, id: node_id}; @@ -659,20 +707,28 @@ type decl = spanned; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum decl_ { decl_local(~[@local]), decl_item(@item), } #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type arm = {pats: ~[@pat], guard: Option<@expr>, body: blk}; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type field_ = {mutbl: mutability, ident: ident, expr: @expr}; type field = spanned; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum blk_check_mode { default_blk, unsafe_blk, } impl blk_check_mode : cmp::Eq { @@ -689,20 +745,28 @@ impl blk_check_mode : cmp::Eq { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type expr = {id: node_id, callee_id: node_id, node: expr_, span: span}; // Extra node ID is only used for index, assign_op, unary, binary #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum log_level { error, debug, other } // 0 = error, 1 = debug, 2 = other #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum alt_mode { alt_check, alt_exhaustive, } #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum expr_ { expr_vstore(@expr, expr_vstore), expr_vec(~[@expr], mutability), @@ -760,6 +824,8 @@ enum expr_ { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type capture_item_ = { id: int, is_move: bool, @@ -789,6 +855,8 @@ type capture_clause = @~[capture_item]; // #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] #[doc="For macro invocations; parsing is delegated to the macro"] enum token_tree { tt_tok(span, token::token), @@ -854,6 +922,8 @@ type matcher = spanned; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum matcher_ { // match one token match_tok(token::token), @@ -870,12 +940,16 @@ type mac_arg = Option<@expr>; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type mac_body_ = {span: span}; type mac_body = Option; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum mac_ { mac_invoc(@path, mac_arg, mac_body), // old macro-invocation mac_invoc_tt(@path,~[token_tree]), // new macro-invocation @@ -890,6 +964,8 @@ type lit = spanned; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum lit_ { lit_str(@~str), lit_int(i64, int_ty), @@ -932,22 +1008,30 @@ impl ast::lit_: cmp::Eq { // type structure in middle/ty.rs as well. #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type mt = {ty: @ty, mutbl: mutability}; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type ty_field_ = {ident: ident, mt: mt}; type ty_field = spanned; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type ty_method = {ident: ident, attrs: ~[attribute], purity: purity, decl: fn_decl, tps: ~[ty_param], self_ty: self_ty, id: node_id, span: span}; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] // A trait method is either required (meaning it doesn't have an // implementation, just a signature) or provided (meaning it has a default // implementation). @@ -958,6 +1042,8 @@ enum trait_method { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum int_ty { ty_i, ty_char, ty_i8, ty_i16, ty_i32, ty_i64, } impl int_ty : to_bytes::IterBytes { @@ -988,6 +1074,8 @@ impl int_ty : cmp::Eq { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum uint_ty { ty_u, ty_u8, ty_u16, ty_u32, ty_u64, } impl uint_ty : to_bytes::IterBytes { @@ -1016,6 +1104,8 @@ impl uint_ty : cmp::Eq { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum float_ty { ty_f, ty_f32, ty_f64, } impl float_ty : to_bytes::IterBytes { @@ -1035,11 +1125,15 @@ impl float_ty : cmp::Eq { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type ty = {id: node_id, node: ty_, span: span}; // Not represented directly in the AST, referred to by name through a ty_path. #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum prim_ty { ty_int(int_ty), ty_uint(uint_ty), @@ -1088,10 +1182,14 @@ impl prim_ty : cmp::Eq { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type region = {id: node_id, node: region_}; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum region_ { re_anon, re_static, @@ -1101,6 +1199,8 @@ enum region_ { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum ty_ { ty_nil, ty_bot, /* bottom type */ @@ -1141,10 +1241,14 @@ impl ty : to_bytes::IterBytes { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type arg = {mode: mode, ty: @ty, ident: ident, id: node_id}; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type fn_decl = {inputs: ~[arg], output: @ty, @@ -1152,6 +1256,8 @@ type fn_decl = #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum purity { pure_fn, // declared with "pure fn" unsafe_fn, // declared with "unsafe fn" @@ -1174,6 +1280,8 @@ impl purity : cmp::Eq { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum ret_style { noreturn, // functions with return type _|_ that always // raise an error or exit (i.e. never return to the caller) @@ -1200,6 +1308,8 @@ impl ret_style : cmp::Eq { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum self_ty_ { sty_static, // no self: static method sty_by_ref, // old by-reference self: `` @@ -1257,6 +1367,8 @@ type self_ty = spanned; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type method = {ident: ident, attrs: ~[attribute], tps: ~[ty_param], self_ty: self_ty, purity: purity, decl: fn_decl, body: blk, @@ -1265,10 +1377,14 @@ type method = {ident: ident, attrs: ~[attribute], #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type _mod = {view_items: ~[@view_item], items: ~[@item]}; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum foreign_abi { foreign_abi_rust_intrinsic, foreign_abi_cdecl, @@ -1278,6 +1394,8 @@ enum foreign_abi { // Foreign mods can be named or anonymous #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum foreign_mod_sort { named, anonymous } impl foreign_mod_sort : cmp::Eq { @@ -1303,6 +1421,8 @@ impl foreign_abi : cmp::Eq { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type foreign_mod = {sort: foreign_mod_sort, view_items: ~[@view_item], @@ -1310,10 +1430,14 @@ type foreign_mod = #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type variant_arg = {ty: @ty, id: node_id}; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum variant_kind { tuple_variant_kind(~[variant_arg]), struct_variant_kind(@struct_def), @@ -1322,14 +1446,20 @@ enum variant_kind { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type enum_def_ = { variants: ~[variant], common: Option<@struct_def> }; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum enum_def = enum_def_; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type variant_ = {name: ident, attrs: ~[attribute], kind: variant_kind, id: node_id, disr_expr: Option<@expr>, vis: visibility}; @@ -1337,12 +1467,16 @@ type variant = spanned; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type path_list_ident_ = {name: ident, id: node_id}; type path_list_ident = spanned; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum namespace { module_ns, type_value_ns } impl namespace : cmp::Eq { @@ -1356,6 +1490,8 @@ type view_path = spanned; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum view_path_ { // quux = foo::bar::baz @@ -1374,11 +1510,15 @@ enum view_path_ { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type view_item = {node: view_item_, attrs: ~[attribute], vis: visibility, span: span}; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum view_item_ { view_item_use(ident, ~[@meta_item], node_id), view_item_import(~[@view_path]), @@ -1393,6 +1533,8 @@ type attribute = spanned; // distinguished for pretty-printing. #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum attr_style { attr_outer, attr_inner, } impl attr_style : cmp::Eq { @@ -1405,6 +1547,8 @@ impl attr_style : cmp::Eq { // doc-comments are promoted to attributes that have is_sugared_doc = true #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type attribute_ = {style: attr_style, value: meta_item, is_sugared_doc: bool}; /* @@ -1418,10 +1562,14 @@ type attribute_ = {style: attr_style, value: meta_item, is_sugared_doc: bool}; */ #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type trait_ref = {path: @path, ref_id: node_id, impl_id: node_id}; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum visibility { public, private, inherited } impl visibility : cmp::Eq { @@ -1440,6 +1588,8 @@ impl visibility : cmp::Eq { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type struct_field_ = { kind: struct_field_kind, id: node_id, @@ -1450,6 +1600,8 @@ type struct_field = spanned; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum struct_field_kind { named_field(ident, class_mutability, visibility), unnamed_field // element of a tuple-like struct @@ -1457,6 +1609,8 @@ enum struct_field_kind { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type struct_def = { traits: ~[@trait_ref], /* traits this struct implements */ fields: ~[@struct_field], /* fields */ @@ -1474,12 +1628,16 @@ type struct_def = { */ #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type item = {ident: ident, attrs: ~[attribute], id: node_id, node: item_, vis: visibility, span: span}; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum item_ { item_const(@ty, @expr), item_fn(fn_decl, purity, ~[ty_param], blk), @@ -1498,6 +1656,8 @@ enum item_ { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum class_mutability { class_mutable, class_immutable } impl class_mutability : to_bytes::IterBytes { @@ -1522,6 +1682,8 @@ type class_ctor = spanned; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type class_ctor_ = {id: node_id, attrs: ~[attribute], self_id: node_id, @@ -1532,6 +1694,8 @@ type class_dtor = spanned; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type class_dtor_ = {id: node_id, attrs: ~[attribute], self_id: node_id, @@ -1539,6 +1703,8 @@ type class_dtor_ = {id: node_id, #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type foreign_item = {ident: ident, attrs: ~[attribute], @@ -1549,6 +1715,8 @@ type foreign_item = #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum foreign_item_ { foreign_item_fn(fn_decl, purity, ~[ty_param]), foreign_item_const(@ty) @@ -1559,6 +1727,8 @@ enum foreign_item_ { // that we trans. #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum inlined_item { ii_item(@item), ii_method(def_id /* impl id */, @method), diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index ab24d7a5316..897a51f710c 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -408,6 +408,8 @@ fn dtor_dec() -> fn_decl { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type id_range = {min: node_id, max: node_id}; fn empty(range: id_range) -> bool { diff --git a/src/libsyntax/ext/auto_serialize2.rs b/src/libsyntax/ext/auto_serialize2.rs new file mode 100644 index 00000000000..b3102f8b4f7 --- /dev/null +++ b/src/libsyntax/ext/auto_serialize2.rs @@ -0,0 +1,991 @@ +/* + +The compiler code necessary to implement the #[auto_serialize2] and +#[auto_deserialize2] extension. The idea here is that type-defining items may +be tagged with #[auto_serialize2] and #[auto_deserialize2], which will cause +us to generate a little companion module with the same name as the item. + +For example, a type like: + + #[auto_serialize2] + #[auto_deserialize2] + struct Node {id: uint} + +would generate two implementations like: + + impl Node: Serializable { + fn serialize(s: &S) { + do s.emit_struct("Node") { + s.emit_field("id", 0, || s.emit_uint(self)) + } + } + } + + impl node_id: Deserializable { + static fn deserialize(d: &D) -> Node { + do d.read_struct("Node") { + Node { + id: d.read_field(~"x", 0, || deserialize(d)) + } + } + } + } + +Other interesting scenarios are whe the item has type parameters or +references other non-built-in types. A type definition like: + + #[auto_serialize2] + #[auto_deserialize2] + type spanned = {node: T, span: span}; + +would yield functions like: + + impl spanned: Serializable { + fn serialize(s: &S) { + do s.emit_rec { + s.emit_field("node", 0, || self.node.serialize(s)); + s.emit_field("span", 1, || self.span.serialize(s)); + } + } + } + + impl spanned: Deserializable { + static fn deserialize(d: &D) -> spanned { + do d.read_rec { + { + node: d.read_field(~"node", 0, || deserialize(d)), + span: d.read_field(~"span", 1, || deserialize(d)), + } + } + } + } + +FIXME (#2810)--Hygiene. Search for "__" strings. We also assume "std" is the +standard library. + +Misc notes: +----------- + +I use move mode arguments for ast nodes that will get inserted as is +into the tree. This is intended to prevent us from inserting the same +node twice. + +*/ + +use base::*; +use codemap::span; +use std::map; +use std::map::HashMap; + +export expand_auto_serialize; +export expand_auto_deserialize; + +// Transitional reexports so qquote can find the paths it is looking for +mod syntax { + pub use ext; + pub use parse; +} + +fn expand_auto_serialize( + cx: ext_ctxt, + span: span, + _mitem: ast::meta_item, + in_items: ~[@ast::item] +) -> ~[@ast::item] { + fn is_auto_serialize2(a: &ast::attribute) -> bool { + attr::get_attr_name(*a) == ~"auto_serialize2" + } + + fn filter_attrs(item: @ast::item) -> @ast::item { + @{attrs: vec::filter(item.attrs, |a| !is_auto_serialize2(a)), + .. *item} + } + + do vec::flat_map(in_items) |item| { + if item.attrs.any(is_auto_serialize2) { + match item.node { + ast::item_ty(@{node: ast::ty_rec(fields), _}, tps) => { + let ser_impl = mk_rec_ser_impl( + cx, + item.span, + item.ident, + fields, + tps + ); + + ~[filter_attrs(*item), ser_impl] + }, + ast::item_class(@{ fields, _}, tps) => { + let ser_impl = mk_struct_ser_impl( + cx, + item.span, + item.ident, + fields, + tps + ); + + ~[filter_attrs(*item), ser_impl] + }, + ast::item_enum(enum_def, tps) => { + let ser_impl = mk_enum_ser_impl( + cx, + item.span, + item.ident, + enum_def, + tps + ); + + ~[filter_attrs(*item), ser_impl] + }, + _ => { + cx.span_err(span, ~"#[auto_serialize2] can only be \ + applied to structs, record types, \ + and enum definitions"); + ~[*item] + } + } + } else { + ~[*item] + } + } +} + +fn expand_auto_deserialize( + cx: ext_ctxt, + span: span, + _mitem: ast::meta_item, + in_items: ~[@ast::item] +) -> ~[@ast::item] { + fn is_auto_deserialize2(a: &ast::attribute) -> bool { + attr::get_attr_name(*a) == ~"auto_deserialize2" + } + + fn filter_attrs(item: @ast::item) -> @ast::item { + @{attrs: vec::filter(item.attrs, |a| !is_auto_deserialize2(a)), + .. *item} + } + + do vec::flat_map(in_items) |item| { + if item.attrs.any(is_auto_deserialize2) { + match item.node { + ast::item_ty(@{node: ast::ty_rec(fields), _}, tps) => { + let deser_impl = mk_rec_deser_impl( + cx, + item.span, + item.ident, + fields, + tps + ); + + ~[filter_attrs(*item), deser_impl] + }, + ast::item_class(@{ fields, _}, tps) => { + let deser_impl = mk_struct_deser_impl( + cx, + item.span, + item.ident, + fields, + tps + ); + + ~[filter_attrs(*item), deser_impl] + }, + ast::item_enum(enum_def, tps) => { + let deser_impl = mk_enum_deser_impl( + cx, + item.span, + item.ident, + enum_def, + tps + ); + + ~[filter_attrs(*item), deser_impl] + }, + _ => { + cx.span_err(span, ~"#[auto_deserialize2] can only be \ + applied to structs, record types, \ + and enum definitions"); + ~[*item] + } + } + } else { + ~[*item] + } + } +} + +fn mk_impl( + cx: ext_ctxt, + span: span, + ident: ast::ident, + path: @ast::path, + tps: ~[ast::ty_param], + f: fn(@ast::ty) -> @ast::method +) -> @ast::item { + // All the type parameters need to bound to the trait. + let trait_tps = do tps.map |tp| { + let t_bound = ast::bound_trait(@{ + id: cx.next_id(), + node: ast::ty_path(path, cx.next_id()), + span: span, + }); + + { + ident: tp.ident, + id: cx.next_id(), + bounds: @vec::append(~[t_bound], *tp.bounds) + } + }; + + let opt_trait = Some(@{ + path: path, + ref_id: cx.next_id(), + impl_id: cx.next_id(), + }); + + let ty = cx.ty_path( + span, + ~[ident], + tps.map(|tp| cx.ty_path(span, ~[tp.ident], ~[])) + ); + + @{ + // This is a new-style impl declaration. + // XXX: clownshoes + ident: ast::token::special_idents::clownshoes_extensions, + attrs: ~[], + id: cx.next_id(), + node: ast::item_impl(trait_tps, opt_trait, ty, ~[f(ty)]), + vis: ast::public, + span: span, + } +} + +fn mk_ser_impl( + cx: ext_ctxt, + span: span, + ident: ast::ident, + tps: ~[ast::ty_param], + body: @ast::expr +) -> @ast::item { + // Make a path to the std::serialization2::Serializable trait. + let path = cx.path( + span, + ~[ + cx.ident_of(~"std"), + cx.ident_of(~"serialization2"), + cx.ident_of(~"Serializable"), + ] + ); + + mk_impl( + cx, + span, + ident, + path, + tps, + |_ty| mk_ser_method(cx, span, cx.expr_blk(body)) + ) +} + +fn mk_deser_impl( + cx: ext_ctxt, + span: span, + ident: ast::ident, + tps: ~[ast::ty_param], + body: @ast::expr +) -> @ast::item { + // Make a path to the std::serialization2::Deserializable trait. + let path = cx.path( + span, + ~[ + cx.ident_of(~"std"), + cx.ident_of(~"serialization2"), + cx.ident_of(~"Deserializable"), + ] + ); + + mk_impl( + cx, + span, + ident, + path, + tps, + |ty| mk_deser_method(cx, span, ty, cx.expr_blk(body)) + ) +} + +fn mk_ser_method( + cx: ext_ctxt, + span: span, + ser_body: ast::blk +) -> @ast::method { + let ser_bound = cx.ty_path( + span, + ~[ + cx.ident_of(~"std"), + cx.ident_of(~"serialization2"), + cx.ident_of(~"Serializer"), + ], + ~[] + ); + + let ser_tps = ~[{ + ident: cx.ident_of(~"__S"), + id: cx.next_id(), + bounds: @~[ast::bound_trait(ser_bound)], + }]; + + let ty_s = @{ + id: cx.next_id(), + node: ast::ty_rptr( + @{ + id: cx.next_id(), + node: ast::re_anon, + }, + { + ty: cx.ty_path(span, ~[cx.ident_of(~"__S")], ~[]), + mutbl: ast::m_imm + } + ), + span: span, + }; + + let ser_inputs = ~[{ + mode: ast::infer(cx.next_id()), + ty: ty_s, + ident: cx.ident_of(~"__s"), + id: cx.next_id(), + }]; + + let ser_output = @{ + id: cx.next_id(), + node: ast::ty_nil, + span: span, + }; + + let ser_decl = { + inputs: ser_inputs, + output: ser_output, + cf: ast::return_val, + }; + + @{ + ident: cx.ident_of(~"serialize"), + attrs: ~[], + tps: ser_tps, + self_ty: { node: ast::sty_region(ast::m_imm), span: span }, + purity: ast::impure_fn, + decl: ser_decl, + body: ser_body, + id: cx.next_id(), + span: span, + self_id: cx.next_id(), + vis: ast::public, + } +} + +fn mk_deser_method( + cx: ext_ctxt, + span: span, + ty: @ast::ty, + deser_body: ast::blk +) -> @ast::method { + let deser_bound = cx.ty_path( + span, + ~[ + cx.ident_of(~"std"), + cx.ident_of(~"serialization2"), + cx.ident_of(~"Deserializer"), + ], + ~[] + ); + + let deser_tps = ~[{ + ident: cx.ident_of(~"__D"), + id: cx.next_id(), + bounds: @~[ast::bound_trait(deser_bound)], + }]; + + let ty_d = @{ + id: cx.next_id(), + node: ast::ty_rptr( + @{ + id: cx.next_id(), + node: ast::re_anon, + }, + { + ty: cx.ty_path(span, ~[cx.ident_of(~"__D")], ~[]), + mutbl: ast::m_imm + } + ), + span: span, + }; + + let deser_inputs = ~[{ + mode: ast::infer(cx.next_id()), + ty: ty_d, + ident: cx.ident_of(~"__d"), + id: cx.next_id(), + }]; + + let deser_decl = { + inputs: deser_inputs, + output: ty, + cf: ast::return_val, + }; + + @{ + ident: cx.ident_of(~"deserialize"), + attrs: ~[], + tps: deser_tps, + self_ty: { node: ast::sty_static, span: span }, + purity: ast::impure_fn, + decl: deser_decl, + body: deser_body, + id: cx.next_id(), + span: span, + self_id: cx.next_id(), + vis: ast::public, + } +} + +fn mk_rec_ser_impl( + cx: ext_ctxt, + span: span, + ident: ast::ident, + fields: ~[ast::ty_field], + tps: ~[ast::ty_param] +) -> @ast::item { + let fields = mk_ser_fields(cx, span, mk_rec_fields(fields)); + + // ast for `__s.emit_rec(|| $(fields))` + let body = cx.expr_call( + span, + cx.expr_field( + span, + cx.expr_var(span, ~"__s"), + cx.ident_of(~"emit_rec") + ), + ~[cx.lambda_stmts(span, fields)] + ); + + mk_ser_impl(cx, span, ident, tps, body) +} + +fn mk_rec_deser_impl( + cx: ext_ctxt, + span: span, + ident: ast::ident, + fields: ~[ast::ty_field], + tps: ~[ast::ty_param] +) -> @ast::item { + let fields = mk_deser_fields(cx, span, mk_rec_fields(fields)); + + // ast for `read_rec(|| $(fields))` + let body = cx.expr_call( + span, + cx.expr_field( + span, + cx.expr_var(span, ~"__d"), + cx.ident_of(~"read_rec") + ), + ~[ + cx.lambda_expr( + cx.expr( + span, + ast::expr_rec(fields, None) + ) + ) + ] + ); + + mk_deser_impl(cx, span, ident, tps, body) +} + +fn mk_struct_ser_impl( + cx: ext_ctxt, + span: span, + ident: ast::ident, + fields: ~[@ast::struct_field], + tps: ~[ast::ty_param] +) -> @ast::item { + let fields = mk_ser_fields(cx, span, mk_struct_fields(fields)); + + // ast for `__s.emit_struct($(name), || $(fields))` + let ser_body = cx.expr_call( + span, + cx.expr_field( + span, + cx.expr_var(span, ~"__s"), + cx.ident_of(~"emit_struct") + ), + ~[ + cx.lit_str(span, @cx.str_of(ident)), + cx.lambda_stmts(span, fields), + ] + ); + + mk_ser_impl(cx, span, ident, tps, ser_body) +} + +fn mk_struct_deser_impl( + cx: ext_ctxt, + span: span, + ident: ast::ident, + fields: ~[@ast::struct_field], + tps: ~[ast::ty_param] +) -> @ast::item { + let fields = mk_deser_fields(cx, span, mk_struct_fields(fields)); + + // ast for `read_struct($(name), || $(fields))` + let body = cx.expr_call( + span, + cx.expr_field( + span, + cx.expr_var(span, ~"__d"), + cx.ident_of(~"read_struct") + ), + ~[ + cx.lit_str(span, @cx.str_of(ident)), + cx.lambda_expr( + cx.expr( + span, + ast::expr_struct( + cx.path(span, ~[ident]), + fields, + None + ) + ) + ), + ] + ); + + mk_deser_impl(cx, span, ident, tps, body) +} + +// Records and structs don't have the same fields types, but they share enough +// that if we extract the right subfields out we can share the serialization +// generator code. +type field = { span: span, ident: ast::ident, mutbl: ast::mutability }; + +fn mk_rec_fields(fields: ~[ast::ty_field]) -> ~[field] { + do fields.map |field| { + { + span: field.span, + ident: field.node.ident, + mutbl: field.node.mt.mutbl, + } + } +} + +fn mk_struct_fields(fields: ~[@ast::struct_field]) -> ~[field] { + do fields.map |field| { + let (ident, mutbl) = match field.node.kind { + ast::named_field(ident, mutbl, _) => (ident, mutbl), + _ => fail ~"[auto_serialize2] does not support \ + unnamed fields", + }; + + { + span: field.span, + ident: ident, + mutbl: match mutbl { + ast::class_mutable => ast::m_mutbl, + ast::class_immutable => ast::m_imm, + }, + } + } +} + +fn mk_ser_fields( + cx: ext_ctxt, + span: span, + fields: ~[field] +) -> ~[@ast::stmt] { + do fields.mapi |idx, field| { + // ast for `|| self.$(name).serialize(__s)` + let expr_lambda = cx.lambda_expr( + cx.expr_call( + span, + cx.expr_field( + span, + cx.expr_field( + span, + cx.expr_var(span, ~"self"), + field.ident + ), + cx.ident_of(~"serialize") + ), + ~[cx.expr_var(span, ~"__s")] + ) + ); + + // ast for `__s.emit_field($(name), $(idx), $(expr_lambda))` + cx.stmt( + cx.expr_call( + span, + cx.expr_field( + span, + cx.expr_var(span, ~"__s"), + cx.ident_of(~"emit_field") + ), + ~[ + cx.lit_str(span, @cx.str_of(field.ident)), + cx.lit_uint(span, idx), + expr_lambda, + ] + ) + ) + } +} + +fn mk_deser_fields( + cx: ext_ctxt, + span: span, + fields: ~[{ span: span, ident: ast::ident, mutbl: ast::mutability }] +) -> ~[ast::field] { + do fields.mapi |idx, field| { + // ast for `|| std::serialization2::deserialize(__d)` + let expr_lambda = cx.lambda( + cx.expr_blk( + cx.expr_call( + span, + cx.expr_path(span, ~[ + cx.ident_of(~"std"), + cx.ident_of(~"serialization2"), + cx.ident_of(~"deserialize"), + ]), + ~[cx.expr_var(span, ~"__d")] + ) + ) + ); + + // ast for `__d.read_field($(name), $(idx), $(expr_lambda))` + let expr: @ast::expr = cx.expr_call( + span, + cx.expr_field( + span, + cx.expr_var(span, ~"__d"), + cx.ident_of(~"read_field") + ), + ~[ + cx.lit_str(span, @cx.str_of(field.ident)), + cx.lit_uint(span, idx), + expr_lambda, + ] + ); + + { + node: { mutbl: field.mutbl, ident: field.ident, expr: expr }, + span: span, + } + } +} + +fn mk_enum_ser_impl( + cx: ext_ctxt, + span: span, + ident: ast::ident, + enum_def: ast::enum_def, + tps: ~[ast::ty_param] +) -> @ast::item { + let body = mk_enum_ser_body( + cx, + span, + ident, + enum_def.variants + ); + + mk_ser_impl(cx, span, ident, tps, body) +} + +fn mk_enum_deser_impl( + cx: ext_ctxt, + span: span, + ident: ast::ident, + enum_def: ast::enum_def, + tps: ~[ast::ty_param] +) -> @ast::item { + let body = mk_enum_deser_body( + cx, + span, + ident, + enum_def.variants + ); + + mk_deser_impl(cx, span, ident, tps, body) +} + +fn ser_variant( + cx: ext_ctxt, + span: span, + v_name: ast::ident, + v_idx: uint, + args: ~[ast::variant_arg] +) -> ast::arm { + // Name the variant arguments. + let names = args.mapi(|i, _arg| cx.ident_of(fmt!("__v%u", i))); + + // Bind the names to the variant argument type. + let pats = args.mapi(|i, arg| cx.binder_pat(arg.ty.span, names[i])); + + let pat_node = if pats.is_empty() { + ast::pat_ident( + ast::bind_by_implicit_ref, + cx.path(span, ~[v_name]), + None + ) + } else { + ast::pat_enum( + cx.path(span, ~[v_name]), + Some(pats) + ) + }; + + let pat = @{ + id: cx.next_id(), + node: pat_node, + span: span, + }; + + let stmts = do args.mapi |a_idx, _arg| { + // ast for `__s.emit_enum_variant_arg` + let expr_emit = cx.expr_field( + span, + cx.expr_var(span, ~"__s"), + cx.ident_of(~"emit_enum_variant_arg") + ); + + // ast for `|| $(v).serialize(__s)` + let expr_serialize = cx.lambda_expr( + cx.expr_call( + span, + cx.expr_field( + span, + cx.expr_path(span, ~[names[a_idx]]), + cx.ident_of(~"serialize") + ), + ~[cx.expr_var(span, ~"__s")] + ) + ); + + // ast for `$(expr_emit)($(a_idx), $(expr_serialize))` + cx.stmt( + cx.expr_call( + span, + expr_emit, + ~[cx.lit_uint(span, a_idx), expr_serialize] + ) + ) + }; + + // ast for `__s.emit_enum_variant($(name), $(idx), $(sz), $(lambda))` + let body = cx.expr_call( + span, + cx.expr_field( + span, + cx.expr_var(span, ~"__s"), + cx.ident_of(~"emit_enum_variant") + ), + ~[ + cx.lit_str(span, @cx.str_of(v_name)), + cx.lit_uint(span, v_idx), + cx.lit_uint(span, stmts.len()), + cx.lambda_stmts(span, stmts), + ] + ); + + { pats: ~[pat], guard: None, body: cx.expr_blk(body) } +} + +fn mk_enum_ser_body( + cx: ext_ctxt, + span: span, + name: ast::ident, + variants: ~[ast::variant] +) -> @ast::expr { + let arms = do variants.mapi |v_idx, variant| { + match variant.node.kind { + ast::tuple_variant_kind(args) => + ser_variant(cx, span, variant.node.name, v_idx, args), + ast::struct_variant_kind(*) => + fail ~"struct variants unimplemented", + ast::enum_variant_kind(*) => + fail ~"enum variants unimplemented", + } + }; + + // ast for `match *self { $(arms) }` + let match_expr = cx.expr( + span, + ast::expr_match( + cx.expr( + span, + ast::expr_unary(ast::deref, cx.expr_var(span, ~"self")) + ), + arms + ) + ); + + // ast for `__s.emit_enum($(name), || $(match_expr))` + cx.expr_call( + span, + cx.expr_field( + span, + cx.expr_var(span, ~"__s"), + cx.ident_of(~"emit_enum") + ), + ~[ + cx.lit_str(span, @cx.str_of(name)), + cx.lambda_expr(match_expr), + ] + ) +} + +fn mk_enum_deser_variant_nary( + cx: ext_ctxt, + span: span, + name: ast::ident, + args: ~[ast::variant_arg] +) -> @ast::expr { + let args = do args.mapi |idx, _arg| { + // ast for `|| std::serialization2::deserialize(__d)` + let expr_lambda = cx.lambda_expr( + cx.expr_call( + span, + cx.expr_path(span, ~[ + cx.ident_of(~"std"), + cx.ident_of(~"serialization2"), + cx.ident_of(~"deserialize"), + ]), + ~[cx.expr_var(span, ~"__d")] + ) + ); + + // ast for `__d.read_enum_variant_arg($(a_idx), $(expr_lambda))` + cx.expr_call( + span, + cx.expr_field( + span, + cx.expr_var(span, ~"__d"), + cx.ident_of(~"read_enum_variant_arg") + ), + ~[cx.lit_uint(span, idx), expr_lambda] + ) + }; + + // ast for `$(name)($(args))` + cx.expr_call(span, cx.expr_path(span, ~[name]), args) +} + +fn mk_enum_deser_body( + cx: ext_ctxt, + span: span, + name: ast::ident, + variants: ~[ast::variant] +) -> @ast::expr { + let mut arms = do variants.mapi |v_idx, variant| { + let body = match variant.node.kind { + ast::tuple_variant_kind(args) => { + if args.is_empty() { + // for a nullary variant v, do "v" + cx.expr_path(span, ~[variant.node.name]) + } else { + // for an n-ary variant v, do "v(a_1, ..., a_n)" + mk_enum_deser_variant_nary( + cx, + span, + variant.node.name, + args + ) + } + }, + ast::struct_variant_kind(*) => + fail ~"struct variants unimplemented", + ast::enum_variant_kind(*) => + fail ~"enum variants unimplemented", + }; + + let pat = @{ + id: cx.next_id(), + node: ast::pat_lit(cx.lit_uint(span, v_idx)), + span: span, + }; + + { + pats: ~[pat], + guard: None, + body: cx.expr_blk(body), + } + }; + + let impossible_case = { + pats: ~[@{ id: cx.next_id(), node: ast::pat_wild, span: span}], + guard: None, + + // FIXME(#3198): proper error message + body: cx.expr_blk(cx.expr(span, ast::expr_fail(None))), + }; + + arms.push(impossible_case); + + // ast for `|i| { match i { $(arms) } }` + let expr_lambda = cx.expr( + span, + ast::expr_fn_block( + { + inputs: ~[{ + mode: ast::infer(cx.next_id()), + ty: @{ + id: cx.next_id(), + node: ast::ty_infer, + span: span + }, + ident: cx.ident_of(~"i"), + id: cx.next_id(), + }], + output: @{ + id: cx.next_id(), + node: ast::ty_infer, + span: span, + }, + cf: ast::return_val, + }, + cx.expr_blk( + cx.expr( + span, + ast::expr_match(cx.expr_var(span, ~"i"), arms) + ) + ), + @~[] + ) + ); + + // ast for `__d.read_enum_variant($(expr_lambda))` + let expr_lambda = cx.lambda_expr( + cx.expr_call( + span, + cx.expr_field( + span, + cx.expr_var(span, ~"__d"), + cx.ident_of(~"read_enum_variant") + ), + ~[expr_lambda] + ) + ); + + // ast for `__d.read_enum($(e_name), $(expr_lambda))` + cx.expr_call( + span, + cx.expr_field( + span, + cx.expr_var(span, ~"__d"), + cx.ident_of(~"read_enum") + ), + ~[ + cx.lit_str(span, @cx.str_of(name)), + expr_lambda + ] + ) +} diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index c106042b9a3..ab56b6bb322 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -54,7 +54,7 @@ enum syntax_extension { // macro_defining() is obsolete, remove when #old_macros go away. macro_defining(macro_definer), - // #[auto_serialize] and such. will probably survive death of #old_macros + // #[auto_serialize2] and such. will probably survive death of #old_macros item_decorator(item_decorator), // Token-tree expanders @@ -64,6 +64,65 @@ enum syntax_extension { // A temporary hard-coded map of methods for expanding syntax extension // AST nodes into full ASTs +#[cfg(stage0)] +fn syntax_expander_table() -> HashMap<~str, syntax_extension> { + fn builtin(f: syntax_expander_) -> syntax_extension + {normal({expander: f, span: None})} + fn builtin_expr_tt(f: syntax_expander_tt_) -> syntax_extension { + expr_tt({expander: f, span: None}) + } + fn builtin_item_tt(f: syntax_expander_tt_item_) -> syntax_extension { + item_tt({expander: f, span: None}) + } + let syntax_expanders = HashMap(); + syntax_expanders.insert(~"macro", + macro_defining(ext::simplext::add_new_extension)); + syntax_expanders.insert(~"macro_rules", + builtin_item_tt( + ext::tt::macro_rules::add_new_extension)); + syntax_expanders.insert(~"fmt", builtin(ext::fmt::expand_syntax_ext)); + syntax_expanders.insert( + ~"auto_serialize2", + item_decorator(ext::auto_serialize2::expand_auto_serialize)); + syntax_expanders.insert( + ~"auto_deserialize2", + item_decorator(ext::auto_serialize2::expand_auto_deserialize)); + syntax_expanders.insert(~"env", builtin(ext::env::expand_syntax_ext)); + syntax_expanders.insert(~"concat_idents", + builtin(ext::concat_idents::expand_syntax_ext)); + syntax_expanders.insert(~"ident_to_str", + builtin(ext::ident_to_str::expand_syntax_ext)); + syntax_expanders.insert(~"log_syntax", + builtin_expr_tt( + ext::log_syntax::expand_syntax_ext)); + syntax_expanders.insert(~"ast", + builtin(ext::qquote::expand_ast)); + syntax_expanders.insert(~"line", + builtin(ext::source_util::expand_line)); + syntax_expanders.insert(~"col", + builtin(ext::source_util::expand_col)); + syntax_expanders.insert(~"file", + builtin(ext::source_util::expand_file)); + syntax_expanders.insert(~"stringify", + builtin(ext::source_util::expand_stringify)); + syntax_expanders.insert(~"include", + builtin(ext::source_util::expand_include)); + syntax_expanders.insert(~"include_str", + builtin(ext::source_util::expand_include_str)); + syntax_expanders.insert(~"include_bin", + builtin(ext::source_util::expand_include_bin)); + syntax_expanders.insert(~"module_path", + builtin(ext::source_util::expand_mod)); + syntax_expanders.insert(~"proto", + builtin_item_tt(ext::pipes::expand_proto)); + syntax_expanders.insert( + ~"trace_macros", + builtin_expr_tt(ext::trace_macros::expand_trace_macros)); + return syntax_expanders; +} + +#[cfg(stage1)] +#[cfg(stage2)] fn syntax_expander_table() -> HashMap<~str, syntax_extension> { fn builtin(f: syntax_expander_) -> syntax_extension {normal({expander: f, span: None})} diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 22e2cfcde6b..2d0b2f4c80a 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -124,7 +124,7 @@ fn expand_expr(exts: HashMap<~str, syntax_extension>, cx: ext_ctxt, } // This is a secondary mechanism for invoking syntax extensions on items: -// "decorator" attributes, such as #[auto_serialize]. These are invoked by an +// "decorator" attributes, such as #[auto_serialize2]. These are invoked by an // attribute prefixing an item, and are interpreted by feeding the item // through the named attribute _as a syntax extension_ and splicing in the // resulting item vec into place in favour of the decorator. Note that diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index dce4dc3bbc7..b63260997f7 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -4,6 +4,8 @@ use std::map::HashMap; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum binop { PLUS, MINUS, @@ -19,6 +21,8 @@ enum binop { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum token { /* Expression-operator symbols. */ EQ, @@ -77,6 +81,8 @@ enum token { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] /// For interpolation during macro expansion. enum nonterminal { nt_item(@ast::item), diff --git a/src/libsyntax/syntax.rc b/src/libsyntax/syntax.rc index 93ed5bd471b..4c29fc5512a 100644 --- a/src/libsyntax/syntax.rc +++ b/src/libsyntax/syntax.rc @@ -130,6 +130,9 @@ mod ext { mod log_syntax; #[legacy_exports] mod auto_serialize; + #[cfg(stage0)] + #[legacy_exports] + mod auto_serialize2; #[legacy_exports] mod source_util; diff --git a/src/rustc/middle/freevars.rs b/src/rustc/middle/freevars.rs index 1b42c9bb4b6..28400b5455d 100644 --- a/src/rustc/middle/freevars.rs +++ b/src/rustc/middle/freevars.rs @@ -18,6 +18,8 @@ export has_freevars; // (The def_upvar will already have been stripped). #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type freevar_entry = { def: ast::def, //< The variable being accessed free. span: span //< First span where it is accessed (there can be multiple) diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs index ca41be6f9d0..85f03e1f0b3 100644 --- a/src/rustc/middle/ty.rs +++ b/src/rustc/middle/ty.rs @@ -213,6 +213,8 @@ type mt = {ty: t, mutbl: ast::mutability}; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum vstore { vstore_fixed(uint), vstore_uniq, @@ -273,6 +275,8 @@ type opt_region_variance = Option; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum region_variance { rv_covariant, rv_invariant, rv_contravariant } impl region_variance : cmp::Eq { @@ -291,6 +295,8 @@ impl region_variance : cmp::Eq { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type AutoAdjustment = { autoderefs: uint, autoref: Option @@ -298,6 +304,8 @@ type AutoAdjustment = { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type AutoRef = { kind: AutoRefKind, region: region, @@ -306,6 +314,8 @@ type AutoRef = { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum AutoRefKind { /// Convert from @[]/~[] to &[] (or str) AutoSlice, @@ -511,6 +521,8 @@ impl param_ty : to_bytes::IterBytes { /// Representation of regions: #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum region { /// Bound regions are found (primarily) in function types. They indicate /// region parameters that have yet to be replaced with actual regions @@ -540,6 +552,8 @@ enum region { #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum bound_region { /// The self region for classes, impls (&T in a type defn or &self/T) br_self, @@ -671,6 +685,8 @@ enum IntVid = uint; enum FnVid = uint; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum RegionVid = uint; enum InferTy { diff --git a/src/rustc/middle/typeck.rs b/src/rustc/middle/typeck.rs index 7cb04bc0ea3..027a1d06742 100644 --- a/src/rustc/middle/typeck.rs +++ b/src/rustc/middle/typeck.rs @@ -77,6 +77,8 @@ export provided_methods_map; #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] enum method_origin { // fully statically resolved method method_static(ast::def_id), @@ -95,6 +97,8 @@ enum method_origin { // with a bounded trait. #[auto_serialize] #[auto_deserialize] +#[auto_serialize2] +#[auto_deserialize2] type method_param = { // the trait containing the method to be invoked trait_id: ast::def_id,