Skip to content

Commit

Permalink
cgen: fix cross method call + method_call cleanup (#20025)
Browse files Browse the repository at this point in the history
  • Loading branch information
felipensp committed Nov 29, 2023
1 parent fed3552 commit 883eaa6
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 19 deletions.
11 changes: 6 additions & 5 deletions vlib/v/gen/c/assign.v
Expand Up @@ -1081,11 +1081,12 @@ fn (mut g Gen) gen_cross_tmp_variable(left []ast.Expr, val ast.Expr) {
}
ast.CallExpr {
if val.is_method {
rec_cc_type := g.cc_type(val.receiver_type, false)
mut rec_typ_name := util.no_dots(rec_cc_type)
if g.table.sym(val.receiver_type).kind == .array {
rec_typ_name = 'array'
}
unwrapped_rec_type, typ_sym := g.resolve_receiver_type(val)
left_type := g.unwrap_generic(val.left_type)
left_sym := g.table.sym(left_type)
final_left_sym := g.table.final_sym(left_type)
rec_typ_name := g.resolve_receiver_name(val, unwrapped_rec_type, final_left_sym,
left_sym, typ_sym)
fn_name := util.no_dots('${rec_typ_name}_${val.name}')
g.write('${fn_name}(&')
g.gen_cross_tmp_variable(left, val.left)
Expand Down
46 changes: 32 additions & 14 deletions vlib/v/gen/c/fn.v
Expand Up @@ -1158,14 +1158,22 @@ fn (mut g Gen) change_comptime_args(func ast.Fn, mut node_ ast.CallExpr, concret
return comptime_args
}

fn (mut g Gen) method_call(node ast.CallExpr) {
// TODO: there are still due to unchecked exprs (opt/some fn arg)
if node.left_type == 0 {
g.checker_bug('CallExpr.left_type is 0 in method_call', node.pos)
fn (mut g Gen) resolve_receiver_name(node ast.CallExpr, unwrapped_rec_type ast.Type, final_left_sym ast.TypeSymbol, left_sym ast.TypeSymbol, typ_sym ast.TypeSymbol) string {
mut receiver_type_name := util.no_dots(g.cc_type(unwrapped_rec_type, false))
if final_left_sym.kind == .map && node.name in ['clone', 'move'] {
receiver_type_name = 'map'
}
if node.receiver_type == 0 {
g.checker_bug('CallExpr.receiver_type is 0 in method_call', node.pos)
if final_left_sym.kind == .array && !(left_sym.kind == .alias && left_sym.has_method(node.name))
&& node.name in ['clear', 'repeat', 'sort_with_compare', 'sorted_with_compare', 'free', 'push_many', 'trim', 'first', 'last', 'pop', 'clone', 'reverse', 'slice', 'pointers'] {
if !(left_sym.info is ast.Alias && typ_sym.has_method(node.name)) {
// `array_Xyz_clone` => `array_clone`
receiver_type_name = 'array'
}
}
return receiver_type_name
}

fn (mut g Gen) resolve_receiver_type(node ast.CallExpr) (ast.Type, &ast.TypeSymbol) {
left_type := g.unwrap_generic(node.left_type)
mut unwrapped_rec_type := node.receiver_type
if g.cur_fn != unsafe { nil } && g.cur_fn.generic_names.len > 0 { // in generic fn
Expand Down Expand Up @@ -1215,9 +1223,23 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
unwrapped_rec_type = node.from_embed_types.last()
typ_sym = g.table.sym(unwrapped_rec_type)
}
return unwrapped_rec_type, typ_sym
}

fn (mut g Gen) method_call(node ast.CallExpr) {
// TODO: there are still due to unchecked exprs (opt/some fn arg)
if node.left_type == 0 {
g.checker_bug('CallExpr.left_type is 0 in method_call', node.pos)
}
if node.receiver_type == 0 {
g.checker_bug('CallExpr.receiver_type is 0 in method_call', node.pos)
}
left_type := g.unwrap_generic(node.left_type)
mut unwrapped_rec_type, typ_sym := g.resolve_receiver_type(node)

rec_cc_type := g.cc_type(unwrapped_rec_type, false)
mut receiver_type_name := util.no_dots(rec_cc_type)
if mut typ_sym.info is ast.Interface && typ_sym.info.defines_method(node.name) {
if typ_sym.info is ast.Interface && typ_sym.info.defines_method(node.name) {
// Speaker_name_table[s._interface_idx].speak(s._object)
$if debug_interface_method_call ? {
eprintln('>>> interface typ_sym.name: ${typ_sym.name} | receiver_type_name: ${receiver_type_name} | pos: ${node.pos}')
Expand Down Expand Up @@ -1306,15 +1328,11 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
g.get_free_method(rec_type)
}
mut has_cast := false
if final_left_sym.kind == .map && node.name in ['clone', 'move'] {
receiver_type_name = 'map'
}

receiver_type_name = g.resolve_receiver_name(node, unwrapped_rec_type, final_left_sym,
left_sym, typ_sym)
if final_left_sym.kind == .array && !(left_sym.kind == .alias && left_sym.has_method(node.name))
&& node.name in ['clear', 'repeat', 'sort_with_compare', 'sorted_with_compare', 'free', 'push_many', 'trim', 'first', 'last', 'pop', 'clone', 'reverse', 'slice', 'pointers'] {
if !(left_sym.info is ast.Alias && typ_sym.has_method(node.name)) {
// `array_Xyz_clone` => `array_clone`
receiver_type_name = 'array'
}
if node.name in ['last', 'first', 'pop'] {
return_type_str := g.typ(node.return_type)
has_cast = true
Expand Down
17 changes: 17 additions & 0 deletions vlib/v/tests/cross_method_call_test.v
@@ -0,0 +1,17 @@
fn test_main() {
mut l_map := map[int]bool{}
mut r_map := map[int]bool{}

l_map[0] = false
l_map[1] = false

r_map[0] = true
r_map[1] = true

l_map, r_map = r_map.move(), l_map.move()

assert l_map[0] == true
assert l_map[0] == true
assert r_map[0] == false
assert r_map[0] == false
}

0 comments on commit 883eaa6

Please sign in to comment.