]> Nishi Git Mirror - gwion.git/commitdiff
:art: Split VM_Shred
authorfennecdjay <astor.jeremie@wanadoo.fr>
Fri, 15 Feb 2019 14:25:32 +0000 (15:25 +0100)
committerfennecdjay <astor.jeremie@wanadoo.fr>
Fri, 15 Feb 2019 14:25:32 +0000 (15:25 +0100)
56 files changed:
include/shreduler_private.h
include/vm.h
src/compile.c
src/lib/array.c
src/lib/event.c
src/lib/instr.c
src/lib/object.c
src/lib/shred.c
src/lib/ugen.c
src/lib/vec.c
src/oo/nspc.c
src/parse/scan1.c
src/vm/shreduler.c
src/vm/vm.c
src/vm/vm_shred.c
tests/import/Makefile [new file with mode: 0644]
tests/import/array.c [new file with mode: 0644]
tests/import/begin_class.c [new file with mode: 0644]
tests/import/callback.c [new file with mode: 0644]
tests/import/callback.gwold [new file with mode: 0644]
tests/import/callback2.gw [new file with mode: 0644]
tests/import/class_template.c [new file with mode: 0644]
tests/import/class_template.gw [new file with mode: 0644]
tests/import/coverage.c [new file with mode: 0644]
tests/import/coverage.gw [new file with mode: 0644]
tests/import/end_class.c [new file with mode: 0644]
tests/import/enum.c [new file with mode: 0644]
tests/import/enum.gw [new file with mode: 0644]
tests/import/extend_array.c [new file with mode: 0644]
tests/import/extend_array.gw [new file with mode: 0644]
tests/import/extend_event.c [new file with mode: 0644]
tests/import/extend_event.gw [new file with mode: 0644]
tests/import/extend_pair.c [new file with mode: 0644]
tests/import/extend_pair.gw [new file with mode: 0644]
tests/import/global_func.c [new file with mode: 0644]
tests/import/global_func.gw [new file with mode: 0644]
tests/import/global_var.c [new file with mode: 0644]
tests/import/global_var.gw [new file with mode: 0644]
tests/import/invalid_arg.c [new file with mode: 0644]
tests/import/invalid_array.c [new file with mode: 0644]
tests/import/invalid_func.c [new file with mode: 0644]
tests/import/invalid_type1.c [new file with mode: 0644]
tests/import/invalid_type2.c [new file with mode: 0644]
tests/import/invalid_type3.c [new file with mode: 0644]
tests/import/map2.gw [new file with mode: 0644]
tests/import/no_import.c [new file with mode: 0644]
tests/import/op_err.c [new file with mode: 0644]
tests/import/static_string.c [new file with mode: 0644]
tests/import/static_string.gw [new file with mode: 0644]
tests/import/template_arg.c [new file with mode: 0644]
tests/import/typedef.c [new file with mode: 0644]
tests/import/typedef.gw [new file with mode: 0644]
tests/import/union.c [new file with mode: 0644]
tests/import/union.gw [new file with mode: 0644]
tests/import/variadic.c [new file with mode: 0644]
tests/import/variadic.gw [new file with mode: 0644]

index f5bd37d194d47a078996bbf754a6b73db4d8d8a9..d6d4ad1f58562b6081acd9f0697c2604c6b7617c 100644 (file)
@@ -2,8 +2,8 @@
 #define __SHREDULER
 struct  Shreduler_ {
   VM* vm;
-  VM_Shred list;
-  VM_Shred curr;
+  struct ShredTick_ *list;
+  struct ShredTick_ *curr;
   struct Vector_ shreds;
   size_t shred_ids;
   m_bool   loop;
index 16e24d5fe756400541bbfee836c2cdda0c856488..d8a4c8741544ccbfa15919f8d9c286dde815885b 100644 (file)
@@ -35,6 +35,24 @@ typedef struct VM_ {
 } VM;
 
 typedef struct VM_Shred_* VM_Shred;
+
+struct ShredInfo_ {
+  VM* vm;
+  struct M_Object_* me;
+  m_str name;
+  Vector args;
+};
+
+struct ShredTick_ {
+  VM_Shred self;
+  struct ShredTick_ *prev;
+  struct ShredTick_ *next;
+  struct ShredTick_ *parent;
+  struct Vector_ child;
+  size_t xid;
+  m_float wake_time;
+};
+
 struct VM_Shred_ {
   VM_Code code;
   m_bit* reg;
@@ -42,15 +60,8 @@ struct VM_Shred_ {
   m_bit* base;
   size_t pc;
   struct Vector_ gc;
-  m_bit* _reg;
-  VM_Shred prev, next, parent;
-  m_str name;
-  VM* vm;
-  Vector args; // passed pointer from compile
-  struct M_Object_* me;
-  struct Vector_ child;
-  size_t xid;
-  m_float wake_time;
+  struct ShredTick_ * tick;
+  struct ShredInfo_ * info;
 };
 ANN2(4) ANEW VM_Code new_vm_code(const Vector instr, const m_uint stack_depth, const ae_flag, const m_str name);
 
@@ -62,7 +73,7 @@ ANN void shreduler_add(const Shreduler s, const VM_Shred shred);
 
 ANEW ANN VM_Shred new_vm_shred(const VM_Code code) __attribute__((hot));
 __attribute__((hot))
-ANN static inline void vm_shred_exit(const VM_Shred shred) { shreduler_remove(shred->vm->shreduler, shred, 1); }
+ANN static inline void vm_shred_exit(const VM_Shred shred) { shreduler_remove(shred->info->vm->shreduler, shred, 1); }
 void free_vm_shred(const VM_Shred shred)__attribute__((hot, nonnull));
 
 ANN void vm_run(const VM* vm) __attribute__((hot));
index 14f7f5bd458e1830fcef37b65088c2804913e9c3..5e3b1fba1a7f191b7e8f599835f5af17c147da63 100644 (file)
@@ -74,7 +74,7 @@ static m_uint compile(struct Gwion_* gwion, struct Compiler* c) {
      gw_err("while compiling file '%s'\n", c->base);
   else {
     const VM_Shred shred = new_vm_shred(code);
-    shred->args = c->args;
+    shred->info->args = c->args;
     xid = vm_add_shred(gwion->vm, shred);
   }
   compiler_clean(c);
index 56ffc1a456e213931dc8aacff3b49ff97d6640a8..e38aa100a2f58ebcb499f7777b35456ea9156100 100644 (file)
@@ -324,7 +324,7 @@ INSTR(ArrayAlloc) { GWDEBUG_EXE
     aai.data = init_array(shred, info, &num_obj);
   const M_Object ref = do_alloc_array(shred, &aai);
   if(!ref) {
-    gw_err("[Gwion](VM): (note: in shred[id=%" UINT_F ":%s])\n", shred->xid, shred->name);
+    gw_err("[Gwion](VM): (note: in shred[id=%" UINT_F ":%s])\n", shred->tick->xid, shred->info->name);
     vm_shred_exit(shred);
     return; // TODO make exception vararg
   }
index eaa1415b2804e86dcc1ebd0c6f377cb377a3a064..832f01b67eeffaed10a98772ff6a29a0e8677325 100644 (file)
@@ -21,7 +21,7 @@ static INSTR(EventWait) { GWDEBUG_EXE
   const M_Object event = *(M_Object*)REG(-SZ_INT);
   if(!event)
     Except(shred, "NullEventWait");
-  shreduler_remove(shred->vm->shreduler, shred, 0);
+  shreduler_remove(shred->info->vm->shreduler, shred, 0);
   const Vector v = EV_SHREDS(event);
   vector_add(v, (vtype)shred);
   *(m_int*)REG(-SZ_INT) = 1;
@@ -32,7 +32,7 @@ static MFUN(event_signal) {
   const Vector v = EV_SHREDS(o);
   const VM_Shred sh = (VM_Shred)vector_front(v);
   if(sh) {
-    shredule(shred->vm->shreduler, sh, .5);
+    shredule(shred->info->vm->shreduler, sh, .5);
     vector_rem(v, 0);
   }
 }
@@ -40,7 +40,7 @@ static MFUN(event_signal) {
 ANN void broadcast(const M_Object o) {
   for(m_uint i = 0; i < vector_size(EV_SHREDS(o)); i++) {
     const VM_Shred sh = (VM_Shred)vector_at(EV_SHREDS(o), i);
-    shredule(sh->vm->shreduler, sh, .5);
+    shredule(sh->info->vm->shreduler, sh, .5);
   }
   vector_clear(EV_SHREDS(o));
 }
index 8c928f867af4b11873e493cfed75940176db6053..4ee856b7c7630cd61a9ad2bd37cacdb888187e50 100644 (file)
@@ -22,13 +22,13 @@ INSTR(DTOR_EOC) { GWDEBUG_EXE
   o->type_ref = o->type_ref->parent;
   o->ref = 1;
   _release(o, shred);
-  _release(shred->me, shred);
+  _release(shred->info->me, shred);
   vm_shred_exit(shred);
 }
 
 INSTR(EOC2) { GWDEBUG_EXE
   shred->pc = 0;
-  shreduler_remove(shred->vm->shreduler, shred, 0);
+  shreduler_remove(shred->info->vm->shreduler, shred, 0);
 }
 
 /* branching */
@@ -144,7 +144,7 @@ INSTR(DotTmpl) {
     const Func f = nspc_lookup_func1(t->nspc, insert_symbol(str));
     if(f) {
       if(!f->code) {
-      const Emitter emit = shred->vm->gwion->emit;
+      const Emitter emit = shred->info->vm->gwion->emit;
 emit->env->name = "runtime";
   const Value v = f->value_ref;
 m_str start = strchr(name, '<');
@@ -172,7 +172,7 @@ f->def->func->code->stack_depth -= SZ_INT;
       shred->reg += SZ_INT;
       return;
     } else {
-      const Emitter emit = shred->vm->gwion->emit;
+      const Emitter emit = shred->info->vm->gwion->emit;
 emit->env->name = "runtime";
 //m_str start = strchr(name, '<');
 m_str start = name;
index 7620acf1911b0cc6440383b66429db95f7d33e94..1094b00306bac2430a2caa7c94ba5930b1694b62 100644 (file)
@@ -15,7 +15,7 @@
 
 ANN void exception(const VM_Shred shred, const m_str c) {
   err_msg(0, "%s: shred[id=%" UINT_F ":%s], PC=[%" UINT_F "]",
-          c, shred->xid, shred->name, shred->pc - 1);
+          c, shred->tick->xid, shred->info->name, shred->pc - 1);
   vm_shred_exit(shred);
 }
 
@@ -63,8 +63,8 @@ ANN static void handle_dtor(const M_Object object, const VM_Shred shred) {
   *(M_Object*)sh->mem = object;
   sh->mem += SZ_INT;
   *(M_Object*)sh->mem = object;
-  vm_add_shred(shred->vm, sh);
-  ++sh->me->ref;
+  vm_add_shred(shred->info->vm, sh);
+  ++sh->info->me->ref;
 }
 
 __attribute__((hot))
index 2f7bdd17f869258fef837cb73f42292953134c7b..ba7225e3e5113873309acaafeded49054cdce144 100644 (file)
@@ -23,12 +23,12 @@ static MFUN(gw_shred_exit) {
 
 static MFUN(vm_shred_id) {
   const VM_Shred s = ME(o);
-  *(m_int*)RETURN = s ? (m_int)s->xid : -1;
+  *(m_int*)RETURN = s ? (m_int)s->tick->xid : -1;
 }
 
 static MFUN(vm_shred_is_running) {
   const VM_Shred s = ME(o);
-  *(m_uint*)RETURN = (s->next || s->prev) ? 1 : 0;
+  *(m_uint*)RETURN = (s->tick->next || s->tick->prev) ? 1 : 0;
 }
 
 static MFUN(vm_shred_is_done) {
@@ -37,31 +37,33 @@ static MFUN(vm_shred_is_done) {
 
 static MFUN(shred_yield) {
   const VM_Shred s = ME(o);
-  const Shreduler sh = shred->vm->shreduler;
+  const Shreduler sh = shred->info->vm->shreduler;
   shredule(sh, s, .5);
+//  shred->mem += (m_bit*)o - shred->mem;
+//  shred->mem -= SZ_INT;//!!!
 }
 #include "shreduler_private.h"
 static SFUN(vm_shred_from_id) {
   const m_int index =  *(m_int*)MEM(0);
-  const VM_Shred s = (VM_Shred)vector_at(&shred->vm->shreduler->shreds, (vtype)index);
+  const VM_Shred s = (VM_Shred)vector_at(&shred->info->vm->shreduler->shreds, (vtype)index);
   if(s) {
-    *(M_Object*)RETURN = s->me;
-    s->me->ref++;
-    vector_add(&shred->gc, (vtype) s->me);
+    *(M_Object*)RETURN = s->info->me;
+    s->info->me->ref++;
+    vector_add(&shred->gc, (vtype) s->info->me);
   } else
     *(m_uint*)RETURN = 0;
 }
 
 static MFUN(shred_args) {
   const VM_Shred s = ME(o);
-  *(m_uint*)RETURN = s->args ? vector_size(s->args) : 0;
+  *(m_uint*)RETURN = s->info->args ? vector_size(s->info->args) : 0;
 }
 
 static MFUN(shred_arg) {
   const VM_Shred s = ME(o);
   const m_int idx = *(m_int*)MEM(SZ_INT);
-  if(s->args && idx >= 0) {
-    const m_str str = (m_str)vector_at(s->args, *(m_uint*)MEM(SZ_INT));
+  if(s->info->args && idx >= 0) {
+    const m_str str = (m_str)vector_at(s->info->args, *(m_uint*)MEM(SZ_INT));
     *(M_Object*)RETURN = str ? new_string(shred, str) : NULL;
   } else
     *(m_uint*)RETURN = 0;
@@ -81,7 +83,7 @@ static MFUN(shred##name##_dir) { \
   strcpy(c, str); \
   *(m_uint*)RETURN = (m_uint)new_string(shred, dirname(c)); \
 }
-describe_path_and_dir(, s->name)
+describe_path_and_dir(, s->info->name)
 describe_path_and_dir(_code, s->code->name)
 
 GWION_IMPORT(shred) {
index 9ca5ea81976e1273d54d029838150dde22407e50..8e84e1b2b98cfe6feb161cddc4dcda5676faa206 100644 (file)
@@ -203,7 +203,7 @@ describe_connect_instr(Trig, Disconnect, TRIG_EX)
 
 static CTOR(ugen_ctor) {
   UGEN(o) = new_UGen();
-  vector_add(&shred->vm->ugen, (vtype)UGEN(o));
+  vector_add(&shred->info->vm->ugen, (vtype)UGEN(o));
 }
 
 #define describe_release_func(src, tgt, opt)                        \
@@ -231,7 +231,7 @@ ANN static void release_multi(const UGen ug, const VM_Shred shred) {
 
 static DTOR(ugen_dtor) {
   const UGen ug = UGEN(o);
-  vector_rem2(&shred->vm->ugen, (vtype)ug);
+  vector_rem2(&shred->info->vm->ugen, (vtype)ug);
   if(!ug->multi)
     release_mono(ug);
   else
index 59dcba4ed4b712b9f2ac8386f62c5572819ff491..1a5503ea0e75abc305739a8db0de2ab3ecbc007e 100644 (file)
@@ -61,7 +61,7 @@ static MFUN(vec3_##name) {            \
 }
 describe_vec3_x(interp, + v->x)
 describe_vec3_x(float, * v->z * (*(m_float*)MEM(SZ_INT)) + v->x)
-describe_vec3_x(dur, * (*(m_float*)MEM(SZ_INT) / (m_float)shred->vm->bbq->sr) + v->x)
+describe_vec3_x(dur, * (*(m_float*)MEM(SZ_INT) / (m_float)shred->info->vm->bbq->sr) + v->x)
 
 static MFUN(vec3_update) {
   m_vec3* v =  *(m_vec3**)MEM(0);
index bea7357ea73282045a83c4c59da7e25c5d8c4ac5..3ff54f1b19e4c77d2fb4c4923da5345a48ed8801 100644 (file)
@@ -25,7 +25,7 @@ ANN static void nspc_release_object(const Nspc a, Value value) {
     const VM_Shred s = new_vm_shred(code);
     const M_Object obj = value->d.ptr ? (M_Object)value->d.ptr :
         *(M_Object*)(a->class_data + value->offset);
-    s->vm = value->gwion->vm;
+    s->info->vm = value->gwion->vm;
     release(obj, s);
     free_vm_shred(s);
   }
index 57fc2bfe34b2fc9e8f07642beb8249c7f06cf9af..166fe4463f966789b60ef0af6b44699ea48afe0f 100644 (file)
@@ -297,7 +297,7 @@ ANN static m_bool scan1_class_parent(const Env env, const Class_Def class_def) {
   const Type parent = class_def->type->parent = known_type(env, class_def->ext);
   CHECK_OB(parent)
   if(parent == class_def->type)
-    ERR_B(class_def->ext->xid->pos, "class '%s' cannot extend itself", 
+    ERR_B(class_def->ext->xid->pos, "class '%s' cannot extend itself",
       class_def->type->name);
   if(isa(class_def->type->parent, t_object) < 0)
     ERR_B(class_def->ext->xid->pos, "cannot extend primitive type '%s'",
index 3d369016c36586b57ee65a47b5b28dd360ce6995..ea3ecde1ced0f8918e227c44ee1401004985f8e8 100644 (file)
@@ -12,18 +12,19 @@ ANN void shreduler_set_loop(const Shreduler s, const m_bool loop) {
 
 ANN VM_Shred shreduler_get(const Shreduler s) {
   VM* vm = s->vm;
-  const VM_Shred shred = s->list;
-  if(!shred) {
+  struct ShredTick_ *tk = s->list;
+  if(!tk) {
     if(!vector_size(&s->shreds) && !s->loop)
       vm->is_running = 0;
     return NULL;
   }
   const m_float time = (m_float)vm->bbq->pos + (m_float).5;
-  if(shred->wake_time <= time) {
-    if((s->list = shred->next))
+  if(tk->wake_time <= time) {
+    if((s->list = tk->next))
       s->list->prev = NULL;
-    shred->next = shred->prev = NULL;
-    return s->curr = shred;
+    tk->next = tk->prev = NULL;
+    s->curr = tk;
+    return tk->self;
   }
   return NULL;
 }
@@ -32,7 +33,7 @@ ANN static void shreduler_parent(const VM_Shred out, const Vector v) {
   vector_rem2(v, (vtype)out);
   if(!vector_size(v)) {
     vector_release(v);
-    out->parent->child.ptr = NULL;
+    out->tick->parent->child.ptr = NULL;
   }
 }
 
@@ -43,56 +44,59 @@ ANN static void shreduler_child(const Shreduler s, const Vector v) {
   }
 }
 
-ANN static void shreduler_erase(const Shreduler s, const VM_Shred out) {
-  if(out->parent)
-    shreduler_parent(out, &out->parent->child);
-  if(out->child.ptr)
-    shreduler_child(s, &out->child);
-  vector_rem2(&s->shreds, (vtype)out);
+ANN static void shreduler_erase(const Shreduler s, struct ShredTick_ *tk) {
+  if(tk->parent)
+    shreduler_parent(tk->self, &tk->parent->child);
+  if(tk->child.ptr)
+    shreduler_child(s, &tk->child);
+  vector_rem2(&s->shreds, (vtype)tk->self);
 }
 
 ANN void shreduler_remove(const Shreduler s, const VM_Shred out, const m_bool erase) {
-  if(s->curr == out)
+  struct ShredTick_ *tk = out->tick;
+  assert(tk);
+  if(tk == s->curr)
     s->curr = NULL;
-  else if(out == s->list)
-    s->list = out->next;
-  if(out->prev)
-    out->prev->next = out->next;
-  if(out->next)
-    out->next->prev = out->prev;
-  out->prev = out->next = NULL;
+  else if(tk == s->list)
+    s->list = tk->next;
+  if(tk->prev)
+    tk->prev->next = tk->next;
+  if(tk->next)
+    tk->next->prev = tk->prev;
+  tk->prev = tk->next = NULL;
   if(erase) {
-    shreduler_erase(s, out);
+    shreduler_erase(s, tk);
     free_vm_shred(out);
   }
 }
 
 ANN void shredule(const Shreduler s, const VM_Shred shred, const m_float wake_time) {
   const m_float time = wake_time + (m_float)s->vm->bbq->pos;
-  shred->wake_time = time;
+  struct ShredTick_ *tk = shred->tick;
+  tk->wake_time = time;
   if(s->list) {
-    VM_Shred curr = s->list, prev = NULL;
+    struct ShredTick_ *curr = s->list, *prev = NULL;
     do {
       if(curr->wake_time > time)
         break;
       prev = curr;
     } while((curr = curr->next));
     if(!prev) {
-      shred->next = s->list;
-      s->list = (s->list->prev = shred);
+      tk->next = s->list;
+      s->list = (s->list->prev = tk);
     } else {
-      if((shred->next = prev->next))
-        prev->next->prev = shred;
-      shred->prev = prev;
-      prev->next = shred;
+      if((tk->next = prev->next))
+        prev->next->prev = tk;
+      tk->prev = prev;
+      prev->next = tk;
     }
   } else
-    s->list = shred;
-  if(s->curr == shred)
+    s->list = tk;
+  if(tk == s->curr)
     s->curr = NULL;
 }
 
 ANN void shreduler_add(const Shreduler s, const VM_Shred shred) {
-  shred->xid = ++s->shred_ids;
+  shred->tick->xid = ++s->shred_ids;
   vector_add(&s->shreds, (vtype)shred);
 }
index a9959861cbfd89f0f01cd92770ef6b5161c26844..b51f6a632fb0fdb61cca8ad3b3387d68e6312726 100644 (file)
@@ -62,7 +62,7 @@ void vm_remove(const VM* vm, const m_uint index) {
   LOOP_OPTIM
   for(m_uint i = vector_size(v) + 1; i--;) {
     const VM_Shred sh = (VM_Shred)vector_at(v, i - 1);
-    if(sh->xid == index)
+    if(sh->tick->xid == index)
        Except(sh, "MsgRemove");
   }
 }
@@ -78,11 +78,11 @@ ANN void free_vm(VM* vm) {
 }
 
 ANN m_uint vm_add_shred(const VM* vm, const VM_Shred shred) {
-  shred->vm = (VM*)vm;
-  shred->me = new_shred(shred);
+  shred->info->vm = (VM*)vm;
+  shred->info->me = new_shred(shred);
   shreduler_add(vm->shreduler, shred);
   shredule(vm->shreduler, shred, .5);
-  return shred->xid;
+  return shred->tick->xid;
 }
 
 __attribute__((hot))
@@ -106,8 +106,9 @@ ANN static inline void vm_ugen_init(const VM* vm) {
 #ifdef DEBUG_STACK
 #define VM_INFO                                                              \
   if(s->curr)                                                                \
-    gw_err("shred[%" UINT_F "] mem[%" INT_F"] reg[%" INT_F"]\n", shred->xid, \
-    mem - (shred->_reg + SIZEOF_REG), reg - shred->_reg);
+    gw_err("shred[%" UINT_F "] mem[%" INT_F"] reg[%" INT_F"]\n", \
+    shred->tick->xid, \
+    mem - ((m_bit*)shred + sizeof(struct VM_Shred_) + SIZEOF_REG), reg - (m_bit*)shred + sizeof(struct VM_Shred_));
 #else
 #define VM_INFO
 #endif
@@ -120,18 +121,18 @@ static struct timespec exec_time;
 
 
 ANN static inline m_bool overflow_(const m_bit* mem, const VM_Shred c) {
-  return mem >  ((c->_reg + SIZEOF_REG) + (SIZEOF_MEM) - (MEM_STEP));
+  return mem >  (((m_bit*)c + sizeof(struct VM_Shred_) + SIZEOF_REG) + (SIZEOF_MEM) - (MEM_STEP));
 }
 
 ANN static inline VM_Shred init_spork_shred(const VM_Shred shred, const VM_Code code) {
   const VM_Shred sh = new_vm_shred(code);
   ADD_REF(code)
-  sh->parent = shred;
-  if(!shred->child.ptr)
-    vector_init(&shred->child);
-  vector_add(&shred->child, (vtype)sh);
+  sh->tick->parent = shred->tick;
+  if(!shred->tick->child.ptr)
+    vector_init(&shred->tick->child);
+  vector_add(&shred->tick->child, (vtype)sh);
   sh->base = shred->base;
-  vm_add_shred(shred->vm, sh);
+  vm_add_shred(shred->info->vm, sh);
   return sh;
 }
 
@@ -368,7 +369,7 @@ regpushptr:
   *(m_uint*)(reg-SZ_INT) = instr->m_val;
   DISPATCH()
 regpushme:
-  *(M_Object*)reg = shred->me;
+  *(M_Object*)reg = shred->info->me;
   reg += SZ_INT;
   DISPATCH()
 regpushmaybe:
@@ -541,7 +542,7 @@ timeadv:
   reg -= SZ_FLOAT;
 {
   register const m_float f = *(m_float*)(reg-SZ_FLOAT);
-  *(m_float*)(reg-SZ_FLOAT) = (shred->wake_time += f);
+  *(m_float*)(reg-SZ_FLOAT) = (shred->tick->wake_time += f);
   shredule(s, shred, f);
 }
 shred->code = code;
@@ -656,7 +657,7 @@ sporkexp:
     *(m_uint*)(a.child->mem + i) = *(m_uint*)(mem+i);
   DISPATCH()
 sporkend:
-  *(M_Object*)(reg-SZ_INT) = a.child->me;
+  *(M_Object*)(reg-SZ_INT) = a.child->info->me;
   DISPATCH()
 funcptr:
   if(!GET_FLAG((VM_Code)a.code, builtin))
index 9325400e54b4ed7f3c86049aaf5743a4344adc72..48b17473aaea80d21face8d6a1d097022759b1bc 100644 (file)
 #include "object.h"
 
 struct Stack_ {
-//  VM_Shred shred;
+  VM_Shred shred;
   char c[SIZEOF_REG];
   char d[SIZEOF_MEM];
 };
 
+static inline struct ShredInfo_ *new_shredinfo(const m_str name) {
+  struct ShredInfo_ *info = mp_alloc(ShredInfo);
+  info->name = strdup(name);
+  return info;
+}
+
+static inline void free_shredinfo(struct ShredInfo_ *info, const VM_Shred shred) {
+  free(info->name);
+  release(info->me, shred);
+  if(info->args) {
+    const Vector v = info->args;
+    LOOP_OPTIM
+    for(m_uint i = vector_size(v) + 1; --i;)
+      free((void*)vector_at(v, i - 1));
+    free_vector(v);
+  }
+  mp_free(ShredInfo, info);
+}
+
 VM_Shred new_vm_shred(VM_Code c) {
-  const VM_Shred shred = mp_alloc(VM_Shred);
-  shred->_reg          = mp_alloc(Stack);
-//  const VM_Shred shred = mp_alloc(Stack);
-//  shred->reg           = (m_bit*)shred + sizeof(struct VM_Shred_);
-  shred->mem           = shred->_reg + SIZEOF_REG;
-  shred->reg = shred->_reg;
-  shred->base          = shred->mem;
-//  shred->_mem          = shred->base;
+  const VM_Shred shred = mp_alloc(Stack);
   shred->code          = c;
-  shred->name          = strdup(c->name);
+  shred->reg           = (m_bit*)shred + sizeof(struct VM_Shred_);
+  shred->base = shred->mem = shred->reg + SIZEOF_REG;
+  shred->tick = mp_alloc(ShredTick);
+  shred->tick->self = shred;
+  shred->info = new_shredinfo(c->name);
   vector_init(&shred->gc);
   return shred;
 }
 
-static void vm_shred_free_args(Vector v) {
-  LOOP_OPTIM
-  for(m_uint i = vector_size(v) + 1; --i;)
-    free((void*)vector_at(v, i - 1));
-  free_vector(v);
-}
-
 void free_vm_shred(VM_Shred shred) {
   for(m_uint i = vector_size(&shred->gc) + 1; --i;)
     release((M_Object)vector_at(&shred->gc, i - 1), shred);
   vector_release(&shred->gc);
-  release(shred->me, shred);
-  mp_free(Stack, shred->_reg);
-//  mp_free(Stack, shred->mem);
   REM_REF(shred->code);
-  free(shred->name);
-  if(shred->args)
-    vm_shred_free_args(shred->args);
-  mp_free(VM_Shred, shred);
-//  mp_free(Stack, shred);
+  mp_free(ShredTick, shred->tick);
+  free_shredinfo(shred->info, shred);
+  mp_free(Stack, shred);
 }
diff --git a/tests/import/Makefile b/tests/import/Makefile
new file mode 100644 (file)
index 0000000..6a5949f
--- /dev/null
@@ -0,0 +1,36 @@
+INC      = -I../../include -I../../util/include -I../../ast/include
+CC       ?= gcc
+
+SRC = ${NAME}.c
+OBJ = $(SRC:.c=.o)
+CFLAGS   = $(../../gwion -C 2>&1 | grep CFLAGS) ${INC}
+LDFLAGS   = $(../../gwion -C 2>&1 | grep LDFLAGS)
+
+# os specific
+ifeq ($(shell uname), Linux)
+LDFLAGS += -shared
+else
+LDFLAGS += -bundle -undefined dynamic_lookup
+endif
+
+all: ${NAME}.so
+
+
+${NAME}.so: ${OBJ}
+ifeq (${USE_LD}, 1)
+       ${LD} $^ -o ${NAME}.so ${LDFLAGS}
+else
+       ${CC} $^ -o ${NAME}.so ${LDFLAGS}
+endif
+
+clean:
+       rm -f ${OBJ} ${NAME}.so
+
+.c.o:
+       ${CC} -fPIC ${CFLAGS} -c $< -o $(<:.c=.o) -g
+
+install: ${NAME}.so
+       install ${NAME}.so ${GWION_ADD_DIR}
+
+uninstall:
+       rm ${GWION_ADD_DIR}/${NAME}.so
diff --git a/tests/import/array.c b/tests/import/array.c
new file mode 100644 (file)
index 0000000..a256dda
--- /dev/null
@@ -0,0 +1,25 @@
+#include "gwion_util.h"
+#include "gwion_ast.h"
+#include "oo.h"
+#include "vm.h"
+#include "env.h"
+#include "type.h"
+#include "object.h"
+#include "instr.h"
+#include "import.h"
+
+MFUN(test_mfun){}
+
+GWION_IMPORT(array_test) {
+  Type t_invalid_var_name;
+  CHECK_BB((t_invalid_var_name = gwi_mk_type(gwi, "invalid_var_name", SZ_INT, t_object)))
+  CHECK_BB(gwi_class_ini(gwi, t_invalid_var_name, NULL, NULL))
+  CHECK_BB(gwi_item_ini(gwi,"int[]", "int_array"))
+  CHECK_BB(gwi_item_end(gwi, 0, NULL)) // import array var
+  CHECK_BB(gwi_func_ini(gwi, "float[][]", "f", test_mfun))
+  CHECK_BB(gwi_func_end(gwi, 0))
+  CHECK_BB(gwi_func_ini(gwi, "float[][]", "g", test_mfun))
+  CHECK_BB(gwi_func_end(gwi, 0))
+  CHECK_BB(gwi_class_end(gwi))
+  return GW_OK;
+}
diff --git a/tests/import/begin_class.c b/tests/import/begin_class.c
new file mode 100644 (file)
index 0000000..e521b2c
--- /dev/null
@@ -0,0 +1,18 @@
+#include "gwion_util.h"
+#include "gwion_ast.h"
+#include "oo.h"
+#include "vm.h"
+#include "env.h"
+#include "type.h"
+#include "object.h"
+#include "instr.h"
+#include "import.h"
+
+MFUN(test_mfun){}
+GWION_IMPORT(begin_class) {
+  Type t_invalid_var_name;
+  CHECK_OB((t_invalid_var_name = gwi_mk_type(gwi, "invalid_var_name", SZ_INT, t_object)))
+  CHECK_BB(gwi_class_ini(gwi, t_invalid_var_name, NULL, NULL))
+  CHECK_BB(gwi_class_ini(gwi, t_invalid_var_name, NULL, NULL))
+  return GW_OK;
+}
diff --git a/tests/import/callback.c b/tests/import/callback.c
new file mode 100644 (file)
index 0000000..9faa39c
--- /dev/null
@@ -0,0 +1,80 @@
+#include "gwion_util.h"
+#include "gwion_ast.h"
+#include "oo.h"
+#include "vm.h"
+#include "env.h"
+#include "type.h"
+#include "instr.h"
+#include "object.h"
+#include "instr.h"
+#include "import.h"
+#include "func.h"
+
+struct ret_info {
+  Instr instr;
+  VM_Code code;
+  m_uint offset;
+  m_uint size;
+  size_t pc;
+};
+
+static INSTR(my_ret) { GWDEBUG_EXE
+  struct ret_info* info = (struct ret_info*)instr->m_val;
+  POP_MEM(shred, info->offset);
+  vector_set(shred->code->instr, shred->pc, (vtype)info->instr);
+  shred->code = info->code;
+//*(VM_Code*)instr->ptr;
+  POP_REG(shred, info->size)
+  if(shred->mem == (m_bit*)shred + sizeof(struct VM_Shred_) + SIZEOF_REG)
+    POP_REG(shred, SZ_INT)
+  POP_REG(shred, shred->code->stack_depth);
+//  shred->pc = instr->m_val2;
+  shred->pc = info->pc;
+  free(info);
+  *(m_int*)shred->reg = 2;
+  PUSH_REG(shred, SZ_INT);
+}
+
+static SFUN(cb_func) {
+  m_uint i;
+  Func f = *(Func*)MEM(0);
+  if(!f){
+    Except(shred, "NullCallbackException");
+  }
+  m_uint offset = shred->mem - ((m_bit*)shred + sizeof(struct VM_Shred_) + SIZEOF_REG);
+  PUSH_MEM(shred, offset);
+  Instr instr = mp_alloc(Instr);
+  struct ret_info* info = (struct ret_info*)xmalloc(sizeof(struct ret_info));
+  info->offset = offset;
+  info->code = shred->code;
+  info->size = f->def->ret_type->size;
+  info->pc = shred->pc;
+  instr->execute = my_ret;
+//  *(VM_Code*)instr->ptr = shred->code;
+  instr->m_val = (m_uint)info;
+//  instr->m_val2 = shred->pc;
+  for(i = 0; i < vector_size(f->code->instr); i++) {
+    Instr in = (Instr)vector_at(f->code->instr, i);
+    if(in->execute == FuncReturn ||
+      in->execute == my_ret) {
+      info->instr = in;
+      vector_set(f->code->instr, i, (vtype)instr);
+    }
+  }
+  *(m_int*)RETURN = 1;
+  shred->pc = 0;
+  shred->code = f->code;
+}
+
+GWION_IMPORT(callback) {
+  CHECK_BB(gwi_fptr_ini(gwi, "Vec4", "PtrType"))
+  CHECK_BB(gwi_fptr_end(gwi, 0))
+
+  const Type t_callback = gwi_mk_type(gwi, "Callback", SZ_INT, t_object);
+  CHECK_BB(gwi_class_ini(gwi, t_callback, NULL, NULL))
+    CHECK_BB(gwi_func_ini(gwi, "int", "callback", cb_func))
+      CHECK_BB(gwi_func_arg(gwi, "PtrType", "func"))
+    CHECK_BB(gwi_func_end(gwi, ae_flag_static))
+  CHECK_BB(gwi_class_end(gwi))
+  return GW_OK;
+}
diff --git a/tests/import/callback.gwold b/tests/import/callback.gwold
new file mode 100644 (file)
index 0000000..d139760
--- /dev/null
@@ -0,0 +1,16 @@
+int i;
+int j;
+int K;
+fun Vec4 test() { <<<"test">>>; }
+fun void test2(PtrType t) { Callback.callback(t); }
+
+test @=> PtrType t;
+<<<Callback.callback(t)>>>;
+<<<Callback.callback(t)>>>;
+<<<Callback.callback(t)>>>;
+Callback.callback(t);
+test2(t);
+test2(t);
+spork ~test2(t);
+spork ~Callback.callback(t);
+me.yield();
diff --git a/tests/import/callback2.gw b/tests/import/callback2.gw
new file mode 100644 (file)
index 0000000..c9f0668
--- /dev/null
@@ -0,0 +1,15 @@
+fun Vec4 test(int i) { <<<"test with arg ", i>>>; }
+
+//typedef Vec4 PT();
+//test @=> 
+PtrTypeI p;
+test @=> p;
+//test @=> PT ti;
+<<<test>>>;
+//<<<ti>>>;
+<<<p>>>;
+//ti();
+<<<"test">>>;
+p(2);
+<<<"end">>>;
+Callback.callback(p, 6);
diff --git a/tests/import/class_template.c b/tests/import/class_template.c
new file mode 100644 (file)
index 0000000..0a6a26d
--- /dev/null
@@ -0,0 +1,47 @@
+#include "gwion_util.h"
+#include "gwion_ast.h"
+#include "oo.h"
+#include "vm.h"
+#include "env.h"
+#include "type.h"
+#include "object.h"
+#include "instr.h"
+#include "import.h"
+
+static m_int o_map_key;
+static m_int o_map_value;
+#define MAP_KEY(a) *((M_Object*)(a->data + o_map_key))
+#define MAP_VAL(a) *((M_Object*)(a->data + o_map_value))
+static CTOR(class_template_ctor) {
+  /*char* name = strdup(o->type_ref->name);*/
+  /*char* tmp = strsep(&name, "@");*/
+  /*char* name1 = strsep(&name, "@");*/
+/*Type t1 = nspc_lookup_type1(o->type_ref->info->parent, insert_symbol(name1));*/
+  /*Type t2 = nspc_lookup_type0(shred->vm->emit->env->curr, insert_symbol(name));*/
+/*free(tmp);*/
+/**(M_Object*)(o->data) = new_array(t1->size, 0, t1->array_depth);*/
+  /**(M_Object*)(o->data + SZ_INT) = new_array(t2->size, 0, t2->array_depth);*/
+}
+
+static MFUN(class_template_set) {
+
+}
+
+GWION_IMPORT(class_template) {
+  Type t_class_template;
+  const m_str list[2] = { "A", "B" };
+  gwi_tmpl_ini(gwi, 2, list);
+  CHECK_OB((t_class_template = gwi_mk_type(gwi, "ClassTemplate", SZ_INT, t_object)))
+  CHECK_BB(gwi_class_ini(gwi, t_class_template, class_template_ctor, NULL))
+  gwi_tmpl_end(gwi);
+  CHECK_BB(gwi_item_ini(gwi, "A[]", "key"))
+    CHECK_BB((o_map_key = gwi_item_end(gwi, ae_flag_member | ae_flag_template, NULL)))
+    CHECK_BB(gwi_item_ini(gwi, "B[]", "value"))
+    CHECK_BB((o_map_value = gwi_item_end(gwi, ae_flag_member, NULL)))
+
+
+    /*gwi_func_ini(gwi, "B", "set", class_template_set);*/
+    /*gwi_func_end(gwi, ae_flag_member);*/
+  CHECK_BB(gwi_class_end(gwi))
+  return GW_OK;
+}
diff --git a/tests/import/class_template.gw b/tests/import/class_template.gw
new file mode 100644 (file)
index 0000000..245aca5
--- /dev/null
@@ -0,0 +1,15 @@
+//class child {}
+//template<~A, B~>
+//class C{ A key; B value; }
+//<~int, int~>C c1;
+//<float, float>C c2;
+//<<<c1>>>;
+//<<<c2>>>;
+//<<<c2.value>>>;
+
+<~int, int~>ClassTemplate ct;
+<<<ct.key>>>;
+//<float, float>ClassTemplate ct2;
+//<<<ct2.key>>>;
+//<child, float>ClassTemplate ct3;
+//<<<ct3.key>>>;
diff --git a/tests/import/coverage.c b/tests/import/coverage.c
new file mode 100644 (file)
index 0000000..8c62922
--- /dev/null
@@ -0,0 +1,63 @@
+#include "gwion_util.h"
+#include "gwion_ast.h"
+#include "oo.h"
+#include "vm.h"
+#include "env.h"
+#include "type.h"
+#include "object.h"
+#include "instr.h"
+#include "import.h"
+
+SFUN(coverage_int)     { *(m_uint*)RETURN    = 0; }
+SFUN(coverage_float)   { *(m_float*)RETURN   = 0; }
+SFUN(coverage_complex) { *(m_complex*)RETURN = 0; }
+SFUN(coverage_vec3)    { m_vec3 v = {0,0,0};   *(m_vec3*)RETURN = v; }
+SFUN(coverage_vec4)    { m_vec4 v = {0,0,0,0}; *(m_vec4*)RETURN = v; }
+
+GWION_IMPORT(coverage) {
+  Type t_coverage;
+  CHECK_OB((t_coverage = gwi_mk_type(gwi, "Coverage", SZ_INT, t_object)))
+  CHECK_BB(gwi_class_ini(gwi, t_coverage, NULL, NULL))
+  CHECK_BB(gwi_func_ini(gwi, "int", "i", coverage_int))
+  CHECK_BB(gwi_func_end(gwi, ae_flag_static))
+  CHECK_BB(gwi_func_ini(gwi, "float", "f", coverage_float))
+  CHECK_BB(gwi_func_end(gwi, ae_flag_static))
+  CHECK_BB(gwi_func_ini(gwi, "complex", "c", coverage_complex))
+  CHECK_BB(gwi_func_end(gwi, ae_flag_static))
+  CHECK_BB(gwi_func_ini(gwi, "Vec3", "v", coverage_vec3))
+  CHECK_BB(gwi_func_end(gwi, ae_flag_static))
+  CHECK_BB(gwi_func_ini(gwi, "Vec4", "w", coverage_vec4))
+  CHECK_BB(gwi_func_end(gwi, ae_flag_static))
+
+  m_uint* i = (m_uint*)xmalloc(sizeof(m_uint));
+  *i = 5;
+  CHECK_BB(gwi_item_ini(gwi,"int", "s_i"))
+  CHECK_BB(gwi_item_end(gwi, ae_flag_static | ae_flag_const, i))
+  m_float* f = (m_float*)xmalloc(sizeof(m_float));
+  *f = 2.1;
+  CHECK_BB(gwi_item_ini(gwi,"float", "s_f"))
+  CHECK_BB(gwi_item_end(gwi, ae_flag_static | ae_flag_const, (void*)f))
+
+  m_complex* c = (m_complex*)xmalloc(sizeof(m_complex));
+  *c = 2.1;
+  CHECK_BB(gwi_item_ini(gwi,"complex", "s_c"))
+  CHECK_BB(gwi_item_end(gwi, ae_flag_static | ae_flag_const, (void*)c))
+
+  m_vec3* v = (m_vec3*)xmalloc(sizeof(m_vec3));
+  v->x = 2.1;
+  v->y = 2.2;
+  v->z = 2.3;
+  CHECK_BB(gwi_item_ini(gwi,"Vec3", "s_v"))
+  CHECK_BB(gwi_item_end(gwi, ae_flag_static | ae_flag_const, (void*)v))
+
+  m_vec4* w = (m_vec4*)xmalloc(sizeof(m_vec4));
+  w->x = 2.1;
+  w->y = 2.2;
+  w->z = 2.3;
+  w->w = 2.4;
+  CHECK_BB(gwi_item_ini(gwi,"Vec4", "s_w"))
+  CHECK_BB(gwi_item_end(gwi, ae_flag_static | ae_flag_const, (void*)w))
+
+  CHECK_BB(gwi_class_end(gwi))
+  return GW_OK;
+}
diff --git a/tests/import/coverage.gw b/tests/import/coverage.gw
new file mode 100644 (file)
index 0000000..d616e42
--- /dev/null
@@ -0,0 +1,20 @@
+float f;
+Coverage c;
+c.s_i;
+<<< Coverage.i() >>>;
+<<< Coverage.f() >>>;
+<<< Coverage.c() >>>;
+<<< Coverage.v() >>>;
+<<< Coverage.w() >>>;
+
+<<<Coverage.s_i >>>;
+<<<Coverage.s_f >>>;
+<<<Coverage.s_c >>>;
+<<<Coverage.s_v >>>;
+<<<Coverage.s_w >>>;
+
+<<< 1 => Coverage.s_i >>>;
+<<< 1.2 => Coverage.s_f >>>;
+<<< #(1.2, 0.1) => Coverage.s_c >>>;
+<<< @(1.2, 0.1, 2.6) => Coverage.s_v >>>;
+<<< @(1.2, 0.1, 2.6, 4.6) => Coverage.s_w >>>;
diff --git a/tests/import/end_class.c b/tests/import/end_class.c
new file mode 100644 (file)
index 0000000..8961e03
--- /dev/null
@@ -0,0 +1,16 @@
+#include "gwion_util.h"
+#include "gwion_ast.h"
+#include "absyn.h"
+#include "oo.h"
+#include "vm.h"
+#include "env.h"
+#include "operator.h"
+#include "object.h"
+#include "instr.h"
+#include "import.h"
+
+MFUN(test_mfun){}
+GWION_IMPORT(end_class) {
+  CHECK_BB(gwi_class_end(gwi))
+  return GW_OK;
+}
diff --git a/tests/import/enum.c b/tests/import/enum.c
new file mode 100644 (file)
index 0000000..032d785
--- /dev/null
@@ -0,0 +1,69 @@
+#include "gwion_util.h"
+#include "gwion_ast.h"
+#include "oo.h"
+#include "vm.h"
+#include "env.h"
+#include "type.h"
+#include "object.h"
+#include "instr.h"
+#include "import.h"
+
+GWION_IMPORT(enum_test) {
+  CHECK_BB(gwi_enum_ini(gwi, NULL))
+    CHECK_BB(gwi_enum_add(gwi, "ENUM0", 0))
+    CHECK_BB(gwi_enum_add(gwi, "ENUM1", 1))
+    CHECK_BB(gwi_enum_add(gwi, "ENUM2", 2))
+    CHECK_BB(gwi_enum_add(gwi, "ENUM3", 3))
+    CHECK_BB(gwi_enum_add(gwi, "ENUM4", 4))
+    CHECK_BB(gwi_enum_add(gwi, "ENUM5", 5))
+    CHECK_BB(gwi_enum_add(gwi, "ENUM6", 6))
+    CHECK_BB(gwi_enum_add(gwi, "ENUM7", 7))
+    CHECK_BB(gwi_enum_add(gwi, "ENUM8", 8))
+    CHECK_BB(gwi_enum_add(gwi, "ENUM9", 9))
+  CHECK_BB(gwi_enum_end(gwi))
+
+  CHECK_BB(gwi_enum_ini(gwi, "test"))
+    CHECK_BB(gwi_enum_add(gwi, "TYPED_ENUM0", 0))
+    CHECK_BB(gwi_enum_add(gwi, "TYPED_ENUM1", 1))
+    CHECK_BB(gwi_enum_add(gwi, "TYPED_ENUM2", 2))
+    CHECK_BB(gwi_enum_add(gwi, "TYPED_ENUM3", 3))
+    CHECK_BB(gwi_enum_add(gwi, "TYPED_ENUM4", 4))
+    CHECK_BB(gwi_enum_add(gwi, "TYPED_ENUM5", 5))
+    CHECK_BB(gwi_enum_add(gwi, "TYPED_ENUM6", 6))
+    CHECK_BB(gwi_enum_add(gwi, "TYPED_ENUM7", 7))
+    CHECK_BB(gwi_enum_add(gwi, "TYPED_ENUM8", 8))
+    CHECK_BB(gwi_enum_add(gwi, "TYPED_ENUM9", 9))
+  CHECK_BB(gwi_enum_end(gwi))
+
+  Type t_enum;
+  CHECK_OB((t_enum = gwi_mk_type(gwi, "Enum", 0, NULL)))
+  CHECK_BB(gwi_class_ini(gwi, t_enum, NULL, NULL))
+    CHECK_BB(gwi_enum_ini(gwi, 0))
+      CHECK_BB(gwi_enum_add(gwi, "ENUM0", 0))
+      CHECK_BB(gwi_enum_add(gwi, "ENUM1", 1))
+      CHECK_BB(gwi_enum_add(gwi, "ENUM2", 2))
+      CHECK_BB(gwi_enum_add(gwi, "ENUM3", 3))
+      CHECK_BB(gwi_enum_add(gwi, "ENUM4", 4))
+      CHECK_BB(gwi_enum_add(gwi, "ENUM5", 5))
+      CHECK_BB(gwi_enum_add(gwi, "ENUM6", 6))
+      CHECK_BB(gwi_enum_add(gwi, "ENUM7", 7))
+      CHECK_BB(gwi_enum_add(gwi, "ENUM8", 8))
+      CHECK_BB(gwi_enum_add(gwi, "ENUM9", 9))
+    CHECK_BB(gwi_enum_end(gwi))
+
+    CHECK_BB(gwi_enum_ini(gwi, "Enumtest"))
+      CHECK_BB(gwi_enum_add(gwi, "TYPED_ENUM0", 0))
+      CHECK_BB(gwi_enum_add(gwi, "TYPED_ENUM1", 1))
+      CHECK_BB(gwi_enum_add(gwi, "TYPED_ENUM2", 2))
+      CHECK_BB(gwi_enum_add(gwi, "TYPED_ENUM3", 3))
+      CHECK_BB(gwi_enum_add(gwi, "TYPED_ENUM4", 4))
+      CHECK_BB(gwi_enum_add(gwi, "TYPED_ENUM5", 5))
+      CHECK_BB(gwi_enum_add(gwi, "TYPED_ENUM6", 6))
+      CHECK_BB(gwi_enum_add(gwi, "TYPED_ENUM7", 7))
+      CHECK_BB(gwi_enum_add(gwi, "TYPED_ENUM8", 8))
+      CHECK_BB(gwi_enum_add(gwi, "TYPED_ENUM9", 9))
+    CHECK_BB(gwi_enum_end(gwi))
+  CHECK_BB(gwi_class_end(gwi))
+
+  return GW_OK;
+}
diff --git a/tests/import/enum.gw b/tests/import/enum.gw
new file mode 100644 (file)
index 0000000..8566665
--- /dev/null
@@ -0,0 +1,48 @@
+// untyped global enum
+<<<ENUM0>>>;
+<<<ENUM1>>>;
+<<<ENUM2>>>;
+<<<ENUM3>>>;
+<<<ENUM4>>>;
+<<<ENUM5>>>;
+<<<ENUM6>>>;
+<<<ENUM7>>>;
+<<<ENUM8>>>;
+<<<ENUM9>>>;
+
+// typed global enum
+<<<TYPED_ENUM0>>>;
+<<<TYPED_ENUM1>>>;
+<<<TYPED_ENUM2>>>;
+<<<TYPED_ENUM3>>>;
+<<<TYPED_ENUM4>>>;
+<<<TYPED_ENUM5>>>;
+<<<TYPED_ENUM6>>>;
+<<<TYPED_ENUM7>>>;
+<<<TYPED_ENUM8>>>;
+<<<TYPED_ENUM9>>>;
+
+// in class 
+// untyped global enum
+<<<Enum.ENUM0>>>;
+<<<Enum.ENUM1>>>;
+<<<Enum.ENUM2>>>;
+<<<Enum.ENUM3>>>;
+<<<Enum.ENUM4>>>;
+<<<Enum.ENUM5>>>;
+<<<Enum.ENUM6>>>;
+<<<Enum.ENUM7>>>;
+<<<Enum.ENUM8>>>;
+<<<Enum.ENUM9>>>;
+
+// Enum.typed global enum
+<<<Enum.TYPED_ENUM0>>>;
+<<<Enum.TYPED_ENUM1>>>;
+<<<Enum.TYPED_ENUM2>>>;
+<<<Enum.TYPED_ENUM3>>>;
+<<<Enum.TYPED_ENUM4>>>;
+<<<Enum.TYPED_ENUM5>>>;
+<<<Enum.TYPED_ENUM6>>>;
+<<<Enum.TYPED_ENUM7>>>;
+<<<Enum.TYPED_ENUM8>>>;
+<<<Enum.TYPED_ENUM9>>>;
diff --git a/tests/import/extend_array.c b/tests/import/extend_array.c
new file mode 100644 (file)
index 0000000..6780257
--- /dev/null
@@ -0,0 +1,23 @@
+#include "gwion_util.h"
+#include "gwion_ast.h"
+#include "oo.h"
+#include "vm.h"
+#include "env.h"
+#include "type.h"
+#include "instr.h"
+#include "object.h"
+#include "import.h"
+#include "instr.h"
+
+GWION_IMPORT(extend_array_test) {
+  Type t_array_ext;
+  CHECK_OB((t_array_ext = gwi_mk_type(gwi, "ArrayExt", SZ_INT, NULL)))
+  CHECK_BB(gwi_class_ini(gwi, t_array_ext, NULL, NULL))
+  Type_Decl* td = new_type_decl(new_id_list(insert_symbol("float"), 0), 0);
+  Exp e = new_exp_prim_int(1, 0);
+  Array_Sub array = new_array_sub(e);
+  add_type_decl_array(td, array);
+  CHECK_BB(gwi_class_ext(gwi, td))
+  CHECK_BB(gwi_class_end(gwi))
+  return GW_OK;
+}
diff --git a/tests/import/extend_array.gw b/tests/import/extend_array.gw
new file mode 100644 (file)
index 0000000..a3aa970
--- /dev/null
@@ -0,0 +1,3 @@
+ArrayExt a;
+<<<a>>>;
+<<<a.size()>>>;
diff --git a/tests/import/extend_event.c b/tests/import/extend_event.c
new file mode 100644 (file)
index 0000000..92a8e9e
--- /dev/null
@@ -0,0 +1,22 @@
+#include "gwion_util.h"
+#include "gwion_ast.h"
+#include "oo.h"
+#include "vm.h"
+#include "env.h"
+#include "type.h"
+#include "instr.h"
+#include "object.h"
+#include "instr.h"
+#include "import.h"
+
+static CTOR(ev_ctor) { printf(" %p this to test ctor\n", (void*)o); }
+
+GWION_IMPORT(extend_event_test) {
+  Type t_ev ;
+  CHECK_OB((t_ev = gwi_mk_type(gwi, "Ev", SZ_INT , NULL)))
+  CHECK_BB(gwi_class_ini(gwi, t_ev, ev_ctor, NULL))
+  Type_Decl* td = new_type_decl(new_id_list(insert_symbol("Event"), 0), 0);
+  CHECK_BB(gwi_class_ext(gwi, td))
+  CHECK_BB(gwi_class_end(gwi))
+  return GW_OK;
+}
diff --git a/tests/import/extend_event.gw b/tests/import/extend_event.gw
new file mode 100644 (file)
index 0000000..b4c6647
--- /dev/null
@@ -0,0 +1,2 @@
+Ev ev;
+<<<ev>>>;
diff --git a/tests/import/extend_pair.c b/tests/import/extend_pair.c
new file mode 100644 (file)
index 0000000..304a8d3
--- /dev/null
@@ -0,0 +1,28 @@
+#include "gwion_util.h"
+#include "gwion_ast.h"
+#include "oo.h"
+#include "vm.h"
+#include "env.h"
+#include "type.h"
+#include "instr.h"
+#include "object.h"
+#include "instr.h"
+#include "import.h"
+
+GWION_IMPORT(extend_pair_test) {
+  m_str types[] = { "A", "B" };
+  Type t_pair_ext ;
+  CHECK_OB((t_pair_ext = gwi_mk_type(gwi, "PairExt", SZ_INT , NULL)))
+  CHECK_BB(gwi_tmpl_ini(gwi, 2, types))
+  CHECK_BB(gwi_class_ini(gwi, t_pair_ext, NULL, NULL))
+  CHECK_BB(gwi_tmpl_end(gwi))
+  Type_Decl* td  = new_type_decl(new_id_list(insert_symbol("Pair"), 0), 0);
+  Type_Decl* td0 = new_type_decl(new_id_list(insert_symbol("A"), 0), 0);
+  Type_Decl* td1 = new_type_decl(new_id_list(insert_symbol("B"), 0), 0);
+  Type_List tl1  = new_type_list(td1, NULL);
+  Type_List tl0  = new_type_list(td0, tl1);
+  td->types = tl0;
+  CHECK_BB(gwi_class_ext(gwi, td))
+  CHECK_BB(gwi_class_end(gwi))
+  return GW_OK;
+}
diff --git a/tests/import/extend_pair.gw b/tests/import/extend_pair.gw
new file mode 100644 (file)
index 0000000..f32763d
--- /dev/null
@@ -0,0 +1,4 @@
+<~int, int~>PairExt p;
+<<<p>>>;
+<<<p.key>>>;
+<<<p.val>>>;
diff --git a/tests/import/global_func.c b/tests/import/global_func.c
new file mode 100644 (file)
index 0000000..8bfcbc3
--- /dev/null
@@ -0,0 +1,22 @@
+#include "gwion_util.h"
+#include "gwion_ast.h"
+#include "oo.h"
+#include "vm.h"
+#include "env.h"
+#include "type.h"
+#include "instr.h"
+#include "object.h"
+#include "import.h"
+#include "instr.h"
+
+SFUN(coverage_int) {
+  puts("test");
+  *(m_int*)RETURN = *(m_int*)MEM(0);
+}
+
+GWION_IMPORT(global_func_test) {
+  CHECK_BB(gwi_func_ini(gwi, "int", "test", coverage_int))
+  CHECK_BB(gwi_func_arg(gwi, "int", "i"))
+  CHECK_BB(gwi_func_end(gwi, 0))
+  return GW_OK;
+}
diff --git a/tests/import/global_func.gw b/tests/import/global_func.gw
new file mode 100644 (file)
index 0000000..4fa2281
--- /dev/null
@@ -0,0 +1,3 @@
+<<<test>>>;
+<<<1 => test>>>;
+
diff --git a/tests/import/global_var.c b/tests/import/global_var.c
new file mode 100644 (file)
index 0000000..3f46664
--- /dev/null
@@ -0,0 +1,18 @@
+#include "gwion_util.h"
+#include "gwion_ast.h"
+#include "oo.h"
+#include "vm.h"
+#include "env.h"
+#include "type.h"
+#include "object.h"
+#include "instr.h"
+#include "import.h"
+
+
+GWION_IMPORT(global_var_test) {
+//  ALLOC_PTR(i, m_uint, 1);
+  M_Object i = new_string(NULL, "test");
+  CHECK_BB(gwi_item_ini(gwi,"string", "i"))
+  CHECK_BB(gwi_item_end(gwi, 0, i))
+  return GW_OK;
+}
diff --git a/tests/import/global_var.gw b/tests/import/global_var.gw
new file mode 100644 (file)
index 0000000..a4041bc
--- /dev/null
@@ -0,0 +1 @@
+<<<i>>>;
diff --git a/tests/import/invalid_arg.c b/tests/import/invalid_arg.c
new file mode 100644 (file)
index 0000000..b817830
--- /dev/null
@@ -0,0 +1,23 @@
+#include "gwion_util.h"
+#include "gwion_ast.h"
+#include "oo.h"
+#include "vm.h"
+#include "env.h"
+#include "type.h"
+#include "object.h"
+#include "instr.h"
+#include "import.h"
+
+static MFUN(test_mfun){}
+GWION_IMPORT(invalid_arg_test) {
+    Type t_invalid_var_type ;
+  CHECK_OB((t_invalid_var_type = gwi_mk_type(gwi, "invalid_var_type", 
+          SZ_INT , NULL)))
+  CHECK_BB(gwi_class_ini(gwi, t_invalid_var_type, NULL, NULL))
+  CHECK_BB(gwi_func_ini(gwi, "int[]", "func", test_mfun))
+  CHECK_BB(gwi_func_arg(gwi, ".int", "i"))
+  CHECK_BB(gwi_func_end(gwi, ae_flag_static))
+
+  CHECK_BB(gwi_class_end(gwi))
+  return GW_OK;
+}
diff --git a/tests/import/invalid_array.c b/tests/import/invalid_array.c
new file mode 100644 (file)
index 0000000..3488086
--- /dev/null
@@ -0,0 +1,37 @@
+#include "gwion_util.h"
+#include "gwion_ast.h"
+#include "oo.h"
+#include "vm.h"
+#include "env.h"
+#include "type.h"
+#include "object.h"
+#include "instr.h"
+#include "import.h"
+
+static MFUN(test_mfun){}
+GWION_IMPORT(inalid_array_test) {
+  Type t_invalid_var_type;
+  CHECK_OB((t_invalid_var_type = gwi_mk_type(gwi, "invalid_var_type",
+          SZ_INT , NULL)))
+  CHECK_BB(gwi_class_ini(gwi, t_invalid_var_type, NULL, NULL))
+  CHECK_BB(gwi_func_ini(gwi, "int[]", "func", test_mfun))
+    CHECK_BB(gwi_func_arg(gwi, "int[][]", "i"))
+    CHECK_BB(gwi_func_arg(gwi, "int", "j[]"))
+    CHECK_BB(gwi_func_arg(gwi, "int[]", "k[]"))
+    CHECK_BB(gwi_func_arg(gwi, "int", "l"))
+  CHECK_BB(gwi_func_end(gwi, ae_flag_static))
+
+  CHECK_BB(gwi_func_ini(gwi, "int[]", "func", test_mfun))
+    CHECK_BB(gwi_func_arg(gwi, "int", "j[][]"))
+    CHECK_BB(gwi_func_arg(gwi, "int[]", "+k[][][]"))
+    CHECK_BB(gwi_func_arg(gwi, "int", "l"))
+  CHECK_BB(gwi_func_end(gwi, ae_flag_static))
+
+  CHECK_BB(gwi_func_ini(gwi, "int[]", "func", test_mfun))
+    CHECK_BB(gwi_func_arg(gwi, "+int", "j[][]"))
+    CHECK_BB(gwi_func_arg(gwi, "int[]", "+k[][][]"))
+  CHECK_BB(gwi_func_end(gwi, ae_flag_static))
+
+  CHECK_BB(gwi_class_end(gwi))
+  return GW_OK;
+}
diff --git a/tests/import/invalid_func.c b/tests/import/invalid_func.c
new file mode 100644 (file)
index 0000000..0eb8530
--- /dev/null
@@ -0,0 +1,22 @@
+#include "gwion_util.h"
+#include "gwion_ast.h"
+#include "oo.h"
+#include "vm.h"
+#include "env.h"
+#include "type.h"
+#include "object.h"
+#include "instr.h"
+#include "import.h"
+
+static MFUN(test_mfun){}
+GWION_IMPORT(invalid_func_test) {
+  Type t_invalid_var_type ;
+  CHECK_OB((t_invalid_var_type = gwi_mk_type(gwi, "invalid_var_type",
+          SZ_INT , NULL)))
+  CHECK_BB(gwi_class_ini(gwi, t_invalid_var_type, NULL, NULL))
+  CHECK_BB(gwi_func_ini(gwi, ".int", "i", test_mfun))
+  CHECK_BB(gwi_func_end(gwi, ae_flag_static))
+
+  CHECK_BB(gwi_class_end(gwi))
+  return GW_OK;
+}
diff --git a/tests/import/invalid_type1.c b/tests/import/invalid_type1.c
new file mode 100644 (file)
index 0000000..99bed3f
--- /dev/null
@@ -0,0 +1,21 @@
+#include "gwion_util.h"
+#include "gwion_ast.h"
+#include "oo.h"
+#include "vm.h"
+#include "env.h"
+#include "type.h"
+#include "object.h"
+#include "instr.h"
+#include "import.h"
+
+static MFUN(test_mfun){}
+GWION_IMPORT(invalid_type1_test) {
+  Type t_invalid_var_type;
+  CHECK_OB((t_invalid_var_type = gwi_mk_type(gwi, "invalid_var_type",
+          SZ_INT , NULL)))
+  CHECK_BB(gwi_class_ini(gwi, t_invalid_var_type, NULL, NULL))
+  CHECK_BB(gwi_item_ini(gwi,"i|nt", "test"))
+  CHECK_BB(gwi_item_end(gwi, 0, NULL))
+  CHECK_BB(gwi_class_end(gwi))
+  return GW_OK;
+}
diff --git a/tests/import/invalid_type2.c b/tests/import/invalid_type2.c
new file mode 100644 (file)
index 0000000..b2242ec
--- /dev/null
@@ -0,0 +1,21 @@
+#include "gwion_util.h"
+#include "gwion_ast.h"
+#include "oo.h"
+#include "vm.h"
+#include "env.h"
+#include "type.h"
+#include "object.h"
+#include "instr.h"
+#include "import.h"
+
+static MFUN(test_mfun){}
+GWION_IMPORT(invalid_type2_test) {
+  Type t_invalid_var_type ;
+  CHECK_OB((t_invalid_var_type = gwi_mk_type(gwi, "invalid_var_type",
+          SZ_INT , NULL)))
+  CHECK_BB(gwi_class_ini(gwi, t_invalid_var_type, NULL, NULL))
+  CHECK_BB(gwi_item_ini(gwi,".int", "test"))
+  CHECK_BB(gwi_item_end(gwi, 0, NULL))
+  CHECK_BB(gwi_class_end(gwi))
+  return GW_OK;
+}
diff --git a/tests/import/invalid_type3.c b/tests/import/invalid_type3.c
new file mode 100644 (file)
index 0000000..f8e8c9f
--- /dev/null
@@ -0,0 +1,22 @@
+#include "gwion_util.h"
+#include "gwion_ast.h"
+#include "absyn.h"
+#include "oo.h"
+#include "vm.h"
+#include "env.h"
+#include "type.h"
+#include "object.h"
+#include "instr.h"
+#include "import.h"
+
+static MFUN(test_mfun){}
+GWION_IMPORT(invalid_type3_test) {
+  Type t_invalid_var_type ;
+  CHECK_OB((t_invalid_var_type = gwi_mk_type(gwi, ".invalid_var_type",
+          SZ_INT , NULL)))
+  CHECK_BB(gwi_class_ini(gwi, t_invalid_var_type, NULL, NULL))
+  CHECK_BB(gwi_item_ini(gwi,".int", "test"))
+  CHECK_BB(gwi_item_end(gwi, 0, NULL))
+  CHECK_BB(gwi_class_end(gwi))
+  return GW_OK;
+}
diff --git a/tests/import/map2.gw b/tests/import/map2.gw
new file mode 100644 (file)
index 0000000..4834e84
--- /dev/null
@@ -0,0 +1,5 @@
+<~int, float~>Map pp;
+<<<pp>>>;
+<<<pp.size()>>>;
+<<<pp.set(1, 2)>>>;
+<<<pp.get(1)>>>;
diff --git a/tests/import/no_import.c b/tests/import/no_import.c
new file mode 100644 (file)
index 0000000..9a10bea
--- /dev/null
@@ -0,0 +1,12 @@
+#include "gwion_util.h"
+#include "gwion_ast.h"
+#include "oo.h"
+#include "vm.h"
+#include "env.h"
+#include "type.h"
+#include "object.h"
+#include "instr.h"
+#include "import.h"
+
+
+static MFUN(test_mfun){}
diff --git a/tests/import/op_err.c b/tests/import/op_err.c
new file mode 100644 (file)
index 0000000..c6b2b98
--- /dev/null
@@ -0,0 +1,17 @@
+#include "gwion_util.h"
+#include "gwion_ast.h"
+#include "oo.h"
+#include "vm.h"
+#include "env.h"
+#include "type.h"
+#include "object.h"
+#include "instr.h"
+#include "import.h"
+
+GWION_IMPORT(op_err_test) {
+  gwi_oper_ini(gwi, "int", "int", "int"); // ignore the check
+  gwi_oper_end(gwi, 220, NULL); // ignore the check.
+  CHECK_BB(gwi_oper_ini(gwi, "int", "int", "int"))
+  CHECK_BB(gwi_oper_end(gwi, op_chuck, NULL))
+  return GW_OK;
+}
diff --git a/tests/import/static_string.c b/tests/import/static_string.c
new file mode 100644 (file)
index 0000000..63befdf
--- /dev/null
@@ -0,0 +1,17 @@
+#include <stdlib.h>
+#include "gwion_util.h"
+#include "gwion_ast.h"
+#include "oo.h"
+#include "vm.h"
+#include "env.h"
+#include "type.h"
+#include "object.h"
+#include "instr.h"
+#include "import.h"
+
+GWION_IMPORT(static_string_test) {
+  CHECK_BB(gwi_item_ini(gwi, "string", "self"))
+  M_Object obj = new_string(NULL, "test static string");
+  CHECK_BB(gwi_item_end(gwi, ae_flag_global, obj))
+  return GW_OK;
+}
diff --git a/tests/import/static_string.gw b/tests/import/static_string.gw
new file mode 100644 (file)
index 0000000..fadda99
--- /dev/null
@@ -0,0 +1,2 @@
+//<<<StaticString.self>>>;
+<<<self>>>;
diff --git a/tests/import/template_arg.c b/tests/import/template_arg.c
new file mode 100644 (file)
index 0000000..e483910
--- /dev/null
@@ -0,0 +1,22 @@
+#include "gwion_util.h"
+#include "gwion_ast.h"
+#include "oo.h"
+#include "vm.h"
+#include "env.h"
+#include "type.h"
+#include "object.h"
+#include "instr.h"
+#include "import.h"
+
+static MFUN(template_arg_fun) {}
+
+GWION_IMPORT(template_arg_test) {
+  Type t_template_arg;
+  CHECK_OB((t_template_arg = gwi_mk_type(gwi, "TemplateArg", SZ_INT , NULL)))
+  CHECK_BB(gwi_class_ini(gwi, t_template_arg, NULL, NULL))
+  CHECK_BB(gwi_func_ini(gwi, "int", "set", template_arg_fun))
+  CHECK_BB(gwi_func_arg(gwi, "Pair<Ptr<int>,float>","test"))
+  CHECK_BB(gwi_func_end(gwi, 0))
+  CHECK_BB(gwi_class_end(gwi))
+  return GW_OK;
+}
diff --git a/tests/import/typedef.c b/tests/import/typedef.c
new file mode 100644 (file)
index 0000000..61f228c
--- /dev/null
@@ -0,0 +1,27 @@
+#include "gwion_util.h"
+#include "gwion_ast.h"
+#include "oo.h"
+#include "vm.h"
+#include "env.h"
+#include "type.h"
+#include "object.h"
+#include "instr.h"
+#include "import.h"
+
+static MFUN(test_func) { puts("test"); }
+GWION_IMPORT(typedef_test) {
+  Type t_func_typedef;
+  CHECK_OB((t_func_typedef = gwi_mk_type(gwi, "FuncTypedef", SZ_INT , NULL)))
+  CHECK_BB(gwi_fptr_ini(gwi, "void", "PtrType"))
+  CHECK_BB(gwi_fptr_end(gwi, 0))
+  
+  CHECK_BB(gwi_class_ini(gwi, t_func_typedef, NULL, NULL))
+    CHECK_BB(gwi_fptr_ini(gwi, "void", "PtrType"))
+    CHECK_BB(gwi_fptr_end(gwi, ae_flag_static))
+    CHECK_BB(gwi_func_ini(gwi, "void", "test_func", test_func))
+    CHECK_BB(gwi_func_end(gwi, ae_flag_static))
+    CHECK_BB(gwi_item_ini(gwi, "PtrType", "ptr"))
+    CHECK_BB(gwi_item_end(gwi, ae_flag_static, NULL))
+  CHECK_BB(gwi_class_end(gwi))
+  return GW_OK;
+}
diff --git a/tests/import/typedef.gw b/tests/import/typedef.gw
new file mode 100644 (file)
index 0000000..25282b0
--- /dev/null
@@ -0,0 +1,13 @@
+fun void test(){ <<<"test">>>; }
+PtrType ptr;
+test();
+test @=> ptr;
+ptr();
+
+
+FuncTypedef.test_func();
+<<<FuncTypedef.test_func @=> FuncTypedef.ptr>>>;
+<FuncTypedef.PtrType> _ptr;
+<<<FuncTypedef.ptr>>>;
+FuncTypedef.ptr();
+
diff --git a/tests/import/union.c b/tests/import/union.c
new file mode 100644 (file)
index 0000000..fe78166
--- /dev/null
@@ -0,0 +1,17 @@
+#include "gwion_util.h"
+#include "gwion_ast.h"
+#include "oo.h"
+#include "vm.h"
+#include "env.h"
+#include "type.h"
+#include "object.h"
+#include "instr.h"
+#include "import.h"
+
+GWION_IMPORT(union_test) {
+  CHECK_BB(gwi_union_ini(gwi, NULL))
+  CHECK_BB(gwi_union_add(gwi,"float", "f"))
+  CHECK_BB(gwi_union_add(gwi,"int", "i"))
+  CHECK_BB(gwi_union_end(gwi, 0))
+  return GW_OK;
+}
diff --git a/tests/import/union.gw b/tests/import/union.gw
new file mode 100644 (file)
index 0000000..b838c6a
--- /dev/null
@@ -0,0 +1,8 @@
+Union u;
+<<<u.i>>>;
+<<<12 => u.f>>>;
+<<<1 => u.i>>>;
+<<<u.i>>>;
+<<<u.f>>>;
+<<<0 => u.i>>>;
+<<<null @=> u.o>>>;
diff --git a/tests/import/variadic.c b/tests/import/variadic.c
new file mode 100644 (file)
index 0000000..edbb6bf
--- /dev/null
@@ -0,0 +1,49 @@
+#include "gwion_util.h"
+#include "gwion_ast.h"
+#include "oo.h"
+#include "vm.h"
+#include "env.h"
+#include "type.h"
+#include "instr.h"
+#include "object.h"
+#include "import.h"
+#include "vararg.h"
+
+static MFUN(m_test) {
+  printf("%p\n", *(M_Object*)MEM(0));
+}
+
+static MFUN(m_variadic) {
+  M_Object str_obj = *(M_Object*)MEM(SZ_INT);
+  if(!str_obj)return;
+  m_str str = STRING(str_obj);
+  struct Vararg_* arg = *(struct Vararg_**)MEM(SZ_INT*2);
+
+  while(arg->i < arg->s) {
+    if(*str == 'i') {
+      printf("%" INT_F "\n", *(m_int*)(arg->d + arg->o));
+      arg->o += SZ_INT;
+    } else if(*str == 'f') {
+      printf("%f\n", *(m_float*)(arg->d + arg->o));
+      arg->o += SZ_FLOAT;
+    } else if(*str == 'o') {
+      printf("%p\n", (void*)*(M_Object*)(arg->d + arg->o));
+      arg->o += SZ_INT;
+    }
+    arg->i++;
+    str++;
+  }
+  free_vararg(arg);
+}
+
+GWION_IMPORT(variadic test) {
+  const Type t_variadic = gwi_mk_type(gwi, "Variadic", SZ_INT, t_object);
+  CHECK_BB(gwi_class_ini(gwi, t_variadic, NULL, NULL))
+  CHECK_BB(gwi_func_ini(gwi, "void", "member", m_variadic))
+  CHECK_BB(gwi_func_arg(gwi, "string", "format"))
+  CHECK_BB(gwi_func_end(gwi, ae_flag_variadic))
+  CHECK_BB(gwi_func_ini(gwi, "void", "test", m_test))
+  CHECK_BB(gwi_func_end(gwi, 0))
+  CHECK_BB(gwi_class_end(gwi))
+  return GW_OK;
+}
diff --git a/tests/import/variadic.gw b/tests/import/variadic.gw
new file mode 100644 (file)
index 0000000..c315163
--- /dev/null
@@ -0,0 +1,13 @@
+<<<"test builtin variadic function">>>;
+Variadic v;
+"iiii" => string format;
+<<<v, " ", format $ Object>>>;
+v.member(format, 1,2,3,4);
+v.member(format, 1,2,3,4);
+v.test();
+v.member(format, 1,2,3,4);
+v.member(format, 1,2,3,4);
+v.test();
+v.member(format, 1,2,3,4);
+v.member(format, 1,2,3,4);
+v.test();