diff --git a/vlib/v/gen/c/auto_free_methods.v b/vlib/v/gen/c/auto_free_methods.v index bcd11841f5..ea74f5281a 100644 --- a/vlib/v/gen/c/auto_free_methods.v +++ b/vlib/v/gen/c/auto_free_methods.v @@ -14,11 +14,6 @@ fn (mut g Gen) gen_free_method_for_type(typ ast.Type) string { sym = g.table.get_type_symbol(sym.info.parent_type) } } - if sym.kind == .map { - return 'map_free' - } else if sym.kind == .array { - return 'array_free' - } if sym.has_method('free') { return fn_name @@ -27,6 +22,12 @@ fn (mut g Gen) gen_free_method_for_type(typ ast.Type) string { ast.Struct { g.gen_free_for_struct(sym.info, styp, fn_name) } + ast.Array { + g.gen_free_for_array(sym.info, styp, fn_name) + } + ast.Map { + g.gen_free_for_map(sym.info, styp, fn_name) + } else { println(g.table.type_str(typ)) verror("could not generate free method '$fn_name' for type '$styp'") @@ -37,7 +38,7 @@ fn (mut g Gen) gen_free_method_for_type(typ ast.Type) string { fn (mut g Gen) gen_free_for_struct(info ast.Struct, styp string, fn_name string) { g.type_definitions.writeln('void ${fn_name}($styp* it); // auto') - mut fn_builder := strings.new_builder(512) + mut fn_builder := strings.new_builder(128) defer { g.auto_fn_definitions << fn_builder.str() } @@ -59,6 +60,43 @@ fn (mut g Gen) gen_free_for_struct(info ast.Struct, styp string, fn_name string) fn_builder.writeln('}') } +fn (mut g Gen) gen_free_for_array(info ast.Array, styp string, fn_name string) { + g.type_definitions.writeln('void ${fn_name}($styp* it); // auto') + mut fn_builder := strings.new_builder(128) + defer { + g.auto_fn_definitions << fn_builder.str() + } + fn_builder.writeln('void ${fn_name}($styp* it) {') + + sym := g.table.get_type_symbol(g.unwrap_generic(info.elem_type)) + if sym.kind in [.string, .array, .map, .struct_] { + fn_builder.writeln('\tfor (int i = 0; i < it->len; i++) {') + + mut elem_styp := g.typ(info.elem_type).replace('*', '') + elem_styp_fn_name := if sym.has_method('free') { + '${elem_styp}_free' + } else { + g.gen_free_method_for_type(info.elem_type) + } + fn_builder.writeln('\t\t${elem_styp_fn_name}(&((($elem_styp*)it->data)[i]));') + fn_builder.writeln('\t}') + } + fn_builder.writeln('\tarray_free(it);') + fn_builder.writeln('}') +} + +fn (mut g Gen) gen_free_for_map(info ast.Map, styp string, fn_name string) { + g.type_definitions.writeln('void ${fn_name}($styp* it); // auto') + mut fn_builder := strings.new_builder(128) + defer { + g.auto_fn_definitions << fn_builder.str() + } + fn_builder.writeln('void ${fn_name}($styp* it) {') + + fn_builder.writeln('\tmap_free(it);') + fn_builder.writeln('}') +} + [inline] fn styp_to_free_fn_name(styp string) string { return styp.replace_each(['*', '', '.', '__', ' ', '__']) + '_free' diff --git a/vlib/v/tests/autogen_free_test.v b/vlib/v/tests/autogen_free_test.v index f22fd1d2b1..e2de36e318 100644 --- a/vlib/v/tests/autogen_free_test.v +++ b/vlib/v/tests/autogen_free_test.v @@ -2,7 +2,7 @@ struct Info { name string notes []string maps map[int]int - info SubInfo + info []SubInfo } struct SubInfo {