diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 8ab699ea927..1feddbdb54c 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -2219,8 +2219,8 @@ fn trans_assign_op(bcx: @block_ctxt, ex: @ast::expr, op: ast::binop, let fty = ty::node_id_to_monotype(bcx_tcx(bcx), callee_id); ret trans_call_inner(bcx, fty, {|bcx| // FIXME provide the already-computed address, not the expr - trans_impl::trans_method_callee(bcx, callee_id, src, origin) - }, [dst], ex.id, save_in(lhs_res.val)); + trans_impl::trans_method_callee(bcx, callee_id, dst, origin) + }, [src], ex.id, save_in(lhs_res.val)); } _ {} } @@ -2333,16 +2333,16 @@ fn trans_lazy_binop(bcx: @block_ctxt, op: ast::binop, a: @ast::expr, -fn trans_binary(bcx: @block_ctxt, op: ast::binop, a: @ast::expr, - b: @ast::expr, dest: dest, ex: @ast::expr) -> @block_ctxt { +fn trans_binary(bcx: @block_ctxt, op: ast::binop, lhs: @ast::expr, + rhs: @ast::expr, dest: dest, ex: @ast::expr) -> @block_ctxt { // User-defined operators alt bcx_ccx(bcx).method_map.find(ex.id) { some(origin) { let callee_id = ast_util::op_expr_callee_id(ex); let fty = ty::node_id_to_monotype(bcx_tcx(bcx), callee_id); ret trans_call_inner(bcx, fty, {|bcx| - trans_impl::trans_method_callee(bcx, callee_id, a, origin) - }, [b], ex.id, dest); + trans_impl::trans_method_callee(bcx, callee_id, lhs, origin) + }, [rhs], ex.id, dest); } _ {} } @@ -2350,15 +2350,15 @@ fn trans_binary(bcx: @block_ctxt, op: ast::binop, a: @ast::expr, // First couple cases are lazy: alt op { ast::and | ast::or { - ret trans_lazy_binop(bcx, op, a, b, dest); + ret trans_lazy_binop(bcx, op, lhs, rhs, dest); } _ { // Remaining cases are eager: - let lhs = trans_temp_expr(bcx, a); - let rhs = trans_temp_expr(lhs.bcx, b); - ret trans_eager_binop(rhs.bcx, op, lhs.val, - ty::expr_ty(bcx_tcx(bcx), a), rhs.val, - ty::expr_ty(bcx_tcx(bcx), b), dest); + let lhs_res = trans_temp_expr(bcx, lhs); + let rhs_res = trans_temp_expr(lhs_res.bcx, rhs); + ret trans_eager_binop(rhs_res.bcx, op, lhs_res.val, + ty::expr_ty(bcx_tcx(bcx), lhs), rhs_res.val, + ty::expr_ty(bcx_tcx(bcx), rhs), dest); } } } @@ -3517,8 +3517,8 @@ fn trans_expr(bcx: @block_ctxt, e: @ast::expr, dest: dest) -> @block_ctxt { ast::expr_tup(args) { ret trans_tup(bcx, args, e.id, dest); } ast::expr_lit(lit) { ret trans_lit(bcx, *lit, dest); } ast::expr_vec(args, _) { ret tvec::trans_vec(bcx, args, e.id, dest); } - ast::expr_binary(op, x, y) { - ret trans_binary(bcx, op, x, y, dest, e); + ast::expr_binary(op, lhs, rhs) { + ret trans_binary(bcx, op, lhs, rhs, dest, e); } ast::expr_unary(op, x) { assert op != ast::deref; // lvals are handled above diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index 5d65e9c7f14..743bc190796 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -1768,17 +1768,9 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier, fn binop_method(op: ast::binop) -> option::t { alt op { - ast::add { some("op_add") } - ast::subtract { some("op_sub") } - ast::mul { some("op_mul") } - ast::div { some("op_div") } - ast::rem { some("op_rem") } - ast::bitxor { some("op_xor") } - ast::bitand { some("op_and") } - ast::bitor { some("op_or") } - ast::lsl { some("op_shift_left") } - ast::lsr { some("op_shift_right") } - ast::asr { some("op_ashift_right") } + ast::add | ast::subtract | ast::mul | ast::div | ast::rem | + ast::bitxor | ast::bitand | ast::bitor | ast::lsl | ast::lsr | + ast::asr { some(ast_util::binop_to_str(op)) } _ { none } } } @@ -1904,14 +1896,14 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier, oper_t = structurally_resolved_type(fcx, oper.span, oper_t); if !(ty::type_is_integral(tcx, oper_t) || ty::struct(tcx, oper_t) == ty::ty_bool) { - oper_t = check_user_unop(fcx, "!", "op_not", expr, oper_t); + oper_t = check_user_unop(fcx, "!", "!", expr, oper_t); } } ast::neg { oper_t = structurally_resolved_type(fcx, oper.span, oper_t); if !(ty::type_is_integral(tcx, oper_t) || ty::type_is_fp(tcx, oper_t)) { - oper_t = check_user_unop(fcx, "-", "op_neg", expr, oper_t); + oper_t = check_user_unop(fcx, "-", "neg", expr, oper_t); } } } @@ -2337,7 +2329,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier, _ { let resolved = structurally_resolved_type(fcx, expr.span, raw_base_t); - alt lookup_op_method(fcx, expr, resolved, "op_index", + alt lookup_op_method(fcx, expr, resolved, "[]", [some(idx)]) { some(ret_ty) { write::ty_only_fixup(fcx, id, ret_ty); } _ { diff --git a/src/comp/syntax/parse/parser.rs b/src/comp/syntax/parse/parser.rs index 3d6b76db628..8b2d6cf36a7 100644 --- a/src/comp/syntax/parse/parser.rs +++ b/src/comp/syntax/parse/parser.rs @@ -284,7 +284,7 @@ fn parse_ty_methods(p: parser) -> [ast::ty_method] { parse_seq(token::LBRACE, token::RBRACE, seq_sep_none(), {|p| let flo = p.span.lo; expect_word(p, "fn"); - let ident = parse_value_ident(p); + let ident = parse_method_name(p); let tps = parse_ty_params(p); let f = parse_ty_fn(ast::proto_bare, p), fhi = p.last_span.hi; expect(p, token::SEMI); @@ -1824,10 +1824,19 @@ fn parse_item_fn(p: parser, purity: ast::purity, ast::item_fn(decl, t.tps, body), attrs); } +fn parse_method_name(p: parser) -> ast::ident { + alt p.token { + token::BINOP(op) { p.bump(); token::binop_to_str(op) } + token::NOT { p.bump(); "!" } + token::LBRACKET { p.bump(); expect(p, token::RBRACKET); "[]" } + _ { parse_value_ident(p) } + } +} + fn parse_method(p: parser) -> @ast::method { let lo = p.span.lo; expect_word(p, "fn"); - let ident = parse_value_ident(p); + let ident = parse_method_name(p); let tps = parse_ty_params(p); let decl = parse_fn_decl(p, ast::impure_fn); let body = parse_block(p); diff --git a/src/test/run-pass/operator-overloading.rs b/src/test/run-pass/operator-overloading.rs index 55761548f14..412e1fd538c 100644 --- a/src/test/run-pass/operator-overloading.rs +++ b/src/test/run-pass/operator-overloading.rs @@ -1,20 +1,24 @@ type point = {x: int, y: int}; -impl add_point for point { - fn op_add(other: point) -> point { +impl point_ops for point { + fn +(other: point) -> point { {x: self.x + other.x, y: self.y + other.y} } - fn op_neg() -> point { + fn -(other: point) -> point { + {x: self.x - other.x, y: self.y - other.y} + } + fn neg() -> point { {x: -self.x, y: -self.y} } - fn op_index(x: bool) -> int { + fn [](x: bool) -> int { x ? self.x : self.y } } fn main() { let p = {x: 10, y: 20}; - p += {x: 1, y: 2}; + p += {x: 101, y: 102}; + p -= {x: 100, y: 100}; assert p + {x: 5, y: 5} == {x: 16, y: 27}; assert -p == {x: -11, y: -22}; assert p[true] == 11;