2022-07-28 18:46:32 +00:00
|
|
|
#include "alloc.h"
|
|
|
|
|
#include "gc.h"
|
|
|
|
|
#include "matcher.h"
|
|
|
|
|
|
|
|
|
|
static bool
|
|
|
|
|
init_values_list(struct apfl_allocator allocator, struct apfl_value **list, size_t len)
|
|
|
|
|
{
|
|
|
|
|
if (len == 0) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((*list = ALLOC_LIST(allocator, struct apfl_value, len)) == NULL) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (size_t i = 0; i < len; i++) {
|
|
|
|
|
(*list)[i] = (struct apfl_value) { .type = VALUE_NIL };
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct matcher *
|
|
|
|
|
apfl_matcher_new(struct gc *gc, struct matcher_instruction_list *milist)
|
|
|
|
|
{
|
|
|
|
|
struct matcher matcher = {
|
|
|
|
|
.instructions = milist,
|
2022-08-12 12:42:49 +00:00
|
|
|
.value_count = 0,
|
|
|
|
|
.capture_count = 0,
|
2022-07-28 18:46:32 +00:00
|
|
|
.values = NULL,
|
|
|
|
|
.captures = NULL,
|
|
|
|
|
.result = false,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (!init_values_list(gc->allocator, &matcher.values, milist->value_count)) {
|
|
|
|
|
goto error;
|
|
|
|
|
}
|
2022-08-12 12:42:49 +00:00
|
|
|
matcher.value_count = milist->value_count;
|
2022-07-28 18:46:32 +00:00
|
|
|
|
|
|
|
|
if (!init_values_list(gc->allocator, &matcher.captures, milist->capture_count)) {
|
|
|
|
|
goto error;
|
|
|
|
|
}
|
2022-08-12 12:42:49 +00:00
|
|
|
matcher.capture_count = milist->capture_count;
|
2022-07-28 18:46:32 +00:00
|
|
|
|
|
|
|
|
struct matcher *gc_matcher = apfl_gc_new_matcher(gc);
|
|
|
|
|
if (gc_matcher == NULL) {
|
|
|
|
|
goto error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*gc_matcher = matcher;
|
|
|
|
|
|
|
|
|
|
return gc_matcher;
|
|
|
|
|
|
|
|
|
|
error:
|
|
|
|
|
apfl_matcher_deinit(gc->allocator, &matcher);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
apfl_matcher_deinit(struct apfl_allocator allocator, struct matcher *matcher)
|
|
|
|
|
{
|
2022-08-12 12:42:49 +00:00
|
|
|
FREE_LIST(allocator, matcher->values, matcher->value_count);
|
|
|
|
|
FREE_LIST(allocator, matcher->captures, matcher->capture_count);
|
2022-07-28 18:46:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
apfl_gc_matcher_traverse(struct matcher *matcher, gc_visitor visitor, void *opaque)
|
|
|
|
|
{
|
|
|
|
|
visitor(opaque, GC_OBJECT_FROM(matcher->instructions, GC_TYPE_MATCHER_INSTRUCTIONS));
|
|
|
|
|
|
|
|
|
|
for (size_t i = 0; i < matcher->instructions->value_count; i++) {
|
|
|
|
|
struct gc_object *object = apfl_value_get_gc_object(matcher->values[i]);
|
|
|
|
|
if (object != NULL) {
|
|
|
|
|
visitor(opaque, object);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (size_t i = 0; i < matcher->instructions->capture_count; i++) {
|
|
|
|
|
struct gc_object *object = apfl_value_get_gc_object(matcher->captures[i]);
|
|
|
|
|
if (object != NULL) {
|
|
|
|
|
visitor(opaque, object);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|