]> Nishi Git Mirror - gwion.git/commitdiff
:art: Introduce FREEARG
authorfennecdjay <astor.jeremie@wanadoo.fr>
Sun, 31 Mar 2019 19:38:20 +0000 (21:38 +0200)
committerfennecdjay <astor.jeremie@wanadoo.fr>
Sun, 31 Mar 2019 19:38:20 +0000 (21:38 +0200)
13 files changed:
include/gwi.h
include/gwion.h
include/import.h
include/instr.h
src/emit/emit.c
src/gwion.c
src/lib/array.c
src/lib/engine.c
src/lib/func.c
src/lib/import.c
src/lib/instr.c
src/lib/vararg.c
src/vm/vm_code.c

index 70b3122f3ecce397b9ba8d8bbe9a1e95397e5f39..9438c03719fd4c9ae39a13dbe3b428105232fd05 100644 (file)
@@ -45,10 +45,8 @@ typedef struct {
   Decl_List list;
 } DL_Union;
 
-struct Gwi_{
-  VM* vm;
-  Emitter emit;
-  Env env;
+struct Gwi_ {
+  struct Gwion_* gwion;
   Class_Body body;
   DL_Var var;
   DL_Func func;
index 32f57ff572b9c53aa90c49d546bbbac2aa753736..431af256e4356adb7339143ec89e5b9e6b34f8dd 100644 (file)
@@ -12,7 +12,9 @@ struct Gwion_ {
   Env      env;
   Emitter  emit;
   VM*      vm;
+  struct Map_ freearg;
 };
+
 ANN m_bool gwion_ini(const Gwion, struct Arg_*);
 ANN VM* gwion_cpy(const VM*);
 ANN void   gwion_run(const Gwion gwion);
index 028e8b36ba53cf5265494157152ddf19517650d3..5947e74eb9138f5212c6b6b6d2ffb0cec5393df2 100644 (file)
@@ -74,4 +74,8 @@ OP_EMIT(opem_basic_cast);
 OP_EMIT(opem_new);
 
 ANN Type_List str2tl(const Env env, const m_str s, m_uint *depth);
+
+#define FREEARG(a) ANN void a(Instr instr, void *gwion)
+typedef void (*f_freearg)(Instr, void*);
+ANN void register_freearg(const Gwi, const f_instr, void(*)(const Instr,void*));
 #endif
index e9e4ed4f568e0388e583268a0761231cfb13e90b..20b7f4ba97900caabde0fe020d75e7ac26016907 100644 (file)
@@ -34,7 +34,7 @@ INSTR(DTOR_EOC);
 INSTR(DtorReturn);
 
 /* branching */
-INSTR(BranchSwitch);
+INSTR(SwitchBranch);
 INSTR(SwitchIni);
 INSTR(SwitchEnd);
 
index 66e14f154e88759b175d6024ef1a0abead0b57e2..38a083286398225629b27d76b5b5dc5ddba99510 100644 (file)
@@ -1266,7 +1266,7 @@ ANN static m_bool emit_stmt_switch(const Emitter emit, const Stmt_Switch stmt) {
   CHECK_BB(emit_exp(emit, stmt->val, 0))
   CHECK_BB(emit_switch_instr(emit, push))
   vector_add(&emit->code->stack_break, (vtype)NULL);
-  const Instr instr = emit_add_instr(emit, BranchSwitch);
+  const Instr instr = emit_add_instr(emit, SwitchBranch);
   instr->m_val2 = (m_uint)switch_map(emit->env);
   CHECK_BB(emit_stmt(emit, stmt->stmt, 1))
   instr->m_val = switch_idx(emit->env) ?: emit_code_size(emit);
index 1a357a66167f46cdce1e5370933524adbdf56b87..72834153480529a473ace11cb30e6e74bd36c803 100644 (file)
@@ -60,6 +60,7 @@ ANN VM* gwion_cpy(const VM* src) {
   gwion->vm->bbq->si = soundinfo_cpy(src->bbq->si);
   gwion->emit = src->gwion->emit;
   gwion->env = src->gwion->env;
+  gwion->freearg = src->gwion->freearg;
   return gwion->vm;
 }
 ANN m_bool gwion_ini(const Gwion gwion, Arg* arg) {
@@ -75,6 +76,7 @@ ANN m_bool gwion_ini(const Gwion gwion, Arg* arg) {
   arg->si = gwion->vm->bbq->si;
   arg_parse(arg);
   gwion->plug = new_plug(&arg->lib);
+  map_init(&gwion->freearg);
   shreduler_set_loop(gwion->vm->shreduler, arg->loop);
   if(gwion_audio(gwion) > 0 && gwion_engine(gwion)) {
     gwion_compile(gwion, &arg->add);
@@ -100,5 +102,6 @@ ANN void gwion_end(const Gwion gwion) {
   free_emitter(gwion->emit);
   free_vm(gwion->vm);
   free_plug(gwion);
+  map_release(&gwion->freearg);
   free_symbols();
 }
index 2d09aa5d650ffbd83720a18c443c1247ec6928e7..0c29507852a015eb56aefb09bb6d2dea5c88e21e 100644 (file)
@@ -28,7 +28,7 @@ ANN m_uint m_vector_size(const M_Vector v) {
 
 M_Vector new_m_vector(const m_uint size) {
   const M_Vector array = mp_alloc(M_Vector);
-const size_t sz = (ARRAY_OFFSET*SZ_INT) + (2*size);
+  const size_t sz = (ARRAY_OFFSET*SZ_INT) + (2*size);
   array->ptr   = (m_bit*)xcalloc(1, sz);
   ARRAY_CAP(array)   = 2;
   ARRAY_SIZE(array)  = size;
@@ -187,6 +187,13 @@ static OP_CHECK(opck_array_cast) {
   return t_null;
 }
 
+static FREEARG(freearg_array) {
+  ArrayInfo* info = (ArrayInfo*)instr->m_val;
+  REM_REF((Type)vector_back(&info->type), gwion);
+  vector_release(&info->type);
+  mp_free(ArrayInfo, info);
+}
+
 GWION_IMPORT(array) {
   t_array  = gwi_mk_type(gwi, "Array", SZ_INT, t_object);
   SET_FLAG((t_array), abstract);
@@ -218,6 +225,7 @@ GWION_IMPORT(array) {
   CHECK_BB(gwi_oper_add(gwi, opck_array_cast))
   CHECK_BB(gwi_oper_emi(gwi, opem_basic_cast))
   CHECK_BB(gwi_oper_end(gwi, op_cast, NULL))
+  register_freearg(gwi, ArrayAlloc, freearg_array);
   return GW_OK;
 }
 
index ddc9743f39b547f84e9a516f55d8c658b424374e..500a93b14df08619c42cef04cb63fbd5cf529d82 100644 (file)
 #include "engine.h"
 #include "gwion.h"
 
+static FREEARG(freearg_switchini) {
+  free_vector((Vector)instr->m_val);
+  free_map((Map)instr->m_val2);
+}
+
+static FREEARG(freearg_switchbranch) {
+  free_map((Map)instr->m_val2);
+}
+
+static FREEARG(freearg_gack) {
+  const Vector v = (Vector)instr->m_val2;
+  for(m_uint i = vector_size(v) + 1; --i;)
+    REM_REF(((Type)vector_at(v, i - 1)), gwion);
+  free_vector(v);
+}
+
 ANN static m_bool import_core_libs(const Gwi gwi) {
   CHECK_OB((t_class = gwi_mk_type(gwi, "@Class", SZ_INT, NULL)))
   CHECK_OB((t_void  = gwi_mk_type(gwi, "void", 0, NULL)))
@@ -63,6 +79,9 @@ ANN static m_bool import_core_libs(const Gwi gwi) {
   CHECK_BB(import_string(gwi))
   CHECK_BB(import_shred(gwi))
   CHECK_BB(import_modules(gwi))
+  register_freearg(gwi, SwitchIni, freearg_switchini);
+  register_freearg(gwi, SwitchBranch, freearg_switchbranch);
+  register_freearg(gwi, Gack, freearg_gack);
   return GW_OK;
 }
 
@@ -70,15 +89,13 @@ ANN m_bool type_engine_init(VM* vm, const Vector plug_dirs) {
   vm->gwion->env->name = "[builtin]";
   struct Gwi_ gwi;
   memset(&gwi, 0, sizeof(struct Gwi_));
-  gwi.vm = vm;
-  gwi.emit = vm->gwion->emit;
-  gwi.env = vm->gwion->env;
+  gwi.gwion = vm->gwion;
   CHECK_BB(import_core_libs(&gwi))
   vm->gwion->env->name = "[imported]";
   for(m_uint i = 0; i < vector_size(plug_dirs); ++i) {
     m_bool (*import)(Gwi) = (m_bool(*)(Gwi))vector_at(plug_dirs, i);
     if(import && import(&gwi) < 0)
-      env_reset(gwi.env);
+      env_reset(gwi.gwion->env);
   }
   return GW_OK;
 }
index 77968a03128f79fedcbd7a474c928434cb816490..8d093bb775019dce6c6bcb1b94950e7ca1885331 100644 (file)
@@ -167,6 +167,16 @@ static OP_EMIT(opem_spork) {
   return emit_exp_spork(emit, unary);
 }
 
+static FREEARG(freearg_xork) {
+  REM_REF((VM_Code)instr->m_val, gwion)
+}
+
+static FREEARG(freearg_dottmpl) {
+  struct dottmpl_ *dt = (struct dottmpl_*)instr->m_val;
+  free_type_list(dt->tl);
+  mp_free(dottmpl, dt);
+}
+
 GWION_IMPORT(func) {
   CHECK_BB(gwi_oper_ini(gwi, (m_str)OP_ANY_TYPE, "@function", NULL))
   CHECK_BB(gwi_oper_add(gwi, opck_func_call))
@@ -185,5 +195,8 @@ GWION_IMPORT(func) {
   CHECK_BB(gwi_oper_end(gwi, op_spork, NULL))
   CHECK_BB(gwi_oper_add(gwi, opck_spork))
   CHECK_BB(gwi_oper_emi(gwi, opem_spork))
-  return (m_bool)gwi_oper_end(gwi, op_fork, NULL);
+  CHECK_BB(gwi_oper_end(gwi, op_fork, NULL))
+  register_freearg(gwi, SporkIni, freearg_xork);
+  register_freearg(gwi, ForkIni, freearg_xork);
+  return GW_OK;
 }
index 96b5982b35996cb3dd228eb8fe1712424dec7538..4ae707d96806b9860fa5ba96468d58c7c0a663dc 100644 (file)
@@ -17,6 +17,7 @@
 #include "func.h"
 #include "nspc.h"
 #include "operator.h"
+#include "gwion.h"
 
 struct Path {
   m_str path, curr;
@@ -34,7 +35,7 @@ ANN static ID_List templater_def(const Templater* templater) {
 }
 
 ANN VM* gwi_vm(const Gwi gwi) {
-  return gwi->vm;
+  return gwi->gwion->vm;
 }
 
 ANN m_int gwi_tmpl_end(const Gwi gwi) {
@@ -181,7 +182,7 @@ ANN2(1,2) Type gwi_mk_type(const Gwi gwi __attribute__((unused)), const m_str na
 ANN m_int gwi_add_type(const Gwi gwi, const Type type) {
   if(type->name[0] != '@')
     CHECK_BB(name_valid(type->name));
-  env_add_type(gwi->env, type);
+  env_add_type(gwi->gwion->env, type);
   return (m_int)type->xid;
 }
 
@@ -215,39 +216,39 @@ ANN2(1,2) m_int gwi_class_ini(const Gwi gwi, const Type type, const f_xtor pre_c
   } else
     SET_FLAG(type, scan1 | ae_flag_scan2 | ae_flag_check | ae_flag_emit);
   gwi_add_type(gwi, type);
-  import_class_ini(gwi->env, type, pre_ctor, dtor);
+  import_class_ini(gwi->gwion->env, type, pre_ctor, dtor);
   return (m_int)type->xid;
 }
 
 ANN m_int gwi_class_ext(const Gwi gwi, Type_Decl* td) {
-  if(!gwi->env->class_def)
+  if(!gwi->gwion->env->class_def)
     ERR_B(0, "gwi_class_ext invoked before gwi_class_ini")
-  const VM_Code ctor = gwi->env->class_def->nspc->pre_ctor;
-  if(gwi->env->class_def->parent ||
-      (gwi->env->class_def->def && gwi->env->class_def->def->ext))
+  const VM_Code ctor = gwi->gwion->env->class_def->nspc->pre_ctor;
+  if(gwi->gwion->env->class_def->parent ||
+      (gwi->gwion->env->class_def->def && gwi->gwion->env->class_def->def->ext))
     ERR_B(0, "class extend already set")
   if(td->array && !td->array->exp)
     ERR_B(0, "class extend array can't be empty")
-  if(!gwi->env->class_def->def) {
-    const Type t = known_type(gwi->env, td);
+  if(!gwi->gwion->env->class_def->def) {
+    const Type t = known_type(gwi->gwion->env, td);
     CHECK_OB(t)
     if(td->array)
-      SET_FLAG(gwi->env->class_def, typedef);
-    gwi->env->class_def->parent = t;
-    gwi->env->class_def->nspc->info->offset = t->nspc->info->offset;
+      SET_FLAG(gwi->gwion->env->class_def, typedef);
+    gwi->gwion->env->class_def->parent = t;
+    gwi->gwion->env->class_def->nspc->info->offset = t->nspc->info->offset;
     if(t->nspc->info->vtable.ptr)
-      vector_copy2(&t->nspc->info->vtable, &gwi->env->class_def->nspc->info->vtable);
-    CHECK_OB((gwi->emit->code = emit_class_code(gwi->emit,
-          gwi->env->class_def->name)))
+      vector_copy2(&t->nspc->info->vtable, &gwi->gwion->env->class_def->nspc->info->vtable);
+    CHECK_OB((gwi->gwion->emit->code = emit_class_code(gwi->gwion->emit,
+          gwi->gwion->env->class_def->name)))
     if(td->array)
-      CHECK_BB(emit_array_extend(gwi->emit, t, td->array->exp))
+      CHECK_BB(emit_array_extend(gwi->gwion->emit, t, td->array->exp))
     if(ctor)
-      emit_ext_ctor(gwi->emit, ctor);
-    emit_class_finish(gwi->emit, gwi->env->class_def->nspc);
+      emit_ext_ctor(gwi->gwion->emit, ctor);
+    emit_class_finish(gwi->gwion->emit, gwi->gwion->env->class_def->nspc);
     free_type_decl(td);
   } else {
     SET_FLAG(td, typedef);
-    gwi->env->class_def->def->ext = td;
+    gwi->gwion->env->class_def->def->ext = td;
   }
   return GW_OK;
 }
@@ -264,11 +265,11 @@ ANN static m_int import_class_end(const Env env) {
 
 #include "mpool.h"
 ANN m_int gwi_class_end(const Gwi gwi) {
-  if(!gwi->env->class_def)return GW_ERROR;
-  const Type t = gwi->env->class_def;
+  if(!gwi->gwion->env->class_def)return GW_ERROR;
+  const Type t = gwi->gwion->env->class_def;
   if(t->nspc && t->nspc->info->offset)
     t->p = mp_ini((uint32_t)t->nspc->info->offset);
-  return import_class_end(gwi->env);
+  return import_class_end(gwi->gwion->env);
 }
 
 ANN static void dl_var_new_exp_array(DL_Var* v) {
@@ -302,7 +303,7 @@ ANN m_int gwi_item_ini(const Gwi gwi, const restrict m_str type, const restrict
   memset(v, 0, sizeof(DL_Var));
   if(!(v->t.xid = str2list(type, &v->array_depth)))
     ERR_B(0, "\t...\tduring var import '%s.%s'.",
-          gwi->env->class_def->name, name)
+          gwi->gwion->env->class_def->name, name)
   v->var.xid = insert_symbol(name);
   return GW_OK;
 }
@@ -310,8 +311,8 @@ ANN m_int gwi_item_ini(const Gwi gwi, const restrict m_str type, const restrict
 #undef gwi_item_end
 
 static void gwi_body(const Gwi gwi, const Class_Body body) {
-  if(!gwi->env->class_def->def->body)
-    gwi->env->class_def->def->body = body;
+  if(!gwi->gwion->env->class_def->def->body)
+    gwi->gwion->env->class_def->def->body = body;
   else
     gwi->body->next = body;
   gwi->body = body;
@@ -321,7 +322,7 @@ ANN2(1) m_int gwi_item_end(const Gwi gwi, const ae_flag flag, const m_uint* addr
   DL_Var* v = &gwi->var;
   dl_var_set(v, flag | ae_flag_builtin);
   v->var.addr = (void*)addr;
-  if(gwi->env->class_def && GET_FLAG(gwi->env->class_def, template)) {
+  if(gwi->gwion->env->class_def && GET_FLAG(gwi->gwion->env->class_def, template)) {
     Type_Decl *type_decl = new_type_decl(v->t.xid, flag);
     const Var_Decl var_decl = new_var_decl(v->var.xid, v->var.array, 0);
     const Var_Decl_List var_decl_list = new_var_decl_list(var_decl, NULL);
@@ -334,7 +335,7 @@ ANN2(1) m_int gwi_item_end(const Gwi gwi, const ae_flag flag, const m_uint* addr
     gwi_body(gwi, body);
     return GW_OK;
   }
-  CHECK_BB(traverse_decl(gwi->env, &v->exp.d.exp_decl))
+  CHECK_BB(traverse_decl(gwi->gwion->env, &v->exp.d.exp_decl))
   SET_FLAG(v->var.value, builtin);
   dl_var_release(v);
   return (m_int)v->var.value->offset;
@@ -444,7 +445,7 @@ ANN static Func_Def import_fun(const Env env, DL_Func * mfun, const ae_flag flag
 }
 
 ANN m_int gwi_func_end(const Gwi gwi, const ae_flag flag) {
-  Func_Def def = import_fun(gwi->env, &gwi->func, flag);
+  Func_Def def = import_fun(gwi->gwion->env, &gwi->func, flag);
   CHECK_OB(def)
   if(gwi->templater.n) {
     def = new_func_def(NULL, NULL, NULL, NULL, 0);
@@ -452,13 +453,13 @@ ANN m_int gwi_func_end(const Gwi gwi, const ae_flag flag) {
     def->tmpl = new_tmpl_list(list, -1);
     SET_FLAG(def, template);
   }
-  if(gwi->env->class_def && GET_FLAG(gwi->env->class_def, template)) {
+  if(gwi->gwion->env->class_def && GET_FLAG(gwi->gwion->env->class_def, template)) {
     Section* section = new_section_func_def(def);
     Class_Body body = new_class_body(section, NULL);
     gwi_body(gwi, body);
     return GW_OK;
   }
-  if(traverse_func_def(gwi->env, def) < 0) {
+  if(traverse_func_def(gwi->gwion->env, def) < 0) {
     free_func_def(def);
     return GW_ERROR;
   }
@@ -510,7 +511,7 @@ ANN void gwi_oper_mut(const Gwi gwi, const m_bool mut) {
 
 ANN m_int gwi_oper_end(const Gwi gwi, const Operator op, const f_instr f) {
   gwi->oper.op = op;
-  const m_bool ret = import_op(gwi->env, &gwi->oper, f);
+  const m_bool ret = import_op(gwi->gwion->env, &gwi->oper, f);
   gwi->oper.ck = NULL;
   gwi->oper.em = NULL;
   return ret;
@@ -535,10 +536,10 @@ ANN static Stmt import_fptr(const Env env, DL_Func* dl_fun, ae_flag flag) {
 }
 
 ANN m_int gwi_fptr_end(const Gwi gwi, const ae_flag flag) {
-  const Stmt stmt = import_fptr(gwi->env, &gwi->func, flag);
+  const Stmt stmt = import_fptr(gwi->gwion->env, &gwi->func, flag);
 
-  CHECK_BB(traverse_stmt_fptr(gwi->env, &stmt->d.stmt_fptr))
-  if(gwi->env->class_def)
+  CHECK_BB(traverse_stmt_fptr(gwi->gwion->env, &stmt->d.stmt_fptr))
+  if(gwi->gwion->env->class_def)
     SET_FLAG(stmt->d.stmt_fptr.func->def, builtin);
   else
     SET_FLAG(stmt->d.stmt_fptr.func, builtin);
@@ -572,7 +573,7 @@ ANN2(1) m_int gwi_union_ini(const Gwi gwi, const m_str name) {
 ANN m_int gwi_union_add(const Gwi gwi, const restrict m_str type, const restrict m_str name) {
   const Exp exp = make_exp(type, name);
   CHECK_OB(exp);
-  const Type t = type_decl_resolve(gwi->env, exp->d.exp_decl.td);
+  const Type t = type_decl_resolve(gwi->gwion->env, exp->d.exp_decl.td);
   if(!t)
     ERR_B(0, "type '%s' unknown in union declaration.", type)
   if(isa(t, t_object) > 0)
@@ -586,10 +587,10 @@ ANN m_int gwi_union_end(const Gwi gwi, const ae_flag flag) {
     ERR_B(0, "union is empty");
   const Stmt stmt = new_stmt_union(gwi->union_data.list, 0);
   stmt->d.stmt_union.flag = flag;
-  CHECK_BB(traverse_stmt_union(gwi->env, &stmt->d.stmt_union))
+  CHECK_BB(traverse_stmt_union(gwi->gwion->env, &stmt->d.stmt_union))
   emit_union_offset(stmt->d.stmt_union.l, stmt->d.stmt_union.o);
   if(GET_FLAG((&stmt->d.stmt_union), member))
-    gwi->env->class_def->nspc->info->offset =
+    gwi->gwion->env->class_def->nspc->info->offset =
       stmt->d.stmt_union.o + stmt->d.stmt_union.s;
   free_stmt(stmt);
   gwi->union_data.list = NULL;
@@ -622,7 +623,7 @@ ANN static void import_enum_end(const Gwi gwi, const Vector v) {
     Value value = (Value)vector_at(v, i);
     const m_uint addr = vector_at(&d->addr, i);
     SET_FLAG(value, builtin);
-    if(!gwi->env->class_def)
+    if(!gwi->gwion->env->class_def)
       value->d.ptr = (m_uint*)(addr ? addr : i);
     else
       value->d.ptr = (m_uint*)(addr ? *(m_uint*)addr : i);
@@ -635,7 +636,7 @@ ANN static void import_enum_end(const Gwi gwi, const Vector v) {
 ANN m_int gwi_enum_end(const Gwi gwi) {
   DL_Enum* d = &gwi->enum_data;
   const Stmt stmt = new_stmt_enum(d->base, d->t ? insert_symbol(d->t) : NULL);
-  if(traverse_stmt_enum(gwi->env, &stmt->d.stmt_enum) < 0) {
+  if(traverse_stmt_enum(gwi->gwion->env, &stmt->d.stmt_enum) < 0) {
     free_id_list(d->base);
     return GW_ERROR;
   }
@@ -643,3 +644,7 @@ ANN m_int gwi_enum_end(const Gwi gwi) {
   free_stmt(stmt);
   return GW_OK;
 }
+
+ANN void register_freearg(const Gwi gwi, const f_instr _exec, void(*_free)(const Instr, void*)) {
+  map_set(&gwi->gwion->freearg, (vtype)_exec, (vtype)_free);
+}
\ No newline at end of file
index 34e6cf8650a85eaa7f555146e1c44de00b4cf906..b070d1418200cc22d0073ee2965ca59f88fe1d99 100644 (file)
@@ -34,7 +34,7 @@ INSTR(SwitchIni) {
     map_set((Map)instr->m_val2, *(vtype*)REG((i) * SZ_INT), vector_at(v, i));
 }
 
-INSTR(BranchSwitch) { GWDEBUG_EXE
+INSTR(SwitchBranch) { GWDEBUG_EXE
   POP_REG(shred, SZ_INT);
   const Map map = *(Map*)REG(SZ_INT);
   shred->pc = map_get(map, *(m_uint*)REG(0)) ?: instr->m_val;
index 423e145428a057dd1aa6746ef94ec117751a1244..32db5c3a51ea3b06e8b2dd20f327e30adbc378b8 100644 (file)
@@ -71,6 +71,10 @@ static INSTR(VarargAssign) { GWDEBUG_EXE
   *(M_Object**)REG(0) = &*(M_Object*)REG(-SZ_INT);
 }
 
+FREEARG(freearg_vararg) {
+  if(instr->m_val2)
+    free_vector((Vector)instr->m_val2);
+}
 GWION_IMPORT(vararg) {
   CHECK_OB((t_vararg  = gwi_mk_type(gwi, "@Vararg", SZ_INT, t_object)))
   const Type t_varobj  = gwi_mk_type(gwi, "VarObject", SZ_INT, t_vararg);
@@ -101,5 +105,6 @@ GWION_IMPORT(vararg) {
   CHECK_BB(gwi_oper_ini(gwi, "Object", "VarObject", NULL))
   CHECK_BB(gwi_oper_add(gwi, at_varobj))
   CHECK_BB(gwi_oper_end(gwi, op_ref, VarargAssign))
+  register_freearg(gwi, VarargIni, freearg_vararg);
   return GW_OK;
 }
index 713655cabbb08813247627b03f6d2154870b9420..dfb72d42d38e0a889dc37b7ff02fe0c6dd1f122f 100644 (file)
 #include "object.h"
 #include "array.h"
 #include "memoize.h"
+#include "gwion.h"
+#include "import.h"
 
-ANN static void free_code_instr_gack(const Instr instr, void *gwion) {
-  const Vector v = (Vector)instr->m_val2;
-  for(m_uint i = vector_size(v) + 1; --i;)
-    REM_REF(((Type)vector_at(v, i - 1)), gwion);
-  free_vector(v);
-}
-
-ANN static void free_array_info(ArrayInfo* info, void *gwion) {
-  REM_REF((Type)vector_back(&info->type), gwion);
-  vector_release(&info->type);
-  mp_free(ArrayInfo, info);
-}
-
-ANN static void free_code_instr(const Vector v, void *gwion) {
+ANN static void free_code_instr(const Vector v, const Gwion gwion) {
   for(m_uint i = vector_size(v) + 1; --i;) {
     const Instr instr = (Instr)vector_at(v, i - 1);
-    if(instr->opcode == eSporkIni || instr->opcode == eForkIni)
-      REM_REF((VM_Code)instr->m_val, gwion)
-    else if(instr->execute == ArrayAlloc)
-      free_array_info((ArrayInfo*)instr->m_val, gwion);
-    else if(instr->opcode == (m_uint)Gack)
-      free_code_instr_gack(instr, gwion);
-    else if(instr->execute == BranchSwitch)
-      free_map((Map)instr->m_val2);
-    else if(instr->execute == DotTmpl) {
-      struct dottmpl_ *dt = (struct dottmpl_*)instr->m_val;
-      free_type_list(dt->tl);
-      mp_free(dottmpl, dt);
-    }
-    else if(instr->execute == SwitchIni) {
-      free_vector((Vector)instr->m_val);
-      free_map((Map)instr->m_val2);
-    } else if(instr->execute == VarargIni) {
-      if(instr->m_val2)
-      free_vector((Vector)instr->m_val2);
-    }
+    const f_freearg f = (f_freearg)(map_get(&gwion->freearg, instr->opcode) ?:
+       map_get(&gwion->freearg, (vtype)instr->execute));
+    if(f)
+      f(instr, gwion);
     mp_free(Instr, instr);
   }
   free_vector(v);
@@ -60,7 +33,7 @@ ANN static void free_vm_code(VM_Code a, void *gwion) {
 #endif
   if(!GET_FLAG(a, builtin))
     free_code_instr(a->instr, gwion);
-  free(a->name);
+  xfree(a->name);
   mp_free(VM_Code, a);
 }