From 7f7f47620eaeaab8e4993e568d2f5c23e1cb6416 Mon Sep 17 00:00:00 2001 From: Michael Sullivan Date: Thu, 2 Aug 2012 16:01:38 -0700 Subject: Implement static typeclass methods. Closes #3132. --- src/libsyntax/ast.rs | 2 ++ src/libsyntax/ast_util.rs | 2 +- src/libsyntax/parse/parser.rs | 54 +++++++++++++++++++++++++++++-------------- src/libsyntax/print/pprust.rs | 50 +++++++++++++++++++++++++++------------ 4 files changed, 75 insertions(+), 33 deletions(-) (limited to 'src/libsyntax') diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 78b1fa0a469..0cc433fdeba 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -71,6 +71,7 @@ type ty_param = {ident: ident, id: node_id, bounds: @~[ty_param_bound]}; #[auto_serialize] enum def { def_fn(def_id, purity), + def_static_method(def_id, purity), def_self(node_id), def_mod(def_id), def_foreign_mod(def_id), @@ -596,6 +597,7 @@ enum ret_style { #[auto_serialize] enum self_ty_ { + sty_static, // no self: static method sty_by_ref, // old by-reference self: `` sty_value, // by-value self: `self` sty_region(@region, mutability), // by-region self: `&self` diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index caaf6cca5b1..7bbdac4db3c 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -53,7 +53,7 @@ fn variant_def_ids(d: def) -> {enm: def_id, var: def_id} { pure fn def_id_of_def(d: def) -> def_id { match d { - def_fn(id, _) | def_mod(id) | + def_fn(id, _) | def_static_method(id, _) | def_mod(id) | def_foreign_mod(id) | def_const(id) | def_variant(_, id) | def_ty(id) | def_ty_param(id, _) | def_use(id) | def_class(id, _) => { diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 52a93a60361..780eff1f757 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -43,20 +43,24 @@ import ast::{_mod, add, alt_check, alt_exhaustive, arg, arm, attribute, match_nonterminal, match_seq, match_tok, method, mode, mt, mul, mutability, neg, noreturn, not, pat, pat_box, pat_enum, pat_ident, pat_lit, pat_range, pat_rec, pat_struct, pat_tup, - pat_uniq, pat_wild, path, private, proto, proto_bare, - proto_block, proto_box, proto_uniq, provided, public, pure_fn, - purity, re_anon, re_named, region, rem, required, ret_style, - return_val, self_ty, shl, shr, stmt, stmt_decl, stmt_expr, - stmt_semi, subtract, sty_box, sty_by_ref, sty_region, sty_uniq, - sty_value, token_tree, trait_method, trait_ref, tt_delim, tt_seq, - tt_tok, tt_nonterminal, tuple_variant_kind, ty, ty_, ty_bot, - ty_box, ty_field, ty_fn, ty_infer, ty_mac, ty_method, ty_nil, - ty_param, ty_param_bound, ty_path, ty_ptr, ty_rec, ty_rptr, - ty_tup, ty_u32, ty_uniq, ty_vec, ty_fixed_length, unchecked_blk, - uniq, unsafe_blk, unsafe_fn, variant, view_item, view_item_, - view_item_export, view_item_import, view_item_use, view_path, - view_path_glob, view_path_list, view_path_simple, visibility, - vstore, vstore_box, vstore_fixed, vstore_slice, vstore_uniq}; + pat_uniq, + pat_wild, path, private, proto, proto_bare, proto_block, + proto_box, proto_uniq, provided, public, pure_fn, purity, + re_anon, re_named, region, rem, required, ret_style, return_val, + self_ty, shl, shr, stmt, stmt_decl, stmt_expr, stmt_semi, + subtract, sty_box, sty_by_ref, sty_region, sty_static, + sty_uniq, sty_value, + token_tree, trait_method, trait_ref, tt_delim, tt_seq, tt_tok, + tt_nonterminal, ty, ty_, ty_bot, ty_box, ty_field, ty_fn, + ty_infer, ty_mac, ty_method, ty_nil, ty_param, ty_param_bound, + ty_path, ty_ptr, + ty_rec, ty_rptr, ty_tup, ty_u32, ty_uniq, ty_vec, + ty_fixed_length, tuple_variant_kind, + unchecked_blk, uniq, unsafe_blk, unsafe_fn, + variant, view_item, view_item_, view_item_export, + view_item_import, view_item_use, view_path, view_path_glob, + view_path_list, view_path_simple, visibility, vstore, vstore_box, + vstore_fixed, vstore_slice, vstore_uniq}; export file_type; export parser; @@ -279,6 +283,9 @@ class parser { seq_sep_none()) |p| { let attrs = p.parse_outer_attributes(); let lo = p.span.lo; + let is_static = p.parse_staticness(); + let static_sty = spanned(lo, p.span.hi, sty_static); + let pur = p.parse_fn_purity(); // NB: at the moment, trait methods are public by default; this // could change. @@ -287,7 +294,8 @@ class parser { let tps = p.parse_ty_params(); let d = p.parse_ty_fn_decl(pur); let hi = p.last_span.hi; - let self_ty = spanned(lo, hi, sty_by_ref); // XXX: Wrong. + let self_ty = if is_static { static_sty } else + { spanned(lo, hi, sty_by_ref) }; // XXX: Wrong. debug!{"parse_trait_methods(): trait method signature ends in \ `%s`", token_to_str(p.reader, p.token)}; @@ -2379,15 +2387,24 @@ class parser { fn parse_method(pr: visibility) -> @method { let attrs = self.parse_outer_attributes(); - let lo = self.span.lo, pur = self.parse_fn_purity(); + let lo = self.span.lo; + + let is_static = self.parse_staticness(); + let static_sty = spanned(lo, self.span.hi, sty_static); + + let pur = self.parse_fn_purity(); let ident = self.parse_method_name(); let tps = self.parse_ty_params(); let (self_ty, decl, _) = do self.parse_fn_decl_with_self(pur) |p| { p.parse_arg() }; + // XXX: interaction between staticness, self_ty is broken now + let self_ty = if is_static { static_sty} else { self_ty }; + let (inner_attrs, body) = self.parse_inner_attrs_and_block(true); let attrs = vec::append(attrs, inner_attrs); - @{ident: ident, attrs: attrs, tps: tps, self_ty: self_ty, decl: decl, + @{ident: ident, attrs: attrs, + tps: tps, self_ty: self_ty, decl: decl, body: body, id: self.get_id(), span: mk_sp(lo, body.span.hi), self_id: self.get_id(), vis: pr} } @@ -2689,6 +2706,9 @@ class parser { else if self.eat_keyword(~"priv") { private } else { inherited } } + fn parse_staticness() -> bool { + self.eat_keyword(~"static") + } fn parse_mod_items(term: token::token, +first_item_attrs: ~[attribute]) -> _mod { diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index db62637a673..1965ea73186 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -144,7 +144,7 @@ fn fun_to_str(decl: ast::fn_decl, name: ast::ident, params: ~[ast::ty_param]) -> ~str { let buffer = io::mem_buffer(); let s = rust_printer(io::mem_buffer_writer(buffer)); - print_fn(s, decl, name, params); + print_fn(s, decl, name, params, none); end(s); // Close the head box end(s); // Close the outer box eof(s.s); @@ -400,7 +400,7 @@ fn print_type_ex(s: ps, &&ty: @ast::ty, print_colons: bool) { pclose(s); } ast::ty_fn(proto, bounds, d) => { - print_ty_fn(s, some(proto), bounds, d, none, none); + print_ty_fn(s, some(proto), bounds, d, none, none, none); } ast::ty_path(path, _) => print_path(s, path, print_colons), ast::ty_fixed_length(t, v) => { @@ -425,7 +425,7 @@ fn print_foreign_item(s: ps, item: @ast::foreign_item) { print_outer_attributes(s, item.attrs); match item.node { ast::foreign_item_fn(decl, typarams) => { - print_fn(s, decl, item.ident, typarams); + print_fn(s, decl, item.ident, typarams, none); end(s); // end head-ibox word(s.s, ~";"); end(s); // end the outer fn box @@ -454,7 +454,7 @@ fn print_item(s: ps, &&item: @ast::item) { } ast::item_fn(decl, typarams, body) => { - print_fn(s, decl, item.ident, typarams); + print_fn(s, decl, item.ident, typarams, none); word(s.s, ~" "); print_block_with_attrs(s, body, item.attrs); } @@ -722,7 +722,8 @@ fn print_ty_method(s: ps, m: ast::ty_method) { hardbreak_if_not_bol(s); maybe_print_comment(s, m.span.lo); print_outer_attributes(s, m.attrs); - print_ty_fn(s, none, @~[], m.decl, some(m.ident), some(m.tps)); + print_ty_fn(s, none, @~[], m.decl, some(m.ident), some(m.tps), + some(m.self_ty.node)); word(s.s, ~";"); } @@ -737,7 +738,7 @@ fn print_method(s: ps, meth: @ast::method) { hardbreak_if_not_bol(s); maybe_print_comment(s, meth.span.lo); print_outer_attributes(s, meth.attrs); - print_fn(s, meth.decl, meth.ident, meth.tps); + print_fn(s, meth.decl, meth.ident, meth.tps, some(meth.self_ty.node)); word(s.s, ~" "); print_block_with_attrs(s, meth.body, meth.attrs); } @@ -1150,8 +1151,7 @@ fn print_expr(s: ps, &&expr: @ast::expr) { cbox(s, indent_unit); // head-box, will be closed by print-block at start ibox(s, 0u); - print_purity(s, decl.purity); - word(s.s, proto_to_str(proto)); + word(s.s, fn_header_info_to_str(none, decl.purity, some(proto))); print_fn_args_and_ret(s, decl, *cap_clause); space(s.s); print_block(s, body); @@ -1455,11 +1455,9 @@ fn print_pat(s: ps, &&pat: @ast::pat) { } fn print_fn(s: ps, decl: ast::fn_decl, name: ast::ident, - typarams: ~[ast::ty_param]) { - match decl.purity { - ast::impure_fn => head(s, ~"fn"), - _ => head(s, purity_to_str(decl.purity) + ~" fn") - } + typarams: ~[ast::ty_param], + opt_self_ty: option) { + head(s, fn_header_info_to_str(opt_self_ty, decl.purity, none)); word(s.s, *name); print_type_params(s, typarams); print_fn_args_and_ret(s, decl, ~[]); @@ -1667,9 +1665,10 @@ fn print_arg(s: ps, input: ast::arg) { fn print_ty_fn(s: ps, opt_proto: option, bounds: @~[ast::ty_param_bound], decl: ast::fn_decl, id: option, - tps: option<~[ast::ty_param]>) { + tps: option<~[ast::ty_param]>, + opt_self_ty: option) { ibox(s, indent_unit); - word(s.s, opt_proto_to_str(opt_proto)); + word(s.s, fn_header_info_to_str(opt_self_ty, decl.purity, opt_proto)); print_bounds(s, bounds); match id { some(id) => { word(s.s, ~" "); word(s.s, *id); } _ => () } match tps { some(tps) => print_type_params(s, tps), _ => () } @@ -1869,6 +1868,27 @@ fn next_comment(s: ps) -> option { } } +fn fn_header_info_to_str(opt_sty: option, + purity: ast::purity, + opt_p: option) -> ~str { + let mut s = match opt_sty { + some(ast::sty_static) => ~"static ", + _ => ~ "" + }; + + match purity { + ast::impure_fn => { } + _ => { + str::push_str(s, purity_to_str(purity)); + str::push_char(s, ' '); + } + } + + str::push_str(s, opt_proto_to_str(opt_p)); + + return s; +} + fn opt_proto_to_str(opt_p: option) -> ~str { match opt_p { none => ~"fn", -- cgit 1.4.1-3-g733a5