about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorGraydon Hoare <graydon@mozilla.com>2011-02-15 18:16:13 -0800
committerGraydon Hoare <graydon@mozilla.com>2011-02-15 18:16:13 -0800
commitd4bf67dde638fdeea4361daf16bee421d479628e (patch)
tree9ed7ccd2ec3a948f9777d8867b47925d4bd06411 /src
parent370c1ad00eaa0ff95c4e09a6e0545bf833d6668a (diff)
downloadrust-d4bf67dde638fdeea4361daf16bee421d479628e.tar.gz
rust-d4bf67dde638fdeea4361daf16bee421d479628e.zip
Translate record extension.
Diffstat (limited to 'src')
-rw-r--r--src/Makefile1
-rw-r--r--src/comp/middle/trans.rs44
2 files changed, 37 insertions, 8 deletions
diff --git a/src/Makefile b/src/Makefile
index 11c7bee89d2..544075faf15 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -519,6 +519,7 @@ TEST_XFAILS_RUSTC := $(filter-out \
                         readalias.rs \
                         rec.rs \
                         rec-auto.rs \
+                        rec-extend.rs \
                         rec-tup.rs \
                         return-nil.rs \
                         simple-obj.rs \
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index 72a4fe5ca98..7d3f9997437 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -2998,9 +2998,6 @@ fn trans_vec(@block_ctxt cx, vec[@ast.expr] args,
 fn trans_rec(@block_ctxt cx, vec[ast.field] fields,
              option.t[@ast.expr] base, &ast.ann ann) -> result {
 
-    // FIXME: handle presence of a nonempty base.
-    check (base == none[@ast.expr]);
-
     auto bcx = cx;
     auto t = node_ann_type(bcx.fcx.ccx, ann);
     auto llty = type_of(bcx.fcx.ccx, t);
@@ -3011,13 +3008,44 @@ fn trans_rec(@block_ctxt cx, vec[ast.field] fields,
     find_scope_cx(cx).cleanups += clean(bind drop_ty(_, rec_val, t));
     let int i = 0;
 
-    for (ast.field f in fields) {
-        auto e_ty = ty.expr_ty(f.expr);
-        auto src_res = trans_expr(bcx, f.expr);
-        bcx = src_res.bcx;
+    auto base_val = C_nil();
+
+    alt (base) {
+        case (none[@ast.expr]) { }
+        case (some[@ast.expr](?bexp)) {
+            auto base_res = trans_expr(bcx, bexp);
+            bcx = base_res.bcx;
+            base_val = base_res.val;
+        }
+    }
+
+    let vec[ty.field] ty_fields = vec();
+    alt (t.struct) {
+        case (ty.ty_rec(?flds)) { ty_fields = flds; }
+    }
+
+    for (ty.field tf in ty_fields) {
+        auto e_ty = tf.ty;
         auto dst_res = GEP_tup_like(bcx, t, rec_val, vec(0, i));
         bcx = dst_res.bcx;
-        bcx = copy_ty(src_res.bcx, INIT, dst_res.val, src_res.val, e_ty).bcx;
+
+        auto expr_provided = false;
+        auto src_res = res(bcx, C_nil());
+
+        for (ast.field f in fields) {
+            if (_str.eq(f.ident, tf.ident)) {
+                expr_provided = true;
+                src_res = trans_expr(bcx, f.expr);
+            }
+        }
+        if (!expr_provided) {
+            src_res = GEP_tup_like(bcx, t, base_val, vec(0, i));
+            src_res = res(src_res.bcx,
+                          load_scalar_or_boxed(bcx, src_res.val, e_ty));
+        }
+
+        bcx = src_res.bcx;
+        bcx = copy_ty(bcx, INIT, dst_res.val, src_res.val, e_ty).bcx;
         i += 1;
     }
     ret res(bcx, rec_val);