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