]> Nishi Git Mirror - gwion.git/commitdiff
:art: Proper global scoping
authorJérémie Astor <fennecdjay@gmail.com>
Tue, 3 May 2022 12:32:48 +0000 (14:32 +0200)
committerJérémie Astor <fennecdjay@gmail.com>
Tue, 3 May 2022 12:32:48 +0000 (14:32 +0200)
include/gwion.h
include/gwiondata.h
include/plug.h
src/env/context.c
src/env/env.c
src/gwion.c
src/gwiondata.c
src/plug.c

index 5fdf4b33f079b92680ee7fdf3447022b2b4b59db..4f85424519e2becc9f510c8e22862607c3ad6941 100644 (file)
@@ -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,
index 39203c68ed6b4cb668ee9f7c94a525850e17bf72..e1c9323b74635b3a1b40a2e0a970fa915062a047 100644 (file)
@@ -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;
 
index 18ade2d7b18c8677640d9f6ae9e724f52db8a99d..e53a04033842aa6e838cb2e6bbff15b861fafd9f 100644 (file)
@@ -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);
index b0c9c58d4054d7b1266494913ebf1fd5e3df9695..4f73e29e2902a72bbc5b84e2cf96664cf914c363 100644 (file)
@@ -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);
 }
index 539eeba123a135888a39c742b984738fb3e80e93..b53a6680056cd57bcbb55f594067b5ea9860bbfd 100644 (file)
@@ -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);
 }
 
index 0f7f94e81f31bbf47eaa70f0da601f682d2d6c25..7de937623e646a39e11581def4c790d15b2b3b73 100644 (file)
@@ -1,7 +1,3 @@
-#ifdef USE_GETTEXT
-#include <locale.h>
-#include <libintl.h>
-#endif
 #include <unistd.h>
 #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) {
index 3ded0aa8a3c81a4687004eb042615b912f017178..1de2eab67b02aea04b529ff3db7513bdfd1b14dc 100644 (file)
@@ -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);
 }
index bff274b2c06c82406c1c46dcd8efef0701bb650d..9fadddc5913ca113879c95a315baad15dbf1feec 100644 (file)
@@ -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);