Skip to content

Commit 68af077

Browse files
committed
Implement binop= forms. Un-XFAIL bitwise.rs.
1 parent b971d63 commit 68af077

File tree

8 files changed

+128
-113
lines changed

8 files changed

+128
-113
lines changed

src/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -522,6 +522,7 @@ TEST_XFAILS_SELF := $(filter-out \
522522
arith-0.rs \
523523
arith-1.rs \
524524
arith-2.rs \
525+
bitwise.rs \
525526
bool-not.rs \
526527
box.rs \
527528
box-in-tup.rs \

src/comp/front/ast.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ tag expr_ {
145145
expr_alt(@expr, vec[arm], ann);
146146
expr_block(block, ann);
147147
expr_assign(@expr /* TODO: @expr|is_lval */, @expr, ann);
148+
expr_assign_op(binop, @expr /* TODO: @expr|is_lval */, @expr, ann);
148149
expr_field(@expr, ident, ann);
149150
expr_index(@expr, @expr, ann);
150151
expr_name(name, option.t[def], ann);

src/comp/front/lexer.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -426,7 +426,7 @@ impure fn next_token(reader rdr) -> token.token {
426426

427427
impure fn binop(reader rdr, token.binop op) -> token.token {
428428
rdr.bump();
429-
if (rdr.next() == '=') {
429+
if (rdr.curr() == '=') {
430430
rdr.bump();
431431
ret token.BINOPEQ(op);
432432
} else {

src/comp/front/parser.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -714,6 +714,26 @@ impure fn parse_assign_expr(parser p) -> @ast.expr {
714714
ret @spanned(lo, rhs.span,
715715
ast.expr_assign(lhs, rhs, ast.ann_none));
716716
}
717+
case (token.BINOPEQ(?op)) {
718+
p.bump();
719+
auto rhs = parse_expr(p);
720+
auto aop = ast.add;
721+
alt (op) {
722+
case (token.PLUS) { aop = ast.add; }
723+
case (token.MINUS) { aop = ast.sub; }
724+
case (token.STAR) { aop = ast.mul; }
725+
case (token.SLASH) { aop = ast.div; }
726+
case (token.PERCENT) { aop = ast.rem; }
727+
case (token.CARET) { aop = ast.bitxor; }
728+
case (token.AND) { aop = ast.bitand; }
729+
case (token.OR) { aop = ast.bitor; }
730+
case (token.LSL) { aop = ast.lsl; }
731+
case (token.LSR) { aop = ast.lsr; }
732+
case (token.ASR) { aop = ast.asr; }
733+
}
734+
ret @spanned(lo, rhs.span,
735+
ast.expr_assign_op(aop, lhs, rhs, ast.ann_none));
736+
}
717737
case (_) { /* fall through */ }
718738
}
719739
ret lhs;
@@ -1080,6 +1100,8 @@ fn stmt_ends_with_semi(@ast.stmt stmt) -> bool {
10801100
case (ast.expr_alt(_,_,_)) { ret false; }
10811101
case (ast.expr_block(_,_)) { ret false; }
10821102
case (ast.expr_assign(_,_,_)) { ret true; }
1103+
case (ast.expr_assign_op(_,_,_,_))
1104+
{ ret true; }
10831105
case (ast.expr_field(_,_,_)) { ret true; }
10841106
case (ast.expr_index(_,_,_)) { ret true; }
10851107
case (ast.expr_name(_,_,_)) { ret true; }

src/comp/lib/llvm.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -45,16 +45,16 @@ const uint LLVMX86FastcallCallConv = 65u;
4545
// Consts for the LLVM IntPredicate type, pre-cast to uint.
4646
// FIXME: as above.
4747

48-
const uint LLVMIntEQ = 32;
49-
const uint LLVMIntNE = 33;
50-
const uint LLVMIntUGT = 34;
51-
const uint LLVMIntUGE = 35;
52-
const uint LLVMIntULT = 36;
53-
const uint LLVMIntULE = 37;
54-
const uint LLVMIntSGT = 38;
55-
const uint LLVMIntSGE = 39;
56-
const uint LLVMIntSLT = 40;
57-
const uint LLVMIntSLE = 41;
48+
const uint LLVMIntEQ = 32u;
49+
const uint LLVMIntNE = 33u;
50+
const uint LLVMIntUGT = 34u;
51+
const uint LLVMIntUGE = 35u;
52+
const uint LLVMIntULT = 36u;
53+
const uint LLVMIntULE = 37u;
54+
const uint LLVMIntSGT = 38u;
55+
const uint LLVMIntSGE = 39u;
56+
const uint LLVMIntSLT = 40u;
57+
const uint LLVMIntSLE = 41u;
5858

5959

6060
native mod llvm = llvm_lib {

src/comp/middle/fold.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,11 @@ type ast_fold[ENV] =
114114
@expr lhs, @expr rhs,
115115
ann a) -> @expr) fold_expr_assign,
116116

117+
(fn(&ENV e, &span sp,
118+
ast.binop,
119+
@expr lhs, @expr rhs,
120+
ann a) -> @expr) fold_expr_assign_op,
121+
117122
(fn(&ENV e, &span sp,
118123
@expr e, ident i,
119124
ann a) -> @expr) fold_expr_field,
@@ -465,6 +470,12 @@ fn fold_expr[ENV](&ENV env, ast_fold[ENV] fld, &@expr e) -> @expr {
465470
ret fld.fold_expr_assign(env_, e.span, llhs, rrhs, t);
466471
}
467472

473+
case (ast.expr_assign_op(?op, ?lhs, ?rhs, ?t)) {
474+
auto llhs = fold_expr(env_, fld, lhs);
475+
auto rrhs = fold_expr(env_, fld, rhs);
476+
ret fld.fold_expr_assign_op(env_, e.span, op, llhs, rrhs, t);
477+
}
478+
468479
case (ast.expr_field(?e, ?i, ?t)) {
469480
auto ee = fold_expr(env_, fld, e);
470481
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,
790801
ret @respan(sp, ast.expr_assign(lhs, rhs, a));
791802
}
792803

804+
fn identity_fold_expr_assign_op[ENV](&ENV env, &span sp, ast.binop op,
805+
@expr lhs, @expr rhs, ann a)
806+
-> @expr {
807+
ret @respan(sp, ast.expr_assign_op(op, lhs, rhs, a));
808+
}
809+
793810
fn identity_fold_expr_field[ENV](&ENV env, &span sp,
794811
@expr e, ident i, ann a) -> @expr {
795812
ret @respan(sp, ast.expr_field(e, i, a));
@@ -986,6 +1003,8 @@ fn new_identity_fold[ENV]() -> ast_fold[ENV] {
9861003
fold_expr_alt = bind identity_fold_expr_alt[ENV](_,_,_,_,_),
9871004
fold_expr_block = bind identity_fold_expr_block[ENV](_,_,_,_),
9881005
fold_expr_assign = bind identity_fold_expr_assign[ENV](_,_,_,_,_),
1006+
fold_expr_assign_op
1007+
= bind identity_fold_expr_assign_op[ENV](_,_,_,_,_,_),
9891008
fold_expr_field = bind identity_fold_expr_field[ENV](_,_,_,_,_),
9901009
fold_expr_index = bind identity_fold_expr_index[ENV](_,_,_,_,_),
9911010
fold_expr_name = bind identity_fold_expr_name[ENV](_,_,_,_,_),

src/comp/middle/trans.rs

Lines changed: 53 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -1031,6 +1031,42 @@ impure fn trans_unary(@block_ctxt cx, ast.unop op,
10311031
fail;
10321032
}
10331033

1034+
fn trans_eager_binop(@block_ctxt cx, ast.binop op,
1035+
ValueRef lhs, ValueRef rhs) -> ValueRef {
1036+
1037+
alt (op) {
1038+
case (ast.add) { ret cx.build.Add(lhs, rhs); }
1039+
case (ast.sub) { ret cx.build.Sub(lhs, rhs); }
1040+
1041+
// FIXME: switch by signedness.
1042+
case (ast.mul) { ret cx.build.Mul(lhs, rhs); }
1043+
case (ast.div) { ret cx.build.SDiv(lhs, rhs); }
1044+
case (ast.rem) { ret cx.build.SRem(lhs, rhs); }
1045+
1046+
case (ast.bitor) { ret cx.build.Or(lhs, rhs); }
1047+
case (ast.bitand) { ret cx.build.And(lhs, rhs); }
1048+
case (ast.bitxor) { ret cx.build.Xor(lhs, rhs); }
1049+
case (ast.lsl) { ret cx.build.Shl(lhs, rhs); }
1050+
case (ast.lsr) { ret cx.build.LShr(lhs, rhs); }
1051+
case (ast.asr) { ret cx.build.AShr(lhs, rhs); }
1052+
case (_) {
1053+
auto cmp = lib.llvm.LLVMIntEQ;
1054+
alt (op) {
1055+
case (ast.eq) { cmp = lib.llvm.LLVMIntEQ; }
1056+
case (ast.ne) { cmp = lib.llvm.LLVMIntNE; }
1057+
1058+
// FIXME: switch by signedness.
1059+
case (ast.lt) { cmp = lib.llvm.LLVMIntSLT; }
1060+
case (ast.le) { cmp = lib.llvm.LLVMIntSLE; }
1061+
case (ast.ge) { cmp = lib.llvm.LLVMIntSGE; }
1062+
case (ast.gt) { cmp = lib.llvm.LLVMIntSGT; }
1063+
}
1064+
ret cx.build.ICmp(cmp, lhs, rhs);
1065+
}
1066+
}
1067+
fail;
1068+
}
1069+
10341070
impure fn trans_binary(@block_ctxt cx, ast.binop op,
10351071
@ast.expr a, @ast.expr b) -> result {
10361072

@@ -1073,109 +1109,12 @@ impure fn trans_binary(@block_ctxt cx, ast.binop op,
10731109
vec(lhs_true_res, rhs_res));
10741110
}
10751111

1076-
case (_) { /* fall through */ }
1077-
}
1078-
1079-
// Remaining cases are eager:
1080-
1081-
auto lhs = trans_expr(cx, a);
1082-
auto sub = trans_expr(lhs.bcx, b);
1083-
1084-
alt (op) {
1085-
case (ast.add) {
1086-
sub.val = cx.build.Add(lhs.val, sub.val);
1087-
ret sub;
1088-
}
1089-
1090-
case (ast.sub) {
1091-
sub.val = cx.build.Sub(lhs.val, sub.val);
1092-
ret sub;
1093-
}
1094-
1095-
case (ast.mul) {
1096-
// FIXME: switch by signedness.
1097-
sub.val = cx.build.Mul(lhs.val, sub.val);
1098-
ret sub;
1099-
}
1100-
1101-
case (ast.div) {
1102-
// FIXME: switch by signedness.
1103-
sub.val = cx.build.SDiv(lhs.val, sub.val);
1104-
ret sub;
1105-
}
1106-
1107-
case (ast.rem) {
1108-
// FIXME: switch by signedness.
1109-
sub.val = cx.build.SRem(lhs.val, sub.val);
1110-
ret sub;
1111-
}
1112-
1113-
case (ast.bitor) {
1114-
sub.val = cx.build.Or(lhs.val, sub.val);
1115-
ret sub;
1116-
}
1117-
1118-
case (ast.bitand) {
1119-
sub.val = cx.build.And(lhs.val, sub.val);
1120-
ret sub;
1121-
}
1122-
1123-
case (ast.bitxor) {
1124-
sub.val = cx.build.Xor(lhs.val, sub.val);
1125-
ret sub;
1126-
}
1127-
1128-
case (ast.lsl) {
1129-
sub.val = cx.build.Shl(lhs.val, sub.val);
1130-
ret sub;
1131-
}
1132-
1133-
case (ast.lsr) {
1134-
sub.val = cx.build.LShr(lhs.val, sub.val);
1135-
ret sub;
1136-
}
1137-
1138-
case (ast.asr) {
1139-
sub.val = cx.build.AShr(lhs.val, sub.val);
1140-
ret sub;
1141-
}
1142-
1143-
case (ast.eq) {
1144-
sub.val = cx.build.ICmp(lib.llvm.LLVMIntEQ, lhs.val, sub.val);
1145-
ret sub;
1146-
}
1147-
1148-
case (ast.ne) {
1149-
sub.val = cx.build.ICmp(lib.llvm.LLVMIntNE, lhs.val, sub.val);
1150-
ret sub;
1151-
}
1152-
1153-
case (ast.lt) {
1154-
// FIXME: switch by signedness.
1155-
sub.val = cx.build.ICmp(lib.llvm.LLVMIntSLT, lhs.val, sub.val);
1156-
ret sub;
1157-
}
1158-
1159-
case (ast.le) {
1160-
// FIXME: switch by signedness.
1161-
sub.val = cx.build.ICmp(lib.llvm.LLVMIntSLE, lhs.val, sub.val);
1162-
ret sub;
1163-
}
1164-
1165-
case (ast.ge) {
1166-
// FIXME: switch by signedness.
1167-
sub.val = cx.build.ICmp(lib.llvm.LLVMIntSGE, lhs.val, sub.val);
1168-
ret sub;
1169-
}
1170-
1171-
case (ast.gt) {
1172-
// FIXME: switch by signedness.
1173-
sub.val = cx.build.ICmp(lib.llvm.LLVMIntSGT, lhs.val, sub.val);
1174-
ret sub;
1175-
}
1176-
11771112
case (_) {
1178-
cx.fcx.ccx.sess.unimpl("operator in trans_binary");
1113+
// Remaining cases are eager:
1114+
auto lhs = trans_expr(cx, a);
1115+
auto sub = trans_expr(lhs.bcx, b);
1116+
ret res(sub.bcx, trans_eager_binop(sub.bcx, op,
1117+
lhs.val, sub.val));
11791118
}
11801119
}
11811120
fail;
@@ -1551,6 +1490,18 @@ impure fn trans_expr(@block_ctxt cx, @ast.expr e) -> result {
15511490
ret copy_ty(rhs_res.bcx, false, lhs_res._0.val, rhs_res.val, t);
15521491
}
15531492

1493+
case (ast.expr_assign_op(?op, ?dst, ?src, ?ann)) {
1494+
auto t = node_ann_type(cx.fcx.ccx, ann);
1495+
auto lhs_res = trans_lval(cx, dst);
1496+
check (lhs_res._1);
1497+
auto lhs_val = load_non_structural(lhs_res._0.bcx,
1498+
lhs_res._0.val, t);
1499+
auto rhs_res = trans_expr(lhs_res._0.bcx, src);
1500+
auto v = trans_eager_binop(rhs_res.bcx, op, lhs_val, rhs_res.val);
1501+
// FIXME: calculate copy init-ness in typestate.
1502+
ret copy_ty(rhs_res.bcx, false, lhs_res._0.val, v, t);
1503+
}
1504+
15541505
case (ast.expr_call(?f, ?args, _)) {
15551506
ret trans_call(cx, f, args);
15561507
}

src/comp/middle/typeck.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -684,6 +684,8 @@ fn expr_ty(@ast.expr expr) -> @ty {
684684
case (ast.expr_do_while(_, _, ?ann)) { ret ann_to_type(ann); }
685685
case (ast.expr_block(_, ?ann)) { ret ann_to_type(ann); }
686686
case (ast.expr_assign(_, _, ?ann)) { ret ann_to_type(ann); }
687+
case (ast.expr_assign_op(_, _, _, ?ann))
688+
{ ret ann_to_type(ann); }
687689
case (ast.expr_field(_, _, ?ann)) { ret ann_to_type(ann); }
688690
case (ast.expr_index(_, _, ?ann)) { ret ann_to_type(ann); }
689691
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 {
11201122
auto t = demand(fcx, e.span, expected, ann_to_type(ann));
11211123
e_1 = ast.expr_assign(lhs, rhs, ast.ann_type(t));
11221124
}
1125+
case (ast.expr_assign_op(?op, ?lhs, ?rhs, ?ann)) {
1126+
auto t = demand(fcx, e.span, expected, ann_to_type(ann));
1127+
e_1 = ast.expr_assign_op(op, lhs, rhs, ast.ann_type(t));
1128+
}
11231129
case (ast.expr_field(?lhs, ?rhs, ?ann)) {
11241130
auto t = demand(fcx, e.span, expected, ann_to_type(ann));
11251131
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 {
13081314
ast.expr_assign(lhs_1, rhs_1, ann));
13091315
}
13101316

1317+
case (ast.expr_assign_op(?op, ?lhs, ?rhs, _)) {
1318+
auto lhs_0 = check_expr(fcx, lhs);
1319+
auto rhs_0 = check_expr(fcx, rhs);
1320+
auto lhs_t0 = expr_ty(lhs_0);
1321+
auto rhs_t0 = expr_ty(rhs_0);
1322+
1323+
auto lhs_1 = demand_expr(fcx, rhs_t0, lhs_0);
1324+
auto rhs_1 = demand_expr(fcx, expr_ty(lhs_1), rhs_0);
1325+
1326+
auto ann = ast.ann_type(rhs_t0);
1327+
ret @fold.respan[ast.expr_](expr.span,
1328+
ast.expr_assign_op(op, lhs_1, rhs_1,
1329+
ann));
1330+
}
1331+
13111332
case (ast.expr_if(?cond, ?thn, ?elsopt, _)) {
13121333
auto cond_0 = check_expr(fcx, cond);
13131334
auto cond_1 = demand_expr(fcx, plain_ty(ty_bool), cond_0);

0 commit comments

Comments
 (0)