diff options
| author | Graydon Hoare <[email protected]> | 2010-12-08 14:50:47 -0800 |
|---|---|---|
| committer | Graydon Hoare <[email protected]> | 2010-12-08 14:50:47 -0800 |
| commit | 68af077e8192a6a1b18778b97449ad695a4ecffb (patch) | |
| tree | d5a7bb274b328239429bdb0c40cf1675f01c3d1a | |
| parent | Fix missing case in resolve, un-XFAIL rec-tup.rs. (diff) | |
| download | rust-68af077e8192a6a1b18778b97449ad695a4ecffb.tar.xz rust-68af077e8192a6a1b18778b97449ad695a4ecffb.zip | |
Implement binop= forms. Un-XFAIL bitwise.rs.
| -rw-r--r-- | src/Makefile | 1 | ||||
| -rw-r--r-- | src/comp/front/ast.rs | 1 | ||||
| -rw-r--r-- | src/comp/front/lexer.rs | 2 | ||||
| -rw-r--r-- | src/comp/front/parser.rs | 22 | ||||
| -rw-r--r-- | src/comp/lib/llvm.rs | 20 | ||||
| -rw-r--r-- | src/comp/middle/fold.rs | 19 | ||||
| -rw-r--r-- | src/comp/middle/trans.rs | 155 | ||||
| -rw-r--r-- | src/comp/middle/typeck.rs | 21 |
8 files changed, 128 insertions, 113 deletions
diff --git a/src/Makefile b/src/Makefile index 041084c3..cb950eb7 100644 --- a/src/Makefile +++ b/src/Makefile @@ -522,6 +522,7 @@ TEST_XFAILS_SELF := $(filter-out \ arith-0.rs \ arith-1.rs \ arith-2.rs \ + bitwise.rs \ bool-not.rs \ box.rs \ box-in-tup.rs \ diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs index e7695e0b..a37fd191 100644 --- a/src/comp/front/ast.rs +++ b/src/comp/front/ast.rs @@ -145,6 +145,7 @@ tag expr_ { expr_alt(@expr, vec[arm], ann); expr_block(block, ann); expr_assign(@expr /* TODO: @expr|is_lval */, @expr, ann); + expr_assign_op(binop, @expr /* TODO: @expr|is_lval */, @expr, ann); expr_field(@expr, ident, ann); expr_index(@expr, @expr, ann); expr_name(name, option.t[def], ann); diff --git a/src/comp/front/lexer.rs b/src/comp/front/lexer.rs index 0506ce6c..42a5e610 100644 --- a/src/comp/front/lexer.rs +++ b/src/comp/front/lexer.rs @@ -426,7 +426,7 @@ impure fn next_token(reader rdr) -> token.token { impure fn binop(reader rdr, token.binop op) -> token.token { rdr.bump(); - if (rdr.next() == '=') { + if (rdr.curr() == '=') { rdr.bump(); ret token.BINOPEQ(op); } else { diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index 879cb2c0..d8d7ca4e 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -714,6 +714,26 @@ impure fn parse_assign_expr(parser p) -> @ast.expr { ret @spanned(lo, rhs.span, ast.expr_assign(lhs, rhs, ast.ann_none)); } + case (token.BINOPEQ(?op)) { + p.bump(); + auto rhs = parse_expr(p); + auto aop = ast.add; + alt (op) { + case (token.PLUS) { aop = ast.add; } + case (token.MINUS) { aop = ast.sub; } + case (token.STAR) { aop = ast.mul; } + case (token.SLASH) { aop = ast.div; } + case (token.PERCENT) { aop = ast.rem; } + case (token.CARET) { aop = ast.bitxor; } + case (token.AND) { aop = ast.bitand; } + case (token.OR) { aop = ast.bitor; } + case (token.LSL) { aop = ast.lsl; } + case (token.LSR) { aop = ast.lsr; } + case (token.ASR) { aop = ast.asr; } + } + ret @spanned(lo, rhs.span, + ast.expr_assign_op(aop, lhs, rhs, ast.ann_none)); + } case (_) { /* fall through */ } } ret lhs; @@ -1080,6 +1100,8 @@ fn stmt_ends_with_semi(@ast.stmt stmt) -> bool { case (ast.expr_alt(_,_,_)) { ret false; } case (ast.expr_block(_,_)) { ret false; } case (ast.expr_assign(_,_,_)) { ret true; } + case (ast.expr_assign_op(_,_,_,_)) + { ret true; } case (ast.expr_field(_,_,_)) { ret true; } case (ast.expr_index(_,_,_)) { ret true; } case (ast.expr_name(_,_,_)) { ret true; } diff --git a/src/comp/lib/llvm.rs b/src/comp/lib/llvm.rs index c5236725..1fc19e5c 100644 --- a/src/comp/lib/llvm.rs +++ b/src/comp/lib/llvm.rs @@ -45,16 +45,16 @@ const uint LLVMX86FastcallCallConv = 65u; // Consts for the LLVM IntPredicate type, pre-cast to uint. // FIXME: as above. -const uint LLVMIntEQ = 32; -const uint LLVMIntNE = 33; -const uint LLVMIntUGT = 34; -const uint LLVMIntUGE = 35; -const uint LLVMIntULT = 36; -const uint LLVMIntULE = 37; -const uint LLVMIntSGT = 38; -const uint LLVMIntSGE = 39; -const uint LLVMIntSLT = 40; -const uint LLVMIntSLE = 41; +const uint LLVMIntEQ = 32u; +const uint LLVMIntNE = 33u; +const uint LLVMIntUGT = 34u; +const uint LLVMIntUGE = 35u; +const uint LLVMIntULT = 36u; +const uint LLVMIntULE = 37u; +const uint LLVMIntSGT = 38u; +const uint LLVMIntSGE = 39u; +const uint LLVMIntSLT = 40u; +const uint LLVMIntSLE = 41u; native mod llvm = llvm_lib { diff --git a/src/comp/middle/fold.rs b/src/comp/middle/fold.rs index 24e23e92..54492305 100644 --- a/src/comp/middle/fold.rs +++ b/src/comp/middle/fold.rs @@ -115,6 +115,11 @@ type ast_fold[ENV] = ann a) -> @expr) fold_expr_assign, (fn(&ENV e, &span sp, + ast.binop, + @expr lhs, @expr rhs, + ann a) -> @expr) fold_expr_assign_op, + + (fn(&ENV e, &span sp, @expr e, ident i, ann a) -> @expr) fold_expr_field, @@ -465,6 +470,12 @@ fn fold_expr[ENV](&ENV env, ast_fold[ENV] fld, &@expr e) -> @expr { ret fld.fold_expr_assign(env_, e.span, llhs, rrhs, t); } + case (ast.expr_assign_op(?op, ?lhs, ?rhs, ?t)) { + auto llhs = fold_expr(env_, fld, lhs); + auto rrhs = fold_expr(env_, fld, rhs); + ret fld.fold_expr_assign_op(env_, e.span, op, llhs, rrhs, t); + } + case (ast.expr_field(?e, ?i, ?t)) { auto ee = fold_expr(env_, fld, e); ret fld.fold_expr_field(env_, e.span, ee, i, t); @@ -790,6 +801,12 @@ fn identity_fold_expr_assign[ENV](&ENV env, &span sp, ret @respan(sp, ast.expr_assign(lhs, rhs, a)); } +fn identity_fold_expr_assign_op[ENV](&ENV env, &span sp, ast.binop op, + @expr lhs, @expr rhs, ann a) + -> @expr { + ret @respan(sp, ast.expr_assign_op(op, lhs, rhs, a)); +} + fn identity_fold_expr_field[ENV](&ENV env, &span sp, @expr e, ident i, ann a) -> @expr { ret @respan(sp, ast.expr_field(e, i, a)); @@ -986,6 +1003,8 @@ fn new_identity_fold[ENV]() -> ast_fold[ENV] { fold_expr_alt = bind identity_fold_expr_alt[ENV](_,_,_,_,_), fold_expr_block = bind identity_fold_expr_block[ENV](_,_,_,_), fold_expr_assign = bind identity_fold_expr_assign[ENV](_,_,_,_,_), + fold_expr_assign_op + = bind identity_fold_expr_assign_op[ENV](_,_,_,_,_,_), fold_expr_field = bind identity_fold_expr_field[ENV](_,_,_,_,_), fold_expr_index = bind identity_fold_expr_index[ENV](_,_,_,_,_), fold_expr_name = bind identity_fold_expr_name[ENV](_,_,_,_,_), diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index d49443ef..c5cc2063 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1031,6 +1031,42 @@ impure fn trans_unary(@block_ctxt cx, ast.unop op, fail; } +fn trans_eager_binop(@block_ctxt cx, ast.binop op, + ValueRef lhs, ValueRef rhs) -> ValueRef { + + alt (op) { + case (ast.add) { ret cx.build.Add(lhs, rhs); } + case (ast.sub) { ret cx.build.Sub(lhs, rhs); } + + // FIXME: switch by signedness. + case (ast.mul) { ret cx.build.Mul(lhs, rhs); } + case (ast.div) { ret cx.build.SDiv(lhs, rhs); } + case (ast.rem) { ret cx.build.SRem(lhs, rhs); } + + case (ast.bitor) { ret cx.build.Or(lhs, rhs); } + case (ast.bitand) { ret cx.build.And(lhs, rhs); } + case (ast.bitxor) { ret cx.build.Xor(lhs, rhs); } + case (ast.lsl) { ret cx.build.Shl(lhs, rhs); } + case (ast.lsr) { ret cx.build.LShr(lhs, rhs); } + case (ast.asr) { ret cx.build.AShr(lhs, rhs); } + case (_) { + auto cmp = lib.llvm.LLVMIntEQ; + alt (op) { + case (ast.eq) { cmp = lib.llvm.LLVMIntEQ; } + case (ast.ne) { cmp = lib.llvm.LLVMIntNE; } + + // FIXME: switch by signedness. + case (ast.lt) { cmp = lib.llvm.LLVMIntSLT; } + case (ast.le) { cmp = lib.llvm.LLVMIntSLE; } + case (ast.ge) { cmp = lib.llvm.LLVMIntSGE; } + case (ast.gt) { cmp = lib.llvm.LLVMIntSGT; } + } + ret cx.build.ICmp(cmp, lhs, rhs); + } + } + fail; +} + impure fn trans_binary(@block_ctxt cx, ast.binop op, @ast.expr a, @ast.expr b) -> result { @@ -1073,109 +1109,12 @@ impure fn trans_binary(@block_ctxt cx, ast.binop op, vec(lhs_true_res, rhs_res)); } - case (_) { /* fall through */ } - } - - // Remaining cases are eager: - - auto lhs = trans_expr(cx, a); - auto sub = trans_expr(lhs.bcx, b); - - alt (op) { - case (ast.add) { - sub.val = cx.build.Add(lhs.val, sub.val); - ret sub; - } - - case (ast.sub) { - sub.val = cx.build.Sub(lhs.val, sub.val); - ret sub; - } - - case (ast.mul) { - // FIXME: switch by signedness. - sub.val = cx.build.Mul(lhs.val, sub.val); - ret sub; - } - - case (ast.div) { - // FIXME: switch by signedness. - sub.val = cx.build.SDiv(lhs.val, sub.val); - ret sub; - } - - case (ast.rem) { - // FIXME: switch by signedness. - sub.val = cx.build.SRem(lhs.val, sub.val); - ret sub; - } - - case (ast.bitor) { - sub.val = cx.build.Or(lhs.val, sub.val); - ret sub; - } - - case (ast.bitand) { - sub.val = cx.build.And(lhs.val, sub.val); - ret sub; - } - - case (ast.bitxor) { - sub.val = cx.build.Xor(lhs.val, sub.val); - ret sub; - } - - case (ast.lsl) { - sub.val = cx.build.Shl(lhs.val, sub.val); - ret sub; - } - - case (ast.lsr) { - sub.val = cx.build.LShr(lhs.val, sub.val); - ret sub; - } - - case (ast.asr) { - sub.val = cx.build.AShr(lhs.val, sub.val); - ret sub; - } - - case (ast.eq) { - sub.val = cx.build.ICmp(lib.llvm.LLVMIntEQ, lhs.val, sub.val); - ret sub; - } - - case (ast.ne) { - sub.val = cx.build.ICmp(lib.llvm.LLVMIntNE, lhs.val, sub.val); - ret sub; - } - - case (ast.lt) { - // FIXME: switch by signedness. - sub.val = cx.build.ICmp(lib.llvm.LLVMIntSLT, lhs.val, sub.val); - ret sub; - } - - case (ast.le) { - // FIXME: switch by signedness. - sub.val = cx.build.ICmp(lib.llvm.LLVMIntSLE, lhs.val, sub.val); - ret sub; - } - - case (ast.ge) { - // FIXME: switch by signedness. - sub.val = cx.build.ICmp(lib.llvm.LLVMIntSGE, lhs.val, sub.val); - ret sub; - } - - case (ast.gt) { - // FIXME: switch by signedness. - sub.val = cx.build.ICmp(lib.llvm.LLVMIntSGT, lhs.val, sub.val); - ret sub; - } - case (_) { - cx.fcx.ccx.sess.unimpl("operator in trans_binary"); + // Remaining cases are eager: + auto lhs = trans_expr(cx, a); + auto sub = trans_expr(lhs.bcx, b); + ret res(sub.bcx, trans_eager_binop(sub.bcx, op, + lhs.val, sub.val)); } } fail; @@ -1551,6 +1490,18 @@ impure fn trans_expr(@block_ctxt cx, @ast.expr e) -> result { ret copy_ty(rhs_res.bcx, false, lhs_res._0.val, rhs_res.val, t); } + case (ast.expr_assign_op(?op, ?dst, ?src, ?ann)) { + auto t = node_ann_type(cx.fcx.ccx, ann); + auto lhs_res = trans_lval(cx, dst); + check (lhs_res._1); + auto lhs_val = load_non_structural(lhs_res._0.bcx, + lhs_res._0.val, t); + auto rhs_res = trans_expr(lhs_res._0.bcx, src); + auto v = trans_eager_binop(rhs_res.bcx, op, lhs_val, rhs_res.val); + // FIXME: calculate copy init-ness in typestate. + ret copy_ty(rhs_res.bcx, false, lhs_res._0.val, v, t); + } + case (ast.expr_call(?f, ?args, _)) { ret trans_call(cx, f, args); } diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index 9811af9e..2ca20977 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -684,6 +684,8 @@ fn expr_ty(@ast.expr expr) -> @ty { case (ast.expr_do_while(_, _, ?ann)) { ret ann_to_type(ann); } case (ast.expr_block(_, ?ann)) { ret ann_to_type(ann); } case (ast.expr_assign(_, _, ?ann)) { ret ann_to_type(ann); } + case (ast.expr_assign_op(_, _, _, ?ann)) + { ret ann_to_type(ann); } case (ast.expr_field(_, _, ?ann)) { ret ann_to_type(ann); } case (ast.expr_index(_, _, ?ann)) { ret ann_to_type(ann); } case (ast.expr_name(_, _, ?ann)) { ret ann_to_type(ann); } @@ -1120,6 +1122,10 @@ fn demand_expr(&fn_ctxt fcx, @ty expected, @ast.expr e) -> @ast.expr { auto t = demand(fcx, e.span, expected, ann_to_type(ann)); e_1 = ast.expr_assign(lhs, rhs, ast.ann_type(t)); } + case (ast.expr_assign_op(?op, ?lhs, ?rhs, ?ann)) { + auto t = demand(fcx, e.span, expected, ann_to_type(ann)); + e_1 = ast.expr_assign_op(op, lhs, rhs, ast.ann_type(t)); + } case (ast.expr_field(?lhs, ?rhs, ?ann)) { auto t = demand(fcx, e.span, expected, ann_to_type(ann)); e_1 = ast.expr_field(lhs, rhs, ast.ann_type(t)); @@ -1308,6 +1314,21 @@ fn check_expr(&fn_ctxt fcx, @ast.expr expr) -> @ast.expr { ast.expr_assign(lhs_1, rhs_1, ann)); } + case (ast.expr_assign_op(?op, ?lhs, ?rhs, _)) { + auto lhs_0 = check_expr(fcx, lhs); + auto rhs_0 = check_expr(fcx, rhs); + auto lhs_t0 = expr_ty(lhs_0); + auto rhs_t0 = expr_ty(rhs_0); + + auto lhs_1 = demand_expr(fcx, rhs_t0, lhs_0); + auto rhs_1 = demand_expr(fcx, expr_ty(lhs_1), rhs_0); + + auto ann = ast.ann_type(rhs_t0); + ret @fold.respan[ast.expr_](expr.span, + ast.expr_assign_op(op, lhs_1, rhs_1, + ann)); + } + case (ast.expr_if(?cond, ?thn, ?elsopt, _)) { auto cond_0 = check_expr(fcx, cond); auto cond_1 = demand_expr(fcx, plain_ty(ty_bool), cond_0); |