From a5ba8d58907f691e05734d5a4dc694262aca42b5 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=A9mie=20Astor?= Date: Tue, 3 May 2022 14:32:48 +0200 Subject: [PATCH] :art: Proper global scoping --- include/gwion.h | 2 +- include/gwiondata.h | 8 +++- include/plug.h | 2 +- src/env/context.c | 21 ++++++--- src/env/env.c | 10 ++--- src/gwion.c | 21 ++++----- src/gwiondata.c | 3 +- src/plug.c | 104 ++++++++++++++++++++++++++++---------------- 8 files changed, 106 insertions(+), 65 deletions(-) diff --git a/include/gwion.h b/include/gwion.h index 5fdf4b33..4f854245 100644 --- a/include/gwion.h +++ b/include/gwion.h @@ -26,7 +26,7 @@ ANN void gwion_end(const Gwion gwion); void free_code_instr(const Vector v, const Gwion gwion); ANN void gwion_end_child(const VM_Shred shred, const Gwion gwion); ANN void push_global(const Gwion gwion, const m_str name); -ANN Nspc pop_global(const Gwion gwion); +ANN void pop_global(const Gwion gwion); __attribute__((returns_nonnull)) ANN static inline Value type_value(const Gwion gwion, const Type t) { return (Value)nspc_lookup_value1(t->info->value->from->owner, diff --git a/include/gwiondata.h b/include/gwiondata.h index 39203c68..e1c9323b 100644 --- a/include/gwiondata.h +++ b/include/gwiondata.h @@ -1,5 +1,11 @@ #ifndef __GWIONDATA #define __GWIONDATA + +typedef struct Plugs { + struct Map_ map; //! map of plugs + struct Vector_ vec; //! dependencies +} Plugs; + typedef struct GwionData_ { struct Map_ freearg; struct Map_ id; @@ -7,7 +13,7 @@ typedef struct GwionData_ { struct Vector_ child; struct Vector_ child2; struct Passes_ *passes; - struct Map_ plug; + Plugs *plugs; bool cdoc; } GwionData; diff --git a/include/plug.h b/include/plug.h index 18ade2d7..e53a0403 100644 --- a/include/plug.h +++ b/include/plug.h @@ -4,7 +4,7 @@ ANN m_bool plug_ini(const struct Gwion_ *, const Vector); ANN m_bool driver_ini(const struct Gwion_ *); ANN void plug_run(const struct Gwion_ *, const Map); -ANN void free_plug(const struct Gwion_ *); +ANN void free_plug(const Gwion); ANN void * get_module(const struct Gwion_ *, const m_str); ANN void set_module(const struct Gwion_ *gwion, const m_str name, void *const ptr); diff --git a/src/env/context.c b/src/env/context.c index b0c9c58d..4f73e29e 100644 --- a/src/env/context.c +++ b/src/env/context.c @@ -32,14 +32,21 @@ ANN void load_context(const Context context, const Env env) { env->curr = context->nspc; } +ANN static void clean(const Nspc nspc, const Env env) { + env->global_nspc = nspc->parent; + nspc_remref(nspc, env->gwion); +} + ANN void unload_context(const Context ctx, const Env env) { - const Nspc global = env->global_nspc; + const Nspc global = ctx->nspc->parent; + if(global != env->global_nspc) exit(3); context_remref(ctx, env->gwion); env->curr = (Nspc)vector_pop(&env->scope->nspc_stack); - if(ctx->error) { - nspc_remref(global, env->gwion); - env->global_nspc = global->parent; - } - else if(!ctx->global) - env->global_nspc = global->parent; + const Nspc user = (Nspc)vector_at(&env->scope->nspc_stack, 1); + user->parent = (Nspc)vector_at(&env->scope->nspc_stack, 0); + if(ctx->error) clean(global, env); + else if(!ctx->global) { + ctx->nspc->parent = global->parent; + clean(global, env); + } else vector_set(&env->scope->nspc_stack, 2, (m_uint)global); } diff --git a/src/env/env.c b/src/env/env.c index 539eeba1..b53a6680 100644 --- a/src/env/env.c +++ b/src/env/env.c @@ -7,7 +7,6 @@ #include "traverse.h" #include "vm.h" #include "parse.h" -//#include "clean.h" ANN static struct Env_Scope_ *new_envscope(MemPool p) { struct Env_Scope_ *a = mp_calloc(p, Env_Scope); @@ -25,14 +24,17 @@ Env new_env(MemPool p) { env->global_nspc = new_nspc(p, "global_nspc"); env->context = NULL; env->scope = new_envscope(p); + vector_add(&env->scope->nspc_stack, (vtype)env->global_nspc); env_reset(env); return env; } ANN void env_reset(const Env env) { +const Nspc nspc = (Nspc)vector_front(&env->scope->nspc_stack); vector_clear(&env->scope->breaks); vector_clear(&env->scope->conts); vector_clear(&env->scope->nspc_stack); + vector_add(&env->scope->nspc_stack, (vtype)nspc); vector_add(&env->scope->nspc_stack, (vtype)env->global_nspc); vector_clear(&env->scope->class_stack); vector_add(&env->scope->class_stack, (vtype)NULL); @@ -48,13 +50,11 @@ ANN void release_ctx(struct Env_Scope_ *a, struct Gwion_ *gwion) { const m_uint size = vector_size(&a->known_ctx); for (m_uint i = size + 1; --i;) { const Context ctx = (Context)vector_at(&a->known_ctx, i - 1); -// if (!ctx->error && ctx->global) ast_cleaner(gwion, ctx->tree); context_remref(ctx, gwion); } } ANN static void free_env_scope(struct Env_Scope_ *a, Gwion gwion) { - release_ctx(a, gwion); vector_release(&a->known_ctx); vector_release(&a->nspc_stack); vector_release(&a->class_stack); @@ -77,14 +77,12 @@ ANN void env_add_effect(const Env a, const Symbol effect, const loc_t pos) { VPTR(v, VLEN(v) - 1) = (vtype)w; } struct ScopeEffect eff = {effect, pos}; -// mp_vector_add(a->gwion->mp, &w, struct ScopeEffect, eff); mp_vector_add(a->gwion->mp, (MP_Vector**)&(VPTR(v, VLEN(v) - 1)) , struct ScopeEffect, eff); } ANN void free_env(const Env a) { free_env_scope(a->scope, a->gwion); - while (pop_global(a->gwion)) - ; + pop_global(a->gwion); mp_free(a->gwion->mp, Env, a); } diff --git a/src/gwion.c b/src/gwion.c index 0f7f94e8..7de93762 100644 --- a/src/gwion.c +++ b/src/gwion.c @@ -1,7 +1,3 @@ -#ifdef USE_GETTEXT -#include -#include -#endif #include #include "gwion_util.h" #include "gwion_ast.h" @@ -14,8 +10,8 @@ #include "engine.h" #include "arg.h" #include "compile.h" -#include "object.h" // fork_clean -#include "pass.h" // fork_clean +#include "object.h" +#include "pass.h" #include "shreduler_private.h" #include "ugen.h" @@ -82,6 +78,7 @@ ANN static m_bool gwion_ok(const Gwion gwion, CliArg *arg) { if (gwion_audio(gwion) > 0) { plug_run(gwion, &arg->mod); if (type_engine_init(gwion)) { + vector_add(&gwion->data->plugs->vec, (m_uint)gwion->env->global_nspc); gwion->vm->cleaner_shred = gwion_cleaner(gwion); gwion->emit->locale = gwion_locale(gwion); (void)arg_compile(gwion, arg); @@ -170,6 +167,8 @@ ANN static inline void free_killed_shred(const Vector v) { ANN void gwion_end(const Gwion gwion) { free_killed_shred(&gwion->vm->shreduler->killed_shreds); gwion_end_child(gwion->vm->cleaner_shred, gwion); + release_ctx(gwion->env->scope, gwion); + if (gwion->data->plugs) free_plug(gwion); free_env(gwion->env); if (gwion->vm->cleaner_shred) free_vm_shred(gwion->vm->cleaner_shred); free_emitter(gwion->mp, gwion->emit); @@ -251,10 +250,12 @@ ANN void push_global(struct Gwion_ *gwion, const m_str name) { gwion->env->curr = gwion->env->global_nspc = nspc; } -ANN Nspc pop_global(struct Gwion_ *gwion) { - const Nspc nspc = gwion->env->global_nspc->parent; - nspc_remref(gwion->env->global_nspc, gwion); - return gwion->env->curr = gwion->env->global_nspc = nspc; +ANN void pop_global(const Gwion gwion) { + Nspc nspc = gwion->env->global_nspc, parent; + do { + parent = nspc->parent; + nspc_remref(nspc, gwion); + } while((nspc = parent)); } ANN void gwion_set_debug(const Gwion gwion, const bool dbg) { diff --git a/src/gwiondata.c b/src/gwiondata.c index 3ded0aa8..1de2eab6 100644 --- a/src/gwiondata.c +++ b/src/gwiondata.c @@ -27,7 +27,7 @@ ANN GwionData *cpy_gwiondata(MemPool mp, const GwionData *src) { GwionData *data = gwiondata(mp); data->freearg = src->freearg; data->id = src->id; - data->plug = src->plug; + data->plugs = src->plugs; data->passes = src->passes; return data; } @@ -44,6 +44,5 @@ ANN void free_gwiondata(const Gwion gwion) { mp_free(gwion->mp, SpecialId, (struct SpecialId_ *)map_at(&data->id, i)); map_release(&data->id); free_passes(gwion->mp, data->passes); - if (data->plug.ptr) free_plug(gwion); free_gwiondata_cpy(gwion->mp, data); } diff --git a/src/plug.c b/src/plug.c index bff274b2..9fadddc5 100644 --- a/src/plug.c +++ b/src/plug.c @@ -29,7 +29,7 @@ struct PlugHandle { typedef struct Plug_ { void *dl; void *self; - int imp; + Nspc nspc; } * Plug; ANN static struct Plug_ *new_plug(MemPool p, void *dl) { @@ -74,21 +74,23 @@ ANN static void plug_get_all(struct PlugHandle *h, const m_str name) { } ANN m_bool plug_ini(const struct Gwion_ *gwion, const Vector list) { - const Map map = &gwion->data->plug; + gwion->data->plugs = mp_calloc2(gwion->mp, sizeof(Plugs)); + const Map map = &gwion->data->plugs->map; map_init(map); + vector_init(&gwion->data->plugs->vec); struct PlugHandle h = {.mp = gwion->mp, .map = map}; for (m_uint i = 0; i < vector_size(list); i++) { const m_str dir = (m_str)vector_at(list, i); h.len = strlen(dir); char name[PATH_MAX]; - sprintf(name, "%s/*.so", dir); + sprintf(name, "%s/*.so" /**/, dir); plug_get_all(&h, name); } return GW_OK; } -void free_plug(const struct Gwion_ *gwion) { - const Map map = &gwion->data->plug; +void free_plug(const Gwion gwion) { + const Map map = &gwion->data->plugs->map; for (m_uint i = 0; i < map_size(map); ++i) { const Plug plug = (Plug)VVAL(map, i); const modend end = DLSYM(plug->dl, modend, GWMODEND_NAME); @@ -97,6 +99,13 @@ void free_plug(const struct Gwion_ *gwion) { DLCLOSE(plug->dl); } map_release(map); + const Vector vec = &gwion->data->plugs->vec; + for (m_uint i = vector_size(vec) + 1; --i;) { + const Nspc nspc = (Nspc)vector_at(vec, i-1); + nspc_remref(nspc, gwion); + } + vector_release(&gwion->data->plugs->vec); + mp_free2(gwion->mp, sizeof(Plugs), gwion->data->plugs); } ANN static void plug_free_arg(MemPool p, const Vector v) { @@ -107,7 +116,7 @@ ANN static void plug_free_arg(MemPool p, const Vector v) { ANN void set_module(const struct Gwion_ *gwion, const m_str name, void *const ptr) { - const Map map = &gwion->data->plug; + const Map map = &gwion->data->plugs->map; for (m_uint j = 0; j < map_size(map); ++j) { if (!strcmp(name, (m_str)VKEY(map, j))) { Plug plug = (Plug)VVAL(map, j); @@ -121,7 +130,7 @@ ANN void set_module(const struct Gwion_ *gwion, const m_str name, } ANN void plug_run(const struct Gwion_ *gwion, const Map mod) { - const Map map = &gwion->data->plug; + const Map map = &gwion->data->plugs->map; for (m_uint i = 0; i < map_size(mod); ++i) { const m_str name = (m_str)VKEY(mod, i); const m_str opt = (m_str)VVAL(mod, i); @@ -154,33 +163,56 @@ ANN static m_bool dependencies(struct Gwion_ *gwion, const Plug plug, const loc_ return ret ? GW_OK : GW_ERROR; } +ANN static void plug_name(m_str name, const m_str iname, const m_uint size) { + strcpy(name, iname); + for (size_t j = 0; j < size; j++) + if (name[j] == ':' || name[j] == '[' || name[j] == ']') name[j] = '_'; +} + +ANN static void set_parent(const Nspc nspc, const Gwion gwion ) { + const Nspc user = (Nspc)vector_at(&gwion->env->scope->nspc_stack, 1); + nspc->parent = user->parent; + user->parent = nspc; +} + +ANN static m_bool start(const Plug plug, const Gwion gwion, const m_str iname, const loc_t loc) { + const plugin imp = DLSYM(plug->dl, plugin, GWIMPORT_NAME); + const bool cdoc = gwion->data->cdoc; + gwion->data->cdoc = 0; // check cdoc + CHECK_BB(dependencies(gwion, plug, loc)); + gwion->data->cdoc = cdoc; + plug->nspc = new_nspc(gwion->mp, iname); + vector_add(&gwion->data->plugs->vec, (m_uint)plug->nspc); + set_parent(plug->nspc, gwion); + const m_uint scope = env_push(gwion->env, NULL, plug->nspc); + const m_str name = gwion->env->name; + gwion->env->name = iname; + const m_bool ret = gwi_run(gwion, imp); + gwion->env->name = name; + env_pop(gwion->env, scope); + return ret; +} + +ANN static m_bool started(const Plug plug, const Gwion gwion, const m_str iname) { + Nspc nspc = gwion->env->global_nspc->parent; + do if(!strcmp(nspc->name, iname)) + return GW_OK; + while((nspc = nspc->parent)); + set_parent(plug->nspc, gwion); + return GW_OK; +} + ANN static m_bool _plugin_ini(struct Gwion_ *gwion, const m_str iname, const loc_t loc) { - const Map map = &gwion->data->plug; + const Map map = &gwion->data->plugs->map; for (m_uint i = 0; i < map_size(map); ++i) { const Plug plug = (Plug)VVAL(map, i); const m_str base = (m_str)VKEY(map, i); const size_t size = strlen(iname); char name[size + 1]; - strcpy(name, iname); - for (size_t j = 0; j < size; j++) { - if (name[j] == ':' || name[j] == '[' || name[j] == ']') name[j] = '_'; - } + plug_name(name, iname, size); if (!strcmp(name, base)) { - if (plug->imp) return GW_OK; - const plugin imp = DLSYM(plug->dl, plugin, GWIMPORT_NAME); - if (!imp) break; - plug->imp = 1; - const bool cdoc = gwion->data->cdoc; - gwion->data->cdoc = 0; - CHECK_BB(dependencies(gwion, plug, loc)); - gwion->data->cdoc = cdoc; - const m_uint scope = env_push_global(gwion->env); - const m_str name = gwion->env->name; - gwion->env->name = iname; - const m_bool ret = gwi_run(gwion, imp); - gwion->env->name = name; - env_pop(gwion->env, scope); - return ret; + if (!plug->nspc) return start(plug, gwion, iname, loc); + else return started(plug, gwion, iname); } } return GW_ERROR; @@ -188,18 +220,16 @@ ANN static m_bool _plugin_ini(struct Gwion_ *gwion, const m_str iname, const loc ANN m_bool plugin_ini(struct Gwion_ *gwion, const m_str iname, const loc_t loc) { const Env env = gwion->env; - const Context ctx = env->context; - gwion->env->context = NULL; - const m_bool ret = _plugin_ini(gwion, iname, loc); - gwion->env->context = ctx; - if(ret > 0) return GW_OK; - if(gwion->env->context && !gwion->env->context->error) - env_err(env, loc, "no such plugin\n"); - return GW_ERROR; + if(_plugin_ini(gwion, iname, loc) < 0) { + if(gwion->env->context && !gwion->env->context->error) + env_err(env, loc, "no such plugin\n"); + return GW_ERROR; + } + return GW_OK; } ANN m_bool driver_ini(const struct Gwion_ *gwion) { - const Map map = &gwion->data->plug; + const Map map = &gwion->data->plugs->map; m_str dname = gwion->vm->bbq->si->arg; m_str opt = strchr(dname, '='); const char c = opt ? *opt : '\0'; @@ -220,7 +250,7 @@ ANN m_bool driver_ini(const struct Gwion_ *gwion) { } ANN void *get_module(const struct Gwion_ *gwion, const m_str name) { - const Map map = &gwion->data->plug; + const Map map = &gwion->data->plugs->map; for (m_uint i = 0; i < map_size(map); ++i) { if (!strcmp(name, (m_str)VKEY(map, i))) { const Plug plug = (Plug)VVAL(map, i); -- 2.43.0