parent
a2cd1b163c
commit
70c136441b
vlib
builtin
v/gen
|
@ -1195,3 +1195,34 @@ fn test_any_type_array_contains() {
|
||||||
assert [2] in c
|
assert [2] in c
|
||||||
assert [3] !in c
|
assert [3] !in c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Person {
|
||||||
|
name string
|
||||||
|
nums []int
|
||||||
|
kv map[string]string
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_struct_array_of_multi_type_in() {
|
||||||
|
ivan := Person{
|
||||||
|
name: 'ivan'
|
||||||
|
nums: [1, 2, 3]
|
||||||
|
kv: {
|
||||||
|
'aaa': '111'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
people := [Person{
|
||||||
|
name: 'ivan'
|
||||||
|
nums: [1, 2, 3]
|
||||||
|
kv: {
|
||||||
|
'aaa': '111'
|
||||||
|
}
|
||||||
|
}, Person{
|
||||||
|
name: 'bob'
|
||||||
|
nums: [2]
|
||||||
|
kv: {
|
||||||
|
'bbb': '222'
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
println(ivan in people)
|
||||||
|
assert ivan in people
|
||||||
|
}
|
||||||
|
|
|
@ -90,6 +90,8 @@ mut:
|
||||||
threaded_fns []string // for generating unique wrapper types and fns for `go xxx()`
|
threaded_fns []string // for generating unique wrapper types and fns for `go xxx()`
|
||||||
array_fn_definitions []string // array equality functions that have been defined
|
array_fn_definitions []string // array equality functions that have been defined
|
||||||
map_fn_definitions []string // map equality functions that have been defined
|
map_fn_definitions []string // map equality functions that have been defined
|
||||||
|
struct_fn_definitions []string // struct equality functions that have been defined
|
||||||
|
auto_fn_definitions []string // auto generated functions defination list
|
||||||
is_json_fn bool // inside json.encode()
|
is_json_fn bool // inside json.encode()
|
||||||
json_types []string // to avoid json gen duplicates
|
json_types []string // to avoid json gen duplicates
|
||||||
pcs []ProfileCounterMeta // -prof profile counter fn_names => fn counter name
|
pcs []ProfileCounterMeta // -prof profile counter fn_names => fn counter name
|
||||||
|
@ -316,6 +318,11 @@ pub fn cgen(files []ast.File, table &table.Table, pref &pref.Preferences) string
|
||||||
b.write(g.auto_str_funcs.str())
|
b.write(g.auto_str_funcs.str())
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
if g.auto_fn_definitions.len > 0 {
|
||||||
|
for fn_def in g.auto_fn_definitions {
|
||||||
|
b.writeln(fn_def)
|
||||||
|
}
|
||||||
|
}
|
||||||
b.writeln('\n// V out')
|
b.writeln('\n// V out')
|
||||||
b.write(g.out.str())
|
b.write(g.out.str())
|
||||||
b.writeln('\n// THE END.')
|
b.writeln('\n// THE END.')
|
||||||
|
@ -4519,6 +4526,51 @@ fn (mut g Gen) assoc(node ast.Assoc) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (mut g Gen) gen_struct_equality_fn(left table.Type) string {
|
||||||
|
left_sym := g.table.get_type_symbol(left)
|
||||||
|
info := left_sym.struct_info()
|
||||||
|
ptr_typ := g.typ(left).trim('*')
|
||||||
|
if ptr_typ in g.struct_fn_definitions {
|
||||||
|
return ptr_typ
|
||||||
|
}
|
||||||
|
g.struct_fn_definitions << ptr_typ
|
||||||
|
g.type_definitions.writeln('static bool ${ptr_typ}_struct_eq($ptr_typ a, $ptr_typ b);')
|
||||||
|
mut fn_builder := strings.new_builder(512)
|
||||||
|
fn_builder.writeln('static bool ${ptr_typ}_struct_eq($ptr_typ a, $ptr_typ b) {')
|
||||||
|
for field in info.fields {
|
||||||
|
sym := g.table.get_type_symbol(field.typ)
|
||||||
|
match sym.kind {
|
||||||
|
.string {
|
||||||
|
fn_builder.writeln('\tif (string_ne(a.$field.name, b.$field.name)) {')
|
||||||
|
}
|
||||||
|
.struct_ {
|
||||||
|
eq_fn := g.gen_struct_equality_fn(field.typ)
|
||||||
|
fn_builder.writeln('\tif (!${eq_fn}_struct_eq(a.$field.name, b.$field.name)) {')
|
||||||
|
}
|
||||||
|
.array {
|
||||||
|
eq_fn := g.gen_array_equality_fn(field.typ)
|
||||||
|
fn_builder.writeln('\tif (!${eq_fn}_arr_eq(a.$field.name, b.$field.name)) {')
|
||||||
|
}
|
||||||
|
.map {
|
||||||
|
eq_fn := g.gen_map_equality_fn(field.typ)
|
||||||
|
fn_builder.writeln('\tif (!${eq_fn}_map_eq(a.$field.name, b.$field.name)) {')
|
||||||
|
}
|
||||||
|
.function {
|
||||||
|
fn_builder.writeln('\tif (*((voidptr*)(a.$field.name)) != *((voidptr*)(b.$field.name))) {')
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fn_builder.writeln('\tif (a.$field.name != b.$field.name)) {')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn_builder.writeln('\t\treturn false;')
|
||||||
|
fn_builder.writeln('\t}')
|
||||||
|
}
|
||||||
|
fn_builder.writeln('\treturn true;')
|
||||||
|
fn_builder.writeln('}')
|
||||||
|
g.auto_fn_definitions << fn_builder.str()
|
||||||
|
return ptr_typ
|
||||||
|
}
|
||||||
|
|
||||||
fn (mut g Gen) gen_array_equality_fn(left table.Type) string {
|
fn (mut g Gen) gen_array_equality_fn(left table.Type) string {
|
||||||
left_sym := g.table.get_type_symbol(left)
|
left_sym := g.table.get_type_symbol(left)
|
||||||
typ_name := g.typ(left)
|
typ_name := g.typ(left)
|
||||||
|
@ -4534,32 +4586,34 @@ fn (mut g Gen) gen_array_equality_fn(left table.Type) string {
|
||||||
return ptr_typ
|
return ptr_typ
|
||||||
}
|
}
|
||||||
g.array_fn_definitions << ptr_typ
|
g.array_fn_definitions << ptr_typ
|
||||||
g.definitions.writeln('bool ${ptr_typ}_arr_eq(array_$ptr_typ a, array_$ptr_typ b) {')
|
g.type_definitions.writeln('static bool ${ptr_typ}_arr_eq(array_$ptr_typ a, array_$ptr_typ b);')
|
||||||
g.definitions.writeln('\tif (a.len != b.len) {')
|
mut fn_builder := strings.new_builder(512)
|
||||||
g.definitions.writeln('\t\treturn false;')
|
fn_builder.writeln('bool ${ptr_typ}_arr_eq(array_$ptr_typ a, array_$ptr_typ b) {')
|
||||||
g.definitions.writeln('\t}')
|
fn_builder.writeln('\tif (a.len != b.len) {')
|
||||||
|
fn_builder.writeln('\t\treturn false;')
|
||||||
|
fn_builder.writeln('\t}')
|
||||||
i := g.new_tmp_var()
|
i := g.new_tmp_var()
|
||||||
g.definitions.writeln('\tfor (int $i = 0; $i < a.len; ++$i) {')
|
fn_builder.writeln('\tfor (int $i = 0; $i < a.len; ++$i) {')
|
||||||
// compare every pair of elements of the two arrays
|
// compare every pair of elements of the two arrays
|
||||||
match elem_sym.kind {
|
match elem_sym.kind {
|
||||||
.string { g.definitions.writeln('\t\tif (string_ne(*(($ptr_typ*)((byte*)a.data+($i*a.element_size))), *(($ptr_typ*)((byte*)b.data+($i*b.element_size))))) {') }
|
.string { fn_builder.writeln('\t\tif (string_ne(*(($ptr_typ*)((byte*)a.data+($i*a.element_size))), *(($ptr_typ*)((byte*)b.data+($i*b.element_size))))) {') }
|
||||||
.struct_ { g.definitions.writeln('\t\tif (memcmp((byte*)a.data+($i*a.element_size), (byte*)b.data+($i*b.element_size), a.element_size)) {') }
|
.struct_ { fn_builder.writeln('\t\tif (memcmp((byte*)a.data+($i*a.element_size), (byte*)b.data+($i*b.element_size), a.element_size)) {') }
|
||||||
.array { g.definitions.writeln('\t\tif (!${ptr_elem_typ}_arr_eq((($elem_typ*)a.data)[$i], (($elem_typ*)b.data)[$i])) {') }
|
.array { fn_builder.writeln('\t\tif (!${ptr_elem_typ}_arr_eq((($elem_typ*)a.data)[$i], (($elem_typ*)b.data)[$i])) {') }
|
||||||
.function { g.definitions.writeln('\t\tif (*((voidptr*)((byte*)a.data+($i*a.element_size))) != *((voidptr*)((byte*)b.data+($i*b.element_size)))) {') }
|
.function { fn_builder.writeln('\t\tif (*((voidptr*)((byte*)a.data+($i*a.element_size))) != *((voidptr*)((byte*)b.data+($i*b.element_size)))) {') }
|
||||||
else { g.definitions.writeln('\t\tif (*(($ptr_typ*)((byte*)a.data+($i*a.element_size))) != *(($ptr_typ*)((byte*)b.data+($i*b.element_size)))) {') }
|
else { fn_builder.writeln('\t\tif (*(($ptr_typ*)((byte*)a.data+($i*a.element_size))) != *(($ptr_typ*)((byte*)b.data+($i*b.element_size)))) {') }
|
||||||
}
|
}
|
||||||
g.definitions.writeln('\t\t\treturn false;')
|
fn_builder.writeln('\t\t\treturn false;')
|
||||||
g.definitions.writeln('\t\t}')
|
fn_builder.writeln('\t\t}')
|
||||||
g.definitions.writeln('\t}')
|
fn_builder.writeln('\t}')
|
||||||
g.definitions.writeln('\treturn true;')
|
fn_builder.writeln('\treturn true;')
|
||||||
g.definitions.writeln('}')
|
fn_builder.writeln('}')
|
||||||
|
g.auto_fn_definitions << fn_builder.str()
|
||||||
return ptr_typ
|
return ptr_typ
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut g Gen) gen_map_equality_fn(left table.Type) string {
|
fn (mut g Gen) gen_map_equality_fn(left table.Type) string {
|
||||||
left_sym := g.table.get_type_symbol(left)
|
left_sym := g.table.get_type_symbol(left)
|
||||||
typ_name := g.typ(left)
|
ptr_typ := g.typ(left).trim('*')
|
||||||
ptr_typ := typ_name[typ_name.index_after('_', 0) + 1..].trim('*')
|
|
||||||
value_sym := g.table.get_type_symbol(left_sym.map_info().value_type)
|
value_sym := g.table.get_type_symbol(left_sym.map_info().value_type)
|
||||||
value_typ := g.typ(left_sym.map_info().value_type)
|
value_typ := g.typ(left_sym.map_info().value_type)
|
||||||
if value_sym.kind == .map {
|
if value_sym.kind == .map {
|
||||||
|
@ -4570,40 +4624,43 @@ fn (mut g Gen) gen_map_equality_fn(left table.Type) string {
|
||||||
return ptr_typ
|
return ptr_typ
|
||||||
}
|
}
|
||||||
g.map_fn_definitions << ptr_typ
|
g.map_fn_definitions << ptr_typ
|
||||||
g.definitions.writeln('bool ${ptr_typ}_map_eq(map_$ptr_typ a, map_$ptr_typ b) {')
|
g.type_definitions.writeln('static bool ${ptr_typ}_map_eq($ptr_typ a, $ptr_typ b);')
|
||||||
g.definitions.writeln('\tif (a.len != b.len) {')
|
mut fn_builder := strings.new_builder(512)
|
||||||
g.definitions.writeln('\t\treturn false;')
|
fn_builder.writeln('bool ${ptr_typ}_map_eq($ptr_typ a, $ptr_typ b) {')
|
||||||
g.definitions.writeln('\t}')
|
fn_builder.writeln('\tif (a.len != b.len) {')
|
||||||
g.definitions.writeln('\tarray_string _keys = map_keys(&a);')
|
fn_builder.writeln('\t\treturn false;')
|
||||||
|
fn_builder.writeln('\t}')
|
||||||
|
fn_builder.writeln('\tarray_string _keys = map_keys(&a);')
|
||||||
i := g.new_tmp_var()
|
i := g.new_tmp_var()
|
||||||
g.definitions.writeln('\tfor (int $i = 0; $i < _keys.len; ++$i) {')
|
fn_builder.writeln('\tfor (int $i = 0; $i < _keys.len; ++$i) {')
|
||||||
g.definitions.writeln('\t\tstring k = string_clone( ((string*)_keys.data)[$i]);')
|
fn_builder.writeln('\t\tstring k = string_clone( ((string*)_keys.data)[$i]);')
|
||||||
if value_sym.kind == .function {
|
if value_sym.kind == .function {
|
||||||
func := value_sym.info as table.FnType
|
func := value_sym.info as table.FnType
|
||||||
ret_styp := g.typ(func.func.return_type)
|
ret_styp := g.typ(func.func.return_type)
|
||||||
g.definitions.write('\t\t$ret_styp (*v) (')
|
fn_builder.write('\t\t$ret_styp (*v) (')
|
||||||
arg_len := func.func.params.len
|
arg_len := func.func.params.len
|
||||||
for j, arg in func.func.params {
|
for j, arg in func.func.params {
|
||||||
arg_styp := g.typ(arg.typ)
|
arg_styp := g.typ(arg.typ)
|
||||||
g.definitions.write('$arg_styp $arg.name')
|
fn_builder.write('$arg_styp $arg.name')
|
||||||
if j < arg_len - 1 {
|
if j < arg_len - 1 {
|
||||||
g.definitions.write(', ')
|
fn_builder.write(', ')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
g.definitions.writeln(') = (*(voidptr*)map_get_1(&a, &k, &(voidptr[]){ 0 }));')
|
fn_builder.writeln(') = (*(voidptr*)map_get_1(&a, &k, &(voidptr[]){ 0 }));')
|
||||||
} else {
|
} else {
|
||||||
g.definitions.writeln('\t\t$value_typ v = (*($value_typ*)map_get_1(&a, &k, &($value_typ[]){ 0 }));')
|
fn_builder.writeln('\t\t$value_typ v = (*($value_typ*)map_get_1(&a, &k, &($value_typ[]){ 0 }));')
|
||||||
}
|
}
|
||||||
match value_sym.kind {
|
match value_sym.kind {
|
||||||
.string { g.definitions.writeln('\t\tif (!map_exists(b, k) || string_ne((*(string*)map_get_1(&b, &k, &(string[]){_SLIT("")})), v)) {') }
|
.string { fn_builder.writeln('\t\tif (!map_exists(b, k) || string_ne((*(string*)map_get_1(&b, &k, &(string[]){_SLIT("")})), v)) {') }
|
||||||
.function { g.definitions.writeln('\t\tif (!map_exists(b, k) || (*(voidptr*)map_get_1(&b, &k, &(voidptr[]){ 0 })) != v) {') }
|
.function { fn_builder.writeln('\t\tif (!map_exists(b, k) || (*(voidptr*)map_get_1(&b, &k, &(voidptr[]){ 0 })) != v) {') }
|
||||||
else { g.definitions.writeln('\t\tif (!map_exists(b, k) || (*($value_typ*)map_get_1(&b, &k, &($value_typ[]){ 0 })) != v) {') }
|
else { fn_builder.writeln('\t\tif (!map_exists(b, k) || (*($value_typ*)map_get_1(&b, &k, &($value_typ[]){ 0 })) != v) {') }
|
||||||
}
|
}
|
||||||
g.definitions.writeln('\t\t\treturn false;')
|
fn_builder.writeln('\t\t\treturn false;')
|
||||||
g.definitions.writeln('\t\t}')
|
fn_builder.writeln('\t\t}')
|
||||||
g.definitions.writeln('\t}')
|
fn_builder.writeln('\t}')
|
||||||
g.definitions.writeln('\treturn true;')
|
fn_builder.writeln('\treturn true;')
|
||||||
g.definitions.writeln('}')
|
fn_builder.writeln('}')
|
||||||
|
g.auto_fn_definitions << fn_builder.str()
|
||||||
return ptr_typ
|
return ptr_typ
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5143,23 +5200,38 @@ fn (mut g Gen) gen_array_contains_method(left_type table.Type) string {
|
||||||
fn_name := '${left_type_str}_contains'
|
fn_name := '${left_type_str}_contains'
|
||||||
if !left_sym.has_method('contains') {
|
if !left_sym.has_method('contains') {
|
||||||
g.type_definitions.writeln('static bool ${fn_name}($left_type_str a, $elem_type_str v); // auto')
|
g.type_definitions.writeln('static bool ${fn_name}($left_type_str a, $elem_type_str v); // auto')
|
||||||
g.auto_str_funcs.writeln('static bool ${fn_name}($left_type_str a, $elem_type_str v) {')
|
mut fn_builder := strings.new_builder(512)
|
||||||
g.auto_str_funcs.writeln('\tfor (int i = 0; i < a.len; ++i) {')
|
fn_builder.writeln('static bool ${fn_name}($left_type_str a, $elem_type_str v) {')
|
||||||
if elem_sym.kind == .string {
|
fn_builder.writeln('\tfor (int i = 0; i < a.len; ++i) {')
|
||||||
g.auto_str_funcs.writeln('\t\tif (string_eq((*(string*)array_get(a, i)), v)) {')
|
match elem_sym.kind {
|
||||||
} else if elem_sym.kind == .array {
|
.string {
|
||||||
ptr_typ := g.gen_array_equality_fn(left_info.elem_type)
|
fn_builder.writeln('\t\tif (string_eq((*(string*)array_get(a, i)), v)) {')
|
||||||
g.auto_str_funcs.writeln('\t\tif (${ptr_typ}_arr_eq(*($elem_type_str*)array_get(a, i), v)) {')
|
|
||||||
} else if elem_sym.kind == .function {
|
|
||||||
g.auto_str_funcs.writeln('\t\tif ((*(voidptr*)array_get(a, i)) == v) {')
|
|
||||||
} else {
|
|
||||||
g.auto_str_funcs.writeln('\t\tif ((*($elem_type_str*)array_get(a, i)) == v) {')
|
|
||||||
}
|
}
|
||||||
g.auto_str_funcs.writeln('\t\t\treturn true;')
|
.array {
|
||||||
g.auto_str_funcs.writeln('\t\t}')
|
ptr_typ := g.gen_array_equality_fn(left_info.elem_type)
|
||||||
g.auto_str_funcs.writeln('\t}')
|
fn_builder.writeln('\t\tif (${ptr_typ}_arr_eq(*($elem_type_str*)array_get(a, i), v)) {')
|
||||||
g.auto_str_funcs.writeln('\treturn false;')
|
}
|
||||||
g.auto_str_funcs.writeln('}')
|
.function {
|
||||||
|
fn_builder.writeln('\t\tif ((*(voidptr*)array_get(a, i)) == v) {')
|
||||||
|
}
|
||||||
|
.map {
|
||||||
|
ptr_typ := g.gen_map_equality_fn(left_info.elem_type)
|
||||||
|
fn_builder.writeln('\t\tif (${ptr_typ}_map_eq(*($elem_type_str*)array_get(a, i), v)) {')
|
||||||
|
}
|
||||||
|
.struct_ {
|
||||||
|
ptr_typ := g.gen_struct_equality_fn(left_info.elem_type)
|
||||||
|
fn_builder.writeln('\t\tif (${ptr_typ}_struct_eq(*($elem_type_str*)array_get(a, i), v)) {')
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fn_builder.writeln('\t\tif ((*($elem_type_str*)array_get(a, i)) == v) {')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn_builder.writeln('\t\t\treturn true;')
|
||||||
|
fn_builder.writeln('\t\t}')
|
||||||
|
fn_builder.writeln('\t}')
|
||||||
|
fn_builder.writeln('\treturn false;')
|
||||||
|
fn_builder.writeln('}')
|
||||||
|
g.auto_fn_definitions << fn_builder.str()
|
||||||
left_sym.register_method(&table.Fn{
|
left_sym.register_method(&table.Fn{
|
||||||
name: 'contains'
|
name: 'contains'
|
||||||
params: [table.Param{
|
params: [table.Param{
|
||||||
|
|
Loading…
Reference in New Issue