summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2012-08-06 13:15:40 -0700
committerPatrick Walton <pcwalton@mimiga.net>2012-08-06 13:17:42 -0700
commitbff512a90facf2b0064f13737d44c716863f644d (patch)
tree72553ae018b6ed52c06e532346b35f3608d7559d /src/libsyntax
parent1e3143b34e66ca5157b03d3658d64d7c01563186 (diff)
downloadrust-bff512a90facf2b0064f13737d44c716863f644d.tar.gz
rust-bff512a90facf2b0064f13737d44c716863f644d.zip
rustc: Implement functional record update for structs
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/ast.rs4
-rw-r--r--src/libsyntax/fold.rs6
-rw-r--r--src/libsyntax/parse/parser.rs15
-rw-r--r--src/libsyntax/print/pprust.rs13
-rw-r--r--src/libsyntax/visit.rs3
5 files changed, 30 insertions, 11 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 1e43ae219ba..daf3e20f469 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -347,9 +347,7 @@ enum expr_ {
     expr_mac(mac),
 
     // A struct literal expression.
-    //
-    // XXX: Add functional record update.
-    expr_struct(@path, ~[field]),
+    expr_struct(@path, ~[field], option<@expr>),
 
     // A vector literal constructed from one repeated element.
     expr_repeat(@expr /* element */, @expr /* count */, mutability)
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index ec6d7010aa1..71c23ff4fa6 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -478,8 +478,10 @@ fn noop_fold_expr(e: expr_, fld: ast_fold) -> expr_ {
                                          fld.fold_expr(e)),
           expr_assert(e) => expr_assert(fld.fold_expr(e)),
           expr_mac(mac) => expr_mac(fold_mac(mac)),
-          expr_struct(path, fields) => {
-            expr_struct(fld.fold_path(path), vec::map(fields, fold_field))
+          expr_struct(path, fields, maybe_expr) => {
+            expr_struct(fld.fold_path(path),
+                        vec::map(fields, fold_field),
+                        option::map(maybe_expr, |x| fld.fold_expr(x)))
           }
         }
 }
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index a6c4e6c4131..71bd87981bc 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -912,18 +912,27 @@ class parser {
                     self.bump();
                     let mut fields = ~[];
                     vec::push(fields, self.parse_field(token::COLON));
-                    while self.token != token::RBRACE {
+                    while self.token != token::RBRACE &&
+                            !self.is_keyword(~"with") {
                         self.expect(token::COMMA);
-                        if self.token == token::RBRACE {
+                        if self.token == token::RBRACE ||
+                                self.is_keyword(~"with") {
                             // Accept an optional trailing comma.
                             break;
                         }
                         vec::push(fields, self.parse_field(token::COLON));
                     }
 
+                    let base;
+                    if self.eat_keyword(~"with") {
+                        base = some(self.parse_expr());
+                    } else {
+                        base = none;
+                    }
+
                     hi = pth.span.hi;
                     self.expect(token::RBRACE);
-                    ex = expr_struct(pth, fields);
+                    ex = expr_struct(pth, fields, base);
                     return self.mk_pexpr(lo, hi, ex);
                 }
             }
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index c81b8b5335f..eca571b9ccd 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -973,11 +973,20 @@ fn print_expr(s: ps, &&expr: @ast::expr) {
         }
         word(s.s, ~"}");
       }
-      ast::expr_struct(path, fields) => {
+      ast::expr_struct(path, fields, wth) => {
         print_path(s, path, true);
         word(s.s, ~"{");
         commasep_cmnt(s, consistent, fields, print_field, get_span);
-        word(s.s, ~",");
+        alt wth {
+            some(expr) => {
+                if vec::len(fields) > 0u { space(s.s); }
+                ibox(s, indent_unit);
+                word_space(s, ~"with");
+                print_expr(s, expr);
+                end(s);
+            }
+            _ => word(s.s, ~",")
+        }
         word(s.s, ~"}");
       }
       ast::expr_tup(exprs) => {
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index 8d80f9663a3..1c92f26cabe 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -364,9 +364,10 @@ fn visit_expr<E>(ex: @expr, e: E, v: vt<E>) {
         for flds.each |f| { v.visit_expr(f.node.expr, e, v); }
         visit_expr_opt(base, e, v);
       }
-      expr_struct(p, flds) => {
+      expr_struct(p, flds, base) => {
         visit_path(p, e, v);
         for flds.each |f| { v.visit_expr(f.node.expr, e, v); }
+        visit_expr_opt(base, e, v);
       }
       expr_tup(elts) => for elts.each |el| { v.visit_expr(el, e, v); }
       expr_call(callee, args, _) => {