From de0b35ac1211ebd505121ab4a45adbb81824dc2c Mon Sep 17 00:00:00 2001
From: fennecdjay <fennecdjay@gmail.com>
Date: Mon, 8 Aug 2022 15:51:00 +0200
Subject: [PATCH] :art: Update

---
 include/instr.h     |  2 ++
 src/emit/emit.c     |  9 +++------
 src/emit/emitter.c  |  9 +++++++--
 src/lib/object_op.c |  1 -
 src/parse/check.c   | 46 ++++++++++++++++++++++++++++++++++++++++-----
 src/parse/scan1.c   | 12 ++++++------
 src/parse/scan2.c   |  6 ++----
 src/vm/shreduler.c  | 15 +++++++++++----
 src/vm/vm.c         |  8 ++++----
 9 files changed, 76 insertions(+), 32 deletions(-)

diff --git a/include/instr.h b/include/instr.h
index 8a7466bd..d85e5962 100644
--- a/include/instr.h
+++ b/include/instr.h
@@ -35,6 +35,8 @@ struct Instr_ {
 };
 #define BYTECODE_SZ (SZ_INT * 4)
 
+__attribute__((returns_nonnull)) ANN2(1) Instr
+new_instr(const MemPool mp, const f_instr f);
 ANN void free_instr(const Gwion, const Instr);
 INSTR(EOC);
 INSTR(DTOR_EOC);
diff --git a/src/emit/emit.c b/src/emit/emit.c
index 0958be8a..077a39c4 100644
--- a/src/emit/emit.c
+++ b/src/emit/emit.c
@@ -2351,12 +2351,9 @@ ANN static m_bool emit_stmt_loop(const Emitter emit, const Stmt_Loop stmt) {
 
 ANN static m_bool emit_type_def(const Emitter emit, const Type_Def tdef) {
   if (tdef->when_def) CHECK_BB(emit_func_def(emit, tdef->when_def));
-
-  if (tflag(tdef->type, tflag_cdef)) {
-    if(!tflag(tdef->type->info->parent, tflag_emit))
-                    return emit_class_def(emit, tdef->type->info->parent->info->cdef);
-  }
-  return tdef->type->info->cdef ? emit_class_def(emit, tdef->type->info->cdef) : GW_OK;
+  if (tflag(tdef->type, tflag_cdef))
+    return emit_class_def(emit, tdef->type->info->cdef);
+  return GW_OK;
 }
 
 ANN static m_bool emit_enum_def(const Emitter emit NUSED, const Enum_Def edef) {
diff --git a/src/emit/emitter.c b/src/emit/emitter.c
index d15592e8..b3473321 100644
--- a/src/emit/emitter.c
+++ b/src/emit/emitter.c
@@ -36,14 +36,19 @@ ANN void free_emitter(MemPool p, Emitter a) {
 }
 
 __attribute__((returns_nonnull)) ANN2(1) Instr
-emit_add_instr(const Emitter emit, const f_instr f) {
-  const Instr instr = mp_calloc(emit->gwion->mp, Instr);
+new_instr(const MemPool mp, const f_instr f) {
+  const Instr instr = mp_calloc(mp, Instr);
   if ((m_uint)f < 255)
     instr->opcode = (m_uint)f;
   else {
     instr->opcode  = eOP_MAX;
     instr->execute = f;
   }
+  return instr;
+}
+__attribute__((returns_nonnull)) ANN2(1) Instr
+emit_add_instr(const Emitter emit, const f_instr f) {
+  const Instr instr = new_instr(emit->gwion->mp, f);
   vector_add(&emit->code->instr, (vtype)instr);
   return instr;
 }
diff --git a/src/lib/object_op.c b/src/lib/object_op.c
index 30c44658..3266bbce 100644
--- a/src/lib/object_op.c
+++ b/src/lib/object_op.c
@@ -477,6 +477,5 @@ GWION_IMPORT(object_op) {
   GWI_BB(gwi_oper_ini(gwi, "@Compound", NULL, NULL))
   GWI_BB(gwi_oper_add(gwi, opck_struct_scan))
   GWI_BB(gwi_oper_end(gwi, "@scan", NULL))
-
   return GW_OK;
 }
diff --git a/src/parse/check.c b/src/parse/check.c
index ff80ee37..ef7db50f 100644
--- a/src/parse/check.c
+++ b/src/parse/check.c
@@ -669,8 +669,32 @@ ANN static Type_List check_template_args(const Env env, Exp_Call *exp,
   const bool spread = is_spread_tmpl(fdef->base->tmpl);
   const uint32_t len = sl->len - spread;
   Type_List    tl = new_mp_vector(env->gwion->mp, Type_Decl*, len);
-
   m_uint       args_number = 0;
+
+  if(exp->other) {
+    for(uint32_t i = 0; i < len; i++) {
+      Specialized *spec = mp_vector_at(sl, Specialized, i);
+      if (spec->xid == fdef->base->td->xid) { // check no next?
+        CHECK_OO(check_exp(env, exp->other));
+         if(!is_func(env->gwion, exp->other->type)) {
+           Type_Decl *td = type2td(env->gwion, exp->other->type, fdef->base->pos);
+           mp_vector_set(tl, Type_Decl*, 0, td);
+         } else {
+           Func func = exp->other->type->info->func;
+           do {
+             if(mp_vector_len(func->def->base->args) == 1) {
+               Arg *arg = mp_vector_at(func->def->base->args, Arg, 0);
+               Type_Decl *td = cpy_type_decl(env->gwion->mp, arg->td);
+               mp_vector_set(tl, Type_Decl*, 0, td);
+               break;
+             }
+           } while((func = func->next));
+        }
+        ++args_number;
+        break;
+      }
+    }
+  }
   for(uint32_t i = 0; i < len; i++) {
     Specialized *spec = mp_vector_at(sl, Specialized, i);
     Arg_List args          = fdef->base->args;
@@ -913,8 +937,13 @@ ANN Type check_exp_call1(const Env env, Exp_Call *const exp) {
 }
 
 ANN static Type check_exp_binary(const Env env, const Exp_Binary *bin) {
+  if(bin->lhs->exp_type == ae_exp_call && !bin->lhs->d.exp_call.tmpl) {
+    CHECK_OO(check_exp(env, bin->lhs->d.exp_call.func));
+    // check is template?
+    bin->lhs->d.exp_call.other = bin->rhs;
+  }
   CHECK_OO(check_exp(env, bin->lhs));
-  const m_bool is_auto = bin->op == insert_symbol(":=>")  &&
+  const m_bool is_auto = //bin->op == insert_symbol(":=>")  &&
                          bin->rhs->exp_type == ae_exp_decl &&
                          bin->rhs->d.exp_decl.type == env->gwion->type[et_auto];
   if (is_auto) bin->rhs->d.exp_decl.type = bin->lhs->type;
@@ -930,12 +959,19 @@ ANN static Type check_exp_binary(const Env env, const Exp_Binary *bin) {
    e->exp_type = ae_exp_unary;
    unary->unary_type = unary_td;
    unary->op = insert_symbol("new");
-   unary->ctor.td = cpy_type_decl(env->gwion->mp, bin->rhs->d.exp_unary.ctor.td);
+   unary->ctor.td = new_type_decl(env->gwion->mp, insert_symbol("auto"), bin->rhs->d.exp_unary.ctor.td->pos);
    unary->ctor.exp = lhs;
    free_exp(env->gwion->mp, rhs);
    return check_exp(env, e);
   }
+  if(bin->rhs->exp_type == ae_exp_call && !bin->rhs->d.exp_call.tmpl)
+    bin->rhs->d.exp_call.other = bin->lhs;
+  const m_uint scope = env->scope->depth;
+  if(bin->op == insert_symbol(">=>"))
+    env_push_type(env, bin->lhs->type);
   CHECK_OO(check_exp(env, bin->rhs));
+  if(bin->op == insert_symbol(">=>"))
+    env_pop(env, scope);
   if (is_auto) {
     assert(bin->rhs->type == bin->lhs->type);
     set_vflag(bin->rhs->d.exp_decl.vd.value, vflag_assigned);
@@ -1115,8 +1151,6 @@ ANN static Type check_exp_dot(const Env env, Exp_Dot *member) {
 }
 
 ANN m_bool check_type_def(const Env env, const Type_Def tdef) {
-  if(tdef->ext->array && tdef->ext->array->exp)
-    CHECK_OB(check_exp(env, tdef->type->info->cdef->base.ext->array->exp));
   if (tdef->when) {
     set_tflag(tdef->type, tflag_contract);
     struct Var_Decl_ decl = { .xid = insert_symbol("self"), .pos = tdef->when->pos };
@@ -1169,6 +1203,8 @@ ANN m_bool check_type_def(const Env env, const Type_Def tdef) {
     mp_vector_set(fdef->d.code->d.stmt_code.stmt_list, struct Stmt_, 1, ret);
     ret_id->type = tdef->type;
   }
+  if (tflag(tdef->type, tflag_cdef))
+    return check_class_def(env, tdef->type->info->cdef);
   return GW_OK;
 }
 
diff --git a/src/parse/scan1.c b/src/parse/scan1.c
index 11590445..627379f4 100644
--- a/src/parse/scan1.c
+++ b/src/parse/scan1.c
@@ -190,6 +190,8 @@ ANN static inline m_bool scan1_prim(const Env env, const Exp_Primary *prim) {
   if (prim->prim_type == ae_prim_array && prim->d.array->exp)
     return scan1_exp(env, prim->d.array->exp);
   if (prim->prim_type == ae_prim_range) return scan1_range(env, prim->d.range);
+  if (env->func && prim->prim_type == ae_prim_perform && env->scope->depth <= 2)
+    env->func->memoize = 1;
   return GW_OK;
 }
 
@@ -465,12 +467,10 @@ ANN m_bool scan1_fptr_def(const Env env, const Fptr_Def fptr) {
 }
 
 ANN m_bool scan1_type_def(const Env env, const Type_Def tdef) {
-  if (!tdef->type) tdef->type = nspc_lookup_type0(env->curr, tdef->xid);
+  //if (!tdef->type) tdef->type = nspc_lookup_type0(env->curr, tdef->xid);
   if (tdef->when) CHECK_BB(scan1_exp(env, tdef->when));
-  if (!tflag(tdef->type, tflag_cdef)) {
-    if(!tflag(tdef->type->info->parent, tflag_scan1))
-                    return scan1_class_def(env, tdef->type->info->parent->info->cdef);
-  }
+  if (tflag(tdef->type, tflag_cdef))
+    return scan1_class_def(env, tdef->type->info->cdef);
   return tdef->type->info->cdef ? scan1_cdef(env, tdef->type) : GW_OK;
 }
 
@@ -682,7 +682,7 @@ ANN static m_bool _scan1_func_def(const Env env, const Func_Def fdef) {
        fdef->base->ret_type != env->gwion->type[et_void] && fdef->d.code &&
        !fake.memoize)
      ERR_B(fdef->base->td->pos,
-           _("missing return statement in a non void function %u"), fake.memoize);
+           _("missing return statement in a non void function"));
   if (fdef->base->xid == insert_symbol("@gack") && !fake.weight) {
     gwerr_basic(_("`@gack` operator does not print anything"), NULL,
       _("use `<<<` `>>>` in the function"), env->name, fdef->base->pos, 0);
diff --git a/src/parse/scan2.c b/src/parse/scan2.c
index 876cc82d..4536842c 100644
--- a/src/parse/scan2.c
+++ b/src/parse/scan2.c
@@ -87,10 +87,8 @@ ANN m_bool scan2_fptr_def(const Env env NUSED, const Fptr_Def fptr) {
 ANN static m_bool scan2_func_def_op(const Env env, const Func_Def f);
 ANN m_bool        scan2_type_def(const Env env, const Type_Def tdef) {
   if (tdef->when) CHECK_BB(scan2_exp(env, tdef->when));
-  if (tflag(tdef->type, tflag_cdef)) {
-    if(!tflag(tdef->type->info->parent, tflag_scan2))
-                    return scan2_class_def(env, tdef->type->info->parent->info->cdef);
-  }
+  if (tflag(tdef->type, tflag_cdef))
+    return scan2_class_def(env, tdef->type->info->cdef);
   if (!tdef->type->info->cdef) return GW_OK;
   return tdef->type->info->cdef ? scan2_class_def(env, tdef->type->info->cdef) : GW_OK;
 }
diff --git a/src/vm/shreduler.c b/src/vm/shreduler.c
index 7e647175..bd793d97 100644
--- a/src/vm/shreduler.c
+++ b/src/vm/shreduler.c
@@ -76,11 +76,9 @@ ANN void shreduler_remove(const Shreduler s, const VM_Shred out,
   MUTEX_UNLOCK(s->mutex);
 }
 
-ANN void shredule(const Shreduler s, const VM_Shred shred,
+ANN void _shredule(const Shreduler s,   struct ShredTick_ *tk,
                   const m_float wake_time) {
-  struct ShredTick_ *tk   = shred->tick;
   if(tk->prev == (struct ShredTick_*)-1) return;
-  MUTEX_LOCK(s->mutex);
   const m_float      time = wake_time + (m_float)s->bbq->pos;
   tk->wake_time           = time;
   if (s->list) {
@@ -100,6 +98,13 @@ ANN void shredule(const Shreduler s, const VM_Shred shred,
   } else
     s->list = tk;
   if (tk == s->curr) s->curr = NULL;
+}
+
+ANN void shredule(const Shreduler s, const VM_Shred shred,
+                  const m_float wake_time) {
+  struct ShredTick_ *tk   = shred->tick;
+  MUTEX_LOCK(s->mutex);
+  _shredule(s, tk, wake_time);
   MUTEX_UNLOCK(s->mutex);
 }
 
@@ -112,8 +117,10 @@ ANN void shreduler_ini(const Shreduler s, const VM_Shred shred) {
 ANN void shreduler_add(const Shreduler s, const VM_Shred shred) {
   shreduler_ini(s, shred);
   shred->tick->xid = ++s->shred_ids;
+  MUTEX_LOCK(s->mutex);
   vector_add(&s->active_shreds, (vtype)shred);
-  shredule(s, shred, GWION_EPSILON);
+  _shredule(s, shred->tick, GWION_EPSILON);
+  MUTEX_UNLOCK(s->mutex);
 }
 
 ANN Shreduler new_shreduler(const MemPool mp) {
diff --git a/src/vm/vm.c b/src/vm/vm.c
index 1f31a702..d14d07a4 100644
--- a/src/vm/vm.c
+++ b/src/vm/vm.c
@@ -59,7 +59,7 @@ ANN static void clean_values(const VM_Shred shred) {
   }
 }
 
-ANN static uint16_t find_pc(const VM_Shred shred, const Symbol effect, const m_uint size) {
+ANN static uint16_t find_pc(const VM_Shred shred, const Symbol effect) {
   const VM_Code code = shred->code;
   const m_uint start = vector_at(&shred->info->frame, vector_size(&shred->info->frame) - 2);
   if (start > shred->pc) return true;
@@ -76,8 +76,8 @@ ANN static uint16_t find_pc(const VM_Shred shred, const Symbol effect, const m_u
   return 0;
 }
 
-ANN static inline bool find_handle(const VM_Shred shred, const Symbol effect, const m_uint size) {
-  const uint16_t pc = find_pc(shred, effect, size);
+ANN static inline bool find_handle(const VM_Shred shred, const Symbol effect) {
+  const uint16_t pc = find_pc(shred, effect);
   if (!pc) return false; // outside of a try statement
   shred->reg = // restore reg
       (m_bit *)VPTR(&shred->info->frame, VLEN(&shred->info->frame) - 1);
@@ -94,7 +94,7 @@ ANN bool unwind(const VM_Shred shred, const Symbol effect, const m_uint size) {
     clean_values(shred);
   if (!size) return false;
   if (code->handlers.ptr)
-    return find_handle(shred, effect, size);
+    return find_handle(shred, effect);
   // there might be no more stack to unwind
   if (shred->mem == (m_bit *)shred + sizeof(struct VM_Shred_) + SIZEOF_REG)
     return false;
-- 
2.43.0