parent
0edec06eac
commit
21cd765eaa
|
@ -1174,3 +1174,24 @@ fn test_multi_array_insert() {
|
|||
b.insert(0, [[1, 2, 3]])
|
||||
assert b == [[1, 2, 3]]
|
||||
}
|
||||
|
||||
fn test_multi_array_in() {
|
||||
a := [[1]]
|
||||
println([1] in a)
|
||||
assert [1] in a
|
||||
}
|
||||
|
||||
fn test_any_type_array_contains() {
|
||||
a := [true, false]
|
||||
assert a.contains(true)
|
||||
assert true in a
|
||||
assert a.contains(false)
|
||||
assert false in a
|
||||
b := [i64(2), 3, 4]
|
||||
assert b.contains(i64(3))
|
||||
assert 5 !in b
|
||||
c := [[1], [2]]
|
||||
assert c.contains([1])
|
||||
assert [2] in c
|
||||
assert [3] !in c
|
||||
}
|
||||
|
|
|
@ -1155,7 +1155,8 @@ pub fn (mut c Checker) call_method(mut call_expr ast.CallExpr) table.Type {
|
|||
// TODO: remove this for actual methods, use only for compiler magic
|
||||
// FIXME: Argument count != 1 will break these
|
||||
if left_type_sym.kind == .array &&
|
||||
method_name in ['filter', 'clone', 'repeat', 'reverse', 'map', 'slice', 'sort'] {
|
||||
method_name in
|
||||
['filter', 'clone', 'repeat', 'reverse', 'map', 'slice', 'sort', 'contains'] {
|
||||
mut elem_typ := table.void_type
|
||||
is_filter_map := method_name in ['filter', 'map']
|
||||
is_sort := method_name == 'sort'
|
||||
|
@ -1204,6 +1205,8 @@ pub fn (mut c Checker) call_method(mut call_expr ast.CallExpr) table.Type {
|
|||
// call_expr.return_type = call_expr.receiver_type
|
||||
} else if method_name == 'sort' {
|
||||
call_expr.return_type = table.void_type
|
||||
} else if method_name == 'contains' {
|
||||
call_expr.return_type = table.bool_type
|
||||
}
|
||||
return call_expr.return_type
|
||||
} else if left_type_sym.kind == .map && method_name == 'clone' {
|
||||
|
|
|
@ -2982,20 +2982,16 @@ fn (mut g Gen) infix_expr(node ast.InfixExpr) {
|
|||
return
|
||||
}
|
||||
}
|
||||
if left_sym.kind == .function {
|
||||
g.write('_IN(voidptr, ')
|
||||
} else {
|
||||
elem_type := right_sym.array_info().elem_type
|
||||
styp := g.typ(g.table.mktyp(elem_type))
|
||||
g.write('_IN($styp, ')
|
||||
}
|
||||
g.expr(node.left)
|
||||
g.write(', ')
|
||||
fn_name := g.gen_array_contains_method(node.right_type)
|
||||
g.write('(${fn_name}(')
|
||||
if node.right_type.is_ptr() {
|
||||
g.write('*')
|
||||
}
|
||||
g.expr(node.right)
|
||||
g.write(')')
|
||||
g.write(',')
|
||||
g.expr(node.left)
|
||||
g.write('))')
|
||||
return
|
||||
} else if right_sym.kind == .map {
|
||||
g.write('_IN_MAP(')
|
||||
g.expr(node.left)
|
||||
|
@ -5134,6 +5130,61 @@ fn (mut g Gen) gen_array_prepend(node ast.CallExpr) {
|
|||
}
|
||||
}
|
||||
|
||||
fn (mut g Gen) gen_array_contains_method(left_type table.Type) string {
|
||||
mut left_sym := g.table.get_type_symbol(left_type)
|
||||
mut left_type_str := g.typ(left_type).replace('*', '')
|
||||
left_info := left_sym.info as table.Array
|
||||
mut elem_type_str := g.typ(left_info.elem_type)
|
||||
elem_sym := g.table.get_type_symbol(left_info.elem_type)
|
||||
if elem_sym.kind == .function {
|
||||
left_type_str = 'array_voidptr'
|
||||
elem_type_str = 'voidptr'
|
||||
}
|
||||
fn_name := '${left_type_str}_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.auto_str_funcs.writeln('static bool ${fn_name}($left_type_str a, $elem_type_str v) {')
|
||||
g.auto_str_funcs.writeln('\tfor (int i = 0; i < a.len; ++i) {')
|
||||
if elem_sym.kind == .string {
|
||||
g.auto_str_funcs.writeln('\t\tif (string_eq((*(string*)array_get(a, i)), v)) {')
|
||||
} else if elem_sym.kind == .array {
|
||||
ptr_typ := g.gen_array_equality_fn(left_info.elem_type)
|
||||
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;')
|
||||
g.auto_str_funcs.writeln('\t\t}')
|
||||
g.auto_str_funcs.writeln('\t}')
|
||||
g.auto_str_funcs.writeln('\treturn false;')
|
||||
g.auto_str_funcs.writeln('}')
|
||||
left_sym.register_method(&table.Fn{
|
||||
name: 'contains'
|
||||
params: [table.Param{
|
||||
typ: left_type
|
||||
}, table.Param{
|
||||
typ: left_info.elem_type
|
||||
}]
|
||||
})
|
||||
}
|
||||
return fn_name
|
||||
}
|
||||
|
||||
// `nums.contains(2)`
|
||||
fn (mut g Gen) gen_array_contains(node ast.CallExpr) {
|
||||
fn_name := g.gen_array_contains_method(node.left_type)
|
||||
g.write('${fn_name}(')
|
||||
if node.left_type.is_ptr() {
|
||||
g.write('*')
|
||||
}
|
||||
g.expr(node.left)
|
||||
g.write(',')
|
||||
g.expr(node.args[0].expr)
|
||||
g.write(')')
|
||||
}
|
||||
|
||||
[inline]
|
||||
fn (g &Gen) nth_stmt_pos(n int) int {
|
||||
return g.stmt_path_pos[g.stmt_path_pos.len - (1 + n)]
|
||||
|
|
|
@ -272,23 +272,8 @@ static void* g_live_info = NULL;
|
|||
// take the address of an rvalue
|
||||
#define ADDR(type, expr) (&((type[]){expr}[0]))
|
||||
#define _PUSH_MANY(arr, val, tmp, tmp_typ) {tmp_typ tmp = (val); array_push_many(arr, tmp.data, tmp.len);}
|
||||
#define _IN(typ, val, arr) array_##typ##_contains(arr, val)
|
||||
#define _IN_MAP(val, m) map_exists(m, val)
|
||||
|
||||
// these macros have corresponding implementations in builtin/int.v with different signedness
|
||||
#define array_i8_contains(a, b) array_byte_contains(a, (byte)(b))
|
||||
#define array_i16_contains(a, b) array_u16_contains(a, (u16)(b))
|
||||
#define array_u32_contains(a, b) array_int_contains(a, (int)(b))
|
||||
#define array_i64_contains(a, b) array_u64_contains(a, (u64)(b))
|
||||
#define array_rune_contains(a, b) array_int_contains(a, (int)(b))
|
||||
#define array_f32_contains(a, b) array_int_contains(a, *(int*)&((f32[]){(b)}))
|
||||
#define array_f64_contains(a, b) array_u64_contains(a, *(u64*)&((f64[]){(b)}))
|
||||
#ifdef TARGET_IS_64BIT
|
||||
#define array_voidptr_contains(a, b) array_u64_contains(a, (u64)(b))
|
||||
#else
|
||||
#define array_voidptr_contains(a, b) array_int_contains(a, (int)(b))
|
||||
#endif
|
||||
|
||||
// unsigned/signed comparisons
|
||||
static inline bool _us32_gt(uint32_t a, int32_t b) { return a > INT32_MAX || (int32_t)a > b; }
|
||||
static inline bool _us32_ge(uint32_t a, int32_t b) { return a >= INT32_MAX || (int32_t)a >= b; }
|
||||
|
|
|
@ -370,6 +370,10 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
|
|||
g.gen_array_prepend(node)
|
||||
return
|
||||
}
|
||||
'contains' {
|
||||
g.gen_array_contains(node)
|
||||
return
|
||||
}
|
||||
else {}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue