about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2012-11-30 11:18:25 -0800
committerPatrick Walton <pcwalton@mimiga.net>2012-11-30 20:41:46 -0800
commitf34833abfce74cf178c0589a4b7cf5fba9d2a2db (patch)
tree08943a296d704c10303fbd6b33b3d7e8fb704ac6 /src/libsyntax
parent54ae377ec26ed47bbb627bdcb58bb10658cf03c4 (diff)
downloadrust-f34833abfce74cf178c0589a4b7cf5fba9d2a2db.tar.gz
rust-f34833abfce74cf178c0589a4b7cf5fba9d2a2db.zip
librustc: Make `a.b()` always a method call. r=nmatsakis
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/ast.rs3
-rw-r--r--src/libsyntax/fold.rs7
-rw-r--r--src/libsyntax/parse/classify.rs10
-rw-r--r--src/libsyntax/parse/parser.rs48
-rw-r--r--src/libsyntax/print/pprust.rs89
-rw-r--r--src/libsyntax/visit.rs5
6 files changed, 121 insertions, 41 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 1ffe741d255..9dab40ba991 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -645,7 +645,7 @@ impl blk_check_mode : cmp::Eq {
 #[auto_serialize]
 #[auto_deserialize]
 type expr = {id: node_id, callee_id: node_id, node: expr_, span: span};
-// Extra node ID is only used for index, assign_op, unary, binary
+// Extra node ID is only used for index, assign_op, unary, binary, method call
 
 #[auto_serialize]
 #[auto_deserialize]
@@ -659,6 +659,7 @@ enum expr_ {
     expr_vec(~[@expr], mutability),
     expr_rec(~[field], Option<@expr>),
     expr_call(@expr, ~[@expr], bool), // True iff last argument is a block
+    expr_method_call(@expr, ident, ~[@Ty], ~[@expr], bool), // Ditto
     expr_tup(~[@expr]),
     expr_binary(binop, @expr, @expr),
     expr_unary(unop, @expr),
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index 9a1f3e7f04e..03a9729477a 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -409,6 +409,13 @@ fn noop_fold_expr(e: expr_, fld: ast_fold) -> expr_ {
                       fld.map_exprs(|x| fld.fold_expr(x), args),
                       blk)
           }
+          expr_method_call(f, i, tps, args, blk) => {
+            expr_method_call(fld.fold_expr(f),
+                             fld.fold_ident(i),
+                             vec::map(tps, |x| fld.fold_ty(*x)),
+                             fld.map_exprs(|x| fld.fold_expr(x), args),
+                             blk)
+          }
           expr_binary(binop, lhs, rhs) => {
             expr_binary(binop, fld.fold_expr(lhs), fld.fold_expr(rhs))
           }
diff --git a/src/libsyntax/parse/classify.rs b/src/libsyntax/parse/classify.rs
index 0d370525d17..e0210feb9de 100644
--- a/src/libsyntax/parse/classify.rs
+++ b/src/libsyntax/parse/classify.rs
@@ -6,9 +6,13 @@ use ast_util::operator_prec;
 
 fn expr_requires_semi_to_be_stmt(e: @ast::expr) -> bool {
     match e.node {
-      ast::expr_if(*) | ast::expr_match(*) | ast::expr_block(_)
-      | ast::expr_while(*) | ast::expr_loop(*)
-      | ast::expr_call(_, _, true) => false,
+      ast::expr_if(*)
+      | ast::expr_match(*)
+      | ast::expr_block(_)
+      | ast::expr_while(*)
+      | ast::expr_loop(*)
+      | ast::expr_call(_, _, true)
+      | ast::expr_method_call(_, _, _, _, true) => false,
       _ => true
     }
 }
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index d8fd58b3d50..7cf279d0d81 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -34,10 +34,10 @@ use ast::{_mod, add, arg, arm, attribute,
              expr_call, expr_cast, expr_copy, expr_do_body, expr_fail,
              expr_field, expr_fn, expr_fn_block, expr_if, expr_index,
              expr_lit, expr_log, expr_loop, expr_loop_body, expr_mac,
-             expr_paren, expr_path, expr_rec, expr_repeat, expr_ret,
-             expr_swap, expr_struct, expr_tup, expr_unary, expr_unary_move,
-             expr_vec, expr_vstore, expr_vstore_mut_box, expr_while,
-             extern_fn, field, fn_decl,
+             expr_method_call, expr_paren, expr_path, expr_rec, expr_repeat,
+             expr_ret, expr_swap, expr_struct, expr_tup, expr_unary,
+             expr_unary_move, expr_vec, expr_vstore, expr_vstore_mut_box,
+             expr_while, extern_fn, field, fn_decl,
              foreign_item, foreign_item_const, foreign_item_fn, foreign_mod,
              ident, impure_fn, infer, inherited,
              item, item_, item_class, item_const, item_enum, item_fn,
@@ -1212,8 +1212,26 @@ impl Parser {
                         self.expect(token::LT);
                         self.parse_seq_to_gt(Some(token::COMMA),
                                              |p| p.parse_ty(false))
-                    } else { ~[] };
-                    e = self.mk_expr(lo, hi, expr_field(e, i, tys));
+                    } else {
+                        ~[]
+                    };
+
+                    // expr.f() method call
+                    match copy self.token {
+                        token::LPAREN if self.permits_call() => {
+                            let es = self.parse_unspanned_seq(
+                                token::LPAREN, token::RPAREN,
+                                seq_sep_trailing_disallowed(token::COMMA),
+                                |p| p.parse_expr());
+                            hi = self.span.hi;
+
+                            let nd = expr_method_call(e, i, tys, es, false);
+                            e = self.mk_expr(lo, hi, move nd);
+                        }
+                        _ => {
+                            e = self.mk_expr(lo, hi, expr_field(e, i, tys));
+                        }
+                    }
                   }
                   _ => self.unexpected()
                 }
@@ -1674,7 +1692,23 @@ impl Parser {
             @{node: expr_call(f, args, true),
               .. *e}
           }
-          expr_path(*) | expr_field(*) | expr_call(*) | expr_paren(*) => {
+          expr_method_call(f, i, tps, args, false) => {
+            let block = self.parse_lambda_block_expr();
+            let last_arg = self.mk_expr(block.span.lo, block.span.hi,
+                                    ctor(block));
+            let args = vec::append(args, ~[last_arg]);
+            @{node: expr_method_call(f, i, tps, args, true),
+              .. *e}
+          }
+          expr_field(f, i, tps) => {
+            let block = self.parse_lambda_block_expr();
+            let last_arg = self.mk_expr(block.span.lo, block.span.hi,
+                                    ctor(block));
+            @{node: expr_method_call(f, i, tps, ~[last_arg], true),
+              .. *e}
+          }
+          expr_path(*) | expr_call(*) | expr_method_call(*) |
+          expr_paren(*) => {
             let block = self.parse_lambda_block_expr();
             let last_arg = self.mk_expr(block.span.lo, block.span.hi,
                                     ctor(block));
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 5ad3c051c59..e13c6da403f 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -1041,6 +1041,50 @@ fn print_expr_vstore(s: ps, t: ast::expr_vstore) {
     }
 }
 
+fn print_call_pre(s: ps,
+                  has_block: bool,
+                  base_args: &mut ~[@ast::expr])
+               -> Option<@ast::expr> {
+    if has_block {
+        let blk_arg = base_args.pop();
+        match blk_arg.node {
+          ast::expr_loop_body(_) => { head(s, ~"for"); }
+          ast::expr_do_body(_) => { head(s, ~"do"); }
+          _ => {}
+        }
+        Some(blk_arg)
+    } else {
+        None
+    }
+}
+
+fn print_call_post(s: ps,
+                   has_block: bool,
+                   blk: &Option<@ast::expr>,
+                   base_args: &mut ~[@ast::expr]) {
+    if !has_block || base_args.is_not_empty() {
+        popen(s);
+        commasep_exprs(s, inconsistent, *base_args);
+        pclose(s);
+    }
+    if has_block {
+        nbsp(s);
+        match blk.get().node {
+          // need to handle closures specifically
+          ast::expr_do_body(e) | ast::expr_loop_body(e) => {
+            end(s); // we close our head box; closure
+                    // will create it's own.
+            print_expr(s, e);
+            end(s); // close outer box, as closures don't
+          }
+          _ => {
+            // not sure if this can happen.
+            print_expr(s, blk.get());
+          }
+        }
+    }
+}
+
 fn print_expr(s: ps, &&expr: @ast::expr) {
     fn print_field(s: ps, field: ast::field) {
         ibox(s, indent_unit);
@@ -1135,38 +1179,23 @@ fn print_expr(s: ps, &&expr: @ast::expr) {
         pclose(s);
       }
       ast::expr_call(func, args, has_block) => {
-        let mut base_args = args;
-        let blk = if has_block {
-            let blk_arg = base_args.pop();
-            match blk_arg.node {
-              ast::expr_loop_body(_) => { head(s, ~"for"); }
-              ast::expr_do_body(_) => { head(s, ~"do"); }
-              _ => {}
-            }
-            Some(blk_arg)
-        } else { None };
+        let mut base_args = copy args;
+        let blk = print_call_pre(s, has_block, &mut base_args);
         print_expr(s, func);
-        if !has_block || base_args.is_not_empty() {
-            popen(s);
-            commasep_exprs(s, inconsistent, base_args);
-            pclose(s);
-        }
-        if has_block {
-            nbsp(s);
-            match blk.get().node {
-              // need to handle closures specifically
-              ast::expr_do_body(e) | ast::expr_loop_body(e) => {
-                end(s); // we close our head box; closure
-                        // will create it's own.
-                print_expr(s, e);
-                end(s); // close outer box, as closures don't
-              }
-              _ => {
-                // not sure if this can happen.
-                print_expr(s, blk.get());
-              }
-            }
+        print_call_post(s, has_block, &blk, &mut base_args);
+      }
+      ast::expr_method_call(func, ident, tys, args, has_block) => {
+        let mut base_args = copy args;
+        let blk = print_call_pre(s, has_block, &mut base_args);
+        print_expr(s, func);
+        word(s.s, ~".");
+        print_ident(s, ident);
+        if vec::len(tys) > 0u {
+            word(s.s, ~"::<");
+            commasep(s, inconsistent, tys, print_type);
+            word(s.s, ~">");
         }
+        print_call_post(s, has_block, &blk, &mut base_args);
       }
       ast::expr_binary(op, lhs, rhs) => {
         print_expr(s, lhs);
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index fbb1bc91172..bac651ef36c 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -408,6 +408,11 @@ fn visit_expr<E>(ex: @expr, e: E, v: vt<E>) {
         visit_exprs(args, e, v);
         (v.visit_expr)(callee, e, v);
       }
+      expr_method_call(callee, _, tys, args, _) => {
+        visit_exprs(args, e, v);
+        for tys.each |tp| { (v.visit_ty)(*tp, e, v); }
+        (v.visit_expr)(callee, e, v);
+      }
       expr_binary(_, a, b) => {
         (v.visit_expr)(a, e, v); (v.visit_expr)(b, e, v);
       }