From ec19f4289ce155f20207509e05a3d0cfb24936fc Mon Sep 17 00:00:00 2001 From: yuyi Date: Tue, 12 Jul 2022 00:20:15 +0800 Subject: [PATCH] checker, cgen: fix alias operator overloading (#15024) --- vlib/v/checker/infix.v | 12 +++++++ vlib/v/gen/c/infix.v | 15 ++++++--- .../v/tests/alias_operator_overloading_test.v | 31 +++++++++++++++++++ 3 files changed, 53 insertions(+), 5 deletions(-) create mode 100644 vlib/v/tests/alias_operator_overloading_test.v diff --git a/vlib/v/checker/infix.v b/vlib/v/checker/infix.v index ed73eafad4..4bd24346a9 100644 --- a/vlib/v/checker/infix.v +++ b/vlib/v/checker/infix.v @@ -174,6 +174,12 @@ pub fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type { } else { return_type = left_type } + } else if left_final.has_method(node.op.str()) { + if method := left_final.find_method(node.op.str()) { + return_type = method.return_type + } else { + return_type = left_type + } } else { left_name := c.table.type_to_str(left_type) right_name := c.table.type_to_str(right_type) @@ -192,6 +198,12 @@ pub fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type { } else { return_type = right_type } + } else if right_final.has_method(node.op.str()) { + if method := right_final.find_method(node.op.str()) { + return_type = method.return_type + } else { + return_type = right_type + } } else { left_name := c.table.type_to_str(left_type) right_name := c.table.type_to_str(right_type) diff --git a/vlib/v/gen/c/infix.v b/vlib/v/gen/c/infix.v index 8bd7dfd0f8..2484617a65 100644 --- a/vlib/v/gen/c/infix.v +++ b/vlib/v/gen/c/infix.v @@ -664,14 +664,19 @@ fn (mut g Gen) infix_expr_arithmetic_op(node ast.InfixExpr) { g.expr(node.right) g.write(')') } else { - method := g.table.find_method(left.sym, node.op.str()) or { + mut method := ast.Fn{} + mut method_name := '' + if left.sym.has_method(node.op.str()) { + method = left.sym.find_method(node.op.str()) or { ast.Fn{} } + method_name = left.sym.cname + '_' + util.replace_op(node.op.str()) + } else if left.unaliased_sym.has_method(node.op.str()) { + method = left.unaliased_sym.find_method(node.op.str()) or { ast.Fn{} } + method_name = left.unaliased_sym.cname + '_' + util.replace_op(node.op.str()) + } else { g.gen_plain_infix_expr(node) return } - left_styp := g.typ(left.typ.set_nr_muls(0)) - g.write(left_styp) - g.write('_') - g.write(util.replace_op(node.op.str())) + g.write(method_name) g.write('(') g.op_arg(node.left, method.params[0].typ, left.typ) g.write(', ') diff --git a/vlib/v/tests/alias_operator_overloading_test.v b/vlib/v/tests/alias_operator_overloading_test.v new file mode 100644 index 0000000000..731ef53847 --- /dev/null +++ b/vlib/v/tests/alias_operator_overloading_test.v @@ -0,0 +1,31 @@ +pub struct Vector { + vec []f64 +} + +pub fn (a Vector) + (b Vector) Vector { + size := a.vec.len + if size != b.vec.len { + panic('unequal sizes') + } + mut c := []f64{len: size} + for i in 0 .. size { + c[i] = a.vec[i] + b.vec[i] + } + return Vector{ + vec: c + } +} + +type Vec = Vector + +fn test_alias_operator_overloading() { + a := Vec{ + vec: [0.1, 0.2] + } + b := Vec{ + vec: [0.3, 0.2] + } + c := a + b + println(c) + assert c.vec == [0.4, 0.4] +}