Implement binop= forms. Un-XFAIL bitwise.rs.
This commit is contained in:
parent
b971d6312e
commit
68af077e81
8 changed files with 128 additions and 113 deletions
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -114,6 +114,11 @@ type ast_fold[ENV] =
|
|||
@expr lhs, @expr rhs,
|
||||
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](_,_,_,_,_),
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue