From b3322c93e9eb3f4573d98f577045410ef0543464 Mon Sep 17 00:00:00 2001 From: Laria Carolin Chabowski Date: Fri, 15 Apr 2022 14:41:22 +0200 Subject: [PATCH] Move scope functions/structs out of context.[ch] --- src/Makefile.am | 2 + src/context.c | 142 +---------------------------------------------- src/context.h | 15 +---- src/gc.c | 1 + src/scope.c | 144 ++++++++++++++++++++++++++++++++++++++++++++++++ src/scope.h | 30 ++++++++++ 6 files changed, 179 insertions(+), 155 deletions(-) create mode 100644 src/scope.c create mode 100644 src/scope.h diff --git a/src/Makefile.am b/src/Makefile.am index bd357e5..4e43da2 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -17,6 +17,7 @@ libapfl_a_SOURCES += parser.c libapfl_a_SOURCES += position.c libapfl_a_SOURCES += resizable.c libapfl_a_SOURCES += source_readers.c +libapfl_a_SOURCES += scope.c libapfl_a_SOURCES += strings.c libapfl_a_SOURCES += token.c libapfl_a_SOURCES += tokenizer.c @@ -31,6 +32,7 @@ apfl_internal_headers += gc.h apfl_internal_headers += hashmap.h apfl_internal_headers += internal.h apfl_internal_headers += resizable.h +apfl_internal_headers += scope.h apfl_internal_headers += value.h EXTRA_DIST = $(apfl_internal_headers) apfl.h diff --git a/src/context.c b/src/context.c index 2b3184a..c11e6d5 100644 --- a/src/context.c +++ b/src/context.c @@ -10,8 +10,6 @@ #include "resizable.h" #include "value.h" -typedef struct apfl_value *variable; - static struct stack * stack_new(struct gc *gc) { @@ -169,144 +167,6 @@ apfl_stack_drop(apfl_ctx ctx, apfl_stackidx index) return apfl_stack_pop(ctx, &value, index); } -static bool -scope_keys_eq(void *opaque, const void *_a, const void *_b) -{ - (void)opaque; - const struct apfl_string * const *a = _a; - const struct apfl_string * const *b = _b; - - return apfl_string_eq(**a, **b); -} - -static apfl_hash -scope_calc_hash(void *opaque, const void *_key) -{ - (void)opaque; - const struct apfl_string *const*key = _key; - struct apfl_string_view sv = apfl_string_view_from(**key); - return apfl_hash_fnv1a(sv.bytes, sv.len); -} - -static struct scope * -scope_new(struct gc *gc) -{ - struct apfl_hashmap map; - if (!apfl_hashmap_init( - &map, - gc->allocator, - (struct apfl_hashmap_callbacks) { - .opaque = NULL, - .keys_eq = scope_keys_eq, - .calc_hash = scope_calc_hash, - }, - sizeof(struct apfl_string *), - sizeof(variable) - )) { - return NULL; - } - - struct scope *scope = apfl_gc_new_scope(gc); - if (scope == NULL) { - apfl_hashmap_deinit(&map); - return NULL; - } - - *scope = (struct scope) { - .map = map, - }; - - return scope; -} - -void -apfl_scope_deinit(struct apfl_allocator allocator, struct scope *scope) -{ - (void)allocator; - apfl_hashmap_deinit(&scope->map); -} - -void -apfl_gc_var_traverse(struct apfl_value *var, gc_visitor cb, void *opaque) -{ - struct gc_object *child = apfl_value_get_gc_object(*var); - if (child != NULL) { - cb(opaque, child); - } -} - -void -apfl_gc_scope_traverse(struct scope *scope, gc_visitor cb, void *opaque) -{ - HASHMAP_EACH(&scope->map, cur) { - struct apfl_string **k = apfl_hashmap_cursor_peek_key(cur); - assert(k != NULL); - cb(opaque, GC_OBJECT_FROM(*k, GC_TYPE_STRING)); - - variable *v = apfl_hashmap_cursor_peek_value(cur); - assert(v != NULL); - cb(opaque, GC_OBJECT_FROM(*v, GC_TYPE_VAR)); - } -} - -bool -apfl_scope_get(struct scope *scope, struct apfl_string *name, struct apfl_value *out) -{ - variable var; - if (!apfl_hashmap_get(&scope->map, &name, &var)) { - return false; - } - - // The value is now in the variable and outside of it (presumably to be - // saved onto the stack). We need to set the COW flag so a mutation of one - // copy doesn't affect the other one. - *out = apfl_value_set_cow_flag(*var); - - return true; -} - -static variable -get_or_create_variable(struct gc *gc, struct scope *scope, struct apfl_string *name) -{ - variable var; - if (apfl_hashmap_get(&scope->map, &name, &var)) { - return var; - } - - struct apfl_hashmap_prepared_set prepared_set; - if (!apfl_hashmap_prepare_set(&scope->map, &prepared_set, &name)) { - return NULL; - } - - var = apfl_gc_new_var(gc); - if (var == NULL) { - return NULL; - } - - *var = (struct apfl_value) { .type = VALUE_NIL }; - apfl_hashmap_set_prepared(prepared_set, &var); - - return var; -} - -bool -apfl_scope_set(struct gc *gc, struct scope *scope, struct apfl_string *name, struct apfl_value value) -{ - variable var = get_or_create_variable(gc, scope, name); - if (var == NULL) { - return false; - } - - *var = value; - return true; -} - -bool -apfl_scope_create_var(struct gc *gc, struct scope *scope, struct apfl_string *name) -{ - return get_or_create_variable(gc, scope, name) != NULL; -} - apfl_ctx apfl_ctx_new(struct apfl_allocator base_allocator) { @@ -320,7 +180,7 @@ apfl_ctx_new(struct apfl_allocator base_allocator) return NULL; } - if ((ctx->scope = scope_new(&ctx->gc)) == NULL) { + if ((ctx->scope = apfl_scope_new(&ctx->gc)) == NULL) { goto error; } diff --git a/src/context.h b/src/context.h index c5e74ee..fee0614 100644 --- a/src/context.h +++ b/src/context.h @@ -11,6 +11,7 @@ extern "C" { #include "hashmap.h" #include "gc.h" #include "value.h" +#include "scope.h" struct stack { struct apfl_value *items; @@ -18,10 +19,6 @@ struct stack { size_t cap; }; -struct scope { - struct apfl_hashmap map; -}; - struct apfl_ctx_data { struct gc gc; @@ -34,16 +31,6 @@ struct apfl_ctx_data { void apfl_stack_deinit(struct apfl_allocator, struct stack *); void apfl_gc_stack_traverse(struct stack *, gc_visitor, void *); -void apfl_scope_deinit(struct apfl_allocator, struct scope *); - -bool apfl_scope_get(struct scope *, struct apfl_string *name, struct apfl_value *out); -bool apfl_scope_set(struct gc *, struct scope *, struct apfl_string *name, struct apfl_value value); -bool apfl_scope_create_var(struct gc *, struct scope *, struct apfl_string *name); - - -void apfl_gc_var_traverse(struct apfl_value *, gc_visitor, void *); -void apfl_gc_scope_traverse(struct scope *, gc_visitor, void *); - bool apfl_stack_push(apfl_ctx, struct apfl_value); bool apfl_stack_check_index(apfl_ctx, apfl_stackidx *); bool apfl_stack_pop(apfl_ctx, struct apfl_value *value, apfl_stackidx); diff --git a/src/gc.c b/src/gc.c index 63df428..a25f1de 100644 --- a/src/gc.c +++ b/src/gc.c @@ -7,6 +7,7 @@ #include "gc.h" #include "hashmap.h" #include "resizable.h" +#include "scope.h" #include "value.h" #define DEBUG_GC 1 diff --git a/src/scope.c b/src/scope.c new file mode 100644 index 0000000..de24cd8 --- /dev/null +++ b/src/scope.c @@ -0,0 +1,144 @@ +#include + +#include "hashmap.h" +#include "scope.h" + +typedef struct apfl_value *variable; + +void +apfl_scope_deinit(struct apfl_allocator allocator, struct scope *scope) +{ + (void)allocator; + apfl_hashmap_deinit(&scope->map); +} + +static bool +scope_keys_eq(void *opaque, const void *_a, const void *_b) +{ + (void)opaque; + const struct apfl_string * const *a = _a; + const struct apfl_string * const *b = _b; + + return apfl_string_eq(**a, **b); +} + +static apfl_hash +scope_calc_hash(void *opaque, const void *_key) +{ + (void)opaque; + const struct apfl_string *const*key = _key; + struct apfl_string_view sv = apfl_string_view_from(**key); + return apfl_hash_fnv1a(sv.bytes, sv.len); +} + +struct scope * +apfl_scope_new(struct gc *gc) +{ + struct apfl_hashmap map; + if (!apfl_hashmap_init( + &map, + gc->allocator, + (struct apfl_hashmap_callbacks) { + .opaque = NULL, + .keys_eq = scope_keys_eq, + .calc_hash = scope_calc_hash, + }, + sizeof(struct apfl_string *), + sizeof(variable) + )) { + return NULL; + } + + struct scope *scope = apfl_gc_new_scope(gc); + if (scope == NULL) { + apfl_hashmap_deinit(&map); + return NULL; + } + + *scope = (struct scope) { + .map = map, + }; + + return scope; +} + +void +apfl_gc_var_traverse(struct apfl_value *var, gc_visitor cb, void *opaque) +{ + struct gc_object *child = apfl_value_get_gc_object(*var); + if (child != NULL) { + cb(opaque, child); + } +} + +void +apfl_gc_scope_traverse(struct scope *scope, gc_visitor cb, void *opaque) +{ + HASHMAP_EACH(&scope->map, cur) { + struct apfl_string **k = apfl_hashmap_cursor_peek_key(cur); + assert(k != NULL); + cb(opaque, GC_OBJECT_FROM(*k, GC_TYPE_STRING)); + + variable *v = apfl_hashmap_cursor_peek_value(cur); + assert(v != NULL); + cb(opaque, GC_OBJECT_FROM(*v, GC_TYPE_VAR)); + } +} + +bool +apfl_scope_get(struct scope *scope, struct apfl_string *name, struct apfl_value *out) +{ + variable var; + if (!apfl_hashmap_get(&scope->map, &name, &var)) { + return false; + } + + // The value is now in the variable and outside of it (presumably to be + // saved onto the stack). We need to set the COW flag so a mutation of one + // copy doesn't affect the other one. + *out = apfl_value_set_cow_flag(*var); + + return true; +} + +static variable +get_or_create_variable(struct gc *gc, struct scope *scope, struct apfl_string *name) +{ + variable var; + if (apfl_hashmap_get(&scope->map, &name, &var)) { + return var; + } + + struct apfl_hashmap_prepared_set prepared_set; + if (!apfl_hashmap_prepare_set(&scope->map, &prepared_set, &name)) { + return NULL; + } + + var = apfl_gc_new_var(gc); + if (var == NULL) { + return NULL; + } + + *var = (struct apfl_value) { .type = VALUE_NIL }; + apfl_hashmap_set_prepared(prepared_set, &var); + + return var; +} + +bool +apfl_scope_set(struct gc *gc, struct scope *scope, struct apfl_string *name, struct apfl_value value) +{ + variable var = get_or_create_variable(gc, scope, name); + if (var == NULL) { + return false; + } + + *var = value; + return true; +} + +bool +apfl_scope_create_var(struct gc *gc, struct scope *scope, struct apfl_string *name) +{ + return get_or_create_variable(gc, scope, name) != NULL; +} diff --git a/src/scope.h b/src/scope.h new file mode 100644 index 0000000..9cadb2f --- /dev/null +++ b/src/scope.h @@ -0,0 +1,30 @@ +#ifndef APFL_SCOPE_H +#define APFL_SCOPE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "gc.h" +#include "hashmap.h" +#include "value.h" + +struct scope { + struct apfl_hashmap map; +}; + +struct scope *apfl_scope_new(struct gc *); +void apfl_scope_deinit(struct apfl_allocator, struct scope *); + +bool apfl_scope_get(struct scope *, struct apfl_string *name, struct apfl_value *out); +bool apfl_scope_set(struct gc *, struct scope *, struct apfl_string *name, struct apfl_value value); +bool apfl_scope_create_var(struct gc *, struct scope *, struct apfl_string *name); + +void apfl_gc_var_traverse(struct apfl_value *, gc_visitor, void *); +void apfl_gc_scope_traverse(struct scope *, gc_visitor, void *); + +#ifdef __cplusplus +} +#endif + +#endif