diff --git a/src/librustc/middle/freevars.rs b/src/librustc/middle/freevars.rs index 41e29132155e7..872ad83b7391c 100644 --- a/src/librustc/middle/freevars.rs +++ b/src/librustc/middle/freevars.rs @@ -20,8 +20,7 @@ use syntax::{ast, ast_util, visit}; // A vector of defs representing the free variables referred to in a function. // (The def_upvar will already have been stripped). -#[auto_encode] -#[auto_decode] +#[deriving(Encodable, Decodable)] pub struct 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/librustc/middle/moves.rs b/src/librustc/middle/moves.rs index 3a2fb654006ec..e81a9d6b78fcd 100644 --- a/src/librustc/middle/moves.rs +++ b/src/librustc/middle/moves.rs @@ -221,16 +221,14 @@ use syntax::visit::vt; use syntax::print::pprust; use syntax::codemap::span; -#[auto_encode] -#[auto_decode] +#[deriving(Encodable, Decodable)] pub enum CaptureMode { CapCopy, // Copy the value into the closure. CapMove, // Move the value into the closure. CapRef, // Reference directly from parent stack frame (used by `&fn()`). } -#[auto_encode] -#[auto_decode] +#[deriving(Encodable, Decodable)] pub struct CaptureVar { def: def, // Variable being accessed free span: span, // Location of an access to this variable diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 4ee2c5b01006f..e85c7d00c58e0 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -96,9 +96,7 @@ pub struct mt { mutbl: ast::mutability, } -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub enum vstore { vstore_fixed(uint), vstore_uniq, @@ -106,9 +104,7 @@ pub enum vstore { vstore_slice(Region) } -#[auto_encode] -#[auto_decode] -#[deriving(Eq, IterBytes)] +#[deriving(Eq, IterBytes, Encodable, Decodable)] pub enum TraitStore { BoxTraitStore, // @Trait UniqTraitStore, // ~Trait @@ -117,9 +113,7 @@ pub enum TraitStore { // XXX: This should probably go away at some point. Maybe after destructors // do? -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub enum SelfMode { ByCopy, ByRef, @@ -197,27 +191,22 @@ pub enum ast_ty_to_ty_cache_entry { pub type opt_region_variance = Option; -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Decodable, Encodable)] pub enum region_variance { rv_covariant, rv_invariant, rv_contravariant } -#[auto_encode] -#[auto_decode] +#[deriving(Decodable, Encodable)] pub enum AutoAdjustment { AutoAddEnv(ty::Region, ast::Sigil), AutoDerefRef(AutoDerefRef) } -#[auto_encode] -#[auto_decode] +#[deriving(Decodable, Encodable)] pub struct AutoDerefRef { autoderefs: uint, autoref: Option } -#[auto_encode] -#[auto_decode] +#[deriving(Decodable, Encodable)] pub enum AutoRef { /// Convert from T to &T AutoPtr(Region, ast::mutability), @@ -453,9 +442,7 @@ pub struct param_ty { } /// Representation of regions: -#[auto_encode] -#[auto_decode] -#[deriving(Eq, IterBytes)] +#[deriving(Eq, IterBytes, Encodable, Decodable)] pub enum Region { /// Bound regions are found (primarily) in function types. They indicate /// region parameters that have yet to be replaced with actual regions @@ -501,17 +488,13 @@ pub impl Region { } } -#[auto_encode] -#[auto_decode] -#[deriving(Eq, IterBytes)] +#[deriving(Eq, IterBytes, Encodable, Decodable)] pub struct FreeRegion { scope_id: node_id, bound_region: bound_region } -#[auto_encode] -#[auto_decode] -#[deriving(Eq, IterBytes)] +#[deriving(Eq, IterBytes, Encodable, Decodable)] pub enum bound_region { /// The self region for structs, impls (&T in a type defn or &'self T) br_self, @@ -742,9 +725,7 @@ pub struct IntVid(uint); #[deriving(Eq)] pub struct FloatVid(uint); -#[deriving(Eq)] -#[auto_encode] -#[auto_decode] +#[deriving(Eq, Encodable, Decodable)] pub struct RegionVid { id: uint } @@ -777,8 +758,7 @@ impl to_bytes::IterBytes for InferTy { } } -#[auto_encode] -#[auto_decode] +#[deriving(Encodable, Decodable)] pub enum InferRegion { ReVar(RegionVid), ReSkolemized(uint, bound_region) diff --git a/src/librustc/middle/typeck/mod.rs b/src/librustc/middle/typeck/mod.rs index 0dec0fc937b15..dd313c54efb92 100644 --- a/src/librustc/middle/typeck/mod.rs +++ b/src/librustc/middle/typeck/mod.rs @@ -73,8 +73,7 @@ pub mod infer; pub mod collect; pub mod coherence; -#[auto_encode] -#[auto_decode] +#[deriving(Encodable, Decodable)] pub enum method_origin { // supertrait method invoked on "self" inside a default method // first field is supertrait ID; @@ -98,8 +97,7 @@ pub enum method_origin { // details for a method invoked with a receiver whose type is a type parameter // with a bounded trait. -#[auto_encode] -#[auto_decode] +#[deriving(Encodable, Decodable)] pub struct method_param { // the trait containing the method to be invoked trait_id: ast::def_id, diff --git a/src/libstd/json.rs b/src/libstd/json.rs index 7702b46ddcbf9..270cf675c878a 100644 --- a/src/libstd/json.rs +++ b/src/libstd/json.rs @@ -1331,26 +1331,20 @@ mod tests { use std::serialize::Decodable; - #[auto_encode] - #[auto_decode] - #[deriving(Eq)] + #[deriving(Eq, Encodable, Decodable)] enum Animal { Dog, Frog(~str, int) } - #[auto_encode] - #[auto_decode] - #[deriving(Eq)] + #[deriving(Eq, Encodable, Decodable)] struct Inner { a: (), b: uint, c: ~[~str], } - #[auto_encode] - #[auto_decode] - #[deriving(Eq)] + #[deriving(Eq, Encodable, Decodable)] struct Outer { inner: ~[Inner], } diff --git a/src/libstd/time.rs b/src/libstd/time.rs index e731f679221fd..202b96f9797aa 100644 --- a/src/libstd/time.rs +++ b/src/libstd/time.rs @@ -29,9 +29,7 @@ pub mod rustrt { } /// A record specifying a time value in seconds and nanoseconds. -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub struct Timespec { sec: i64, nsec: i32 } /* @@ -100,9 +98,7 @@ pub fn tzset() { } } -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub struct Tm { tm_sec: i32, // seconds after the minute ~[0-60] tm_min: i32, // minutes after the hour ~[0-59] diff --git a/src/libstd/workcache.rs b/src/libstd/workcache.rs index a9e4ec50c7c09..f173df60df893 100644 --- a/src/libstd/workcache.rs +++ b/src/libstd/workcache.rs @@ -92,9 +92,7 @@ use core::util::replace; * */ -#[deriving(Eq)] -#[auto_encode] -#[auto_decode] +#[deriving(Eq, Encodable, Decodable)] struct WorkKey { kind: ~str, name: ~str diff --git a/src/libsyntax/abi.rs b/src/libsyntax/abi.rs index ee62bb270b829..1b166dcf36618 100644 --- a/src/libsyntax/abi.rs +++ b/src/libsyntax/abi.rs @@ -58,9 +58,7 @@ enum AbiArchitecture { Archs(u32) // Multiple architectures (bitset) } -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub struct AbiSet { priv bits: u32 // each bit represents one of the abis below } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index f77d00ce9b196..4a3ae7d94ad76 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -47,9 +47,7 @@ pub type SyntaxContext = uint; pub type SCTable = ~[SyntaxContext_]; pub static empty_ctxt : uint = 0; -#[deriving(Eq)] -#[auto_encode] -#[auto_decode] +#[deriving(Eq, Encodable, Decodable)] pub enum SyntaxContext_ { EmptyCtxt, Mark (Mrk,SyntaxContext), @@ -115,9 +113,7 @@ impl to_bytes::IterBytes for ident { // Functions may or may not have names. pub type fn_ident = Option; -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub struct Lifetime { id: node_id, span: span, @@ -142,9 +138,7 @@ impl to_bytes::IterBytes for Lifetime { // for instance: core::cmp::Eq . It's represented // as a sequence of identifiers, along with a bunch // of supporting information. -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub struct Path { span: span, global: bool, @@ -157,9 +151,7 @@ pub type crate_num = int; pub type node_id = int; -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub struct def_id { crate: crate_num, node: node_id, @@ -168,9 +160,7 @@ pub struct def_id { pub static local_crate: crate_num = 0; pub static crate_node_id: node_id = 0; -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] // The AST represents all type param bounds as types. // typeck::collect::compute_bounds matches these against // the "special" built-in traits (see middle::lang_items) and @@ -180,18 +170,14 @@ pub enum TyParamBound { RegionTyParamBound } -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub struct TyParam { ident: ident, id: node_id, bounds: @OptVec } -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub struct Generics { lifetimes: OptVec, ty_params: OptVec @@ -209,9 +195,7 @@ pub impl Generics { } } -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub enum def { def_fn(def_id, purity), def_static_method(/* method */ def_id, @@ -248,9 +232,7 @@ pub type crate_cfg = ~[@meta_item]; pub type crate = spanned; -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub struct crate_ { module: _mod, attrs: ~[attribute], @@ -259,9 +241,7 @@ pub struct crate_ { pub type meta_item = spanned; -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub enum meta_item_ { meta_word(@~str), meta_list(@~str, ~[@meta_item]), @@ -270,9 +250,7 @@ pub enum meta_item_ { pub type blk = spanned; -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub struct blk_ { view_items: ~[@view_item], stmts: ~[@stmt], @@ -281,26 +259,20 @@ pub struct blk_ { rules: blk_check_mode, } -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub struct pat { id: node_id, node: pat_, span: span, } -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub struct field_pat { ident: ident, pat: @pat, } -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub enum binding_mode { bind_by_copy, bind_by_ref(mutability), @@ -334,9 +306,7 @@ impl to_bytes::IterBytes for binding_mode { } } -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub enum pat_ { pat_wild, // A pat_ident may either be a new bound variable, @@ -361,9 +331,7 @@ pub enum pat_ { pat_vec(~[@pat], Option<@pat>, ~[@pat]) } -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub enum mutability { m_mutbl, m_imm, m_const, } #[cfg(stage0)] @@ -379,9 +347,7 @@ impl to_bytes::IterBytes for mutability { } } -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub enum Sigil { BorrowedSigil, OwnedSigil, @@ -411,9 +377,7 @@ impl ToStr for Sigil { } } -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub enum vstore { // FIXME (#3469): Change uint to @expr (actually only constant exprs) vstore_fixed(Option), // [1,2,3,4] @@ -422,9 +386,7 @@ pub enum vstore { vstore_slice(Option<@Lifetime>) // &'foo? [1,2,3,4] } -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub enum expr_vstore { expr_vstore_uniq, // ~[1,2,3,4] expr_vstore_box, // @[1,2,3,4] @@ -433,9 +395,7 @@ pub enum expr_vstore { expr_vstore_mut_slice, // &mut [1,2,3,4] } -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub enum binop { add, subtract, @@ -457,9 +417,7 @@ pub enum binop { gt, } -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub enum unop { box(mutability), uniq(mutability), @@ -470,9 +428,7 @@ pub enum unop { pub type stmt = spanned; -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub enum stmt_ { stmt_decl(@decl, node_id), @@ -488,9 +444,7 @@ pub enum stmt_ { // FIXME (pending discussion of #1697, #2178...): local should really be // a refinement on pat. -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub struct local_ { is_mutbl: bool, ty: @Ty, @@ -503,23 +457,17 @@ pub type local = spanned; pub type decl = spanned; -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub enum decl_ { decl_local(~[@local]), decl_item(@item), } -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub struct arm { pats: ~[@pat], guard: Option<@expr>, body: blk, } -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub struct field_ { mutbl: mutability, ident: ident, @@ -528,14 +476,10 @@ pub struct field_ { pub type field = spanned; -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub enum blk_check_mode { default_blk, unsafe_blk, } -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub struct expr { id: node_id, // Extra node ID is only used for index, assign_op, unary, binary, method @@ -545,18 +489,14 @@ pub struct expr { span: span, } -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub enum CallSugar { NoSugar, DoSugar, ForSugar } -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub enum expr_ { expr_vstore(@expr, expr_vstore), expr_vec(~[@expr], mutability), @@ -627,9 +567,7 @@ pub enum expr_ { // else knows what to do with them, so you'll probably get a syntax // error. // -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] #[doc="For macro invocations; parsing is delegated to the macro"] pub enum token_tree { // a single token @@ -702,9 +640,7 @@ pub enum token_tree { // pub type matcher = spanned; -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub enum matcher_ { // match one token match_tok(::parse::token::Token), @@ -717,18 +653,14 @@ pub enum matcher_ { pub type mac = spanned; -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub enum mac_ { mac_invoc_tt(@Path,~[token_tree]), // new macro-invocation } pub type lit = spanned; -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub enum lit_ { lit_str(@~str), lit_int(i64, int_ty), @@ -742,17 +674,13 @@ pub enum lit_ { // NB: If you change this, you'll probably want to change the corresponding // type structure in middle/ty.rs as well. -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub struct mt { ty: @Ty, mutbl: mutability, } -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub struct ty_field_ { ident: ident, mt: mt, @@ -760,9 +688,7 @@ pub struct ty_field_ { pub type ty_field = spanned; -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub struct ty_method { ident: ident, attrs: ~[attribute], @@ -774,9 +700,7 @@ pub struct ty_method { span: span, } -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] // A trait method is either required (meaning it doesn't have an // implementation, just a signature) or provided (meaning it has a default // implementation). @@ -785,9 +709,7 @@ pub enum trait_method { provided(@method), } -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub enum int_ty { ty_i, ty_char, ty_i8, ty_i16, ty_i32, ty_i64, } impl ToStr for int_ty { @@ -809,9 +731,7 @@ impl to_bytes::IterBytes for int_ty { } } -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub enum uint_ty { ty_u, ty_u8, ty_u16, ty_u32, ty_u64, } impl ToStr for uint_ty { @@ -833,9 +753,7 @@ impl to_bytes::IterBytes for uint_ty { } } -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub enum float_ty { ty_f, ty_f32, ty_f64, } impl ToStr for float_ty { @@ -858,9 +776,7 @@ impl to_bytes::IterBytes for float_ty { } // NB Eq method appears below. -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub struct Ty { id: node_id, node: ty_, @@ -868,9 +784,7 @@ pub struct Ty { } // Not represented directly in the AST, referred to by name through a ty_path. -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub enum prim_ty { ty_int(int_ty), ty_uint(uint_ty), @@ -879,9 +793,7 @@ pub enum prim_ty { ty_bool, } -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub enum Onceness { Once, Many @@ -909,9 +821,7 @@ impl to_bytes::IterBytes for Onceness { } } -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub struct TyClosure { sigil: Sigil, region: Option<@Lifetime>, @@ -921,9 +831,7 @@ pub struct TyClosure { decl: fn_decl } -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub struct TyBareFn { purity: purity, abis: AbiSet, @@ -931,9 +839,7 @@ pub struct TyBareFn { decl: fn_decl } -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub enum ty_ { ty_nil, ty_bot, /* bottom type */ @@ -967,17 +873,13 @@ impl to_bytes::IterBytes for Ty { } } -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub enum asm_dialect { asm_att, asm_intel } -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub struct inline_asm { asm: @~str, clobbers: @~str, @@ -988,9 +890,7 @@ pub struct inline_asm { dialect: asm_dialect } -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub struct arg { is_mutbl: bool, ty: @Ty, @@ -998,18 +898,14 @@ pub struct arg { id: node_id, } -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub struct fn_decl { inputs: ~[arg], output: @Ty, cf: ret_style, } -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub enum purity { pure_fn, // declared with "pure fn" unsafe_fn, // declared with "unsafe fn" @@ -1041,9 +937,7 @@ impl to_bytes::IterBytes for purity { } } -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub enum ret_style { noreturn, // functions with return type _|_ that always // raise an error or exit (i.e. never return to the caller) @@ -1063,9 +957,7 @@ impl to_bytes::IterBytes for ret_style { } } -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub enum explicit_self_ { sty_static, // no self sty_value, // `self` @@ -1102,9 +994,7 @@ impl to_bytes::IterBytes for explicit_self_ { pub type explicit_self = spanned; -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub struct method { ident: ident, attrs: ~[attribute], @@ -1119,23 +1009,17 @@ pub struct method { vis: visibility, } -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub struct _mod { view_items: ~[@view_item], items: ~[@item], } // Foreign mods can be named or anonymous -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub enum foreign_mod_sort { named, anonymous } -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub struct foreign_mod { sort: foreign_mod_sort, abis: AbiSet, @@ -1143,32 +1027,24 @@ pub struct foreign_mod { items: ~[@foreign_item], } -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub struct variant_arg { ty: @Ty, id: node_id, } -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub enum variant_kind { tuple_variant_kind(~[variant_arg]), struct_variant_kind(@struct_def), } -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub struct enum_def { variants: ~[variant], } -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub struct variant_ { name: ident, attrs: ~[attribute], @@ -1180,9 +1056,7 @@ pub struct variant_ { pub type variant = spanned; -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub struct path_list_ident_ { name: ident, id: node_id, @@ -1192,9 +1066,7 @@ pub type path_list_ident = spanned; pub type view_path = spanned; -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub enum view_path_ { // quux = foo::bar::baz @@ -1211,9 +1083,7 @@ pub enum view_path_ { view_path_list(@Path, ~[path_list_ident], node_id) } -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub struct view_item { node: view_item_, attrs: ~[attribute], @@ -1221,9 +1091,7 @@ pub struct view_item { span: span, } -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub enum view_item_ { view_item_extern_mod(ident, ~[@meta_item], node_id), view_item_use(~[@view_path]), @@ -1235,15 +1103,11 @@ pub type attribute = spanned; // Distinguishes between attributes that decorate items and attributes that // are contained as statements within items. These two cases need to be // distinguished for pretty-printing. -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub enum attr_style { attr_outer, attr_inner, } // doc-comments are promoted to attributes that have is_sugared_doc = true -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub struct attribute_ { style: attr_style, value: @meta_item, @@ -1257,17 +1121,13 @@ pub struct attribute_ { If this impl is an item_impl, the impl_id is redundant (it could be the same as the impl's node id). */ -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub struct trait_ref { path: @Path, ref_id: node_id, } -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub enum visibility { public, private, inherited } impl visibility { @@ -1279,9 +1139,7 @@ impl visibility { } } -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub struct struct_field_ { kind: struct_field_kind, id: node_id, @@ -1291,17 +1149,13 @@ pub struct struct_field_ { pub type struct_field = spanned; -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub enum struct_field_kind { named_field(ident, visibility), unnamed_field // element of a tuple-like struct } -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub struct struct_def { fields: ~[@struct_field], /* fields, not including ctor */ /* ID of the constructor. This is only used for tuple- or enum-like @@ -1313,9 +1167,7 @@ pub struct struct_def { FIXME (#3300): Should allow items to be anonymous. Right now we just use dummy names for anon items. */ -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub struct item { ident: ident, attrs: ~[attribute], @@ -1325,9 +1177,7 @@ pub struct item { span: span, } -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub enum item_ { item_const(@Ty, @expr), item_fn(fn_decl, purity, AbiSet, Generics, blk), @@ -1345,9 +1195,7 @@ pub enum item_ { item_mac(mac), } -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub struct foreign_item { ident: ident, attrs: ~[attribute], @@ -1357,9 +1205,7 @@ pub struct foreign_item { vis: visibility, } -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub enum foreign_item_ { foreign_item_fn(fn_decl, purity, Generics), foreign_item_const(@Ty) @@ -1368,9 +1214,7 @@ pub enum foreign_item_ { // The data we save and restore about an inlined item or method. This is not // part of the AST that we parse from a file, but it becomes part of the tree // that we trans. -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub 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 a98e3002dcfbb..aa1ee7cd27eb8 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -370,8 +370,7 @@ pub fn empty_generics() -> Generics { // ______________________________________________________________________ // Enumerating the IDs which appear in an AST -#[auto_encode] -#[auto_decode] +#[deriving(Encodable, Decodable)] pub struct id_range { min: node_id, max: node_id, diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index cd0b29f2a1e3f..44a368738fd16 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -127,9 +127,7 @@ pub struct span { expn_info: Option<@ExpnInfo> } -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, Encodable, Decodable)] pub struct spanned { node: T, span: span } impl cmp::Eq for span { diff --git a/src/libsyntax/ext/auto_encode.rs b/src/libsyntax/ext/auto_encode.rs index 5c306aefc6ad2..6bb3ac5eba4cd 100644 --- a/src/libsyntax/ext/auto_encode.rs +++ b/src/libsyntax/ext/auto_encode.rs @@ -8,102 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! - -The compiler code necessary to implement the #[auto_encode] and -#[auto_decode] extension. The idea here is that type-defining items may -be tagged with #[auto_encode] and #[auto_decode], which will cause -us to generate a little companion module with the same name as the item. - -For example, a type like: - - #[auto_encode] - #[auto_decode] - struct Node {id: uint} - -would generate two implementations like: - -impl Encodable for Node { - fn encode(&self, s: &S) { - do s.emit_struct("Node", 1) { - s.emit_field("id", 0, || s.emit_uint(self.id)) - } - } -} - -impl Decodable for node_id { - fn decode(d: &D) -> Node { - do d.read_struct("Node", 1) { - Node { - id: d.read_field(~"x", 0, || decode(d)) - } - } - } -} - -Other interesting scenarios are whe the item has type parameters or -references other non-built-in types. A type definition like: - - #[auto_encode] - #[auto_decode] - struct spanned {node: T, span: span} - -would yield functions like: - - impl< - S: Encoder, - T: Encodable - > spanned: Encodable { - fn encode(s: &S) { - do s.emit_rec { - s.emit_field("node", 0, || self.node.encode(s)); - s.emit_field("span", 1, || self.span.encode(s)); - } - } - } - - impl< - D: Decoder, - T: Decodable - > spanned: Decodable { - fn decode(d: &D) -> spanned { - do d.read_rec { - { - node: d.read_field(~"node", 0, || decode(d)), - span: d.read_field(~"span", 1, || decode(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. - -*/ +/// Deprecated #[auto_encode] and #[auto_decode] syntax extensions use ast; -use ast_util; -use attr; -use codemap; use codemap::span; use ext::base::*; -use parse; -use opt_vec; -use opt_vec::OptVec; -use ext::build; - -// Transitional reexports so qquote can find the paths it is looking for -mod syntax { - pub use ext; - pub use parse; -} pub fn expand_auto_encode( cx: @ext_ctxt, @@ -111,53 +20,8 @@ pub fn expand_auto_encode( _mitem: @ast::meta_item, in_items: ~[@ast::item] ) -> ~[@ast::item] { - fn is_auto_encode(a: &ast::attribute) -> bool { - *attr::get_attr_name(a) == ~"auto_encode" - } - - fn filter_attrs(item: @ast::item) -> @ast::item { - @ast::item { - attrs: item.attrs.filtered(|a| !is_auto_encode(a)), - .. copy *item - } - } - - do vec::flat_map(in_items) |item| { - if item.attrs.any(is_auto_encode) { - match item.node { - ast::item_struct(ref struct_def, ref generics) => { - let ser_impl = mk_struct_ser_impl( - cx, - item.span, - item.ident, - struct_def.fields, - generics - ); - - ~[filter_attrs(*item), ser_impl] - }, - ast::item_enum(ref enum_def, ref generics) => { - let ser_impl = mk_enum_ser_impl( - cx, - item.span, - item.ident, - copy *enum_def, - generics - ); - - ~[filter_attrs(*item), ser_impl] - }, - _ => { - cx.span_err(span, ~"#[auto_encode] can only be \ - applied to structs, record types, \ - and enum definitions"); - ~[*item] - } - } - } else { - ~[*item] - } - } + cx.span_err(span, "`#[auto_encode]` is deprecated, use `#[deriving(Encodable)]` instead"); + in_items } pub fn expand_auto_decode( @@ -166,1346 +30,6 @@ pub fn expand_auto_decode( _mitem: @ast::meta_item, in_items: ~[@ast::item] ) -> ~[@ast::item] { - fn is_auto_decode(a: &ast::attribute) -> bool { - *attr::get_attr_name(a) == ~"auto_decode" - } - - fn filter_attrs(item: @ast::item) -> @ast::item { - @ast::item { - attrs: item.attrs.filtered(|a| !is_auto_decode(a)), - .. copy *item - } - } - - do vec::flat_map(in_items) |item| { - if item.attrs.any(is_auto_decode) { - match item.node { - ast::item_struct(ref struct_def, ref generics) => { - let deser_impl = mk_struct_deser_impl( - cx, - item.span, - item.ident, - struct_def.fields, - generics - ); - - ~[filter_attrs(*item), deser_impl] - }, - ast::item_enum(ref enum_def, ref generics) => { - let deser_impl = mk_enum_deser_impl( - cx, - item.span, - item.ident, - copy *enum_def, - generics - ); - - ~[filter_attrs(*item), deser_impl] - }, - _ => { - cx.span_err(span, ~"#[auto_decode] can only be \ - applied to structs, record types, \ - and enum definitions"); - ~[*item] - } - } - } else { - ~[*item] - } - } -} - -trait ExtCtxtMethods { - fn bind_path(&self, - span: span, - ident: ast::ident, - path: @ast::Path, - bounds: @OptVec) - -> ast::TyParam; - fn expr(&self, span: span, node: ast::expr_) -> @ast::expr; - fn path(&self, span: span, strs: ~[ast::ident]) -> @ast::Path; - fn path_global(&self, span: span, strs: ~[ast::ident]) -> @ast::Path; - fn path_tps(&self, span: span, strs: ~[ast::ident], tps: ~[@ast::Ty]) - -> @ast::Path; - fn path_tps_global(&self, - span: span, - strs: ~[ast::ident], - tps: ~[@ast::Ty]) - -> @ast::Path; - fn ty_path(&self, span: span, strs: ~[ast::ident], tps: ~[@ast::Ty]) - -> @ast::Ty; - fn binder_pat(&self, span: span, nm: ast::ident) -> @ast::pat; - fn stmt(&self, expr: @ast::expr) -> @ast::stmt; - fn lit_str(&self, span: span, s: @~str) -> @ast::expr; - fn lit_uint(&self, span: span, i: uint) -> @ast::expr; - fn lambda0(&self, blk: ast::blk) -> @ast::expr; - fn lambda1(&self, blk: ast::blk, ident: ast::ident) -> @ast::expr; - fn blk(&self, span: span, stmts: ~[@ast::stmt]) -> ast::blk; - fn expr_blk(&self, expr: @ast::expr) -> ast::blk; - fn expr_path(&self, span: span, strs: ~[ast::ident]) -> @ast::expr; - fn expr_path_global(&self, span: span, strs: ~[ast::ident]) -> @ast::expr; - fn expr_var(&self, span: span, var: &str) -> @ast::expr; - fn expr_self(&self, span: span) -> @ast::expr; - fn expr_field(&self, span: span, expr: @ast::expr, ident: ast::ident) - -> @ast::expr; - fn expr_call(&self, span: span, expr: @ast::expr, args: ~[@ast::expr]) - -> @ast::expr; - fn expr_method_call(&self, - span: span, - expr: @ast::expr, - ident: ast::ident, - args: ~[@ast::expr]) - -> @ast::expr; - fn lambda_expr_0(&self, expr: @ast::expr) -> @ast::expr; - fn lambda_expr_1(&self, expr: @ast::expr, ident: ast::ident) - -> @ast::expr; - fn lambda_stmts_0(&self, span: span, stmts: ~[@ast::stmt]) -> @ast::expr; - fn lambda_stmts_1(&self, - span: span, - stmts: ~[@ast::stmt], - ident: ast::ident) - -> @ast::expr; -} - -impl ExtCtxtMethods for @ext_ctxt { - fn bind_path( - &self, - _span: span, - ident: ast::ident, - path: @ast::Path, - bounds: @OptVec - ) -> ast::TyParam { - let bound = ast::TraitTyParamBound(@ast::trait_ref { - ref_id: self.next_id(), - path: path - }); - - ast::TyParam { - ident: ident, - id: self.next_id(), - bounds: @bounds.prepend(bound) - } - } - - fn expr(&self, span: span, node: ast::expr_) -> @ast::expr { - @ast::expr { - id: self.next_id(), - callee_id: self.next_id(), - node: node, - span: span, - } - } - - fn path(&self, span: span, strs: ~[ast::ident]) -> @ast::Path { - @ast::Path { - span: span, - global: false, - idents: strs, - rp: None, - types: ~[] - } - } - - fn path_global(&self, span: span, strs: ~[ast::ident]) -> @ast::Path { - @ast::Path { - span: span, - global: true, - idents: strs, - rp: None, - types: ~[] - } - } - - fn path_tps( - &self, - span: span, - strs: ~[ast::ident], - tps: ~[@ast::Ty] - ) -> @ast::Path { - @ast::Path { - span: span, - global: false, - idents: strs, - rp: None, - types: tps - } - } - - fn path_tps_global( - &self, - span: span, - strs: ~[ast::ident], - tps: ~[@ast::Ty] - ) -> @ast::Path { - @ast::Path { - span: span, - global: true, - idents: strs, - rp: None, - types: tps - } - } - - fn ty_path( - &self, - span: span, - strs: ~[ast::ident], - tps: ~[@ast::Ty] - ) -> @ast::Ty { - @ast::Ty { - id: self.next_id(), - node: ast::ty_path( - self.path_tps(span, strs, tps), - self.next_id()), - span: span, - } - } - - fn binder_pat(&self, span: span, nm: ast::ident) -> @ast::pat { - @ast::pat { - id: self.next_id(), - node: ast::pat_ident( - ast::bind_by_ref(ast::m_imm), - self.path(span, ~[nm]), - None), - span: span, - } - } - - fn stmt(&self, expr: @ast::expr) -> @ast::stmt { - @codemap::spanned { node: ast::stmt_semi(expr, self.next_id()), - span: expr.span } - } - - fn lit_str(&self, span: span, s: @~str) -> @ast::expr { - self.expr( - span, - ast::expr_vstore( - self.expr( - span, - ast::expr_lit( - @codemap::spanned { node: ast::lit_str(s), - span: span})), - ast::expr_vstore_uniq)) - } - - fn lit_uint(&self, span: span, i: uint) -> @ast::expr { - self.expr( - span, - ast::expr_lit( - @codemap::spanned { node: ast::lit_uint(i as u64, ast::ty_u), - span: span})) - } - - fn lambda0(&self, blk: ast::blk) -> @ast::expr { - let ext_cx = *self; - let blk_e = self.expr(copy blk.span, ast::expr_block(copy blk)); - quote_expr!( || $blk_e ) - } - - fn lambda1(&self, blk: ast::blk, ident: ast::ident) -> @ast::expr { - let ext_cx = *self; - let blk_e = self.expr(copy blk.span, ast::expr_block(copy blk)); - quote_expr!( |$ident| $blk_e ) - } - - fn blk(&self, span: span, stmts: ~[@ast::stmt]) -> ast::blk { - codemap::spanned { - node: ast::blk_ { - view_items: ~[], - stmts: stmts, - expr: None, - id: self.next_id(), - rules: ast::default_blk, - }, - span: span, - } - } - - fn expr_blk(&self, expr: @ast::expr) -> ast::blk { - codemap::spanned { - node: ast::blk_ { - view_items: ~[], - stmts: ~[], - expr: Some(expr), - id: self.next_id(), - rules: ast::default_blk, - }, - span: expr.span, - } - } - - fn expr_path(&self, span: span, strs: ~[ast::ident]) -> @ast::expr { - self.expr(span, ast::expr_path(self.path(span, strs))) - } - - fn expr_path_global( - &self, - span: span, - strs: ~[ast::ident] - ) -> @ast::expr { - self.expr(span, ast::expr_path(self.path_global(span, strs))) - } - - fn expr_var(&self, span: span, var: &str) -> @ast::expr { - self.expr_path(span, ~[self.ident_of(var)]) - } - - fn expr_self(&self, span: span) -> @ast::expr { - self.expr(span, ast::expr_self) - } - - fn expr_field( - &self, - span: span, - expr: @ast::expr, - ident: ast::ident - ) -> @ast::expr { - self.expr(span, ast::expr_field(expr, ident, ~[])) - } - - fn expr_call( - &self, - span: span, - expr: @ast::expr, - args: ~[@ast::expr] - ) -> @ast::expr { - self.expr(span, ast::expr_call(expr, args, ast::NoSugar)) - } - - fn expr_method_call( - &self, - span: span, - expr: @ast::expr, - ident: ast::ident, - args: ~[@ast::expr] - ) -> @ast::expr { - self.expr(span, - ast::expr_method_call(expr, ident, ~[], args, ast::NoSugar)) - } - - fn lambda_expr_0(&self, expr: @ast::expr) -> @ast::expr { - self.lambda0(self.expr_blk(expr)) - } - - fn lambda_expr_1(&self, expr: @ast::expr, ident: ast::ident) - -> @ast::expr { - self.lambda1(self.expr_blk(expr), ident) - } - - fn lambda_stmts_0(&self, span: span, stmts: ~[@ast::stmt]) -> @ast::expr { - self.lambda0(self.blk(span, stmts)) - } - - fn lambda_stmts_1(&self, - span: span, - stmts: ~[@ast::stmt], - ident: ast::ident) - -> @ast::expr { - self.lambda1(self.blk(span, stmts), ident) - } -} - -fn mk_impl( - cx: @ext_ctxt, - span: span, - ident: ast::ident, - ty_param: ast::TyParam, - path: @ast::Path, - generics: &ast::Generics, - f: &fn(@ast::Ty) -> @ast::method -) -> @ast::item { - /*! - * - * Given that we are deriving auto-encode a type `T<'a, ..., - * 'z, A, ..., Z>`, creates an impl like: - * - * impl<'a, ..., 'z, A:Tr, ..., Z:Tr> Tr for T { ... } - * - * where Tr is either Serializable and Deserialize. - * - * FIXME(#5090): Remove code duplication between this and the code - * in deriving.rs - */ - - - // Copy the lifetimes - let impl_lifetimes = generics.lifetimes.map(|l| { - build::mk_lifetime(cx, l.span, l.ident) - }); - - // All the type parameters need to bound to the trait. - let mut impl_tps = opt_vec::with(ty_param); - for generics.ty_params.each |tp| { - let t_bound = ast::TraitTyParamBound(@ast::trait_ref { - path: path, - ref_id: cx.next_id(), - }); - - impl_tps.push(ast::TyParam { - ident: tp.ident, - id: cx.next_id(), - bounds: @tp.bounds.prepend(t_bound) - }) - } - - let opt_trait = Some(@ast::trait_ref { - path: path, - ref_id: cx.next_id(), - }); - - let ty = cx.ty_path( - span, - ~[ident], - opt_vec::take_vec(generics.ty_params.map( - |tp| cx.ty_path(span, ~[tp.ident], ~[]))) - ); - - let generics = ast::Generics { - lifetimes: impl_lifetimes, - ty_params: impl_tps - }; - - @ast::item { - // This is a new-style impl declaration. - // XXX: clownshoes - ident: parse::token::special_idents::clownshoes_extensions, - attrs: ~[], - id: cx.next_id(), - node: ast::item_impl(generics, opt_trait, ty, ~[f(ty)]), - vis: ast::public, - span: span, - } -} - -fn mk_ser_impl( - cx: @ext_ctxt, - span: span, - ident: ast::ident, - generics: &ast::Generics, - body: @ast::expr -) -> @ast::item { - // Make a path to the std::serialize::Encodable typaram. - let ty_param = cx.bind_path( - span, - cx.ident_of("__S"), - cx.path_global( - span, - ~[ - cx.ident_of("std"), - cx.ident_of("serialize"), - cx.ident_of("Encoder"), - ] - ), - @opt_vec::Empty - ); - - // Make a path to the std::serialize::Encodable trait. - let path = cx.path_tps_global( - span, - ~[ - cx.ident_of("std"), - cx.ident_of("serialize"), - cx.ident_of("Encodable"), - ], - ~[cx.ty_path(span, ~[cx.ident_of("__S")], ~[])] - ); - - mk_impl( - cx, - span, - ident, - ty_param, - path, - generics, - |_ty| mk_ser_method(cx, span, cx.expr_blk(body)) - ) -} - -fn mk_deser_impl( - cx: @ext_ctxt, - span: span, - ident: ast::ident, - generics: &ast::Generics, - body: @ast::expr -) -> @ast::item { - // Make a path to the std::serialize::Decodable typaram. - let ty_param = cx.bind_path( - span, - cx.ident_of("__D"), - cx.path_global( - span, - ~[ - cx.ident_of("std"), - cx.ident_of("serialize"), - cx.ident_of("Decoder"), - ] - ), - @opt_vec::Empty - ); - - // Make a path to the std::serialize::Decodable trait. - let path = cx.path_tps_global( - span, - ~[ - cx.ident_of("std"), - cx.ident_of("serialize"), - cx.ident_of("Decodable"), - ], - ~[cx.ty_path(span, ~[cx.ident_of("__D")], ~[])] - ); - - mk_impl( - cx, - span, - ident, - ty_param, - path, - generics, - |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 ty_s = @ast::Ty { - id: cx.next_id(), - node: ast::ty_rptr( - None, - ast::mt { - ty: cx.ty_path(span, ~[cx.ident_of("__S")], ~[]), - mutbl: ast::m_mutbl - } - ), - span: span, - }; - - let ser_inputs = ~[ast::arg { - is_mutbl: false, - ty: ty_s, - pat: @ast::pat { - id: cx.next_id(), - node: ast::pat_ident( - ast::bind_by_copy, - ast_util::ident_to_path(span, cx.ident_of("__s")), - None), - span: span, - }, - id: cx.next_id(), - }]; - - let ser_output = @ast::Ty { - id: cx.next_id(), - node: ast::ty_nil, - span: span, - }; - - let ser_decl = ast::fn_decl { - inputs: ser_inputs, - output: ser_output, - cf: ast::return_val, - }; - - @ast::method { - ident: cx.ident_of("encode"), - attrs: ~[], - generics: ast_util::empty_generics(), - explicit_self: codemap::spanned { - node: ast::sty_region(None, 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 ty_d = @ast::Ty { - id: cx.next_id(), - node: ast::ty_rptr( - None, - ast::mt { - ty: cx.ty_path(span, ~[cx.ident_of("__D")], ~[]), - mutbl: ast::m_mutbl - } - ), - span: span, - }; - - let deser_inputs = ~[ - ast::arg { - is_mutbl: false, - ty: ty_d, - pat: @ast::pat { - id: cx.next_id(), - node: ast::pat_ident(ast::bind_by_copy, - ast_util::ident_to_path(span, - cx.ident_of( - "__d")), - None), - span: span, - }, - id: cx.next_id(), - } - ]; - - let deser_decl = ast::fn_decl { - inputs: deser_inputs, - output: ty, - cf: ast::return_val, - }; - - @ast::method { - ident: cx.ident_of("decode"), - attrs: ~[], - generics: ast_util::empty_generics(), - explicit_self: codemap::spanned { 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_struct_ser_impl( - cx: @ext_ctxt, - span: span, - ident: ast::ident, - fields: &[@ast::struct_field], - generics: &ast::Generics -) -> @ast::item { - let fields = do mk_struct_fields(fields).mapi |idx, field| { - // ast for `|__s| self.$(name).encode(__s)` - let expr_lambda = cx.lambda_expr_1( - cx.expr_method_call( - span, - cx.expr_field(span, cx.expr_self(span), field.ident), - cx.ident_of(~"encode"), - ~[cx.expr_var(span, "__s")] - ), - cx.ident_of("__s") - ); - - // 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_struct_field"), - ~[ - cx.lit_str(span, @cx.str_of(field.ident)), - cx.lit_uint(span, idx), - expr_lambda, - ] - ) - ) - }; - - // ast for `__s.emit_struct($(name), |__s| $(fields))` - let ser_body = cx.expr_method_call( - span, - cx.expr_var(span, "__s"), - cx.ident_of("emit_struct"), - ~[ - cx.lit_str(span, @cx.str_of(ident)), - cx.lit_uint(span, fields.len()), - cx.lambda_stmts_1(span, fields, cx.ident_of("__s")), - ] - ); - - mk_ser_impl(cx, span, ident, generics, ser_body) -} - -fn mk_struct_deser_impl( - cx: @ext_ctxt, - span: span, - ident: ast::ident, - fields: &[@ast::struct_field], - generics: &ast::Generics -) -> @ast::item { - let fields = do mk_struct_fields(fields).mapi |idx, field| { - // ast for `|__d| std::serialize::decode(__d)` - let expr_lambda = cx.lambda1( - cx.expr_blk( - cx.expr_call( - span, - cx.expr_path_global(span, ~[ - cx.ident_of("std"), - cx.ident_of("serialize"), - cx.ident_of("Decodable"), - cx.ident_of("decode"), - ]), - ~[cx.expr_var(span, "__d")] - ) - ), - cx.ident_of("__d") - ); - - // 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_struct_field"), - ~[ - cx.lit_str(span, @cx.str_of(field.ident)), - cx.lit_uint(span, idx), - expr_lambda, - ] - ); - - codemap::spanned { - node: ast::field_ { - mutbl: field.mutbl, - ident: field.ident, - expr: expr, - }, - span: span, - } - }; - - // ast for `read_struct($(name), |__d| $(fields))` - let body = cx.expr_method_call( - span, - cx.expr_var(span, "__d"), - cx.ident_of("read_struct"), - ~[ - cx.lit_str(span, @cx.str_of(ident)), - cx.lit_uint(span, fields.len()), - cx.lambda_expr_1( - cx.expr( - span, - ast::expr_struct( - cx.path(span, ~[ident]), - fields, - None - ) - ), - cx.ident_of("__d") - ), - ] - ); - - mk_deser_impl(cx, span, ident, generics, 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 code -// generator code. -struct field { - span: span, - ident: ast::ident, - mutbl: ast::mutability, -} - -fn mk_struct_fields(fields: &[@ast::struct_field]) -> ~[field] { - do fields.map |field| { - let ident = match field.node.kind { - ast::named_field(ident, _) => ident, - _ => fail!("[auto_encode] does not support unnamed fields") - }; - - field { - span: field.span, - ident: ident, - mutbl: ast::m_imm, - } - } -} - -fn mk_enum_ser_impl( - cx: @ext_ctxt, - span: span, - ident: ast::ident, - enum_def: ast::enum_def, - generics: &ast::Generics -) -> @ast::item { - let body = mk_enum_ser_body( - cx, - span, - ident, - copy enum_def.variants - ); - - mk_ser_impl(cx, span, ident, generics, body) -} - -fn mk_enum_deser_impl( - cx: @ext_ctxt, - span: span, - ident: ast::ident, - enum_def: ast::enum_def, - generics: &ast::Generics -) -> @ast::item { - let body = mk_enum_deser_body( - cx, - span, - ident, - enum_def.variants - ); - - mk_deser_impl(cx, span, ident, generics, 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_infer, - cx.path(span, ~[v_name]), - None - ) - } else { - ast::pat_enum( - cx.path(span, ~[v_name]), - Some(pats) - ) - }; - - let pat = @ast::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 `|__s| $(v).encode(__s)` - let expr_encode = cx.lambda_expr_1( - cx.expr_method_call( - span, - cx.expr_path(span, ~[names[a_idx]]), - cx.ident_of("encode"), - ~[cx.expr_var(span, "__s")] - ), - cx.ident_of("__s") - ); - - // ast for `$(expr_emit)($(a_idx), $(expr_encode))` - cx.stmt( - cx.expr_call( - span, - expr_emit, - ~[cx.lit_uint(span, a_idx), expr_encode] - ) - ) - }; - - // ast for `__s.emit_enum_variant($(name), $(idx), $(sz), $(lambda))` - let body = cx.expr_method_call( - 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_1(span, stmts, cx.ident_of("__s")), - ] - ); - - ast::arm { 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(ref args) => - ser_variant( - cx, - span, - variant.node.name, - v_idx, - /*bad*/ copy *args - ), - ast::struct_variant_kind(*) => - fail!("struct 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_self(span))), - arms) - ); - - // ast for `__s.emit_enum($(name), || $(match_expr))` - cx.expr_method_call( - span, - cx.expr_var(span, "__s"), - cx.ident_of("emit_enum"), - ~[ - cx.lit_str(span, @cx.str_of(name)), - cx.lambda_expr_1(match_expr, cx.ident_of("__s")), - ] - ) -} - -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 `|__s| std::serialize::decode(__d)` - let expr_lambda = cx.lambda_expr_1( - cx.expr_call( - span, - cx.expr_path_global(span, ~[ - cx.ident_of("std"), - cx.ident_of("serialize"), - cx.ident_of("Decodable"), - cx.ident_of("decode"), - ]), - ~[cx.expr_var(span, "__d")] - ), - cx.ident_of("__d") - ); - - // ast for `__d.read_enum_variant_arg($(a_idx), $(expr_lambda))` - cx.expr_method_call( - 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( - ext_cx: @ext_ctxt, - span: span, - name: ast::ident, - variants: &[ast::variant] -) -> @ast::expr { - let expr_arm_names = build::mk_base_vec_e( - ext_cx, - span, - do variants.map |variant| { - build::mk_base_str( - ext_cx, - span, - ext_cx.str_of(variant.node.name) - ) - } - ); - - let mut arms = do variants.mapi |v_idx, variant| { - let body = match variant.node.kind { - ast::tuple_variant_kind(ref args) => { - if args.is_empty() { - // for a nullary variant v, do "v" - ext_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( - ext_cx, - span, - variant.node.name, - copy *args - ) - } - }, - ast::struct_variant_kind(*) => - fail!("struct variants unimplemented"), - }; - - let pat = @ast::pat { - id: ext_cx.next_id(), - node: ast::pat_lit(ext_cx.lit_uint(span, v_idx)), - span: span, - }; - - ast::arm { - pats: ~[pat], - guard: None, - body: ext_cx.expr_blk(body), - } - }; - - let quoted_expr = copy quote_expr!( - ::core::sys::FailWithCause::fail_with("explicit failure", "empty", 1); - ).node; - - let impossible_case = ast::arm { - pats: ~[@ast::pat { - id: ext_cx.next_id(), - node: ast::pat_wild, - span: span, - }], - guard: None, - - // FIXME(#3198): proper error message - body: ext_cx.expr_blk(ext_cx.expr(span, quoted_expr)), - }; - - arms.push(impossible_case); - - // ast for `|i| { match i { $(arms) } }` - let expr_lambda = ext_cx.expr( - span, - ast::expr_fn_block( - ast::fn_decl { - inputs: ~[ - ast::arg { - is_mutbl: false, - ty: @ast::Ty { - id: ext_cx.next_id(), - node: ast::ty_infer, - span: span - }, - pat: @ast::pat { - id: ext_cx.next_id(), - node: ast::pat_ident( - ast::bind_by_copy, - ast_util::ident_to_path(span, - ext_cx.ident_of("__d")), - None), - span: span, - }, - id: ext_cx.next_id(), - }, - ast::arg { - is_mutbl: false, - ty: @ast::Ty { - id: ext_cx.next_id(), - node: ast::ty_infer, - span: span - }, - pat: @ast::pat { - id: ext_cx.next_id(), - node: ast::pat_ident( - ast::bind_by_copy, - ast_util::ident_to_path(span, - ext_cx.ident_of("i")), - None), - span: span, - }, - id: ext_cx.next_id(), - } - ], - output: @ast::Ty { - id: ext_cx.next_id(), - node: ast::ty_infer, - span: span, - }, - cf: ast::return_val, - }, - ext_cx.expr_blk( - ext_cx.expr( - span, - ast::expr_match(ext_cx.expr_var(span, "i"), arms) - ) - ) - ) - ); - - // ast for `__d.read_enum_variant($expr_arm_names, $(expr_lambda))` - let expr_lambda = ext_cx.lambda_expr_1( - ext_cx.expr_method_call( - span, - ext_cx.expr_var(span, "__d"), - ext_cx.ident_of("read_enum_variant"), - ~[expr_arm_names, expr_lambda] - ), - ext_cx.ident_of("__d") - ); - - // ast for `__d.read_enum($(e_name), $(expr_lambda))` - ext_cx.expr_method_call( - span, - ext_cx.expr_var(span, "__d"), - ext_cx.ident_of("read_enum"), - ~[ - ext_cx.lit_str(span, @ext_cx.str_of(name)), - expr_lambda - ] - ) -} - -#[cfg(test)] -mod test { - use core::option::{None, Some}; - use std::serialize::Encodable; - use std::serialize::Encoder; - - // just adding the ones I want to test, for now: - #[deriving(Eq)] - pub enum call { - CallToEmitEnum(~str), - CallToEmitEnumVariant(~str, uint, uint), - CallToEmitEnumVariantArg(uint), - CallToEmitUint(uint), - CallToEmitNil, - CallToEmitStruct(~str,uint), - CallToEmitField(~str,uint), - CallToEmitOption, - CallToEmitOptionNone, - CallToEmitOptionSome, - // all of the ones I was too lazy to handle: - CallToOther - } - // using `@mut` rather than changing the - // type of self in every method of every encoder everywhere. - pub struct TestEncoder {call_log : @mut ~[call]} - - pub impl TestEncoder { - // these self's should be &mut self's, as well.... - fn add_to_log (&self, c : call) { - self.call_log.push(copy c); - } - fn add_unknown_to_log (&self) { - self.add_to_log (CallToOther) - } - } - - impl Encoder for TestEncoder { - fn emit_nil(&mut self) { self.add_to_log(CallToEmitNil) } - - fn emit_uint(&mut self, v: uint) { - self.add_to_log(CallToEmitUint(v)); - } - fn emit_u64(&mut self, _v: u64) { self.add_unknown_to_log(); } - fn emit_u32(&mut self, _v: u32) { self.add_unknown_to_log(); } - fn emit_u16(&mut self, _v: u16) { self.add_unknown_to_log(); } - fn emit_u8(&mut self, _v: u8) { self.add_unknown_to_log(); } - - fn emit_int(&mut self, _v: int) { self.add_unknown_to_log(); } - fn emit_i64(&mut self, _v: i64) { self.add_unknown_to_log(); } - fn emit_i32(&mut self, _v: i32) { self.add_unknown_to_log(); } - fn emit_i16(&mut self, _v: i16) { self.add_unknown_to_log(); } - fn emit_i8(&mut self, _v: i8) { self.add_unknown_to_log(); } - - fn emit_bool(&mut self, _v: bool) { self.add_unknown_to_log(); } - - fn emit_f64(&mut self, _v: f64) { self.add_unknown_to_log(); } - fn emit_f32(&mut self, _v: f32) { self.add_unknown_to_log(); } - fn emit_float(&mut self, _v: float) { self.add_unknown_to_log(); } - - fn emit_char(&mut self, _v: char) { self.add_unknown_to_log(); } - fn emit_str(&mut self, _v: &str) { self.add_unknown_to_log(); } - - fn emit_enum(&mut self, name: &str, f: &fn(&mut TestEncoder)) { - self.add_to_log(CallToEmitEnum(name.to_str())); - f(self); - } - - fn emit_enum_variant(&mut self, - name: &str, - id: uint, - cnt: uint, - f: &fn(&mut TestEncoder)) { - self.add_to_log(CallToEmitEnumVariant(name.to_str(), id, cnt)); - f(self); - } - - fn emit_enum_variant_arg(&mut self, - idx: uint, - f: &fn(&mut TestEncoder)) { - self.add_to_log(CallToEmitEnumVariantArg(idx)); - f(self); - } - - fn emit_enum_struct_variant(&mut self, - name: &str, - id: uint, - cnt: uint, - f: &fn(&mut TestEncoder)) { - self.emit_enum_variant(name, id, cnt, f) - } - - fn emit_enum_struct_variant_field(&mut self, - _name: &str, - idx: uint, - f: &fn(&mut TestEncoder)) { - self.emit_enum_variant_arg(idx, f) - } - - fn emit_struct(&mut self, - name: &str, - len: uint, - f: &fn(&mut TestEncoder)) { - self.add_to_log(CallToEmitStruct (name.to_str(),len)); - f(self); - } - fn emit_struct_field(&mut self, - name: &str, - idx: uint, - f: &fn(&mut TestEncoder)) { - self.add_to_log(CallToEmitField (name.to_str(),idx)); - f(self); - } - - fn emit_tuple(&mut self, _len: uint, f: &fn(&mut TestEncoder)) { - self.add_unknown_to_log(); - f(self); - } - fn emit_tuple_arg(&mut self, _idx: uint, f: &fn(&mut TestEncoder)) { - self.add_unknown_to_log(); - f(self); - } - - fn emit_tuple_struct(&mut self, - _name: &str, - _len: uint, - f: &fn(&mut TestEncoder)) { - self.add_unknown_to_log(); - f(self); - } - - fn emit_tuple_struct_arg(&mut self, - _idx: uint, - f: &fn(&mut TestEncoder)) { - self.add_unknown_to_log(); - f(self); - } - - fn emit_option(&mut self, f: &fn(&mut TestEncoder)) { - self.add_to_log(CallToEmitOption); - f(self); - } - fn emit_option_none(&mut self) { - self.add_to_log(CallToEmitOptionNone); - } - fn emit_option_some(&mut self, f: &fn(&mut TestEncoder)) { - self.add_to_log(CallToEmitOptionSome); - f(self); - } - - fn emit_seq(&mut self, _len: uint, f: &fn(&mut TestEncoder)) { - self.add_unknown_to_log(); - f(self); - } - fn emit_seq_elt(&mut self, _idx: uint, f: &fn(&mut TestEncoder)) { - self.add_unknown_to_log(); - f(self); - } - - fn emit_map(&mut self, _len: uint, f: &fn(&mut TestEncoder)) { - self.add_unknown_to_log(); - f(self); - } - fn emit_map_elt_key(&mut self, _idx: uint, f: &fn(&mut TestEncoder)) { - self.add_unknown_to_log(); - f(self); - } - fn emit_map_elt_val(&mut self, _idx: uint, f: &fn(&mut TestEncoder)) { - self.add_unknown_to_log(); - f(self); - } - } - - - fn to_call_log>(val: E) -> ~[call] { - let mut te = TestEncoder { - call_log: @mut ~[] - }; - val.encode(&mut te); - copy *te.call_log - } - - #[auto_encode] - enum Written { - Book(uint,uint), - Magazine(~str) - } - - #[test] - fn test_encode_enum() { - assert_eq!( - to_call_log(Book(34,44)), - ~[ - CallToEmitEnum(~"Written"), - CallToEmitEnumVariant(~"Book",0,2), - CallToEmitEnumVariantArg(0), - CallToEmitUint(34), - CallToEmitEnumVariantArg(1), - CallToEmitUint(44), - ] - ); - } - - pub struct BPos(uint); - - #[auto_encode] - pub struct HasPos { pos : BPos } - - #[test] - fn test_encode_newtype() { - assert_eq!( - to_call_log(HasPos { pos:BPos(48) }), - ~[ - CallToEmitStruct(~"HasPos",1), - CallToEmitField(~"pos",0), - CallToEmitUint(48), - ] - ); - } - - #[test] - fn test_encode_option() { - let mut v = None; - - assert_eq!( - to_call_log(v), - ~[ - CallToEmitOption, - CallToEmitOptionNone, - ] - ); - - v = Some(54u); - assert_eq!( - to_call_log(v), - ~[ - CallToEmitOption, - CallToEmitOptionSome, - CallToEmitUint(54) - ] - ); - } + cx.span_err(span, "`#[auto_decode]` is deprecated, use `#[deriving(Decodable)]` instead"); + in_items } diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 605ba65b51a9d..01b37a1196cda 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -538,3 +538,301 @@ pub fn duplicate_expr(cx: @ext_ctxt, expr: @ast::expr) -> @ast::expr { folder.fold_expr(expr) } + + +// Transitional reexports so qquote can find the paths it is looking for +mod syntax { + pub use ext; + pub use parse; +} + +trait ExtCtxtMethods { + fn bind_path(&self, + span: span, + ident: ast::ident, + path: @ast::Path, + bounds: @OptVec) + -> ast::TyParam; + fn expr(&self, span: span, node: ast::expr_) -> @ast::expr; + fn path(&self, span: span, strs: ~[ast::ident]) -> @ast::Path; + fn path_global(&self, span: span, strs: ~[ast::ident]) -> @ast::Path; + fn path_tps(&self, span: span, strs: ~[ast::ident], tps: ~[@ast::Ty]) + -> @ast::Path; + fn path_tps_global(&self, + span: span, + strs: ~[ast::ident], + tps: ~[@ast::Ty]) + -> @ast::Path; + fn ty_path(&self, span: span, strs: ~[ast::ident], tps: ~[@ast::Ty]) + -> @ast::Ty; + fn binder_pat(&self, span: span, nm: ast::ident) -> @ast::pat; + fn stmt(&self, expr: @ast::expr) -> @ast::stmt; + fn lit_str(&self, span: span, s: @~str) -> @ast::expr; + fn lit_uint(&self, span: span, i: uint) -> @ast::expr; + fn lambda0(&self, blk: ast::blk) -> @ast::expr; + fn lambda1(&self, blk: ast::blk, ident: ast::ident) -> @ast::expr; + fn blk(&self, span: span, stmts: ~[@ast::stmt]) -> ast::blk; + fn expr_blk(&self, expr: @ast::expr) -> ast::blk; + fn expr_path(&self, span: span, strs: ~[ast::ident]) -> @ast::expr; + fn expr_path_global(&self, span: span, strs: ~[ast::ident]) -> @ast::expr; + fn expr_var(&self, span: span, var: &str) -> @ast::expr; + fn expr_self(&self, span: span) -> @ast::expr; + fn expr_field(&self, span: span, expr: @ast::expr, ident: ast::ident) + -> @ast::expr; + fn expr_call(&self, span: span, expr: @ast::expr, args: ~[@ast::expr]) + -> @ast::expr; + fn expr_method_call(&self, + span: span, + expr: @ast::expr, + ident: ast::ident, + args: ~[@ast::expr]) + -> @ast::expr; + fn lambda_expr_0(&self, expr: @ast::expr) -> @ast::expr; + fn lambda_expr_1(&self, expr: @ast::expr, ident: ast::ident) + -> @ast::expr; + fn lambda_stmts_0(&self, span: span, stmts: ~[@ast::stmt]) -> @ast::expr; + fn lambda_stmts_1(&self, + span: span, + stmts: ~[@ast::stmt], + ident: ast::ident) + -> @ast::expr; +} + +impl ExtCtxtMethods for @ext_ctxt { + fn bind_path( + &self, + _span: span, + ident: ast::ident, + path: @ast::Path, + bounds: @OptVec + ) -> ast::TyParam { + let bound = ast::TraitTyParamBound(@ast::trait_ref { + ref_id: self.next_id(), + path: path + }); + + ast::TyParam { + ident: ident, + id: self.next_id(), + bounds: @bounds.prepend(bound) + } + } + + fn expr(&self, span: span, node: ast::expr_) -> @ast::expr { + @ast::expr { + id: self.next_id(), + callee_id: self.next_id(), + node: node, + span: span, + } + } + + fn path(&self, span: span, strs: ~[ast::ident]) -> @ast::Path { + @ast::Path { + span: span, + global: false, + idents: strs, + rp: None, + types: ~[] + } + } + + fn path_global(&self, span: span, strs: ~[ast::ident]) -> @ast::Path { + @ast::Path { + span: span, + global: true, + idents: strs, + rp: None, + types: ~[] + } + } + + fn path_tps( + &self, + span: span, + strs: ~[ast::ident], + tps: ~[@ast::Ty] + ) -> @ast::Path { + @ast::Path { + span: span, + global: false, + idents: strs, + rp: None, + types: tps + } + } + + fn path_tps_global( + &self, + span: span, + strs: ~[ast::ident], + tps: ~[@ast::Ty] + ) -> @ast::Path { + @ast::Path { + span: span, + global: true, + idents: strs, + rp: None, + types: tps + } + } + + fn ty_path( + &self, + span: span, + strs: ~[ast::ident], + tps: ~[@ast::Ty] + ) -> @ast::Ty { + @ast::Ty { + id: self.next_id(), + node: ast::ty_path( + self.path_tps(span, strs, tps), + self.next_id()), + span: span, + } + } + + fn binder_pat(&self, span: span, nm: ast::ident) -> @ast::pat { + @ast::pat { + id: self.next_id(), + node: ast::pat_ident( + ast::bind_by_ref(ast::m_imm), + self.path(span, ~[nm]), + None), + span: span, + } + } + + fn stmt(&self, expr: @ast::expr) -> @ast::stmt { + @codemap::spanned { node: ast::stmt_semi(expr, self.next_id()), + span: expr.span } + } + + fn lit_str(&self, span: span, s: @~str) -> @ast::expr { + self.expr( + span, + ast::expr_vstore( + self.expr( + span, + ast::expr_lit( + @codemap::spanned { node: ast::lit_str(s), + span: span})), + ast::expr_vstore_uniq)) + } + + fn lit_uint(&self, span: span, i: uint) -> @ast::expr { + self.expr( + span, + ast::expr_lit( + @codemap::spanned { node: ast::lit_uint(i as u64, ast::ty_u), + span: span})) + } + + fn lambda0(&self, blk: ast::blk) -> @ast::expr { + let ext_cx = *self; + let blk_e = self.expr(copy blk.span, ast::expr_block(copy blk)); + quote_expr!( || $blk_e ) + } + + fn lambda1(&self, blk: ast::blk, ident: ast::ident) -> @ast::expr { + let ext_cx = *self; + let blk_e = self.expr(copy blk.span, ast::expr_block(copy blk)); + quote_expr!( |$ident| $blk_e ) + } + + fn blk(&self, span: span, stmts: ~[@ast::stmt]) -> ast::blk { + codemap::spanned { + node: ast::blk_ { + view_items: ~[], + stmts: stmts, + expr: None, + id: self.next_id(), + rules: ast::default_blk, + }, + span: span, + } + } + + fn expr_blk(&self, expr: @ast::expr) -> ast::blk { + codemap::spanned { + node: ast::blk_ { + view_items: ~[], + stmts: ~[], + expr: Some(expr), + id: self.next_id(), + rules: ast::default_blk, + }, + span: expr.span, + } + } + + fn expr_path(&self, span: span, strs: ~[ast::ident]) -> @ast::expr { + self.expr(span, ast::expr_path(self.path(span, strs))) + } + + fn expr_path_global( + &self, + span: span, + strs: ~[ast::ident] + ) -> @ast::expr { + self.expr(span, ast::expr_path(self.path_global(span, strs))) + } + + fn expr_var(&self, span: span, var: &str) -> @ast::expr { + self.expr_path(span, ~[self.ident_of(var)]) + } + + fn expr_self(&self, span: span) -> @ast::expr { + self.expr(span, ast::expr_self) + } + + fn expr_field( + &self, + span: span, + expr: @ast::expr, + ident: ast::ident + ) -> @ast::expr { + self.expr(span, ast::expr_field(expr, ident, ~[])) + } + + fn expr_call( + &self, + span: span, + expr: @ast::expr, + args: ~[@ast::expr] + ) -> @ast::expr { + self.expr(span, ast::expr_call(expr, args, ast::NoSugar)) + } + + fn expr_method_call( + &self, + span: span, + expr: @ast::expr, + ident: ast::ident, + args: ~[@ast::expr] + ) -> @ast::expr { + self.expr(span, + ast::expr_method_call(expr, ident, ~[], args, ast::NoSugar)) + } + + fn lambda_expr_0(&self, expr: @ast::expr) -> @ast::expr { + self.lambda0(self.expr_blk(expr)) + } + + fn lambda_expr_1(&self, expr: @ast::expr, ident: ast::ident) + -> @ast::expr { + self.lambda1(self.expr_blk(expr), ident) + } + + fn lambda_stmts_0(&self, span: span, stmts: ~[@ast::stmt]) -> @ast::expr { + self.lambda0(self.blk(span, stmts)) + } + + fn lambda_stmts_1(&self, + span: span, + stmts: ~[@ast::stmt], + ident: ast::ident) + -> @ast::expr { + self.lambda1(self.blk(span, stmts), ident) + } +} diff --git a/src/libsyntax/ext/deriving/decodable.rs b/src/libsyntax/ext/deriving/decodable.rs index 3be65ecd8db9c..2e2f382a7687b 100644 --- a/src/libsyntax/ext/deriving/decodable.rs +++ b/src/libsyntax/ext/deriving/decodable.rs @@ -8,6 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +/*! +The compiler code necessary for #[deriving(Decodable)]. See +encodable.rs for more. +*/ + use ast; use ast::*; use ext::base::ext_ctxt; diff --git a/src/libsyntax/ext/deriving/encodable.rs b/src/libsyntax/ext/deriving/encodable.rs index 2078ec9d45cf4..8a1c3933f5127 100644 --- a/src/libsyntax/ext/deriving/encodable.rs +++ b/src/libsyntax/ext/deriving/encodable.rs @@ -8,6 +8,74 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +/*! + +The compiler code necessary to implement the #[deriving(Encodable)] +(and Decodable, in decodable.rs) extension. The idea here is that +type-defining items may be tagged with #[deriving(Encodable, +Decodable)]. + +For example, a type like: + + #[deriving(Encodable, Decodable)] + struct Node {id: uint} + +would generate two implementations like: + +impl Encodable for Node { + fn encode(&self, s: &S) { + do s.emit_struct("Node", 1) { + s.emit_field("id", 0, || s.emit_uint(self.id)) + } + } +} + +impl Decodable for node_id { + fn decode(d: &D) -> Node { + do d.read_struct("Node", 1) { + Node { + id: d.read_field(~"x", 0, || decode(d)) + } + } + } +} + +Other interesting scenarios are whe the item has type parameters or +references other non-built-in types. A type definition like: + + #[deriving(Encodable, Decodable)] + struct spanned {node: T, span: span} + +would yield functions like: + + impl< + S: Encoder, + T: Encodable + > spanned: Encodable { + fn encode(s: &S) { + do s.emit_rec { + s.emit_field("node", 0, || self.node.encode(s)); + s.emit_field("span", 1, || self.span.encode(s)); + } + } + } + + impl< + D: Decoder, + T: Decodable + > spanned: Decodable { + fn decode(d: &D) -> spanned { + do d.read_rec { + { + node: d.read_field(~"node", 0, || decode(d)), + span: d.read_field(~"span", 1, || decode(d)), + } + } + } + } +*/ + + use ast; use ast::*; use ext::base::ext_ctxt; @@ -403,3 +471,247 @@ fn expand_deriving_encodable_enum_method( // Create the method. create_encode_method(cx, span, ~[stmt]) } + +#[cfg(test)] +mod test { + extern mod std; + use core::option::{None, Some}; + use std::serialize::Encodable; + use std::serialize::Encoder; + + // just adding the ones I want to test, for now: + #[deriving(Eq)] + pub enum call { + CallToEmitEnum(~str), + CallToEmitEnumVariant(~str, uint, uint), + CallToEmitEnumVariantArg(uint), + CallToEmitUint(uint), + CallToEmitNil, + CallToEmitStruct(~str,uint), + CallToEmitField(~str,uint), + CallToEmitOption, + CallToEmitOptionNone, + CallToEmitOptionSome, + // all of the ones I was too lazy to handle: + CallToOther + } + // using `@mut` rather than changing the + // type of self in every method of every encoder everywhere. + pub struct TestEncoder {call_log : @mut ~[call]} + + pub impl TestEncoder { + // these self's should be &mut self's, as well.... + fn add_to_log (&self, c : call) { + self.call_log.push(copy c); + } + fn add_unknown_to_log (&self) { + self.add_to_log (CallToOther) + } + } + + impl Encoder for TestEncoder { + fn emit_nil(&mut self) { self.add_to_log(CallToEmitNil) } + + fn emit_uint(&mut self, v: uint) { + self.add_to_log(CallToEmitUint(v)); + } + fn emit_u64(&mut self, _v: u64) { self.add_unknown_to_log(); } + fn emit_u32(&mut self, _v: u32) { self.add_unknown_to_log(); } + fn emit_u16(&mut self, _v: u16) { self.add_unknown_to_log(); } + fn emit_u8(&mut self, _v: u8) { self.add_unknown_to_log(); } + + fn emit_int(&mut self, _v: int) { self.add_unknown_to_log(); } + fn emit_i64(&mut self, _v: i64) { self.add_unknown_to_log(); } + fn emit_i32(&mut self, _v: i32) { self.add_unknown_to_log(); } + fn emit_i16(&mut self, _v: i16) { self.add_unknown_to_log(); } + fn emit_i8(&mut self, _v: i8) { self.add_unknown_to_log(); } + + fn emit_bool(&mut self, _v: bool) { self.add_unknown_to_log(); } + + fn emit_f64(&mut self, _v: f64) { self.add_unknown_to_log(); } + fn emit_f32(&mut self, _v: f32) { self.add_unknown_to_log(); } + fn emit_float(&mut self, _v: float) { self.add_unknown_to_log(); } + + fn emit_char(&mut self, _v: char) { self.add_unknown_to_log(); } + fn emit_str(&mut self, _v: &str) { self.add_unknown_to_log(); } + + fn emit_enum(&mut self, name: &str, f: &fn(&mut TestEncoder)) { + self.add_to_log(CallToEmitEnum(name.to_str())); + f(self); + } + + fn emit_enum_variant(&mut self, + name: &str, + id: uint, + cnt: uint, + f: &fn(&mut TestEncoder)) { + self.add_to_log(CallToEmitEnumVariant(name.to_str(), id, cnt)); + f(self); + } + + fn emit_enum_variant_arg(&mut self, + idx: uint, + f: &fn(&mut TestEncoder)) { + self.add_to_log(CallToEmitEnumVariantArg(idx)); + f(self); + } + + fn emit_enum_struct_variant(&mut self, + name: &str, + id: uint, + cnt: uint, + f: &fn(&mut TestEncoder)) { + self.emit_enum_variant(name, id, cnt, f) + } + + fn emit_enum_struct_variant_field(&mut self, + _name: &str, + idx: uint, + f: &fn(&mut TestEncoder)) { + self.emit_enum_variant_arg(idx, f) + } + + fn emit_struct(&mut self, + name: &str, + len: uint, + f: &fn(&mut TestEncoder)) { + self.add_to_log(CallToEmitStruct (name.to_str(),len)); + f(self); + } + fn emit_struct_field(&mut self, + name: &str, + idx: uint, + f: &fn(&mut TestEncoder)) { + self.add_to_log(CallToEmitField (name.to_str(),idx)); + f(self); + } + + fn emit_tuple(&mut self, _len: uint, f: &fn(&mut TestEncoder)) { + self.add_unknown_to_log(); + f(self); + } + fn emit_tuple_arg(&mut self, _idx: uint, f: &fn(&mut TestEncoder)) { + self.add_unknown_to_log(); + f(self); + } + + fn emit_tuple_struct(&mut self, + _name: &str, + _len: uint, + f: &fn(&mut TestEncoder)) { + self.add_unknown_to_log(); + f(self); + } + + fn emit_tuple_struct_arg(&mut self, + _idx: uint, + f: &fn(&mut TestEncoder)) { + self.add_unknown_to_log(); + f(self); + } + + fn emit_option(&mut self, f: &fn(&mut TestEncoder)) { + self.add_to_log(CallToEmitOption); + f(self); + } + fn emit_option_none(&mut self) { + self.add_to_log(CallToEmitOptionNone); + } + fn emit_option_some(&mut self, f: &fn(&mut TestEncoder)) { + self.add_to_log(CallToEmitOptionSome); + f(self); + } + + fn emit_seq(&mut self, _len: uint, f: &fn(&mut TestEncoder)) { + self.add_unknown_to_log(); + f(self); + } + fn emit_seq_elt(&mut self, _idx: uint, f: &fn(&mut TestEncoder)) { + self.add_unknown_to_log(); + f(self); + } + + fn emit_map(&mut self, _len: uint, f: &fn(&mut TestEncoder)) { + self.add_unknown_to_log(); + f(self); + } + fn emit_map_elt_key(&mut self, _idx: uint, f: &fn(&mut TestEncoder)) { + self.add_unknown_to_log(); + f(self); + } + fn emit_map_elt_val(&mut self, _idx: uint, f: &fn(&mut TestEncoder)) { + self.add_unknown_to_log(); + f(self); + } + } + + + fn to_call_log>(val: E) -> ~[call] { + let mut te = TestEncoder { + call_log: @mut ~[] + }; + val.encode(&mut te); + copy *te.call_log + } + + #[deriving(Encodable)] + enum Written { + Book(uint,uint), + Magazine(~str) + } + + #[test] + fn test_encode_enum() { + assert_eq!( + to_call_log(Book(34,44)), + ~[ + CallToEmitEnum(~"Written"), + CallToEmitEnumVariant(~"Book",0,2), + CallToEmitEnumVariantArg(0), + CallToEmitUint(34), + CallToEmitEnumVariantArg(1), + CallToEmitUint(44), + ] + ); + } + + pub struct BPos(uint); + + #[deriving(Encodable)] + pub struct HasPos { pos : BPos } + + #[test] + fn test_encode_newtype() { + assert_eq!( + to_call_log(HasPos { pos:BPos(48) }), + ~[ + CallToEmitStruct(~"HasPos",1), + CallToEmitField(~"pos",0), + CallToEmitUint(48), + ] + ); + } + + #[test] + fn test_encode_option() { + let mut v = None; + + assert_eq!( + to_call_log(v), + ~[ + CallToEmitOption, + CallToEmitOptionNone, + ] + ); + + v = Some(54u); + assert_eq!( + to_call_log(v), + ~[ + CallToEmitOption, + CallToEmitOptionSome, + CallToEmitUint(54) + ] + ); + } +} diff --git a/src/libsyntax/ext/deriving/mod.rs b/src/libsyntax/ext/deriving/mod.rs index ba1f4e3ebb208..99785d55761a3 100644 --- a/src/libsyntax/ext/deriving/mod.rs +++ b/src/libsyntax/ext/deriving/mod.rs @@ -8,8 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/// The compiler code necessary to implement the #[deriving(Eq)] and -/// #[deriving(IterBytes)] extensions. +/*! +The compiler code necessary to implement the #[deriving] extensions. + + +FIXME (#2810)--Hygiene. Search for "__" strings (in other files too). +We also assume "std" is the standard library, and "core" is the core +library. + +*/ use ast; use ast::{Ty, enum_def, expr, ident, item, Generics, meta_item, struct_def}; @@ -203,8 +210,6 @@ pub fn create_derived_impl(cx: @ext_ctxt, * * where B1, B2, ... are the bounds given by `bounds_paths`. * - * FIXME(#5090): Remove code duplication between this and the - * code in auto_encode.rs */ // Copy the lifetimes diff --git a/src/libsyntax/opt_vec.rs b/src/libsyntax/opt_vec.rs index a98e93eec8430..fb3622396c951 100644 --- a/src/libsyntax/opt_vec.rs +++ b/src/libsyntax/opt_vec.rs @@ -20,8 +20,7 @@ use core::prelude::*; use core::old_iter; use core::old_iter::BaseIter; -#[auto_encode] -#[auto_decode] +#[deriving(Encodable, Decodable)] pub enum OptVec { Empty, Vec(~[T]) diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index fe479ab81f77b..36f241b64279a 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -18,9 +18,7 @@ use core::cmp::Equiv; use core::hashmap::HashSet; use core::to_bytes; -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Encodable, Decodable, Eq)] pub enum binop { PLUS, MINUS, @@ -34,9 +32,7 @@ pub enum binop { SHR, } -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Encodable, Decodable, Eq)] pub enum Token { /* Expression-operator symbols. */ EQ, @@ -97,9 +93,7 @@ pub enum Token { EOF, } -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Encodable, Decodable, Eq)] /// For interpolation during macro expansion. pub enum nonterminal { nt_item(@ast::item), diff --git a/src/test/compile-fail/deprecated-auto-code.rs b/src/test/compile-fail/deprecated-auto-code.rs new file mode 100644 index 0000000000000..1f7cbfe980782 --- /dev/null +++ b/src/test/compile-fail/deprecated-auto-code.rs @@ -0,0 +1,15 @@ +// Copyright 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[auto_encode] //~ ERROR: `#[auto_encode]` is deprecated +#[auto_decode] //~ ERROR: `#[auto_decode]` is deprecated +struct A; + +fn main() {} \ No newline at end of file