cgen: fix cross method call + method_call cleanup (#20025)

This commit is contained in:
Felipe Pena 2023-11-29 13:02:26 -03:00 committed by GitHub
parent fed3552671
commit 883eaa6e1f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 55 additions and 19 deletions

View File

@ -1081,11 +1081,12 @@ fn (mut g Gen) gen_cross_tmp_variable(left []ast.Expr, val ast.Expr) {
} }
ast.CallExpr { ast.CallExpr {
if val.is_method { if val.is_method {
rec_cc_type := g.cc_type(val.receiver_type, false) unwrapped_rec_type, typ_sym := g.resolve_receiver_type(val)
mut rec_typ_name := util.no_dots(rec_cc_type) left_type := g.unwrap_generic(val.left_type)
if g.table.sym(val.receiver_type).kind == .array { left_sym := g.table.sym(left_type)
rec_typ_name = 'array' 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}') fn_name := util.no_dots('${rec_typ_name}_${val.name}')
g.write('${fn_name}(&') g.write('${fn_name}(&')
g.gen_cross_tmp_variable(left, val.left) g.gen_cross_tmp_variable(left, val.left)

View File

@ -1158,14 +1158,22 @@ fn (mut g Gen) change_comptime_args(func ast.Fn, mut node_ ast.CallExpr, concret
return comptime_args return comptime_args
} }
fn (mut g Gen) method_call(node ast.CallExpr) { 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 {
// TODO: there are still due to unchecked exprs (opt/some fn arg) mut receiver_type_name := util.no_dots(g.cc_type(unwrapped_rec_type, false))
if node.left_type == 0 { if final_left_sym.kind == .map && node.name in ['clone', 'move'] {
g.checker_bug('CallExpr.left_type is 0 in method_call', node.pos) receiver_type_name = 'map'
} }
if node.receiver_type == 0 { if final_left_sym.kind == .array && !(left_sym.kind == .alias && left_sym.has_method(node.name))
g.checker_bug('CallExpr.receiver_type is 0 in method_call', node.pos) && 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) left_type := g.unwrap_generic(node.left_type)
mut unwrapped_rec_type := node.receiver_type mut unwrapped_rec_type := node.receiver_type
if g.cur_fn != unsafe { nil } && g.cur_fn.generic_names.len > 0 { // in generic fn if g.cur_fn != unsafe { nil } && g.cur_fn.generic_names.len > 0 { // in generic fn
@ -1215,9 +1223,23 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
unwrapped_rec_type = node.from_embed_types.last() unwrapped_rec_type = node.from_embed_types.last()
typ_sym = g.table.sym(unwrapped_rec_type) 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) rec_cc_type := g.cc_type(unwrapped_rec_type, false)
mut receiver_type_name := util.no_dots(rec_cc_type) 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) // Speaker_name_table[s._interface_idx].speak(s._object)
$if debug_interface_method_call ? { $if debug_interface_method_call ? {
eprintln('>>> interface typ_sym.name: ${typ_sym.name} | receiver_type_name: ${receiver_type_name} | pos: ${node.pos}') eprintln('>>> interface typ_sym.name: ${typ_sym.name} | receiver_type_name: ${receiver_type_name} | pos: ${node.pos}')
@ -1306,15 +1328,11 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
g.get_free_method(rec_type) g.get_free_method(rec_type)
} }
mut has_cast := false 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)) 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'] { && 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'] { if node.name in ['last', 'first', 'pop'] {
return_type_str := g.typ(node.return_type) return_type_str := g.typ(node.return_type)
has_cast = true has_cast = true

View File

@ -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
}