aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--builtins/array.c10
-rw-r--r--builtins/array.h2
-rw-r--r--compile.c5
-rw-r--r--typecheck.c1
4 files changed, 18 insertions, 0 deletions
diff --git a/builtins/array.c b/builtins/array.c
index b310e43d..9c393699 100644
--- a/builtins/array.c
+++ b/builtins/array.c
@@ -211,6 +211,16 @@ public void Array$remove_item(array_t *arr, void *item, Int_t max_removals, cons
}
}
+public Int_t Array$find(array_t arr, void *item, const TypeInfo *type)
+{
+ const TypeInfo *item_type = type->ArrayInfo.item;
+ for (int64_t i = 0; i < arr.length; i++) {
+ if (generic_equal(item, arr.data + i*arr.stride, item_type))
+ return I(i+1);
+ }
+ return I(0);
+}
+
public void Array$sort(array_t *arr, closure_t comparison, int64_t padded_item_size)
{
if (arr->data_refcount != 0 || (int64_t)arr->stride != padded_item_size)
diff --git a/builtins/array.h b/builtins/array.h
index 856bd07b..e4540340 100644
--- a/builtins/array.h
+++ b/builtins/array.h
@@ -61,6 +61,8 @@ void Array$insert_all(array_t *arr, array_t to_insert, Int_t index, int64_t padd
void Array$remove_at(array_t *arr, Int_t index, Int_t count, int64_t padded_item_size);
void Array$remove_item(array_t *arr, void *item, Int_t max_removals, const TypeInfo *type);
#define Array$remove_item_value(arr, item_expr, max, type) ({ __typeof(item_expr) item = item_expr; Array$remove_item(arr, &item, max, type); })
+Int_t Array$find(array_t arr, void *item, const TypeInfo *type);
+#define Array$find_value(arr, item_expr, type) ({ __typeof(item_expr) item = item_expr; Array$find(arr, &item, type); })
void Array$sort(array_t *arr, closure_t comparison, int64_t padded_item_size);
array_t Array$sorted(array_t arr, closure_t comparison, int64_t padded_item_size);
void Array$shuffle(array_t *arr, int64_t padded_item_size);
diff --git a/compile.c b/compile.c
index 71800a97..ee4d2e5a 100644
--- a/compile.c
+++ b/compile.c
@@ -2194,6 +2194,11 @@ CORD compile(env_t *env, ast_t *ast)
CORD self = compile_to_pointer_depth(env, call->self, 1, false);
(void)compile_arguments(env, ast, NULL, call->args);
return CORD_all("Array$clear(", self, ")");
+ } else if (streq(call->name, "find")) {
+ CORD self = compile_to_pointer_depth(env, call->self, 0, false);
+ arg_t *arg_spec = new(arg_t, .name="item", .type=item_t);
+ return CORD_all("Array$find_value(", self, ", ", compile_arguments(env, ast, arg_spec, call->args),
+ ", ", compile_type_info(env, self_value_t), ")");
} else if (streq(call->name, "from")) {
CORD self = compile_to_pointer_depth(env, call->self, 0, false);
arg_t *arg_spec = new(arg_t, .name="first", .type=INT_TYPE);
diff --git a/typecheck.c b/typecheck.c
index b893ab93..388e8d7a 100644
--- a/typecheck.c
+++ b/typecheck.c
@@ -714,6 +714,7 @@ type_t *get_type(env_t *env, ast_t *ast)
else if (streq(call->name, "by")) return self_value_t;
else if (streq(call->name, "clear")) return Type(VoidType);
else if (streq(call->name, "counts")) return Type(TableType, .key_type=Match(self_value_t, ArrayType)->item_type, .value_type=INT_TYPE);
+ else if (streq(call->name, "find")) return INT_TYPE;
else if (streq(call->name, "from")) return self_value_t;
else if (streq(call->name, "has")) return Type(BoolType);
else if (streq(call->name, "heap_pop")) return Match(self_value_t, ArrayType)->item_type;