parent
0edec06eac
commit
21cd765eaa
|
@ -1174,3 +1174,24 @@ fn test_multi_array_insert() {
|
||||||
b.insert(0, [[1, 2, 3]])
|
b.insert(0, [[1, 2, 3]])
|
||||||
assert b == [[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
|
// TODO: remove this for actual methods, use only for compiler magic
|
||||||
// FIXME: Argument count != 1 will break these
|
// FIXME: Argument count != 1 will break these
|
||||||
if left_type_sym.kind == .array &&
|
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
|
mut elem_typ := table.void_type
|
||||||
is_filter_map := method_name in ['filter', 'map']
|
is_filter_map := method_name in ['filter', 'map']
|
||||||
is_sort := method_name == 'sort'
|
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
|
// call_expr.return_type = call_expr.receiver_type
|
||||||
} else if method_name == 'sort' {
|
} else if method_name == 'sort' {
|
||||||
call_expr.return_type = table.void_type
|
call_expr.return_type = table.void_type
|
||||||
|
} else if method_name == 'contains' {
|
||||||
|
call_expr.return_type = table.bool_type
|
||||||
}
|
}
|
||||||
return call_expr.return_type
|
return call_expr.return_type
|
||||||
} else if left_type_sym.kind == .map && method_name == 'clone' {
|
} else if left_type_sym.kind == .map && method_name == 'clone' {
|
||||||
|
|
|
@ -2982,20 +2982,16 @@ fn (mut g Gen) infix_expr(node ast.InfixExpr) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if left_sym.kind == .function {
|
fn_name := g.gen_array_contains_method(node.right_type)
|
||||||
g.write('_IN(voidptr, ')
|
g.write('(${fn_name}(')
|
||||||
} 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(', ')
|
|
||||||
if node.right_type.is_ptr() {
|
if node.right_type.is_ptr() {
|
||||||
g.write('*')
|
g.write('*')
|
||||||
}
|
}
|
||||||
g.expr(node.right)
|
g.expr(node.right)
|
||||||
g.write(')')
|
g.write(',')
|
||||||
|
g.expr(node.left)
|
||||||
|
g.write('))')
|
||||||
|
return
|
||||||
} else if right_sym.kind == .map {
|
} else if right_sym.kind == .map {
|
||||||
g.write('_IN_MAP(')
|
g.write('_IN_MAP(')
|
||||||
g.expr(node.left)
|
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]
|
[inline]
|
||||||
fn (g &Gen) nth_stmt_pos(n int) int {
|
fn (g &Gen) nth_stmt_pos(n int) int {
|
||||||
return g.stmt_path_pos[g.stmt_path_pos.len - (1 + n)]
|
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
|
// take the address of an rvalue
|
||||||
#define ADDR(type, expr) (&((type[]){expr}[0]))
|
#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 _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)
|
#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
|
// 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_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; }
|
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)
|
g.gen_array_prepend(node)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
'contains' {
|
||||||
|
g.gen_array_contains(node)
|
||||||
|
return
|
||||||
|
}
|
||||||
else {}
|
else {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue