diff options
| author | Simon BD <simon@server> | 2012-10-22 18:33:41 -0500 |
|---|---|---|
| committer | Simon BD <simon@server> | 2012-10-22 18:33:41 -0500 |
| commit | cc0f2c6bb26ba38d3487a396fa8625e938af6820 (patch) | |
| tree | 6c2063df35144c5477b0adc9e49933d71224dc2a /src/libsyntax/ext | |
| parent | 9aec7a3e85c5b07923eab05d3ebe9d031bf258f3 (diff) | |
| parent | 9ee5fff4f16cfc3390bd69abbb46b0a68521667c (diff) | |
| download | rust-cc0f2c6bb26ba38d3487a396fa8625e938af6820.tar.gz rust-cc0f2c6bb26ba38d3487a396fa8625e938af6820.zip | |
Merge remote-tracking branch 'original/incoming' into incoming
Diffstat (limited to 'src/libsyntax/ext')
| -rw-r--r-- | src/libsyntax/ext/auto_serialize.rs | 1731 | ||||
| -rw-r--r-- | src/libsyntax/ext/auto_serialize2.rs | 1025 | ||||
| -rw-r--r-- | src/libsyntax/ext/base.rs | 27 | ||||
| -rw-r--r-- | src/libsyntax/ext/env.rs | 4 | ||||
| -rw-r--r-- | src/libsyntax/ext/fmt.rs | 16 | ||||
| -rw-r--r-- | src/libsyntax/ext/pipes.rs | 4 | ||||
| -rw-r--r-- | src/libsyntax/ext/pipes/ast_builder.rs | 60 | ||||
| -rw-r--r-- | src/libsyntax/ext/pipes/check.rs | 4 | ||||
| -rw-r--r-- | src/libsyntax/ext/pipes/parse_proto.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax/ext/pipes/pipec.rs | 8 | ||||
| -rw-r--r-- | src/libsyntax/ext/pipes/proto.rs | 12 | ||||
| -rw-r--r-- | src/libsyntax/ext/qquote.rs | 22 | ||||
| -rw-r--r-- | src/libsyntax/ext/simplext.rs | 4 | ||||
| -rw-r--r-- | src/libsyntax/ext/trace_macros.rs | 6 | ||||
| -rw-r--r-- | src/libsyntax/ext/tt/macro_parser.rs | 14 | ||||
| -rw-r--r-- | src/libsyntax/ext/tt/macro_rules.rs | 6 | ||||
| -rw-r--r-- | src/libsyntax/ext/tt/transcribe.rs | 9 |
17 files changed, 1049 insertions, 1905 deletions
diff --git a/src/libsyntax/ext/auto_serialize.rs b/src/libsyntax/ext/auto_serialize.rs index 64915c60742..47e61c26f38 100644 --- a/src/libsyntax/ext/auto_serialize.rs +++ b/src/libsyntax/ext/auto_serialize.rs @@ -1,62 +1,70 @@ /* -The compiler code necessary to implement the #[auto_serialize] -extension. The idea here is that type-defining items may be tagged -with #[auto_serialize], which will cause us to generate a little -companion module with the same name as the item. +The compiler code necessary to implement the #[auto_serialize] and +#[auto_deserialize] extension. The idea here is that type-defining items may +be tagged with #[auto_serialize] and #[auto_deserialize], which will cause +us to generate a little companion module with the same name as the item. For example, a type like: - type node_id = uint; + #[auto_serialize] + #[auto_deserialize] + struct Node {id: uint} -would generate two functions like: +would generate two implementations like: - fn serialize_node_id<S: serializer>(s: S, v: node_id) { - s.emit_uint(v); + impl<S: Serializer> node_id: Serializable<S> { + fn serialize(s: &S) { + do s.emit_struct("Node") { + s.emit_field("id", 0, || s.emit_uint(self)) + } + } } - fn deserialize_node_id<D: deserializer>(d: D) -> node_id { - d.read_uint() + + impl<D: Deserializer> node_id: Deserializable { + static fn deserialize(d: &D) -> Node { + do d.read_struct("Node") { + Node { + id: d.read_field(~"x", 0, || deserialize(d)) + } + } + } } Other interesting scenarios are whe the item has type parameters or references other non-built-in types. A type definition like: + #[auto_serialize] + #[auto_deserialize] type spanned<T> = {node: T, span: span}; would yield functions like: - fn serialize_spanned<S: serializer,T>(s: S, v: spanned<T>, t: fn(T)) { - s.emit_rec(2u) {|| - s.emit_rec_field("node", 0u) {|| - t(s.node); - }; - s.emit_rec_field("span", 1u) {|| - serialize_span(s, s.span); - }; - } - } - fn deserialize_spanned<D: deserializer>(d: D, t: fn() -> T) -> node_id { - d.read_rec(2u) {|| - {node: d.read_rec_field("node", 0u, t), - span: d.read_rec_field("span", 1u) {||deserialize_span(d)}} - } + impl< + S: Serializer, + T: Serializable<S> + > spanned<T>: Serializable<S> { + fn serialize<S: Serializer>(s: &S) { + do s.emit_rec { + s.emit_field("node", 0, || self.node.serialize(s)); + s.emit_field("span", 1, || self.span.serialize(s)); + } + } } -In general, the code to serialize an instance `v` of a non-built-in -type a::b::c<T0,...,Tn> looks like: - - a::b::serialize_c(s, {|v| c_T0}, ..., {|v| c_Tn}, v) - -where `c_Ti` is the code to serialize an instance `v` of the type -`Ti`. - -Similarly, the code to deserialize an instance of a non-built-in type -`a::b::c<T0,...,Tn>` using the deserializer `d` looks like: - - a::b::deserialize_c(d, {|| c_T0}, ..., {|| c_Tn}) - -where `c_Ti` is the code to deserialize an instance of `Ti` using the -deserializer `d`. + impl< + D: Deserializer, + T: Deserializable<D> + > spanned<T>: Deserializable<D> { + static fn deserialize(d: &D) -> spanned<T> { + do d.read_rec { + { + node: d.read_field(~"node", 0, || deserialize(d)), + span: d.read_field(~"span", 1, || deserialize(d)), + } + } + } + } FIXME (#2810)--Hygiene. Search for "__" strings. We also assume "std" is the standard library. @@ -69,137 +77,167 @@ into the tree. This is intended to prevent us from inserting the same node twice. */ + use base::*; use codemap::span; use std::map; use std::map::HashMap; -export expand; +export expand_auto_serialize; +export expand_auto_deserialize; // Transitional reexports so qquote can find the paths it is looking for mod syntax { - #[legacy_exports]; pub use ext; pub use parse; } -type ser_tps_map = map::HashMap<ast::ident, fn@(@ast::expr) -> ~[@ast::stmt]>; -type deser_tps_map = map::HashMap<ast::ident, fn@() -> @ast::expr>; - -fn expand(cx: ext_ctxt, - span: span, - _mitem: ast::meta_item, - in_items: ~[@ast::item]) -> ~[@ast::item] { - fn not_auto_serialize(a: &ast::attribute) -> bool { - attr::get_attr_name(*a) != ~"auto_serialize" +fn expand_auto_serialize( + cx: ext_ctxt, + span: span, + _mitem: ast::meta_item, + in_items: ~[@ast::item] +) -> ~[@ast::item] { + fn is_auto_serialize(a: &ast::attribute) -> bool { + attr::get_attr_name(*a) == ~"auto_serialize" } fn filter_attrs(item: @ast::item) -> @ast::item { - @{attrs: vec::filter(item.attrs, not_auto_serialize), + @{attrs: vec::filter(item.attrs, |a| !is_auto_serialize(a)), .. *item} } - do vec::flat_map(in_items) |in_item| { - match in_item.node { - ast::item_ty(ty, tps) => { - vec::append(~[filter_attrs(*in_item)], - ty_fns(cx, in_item.ident, ty, tps)) - } - - ast::item_enum(enum_definition, tps) => { - vec::append(~[filter_attrs(*in_item)], - enum_fns(cx, in_item.ident, - in_item.span, enum_definition.variants, tps)) - } - - _ => { - cx.span_err(span, ~"#[auto_serialize] can only be \ - applied to type and enum \ - definitions"); - ~[*in_item] - } + do vec::flat_map(in_items) |item| { + if item.attrs.any(is_auto_serialize) { + match item.node { + ast::item_ty(@{node: ast::ty_rec(fields), _}, tps) => { + let ser_impl = mk_rec_ser_impl( + cx, + item.span, + item.ident, + fields, + tps + ); + + ~[filter_attrs(*item), ser_impl] + }, + ast::item_class(@{ fields, _}, tps) => { + let ser_impl = mk_struct_ser_impl( + cx, + item.span, + item.ident, + fields, + tps + ); + + ~[filter_attrs(*item), ser_impl] + }, + ast::item_enum(enum_def, tps) => { + let ser_impl = mk_enum_ser_impl( + cx, + item.span, + item.ident, + enum_def, + tps + ); + + ~[filter_attrs(*item), ser_impl] + }, + _ => { + cx.span_err(span, ~"#[auto_serialize] can only be \ + applied to structs, record types, \ + and enum definitions"); + ~[*item] + } + } + } else { + ~[*item] } } } -trait ext_ctxt_helpers { - fn helper_path(base_path: @ast::path, helper_name: ~str) -> @ast::path; - fn path(span: span, strs: ~[ast::ident]) -> @ast::path; - fn path_tps(span: span, strs: ~[ast::ident], - tps: ~[@ast::ty]) -> @ast::path; - fn ty_path(span: span, strs: ~[ast::ident], tps: ~[@ast::ty]) -> @ast::ty; - fn ty_fn(span: span, - -input_tys: ~[@ast::ty], - -output: @ast::ty) -> @ast::ty; - fn ty_nil(span: span) -> @ast::ty; - fn expr(span: span, node: ast::expr_) -> @ast::expr; - fn var_ref(span: span, name: ast::ident) -> @ast::expr; - fn blk(span: span, stmts: ~[@ast::stmt]) -> ast::blk; - fn expr_blk(expr: @ast::expr) -> ast::blk; - fn binder_pat(span: span, nm: ast::ident) -> @ast::pat; - fn stmt(expr: @ast::expr) -> @ast::stmt; - fn alt_stmt(arms: ~[ast::arm], span: span, -v: @ast::expr) -> @ast::stmt; - fn lit_str(span: span, s: @~str) -> @ast::expr; - fn lit_uint(span: span, i: uint) -> @ast::expr; - fn lambda(blk: ast::blk) -> @ast::expr; - fn clone_folder() -> fold::ast_fold; - fn clone(v: @ast::expr) -> @ast::expr; - fn clone_ty(v: @ast::ty) -> @ast::ty; - fn clone_ty_param(v: ast::ty_param) -> ast::ty_param; - fn at(span: span, expr: @ast::expr) -> @ast::expr; -} - -impl ext_ctxt: ext_ctxt_helpers { - fn helper_path(base_path: @ast::path, - helper_name: ~str) -> @ast::path { - let head = vec::init(base_path.idents); - let tail = vec::last(base_path.idents); - self.path(base_path.span, - vec::append(head, - ~[self.parse_sess().interner. - intern(@(helper_name + ~"_" + - *self.parse_sess().interner.get( - tail)))])) +fn expand_auto_deserialize( + cx: ext_ctxt, + span: span, + _mitem: ast::meta_item, + in_items: ~[@ast::item] +) -> ~[@ast::item] { + fn is_auto_deserialize(a: &ast::attribute) -> bool { + attr::get_attr_name(*a) == ~"auto_deserialize" } - fn path(span: span, strs: ~[ast::ident]) -> @ast::path { - @{span: span, global: false, idents: strs, rp: None, types: ~[]} - } - - fn path_tps(span: span, strs: ~[ast::ident], - tps: ~[@ast::ty]) -> @ast::path { - @{span: span, global: false, idents: strs, rp: None, types: tps} + fn filter_attrs(item: @ast::item) -> @ast::item { + @{attrs: vec::filter(item.attrs, |a| !is_auto_deserialize(a)), + .. *item} } - fn ty_path(span: span, strs: ~[ast::ident], - tps: ~[@ast::ty]) -> @ast::ty { - @{id: self.next_id(), - node: ast::ty_path(self.path_tps(span, strs, tps), self.next_id()), - span: span} + do vec::flat_map(in_items) |item| { + if item.attrs.any(is_auto_deserialize) { + match item.node { + ast::item_ty(@{node: ast::ty_rec(fields), _}, tps) => { + let deser_impl = mk_rec_deser_impl( + cx, + item.span, + item.ident, + fields, + tps + ); + + ~[filter_attrs(*item), deser_impl] + }, + ast::item_class(@{ fields, _}, tps) => { + let deser_impl = mk_struct_deser_impl( + cx, + item.span, + item.ident, + fields, + tps + ); + + ~[filter_attrs(*item), deser_impl] + }, + ast::item_enum(enum_def, tps) => { + let deser_impl = mk_enum_deser_impl( + cx, + item.span, + item.ident, + enum_def, + tps + ); + + ~[filter_attrs(*item), deser_impl] + }, + _ => { + cx.span_err(span, ~"#[auto_deserialize] can only be \ + applied to structs, record types, \ + and enum definitions"); + ~[*item] + } + } + } else { + ~[*item] + } } +} - fn ty_fn(span: span, - -input_tys: ~[@ast::ty], - -output: @ast::ty) -> @ast::ty { - let args = do vec::map(input_tys) |ty| { - {mode: ast::expl(ast::by_ref), - ty: *ty, - ident: parse::token::special_idents::invalid, - id: self.next_id()} - }; - - @{id: self.next_id(), - node: ast::ty_fn(ast::proto_block, - ast::impure_fn, - @~[], - {inputs: args, - output: output, - cf: ast::return_val}), - span: span} - } +priv impl ext_ctxt { + fn bind_path( + span: span, + ident: ast::ident, + path: @ast::path, + bounds: @~[ast::ty_param_bound] + ) -> ast::ty_param { + let bound = ast::ty_param_bound(@{ + id: self.next_id(), + node: ast::ty_path(path, self.next_id()), + span: span, + }); - fn ty_nil(span: span) -> @ast::ty { - @{id: self.next_id(), node: ast::ty_nil, span: span} + { + ident: ident, + id: self.next_id(), + bounds: @vec::append(~[bound], *bounds) + } } fn expr(span: span, node: ast::expr_) -> @ast::expr { @@ -207,26 +245,20 @@ impl ext_ctxt: ext_ctxt_helpers { node: node, span: span} } - fn var_ref(span: span, name: ast::ident) -> @ast::expr { - self.expr(span, ast::expr_path(self.path(span, ~[name]))) + fn path(span: span, strs: ~[ast::ident]) -> @ast::path { + @{span: span, global: false, idents: strs, rp: None, types: ~[]} } - fn blk(span: span, stmts: ~[@ast::stmt]) -> ast::blk { - {node: {view_items: ~[], - stmts: stmts, - expr: None, - id: self.next_id(), - rules: ast::default_blk}, - span: span} + fn path_tps(span: span, strs: ~[ast::ident], + tps: ~[@ast::Ty]) -> @ast::path { + @{span: span, global: false, idents: strs, rp: None, types: tps} } - fn expr_blk(expr: @ast::expr) -> ast::blk { - {node: {view_items: ~[], - stmts: ~[], - expr: Some(expr), - id: self.next_id(), - rules: ast::default_blk}, - span: expr.span} + fn ty_path(span: span, strs: ~[ast::ident], + tps: ~[@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(span: span, nm: ast::ident) -> @ast::pat { @@ -244,14 +276,6 @@ impl ext_ctxt: ext_ctxt_helpers { span: expr.span} } - fn alt_stmt(arms: ~[ast::arm], - span: span, -v: @ast::expr) -> @ast::stmt { - self.stmt( - self.expr( - span, - ast::expr_match(v, arms))) - } - fn lit_str(span: span, s: @~str) -> @ast::expr { self.expr( span, @@ -278,686 +302,835 @@ impl ext_ctxt: ext_ctxt_helpers { #ast{ || $(blk_e) } } - fn clone_folder() -> fold::ast_fold { - fold::make_fold(@{ - new_id: |_id| self.next_id(), - .. *fold::default_ast_fold() - }) + fn blk(span: span, stmts: ~[@ast::stmt]) -> ast::blk { + {node: {view_items: ~[], + stmts: stmts, + expr: None, + id: self.next_id(), + rules: ast::default_blk}, + span: span} } - fn clone(v: @ast::expr) -> @ast::expr { - let fld = self.clone_folder(); - fld.fold_expr(v) + fn expr_blk(expr: @ast::expr) -> ast::blk { + {node: {view_items: ~[], + stmts: ~[], + expr: Some(expr), + id: self.next_id(), + rules: ast::default_blk}, + span: expr.span} } - fn clone_ty(v: @ast::ty) -> @ast::ty { - let fld = self.clone_folder(); - fld.fold_ty(v) + fn expr_path(span: span, strs: ~[ast::ident]) -> @ast::expr { + self.expr(span, ast::expr_path(self.path(span, strs))) } - fn clone_ty_param(v: ast::ty_param) -> ast::ty_param { - let fld = self.clone_folder(); - fold::fold_ty_param(v, fld) + fn expr_var(span: span, var: ~str) -> @ast::expr { + self.expr_path(span, ~[self.ident_of(var)]) } - fn at(span: span, expr: @ast::expr) -> @ast::expr { - fn repl_sp(old_span: span, repl_span: span, with_span: span) -> span { - if old_span == repl_span { - with_span - } else { - old_span - } - } - - let fld = fold::make_fold(@{ - new_span: |a| repl_sp(a, ast_util::dummy_sp(), span), - .. *fold::default_ast_fold() - }); + fn expr_field( + span: span, + expr: @ast::expr, + ident: ast::ident + ) -> @ast::expr { + self.expr(span, ast::expr_field(expr, ident, ~[])) + } - fld.fold_expr(expr) + fn expr_call( + span: span, + expr: @ast::expr, + args: ~[@ast::expr] + ) -> @ast::expr { + self.expr(span, ast::expr_call(expr, args, false)) } -} -fn ser_path(cx: ext_ctxt, tps: ser_tps_map, path: @ast::path, - -s: @ast::expr, -v: @ast::expr) - -> ~[@ast::stmt] { - let ext_cx = cx; // required for #ast{} - - // We want to take a path like a::b::c<...> and generate a call - // like a::b::c::serialize(s, ...), as described above. - - let callee = - cx.expr( - path.span, - ast::expr_path( - cx.helper_path(path, ~"serialize"))); - - let ty_args = do vec::map(path.types) |ty| { - let sv_stmts = ser_ty(cx, tps, *ty, cx.clone(s), #ast{ __v }); - let sv = cx.expr(path.span, - ast::expr_block(cx.blk(path.span, sv_stmts))); - cx.at(ty.span, #ast{ |__v| $(sv) }) - }; + fn lambda_expr(expr: @ast::expr) -> @ast::expr { + self.lambda(self.expr_blk(expr)) + } - ~[cx.stmt( - cx.expr( - path.span, - ast::expr_call(callee, vec::append(~[s, v], ty_args), false)))] + fn lambda_stmts(span: span, stmts: ~[@ast::stmt]) -> @ast::expr { + self.lambda(self.blk(span, stmts)) + } } -fn ser_variant(cx: ext_ctxt, - tps: ser_tps_map, - tys: ~[@ast::ty], - span: span, - -s: @ast::expr, - pfn: fn(~[@ast::pat]) -> ast::pat_, - bodyfn: fn(-v: @ast::expr, ast::blk) -> @ast::expr, - argfn: fn(-v: @ast::expr, uint, ast::blk) -> @ast::expr) - -> ast::arm { - let vnames = do vec::from_fn(vec::len(tys)) |i| { - cx.parse_sess().interner.intern(@fmt!("__v%u", i)) - }; - let pats = do vec::from_fn(vec::len(tys)) |i| { - cx.binder_pat(tys[i].span, vnames[i]) - }; - let pat: @ast::pat = @{id: cx.next_id(), node: pfn(pats), span: span}; - let stmts = do vec::from_fn(vec::len(tys)) |i| { - let v = cx.var_ref(span, vnames[i]); - let arg_blk = - cx.blk( - span, - ser_ty(cx, tps, tys[i], cx.clone(s), move v)); - cx.stmt(argfn(cx.clone(s), i, arg_blk)) - }; - - let body_blk = cx.blk(span, stmts); - let body = cx.blk(span, ~[cx.stmt(bodyfn(move s, body_blk))]); +fn mk_impl( + cx: ext_ctxt, + span: span, + ident: ast::ident, + ty_param: ast::ty_param, + path: @ast::path, + tps: ~[ast::ty_param], + f: fn(@ast::Ty) -> @ast::method +) -> @ast::item { + // All the type parameters need to bound to the trait. + let mut trait_tps = vec::append( + ~[ty_param], + do tps.map |tp| { + let t_bound = ast::ty_param_bound(@{ + id: cx.next_id(), + node: ast::ty_path(path, cx.next_id()), + span: span, + }); - {pats: ~[pat], guard: None, body: body} + { + ident: tp.ident, + id: cx.next_id(), + bounds: @vec::append(~[t_bound], *tp.bounds) + } + } + ); + + let opt_trait = Some(@{ + path: path, + ref_id: cx.next_id(), + impl_id: cx.next_id(), + }); + + let ty = cx.ty_path( + span, + ~[ident], + tps.map(|tp| cx.ty_path(span, ~[tp.ident], ~[])) + ); + + @{ + // This is a new-style impl declaration. + // XXX: clownshoes + ident: ast::token::special_idents::clownshoes_extensions, + attrs: ~[], + id: cx.next_id(), + node: ast::item_impl(trait_tps, opt_trait, ty, ~[f(ty)]), + vis: ast::public, + span: span, + } } -fn ser_lambda(cx: ext_ctxt, tps: ser_tps_map, ty: @ast::ty, - -s: @ast::expr, -v: @ast::expr) -> @ast::expr { - cx.lambda(cx.blk(ty.span, ser_ty(cx, tps, ty, move s, move v))) +fn mk_ser_impl( + cx: ext_ctxt, + span: span, + ident: ast::ident, + tps: ~[ast::ty_param], + body: @ast::expr +) -> @ast::item { + // Make a path to the std::serialization::Serializable typaram. + let ty_param = cx.bind_path( + span, + cx.ident_of(~"__S"), + cx.path( + span, + ~[ + cx.ident_of(~"std"), + cx.ident_of(~"serialization"), + cx.ident_of(~"Serializer"), + ] + ), + @~[] + ); + + // Make a path to the std::serialization::Serializable trait. + let path = cx.path_tps( + span, + ~[ + cx.ident_of(~"std"), + cx.ident_of(~"serialization"), + cx.ident_of(~"Serializable"), + ], + ~[cx.ty_path(span, ~[cx.ident_of(~"__S")], ~[])] + ); + + mk_impl( + cx, + span, + ident, + ty_param, + path, + tps, + |_ty| mk_ser_method(cx, span, cx.expr_blk(body)) + ) } -fn is_vec_or_str(ty: @ast::ty) -> bool { - match ty.node { - ast::ty_vec(_) => true, - // This may be wrong if the user has shadowed (!) str - ast::ty_path(@{span: _, global: _, idents: ids, - rp: None, types: _}, _) - if ids == ~[parse::token::special_idents::str] => true, - _ => false - } +fn mk_deser_impl( + cx: ext_ctxt, + span: span, + ident: ast::ident, + tps: ~[ast::ty_param], + body: @ast::expr +) -> @ast::item { + // Make a path to the std::serialization::Deserializable typaram. + let ty_param = cx.bind_path( + span, + cx.ident_of(~"__D"), + cx.path( + span, + ~[ + cx.ident_of(~"std"), + cx.ident_of(~"serialization"), + cx.ident_of(~"Deserializer"), + ] + ), + @~[] + ); + + // Make a path to the std::serialization::Deserializable trait. + let path = cx.path_tps( + span, + ~[ + cx.ident_of(~"std"), + cx.ident_of(~"serialization"), + cx.ident_of(~"Deserializable"), + ], + ~[cx.ty_path(span, ~[cx.ident_of(~"__D")], ~[])] + ); + + mk_impl( + cx, + span, + ident, + ty_param, + path, + tps, + |ty| mk_deser_method(cx, span, ty, cx.expr_blk(body)) + ) } -fn ser_ty(cx: ext_ctxt, tps: ser_tps_map, - ty: @ast::ty, -s: @ast::expr, -v: @ast::expr) - -> ~[@ast::stmt] { - - let ext_cx = cx; // required for #ast{} - - match ty.node { - ast::ty_nil => { - ~[#ast[stmt]{$(s).emit_nil()}] - } - - ast::ty_bot => { - cx.span_err( - ty.span, fmt!("Cannot serialize bottom type")); - ~[] - } - - ast::ty_box(mt) => { - let l = ser_lambda(cx, tps, mt.ty, cx.clone(s), #ast{ *$(v) }); - ~[#ast[stmt]{$(s).emit_box($(l));}] - } - - // For unique evecs/estrs, just pass through to underlying vec or str - ast::ty_uniq(mt) if is_vec_or_str(mt.ty) => { - ser_ty(cx, tps, mt.ty, move s, move v) - } - - ast::ty_uniq(mt) => { - let l = ser_lambda(cx, tps, mt.ty, cx.clone(s), #ast{ *$(v) }); - ~[#ast[stmt]{$(s).emit_uniq($(l));}] - } - - ast::ty_ptr(_) | ast::ty_rptr(_, _) => { - cx.span_err(ty.span, ~"cannot serialize pointer types"); - ~[] - } - - ast::ty_rec(flds) => { - let fld_stmts = do vec::from_fn(vec::len(flds)) |fidx| { - let fld = flds[fidx]; - let vf = cx.expr(fld.span, - ast::expr_field(cx.clone(v), - fld.node.ident, - ~[])); - let s = cx.clone(s); - let f = cx.lit_str(fld.span, cx.parse_sess().interner.get( - fld.node.ident)); - let i = cx.lit_uint(fld.span, fidx); - let l = ser_lambda(cx, tps, fld.node.mt.ty, cx.clone(s), move vf); - #ast[stmt]{$(s).emit_rec_field($(f), $(i), $(l));} - }; - let fld_lambda = cx.lambda(cx.blk(ty.span, fld_stmts)); - ~[#ast[stmt]{$(s).emit_rec($(fld_lambda));}] - } - - ast::ty_fn(*) => { - cx.span_err(ty.span, ~"cannot serialize function types"); - ~[] - } - - ast::ty_tup(tys) => { - // Generate code like - // - // match v { - // (v1, v2, v3) { - // .. serialize v1, v2, v3 .. - // } - // }; - - let arms = ~[ - ser_variant( - - cx, tps, tys, ty.span, move s, - - // Generate pattern (v1, v2, v3) - |pats| ast::pat_tup(pats), - - // Generate body s.emit_tup(3, {|| blk }) - |-s, blk| { - let sz = cx.lit_uint(ty.span, vec::len(tys)); - let body = cx.lambda(blk); - #ast{ $(s).emit_tup($(sz), $(body)) } - }, - - // Generate s.emit_tup_elt(i, {|| blk }) - |-s, i, blk| { - let idx = cx.lit_uint(ty.span, i); - let body = cx.lambda(blk); - #ast{ $(s).emit_tup_elt($(idx), $(body)) } - }) - ]; - ~[cx.alt_stmt(arms, ty.span, move v)] - } - - ast::ty_path(path, _) => { - if path.idents.len() == 1 && path.types.is_empty() { - let ident = path.idents[0]; - - match tps.find(ident) { - Some(f) => f(v), - None => ser_path(cx, tps, path, move s, move v) +fn mk_ser_method( + cx: ext_ctxt, + span: span, + ser_body: ast::blk +) -> @ast::method { + let ty_s = @{ + id: cx.next_id(), + node: ast::ty_rptr( + @{ + id: cx.next_id(), + node: ast::re_anon, + }, + { + ty: cx.ty_path(span, ~[cx.ident_of(~"__S")], ~[]), + mutbl: ast::m_imm } - } else { - ser_path(cx, tps, path, move s, move v) - } - } + ), + span: span, + }; - ast::ty_mac(_) => { - cx.span_err(ty.span, ~"cannot serialize macro types"); - ~[] - } + let ser_inputs = ~[{ + mode: ast::infer(cx.next_id()), + ty: ty_s, + ident: cx.ident_of(~"__s"), + id: cx.next_id(), + }]; + + let ser_output = @{ + id: cx.next_id(), + node: ast::ty_nil, + span: span, + }; - ast::ty_infer => { - cx.span_err(ty.span, ~"cannot serialize inferred types"); - ~[] - } + let ser_decl = { + inputs: ser_inputs, + output: ser_output, + cf: ast::return_val, + }; - ast::ty_vec(mt) => { - let ser_e = - cx.expr( - ty.span, - ast::expr_block( - cx.blk( - ty.span, - ser_ty( - cx, tps, mt.ty, - cx.clone(s), - cx.at(ty.span, #ast{ __e }))))); - - ~[#ast[stmt]{ - std::serialization::emit_from_vec($(s), $(v), |__e| $(ser_e)) - }] - } - - ast::ty_fixed_length(_, _) => { - cx.span_unimpl(ty.span, ~"serialization for fixed length types"); - } + @{ + ident: cx.ident_of(~"serialize"), + attrs: ~[], + tps: ~[], + self_ty: { node: ast::sty_region(ast::m_imm), span: span }, + purity: ast::impure_fn, + decl: ser_decl, + body: ser_body, + id: cx.next_id(), + span: span, + self_id: cx.next_id(), + vis: ast::public, } } -fn mk_ser_fn(cx: ext_ctxt, span: span, name: ast::ident, - tps: ~[ast::ty_param], - f: fn(ext_ctxt, ser_tps_map, - -v: @ast::expr, -v: @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_nil(span)), - ident: cx.ident_of(~"__s" + cx.str_of(tp.ident)), - id: cx.next_id()}); - - debug!("tp_inputs = %?", tp_inputs); - - - let ser_inputs: ~[ast::arg] = - vec::append(~[{mode: ast::expl(ast::by_ref), - ty: cx.ty_path(span, ~[cx.ident_of(~"__S")], ~[]), - ident: cx.ident_of(~"__s"), - id: cx.next_id()}, - {mode: ast::expl(ast::by_ref), - ty: v_ty, - ident: cx.ident_of(~"__v"), - id: cx.next_id()}], - tp_inputs); - - let tps_map = map::HashMap(); - for vec::each2(tps, tp_inputs) |tp, arg| { - let arg_ident = arg.ident; - tps_map.insert( - tp.ident, - fn@(v: @ast::expr) -> ~[@ast::stmt] { - let f = cx.var_ref(span, arg_ident); - debug!("serializing type arg %s", cx.str_of(arg_ident)); - ~[#ast[stmt]{$(f)($(v));}] - }); - } +fn mk_deser_method( + cx: ext_ctxt, + span: span, + ty: @ast::Ty, + deser_body: ast::blk +) -> @ast::method { + let ty_d = @{ + id: cx.next_id(), + node: ast::ty_rptr( + @{ + id: cx.next_id(), + node: ast::re_anon, + }, + { + ty: cx.ty_path(span, ~[cx.ident_of(~"__D")], ~[]), + mutbl: ast::m_imm + } + ), + span: span, + }; - let ser_bnds = @~[ - ast::bound_trait(cx.ty_path(span, - ~[cx.ident_of(~"std"), - cx.ident_of(~"serialization"), - cx.ident_of(~"Serializer")], - ~[]))]; - - let ser_tps: ~[ast::ty_param] = - vec::append(~[{ident: cx.ident_of(~"__S"), - id: cx.next_id(), - bounds: ser_bnds}], - vec::map(tps, |tp| cx.clone_ty_param(*tp))); - - let ser_output: @ast::ty = @{id: cx.next_id(), - node: ast::ty_nil, - span: span}; - - let ser_blk = cx.blk(span, - f(cx, tps_map, #ast{ __s }, #ast{ __v })); - - @{ident: cx.ident_of(~"serialize_" + cx.str_of(name)), - attrs: ~[], - id: cx.next_id(), - node: ast::item_fn({inputs: ser_inputs, - output: ser_output, - cf: ast::return_val}, - ast::impure_fn, - ser_tps, - ser_blk), - vis: ast::public, - span: span} + let deser_inputs = ~[{ + mode: ast::infer(cx.next_id()), + ty: ty_d, + ident: cx.ident_of(~"__d"), + id: cx.next_id(), + }]; + + let deser_decl = { + inputs: deser_inputs, + output: ty, + cf: ast::return_val, + }; + + @{ + ident: cx.ident_of(~"deserialize"), + attrs: ~[], + tps: ~[], + self_ty: { node: ast::sty_static, span: span }, + purity: ast::impure_fn, + decl: deser_decl, + body: deser_body, + id: cx.next_id(), + span: span, + self_id: cx.next_id(), + vis: ast::public, + } } -// ______________________________________________________________________ +fn mk_rec_ser_impl( + cx: ext_ctxt, + span: span, + ident: ast::ident, + fields: ~[ast::ty_field], + tps: ~[ast::ty_param] +) -> @ast::item { + let fields = mk_ser_fields(cx, span, mk_rec_fields(fields)); + + // ast for `__s.emit_rec(|| $(fields))` + let body = cx.expr_call( + span, + cx.expr_field( + span, + cx.expr_var(span, ~"__s"), + cx.ident_of(~"emit_rec") + ), + ~[cx.lambda_stmts(span, fields)] + ); -fn deser_path(cx: ext_ctxt, tps: deser_tps_map, path: @ast::path, - -d: @ast::expr) -> @ast::expr { - // We want to take a path like a::b::c<...> and generate a call - // like a::b::c::deserialize(d, ...), as described above. + mk_ser_impl(cx, span, ident, tps, body) +} - let callee = - cx.expr( - path.span, - ast::expr_path( - cx.helper_path(path, ~"deserialize"))); +fn mk_rec_deser_impl( + cx: ext_ctxt, + span: span, + ident: ast::ident, + fields: ~[ast::ty_field], + tps: ~[ast::ty_param] +) -> @ast::item { + let fields = mk_deser_fields(cx, span, mk_rec_fields(fields)); + + // ast for `read_rec(|| $(fields))` + let body = cx.expr_call( + span, + cx.expr_field( + span, + cx.expr_var(span, ~"__d"), + cx.ident_of(~"read_rec") + ), + ~[ + cx.lambda_expr( + cx.expr( + span, + ast::expr_rec(fields, None) + ) + ) + ] + ); - let ty_args = do vec::map(path.types) |ty| { - let dv_expr = deser_ty(cx, tps, *ty, cx.clone(d)); - cx.lambda(cx.expr_blk(dv_expr)) - }; + mk_deser_impl(cx, span, ident, tps, body) +} - cx.expr(path.span, ast::expr_call(callee, vec::append(~[d], ty_args), - false)) +fn mk_struct_ser_impl( + cx: ext_ctxt, + span: span, + ident: ast::ident, + fields: ~[@ast::struct_field], + tps: ~[ast::ty_param] +) -> @ast::item { + let fields = mk_ser_fields(cx, span, mk_struct_fields(fields)); + + // ast for `__s.emit_struct($(name), || $(fields))` + let ser_body = cx.expr_call( + span, + cx.expr_field( + span, + cx.expr_var(span, ~"__s"), + cx.ident_of(~"emit_struct") + ), + ~[ + cx.lit_str(span, @cx.str_of(ident)), + cx.lambda_stmts(span, fields), + ] + ); + + mk_ser_impl(cx, span, ident, tps, ser_body) } -fn deser_lambda(cx: ext_ctxt, tps: deser_tps_map, ty: @ast::ty, - -d: @ast::expr) -> @ast::expr { - cx.lambda(cx.expr_blk(deser_ty(cx, tps, ty, move d))) +fn mk_struct_deser_impl( + cx: ext_ctxt, + span: span, + ident: ast::ident, + fields: ~[@ast::struct_field], + tps: ~[ast::ty_param] +) -> @ast::item { + let fields = mk_deser_fields(cx, span, mk_struct_fields(fields)); + + // ast for `read_struct($(name), || $(fields))` + let body = cx.expr_call( + span, + cx.expr_field( + span, + cx.expr_var(span, ~"__d"), + cx.ident_of(~"read_struct") + ), + ~[ + cx.lit_str(span, @cx.str_of(ident)), + cx.lambda_expr( + cx.expr( + span, + ast::expr_struct( + cx.path(span, ~[ident]), + fields, + None + ) + ) + ), + ] + ); + + mk_deser_impl(cx, span, ident, tps, body) } -fn deser_ty(cx: ext_ctxt, tps: deser_tps_map, - ty: @ast::ty, -d: @ast::expr) -> @ast::expr { - - let ext_cx = cx; // required for #ast{} - - match ty.node { - ast::ty_nil => { - #ast{ $(d).read_nil() } - } - - ast::ty_bot => { - #ast{ fail } - } - - ast::ty_box(mt) => { - let l = deser_lambda(cx, tps, mt.ty, cx.clone(d)); - #ast{ @$(d).read_box($(l)) } - } - - // For unique evecs/estrs, just pass through to underlying vec or str - ast::ty_uniq(mt) if is_vec_or_str(mt.ty) => { - deser_ty(cx, tps, mt.ty, move d) - } - - ast::ty_uniq(mt) => { - let l = deser_lambda(cx, tps, mt.ty, cx.clone(d)); - #ast{ ~$(d).read_uniq($(l)) } - } - - ast::ty_ptr(_) | ast::ty_rptr(_, _) => { - #ast{ fail } - } - - ast::ty_rec(flds) => { - let fields = do vec::from_fn(vec::len(flds)) |fidx| { - let fld = flds[fidx]; - let d = cx.clone(d); - let f = cx.lit_str(fld.span, @cx.str_of(fld.node.ident)); - let i = cx.lit_uint(fld.span, fidx); - let l = deser_lambda(cx, tps, fld.node.mt.ty, cx.clone(d)); - {node: {mutbl: fld.node.mt.mutbl, - ident: fld.node.ident, - expr: #ast{ $(d).read_rec_field($(f), $(i), $(l))} }, - span: fld.span} - }; - let fld_expr = cx.expr(ty.span, ast::expr_rec(fields, None)); - let fld_lambda = cx.lambda(cx.expr_blk(fld_expr)); - #ast{ $(d).read_rec($(fld_lambda)) } - } - - ast::ty_fn(*) => { - #ast{ fail } - } - - ast::ty_tup(tys) => { - // Generate code like - // - // d.read_tup(3u) {|| - // (d.read_tup_elt(0u, {||...}), - // d.read_tup_elt(1u, {||...}), - // d.read_tup_elt(2u, {||...})) - // } - - let arg_exprs = do vec::from_fn(vec::len(tys)) |i| { - let idx = cx.lit_uint(ty.span, i); - let body = deser_lambda(cx, tps, tys[i], cx.clone(d)); - #ast{ $(d).read_tup_elt($(idx), $(body)) } - }; - let body = - cx.lambda(cx.expr_blk( - cx.expr(ty.span, ast::expr_tup(arg_exprs)))); - let sz = cx.lit_uint(ty.span, vec::len(tys)); - #ast{ $(d).read_tup($(sz), $(body)) } - } - - ast::ty_path(path, _) => { - if vec::len(path.idents) == 1u && - vec::is_empty(path.types) { - let ident = path.idents[0]; - - match tps.find(ident) { - Some(f) => f(), - None => deser_path(cx, tps, path, move d) - } - } else { - deser_path(cx, tps, path, move d) +// Records and structs don't have the same fields types, but they share enough +// that if we extract the right subfields out we can share the serialization +// generator code. +type field = { span: span, ident: ast::ident, mutbl: ast::mutability }; + +fn mk_rec_fields(fields: ~[ast::ty_field]) -> ~[field] { + do fields.map |field| { + { + span: field.span, + ident: field.node.ident, + mutbl: field.node.mt.mutbl, } - } - - ast::ty_mac(_) => { - #ast{ fail } - } - - ast::ty_infer => { - #ast{ fail } - } + } +} - ast::ty_vec(mt) => { - let l = deser_lambda(cx, tps, mt.ty, cx.clone(d)); - #ast{ std::serialization::read_to_vec($(d), $(l)) } - } +fn mk_struct_fields(fields: ~[@ast::struct_field]) -> ~[field] { + do fields.map |field| { + let (ident, mutbl) = match field.node.kind { + ast::named_field(ident, mutbl, _) => (ident, mutbl), + _ => fail ~"[auto_serialize] does not support \ + unnamed fields", + }; - ast::ty_fixed_length(_, _) => { - cx.span_unimpl(ty.span, ~"deserialization for fixed length types"); - } + { + span: field.span, + ident: ident, + mutbl: match mutbl { + ast::class_mutable => ast::m_mutbl, + ast::class_immutable => ast::m_imm, + }, + } } } -fn mk_deser_fn(cx: ext_ctxt, span: span, - name: ast::ident, tps: ~[ast::ty_param], - f: fn(ext_ctxt, deser_tps_map, -v: @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], ~[])), - ident: cx.ident_of(~"__d" + cx.str_of(tp.ident)), - id: cx.next_id()}); - - debug!("tp_inputs = %?", tp_inputs); - - let deser_inputs: ~[ast::arg] = - vec::append(~[{mode: ast::expl(ast::by_ref), - ty: cx.ty_path(span, ~[cx.ident_of(~"__D")], ~[]), - ident: cx.ident_of(~"__d"), - id: cx.next_id()}], - tp_inputs); - - let tps_map = map::HashMap(); - for vec::each2(tps, tp_inputs) |tp, arg| { - let arg_ident = arg.ident; - tps_map.insert( - tp.ident, - fn@() -> @ast::expr { - let f = cx.var_ref(span, arg_ident); - #ast{ $(f)() } - }); +fn mk_ser_fields( + cx: ext_ctxt, + span: span, + fields: ~[field] +) -> ~[@ast::stmt] { + do fields.mapi |idx, field| { + // ast for `|| self.$(name).serialize(__s)` + let expr_lambda = cx.lambda_expr( + cx.expr_call( + span, + cx.expr_field( + span, + cx.expr_field( + span, + cx.expr_var(span, ~"self"), + field.ident + ), + cx.ident_of(~"serialize") + ), + ~[cx.expr_var(span, ~"__s")] + ) + ); + + // ast for `__s.emit_field($(name), $(idx), $(expr_lambda))` + cx.stmt( + cx.expr_call( + span, + cx.expr_field( + span, + cx.expr_var(span, ~"__s"), + cx.ident_of(~"emit_field") + ), + ~[ + cx.lit_str(span, @cx.str_of(field.ident)), + cx.lit_uint(span, idx), + expr_lambda, + ] + ) + ) } +} - let deser_bnds = @~[ - ast::bound_trait(cx.ty_path( +fn mk_deser_fields( + cx: ext_ctxt, + span: span, + fields: ~[{ span: span, ident: ast::ident, mutbl: ast::mutability }] +) -> ~[ast::field] { + do fields.mapi |idx, field| { + // ast for `|| std::serialization::deserialize(__d)` + let expr_lambda = cx.lambda( + cx.expr_blk( + cx.expr_call( + span, + cx.expr_path(span, ~[ + cx.ident_of(~"std"), + cx.ident_of(~"serialization"), + cx.ident_of(~"deserialize"), + ]), + ~[cx.expr_var(span, ~"__d")] + ) + ) + ); + + // ast for `__d.read_field($(name), $(idx), $(expr_lambda))` + let expr: @ast::expr = cx.expr_call( span, - ~[cx.ident_of(~"std"), cx.ident_of(~"serialization"), - cx.ident_of(~"Deserializer")], - ~[]))]; - - let deser_tps: ~[ast::ty_param] = - vec::append(~[{ident: cx.ident_of(~"__D"), - id: cx.next_id(), - bounds: deser_bnds}], - vec::map(tps, |tp| { - let cloned = cx.clone_ty_param(*tp); - {bounds: @(vec::append(*cloned.bounds, - ~[ast::bound_copy])), - .. cloned} - })); - - let deser_blk = cx.expr_blk(f(cx, tps_map, #ast[expr]{__d})); - - @{ident: cx.ident_of(~"deserialize_" + cx.str_of(name)), - attrs: ~[], - id: cx.next_id(), - node: ast::item_fn({inputs: deser_inputs, - output: v_ty, - cf: ast::return_val}, - ast::impure_fn, - deser_tps, - deser_blk), - vis: ast::public, - span: span} + cx.expr_field( + span, + cx.expr_var(span, ~"__d"), + cx.ident_of(~"read_field") + ), + ~[ + cx.lit_str(span, @cx.str_of(field.ident)), + cx.lit_uint(span, idx), + expr_lambda, + ] + ); + + { + node: { mutbl: field.mutbl, ident: field.ident, expr: expr }, + span: span, + } + } } -fn ty_fns(cx: ext_ctxt, name: ast::ident, - ty: @ast::ty, tps: ~[ast::ty_param]) - -> ~[@ast::item] { +fn mk_enum_ser_impl( + cx: ext_ctxt, + span: span, + ident: ast::ident, + enum_def: ast::enum_def, + tps: ~[ast::ty_param] +) -> @ast::item { + let body = mk_enum_ser_body( + cx, + span, + ident, + enum_def.variants + ); + + mk_ser_impl(cx, span, ident, tps, body) +} - let span = ty.span; - ~[ - mk_ser_fn(cx, span, name, tps, |a,b,c,d| ser_ty(a, b, ty, move c, - move d)), - mk_deser_fn(cx, span, name, tps, |a,b,c| deser_ty(a, b, ty, move c)) - ] +fn mk_enum_deser_impl( + cx: ext_ctxt, + span: span, + ident: ast::ident, + enum_def: ast::enum_def, + tps: ~[ast::ty_param] +) -> @ast::item { + let body = mk_enum_deser_body( + cx, + span, + ident, + enum_def.variants + ); + + mk_deser_impl(cx, span, ident, tps, body) } -fn ser_enum(cx: ext_ctxt, tps: ser_tps_map, e_name: ast::ident, - e_span: span, variants: ~[ast::variant], - -s: @ast::expr, -v: @ast::expr) -> ~[@ast::stmt] { - let ext_cx = cx; - let arms = do vec::from_fn(vec::len(variants)) |vidx| { - let variant = variants[vidx]; - let v_span = variant.span; - let v_name = variant.node.name; +fn ser_variant( + cx: ext_ctxt, + span: span, + v_name: ast::ident, + v_idx: uint, + args: ~[ast::variant_arg] +) -> ast::arm { + // Name the variant arguments. + let names = args.mapi(|i, _arg| cx.ident_of(fmt!("__v%u", i))); + + // Bind the names to the variant argument type. + let pats = args.mapi(|i, arg| cx.binder_pat(arg.ty.span, names[i])); + + let pat_node = if pats.is_empty() { + ast::pat_ident( + ast::bind_by_implicit_ref, + cx.path(span, ~[v_name]), + None + ) + } else { + ast::pat_enum( + cx.path(span, ~[v_name]), + Some(pats) + ) + }; - match variant.node.kind { - ast::tuple_variant_kind(args) => { - let variant_tys = vec::map(args, |a| a.ty); - - ser_variant( - cx, tps, variant_tys, v_span, cx.clone(s), - - // Generate pattern var(v1, v2, v3) - |pats| { - if vec::is_empty(pats) { - ast::pat_ident(ast::bind_by_implicit_ref, - cx.path(v_span, ~[v_name]), - None) - } else { - ast::pat_enum(cx.path(v_span, ~[v_name]), - Some(pats)) - } - }, + let pat = @{ + id: cx.next_id(), + node: pat_node, + span: span, + }; - // Generate body s.emit_enum_variant("foo", 0u, - // 3u, {|| blk }) - |-s, blk| { - let v_name = cx.lit_str(v_span, @cx.str_of(v_name)); - let v_id = cx.lit_uint(v_span, vidx); - let sz = cx.lit_uint(v_span, vec::len(variant_tys)); - let body = cx.lambda(blk); - #ast[expr]{ - $(s).emit_enum_variant($(v_name), $(v_id), - $(sz), $(body)) - } - }, + 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") + ); - // Generate s.emit_enum_variant_arg(i, {|| blk }) - |-s, i, blk| { - let idx = cx.lit_uint(v_span, i); - let body = cx.lambda(blk); - #ast[expr]{ - $(s).emit_enum_variant_arg($(idx), $(body)) - } - }) - } - _ => - fail ~"struct variants unimplemented for auto serialize" - } + // ast for `|| $(v).serialize(__s)` + let expr_serialize = cx.lambda_expr( + cx.expr_call( + span, + cx.expr_field( + span, + cx.expr_path(span, ~[names[a_idx]]), + cx.ident_of(~"serialize") + ), + ~[cx.expr_var(span, ~"__s")] + ) + ); + + // ast for `$(expr_emit)($(a_idx), $(expr_serialize))` + cx.stmt( + cx.expr_call( + span, + expr_emit, + ~[cx.lit_uint(span, a_idx), expr_serialize] + ) + ) }; - let lam = cx.lambda(cx.blk(e_span, ~[cx.alt_stmt(arms, e_span, move v)])); - let e_name = cx.lit_str(e_span, @cx.str_of(e_name)); - ~[#ast[stmt]{ $(s).emit_enum($(e_name), $(lam)) }] -} -fn deser_enum(cx: ext_ctxt, tps: deser_tps_map, e_name: ast::ident, - e_span: span, variants: ~[ast::variant], - -d: @ast::expr) -> @ast::expr { - let ext_cx = cx; - let mut arms: ~[ast::arm] = do vec::from_fn(vec::len(variants)) |vidx| { - let variant = variants[vidx]; - let v_span = variant.span; - let v_name = variant.node.name; + // ast for `__s.emit_enum_variant($(name), $(idx), $(sz), $(lambda))` + let body = cx.expr_call( + span, + cx.expr_field( + span, + cx.expr_var(span, ~"__s"), + cx.ident_of(~"emit_enum_variant") + ), + ~[ + cx.lit_str(span, @cx.str_of(v_name)), + cx.lit_uint(span, v_idx), + cx.lit_uint(span, stmts.len()), + cx.lambda_stmts(span, stmts), + ] + ); + + { pats: ~[pat], guard: None, body: cx.expr_blk(body) } +} - let body; +fn mk_enum_ser_body( + cx: ext_ctxt, + span: span, + name: ast::ident, + variants: ~[ast::variant] +) -> @ast::expr { + let arms = do variants.mapi |v_idx, variant| { match variant.node.kind { - ast::tuple_variant_kind(args) => { - let tys = vec::map(args, |a| a.ty); - - let arg_exprs = do vec::from_fn(vec::len(tys)) |i| { - let idx = cx.lit_uint(v_span, i); - let body = deser_lambda(cx, tps, tys[i], cx.clone(d)); - #ast{ $(d).read_enum_variant_arg($(idx), $(body)) } - }; - - body = { - if vec::is_empty(tys) { - // for a nullary variant v, do "v" - cx.var_ref(v_span, v_name) - } else { - // for an n-ary variant v, do "v(a_1, ..., a_n)" - cx.expr(v_span, ast::expr_call( - cx.var_ref(v_span, v_name), arg_exprs, false)) - } - }; - } + ast::tuple_variant_kind(args) => + ser_variant(cx, span, variant.node.name, v_idx, args), ast::struct_variant_kind(*) => fail ~"struct variants unimplemented", ast::enum_variant_kind(*) => - fail ~"enum variants unimplemented" + fail ~"enum variants unimplemented", } + }; - {pats: ~[@{id: cx.next_id(), - node: ast::pat_lit(cx.lit_uint(v_span, vidx)), - span: v_span}], - guard: None, - body: cx.expr_blk(body)} + // ast for `match *self { $(arms) }` + let match_expr = cx.expr( + span, + ast::expr_match( + cx.expr( + span, + ast::expr_unary(ast::deref, cx.expr_var(span, ~"self")) + ), + arms + ) + ); + + // ast for `__s.emit_enum($(name), || $(match_expr))` + cx.expr_call( + span, + cx.expr_field( + span, + cx.expr_var(span, ~"__s"), + cx.ident_of(~"emit_enum") + ), + ~[ + cx.lit_str(span, @cx.str_of(name)), + cx.lambda_expr(match_expr), + ] + ) +} + +fn mk_enum_deser_variant_nary( + cx: ext_ctxt, + span: span, + name: ast::ident, + args: ~[ast::variant_arg] +) -> @ast::expr { + let args = do args.mapi |idx, _arg| { + // ast for `|| std::serialization::deserialize(__d)` + let expr_lambda = cx.lambda_expr( + cx.expr_call( + span, + cx.expr_path(span, ~[ + cx.ident_of(~"std"), + cx.ident_of(~"serialization"), + cx.ident_of(~"deserialize"), + ]), + ~[cx.expr_var(span, ~"__d")] + ) + ); + + // ast for `__d.read_enum_variant_arg($(a_idx), $(expr_lambda))` + cx.expr_call( + span, + cx.expr_field( + span, + cx.expr_var(span, ~"__d"), + cx.ident_of(~"read_enum_variant_arg") + ), + ~[cx.lit_uint(span, idx), expr_lambda] + ) }; - let impossible_case = {pats: ~[@{id: cx.next_id(), - node: ast::pat_wild, - span: e_span}], - guard: None, - // FIXME #3198: proper error message - body: cx.expr_blk(cx.expr(e_span, - ast::expr_fail(None)))}; - arms += ~[impossible_case]; - - // Generate code like: - let e_name = cx.lit_str(e_span, @cx.str_of(e_name)); - let alt_expr = cx.expr(e_span, - ast::expr_match(#ast{__i}, arms)); - let var_lambda = #ast{ |__i| $(alt_expr) }; - let read_var = #ast{ $(cx.clone(d)).read_enum_variant($(var_lambda)) }; - let read_lambda = cx.lambda(cx.expr_blk(read_var)); - #ast{ $(d).read_enum($(e_name), $(read_lambda)) } + // ast for `$(name)($(args))` + cx.expr_call(span, cx.expr_path(span, ~[name]), args) } -fn enum_fns(cx: ext_ctxt, e_name: ast::ident, e_span: span, - variants: ~[ast::variant], tps: ~[ast::ty_param]) - -> ~[@ast::item] { - ~[ - mk_ser_fn(cx, e_span, e_name, tps, - |a,b,c,d| ser_enum(a, b, e_name, e_span, variants, move c, - move d)), - mk_deser_fn(cx, e_span, e_name, tps, - |a,b,c| deser_enum(a, b, e_name, e_span, variants, move c)) - ] +fn mk_enum_deser_body( + cx: ext_ctxt, + span: span, + name: ast::ident, + variants: ~[ast::variant] +) -> @ast::expr { + let mut arms = do variants.mapi |v_idx, variant| { + let body = match variant.node.kind { + ast::tuple_variant_kind(args) => { + if args.is_empty() { + // for a nullary variant v, do "v" + cx.expr_path(span, ~[variant.node.name]) + } else { + // for an n-ary variant v, do "v(a_1, ..., a_n)" + mk_enum_deser_variant_nary( + cx, + span, + variant.node.name, + args + ) + } + }, + ast::struct_variant_kind(*) => + fail ~"struct variants unimplemented", + ast::enum_variant_kind(*) => + fail ~"enum variants unimplemented", + }; + + let pat = @{ + id: cx.next_id(), + node: ast::pat_lit(cx.lit_uint(span, v_idx)), + span: span, + }; + + { + pats: ~[pat], + guard: None, + body: cx.expr_blk(body), + } + }; + + let impossible_case = { + pats: ~[@{ id: cx.next_id(), node: ast::pat_wild, span: span}], + guard: None, + + // FIXME(#3198): proper error message + body: cx.expr_blk(cx.expr(span, ast::expr_fail(None))), + }; + + arms.push(impossible_case); + + // ast for `|i| { match i { $(arms) } }` + let expr_lambda = cx.expr( + span, + ast::expr_fn_block( + { + inputs: ~[{ + mode: ast::infer(cx.next_id()), + ty: @{ + id: cx.next_id(), + node: ast::ty_infer, + span: span + }, + ident: cx.ident_of(~"i"), + id: cx.next_id(), + }], + output: @{ + id: cx.next_id(), + node: ast::ty_infer, + span: span, + }, + cf: ast::return_val, + }, + cx.expr_blk( + cx.expr( + span, + ast::expr_match(cx.expr_var(span, ~"i"), arms) + ) + ), + @~[] + ) + ); + + // ast for `__d.read_enum_variant($(expr_lambda))` + let expr_lambda = cx.lambda_expr( + cx.expr_call( + span, + cx.expr_field( + span, + cx.expr_var(span, ~"__d"), + cx.ident_of(~"read_enum_variant") + ), + ~[expr_lambda] + ) + ); + + // ast for `__d.read_enum($(e_name), $(expr_lambda))` + cx.expr_call( + span, + cx.expr_field( + span, + cx.expr_var(span, ~"__d"), + cx.ident_of(~"read_enum") + ), + ~[ + cx.lit_str(span, @cx.str_of(name)), + expr_lambda + ] + ) } diff --git a/src/libsyntax/ext/auto_serialize2.rs b/src/libsyntax/ext/auto_serialize2.rs deleted file mode 100644 index 99f837a4c84..00000000000 --- a/src/libsyntax/ext/auto_serialize2.rs +++ /dev/null @@ -1,1025 +0,0 @@ -/* - -The compiler code necessary to implement the #[auto_serialize2] and -#[auto_deserialize2] extension. The idea here is that type-defining items may -be tagged with #[auto_serialize2] and #[auto_deserialize2], which will cause -us to generate a little companion module with the same name as the item. - -For example, a type like: - - #[auto_serialize2] - #[auto_deserialize2] - struct Node {id: uint} - -would generate two implementations like: - - impl Node: Serializable { - fn serialize<S: Serializer>(s: &S) { - do s.emit_struct("Node") { - s.emit_field("id", 0, || s.emit_uint(self)) - } - } - } - - impl node_id: Deserializable { - static fn deserialize<D: Deserializer>(d: &D) -> Node { - do d.read_struct("Node") { - Node { - id: d.read_field(~"x", 0, || deserialize(d)) - } - } - } - } - -Other interesting scenarios are whe the item has type parameters or -references other non-built-in types. A type definition like: - - #[auto_serialize2] - #[auto_deserialize2] - type spanned<T> = {node: T, span: span}; - -would yield functions like: - - impl<T: Serializable> spanned<T>: Serializable { - fn serialize<S: Serializer>(s: &S) { - do s.emit_rec { - s.emit_field("node", 0, || self.node.serialize(s)); - s.emit_field("span", 1, || self.span.serialize(s)); - } - } - } - - impl<T: Deserializable> spanned<T>: Deserializable { - static fn deserialize<D: Deserializer>(d: &D) -> spanned<T> { - do d.read_rec { - { - node: d.read_field(~"node", 0, || deserialize(d)), - span: d.read_field(~"span", 1, || deserialize(d)), - } - } - } - } - -FIXME (#2810)--Hygiene. Search for "__" strings. We also assume "std" is the -standard library. - -Misc notes: ------------ - -I use move mode arguments for ast nodes that will get inserted as is -into the tree. This is intended to prevent us from inserting the same -node twice. - -*/ - -use base::*; -use codemap::span; -use std::map; -use std::map::HashMap; - -export expand_auto_serialize; -export expand_auto_deserialize; - -// Transitional reexports so qquote can find the paths it is looking for -mod syntax { - pub use ext; - pub use parse; -} - -fn expand_auto_serialize( - cx: ext_ctxt, - span: span, - _mitem: ast::meta_item, - in_items: ~[@ast::item] -) -> ~[@ast::item] { - fn is_auto_serialize2(a: &ast::attribute) -> bool { - attr::get_attr_name(*a) == ~"auto_serialize2" - } - - fn filter_attrs(item: @ast::item) -> @ast::item { - @{attrs: vec::filter(item.attrs, |a| !is_auto_serialize2(a)), - .. *item} - } - - do vec::flat_map(in_items) |item| { - if item.attrs.any(is_auto_serialize2) { - match item.node { - ast::item_ty(@{node: ast::ty_rec(fields), _}, tps) => { - let ser_impl = mk_rec_ser_impl( - cx, - item.span, - item.ident, - fields, - tps - ); - - ~[filter_attrs(*item), ser_impl] - }, - ast::item_class(@{ fields, _}, tps) => { - let ser_impl = mk_struct_ser_impl( - cx, - item.span, - item.ident, - fields, - tps - ); - - ~[filter_attrs(*item), ser_impl] - }, - ast::item_enum(enum_def, tps) => { - let ser_impl = mk_enum_ser_impl( - cx, - item.span, - item.ident, - enum_def, - tps - ); - - ~[filter_attrs(*item), ser_impl] - }, - _ => { - cx.span_err(span, ~"#[auto_serialize2] can only be \ - applied to structs, record types, \ - and enum definitions"); - ~[*item] - } - } - } else { - ~[*item] - } - } -} - -fn expand_auto_deserialize( - cx: ext_ctxt, - span: span, - _mitem: ast::meta_item, - in_items: ~[@ast::item] -) -> ~[@ast::item] { - fn is_auto_deserialize2(a: &ast::attribute) -> bool { - attr::get_attr_name(*a) == ~"auto_deserialize2" - } - - fn filter_attrs(item: @ast::item) -> @ast::item { - @{attrs: vec::filter(item.attrs, |a| !is_auto_deserialize2(a)), - .. *item} - } - - do vec::flat_map(in_items) |item| { - if item.attrs.any(is_auto_deserialize2) { - match item.node { - ast::item_ty(@{node: ast::ty_rec(fields), _}, tps) => { - let deser_impl = mk_rec_deser_impl( - cx, - item.span, - item.ident, - fields, - tps - ); - - ~[filter_attrs(*item), deser_impl] - }, - ast::item_class(@{ fields, _}, tps) => { - let deser_impl = mk_struct_deser_impl( - cx, - item.span, - item.ident, - fields, - tps - ); - - ~[filter_attrs(*item), deser_impl] - }, - ast::item_enum(enum_def, tps) => { - let deser_impl = mk_enum_deser_impl( - cx, - item.span, - item.ident, - enum_def, - tps - ); - - ~[filter_attrs(*item), deser_impl] - }, - _ => { - cx.span_err(span, ~"#[auto_deserialize2] can only be \ - applied to structs, record types, \ - and enum definitions"); - ~[*item] - } - } - } else { - ~[*item] - } - } -} - -priv impl ext_ctxt { - fn expr_path(span: span, strs: ~[ast::ident]) -> @ast::expr { - self.expr(span, ast::expr_path(self.path(span, strs))) - } - - fn expr_var(span: span, var: ~str) -> @ast::expr { - self.expr_path(span, ~[self.ident_of(var)]) - } - - fn expr_field( - span: span, - expr: @ast::expr, - ident: ast::ident - ) -> @ast::expr { - self.expr(span, ast::expr_field(expr, ident, ~[])) - } - - fn expr_call( - span: span, - expr: @ast::expr, - args: ~[@ast::expr] - ) -> @ast::expr { - self.expr(span, ast::expr_call(expr, args, false)) - } - - fn lambda_expr(expr: @ast::expr) -> @ast::expr { - self.lambda(self.expr_blk(expr)) - } - - fn lambda_stmts(span: span, stmts: ~[@ast::stmt]) -> @ast::expr { - self.lambda(self.blk(span, stmts)) - } -} - -fn mk_impl( - cx: ext_ctxt, - span: span, - ident: ast::ident, - path: @ast::path, - tps: ~[ast::ty_param], - f: fn(@ast::ty) -> @ast::method -) -> @ast::item { - // All the type parameters need to bound to the trait. - let trait_tps = do tps.map |tp| { - let t_bound = ast::bound_trait(@{ - id: cx.next_id(), - node: ast::ty_path(path, cx.next_id()), - span: span, - }); - - { - ident: tp.ident, - id: cx.next_id(), - bounds: @vec::append(~[t_bound], *tp.bounds) - } - }; - - let opt_trait = Some(@{ - path: path, - ref_id: cx.next_id(), - impl_id: cx.next_id(), - }); - - let ty = cx.ty_path( - span, - ~[ident], - tps.map(|tp| cx.ty_path(span, ~[tp.ident], ~[])) - ); - - @{ - // This is a new-style impl declaration. - // XXX: clownshoes - ident: ast::token::special_idents::clownshoes_extensions, - attrs: ~[], - id: cx.next_id(), - node: ast::item_impl(trait_tps, opt_trait, ty, ~[f(ty)]), - vis: ast::public, - span: span, - } -} - -fn mk_ser_impl( - cx: ext_ctxt, - span: span, - ident: ast::ident, - tps: ~[ast::ty_param], - body: @ast::expr -) -> @ast::item { - // Make a path to the std::serialization2::Serializable trait. - let path = cx.path( - span, - ~[ - cx.ident_of(~"std"), - cx.ident_of(~"serialization2"), - cx.ident_of(~"Serializable"), - ] - ); - - mk_impl( - cx, - span, - ident, - path, - tps, - |_ty| mk_ser_method(cx, span, cx.expr_blk(body)) - ) -} - -fn mk_deser_impl( - cx: ext_ctxt, - span: span, - ident: ast::ident, - tps: ~[ast::ty_param], - body: @ast::expr -) -> @ast::item { - // Make a path to the std::serialization2::Deserializable trait. - let path = cx.path( - span, - ~[ - cx.ident_of(~"std"), - cx.ident_of(~"serialization2"), - cx.ident_of(~"Deserializable"), - ] - ); - - mk_impl( - cx, - span, - ident, - path, - tps, - |ty| mk_deser_method(cx, span, ty, cx.expr_blk(body)) - ) -} - -fn mk_ser_method( - cx: ext_ctxt, - span: span, - ser_body: ast::blk -) -> @ast::method { - let ser_bound = cx.ty_path( - span, - ~[ - cx.ident_of(~"std"), - cx.ident_of(~"serialization2"), - cx.ident_of(~"Serializer"), - ], - ~[] - ); - - let ser_tps = ~[{ - ident: cx.ident_of(~"__S"), - id: cx.next_id(), - bounds: @~[ast::bound_trait(ser_bound)], - }]; - - let ty_s = @{ - id: cx.next_id(), - node: ast::ty_rptr( - @{ - id: cx.next_id(), - node: ast::re_anon, - }, - { - ty: cx.ty_path(span, ~[cx.ident_of(~"__S")], ~[]), - mutbl: ast::m_imm - } - ), - span: span, - }; - - let ser_inputs = ~[{ - mode: ast::infer(cx.next_id()), - ty: ty_s, - ident: cx.ident_of(~"__s"), - id: cx.next_id(), - }]; - - let ser_output = @{ - id: cx.next_id(), - node: ast::ty_nil, - span: span, - }; - - let ser_decl = { - inputs: ser_inputs, - output: ser_output, - cf: ast::return_val, - }; - - @{ - ident: cx.ident_of(~"serialize"), - attrs: ~[], - tps: ser_tps, - self_ty: { node: ast::sty_region(ast::m_imm), span: span }, - purity: ast::impure_fn, - decl: ser_decl, - body: ser_body, - id: cx.next_id(), - span: span, - self_id: cx.next_id(), - vis: ast::public, - } -} - -fn mk_deser_method( - cx: ext_ctxt, - span: span, - ty: @ast::ty, - deser_body: ast::blk -) -> @ast::method { - let deser_bound = cx.ty_path( - span, - ~[ - cx.ident_of(~"std"), - cx.ident_of(~"serialization2"), - cx.ident_of(~"Deserializer"), - ], - ~[] - ); - - let deser_tps = ~[{ - ident: cx.ident_of(~"__D"), - id: cx.next_id(), - bounds: @~[ast::bound_trait(deser_bound)], - }]; - - let ty_d = @{ - id: cx.next_id(), - node: ast::ty_rptr( - @{ - id: cx.next_id(), - node: ast::re_anon, - }, - { - ty: cx.ty_path(span, ~[cx.ident_of(~"__D")], ~[]), - mutbl: ast::m_imm - } - ), - span: span, - }; - - let deser_inputs = ~[{ - mode: ast::infer(cx.next_id()), - ty: ty_d, - ident: cx.ident_of(~"__d"), - id: cx.next_id(), - }]; - - let deser_decl = { - inputs: deser_inputs, - output: ty, - cf: ast::return_val, - }; - - @{ - ident: cx.ident_of(~"deserialize"), - attrs: ~[], - tps: deser_tps, - self_ty: { node: ast::sty_static, span: span }, - purity: ast::impure_fn, - decl: deser_decl, - body: deser_body, - id: cx.next_id(), - span: span, - self_id: cx.next_id(), - vis: ast::public, - } -} - -fn mk_rec_ser_impl( - cx: ext_ctxt, - span: span, - ident: ast::ident, - fields: ~[ast::ty_field], - tps: ~[ast::ty_param] -) -> @ast::item { - let fields = mk_ser_fields(cx, span, mk_rec_fields(fields)); - - // ast for `__s.emit_rec(|| $(fields))` - let body = cx.expr_call( - span, - cx.expr_field( - span, - cx.expr_var(span, ~"__s"), - cx.ident_of(~"emit_rec") - ), - ~[cx.lambda_stmts(span, fields)] - ); - - mk_ser_impl(cx, span, ident, tps, body) -} - -fn mk_rec_deser_impl( - cx: ext_ctxt, - span: span, - ident: ast::ident, - fields: ~[ast::ty_field], - tps: ~[ast::ty_param] -) -> @ast::item { - let fields = mk_deser_fields(cx, span, mk_rec_fields(fields)); - - // ast for `read_rec(|| $(fields))` - let body = cx.expr_call( - span, - cx.expr_field( - span, - cx.expr_var(span, ~"__d"), - cx.ident_of(~"read_rec") - ), - ~[ - cx.lambda_expr( - cx.expr( - span, - ast::expr_rec(fields, None) - ) - ) - ] - ); - - mk_deser_impl(cx, span, ident, tps, body) -} - -fn mk_struct_ser_impl( - cx: ext_ctxt, - span: span, - ident: ast::ident, - fields: ~[@ast::struct_field], - tps: ~[ast::ty_param] -) -> @ast::item { - let fields = mk_ser_fields(cx, span, mk_struct_fields(fields)); - - // ast for `__s.emit_struct($(name), || $(fields))` - let ser_body = cx.expr_call( - span, - cx.expr_field( - span, - cx.expr_var(span, ~"__s"), - cx.ident_of(~"emit_struct") - ), - ~[ - cx.lit_str(span, @cx.str_of(ident)), - cx.lambda_stmts(span, fields), - ] - ); - - mk_ser_impl(cx, span, ident, tps, ser_body) -} - -fn mk_struct_deser_impl( - cx: ext_ctxt, - span: span, - ident: ast::ident, - fields: ~[@ast::struct_field], - tps: ~[ast::ty_param] -) -> @ast::item { - let fields = mk_deser_fields(cx, span, mk_struct_fields(fields)); - - // ast for `read_struct($(name), || $(fields))` - let body = cx.expr_call( - span, - cx.expr_field( - span, - cx.expr_var(span, ~"__d"), - cx.ident_of(~"read_struct") - ), - ~[ - cx.lit_str(span, @cx.str_of(ident)), - cx.lambda_expr( - cx.expr( - span, - ast::expr_struct( - cx.path(span, ~[ident]), - fields, - None - ) - ) - ), - ] - ); - - mk_deser_impl(cx, span, ident, tps, body) -} - -// Records and structs don't have the same fields types, but they share enough -// that if we extract the right subfields out we can share the serialization -// generator code. -type field = { span: span, ident: ast::ident, mutbl: ast::mutability }; - -fn mk_rec_fields(fields: ~[ast::ty_field]) -> ~[field] { - do fields.map |field| { - { - span: field.span, - ident: field.node.ident, - mutbl: field.node.mt.mutbl, - } - } -} - -fn mk_struct_fields(fields: ~[@ast::struct_field]) -> ~[field] { - do fields.map |field| { - let (ident, mutbl) = match field.node.kind { - ast::named_field(ident, mutbl, _) => (ident, mutbl), - _ => fail ~"[auto_serialize2] does not support \ - unnamed fields", - }; - - { - span: field.span, - ident: ident, - mutbl: match mutbl { - ast::class_mutable => ast::m_mutbl, - ast::class_immutable => ast::m_imm, - }, - } - } -} - -fn mk_ser_fields( - cx: ext_ctxt, - span: span, - fields: ~[field] -) -> ~[@ast::stmt] { - do fields.mapi |idx, field| { - // ast for `|| self.$(name).serialize(__s)` - let expr_lambda = cx.lambda_expr( - cx.expr_call( - span, - cx.expr_field( - span, - cx.expr_field( - span, - cx.expr_var(span, ~"self"), - field.ident - ), - cx.ident_of(~"serialize") - ), - ~[cx.expr_var(span, ~"__s")] - ) - ); - - // ast for `__s.emit_field($(name), $(idx), $(expr_lambda))` - cx.stmt( - cx.expr_call( - span, - cx.expr_field( - span, - cx.expr_var(span, ~"__s"), - cx.ident_of(~"emit_field") - ), - ~[ - cx.lit_str(span, @cx.str_of(field.ident)), - cx.lit_uint(span, idx), - expr_lambda, - ] - ) - ) - } -} - -fn mk_deser_fields( - cx: ext_ctxt, - span: span, - fields: ~[{ span: span, ident: ast::ident, mutbl: ast::mutability }] -) -> ~[ast::field] { - do fields.mapi |idx, field| { - // ast for `|| std::serialization2::deserialize(__d)` - let expr_lambda = cx.lambda( - cx.expr_blk( - cx.expr_call( - span, - cx.expr_path(span, ~[ - cx.ident_of(~"std"), - cx.ident_of(~"serialization2"), - cx.ident_of(~"deserialize"), - ]), - ~[cx.expr_var(span, ~"__d")] - ) - ) - ); - - // ast for `__d.read_field($(name), $(idx), $(expr_lambda))` - let expr: @ast::expr = cx.expr_call( - span, - cx.expr_field( - span, - cx.expr_var(span, ~"__d"), - cx.ident_of(~"read_field") - ), - ~[ - cx.lit_str(span, @cx.str_of(field.ident)), - cx.lit_uint(span, idx), - expr_lambda, - ] - ); - - { - node: { mutbl: field.mutbl, ident: field.ident, expr: expr }, - span: span, - } - } -} - -fn mk_enum_ser_impl( - cx: ext_ctxt, - span: span, - ident: ast::ident, - enum_def: ast::enum_def, - tps: ~[ast::ty_param] -) -> @ast::item { - let body = mk_enum_ser_body( - cx, - span, - ident, - enum_def.variants - ); - - mk_ser_impl(cx, span, ident, tps, body) -} - -fn mk_enum_deser_impl( - cx: ext_ctxt, - span: span, - ident: ast::ident, - enum_def: ast::enum_def, - tps: ~[ast::ty_param] -) -> @ast::item { - let body = mk_enum_deser_body( - cx, - span, - ident, - enum_def.variants - ); - - mk_deser_impl(cx, span, ident, tps, body) -} - -fn ser_variant( - cx: ext_ctxt, - span: span, - v_name: ast::ident, - v_idx: uint, - args: ~[ast::variant_arg] -) -> ast::arm { - // Name the variant arguments. - let names = args.mapi(|i, _arg| cx.ident_of(fmt!("__v%u", i))); - - // Bind the names to the variant argument type. - let pats = args.mapi(|i, arg| cx.binder_pat(arg.ty.span, names[i])); - - let pat_node = if pats.is_empty() { - ast::pat_ident( - ast::bind_by_implicit_ref, - cx.path(span, ~[v_name]), - None - ) - } else { - ast::pat_enum( - cx.path(span, ~[v_name]), - Some(pats) - ) - }; - - let pat = @{ - id: cx.next_id(), - node: pat_node, - span: span, - }; - - let stmts = do args.mapi |a_idx, _arg| { - // ast for `__s.emit_enum_variant_arg` - let expr_emit = cx.expr_field( - span, - cx.expr_var(span, ~"__s"), - cx.ident_of(~"emit_enum_variant_arg") - ); - - // ast for `|| $(v).serialize(__s)` - let expr_serialize = cx.lambda_expr( - cx.expr_call( - span, - cx.expr_field( - span, - cx.expr_path(span, ~[names[a_idx]]), - cx.ident_of(~"serialize") - ), - ~[cx.expr_var(span, ~"__s")] - ) - ); - - // ast for `$(expr_emit)($(a_idx), $(expr_serialize))` - cx.stmt( - cx.expr_call( - span, - expr_emit, - ~[cx.lit_uint(span, a_idx), expr_serialize] - ) - ) - }; - - // ast for `__s.emit_enum_variant($(name), $(idx), $(sz), $(lambda))` - let body = cx.expr_call( - span, - cx.expr_field( - span, - cx.expr_var(span, ~"__s"), - cx.ident_of(~"emit_enum_variant") - ), - ~[ - cx.lit_str(span, @cx.str_of(v_name)), - cx.lit_uint(span, v_idx), - cx.lit_uint(span, stmts.len()), - cx.lambda_stmts(span, stmts), - ] - ); - - { pats: ~[pat], guard: None, body: cx.expr_blk(body) } -} - -fn mk_enum_ser_body( - cx: ext_ctxt, - span: span, - name: ast::ident, - variants: ~[ast::variant] -) -> @ast::expr { - let arms = do variants.mapi |v_idx, variant| { - match variant.node.kind { - ast::tuple_variant_kind(args) => - ser_variant(cx, span, variant.node.name, v_idx, args), - ast::struct_variant_kind(*) => - fail ~"struct variants unimplemented", - ast::enum_variant_kind(*) => - fail ~"enum variants unimplemented", - } - }; - - // ast for `match *self { $(arms) }` - let match_expr = cx.expr( - span, - ast::expr_match( - cx.expr( - span, - ast::expr_unary(ast::deref, cx.expr_var(span, ~"self")) - ), - arms - ) - ); - - // ast for `__s.emit_enum($(name), || $(match_expr))` - cx.expr_call( - span, - cx.expr_field( - span, - cx.expr_var(span, ~"__s"), - cx.ident_of(~"emit_enum") - ), - ~[ - cx.lit_str(span, @cx.str_of(name)), - cx.lambda_expr(match_expr), - ] - ) -} - -fn mk_enum_deser_variant_nary( - cx: ext_ctxt, - span: span, - name: ast::ident, - args: ~[ast::variant_arg] -) -> @ast::expr { - let args = do args.mapi |idx, _arg| { - // ast for `|| std::serialization2::deserialize(__d)` - let expr_lambda = cx.lambda_expr( - cx.expr_call( - span, - cx.expr_path(span, ~[ - cx.ident_of(~"std"), - cx.ident_of(~"serialization2"), - cx.ident_of(~"deserialize"), - ]), - ~[cx.expr_var(span, ~"__d")] - ) - ); - - // ast for `__d.read_enum_variant_arg($(a_idx), $(expr_lambda))` - cx.expr_call( - span, - cx.expr_field( - span, - cx.expr_var(span, ~"__d"), - cx.ident_of(~"read_enum_variant_arg") - ), - ~[cx.lit_uint(span, idx), expr_lambda] - ) - }; - - // ast for `$(name)($(args))` - cx.expr_call(span, cx.expr_path(span, ~[name]), args) -} - -fn mk_enum_deser_body( - cx: ext_ctxt, - span: span, - name: ast::ident, - variants: ~[ast::variant] -) -> @ast::expr { - let mut arms = do variants.mapi |v_idx, variant| { - let body = match variant.node.kind { - ast::tuple_variant_kind(args) => { - if args.is_empty() { - // for a nullary variant v, do "v" - cx.expr_path(span, ~[variant.node.name]) - } else { - // for an n-ary variant v, do "v(a_1, ..., a_n)" - mk_enum_deser_variant_nary( - cx, - span, - variant.node.name, - args - ) - } - }, - ast::struct_variant_kind(*) => - fail ~"struct variants unimplemented", - ast::enum_variant_kind(*) => - fail ~"enum variants unimplemented", - }; - - let pat = @{ - id: cx.next_id(), - node: ast::pat_lit(cx.lit_uint(span, v_idx)), - span: span, - }; - - { - pats: ~[pat], - guard: None, - body: cx.expr_blk(body), - } - }; - - let impossible_case = { - pats: ~[@{ id: cx.next_id(), node: ast::pat_wild, span: span}], - guard: None, - - // FIXME(#3198): proper error message - body: cx.expr_blk(cx.expr(span, ast::expr_fail(None))), - }; - - arms.push(impossible_case); - - // ast for `|i| { match i { $(arms) } }` - let expr_lambda = cx.expr( - span, - ast::expr_fn_block( - { - inputs: ~[{ - mode: ast::infer(cx.next_id()), - ty: @{ - id: cx.next_id(), - node: ast::ty_infer, - span: span - }, - ident: cx.ident_of(~"i"), - id: cx.next_id(), - }], - output: @{ - id: cx.next_id(), - node: ast::ty_infer, - span: span, - }, - cf: ast::return_val, - }, - cx.expr_blk( - cx.expr( - span, - ast::expr_match(cx.expr_var(span, ~"i"), arms) - ) - ), - @~[] - ) - ); - - // ast for `__d.read_enum_variant($(expr_lambda))` - let expr_lambda = cx.lambda_expr( - cx.expr_call( - span, - cx.expr_field( - span, - cx.expr_var(span, ~"__d"), - cx.ident_of(~"read_enum_variant") - ), - ~[expr_lambda] - ) - ); - - // ast for `__d.read_enum($(e_name), $(expr_lambda))` - cx.expr_call( - span, - cx.expr_field( - span, - cx.expr_var(span, ~"__d"), - cx.ident_of(~"read_enum") - ), - ~[ - cx.lit_str(span, @cx.str_of(name)), - expr_lambda - ] - ) -} diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 9a31cc1d8f6..5b4cc23ce09 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -1,7 +1,7 @@ use std::map::HashMap; use parse::parser; use diagnostic::span_handler; -use codemap::{codemap, span, expn_info, expanded_from}; +use codemap::{CodeMap, span, expn_info, expanded_from}; // obsolete old-style #macro code: // @@ -80,14 +80,12 @@ fn syntax_expander_table() -> HashMap<~str, syntax_extension> { builtin_item_tt( ext::tt::macro_rules::add_new_extension)); syntax_expanders.insert(~"fmt", builtin(ext::fmt::expand_syntax_ext)); - syntax_expanders.insert(~"auto_serialize", - item_decorator(ext::auto_serialize::expand)); syntax_expanders.insert( - ~"auto_serialize2", - item_decorator(ext::auto_serialize2::expand_auto_serialize)); + ~"auto_serialize", + item_decorator(ext::auto_serialize::expand_auto_serialize)); syntax_expanders.insert( - ~"auto_deserialize2", - item_decorator(ext::auto_serialize2::expand_auto_deserialize)); + ~"auto_deserialize", + item_decorator(ext::auto_serialize::expand_auto_deserialize)); syntax_expanders.insert(~"env", builtin(ext::env::expand_syntax_ext)); syntax_expanders.insert(~"concat_idents", builtin(ext::concat_idents::expand_syntax_ext)); @@ -122,12 +120,11 @@ fn syntax_expander_table() -> HashMap<~str, syntax_extension> { return syntax_expanders; } - // One of these is made during expansion and incrementally updated as we go; // when a macro expansion occurs, the resulting nodes have the backtrace() // -> expn_info of their expansion context stored into their span. trait ext_ctxt { - fn codemap() -> codemap; + fn codemap() -> CodeMap; fn parse_sess() -> parse::parse_sess; fn cfg() -> ast::crate_cfg; fn print_backtrace(); @@ -159,7 +156,7 @@ fn mk_ctxt(parse_sess: parse::parse_sess, mut mod_path: ~[ast::ident], mut trace_mac: bool}; impl ctxt_repr: ext_ctxt { - fn codemap() -> codemap { self.parse_sess.cm } + fn codemap() -> CodeMap { self.parse_sess.cm } fn parse_sess() -> parse::parse_sess { self.parse_sess } fn cfg() -> ast::crate_cfg { self.cfg } fn print_backtrace() { } @@ -234,7 +231,7 @@ fn mk_ctxt(parse_sess: parse::parse_sess, mut mod_path: ~[], mut trace_mac: false }; - move (imp as ext_ctxt) + move ((move imp) as ext_ctxt) } fn expr_to_str(cx: ext_ctxt, expr: @ast::expr, error: ~str) -> ~str { @@ -272,21 +269,21 @@ fn get_mac_args(cx: ext_ctxt, sp: span, arg: ast::mac_arg, match max { Some(max) if ! (min <= elts_len && elts_len <= max) => { cx.span_fatal(sp, - fmt!("#%s takes between %u and %u arguments.", + fmt!("%s! takes between %u and %u arguments.", name, min, max)); } None if ! (min <= elts_len) => { - cx.span_fatal(sp, fmt!("#%s needs at least %u arguments.", + cx.span_fatal(sp, fmt!("%s! needs at least %u arguments.", name, min)); } _ => return elts /* we are good */ } } _ => { - cx.span_fatal(sp, fmt!("#%s: malformed invocation", name)) + cx.span_fatal(sp, fmt!("%s!: malformed invocation", name)) } }, - None => cx.span_fatal(sp, fmt!("#%s: missing arguments", name)) + None => cx.span_fatal(sp, fmt!("%s!: missing arguments", name)) } } diff --git a/src/libsyntax/ext/env.rs b/src/libsyntax/ext/env.rs index 8cecceb2e55..37fb0f05cbd 100644 --- a/src/libsyntax/ext/env.rs +++ b/src/libsyntax/ext/env.rs @@ -1,6 +1,6 @@ /* - * The compiler code necessary to support the #env extension. Eventually this + * The compiler code necessary to support the env! extension. Eventually this * should all get sucked into either the compiler syntax extension plugin * interface. */ @@ -15,7 +15,7 @@ fn expand_syntax_ext(cx: ext_ctxt, sp: codemap::span, arg: ast::mac_arg, // FIXME (#2248): if this was more thorough it would manufacture an // Option<str> rather than just an maybe-empty string. - let var = expr_to_str(cx, args[0], ~"#env requires a string"); + let var = expr_to_str(cx, args[0], ~"env! requires a string"); match os::getenv(var) { option::None => return mk_uniq_str(cx, sp, ~""), option::Some(s) => return mk_uniq_str(cx, sp, s) diff --git a/src/libsyntax/ext/fmt.rs b/src/libsyntax/ext/fmt.rs index ea493eab561..e24575f6cd3 100644 --- a/src/libsyntax/ext/fmt.rs +++ b/src/libsyntax/ext/fmt.rs @@ -1,7 +1,7 @@ /* - * The compiler code necessary to support the #fmt extension. Eventually this + * The compiler code necessary to support the fmt! extension. Eventually this * should all get sucked into either the standard library extfmt module or the * compiler syntax extension plugin interface. */ @@ -16,7 +16,7 @@ fn expand_syntax_ext(cx: ext_ctxt, sp: span, arg: ast::mac_arg, let args = get_mac_args_no_max(cx, sp, arg, 1u, ~"fmt"); let fmt = expr_to_str(cx, args[0], - ~"first argument to #fmt must be a string literal."); + ~"first argument to fmt! must be a string literal."); let fmtspan = args[0].span; debug!("Format string:"); log(debug, fmt); @@ -76,7 +76,7 @@ fn pieces_to_expr(cx: ext_ctxt, sp: span, let count_is_args = ~[count_lit]; return mk_call(cx, sp, count_is_path, count_is_args); } - _ => cx.span_unimpl(sp, ~"unimplemented #fmt conversion") + _ => cx.span_unimpl(sp, ~"unimplemented fmt! conversion") } } fn make_ty(cx: ext_ctxt, sp: span, t: Ty) -> @ast::expr { @@ -133,7 +133,7 @@ fn pieces_to_expr(cx: ext_ctxt, sp: span, _ => return false } } - let unsupported = ~"conversion not supported in #fmt string"; + let unsupported = ~"conversion not supported in fmt! string"; match cnv.param { option::None => (), _ => cx.span_unimpl(sp, unsupported) @@ -145,14 +145,14 @@ fn pieces_to_expr(cx: ext_ctxt, sp: span, if !is_signed_type(cnv) { cx.span_fatal(sp, ~"+ flag only valid in " + - ~"signed #fmt conversion"); + ~"signed fmt! conversion"); } } FlagSpaceForSign => { if !is_signed_type(cnv) { cx.span_fatal(sp, ~"space flag only valid in " + - ~"signed #fmt conversions"); + ~"signed fmt! conversions"); } } FlagLeftZeroPad => (), @@ -252,7 +252,7 @@ fn pieces_to_expr(cx: ext_ctxt, sp: span, n += 1u; if n >= nargs { cx.span_fatal(sp, - ~"not enough arguments to #fmt " + + ~"not enough arguments to fmt! " + ~"for the given format string"); } debug!("Building conversion:"); @@ -267,7 +267,7 @@ fn pieces_to_expr(cx: ext_ctxt, sp: span, if expected_nargs < nargs { cx.span_fatal - (sp, fmt!("too many arguments to #fmt. found %u, expected %u", + (sp, fmt!("too many arguments to fmt!. found %u, expected %u", nargs, expected_nargs)); } diff --git a/src/libsyntax/ext/pipes.rs b/src/libsyntax/ext/pipes.rs index ad4984c5558..4d04552bfa1 100644 --- a/src/libsyntax/ext/pipes.rs +++ b/src/libsyntax/ext/pipes.rs @@ -37,7 +37,7 @@ use codemap::span; use ext::base::ext_ctxt; use ast::tt_delim; use parse::lexer::{new_tt_reader, reader}; -use parse::parser::{parser, SOURCE_FILE}; +use parse::parser::{Parser, SOURCE_FILE}; use parse::common::parser_common; use pipes::parse_proto::proto_parser; @@ -52,7 +52,7 @@ fn expand_proto(cx: ext_ctxt, _sp: span, id: ast::ident, let tt_rdr = new_tt_reader(cx.parse_sess().span_diagnostic, cx.parse_sess().interner, None, tt); let rdr = tt_rdr as reader; - let rust_parser = parser(sess, cfg, rdr.dup(), SOURCE_FILE); + let rust_parser = Parser(sess, cfg, rdr.dup(), SOURCE_FILE); let proto = rust_parser.parse_proto(cx.str_of(id)); diff --git a/src/libsyntax/ext/pipes/ast_builder.rs b/src/libsyntax/ext/pipes/ast_builder.rs index 4da9992b0dd..f10cbc2a589 100644 --- a/src/libsyntax/ext/pipes/ast_builder.rs +++ b/src/libsyntax/ext/pipes/ast_builder.rs @@ -28,17 +28,17 @@ fn empty_span() -> span { } trait append_types { - fn add_ty(ty: @ast::ty) -> @ast::path; - fn add_tys(+tys: ~[@ast::ty]) -> @ast::path; + fn add_ty(ty: @ast::Ty) -> @ast::path; + fn add_tys(+tys: ~[@ast::Ty]) -> @ast::path; } impl @ast::path: append_types { - fn add_ty(ty: @ast::ty) -> @ast::path { + fn add_ty(ty: @ast::Ty) -> @ast::path { @{types: vec::append_one(self.types, ty), .. *self} } - fn add_tys(+tys: ~[@ast::ty]) -> @ast::path { + fn add_tys(+tys: ~[@ast::Ty]) -> @ast::path { @{types: vec::append(self.types, tys), .. *self} } @@ -47,18 +47,18 @@ impl @ast::path: append_types { trait ext_ctxt_ast_builder { fn ty_param(id: ast::ident, +bounds: ~[ast::ty_param_bound]) -> ast::ty_param; - fn arg(name: ident, ty: @ast::ty) -> ast::arg; + fn arg(name: ident, ty: @ast::Ty) -> ast::arg; fn expr_block(e: @ast::expr) -> ast::blk; - fn fn_decl(+inputs: ~[ast::arg], output: @ast::ty) -> ast::fn_decl; + fn fn_decl(+inputs: ~[ast::arg], output: @ast::Ty) -> ast::fn_decl; fn item(name: ident, span: span, +node: ast::item_) -> @ast::item; fn item_fn_poly(name: ident, +inputs: ~[ast::arg], - output: @ast::ty, + output: @ast::Ty, +ty_params: ~[ast::ty_param], +body: ast::blk) -> @ast::item; fn item_fn(name: ident, +inputs: ~[ast::arg], - output: @ast::ty, + output: @ast::Ty, +body: ast::blk) -> @ast::item; fn item_enum_poly(name: ident, span: span, @@ -66,17 +66,17 @@ trait ext_ctxt_ast_builder { +ty_params: ~[ast::ty_param]) -> @ast::item; fn item_enum(name: ident, span: span, +enum_definition: ast::enum_def) -> @ast::item; - fn variant(name: ident, span: span, +tys: ~[@ast::ty]) -> ast::variant; + fn variant(name: ident, span: span, +tys: ~[@ast::Ty]) -> ast::variant; fn item_mod(name: ident, span: span, +items: ~[@ast::item]) -> @ast::item; - fn ty_path_ast_builder(path: @ast::path) -> @ast::ty; + fn ty_path_ast_builder(path: @ast::path) -> @ast::Ty; fn item_ty_poly(name: ident, span: span, - ty: @ast::ty, + ty: @ast::Ty, +params: ~[ast::ty_param]) -> @ast::item; - fn item_ty(name: ident, span: span, ty: @ast::ty) -> @ast::item; - fn ty_vars(+ty_params: ~[ast::ty_param]) -> ~[@ast::ty]; - fn ty_field_imm(name: ident, ty: @ast::ty) -> ast::ty_field; - fn ty_rec(+v: ~[ast::ty_field]) -> @ast::ty; + fn item_ty(name: ident, span: span, ty: @ast::Ty) -> @ast::item; + fn ty_vars(+ty_params: ~[ast::ty_param]) -> ~[@ast::Ty]; + fn ty_field_imm(name: ident, ty: @ast::Ty) -> ast::ty_field; + fn ty_rec(+v: ~[ast::ty_field]) -> @ast::Ty; fn field_imm(name: ident, e: @ast::expr) -> ast::field; fn rec(+v: ~[ast::field]) -> @ast::expr; fn block(+stmts: ~[@ast::stmt], e: @ast::expr) -> ast::blk; @@ -84,11 +84,11 @@ trait ext_ctxt_ast_builder { fn stmt_expr(e: @ast::expr) -> @ast::stmt; fn block_expr(b: ast::blk) -> @ast::expr; fn empty_span() -> span; - fn ty_option(ty: @ast::ty) -> @ast::ty; + fn ty_option(ty: @ast::Ty) -> @ast::Ty; } impl ext_ctxt: ext_ctxt_ast_builder { - fn ty_option(ty: @ast::ty) -> @ast::ty { + fn ty_option(ty: @ast::Ty) -> @ast::Ty { self.ty_path_ast_builder(path(~[self.ident_of(~"Option")], self.empty_span()) .add_ty(ty)) @@ -146,18 +146,18 @@ impl ext_ctxt: ext_ctxt_ast_builder { span: self.empty_span()} } - fn ty_field_imm(name: ident, ty: @ast::ty) -> ast::ty_field { + fn ty_field_imm(name: ident, ty: @ast::Ty) -> ast::ty_field { {node: {ident: name, mt: { ty: ty, mutbl: ast::m_imm } }, span: self.empty_span()} } - fn ty_rec(+fields: ~[ast::ty_field]) -> @ast::ty { + fn ty_rec(+fields: ~[ast::ty_field]) -> @ast::Ty { @{id: self.next_id(), node: ast::ty_rec(fields), span: self.empty_span()} } - fn ty_infer() -> @ast::ty { + fn ty_infer() -> @ast::Ty { @{id: self.next_id(), node: ast::ty_infer, span: self.empty_span()} @@ -169,7 +169,7 @@ impl ext_ctxt: ext_ctxt_ast_builder { {ident: id, id: self.next_id(), bounds: @bounds} } - fn arg(name: ident, ty: @ast::ty) -> ast::arg { + fn arg(name: ident, ty: @ast::Ty) -> ast::arg { {mode: ast::infer(self.next_id()), ty: ty, ident: name, @@ -192,7 +192,7 @@ impl ext_ctxt: ext_ctxt_ast_builder { } fn fn_decl(+inputs: ~[ast::arg], - output: @ast::ty) -> ast::fn_decl { + output: @ast::Ty) -> ast::fn_decl { {inputs: inputs, output: output, cf: ast::return_val} @@ -224,7 +224,7 @@ impl ext_ctxt: ext_ctxt_ast_builder { fn item_fn_poly(name: ident, +inputs: ~[ast::arg], - output: @ast::ty, + output: @ast::Ty, +ty_params: ~[ast::ty_param], +body: ast::blk) -> @ast::item { self.item(name, @@ -237,7 +237,7 @@ impl ext_ctxt: ext_ctxt_ast_builder { fn item_fn(name: ident, +inputs: ~[ast::arg], - output: @ast::ty, + output: @ast::Ty, +body: ast::blk) -> @ast::item { self.item_fn_poly(name, inputs, output, ~[], body) } @@ -256,7 +256,7 @@ impl ext_ctxt: ext_ctxt_ast_builder { fn variant(name: ident, span: span, - +tys: ~[@ast::ty]) -> ast::variant { + +tys: ~[@ast::Ty]) -> ast::variant { let args = tys.map(|ty| {ty: *ty, id: self.next_id()}); {node: {name: name, @@ -278,13 +278,13 @@ impl ext_ctxt: ext_ctxt_ast_builder { items: items})) } - fn ty_path_ast_builder(path: @ast::path) -> @ast::ty { + fn ty_path_ast_builder(path: @ast::path) -> @ast::Ty { @{id: self.next_id(), node: ast::ty_path(path, self.next_id()), span: path.span} } - fn ty_nil_ast_builder() -> @ast::ty { + fn ty_nil_ast_builder() -> @ast::Ty { @{id: self.next_id(), node: ast::ty_nil, span: self.empty_span()} @@ -292,16 +292,16 @@ impl ext_ctxt: ext_ctxt_ast_builder { fn item_ty_poly(name: ident, span: span, - ty: @ast::ty, + ty: @ast::Ty, +params: ~[ast::ty_param]) -> @ast::item { self.item(name, span, ast::item_ty(ty, params)) } - fn item_ty(name: ident, span: span, ty: @ast::ty) -> @ast::item { + fn item_ty(name: ident, span: span, ty: @ast::Ty) -> @ast::item { self.item_ty_poly(name, span, ty, ~[]) } - fn ty_vars(+ty_params: ~[ast::ty_param]) -> ~[@ast::ty] { + fn ty_vars(+ty_params: ~[ast::ty_param]) -> ~[@ast::Ty] { ty_params.map(|p| self.ty_path_ast_builder( path(~[p.ident], self.empty_span()))) } diff --git a/src/libsyntax/ext/pipes/check.rs b/src/libsyntax/ext/pipes/check.rs index 5fcc00ef012..fcc0c84a4ff 100644 --- a/src/libsyntax/ext/pipes/check.rs +++ b/src/libsyntax/ext/pipes/check.rs @@ -38,7 +38,7 @@ impl ext_ctxt: proto::visitor<(), (), ()> { } } - fn visit_message(name: ~str, _span: span, _tys: &[@ast::ty], + fn visit_message(name: ~str, _span: span, _tys: &[@ast::Ty], this: state, next: next_state) { match next { Some({state: next, tys: next_tys}) => { @@ -68,4 +68,4 @@ impl ext_ctxt: proto::visitor<(), (), ()> { None => () } } -} \ No newline at end of file +} diff --git a/src/libsyntax/ext/pipes/parse_proto.rs b/src/libsyntax/ext/pipes/parse_proto.rs index 5c15b616b4a..8f2b92a720c 100644 --- a/src/libsyntax/ext/pipes/parse_proto.rs +++ b/src/libsyntax/ext/pipes/parse_proto.rs @@ -10,7 +10,7 @@ trait proto_parser { fn parse_state(proto: protocol); } -impl parser: proto_parser { +impl parser::Parser: proto_parser { fn parse_proto(id: ~str) -> protocol { let proto = protocol(id, self.span); diff --git a/src/libsyntax/ext/pipes/pipec.rs b/src/libsyntax/ext/pipes/pipec.rs index 874ea01e9b0..7e1cbe9ad0d 100644 --- a/src/libsyntax/ext/pipes/pipec.rs +++ b/src/libsyntax/ext/pipes/pipec.rs @@ -181,7 +181,7 @@ impl message: gen_send { } } - fn to_ty(cx: ext_ctxt) -> @ast::ty { + fn to_ty(cx: ext_ctxt) -> @ast::Ty { cx.ty_path_ast_builder(path(~[cx.ident_of(self.name())], self.span()) .add_tys(cx.ty_vars(self.get_params()))) } @@ -360,7 +360,7 @@ impl protocol: gen_init { }} } - fn buffer_ty_path(cx: ext_ctxt) -> @ast::ty { + fn buffer_ty_path(cx: ext_ctxt) -> @ast::Ty { let mut params: ~[ast::ty_param] = ~[]; for (copy self.states).each |s| { for s.ty_params.each |tp| { @@ -444,13 +444,13 @@ impl ~[@ast::item]: to_source { } } -impl @ast::ty: to_source { +impl @ast::Ty: to_source { fn to_source(cx: ext_ctxt) -> ~str { ty_to_str(self, cx.parse_sess().interner) } } -impl ~[@ast::ty]: to_source { +impl ~[@ast::Ty]: to_source { fn to_source(cx: ext_ctxt) -> ~str { str::connect(self.map(|i| i.to_source(cx)), ~", ") } diff --git a/src/libsyntax/ext/pipes/proto.rs b/src/libsyntax/ext/pipes/proto.rs index 6d58d209fcf..229e55fdfcc 100644 --- a/src/libsyntax/ext/pipes/proto.rs +++ b/src/libsyntax/ext/pipes/proto.rs @@ -18,7 +18,7 @@ impl direction : cmp::Eq { } impl direction: ToStr { - fn to_str() -> ~str { + pure fn to_str() -> ~str { match self { send => ~"Send", recv => ~"Recv" @@ -35,11 +35,11 @@ impl direction { } } -type next_state = Option<{state: ~str, tys: ~[@ast::ty]}>; +type next_state = Option<{state: ~str, tys: ~[@ast::Ty]}>; enum message { // name, span, data, current state, next state - message(~str, span, ~[@ast::ty], state, next_state) + message(~str, span, ~[@ast::Ty], state, next_state) } impl message { @@ -78,7 +78,7 @@ enum state { impl state { fn add_message(name: ~str, span: span, - +data: ~[@ast::ty], next: next_state) { + +data: ~[@ast::Ty], next: next_state) { self.messages.push(message(name, span, data, self, next)); } @@ -92,7 +92,7 @@ impl state { } /// Returns the type that is used for the messages. - fn to_ty(cx: ext_ctxt) -> @ast::ty { + fn to_ty(cx: ext_ctxt) -> @ast::Ty { cx.ty_path_ast_builder (path(~[cx.ident_of(self.name)],self.span).add_tys( cx.ty_vars(self.ty_params))) @@ -200,7 +200,7 @@ impl protocol { trait visitor<Tproto, Tstate, Tmessage> { fn visit_proto(proto: protocol, st: &[Tstate]) -> Tproto; fn visit_state(state: state, m: &[Tmessage]) -> Tstate; - fn visit_message(name: ~str, spane: span, tys: &[@ast::ty], + fn visit_message(name: ~str, spane: span, tys: &[@ast::Ty], this: state, next: next_state) -> Tmessage; } diff --git a/src/libsyntax/ext/qquote.rs b/src/libsyntax/ext/qquote.rs index 342743d8c46..af7ffaa73f5 100644 --- a/src/libsyntax/ext/qquote.rs +++ b/src/libsyntax/ext/qquote.rs @@ -1,7 +1,7 @@ use ast::{crate, expr_, mac_invoc, mac_aq, mac_var}; use parse::parser; -use parse::parser::parse_from_source_str; +use parse::parser::{Parser, parse_from_source_str}; use dvec::DVec; use parse::token::ident_interner; @@ -24,7 +24,7 @@ struct gather_item { type aq_ctxt = @{lo: uint, gather: DVec<gather_item>}; enum fragment { from_expr(@ast::expr), - from_ty(@ast::ty) + from_ty(@ast::Ty) } fn ids_ext(cx: ext_ctxt, strs: ~[~str]) -> ~[ast::ident] { @@ -68,7 +68,7 @@ impl @ast::expr: qq_helper { } fn get_fold_fn() -> ~str {~"fold_expr"} } -impl @ast::ty: qq_helper { +impl @ast::Ty: qq_helper { fn span() -> span {self.span} fn visit(cx: aq_ctxt, v: vt<aq_ctxt>) {visit_ty(self, cx, v);} fn extract_mac() -> Option<ast::mac_> { @@ -186,13 +186,13 @@ fn expand_ast(ecx: ext_ctxt, _sp: span, }; } -fn parse_crate(p: parser) -> @ast::crate { p.parse_crate_mod(~[]) } -fn parse_ty(p: parser) -> @ast::ty { p.parse_ty(false) } -fn parse_stmt(p: parser) -> @ast::stmt { p.parse_stmt(~[]) } -fn parse_expr(p: parser) -> @ast::expr { p.parse_expr() } -fn parse_pat(p: parser) -> @ast::pat { p.parse_pat(true) } +fn parse_crate(p: Parser) -> @ast::crate { p.parse_crate_mod(~[]) } +fn parse_ty(p: Parser) -> @ast::Ty { p.parse_ty(false) } +fn parse_stmt(p: Parser) -> @ast::stmt { p.parse_stmt(~[]) } +fn parse_expr(p: Parser) -> @ast::expr { p.parse_expr() } +fn parse_pat(p: Parser) -> @ast::pat { p.parse_pat(true) } -fn parse_item(p: parser) -> @ast::item { +fn parse_item(p: Parser) -> @ast::item { match p.parse_item(~[]) { Some(item) => item, None => fail ~"parse_item: parsing an item failed" @@ -200,7 +200,7 @@ fn parse_item(p: parser) -> @ast::item { } fn finish<T: qq_helper> - (ecx: ext_ctxt, body: ast::mac_body_, f: fn (p: parser) -> T) + (ecx: ext_ctxt, body: ast::mac_body_, f: fn (p: Parser) -> T) -> @ast::expr { let cm = ecx.codemap(); @@ -309,7 +309,7 @@ fn fold_crate(f: ast_fold, &&n: @ast::crate) -> @ast::crate { @f.fold_crate(*n) } fn fold_expr(f: ast_fold, &&n: @ast::expr) -> @ast::expr {f.fold_expr(n)} -fn fold_ty(f: ast_fold, &&n: @ast::ty) -> @ast::ty {f.fold_ty(n)} +fn fold_ty(f: ast_fold, &&n: @ast::Ty) -> @ast::Ty {f.fold_ty(n)} fn fold_item(f: ast_fold, &&n: @ast::item) -> @ast::item { f.fold_item(n).get() //HACK: we know we don't drop items } diff --git a/src/libsyntax/ext/simplext.rs b/src/libsyntax/ext/simplext.rs index e16e1c55349..bec29c9a835 100644 --- a/src/libsyntax/ext/simplext.rs +++ b/src/libsyntax/ext/simplext.rs @@ -6,7 +6,7 @@ use base::*; use fold::*; use ast_util::respan; -use ast::{ident, path, ty, blk_, expr, expr_path, +use ast::{ident, path, Ty, blk_, expr, expr_path, expr_vec, expr_mac, mac_invoc, node_id, expr_index}; export add_new_extension; @@ -29,7 +29,7 @@ enum matchable { match_expr(@expr), match_path(@path), match_ident(ast::spanned<ident>), - match_ty(@ty), + match_ty(@Ty), match_block(ast::blk), match_exact, /* don't bind anything, just verify the AST traversal */ } diff --git a/src/libsyntax/ext/trace_macros.rs b/src/libsyntax/ext/trace_macros.rs index c2d4de1b423..0c7d408db7c 100644 --- a/src/libsyntax/ext/trace_macros.rs +++ b/src/libsyntax/ext/trace_macros.rs @@ -2,7 +2,7 @@ use codemap::span; use ext::base::ext_ctxt; use ast::tt_delim; use parse::lexer::{new_tt_reader, reader}; -use parse::parser::{parser, SOURCE_FILE}; +use parse::parser::{Parser, SOURCE_FILE}; use parse::common::parser_common; fn expand_trace_macros(cx: ext_ctxt, sp: span, @@ -13,7 +13,7 @@ fn expand_trace_macros(cx: ext_ctxt, sp: span, let tt_rdr = new_tt_reader(cx.parse_sess().span_diagnostic, cx.parse_sess().interner, None, tt); let rdr = tt_rdr as reader; - let rust_parser = parser(sess, cfg, rdr.dup(), SOURCE_FILE); + let rust_parser = Parser(sess, cfg, rdr.dup(), SOURCE_FILE); let arg = cx.str_of(rust_parser.parse_ident()); match arg { @@ -21,7 +21,7 @@ fn expand_trace_macros(cx: ext_ctxt, sp: span, ~"false" => cx.set_trace_macros(false), _ => cx.span_fatal(sp, ~"trace_macros! only accepts `true` or `false`") } - let rust_parser = parser(sess, cfg, rdr.dup(), SOURCE_FILE); + let rust_parser = Parser(sess, cfg, rdr.dup(), SOURCE_FILE); let result = rust_parser.parse_expr(); base::mr_expr(result) } diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index 16e3454ca2c..17122b85fb3 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -1,9 +1,9 @@ // Earley-like parser for macros. use parse::token; -use parse::token::{token, EOF, to_str, nonterminal}; +use parse::token::{Token, EOF, to_str, nonterminal}; use parse::lexer::*; //resolve bug? //import parse::lexer::{reader, tt_reader, tt_reader_as_reader}; -use parse::parser::{parser,SOURCE_FILE}; +use parse::parser::{Parser, SOURCE_FILE}; //import parse::common::parser_common; use parse::common::*; //resolve bug? use parse::parse_sess; @@ -97,7 +97,7 @@ fn is_some(&&mpu: matcher_pos_up) -> bool { type matcher_pos = ~{ elts: ~[ast::matcher], // maybe should be /&? Need to understand regions. - sep: Option<token>, + sep: Option<Token>, mut idx: uint, mut up: matcher_pos_up, // mutable for swapping only matches: ~[DVec<@named_match>], @@ -122,7 +122,7 @@ fn count_names(ms: &[matcher]) -> uint { } #[allow(non_implicitly_copyable_typarams)] -fn initial_matcher_pos(ms: ~[matcher], sep: Option<token>, lo: uint) +fn initial_matcher_pos(ms: ~[matcher], sep: Option<Token>, lo: uint) -> matcher_pos { let mut match_idx_hi = 0u; for ms.each() |elt| { @@ -345,7 +345,7 @@ fn parse(sess: parse_sess, cfg: ast::crate_cfg, rdr: reader, ms: ~[matcher]) built-in NTs %s or %u other options.", nts, next_eis.len())); } else if (bb_eis.len() == 0u && next_eis.len() == 0u) { - return failure(sp, ~"No rules expected the token " + return failure(sp, ~"No rules expected the token: " + to_str(rdr.interner(), tok)); } else if (next_eis.len() > 0u) { /* Now process the next token */ @@ -354,7 +354,7 @@ fn parse(sess: parse_sess, cfg: ast::crate_cfg, rdr: reader, ms: ~[matcher]) } rdr.next_token(); } else /* bb_eis.len() == 1 */ { - let rust_parser = parser(sess, cfg, rdr.dup(), SOURCE_FILE); + let rust_parser = Parser(sess, cfg, rdr.dup(), SOURCE_FILE); let ei = bb_eis.pop(); match ei.elts[ei.idx].node { @@ -381,7 +381,7 @@ fn parse(sess: parse_sess, cfg: ast::crate_cfg, rdr: reader, ms: ~[matcher]) } } -fn parse_nt(p: parser, name: ~str) -> nonterminal { +fn parse_nt(p: Parser, name: ~str) -> nonterminal { match name { ~"item" => match p.parse_item(~[]) { Some(i) => token::nt_item(i), diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 52369ad7207..31bc375a76d 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -4,7 +4,7 @@ use ast::{ident, matcher_, matcher, match_tok, match_nonterminal, match_seq, tt_delim}; use parse::lexer::{new_tt_reader, reader}; use parse::token::{FAT_ARROW, SEMI, LBRACE, RBRACE, nt_matchers, nt_tt}; -use parse::parser::{parser, SOURCE_FILE}; +use parse::parser::{Parser, SOURCE_FILE}; use macro_parser::{parse, parse_or_else, success, failure, named_match, matched_seq, matched_nonterminal, error}; use std::map::HashMap; @@ -86,7 +86,7 @@ fn add_new_extension(cx: ext_ctxt, sp: span, name: ident, // rhs has holes ( `$id` and `$(...)` that need filled) let trncbr = new_tt_reader(s_d, itr, Some(named_matches), ~[rhs]); - let p = parser(cx.parse_sess(), cx.cfg(), + let p = Parser(cx.parse_sess(), cx.cfg(), trncbr as reader, SOURCE_FILE); let e = p.parse_expr(); return mr_expr(e); @@ -111,4 +111,4 @@ fn add_new_extension(cx: ext_ctxt, sp: span, name: ident, name: *cx.parse_sess().interner.get(name), ext: expr_tt({expander: exp, span: Some(sp)}) }); -} \ No newline at end of file +} diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs index a8a41cca6cb..238f9db6ac5 100644 --- a/src/libsyntax/ext/tt/transcribe.rs +++ b/src/libsyntax/ext/tt/transcribe.rs @@ -2,8 +2,7 @@ use diagnostic::span_handler; use ast::{token_tree, tt_delim, tt_tok, tt_seq, tt_nonterminal,ident}; use macro_parser::{named_match, matched_seq, matched_nonterminal}; use codemap::span; -use parse::token::{EOF, INTERPOLATED, IDENT, token, nt_ident, - ident_interner}; +use parse::token::{EOF, INTERPOLATED, IDENT, Token, nt_ident, ident_interner}; use std::map::HashMap; export tt_reader, new_tt_reader, dup_tt_reader, tt_next_token; @@ -19,7 +18,7 @@ type tt_frame = @{ readme: ~[ast::token_tree], mut idx: uint, dotdotdoted: bool, - sep: Option<token>, + sep: Option<Token>, up: tt_frame_up, }; @@ -32,7 +31,7 @@ type tt_reader = @{ mut repeat_idx: ~[uint], mut repeat_len: ~[uint], /* cached: */ - mut cur_tok: token, + mut cur_tok: Token, mut cur_span: span }; @@ -134,7 +133,7 @@ fn lockstep_iter_size(t: token_tree, r: tt_reader) -> lis { } -fn tt_next_token(&&r: tt_reader) -> {tok: token, sp: span} { +fn tt_next_token(&&r: tt_reader) -> {tok: Token, sp: span} { let ret_val = { tok: r.cur_tok, sp: r.cur_span }; while r.cur.idx >= r.cur.readme.len() { /* done with this set; pop or repeat? */ |
