about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorJakub Wieczorek <jakubw@jakubw.net>2012-12-08 20:22:43 +0000
committerGraydon Hoare <graydon@mozilla.com>2012-12-17 16:50:40 -0800
commit1968cb315af9d128ee4457738fddd1eba275277f (patch)
tree99dc401a2713e3502c9b53333b74767adad53e98 /src/libsyntax
parent5bf7ba077330c4cdb75802a4ca2497af24d21c4e (diff)
downloadrust-1968cb315af9d128ee4457738fddd1eba275277f.tar.gz
rust-1968cb315af9d128ee4457738fddd1eba275277f.zip
Add support for destructuring vectors in match expressions
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/ast.rs1
-rw-r--r--src/libsyntax/ast_util.rs8
-rw-r--r--src/libsyntax/fold.rs6
-rw-r--r--src/libsyntax/parse/parser.rs40
-rw-r--r--src/libsyntax/print/pprust.rs10
-rw-r--r--src/libsyntax/visit.rs10
6 files changed, 73 insertions, 2 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 444f90c7f04..351b2995471 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -389,6 +389,7 @@ enum pat_ {
     pat_region(@pat), // borrowed pointer pattern
     pat_lit(@expr),
     pat_range(@expr, @expr),
+    pat_vec(~[@pat], Option<@pat>)
 }
 
 #[auto_serialize]
diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs
index ef7bd1d8928..294a66166fa 100644
--- a/src/libsyntax/ast_util.rs
+++ b/src/libsyntax/ast_util.rs
@@ -593,6 +593,14 @@ fn walk_pat(pat: @pat, it: fn(@pat)) {
         pat_box(s) | pat_uniq(s) | pat_region(s) => {
             walk_pat(s, it)
         }
+        pat_vec(elts, tail) => {
+            for elts.each |p| {
+                walk_pat(*p, it)
+            }
+            do option::iter(&tail) |tail| {
+                walk_pat(*tail, it)
+            }
+        }
         pat_wild | pat_lit(_) | pat_range(_, _) | pat_ident(_, _, _) |
         pat_enum(_, _) => {
         }
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index 93845f3dbb8..0b1ff4f56ec 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -356,7 +356,11 @@ fn noop_fold_pat(p: pat_, fld: ast_fold) -> pat_ {
           pat_region(inner) => pat_region(fld.fold_pat(inner)),
           pat_range(e1, e2) => {
             pat_range(fld.fold_expr(e1), fld.fold_expr(e2))
-          }
+          },
+          pat_vec(elts, tail) => pat_vec(
+            vec::map(elts, |x| fld.fold_pat(*x)),
+            option::map(&tail, |tail| fld.fold_pat(*tail))
+          )
         };
 }
 
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 47f65ed2f8d..50ed0df28a0 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -1794,6 +1794,39 @@ impl Parser {
         };
     }
 
+    fn parse_pat_vec_elements(refutable: bool) -> (~[@pat], Option<@pat>) {
+        let mut elements = ~[];
+        let mut tail = None;
+        let mut first = true;
+
+        while self.token != token::RBRACKET {
+            if first { first = false; }
+            else { self.expect(token::COMMA); }
+
+            let mut is_tail = false;
+            if self.token == token::DOTDOT {
+                self.bump();
+                is_tail = true;
+            }
+
+            let subpat = self.parse_pat(refutable);
+            if is_tail {
+                match subpat {
+                    @{ node: pat_wild, _ } => (),
+                    @{ node: pat_ident(_, _, _), _ } => (),
+                    @{ span, _ } => self.span_fatal(
+                        span, ~"expected an identifier or `_`"
+                    )
+                }
+                tail = Some(subpat);
+                break;
+            }
+
+            elements.push(subpat);
+        }
+        return (elements, tail);
+    }
+
     fn parse_pat_fields(refutable: bool) -> (~[ast::field_pat], bool) {
         let mut fields = ~[];
         let mut etc = false;
@@ -1929,6 +1962,13 @@ impl Parser {
                 pat = pat_tup(fields);
             }
           }
+          token::LBRACKET => {
+            self.bump();
+            let (elements, tail) = self.parse_pat_vec_elements(refutable);
+            hi = self.span.hi;
+            self.expect(token::RBRACKET);
+            pat = ast::pat_vec(elements, tail);
+          }
           copy tok => {
             if !is_ident_or_path(tok)
                 || self.is_keyword(~"true")
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index e977327e919..3b995addd62 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -1641,6 +1641,16 @@ fn print_pat(s: ps, &&pat: @ast::pat, refutable: bool) {
         word(s.s, ~"..");
         print_expr(s, end);
       }
+      ast::pat_vec(elts, tail) => {
+        word(s.s, ~"[");
+        commasep(s, inconsistent, elts, |s, p| print_pat(s, p, refutable));
+        do option::iter(&tail) |tail| {
+            if vec::len(elts) != 0u { word_space(s, ~","); }
+            word(s.s, ~"..");
+            print_pat(s, *tail, refutable);
+        }
+        word(s.s, ~"]");
+      }
     }
     (s.ann.post)(ann_node);
 }
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index 7b406564114..9a47edfeb05 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -251,7 +251,15 @@ fn visit_pat<E>(p: @pat, e: E, v: vt<E>) {
         (v.visit_expr)(e1, e, v);
         (v.visit_expr)(e2, e, v);
       }
-      pat_wild => ()
+      pat_wild => (),
+      pat_vec(elts, tail) => {
+        for elts.each |elt| {
+          (v.visit_pat)(*elt, e, v);
+        }
+        do option::iter(&tail) |tail| {
+          (v.visit_pat)(*tail, e, v);
+        }
+      }
     }
 }