diff options
| author | Niko Matsakis <niko@alum.mit.edu> | 2012-03-14 17:18:53 -0400 |
|---|---|---|
| committer | Niko Matsakis <niko@alum.mit.edu> | 2012-03-14 17:19:33 -0400 |
| commit | 1600be2c3b1054e2fce59778e2f85d7fa582657f (patch) | |
| tree | a3b8b7d281fbc5b4925278149952fce67c30dceb /src/rustc/syntax | |
| parent | 715d1995d7fdb28caeaa5401e1dbdbb3751bee60 (diff) | |
| download | rust-1600be2c3b1054e2fce59778e2f85d7fa582657f.tar.gz rust-1600be2c3b1054e2fce59778e2f85d7fa582657f.zip | |
fix auto_serialize for enums with type parameters
Diffstat (limited to 'src/rustc/syntax')
| -rw-r--r-- | src/rustc/syntax/ast.rs | 148 | ||||
| -rw-r--r-- | src/rustc/syntax/ext/auto_serialize.rs | 72 |
2 files changed, 186 insertions, 34 deletions
diff --git a/src/rustc/syntax/ast.rs b/src/rustc/syntax/ast.rs index 91a884ce57c..a925514b8fb 100644 --- a/src/rustc/syntax/ast.rs +++ b/src/rustc/syntax/ast.rs @@ -1,33 +1,70 @@ // The Rust abstract syntax tree. import codemap::{span, filename}; +import std::serialization::{serializer, + deserializer, + serialize_option, + deserialize_option, + serialize_uint, + deserialize_uint, + serialize_int, + deserialize_int, + serialize_i64, + deserialize_i64, + serialize_u64, + deserialize_u64, + serialize_str, + deserialize_str, + serialize_bool, + deserialize_bool}; + +fn serialize_span<S>(_s: S, _v: span) { + // FIXME-- serialize some span info +} + +fn deserialize_span<D>(_d: D) -> span { + ast_util::dummy_sp() +} +/*#[auto_serialize]*/ type spanned<T> = {node: T, span: span}; +/*#[auto_serialize]*/ type ident = str; // Functions may or may not have names. +/*#[auto_serialize]*/ type fn_ident = option<ident>; +/*#[auto_serialize]*/ type path_ = {global: bool, idents: [ident], types: [@ty]}; +/*#[auto_serialize]*/ type path = spanned<path_>; +/*#[auto_serialize]*/ type crate_num = int; + +/*#[auto_serialize]*/ type node_id = int; + +/*#[auto_serialize]*/ type def_id = {crate: crate_num, node: node_id}; const local_crate: crate_num = 0; const crate_node_id: node_id = 0; +/*#[auto_serialize]*/ enum ty_param_bound { bound_copy, bound_send, bound_iface(@ty), } +/*#[auto_serialize]*/ type ty_param = {ident: ident, id: node_id, bounds: @[ty_param_bound]}; +/*#[auto_serialize]*/ enum def { def_fn(def_id, purity), def_self(node_id), @@ -82,23 +119,30 @@ enum crate_directive_ { type crate_directive = spanned<crate_directive_>; +/*#[auto_serialize]*/ type meta_item = spanned<meta_item_>; +/*#[auto_serialize]*/ enum meta_item_ { meta_word(ident), meta_list(ident, [@meta_item]), meta_name_value(ident, lit), } +/*#[auto_serialize]*/ type blk = spanned<blk_>; +/*#[auto_serialize]*/ type blk_ = {view_items: [@view_item], stmts: [@stmt], expr: option<@expr>, id: node_id, rules: blk_check_mode}; +/*#[auto_serialize]*/ type pat = {id: node_id, node: pat_, span: span}; +/*#[auto_serialize]*/ type field_pat = {ident: ident, pat: @pat}; +/*#[auto_serialize]*/ enum pat_ { pat_wild, // A pat_ident may either be a new bound variable, @@ -118,8 +162,10 @@ enum pat_ { pat_range(@expr, @expr), } +/*#[auto_serialize]*/ enum mutability { m_mutbl, m_imm, m_const, } +/*#[auto_serialize]*/ enum proto { proto_bare, // native fn proto_any, // fn @@ -135,6 +181,7 @@ pure fn is_blockish(p: ast::proto) -> bool { } } +/*#[auto_serialize]*/ enum binop { add, subtract, @@ -157,6 +204,7 @@ enum binop { gt, } +/*#[auto_serialize]*/ enum unop { box(mutability), uniq(mutability), @@ -165,18 +213,23 @@ enum unop { // Generally, after typeck you can get the inferred value // using ty::resolved_T(...). +/*#[auto_serialize]*/ enum inferable<T> { expl(T), infer(node_id) } // "resolved" mode: the real modes. +/*#[auto_serialize]*/ enum rmode { by_ref, by_val, by_mutbl_ref, by_move, by_copy } // inferable mode. +/*#[auto_serialize]*/ type mode = inferable<rmode>; +/*#[auto_serialize]*/ type stmt = spanned<stmt_>; +/*#[auto_serialize]*/ enum stmt_ { stmt_decl(@decl, node_id), @@ -187,34 +240,48 @@ enum stmt_ { stmt_semi(@expr, node_id), } +/*#[auto_serialize]*/ enum init_op { init_assign, init_move, } +/*#[auto_serialize]*/ type initializer = {op: init_op, expr: @expr}; +/*#[auto_serialize]*/ type local_ = // FIXME: should really be a refinement on pat {is_mutbl: bool, ty: @ty, pat: @pat, init: option<initializer>, id: node_id}; +/*#[auto_serialize]*/ type local = spanned<local_>; +/*#[auto_serialize]*/ type decl = spanned<decl_>; +/*#[auto_serialize]*/ enum decl_ { decl_local([@local]), decl_item(@item), } +/*#[auto_serialize]*/ type arm = {pats: [@pat], guard: option<@expr>, body: blk}; +/*#[auto_serialize]*/ type field_ = {mutbl: mutability, ident: ident, expr: @expr}; +/*#[auto_serialize]*/ type field = spanned<field_>; +/*#[auto_serialize]*/ enum blk_check_mode { default_blk, unchecked_blk, unsafe_blk, } +/*#[auto_serialize]*/ enum expr_check_mode { claimed_expr, checked_expr, } +/*#[auto_serialize]*/ type expr = {id: node_id, node: expr_, span: span}; +/*#[auto_serialize]*/ enum alt_mode { alt_check, alt_exhaustive, } +/*#[auto_serialize]*/ enum expr_ { expr_vec([@expr], mutability), expr_rec([field], option<@expr>), @@ -270,11 +337,14 @@ enum expr_ { expr_mac(mac), } +/*#[auto_serialize]*/ type capture_item = { id: int, name: ident, // Currently, can only capture a local var. span: span }; + +/*#[auto_serialize]*/ type capture_clause = { copies: [@capture_item], moves: [@capture_item] @@ -289,13 +359,19 @@ enum blk_sort { } */ +/*#[auto_serialize]*/ type mac = spanned<mac_>; +/*#[auto_serialize]*/ type mac_arg = option<@expr>; +/*#[auto_serialize]*/ type mac_body_ = {span: span}; + +/*#[auto_serialize]*/ type mac_body = option<mac_body_>; +/*#[auto_serialize]*/ enum mac_ { mac_invoc(@path, mac_arg, mac_body), mac_embed_type(@ty), @@ -306,8 +382,10 @@ enum mac_ { mac_var(uint) } +/*#[auto_serialize]*/ type lit = spanned<lit_>; +/*#[auto_serialize]*/ enum lit_ { lit_str(str), lit_int(i64, int_ty), @@ -319,24 +397,33 @@ enum lit_ { // NB: If you change this, you'll probably want to change the corresponding // type structure in middle/ty.rs as well. +/*#[auto_serialize]*/ type mt = {ty: @ty, mutbl: mutability}; +/*#[auto_serialize]*/ type ty_field_ = {ident: ident, mt: mt}; +/*#[auto_serialize]*/ type ty_field = spanned<ty_field_>; +/*#[auto_serialize]*/ type ty_method = {ident: ident, attrs: [attribute], decl: fn_decl, tps: [ty_param], span: span}; +/*#[auto_serialize]*/ enum int_ty { ty_i, ty_char, ty_i8, ty_i16, ty_i32, ty_i64, } +/*#[auto_serialize]*/ enum uint_ty { ty_u, ty_u8, ty_u16, ty_u32, ty_u64, } +/*#[auto_serialize]*/ enum float_ty { ty_f, ty_f32, ty_f64, } +/*#[auto_serialize]*/ 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]*/ enum prim_ty { ty_int(int_ty), ty_uint(uint_ty), @@ -345,14 +432,17 @@ enum prim_ty { ty_bool, } +/*#[auto_serialize]*/ type region = {id: node_id, node: region_}; +/*#[auto_serialize]*/ enum region_ { re_inferred, re_named(ident), re_self } +/*#[auto_serialize]*/ enum ty_ { ty_nil, ty_bot, /* bottom type */ @@ -382,11 +472,19 @@ so that the typestate pass doesn't have to map a function name onto its decl. So, the constr_arg type is parameterized: it's instantiated with uint for declarations, and ident for uses. */ +/*#[auto_serialize]*/ enum constr_arg_general_<T> { carg_base, carg_ident(T), carg_lit(@lit), } +/*#[auto_serialize]*/ type fn_constr_arg = constr_arg_general_<uint>; + +/*#[auto_serialize]*/ type sp_constr_arg<T> = spanned<constr_arg_general_<T>>; + +/*#[auto_serialize]*/ type ty_constr_arg = sp_constr_arg<@path>; + +/*#[auto_serialize]*/ type constr_arg = spanned<fn_constr_arg>; // Constrained types' args are parameterized by paths, since @@ -394,22 +492,34 @@ type constr_arg = spanned<fn_constr_arg>; // The implicit root of such path, in the constraint-list for a // constrained type, is * (referring to the base record) +/*#[auto_serialize]*/ type constr_general_<ARG, ID> = {path: @path, args: [@spanned<constr_arg_general_<ARG>>], id: ID}; // In the front end, constraints have a node ID attached. // Typeck turns this to a def_id, using the output of resolve. +/*#[auto_serialize]*/ type constr_general<ARG> = spanned<constr_general_<ARG, node_id>>; + +/*#[auto_serialize]*/ type constr_ = constr_general_<uint, node_id>; + +/*#[auto_serialize]*/ type constr = spanned<constr_general_<uint, node_id>>; + +/*#[auto_serialize]*/ type ty_constr_ = constr_general_<@path, node_id>; + +/*#[auto_serialize]*/ type ty_constr = spanned<ty_constr_>; /* The parser generates ast::constrs; resolve generates a mapping from each function to a list of ty::constr_defs, corresponding to these. */ +/*#[auto_serialize]*/ type arg = {mode: mode, ty: @ty, ident: ident, id: node_id}; +/*#[auto_serialize]*/ type fn_decl = {inputs: [arg], output: @ty, @@ -417,6 +527,7 @@ type fn_decl = cf: ret_style, constraints: [@constr]}; +/*#[auto_serialize]*/ enum purity { pure_fn, // declared with "pure fn" unsafe_fn, // declared with "unsafe fn" @@ -424,44 +535,58 @@ enum purity { crust_fn, // declared with "crust fn" } +/*#[auto_serialize]*/ enum ret_style { noreturn, // functions with return type _|_ that always // raise an error or exit (i.e. never return to the caller) return_val, // everything else } +/*#[auto_serialize]*/ type method = {ident: ident, attrs: [attribute], tps: [ty_param], decl: fn_decl, body: blk, id: node_id, span: span, self_id: node_id}; +/*#[auto_serialize]*/ type _mod = {view_items: [@view_item], items: [@item]}; +/*#[auto_serialize]*/ enum native_abi { native_abi_rust_intrinsic, native_abi_cdecl, native_abi_stdcall, } +/*#[auto_serialize]*/ type native_mod = {view_items: [@view_item], items: [@native_item]}; +/*#[auto_serialize]*/ type variant_arg = {ty: @ty, id: node_id}; +/*#[auto_serialize]*/ type variant_ = {name: ident, attrs: [attribute], args: [variant_arg], id: node_id, disr_expr: option<@expr>}; +/*#[auto_serialize]*/ type variant = spanned<variant_>; - // FIXME: May want to just use path here, which would allow things like // 'import ::foo' +/*#[auto_serialize]*/ type simple_path = [ident]; +/*#[auto_serialize]*/ type path_list_ident_ = {name: ident, id: node_id}; + +/*#[auto_serialize]*/ type path_list_ident = spanned<path_list_ident_>; +/*#[auto_serialize]*/ type view_path = spanned<view_path_>; + +/*#[auto_serialize]*/ enum view_path_ { // quux = foo::bar::baz @@ -478,7 +603,10 @@ enum view_path_ { view_path_list(@simple_path, [path_list_ident], node_id) } +/*#[auto_serialize]*/ type view_item = spanned<view_item_>; + +/*#[auto_serialize]*/ enum view_item_ { view_item_use(ident, [@meta_item], node_id), view_item_import([@view_path]), @@ -486,19 +614,23 @@ enum view_item_ { } // Meta-data associated with an item +/*#[auto_serialize]*/ type attribute = spanned<attribute_>; - // 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_serialize]*/ enum attr_style { attr_outer, attr_inner, } +/*#[auto_serialize]*/ type attribute_ = {style: attr_style, value: meta_item}; +/*#[auto_serialize]*/ type item = {ident: ident, attrs: [attribute], id: node_id, node: item_, span: span}; +/*#[auto_serialize]*/ enum item_ { item_const(@ty, @expr), item_fn(fn_decl, [ty_param], blk), @@ -518,9 +650,13 @@ enum item_ { @ty /* self */, [@method]), } +/*#[auto_serialize]*/ type class_item_ = {privacy: privacy, decl: class_member}; + +/*#[auto_serialize]*/ type class_item = spanned<class_item_>; +/*#[auto_serialize]*/ enum class_member { instance_var(ident, @ty, class_mutability, node_id), class_method(@item) // FIXME: methods aren't allowed to be @@ -529,15 +665,21 @@ enum class_member { // item to separate out things with type params? } +/*#[auto_serialize]*/ enum class_mutability { class_mutable, class_immutable } +/*#[auto_serialize]*/ enum privacy { priv, pub } +/*#[auto_serialize]*/ type class_ctor = spanned<class_ctor_>; + +/*#[auto_serialize]*/ type class_ctor_ = {id: node_id, dec: fn_decl, body: blk}; +/*#[auto_serialize]*/ type native_item = {ident: ident, attrs: [attribute], @@ -545,6 +687,7 @@ type native_item = id: node_id, span: span}; +/*#[auto_serialize]*/ enum native_item_ { native_item_fn(fn_decl, [ty_param]), } @@ -552,6 +695,7 @@ enum native_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_serialize]*/ enum inlined_item { ii_item(@item), ii_method(def_id /* impl id */, @method) diff --git a/src/rustc/syntax/ext/auto_serialize.rs b/src/rustc/syntax/ext/auto_serialize.rs index 698b962eba7..44db1b1e101 100644 --- a/src/rustc/syntax/ext/auto_serialize.rs +++ b/src/rustc/syntax/ext/auto_serialize.rs @@ -130,9 +130,14 @@ impl helpers for ext_ctxt { span: span} } - fn ty_path(span: span, strs: [str]) -> @ast::ty { + fn path_tps(span: span, strs: [str], tps: [@ast::ty]) -> @ast::path { + @{node: {global: false, idents: strs, types: tps}, + span: span} + } + + fn ty_path(span: span, strs: [str], tps: [@ast::ty]) -> @ast::ty { @{id: self.next_id(), - node: ast::ty_path(self.path(span, strs), self.next_id()), + node: ast::ty_path(self.path_tps(span, strs, tps), self.next_id()), span: span} } @@ -469,27 +474,30 @@ fn ser_ty(cx: ext_ctxt, tps: ser_tps_map, } } -fn mk_ser_fn(cx: ext_ctxt, span: span, name: str, - -v_ty: @ast::ty, tps: [ast::ty_param], - f: fn(ext_ctxt, ser_tps_map, @ast::ty, +fn mk_ser_fn(cx: ext_ctxt, span: span, name: str, tps: [ast::ty_param], + f: fn(ext_ctxt, ser_tps_map, -@ast::expr, -@ast::expr) -> [@ast::stmt]) -> @ast::item { let ext_cx = cx; // required for #ast + let tp_types = vec::map(tps, {|tp| cx.ty_path(span, [tp.ident], [])}); + let v_ty = cx.ty_path(span, [name], tp_types); + let tp_inputs = vec::map(tps, {|tp| {mode: ast::expl(ast::by_ref), ty: cx.ty_fn(span, - [cx.ty_path(span, [tp.ident])], + [cx.ty_path(span, [tp.ident], [])], cx.ty_nil(span)), ident: "__s" + tp.ident, id: cx.next_id()}}); #debug["tp_inputs = %?", tp_inputs]; + let ser_inputs: [ast::arg] = [{mode: ast::expl(ast::by_ref), - ty: cx.ty_path(span, ["__S"]), + ty: cx.ty_path(span, ["__S"], []), ident: "__s", id: cx.next_id()}, {mode: ast::expl(ast::by_ref), @@ -510,10 +518,10 @@ fn mk_ser_fn(cx: ext_ctxt, span: span, name: str, }); } - let ser_bnds = @[ast::bound_iface(cx.ty_path(span, - ["std", - "serialization", - "serializer"]))]; + let ser_bnds = @[ + ast::bound_iface(cx.ty_path(span, + ["std", "serialization", "serializer"], + []))]; let ser_tps: [ast::ty_param] = [{ident: "__S", @@ -526,7 +534,7 @@ fn mk_ser_fn(cx: ext_ctxt, span: span, name: str, span: span}; let ser_blk = cx.blk(span, - f(cx, tps_map, v_ty, #ast{ __s }, #ast{ __v })); + f(cx, tps_map, #ast{ __s }, #ast{ __v })); @{ident: "serialize_" + name, attrs: [], @@ -670,19 +678,20 @@ fn deser_ty(cx: ext_ctxt, tps: deser_tps_map, } } -fn mk_deser_fn(cx: ext_ctxt, span: span, name: str, - -v_ty: @ast::ty, tps: [ast::ty_param], - f: fn(ext_ctxt, deser_tps_map, - @ast::ty, -@ast::expr) -> @ast::expr) +fn mk_deser_fn(cx: ext_ctxt, span: span, name: str, tps: [ast::ty_param], + f: fn(ext_ctxt, deser_tps_map, -@ast::expr) -> @ast::expr) -> @ast::item { let ext_cx = cx; // required for #ast + let tp_types = vec::map(tps, {|tp| cx.ty_path(span, [tp.ident], [])}); + let v_ty = cx.ty_path(span, [name], tp_types); + let tp_inputs = vec::map(tps, {|tp| {mode: ast::expl(ast::by_ref), ty: cx.ty_fn(span, [], - cx.ty_path(span, [tp.ident])), + cx.ty_path(span, [tp.ident], [])), ident: "__d" + tp.ident, id: cx.next_id()}}); @@ -690,7 +699,7 @@ fn mk_deser_fn(cx: ext_ctxt, span: span, name: str, let deser_inputs: [ast::arg] = [{mode: ast::expl(ast::by_ref), - ty: cx.ty_path(span, ["__D"]), + ty: cx.ty_path(span, ["__D"], []), ident: "__d", id: cx.next_id()}] + tp_inputs; @@ -706,10 +715,10 @@ fn mk_deser_fn(cx: ext_ctxt, span: span, name: str, }); } - let deser_bnds = @[ast::bound_iface(cx.ty_path(span, - ["std", - "serialization", - "deserializer"]))]; + let deser_bnds = @[ + ast::bound_iface(cx.ty_path(span, + ["std", "serialization", "deserializer"], + []))]; let deser_tps: [ast::ty_param] = [{ident: "__D", @@ -717,7 +726,7 @@ fn mk_deser_fn(cx: ext_ctxt, span: span, name: str, bounds: deser_bnds}] + vec::map(tps) {|tp| cx.clone_ty_param(tp) }; - let deser_blk = cx.expr_blk(f(cx, tps_map, v_ty, #ast(expr){__d})); + let deser_blk = cx.expr_blk(f(cx, tps_map, #ast(expr){__d})); @{ident: "deserialize_" + name, attrs: [], @@ -737,14 +746,14 @@ fn ty_fns(cx: ext_ctxt, name: str, ty: @ast::ty, tps: [ast::ty_param]) let span = ty.span; [ - mk_ser_fn(cx, span, name, cx.clone_ty(ty), tps, ser_ty), - mk_deser_fn(cx, span, name, cx.clone_ty(ty), tps, deser_ty) + mk_ser_fn(cx, span, name, tps, ser_ty(_, _, ty, _, _)), + mk_deser_fn(cx, span, name, tps, deser_ty(_, _, ty, _)) ] } fn ser_enum(cx: ext_ctxt, tps: ser_tps_map, e_name: str, e_span: span, variants: [ast::variant], - _ty: @ast::ty, -s: @ast::expr, -v: @ast::expr) -> [@ast::stmt] { + -s: @ast::expr, -v: @ast::expr) -> [@ast::stmt] { let ext_cx = cx; let arms = vec::from_fn(vec::len(variants)) {|vidx| let variant = variants[vidx]; @@ -793,7 +802,7 @@ fn ser_enum(cx: ext_ctxt, tps: ser_tps_map, e_name: str, fn deser_enum(cx: ext_ctxt, tps: deser_tps_map, e_name: str, e_span: span, variants: [ast::variant], - _ty: @ast::ty, -d: @ast::expr) -> @ast::expr { + -d: @ast::expr) -> @ast::expr { let ext_cx = cx; let arms: [ast::arm] = vec::from_fn(vec::len(variants)) {|vidx| let variant = variants[vidx]; @@ -831,11 +840,10 @@ fn deser_enum(cx: ext_ctxt, tps: deser_tps_map, e_name: str, fn enum_fns(cx: ext_ctxt, e_name: str, e_span: span, variants: [ast::variant], tps: [ast::ty_param]) -> [@ast::item] { - let ty = cx.ty_path(e_span, [e_name]); [ - mk_ser_fn(cx, e_span, e_name, cx.clone_ty(ty), tps, - ser_enum(_, _, e_name, e_span, variants, _, _, _)), - mk_deser_fn(cx, e_span, e_name, ty, tps, - deser_enum(_, _, e_name, e_span, variants, _, _)) + mk_ser_fn(cx, e_span, e_name, tps, + ser_enum(_, _, e_name, e_span, variants, _, _)), + mk_deser_fn(cx, e_span, e_name, tps, + deser_enum(_, _, e_name, e_span, variants, _)) ] } |
