about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorLindsey Kuper <lindsey@rockstargirl.org>2012-07-10 13:44:20 -0700
committerLindsey Kuper <lindsey@rockstargirl.org>2012-07-13 11:16:07 -0700
commitfc9c4c32451dadab4f8a81897e8fc83ae6473d95 (patch)
treed54e7d2d8ecce561fb04375e31516ccaf1521aa0 /src/libsyntax
parentd5563d732dfb4ebbf50ad221d8d4568319210a65 (diff)
downloadrust-fc9c4c32451dadab4f8a81897e8fc83ae6473d95.tar.gz
rust-fc9c4c32451dadab4f8a81897e8fc83ae6473d95.zip
Front-end support for default impls in traits.
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/ast.rs11
-rw-r--r--src/libsyntax/ast_util.rs3
-rw-r--r--src/libsyntax/parse/parser.rs56
-rw-r--r--src/libsyntax/print/pprust.rs10
-rw-r--r--src/libsyntax/visit.rs24
5 files changed, 88 insertions, 16 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index e79e5e2ab77..f79f6cbcae2 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -453,6 +453,15 @@ type ty_method = {ident: ident, attrs: ~[attribute],
                   decl: fn_decl, tps: ~[ty_param], span: span};
 
 #[auto_serialize]
+// A trait method is either required (meaning it doesn't have an
+// implementation, just a signature) or provided (meaning it has a default
+// implementation).
+enum trait_method {
+    required(ty_method),
+    provided(@method),
+}
+
+#[auto_serialize]
 enum int_ty { ty_i, ty_char, ty_i8, ty_i16, ty_i32, ty_i64, }
 
 #[auto_serialize]
@@ -695,7 +704,7 @@ enum item_ {
                /* dtor is optional */
                option<class_dtor>
                ),
-    item_trait(~[ty_param], ~[ty_method]),
+    item_trait(~[ty_param], ~[trait_method]),
     item_impl(~[ty_param], option<@trait_ref> /* trait */,
               @ty /* self */, ~[@method]),
     item_mac(mac),
diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs
index 1e2de4f5bfa..5675ecadf62 100644
--- a/src/libsyntax/ast_util.rs
+++ b/src/libsyntax/ast_util.rs
@@ -511,6 +511,9 @@ fn id_visitor(vfn: fn@(node_id)) -> visit::vt<()> {
         visit_ty_method: fn@(_ty_m: ty_method) {
         },
 
+        visit_trait_method: fn@(_ty_m: trait_method) {
+        },
+
         visit_class_item: fn@(c: @class_member) {
             alt c.node {
               instance_var(_, _, _, id,_) {
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index e1f3eb3217c..5a1eb7636ba 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -42,14 +42,14 @@ import ast::{_mod, add, alt_check, alt_exhaustive, arg, arm, attribute,
              mtc_rep, mtc_tok, mul, mutability, neg, noreturn, not, pat,
              pat_box, pat_enum, pat_ident, pat_lit, pat_range, pat_rec,
              pat_tup, pat_uniq, pat_wild, path, private, proto, proto_any,
-             proto_bare, proto_block, proto_box, proto_uniq, public, pure_fn,
-             purity, re_anon, re_named, region, rem, ret_style,
-             return_val, shl, shr, stmt, stmt_decl,
-             stmt_expr, stmt_semi, subtract, token_tree, trait_ref, tt_delim,
-             tt_dotdotdot, tt_flat, tt_interpolate, ty, ty_, ty_bot, ty_box,
-             ty_constr, ty_constr_, ty_constr_arg, ty_field, ty_fn, ty_infer,
-             ty_mac, ty_method, ty_nil, ty_param, ty_path, ty_ptr, ty_rec,
-             ty_rptr, ty_tup, ty_u32, ty_uniq, ty_vec, ty_vstore,
+             proto_bare, proto_block, proto_box, proto_uniq, provided, public,
+             pure_fn, purity, re_anon, re_named, region, rem, required,
+             ret_style, return_val, shl, shr, stmt, stmt_decl, stmt_expr,
+             stmt_semi, subtract, token_tree, trait_method, trait_ref,
+             tt_delim, tt_dotdotdot, tt_flat, tt_interpolate, ty, ty_, ty_bot,
+             ty_box, ty_constr, ty_constr_, ty_constr_arg, ty_field, ty_fn,
+             ty_infer, ty_mac, ty_method, ty_nil, ty_param, ty_path, ty_ptr,
+             ty_rec, ty_rptr, ty_tup, ty_u32, ty_uniq, ty_vec, ty_vstore,
              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,
@@ -275,7 +275,7 @@ class parser {
              constraints: constrs};
     }
 
-    fn parse_ty_methods() -> ~[ty_method] {
+    fn parse_trait_methods() -> ~[trait_method] {
         do self.parse_unspanned_seq(token::LBRACE, token::RBRACE,
                                     seq_sep_none()) |p| {
             let attrs = p.parse_outer_attributes();
@@ -284,12 +284,42 @@ class parser {
             let ident = p.parse_method_name();
             let tps = p.parse_ty_params();
             let d = p.parse_ty_fn_decl(pur), fhi = p.last_span.hi;
-            self.expect(token::SEMI);
-            {ident: ident, attrs: attrs, decl: {purity: pur with d}, tps: tps,
-             span: mk_sp(flo, fhi)}
+            #debug["parse_trait_methods(): trait method ends in %s",
+                   token_to_str(self.reader, self.token)];
+            alt self.token {
+              token::SEMI {
+                self.bump();
+                required({ident: ident, attrs: attrs,
+                          decl: {purity: pur with d}, tps: tps,
+                          span: mk_sp(flo, fhi)})
+              }
+              token::LBRACE {
+                self.bump();
+                let (inner_attrs, body) =
+                    self.parse_inner_attrs_and_block(true);
+                let attrs = vec::append(attrs, inner_attrs);
+                self.eat(token::RBRACE);
+                provided(@{ident: ident,
+                           attrs: attrs,
+                           tps: tps,
+                           decl: d,
+                           body: body,
+                           id: self.get_id(),
+                           span: mk_sp(flo, fhi),
+                           self_id: self.get_id(),
+                           // Provided traits methods always public for now
+                           vis: public})
+              }
+
+              _ { self.fatal("expected ';' or '}` \
+                              but found `"
+                             + token_to_str(self.reader, self.token) + "`");
+                }
+            }
         }
     }
 
+
     fn parse_mt() -> mt {
         let mutbl = self.parse_mutability();
         let t = self.parse_ty(false);
@@ -2127,7 +2157,7 @@ class parser {
         let ident = self.parse_ident();
         self.parse_region_param();
         let tps = self.parse_ty_params();
-        let meths = self.parse_ty_methods();
+        let meths = self.parse_trait_methods();
         (ident, item_trait(tps, meths), none)
     }
 
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index d43ed8043ee..c802e40dd05 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -5,6 +5,7 @@ import pp::{break_offset, word, printer,
             space, zerobreak, hardbreak, breaks, consistent,
             inconsistent, eof};
 import diagnostic;
+import ast::{required, provided};
 import ast_util::operator_prec;
 import dvec::{dvec, extensions};
 import parse::classify::*;
@@ -593,7 +594,7 @@ fn print_item(s: ps, &&item: @ast::item) {
         print_type_params(s, tps);
         word(s.s, " ");
         bopen(s);
-        for methods.each |meth| { print_ty_method(s, meth); }
+        for methods.each |meth| { print_trait_method(s, meth); }
         bclose(s, item.span);
       }
       ast::item_mac({node: ast::mac_invoc_tt(pth, tts), _}) {
@@ -647,6 +648,13 @@ fn print_ty_method(s: ps, m: ast::ty_method) {
     word(s.s, ";");
 }
 
+fn print_trait_method(s: ps, m: ast::trait_method) {
+    alt m {
+      required(ty_m) { print_ty_method(s, ty_m) }
+      provided(m)    { print_method(s, m) }
+    }
+}
+
 fn print_method(s: ps, meth: @ast::method) {
     hardbreak_if_not_bol(s);
     maybe_print_comment(s, meth.span.lo);
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index 5dc42fd4823..be9f76650da 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -62,6 +62,7 @@ type visitor<E> =
       visit_constr: fn@(@path, span, node_id, E, vt<E>),
       visit_fn: fn@(fn_kind, fn_decl, blk, span, node_id, E, vt<E>),
       visit_ty_method: fn@(ty_method, E, vt<E>),
+      visit_trait_method: fn@(trait_method, E, vt<E>),
       visit_class_item: fn@(@class_member, E, vt<E>)};
 
 fn default_visitor<E>() -> visitor<E> {
@@ -81,6 +82,7 @@ fn default_visitor<E>() -> visitor<E> {
           visit_constr: |a,b,c,d,e|visit_constr::<E>(a, b, c, d, e),
           visit_fn: |a,b,c,d,e,f,g|visit_fn::<E>(a, b, c, d, e, f, g),
           visit_ty_method: |a,b,c|visit_ty_method::<E>(a, b, c),
+          visit_trait_method: |a,b,c|visit_trait_method::<E>(a, b, c),
           visit_class_item: |a,b,c|visit_class_item::<E>(a, b, c)};
 }
 
@@ -160,7 +162,7 @@ fn visit_item<E>(i: @item, e: E, v: vt<E>) {
       item_trait(tps, methods) {
         v.visit_ty_params(tps, e, v);
         for methods.each |m| {
-            v.visit_ty_method(m, e, v);
+            v.visit_trait_method(m, e, v);
         }
       }
       item_mac(m) { visit_mac(m, e, v) }
@@ -317,6 +319,17 @@ fn visit_ty_method<E>(m: ty_method, e: E, v: vt<E>) {
     v.visit_ty(m.decl.output, e, v);
 }
 
+fn visit_trait_method<E>(m: trait_method, e: E, v: vt<E>) {
+    alt m {
+      required(ty_m) {
+        v.visit_ty_method(ty_m, e, v)
+      }
+      provided(m) {
+        visit_method_helper(m, e, v)
+      }
+    }
+}
+
 fn visit_block<E>(b: ast::blk, e: E, v: vt<E>) {
     for b.node.view_items.each |vi| { v.visit_view_item(vi, e, v); }
     for b.node.stmts.each |s| { v.visit_stmt(s, e, v); }
@@ -465,6 +478,7 @@ type simple_visitor =
       visit_constr: fn@(@path, span, node_id),
       visit_fn: fn@(fn_kind, fn_decl, blk, span, node_id),
       visit_ty_method: fn@(ty_method),
+      visit_trait_method: fn@(trait_method),
       visit_class_item: fn@(@class_member)};
 
 fn simple_ignore_ty(_t: @ty) {}
@@ -487,6 +501,7 @@ fn default_simple_visitor() -> simple_visitor {
           visit_fn: fn@(_fk: fn_kind, _d: fn_decl, _b: blk, _sp: span,
                         _id: node_id) { },
           visit_ty_method: fn@(_m: ty_method) { },
+          visit_trait_method: fn@(_m: trait_method) { },
           visit_class_item: fn@(_c: @class_member) {}
          };
 }
@@ -546,6 +561,11 @@ fn mk_simple_visitor(v: simple_visitor) -> vt<()> {
         f(ty);
         visit_ty_method(ty, e, v);
     }
+    fn v_trait_method(f: fn@(trait_method), m: trait_method, &&e: (),
+                      v: vt<()>) {
+        f(m);
+        visit_trait_method(m, e, v);
+    }
     fn v_ty_params(f: fn@(~[ty_param]),
                    ps: ~[ty_param],
                    &&e: (), v: vt<()>) {
@@ -596,6 +616,8 @@ fn mk_simple_visitor(v: simple_visitor) -> vt<()> {
                     v_fn(v.visit_fn, a, b, c, d, e, f, g),
                 visit_ty_method: |a,b,c|
                     v_ty_method(v.visit_ty_method, a, b, c),
+                visit_trait_method: |a,b,c|
+                    v_trait_method(v.visit_trait_method, a, b, c),
                 visit_class_item: |a,b,c|
                     v_class_item(v.visit_class_item, a, b, c)
                });