apfl/src/matcher.c

80 lines
2 KiB
C
Raw Normal View History

#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,
.values = NULL,
.captures = NULL,
.result = false,
};
if (!init_values_list(gc->allocator, &matcher.values, milist->value_count)) {
goto error;
}
if (!init_values_list(gc->allocator, &matcher.captures, milist->capture_count)) {
goto error;
}
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)
{
FREE_LIST(allocator, matcher->values, matcher->instructions->value_count);
FREE_LIST(allocator, matcher->captures, matcher->instructions->capture_count);
}
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);
}
}
}