]> Nishi Git Mirror - gwion.git/commitdiff
:fire: Update Effects
authorJérémie Astor <fennecdjay@gmail.com>
Tue, 27 Apr 2021 15:15:14 +0000 (17:15 +0200)
committerJérémie Astor <fennecdjay@gmail.com>
Tue, 27 Apr 2021 15:15:14 +0000 (17:15 +0200)
15 files changed:
ast
include/array.h
include/env/env.h
include/vm.h
src/emit/emit.c
src/env/env.c
src/lib/array.c
src/lib/lib_func.c
src/parse/check.c
src/parse/func_resolve_tmpl.c
src/parse/operator.c
src/parse/scanx.c
src/vm/vm.c
src/vm/vm_shred.c
util

diff --git a/ast b/ast
index 3b040d5d5d552df2fb7413545aab0c90055d8634..ded33ab49b042a39ae473a0b2e1841081891f47a 160000 (submodule)
--- a/ast
+++ b/ast
@@ -1 +1 @@
-Subproject commit 3b040d5d5d552df2fb7413545aab0c90055d8634
+Subproject commit ded33ab49b042a39ae473a0b2e1841081891f47a
index 49c9b31c185022c3b5b38a24c612a14aab1aec1e..6fe233a4250476ffb82de0d80e3a68bde5e0d157 100644 (file)
@@ -7,15 +7,6 @@ struct ArrayAccessInfo {
   const bool is_var;
 };
 
-typedef struct M_Vector_  {
-  m_bit* ptr;
-} * M_Vector;
-#define ARRAY_OFFSET SZ_INT * 4
-#define ARRAY_PTR(array) (array->ptr + ARRAY_OFFSET)
-#define ARRAY_LEN(array) *(m_uint*)(array->ptr)
-#define ARRAY_SIZE(array) *(m_uint*)(array->ptr + SZ_INT)
-#define ARRAY_CAP(array) *(m_uint*)(array->ptr + SZ_INT*2)
-
 typedef struct ArrayInfo_ {
   m_int depth;
   struct Vector_   type;
@@ -28,24 +19,6 @@ typedef struct ArrayInfo_ {
   uint is_obj;
 } ArrayInfo;
 
-ANN static inline m_uint m_vector_size(const M_Vector v) {
-  return ARRAY_LEN(v);
-}
-
-ANN static inline void m_vector_get(const M_Vector v, const m_uint i, void* c) {
-  const m_uint size = ARRAY_SIZE(v);
-  memcpy(c, ARRAY_PTR(v) + i * size, size);
-}
-
-ANN static inline m_bit* m_vector_addr(const M_Vector v, const m_uint i) {
-  return &*(m_bit*)(ARRAY_PTR(v) + i * ARRAY_SIZE(v));
-}
-
-ANN void   m_vector_set(const M_Vector,  const m_uint, const void*);
-ANN void   m_vector_add(const M_Vector,  const void*);
-ANN void m_vector_rem(const M_Vector,  const m_uint);
-ANEW M_Vector new_m_vector(MemPool, const m_uint size, const m_uint len);
-ANN void free_m_vector(MemPool, M_Vector);
 ANN Type check_array_access(const Env env, const Array_Sub array);
 ANN m_bool emit_array_access(const Emitter emit, struct ArrayAccessInfo *const info);
 #endif
index 0962ba9e6ccd59b0c31edf69adda01ec109605d5..72683789294a7da071f997d8ce9dfd0019fcbcbf 100644 (file)
@@ -11,7 +11,9 @@ struct Env_Scope_ {
   struct Vector_  conts;
   struct Vector_  known_ctx;
   struct Match_  *match;
-  size_t depth;
+  struct Vector_ effects; // a vector of Effect[]
+  uint   depth;
+  bool   in_try;
 };
 
 typedef struct Env_ {
@@ -46,4 +48,11 @@ ANN void env_err(const Env, const loc_t pos, const m_str fmt, ...);
 ANN void env_warn(const Env, const loc_t pos, const m_str fmt, ...);
 ANN Value global_string(const Env env, const m_str str);
 ANN void release_ctx(struct Env_Scope_ *a, struct Gwion_* gwion);
+
+struct ScopeEffect {
+  Symbol sym;
+  loc_t pos;
+};
+
+ANN void env_add_effect(const Env a, const Symbol effect, const loc_t pos);
 #endif
index 3e3b8cf2f0e40ad4f753e72309dad048271de656..3e2944c555291e6e83aaf95fcf2d37a322569144 100644 (file)
@@ -53,7 +53,7 @@ struct ShredInfo_ {
   Vector args;
   MemPool mp;
   VM_Code orig;
-  struct Map_ frame;
+  struct Vector_ frame;
 };
 
 struct ShredTick_ {
index 21874c26ee134a9a62d8bec8c8f3f5d4b3d173a5..6f1ce8f2b29afa69737d1007ccb9536e0ed7d2a5 100644 (file)
@@ -2127,7 +2127,7 @@ ANN static m_bool emit_stmt_defer(const Emitter emit, const struct Stmt_Defer_*
 
 ANN static m_bool emit_stmt_retry(const Emitter emit, const struct Stmt_Index_* stmt NUSED) {
   const Instr instr = emit_add_instr(emit, Goto);
-  instr->m_val = emit->code->frame->try_top;
+  instr->m_val = emit->code->frame->try_top + 1;
   return GW_OK;
 }
 
index 5eda55172ab00ea6d156115e0943942271aa26c5..4105abba9ea67f8af2e20bf000f2aa90383fe6e7 100644 (file)
@@ -16,6 +16,7 @@ ANN static struct Env_Scope_ *new_envscope(MemPool p) {
   vector_init(&a->class_stack);
   vector_init(&a->nspc_stack);
   vector_init(&a->known_ctx);
+  vector_init(&a->effects);
   return a;
 }
 
@@ -35,6 +36,7 @@ ANN void env_reset(const Env env) {
   vector_add(&env->scope->nspc_stack, (vtype)env->global_nspc);
   vector_clear(&env->scope->class_stack);
   vector_add(&env->scope->class_stack, (vtype)NULL);
+  vector_add(&env->scope->effects, 0);
   env->curr = env->global_nspc;
   env->class_def = NULL;
   env->func = NULL;
@@ -58,9 +60,25 @@ ANN static void free_env_scope(struct Env_Scope_  *a, Gwion gwion) {
   vector_release(&a->class_stack);
   vector_release(&a->breaks);
   vector_release(&a->conts);
+  const Vector v = &a->effects;
+  for(m_uint i = 0; i < vector_size(v); i++) {
+    m_uint _v = vector_at(v, i);
+    if(_v)
+      m_vector_release((M_Vector)&_v);
+  }
+  vector_release(&a->effects);
   mp_free(gwion->mp, Env_Scope, a);
 }
 
+ANN void env_add_effect(const Env a, const Symbol effect, const loc_t pos) {
+  const Vector v = &a->scope->effects;
+  const M_Vector w = (M_Vector)&VPTR(v, VLEN(v) - 1);
+  if(!w->ptr)
+    m_vector_init(w, sizeof(struct ScopeEffect), 0);
+  struct ScopeEffect eff = { effect, pos };
+  m_vector_add(w, &eff);
+}
+
 ANN void free_env(const Env a) {
   free_env_scope(a->scope, a->gwion);
   while(pop_global(a->gwion));
@@ -72,6 +90,7 @@ ANN2(1,3) m_uint env_push(const Env env, const Type type, const Nspc nspc) {
   vector_add(&env->scope->class_stack, (vtype)env->class_def);
   env->class_def = type;
   vector_add(&env->scope->nspc_stack, (vtype)env->curr);
+  vector_add(&env->scope->effects, 0);
   env->curr = nspc;
   env->scope->depth = 0;
   return scope;
@@ -80,6 +99,9 @@ ANN2(1,3) m_uint env_push(const Env env, const Type type, const Nspc nspc) {
 ANN void env_pop(const Env env, const m_uint scope) {
   env->class_def = (Type)vector_pop(&env->scope->class_stack);
   env->curr = (Nspc)vector_pop(&env->scope->nspc_stack);
+  const m_uint _v = vector_pop(&env->scope->effects);
+  if(_v)
+    m_vector_release((M_Vector)&_v);
   env->scope->depth = scope;
 }
 
index 1f8d9180950142be2f37d5cf65d72009f604aa7c..ff4e74e3631827fe8b66dff274a6e1aab57ddba5 100644 (file)
 #include "gwi.h"
 #include "emit.h"
 
-M_Vector new_m_vector(MemPool p, const m_uint size, const m_uint len) {
-  const M_Vector array = mp_calloc(p, M_Vector);
-  const size_t sz = (ARRAY_OFFSET*SZ_INT) + (len*size);
-  array->ptr   = (m_bit*)xcalloc(1, sz);
-  m_uint cap = 1;
-  while(cap < len)
-    cap *= 2;
-  ARRAY_CAP(array)   = cap;
-  ARRAY_SIZE(array)  = size;
-  ARRAY_LEN(array) = len;
-  return array;
-}
-
-void free_m_vector(MemPool p, M_Vector a) {
-  xfree(a->ptr);
-  mp_free(p, M_Vector, a);
-}
-
 static DTOR(array_dtor) {
   if(*(void**)(o->data + SZ_INT))
     xfree(*(void**)(o->data + SZ_INT));
@@ -61,52 +43,6 @@ ANN M_Object new_array(MemPool p, const Type t, const m_uint length) {
   return a;
 }
 
-ANN void m_vector_add(const M_Vector v, const void* data) {
-  const m_uint size = ARRAY_SIZE(v);
-  if(++ARRAY_LEN(v) >= ARRAY_CAP(v)) {
-    const m_uint cap = ARRAY_CAP(v) *=2;
-    v->ptr = (m_bit*)xrealloc(v->ptr, ARRAY_OFFSET + cap * size);
-  }
-  memcpy(ARRAY_PTR(v) + (ARRAY_LEN(v) - 1) * size, data, size);
-}
-
-ANN void m_vector_add_front(const M_Vector v, const void* data) {
-  const m_uint size = ARRAY_SIZE(v);
-  if(++ARRAY_LEN(v) >= ARRAY_CAP(v)) {
-    const m_uint cap = ARRAY_CAP(v) *=2;
-    v->ptr = (m_bit*)xrealloc(v->ptr, ARRAY_OFFSET + cap * size);
-  }
-  memmove(ARRAY_PTR(v) + size, ARRAY_PTR(v), ARRAY_LEN(v) * size);
-  memmove(ARRAY_PTR(v), data, size);
-}
-
-ANN void m_vector_set(const M_Vector v, const m_uint i, const void* data) {
-  const m_uint size = ARRAY_SIZE(v);
-  memcpy(ARRAY_PTR(v) + i * size, data, size);
-}
-
-ANN void m_vector_rem(const M_Vector v, m_uint index) {
-  const m_uint size = ARRAY_SIZE(v);
-  if(index < ARRAY_LEN(v) - 1)
-    memmove(ARRAY_PTR(v) + index * size, ARRAY_PTR(v) + (index + 1) * size,
-      (ARRAY_LEN(v) - index - 1) *size);
-  --ARRAY_LEN(v);
-  if(ARRAY_LEN(v) < ARRAY_CAP(v) / 2) {
-    const m_uint cap = ARRAY_CAP(v) /= 2;
-    v->ptr = (m_bit*)xrealloc(v->ptr, ARRAY_OFFSET + cap * size);
-  }
-}
-
-ANN void m_vector_insert(const M_Vector v, m_uint index, const void* data) {
-  const size_t size = ARRAY_SIZE(v);
-  if(++ARRAY_LEN(v) >= ARRAY_CAP(v)) {
-    const m_uint cap = ARRAY_CAP(v) *=2;
-    v->ptr = (m_bit*)xrealloc(v->ptr, ARRAY_OFFSET + cap * size);
-  }
-  memmove(ARRAY_PTR(v) + (index+1) * size, ARRAY_PTR(v) + index*size, (ARRAY_LEN(v) - index + 1)* size);
-  memcpy(ARRAY_PTR(v) + index*size, data, size);
-}
-
 static MFUN(vm_vector_rem) {
   const m_int index = *(m_int*)(shred->mem + SZ_INT);
   const M_Vector v = ARRAY(o);
index ac0d16b475f4c9944086d42325260631d0b3f4dc..d101d1081ce3521a917f47f237b607b4b42e4d8e 100644 (file)
@@ -104,6 +104,24 @@ ANN static m_bool fptr_args(const Env env, Func_Base *base[2]) {
   return !arg1 ? GW_OK : GW_ERROR;
 }
 
+ANN static bool fptr_effects(const Env env, struct FptrInfo *info) {
+  if(!info->lhs->def->base->effects.ptr)
+    return true;
+  if(!info->rhs->def->base->effects.ptr) {
+    puts("too many effects");
+    return false;
+  }
+  const Vector lhs = &info->lhs->def->base->effects;
+  const Vector rhs = &info->rhs->def->base->effects;
+  for(m_uint i = 0; i < vector_size(lhs); i++) {
+    if(vector_find(rhs, vector_at(lhs, 0)) == -1) {
+      gwerr_secondary("effect not handled", env->name, info->pos);
+      return false;
+    }
+  }
+  return true;
+}
+
 ANN static m_bool fptr_check(const Env env, struct FptrInfo *info) {
 //  if(!info->lhs->def->base->tmpl != !info->rhs->def->base->tmpl)
 //    return GW_ERROR;
@@ -157,8 +175,8 @@ ANN static Type fptr_type(const Env env, struct FptrInfo *info) {
     Type type = NULL;
     Func_Base *base[2] =  { info->lhs->def->base, info->rhs->def->base };
     CHECK_BO(fptr_tmpl_push(env, info))
-    if(fptr_rettype(env, info) > 0 &&
-         fptr_arity(info) && fptr_args(env, base) > 0)
+    if (fptr_rettype(env, info) > 0 && fptr_arity(info) &&
+        fptr_args(env, base) > 0 && fptr_effects(env, info))
       type = actual_type(env->gwion, info->lhs->value_ref->type) ?: info->lhs->value_ref->type;
     if(info->rhs->def->base->tmpl)
       nspc_pop_type(env->gwion->mp, env->curr);
@@ -181,7 +199,7 @@ ANN static m_bool _check_lambda(const Env env, Exp_Lambda *l, const Func_Def def
   l->def->base->td = type2td(env->gwion, known_type(env, def->base->td), exp_self(l)->pos);
   if(is_tmpl)
     nspc_pop_type(env->gwion->mp, env->curr);
-  if(base || arg) // beware, error between pops
+  if(base || arg)
     ERR_B(exp_self(l)->pos, _("argument number does not match for lambda"))
   l->def->base->flag = def->base->flag;
 //  if(GET_FLAG(def->base, global) && !l->owner && def->base->func->value_ref->from->owner_class)
index df1622c3f434d3c133a9d28df73f9789a55341cf..31d24917dc270bb80b9f7057999e05c9aa58d10a 100644 (file)
@@ -345,7 +345,8 @@ ANN static Type check_prim_id(const Env env, const Symbol *data) {
   return prim_id_non_res(env, data);
 }
 
-ANN static Type check_prim_perform(const Env env, const Symbol *data NUSED) {
+ANN static Type check_prim_perform(const Env env, const Symbol *data) {
+  env_add_effect(env, *data, prim_pos(data));
   return env->gwion->type[et_void];
 }
 
@@ -741,6 +742,13 @@ ANN m_bool func_check(const Env env, Exp_Call *const exp) {
     GW_OK : GW_ERROR;
 }
 
+ANN void call_add_effect(const Env env, const Func func, const loc_t pos) {
+  if(func != env->func && func->def->base->effects.ptr) {
+    const Vector v = &func->def->base->effects;
+    for(m_uint i = 0; i < vector_size(v); i++)
+      env_add_effect(env, (Symbol)vector_at(v, i), pos);
+  }
+}
 ANN Type check_exp_call1(const Env env, Exp_Call *const exp) {
   DECL_BO(const m_bool, ret, = func_check(env, exp))
   if(!ret)
@@ -754,7 +762,7 @@ ANN Type check_exp_call1(const Env env, Exp_Call *const exp) {
   }
   if(t == env->gwion->type[et_op])
     return check_op_call(env, exp);
-  if(t == env->gwion->type[et_lambda])
+  if(t == env->gwion->type[et_lambda])   // TODO: effects?
     return check_lambda_call(env, exp);
   if(fflag(t->info->func, fflag_ftmpl)) {
     const Value value = t->info->func->value_ref;
@@ -764,10 +772,21 @@ ANN Type check_exp_call1(const Env env, Exp_Call *const exp) {
   if(exp->args)
     CHECK_OO(check_exp(env, exp->args))
   if(tflag(t, tflag_ftmpl))
-    return check_exp_call_template(env, (Exp_Call*)exp);
+    return check_exp_call_template(env, (Exp_Call*)exp); // TODO: effects?
   const Func func = find_func_match(env, t->info->func, exp);
   if(func) {
+    if(!is_fptr(env->gwion, func->value_ref->type))// skip function pointers
+    if(func != env->func && func->def && !fflag(func, fflag_valid)) {
+//  if(!fflag(func, fflag_valid)) {
+      struct EnvSet es = { .env=env, .data=env, .func=(_exp_func)check_cdef,
+        .scope=env->scope->depth, .flag=tflag_check };
+      CHECK_BO(envset_push(&es, func->value_ref->from->owner_class, func->value_ref->from->owner))
+      CHECK_BO(check_func_def(env, func->def))
+      if(es.run)
+        envset_pop(&es, func->value_ref->from->owner_class);
+    }
     exp->func->type = func->value_ref->type;
+    call_add_effect(env, func, exp->func->pos);
     return func->def->base->ret_type;
   }
   const loc_t pos = exp->args ? exp->args->pos : exp->func->pos;
@@ -1226,10 +1245,41 @@ ANN static inline m_bool check_handler_list(const restrict Env env, const Handle
   RET_NSPC(check_stmt(env, handler->stmt))
 }
 
-ANN static inline m_bool check_stmt_try(const restrict Env env, const Stmt_Try stmt) {
-  CHECK_BB(check_handler_list(env, stmt->handler))
+ANN static inline m_bool check_stmt_try_start(const restrict Env env, const Stmt_Try stmt) {
   RET_NSPC(check_stmt(env, stmt->stmt))
 }
+ANN static inline m_bool _check_stmt_try(const restrict Env env, const Stmt_Try stmt) {
+  CHECK_BB(check_handler_list(env, stmt->handler))
+  vector_add(&env->scope->effects, 0);
+  const m_bool ret = check_stmt_try_start(env, stmt);
+  const m_uint _v = vector_pop(&env->scope->effects);
+  if(_v) {
+    const M_Vector v = (M_Vector)&_v;
+    for(m_uint i = 0; i < m_vector_size(v); i++) {
+      struct ScopeEffect eff;
+      m_vector_get(v, i, &eff);
+      Handler_List handler = stmt->handler;
+      bool found = false;
+      do { // check there is no duplicate handler
+        if(eff.sym == handler->xid) {
+          found = true;
+          break;
+        }
+      } while((handler = handler->next));
+      if(!found)
+        env_add_effect(env, eff.sym, eff.pos);
+    }
+    m_vector_release(v);
+  }
+  return ret;
+}
+
+ANN static inline m_bool check_stmt_try(const restrict Env env, const Stmt_Try stmt) {
+  const bool in_try = env->scope->in_try;
+  const m_bool ret = _check_stmt_try(env, stmt);
+  env->scope->in_try = in_try;
+  return ret;
+}
 
 ANN static m_bool _check_stmt_match(const Env env, const Stmt_Match stmt) {
   CHECK_OB(check_exp(env, stmt->cond))
@@ -1347,15 +1397,29 @@ ANN static m_bool check_func_overload(const Env env, const Func_Def fdef) {
   return GW_OK;
 }
 
-ANN static m_bool check_func_def_override(const Env env, const Func_Def fdef) {
+ANN bool check_effect_overload(const Func_Base *base, const Value override) {
+  if(!base->effects.ptr)
+    return true;
+  if(!override->d.func_ref->def->base->effects.ptr)
+    return false; // TODO: error message
+  const Vector v = &override->d.func_ref->def->base->effects;
+  for(m_uint i = 0; i < vector_size(v); i++) {
+    if(vector_find((Vector)&base->effects, vector_at(v, i)) == -1)
+      return false;
+  }
+  return true;
+}
+
+ANN static m_bool check_func_def_override(const Env env, const Func_Def fdef, Value *ov) {
   const Func func = fdef->base->func;
   if(env->class_def && env->class_def->info->parent) {
     const Value override = find_value(env->class_def->info->parent, fdef->base->xid);
     if(override && override->from->owner_class && isa(override->type, env->gwion->type[et_function]) < 0)
-      ERR_B(fdef->base->pos,
+        ERR_B(fdef->base->pos,
             _("function name '%s' conflicts with previously defined value...\n"
             "  from super class '%s'..."),
             s_name(fdef->base->xid), override->from->owner_class->name)
+    *ov = override;
   }
   if(func->value_ref->from->offset && (!fdef->base->tmpl || !fdef->base->tmpl->base))
     CHECK_BB(check_func_overload(env, fdef))
@@ -1384,7 +1448,8 @@ ANN m_bool check_func_def(const Env env, const Func_Def f) {
     CHECK_BB(check_parent_match(env, fdef))
   if(tmpl_base(fdef->base->tmpl))
     return GW_OK;
-  CHECK_BB(check_func_def_override(env, fdef))
+  Value override = NULL;
+  CHECK_BB(check_func_def_override(env, fdef, &override))
   DECL_BB(const m_int, scope, = GET_FLAG(fdef->base, global) ? env_push_global(env) : env->scope->depth)
   const Func former = env->func;
   env->func = func;
@@ -1395,14 +1460,33 @@ ANN m_bool check_func_def(const Env env, const Func_Def f) {
     func_operator(f, &opi);
     operator_suspend(env->curr, &opi);
   }
+  vector_add(&env->scope->effects, 0);
   const m_bool ret = scanx_fdef(env, env, fdef, (_exp_func)check_fdef);
+  const m_uint _v = vector_pop(&env->scope->effects);
+  if(_v) {
+    const Vector v = (Vector)&_v;
+    const Vector base = &fdef->base->effects;
+    if(!base->ptr)
+      vector_init(base);
+    for(m_uint i = 0; i < vector_size(v); i += 2) {
+      const Symbol effect = (Symbol)vector_at(v, i);
+      if(vector_find(base, (m_uint)effect) == -1)
+        vector_add(base, (m_uint)effect);
+    }
+    vector_release(v);
+  }
   if(fbflag(fdef->base, fbflag_op))
     operator_resume(&opi);
   nspc_pop_value(env->gwion->mp, env->curr);
   --env->scope->depth;
   env->func = former;
-  if(ret > 0)
+  if(ret > 0) {
     set_fflag(fdef->base->func, fflag_valid);
+    if(env->class_def && !check_effect_overload(fdef->base, override))
+      ERR_B(fdef->base->pos,
+          _("too much effects in override."),
+          s_name(fdef->base->xid))
+  }
   if(GET_FLAG(fdef->base, global))
     env_pop(env,scope);
   return ret;
@@ -1464,6 +1548,44 @@ ANN m_bool check_abstract(const Env env, const Class_Def cdef) {
   return !err ? GW_OK : GW_ERROR;
 }
 
+ANN static inline void check_unhandled(const Env env) {
+  const Vector v = &env->scope->effects;
+  const m_uint _w = vector_back(v);
+  if(!_w)
+    return;
+  const M_Vector w = (M_Vector)&_w;
+  for(m_uint j = 0; j < m_vector_size(w); j++) {
+    struct ScopeEffect eff;
+    m_vector_get(w, j, &eff);
+    gwerr_secondary("Unhandled effect", env->name, eff.pos);
+    env->context->error = false;
+  }
+  m_vector_release(w);
+  vector_pop(v);
+}
+
+
+ANN static m_bool check_body(const Env env, Section *const section) {
+  const m_bool ret = check_section(env, section);
+  check_unhandled(env);
+  return ret;
+}
+
+ANN static m_bool _check_class_def(const Env env, const Class_Def cdef) {
+  const Type t = cdef->base.type;
+  if(cdef->base.ext)
+    CHECK_BB(cdef_parent(env, cdef))
+  if(!tflag(t, tflag_struct))
+    inherit(t);
+  if(cdef->body) {
+    CHECK_BB(env_body(env, cdef, check_body))
+    set_tflag(t, tflag_ctor);
+  }
+  if(!GET_FLAG(cdef, abstract))
+    CHECK_BB(check_abstract(env, cdef))
+  return GW_OK;
+}
+
 ANN m_bool check_class_def(const Env env, const Class_Def cdef) {
   if(tmpl_base(cdef->base.tmpl))
     return GW_OK;
@@ -1476,21 +1598,12 @@ ANN m_bool check_class_def(const Env env, const Class_Def cdef) {
   if(tflag(t, tflag_check))
     return GW_OK;
   set_tflag(t, tflag_check);
-  if(cdef->base.ext)
-    CHECK_BB(cdef_parent(env, cdef))
-  if(!tflag(t, tflag_struct))
-    inherit(t);
-  if(cdef->body) {
-    CHECK_BB(env_body(env, cdef, check_section))
-    set_tflag(t, tflag_ctor);
-  }
-  if(!GET_FLAG(cdef, abstract))
-    CHECK_BB(check_abstract(env, cdef))
-  return GW_OK;
+  return _check_class_def(env, cdef);
 }
 
 ANN m_bool check_ast(const Env env, Ast ast) {
   do CHECK_BB(check_section(env, ast->section))
   while((ast = ast->next));
+  check_unhandled(env);
   return GW_OK;
 }
index 2b3eb49b9726b3e59f728e3aba456786161bfb22..f81d223eff5a8e0b81d9a6f705395df7f2b4fcd6 100644 (file)
@@ -54,8 +54,10 @@ ANN static Func ensure_tmpl(const Env env, const Func_Def fdef, Exp_Call *const
   const Func func = find_func_match(env, f, exp);
   nspc_pop_type(env->gwion->mp, env->curr);
   f->next = next;
-  if(func)
+  if(func) {
     set_fflag(func, fflag_tmpl | fflag_valid);
+    call_add_effect(env, func, exp->func->pos);
+  }
   return func;
 }
 
index 28b89484f1f84d4fd019691566ccb6ed0caff453..0c145e1213d9f8246bac4575f5927c58f9fcdd1a 100644 (file)
@@ -100,6 +100,7 @@ struct OpChecker {
   const Env env;
   const Map map;
   const struct Op_Import* opi;
+  struct Vector_ effect;
 };
 
 __attribute__((returns_nonnull))
@@ -128,12 +129,12 @@ ANN static m_bool op_exist(const struct OpChecker* ock, const Nspc n) {
 ANN m_bool add_op(const Gwion gwion, const struct Op_Import* opi) {
   Nspc n = gwion->env->curr;
   do {
-    struct OpChecker ock = { gwion->env, &n->info->op_map, opi };
+    struct OpChecker ock = { .env=gwion->env, .map=&n->info->op_map, .opi=opi };
     CHECK_BB(op_exist(&ock, n))
   } while((n = n->parent));
   if(!gwion->env->curr->info->op_map.ptr)
     map_init(&gwion->env->curr->info->op_map);
-  struct OpChecker ock = { gwion->env, &gwion->env->curr->info->op_map, opi };
+  struct OpChecker ock = { .env=gwion->env, .map=&gwion->env->curr->info->op_map, .opi=opi };
   const Vector v = op_vector(gwion->mp, &ock);
   const M_Operator* mo = new_mo(gwion->mp, opi);
   vector_add(v, (vtype)mo);
@@ -153,9 +154,10 @@ ANN static Type op_check_inner(struct OpChecker* ock, const uint i) {
     const M_Operator* mo;
     const Vector v = (Vector)map_get(ock->map, (vtype)ock->opi->op);
     if(v && (mo = !i ? operator_find2(v, ock->opi->lhs, r) : operator_find(v, ock->opi->lhs, r))) {
-      if((mo->ck && (t = mo->ck(ock->env, (void*)ock->opi->data))))
+      if((mo->ck && (t = mo->ck(ock->env, (void*)ock->opi->data)))) {
+        ock->effect.ptr = mo->effect.ptr;
         return t;
-      else
+      else
         return mo->ret;
     }
   } while(r && (r = r->info->parent));
@@ -171,11 +173,16 @@ for(int i = 0; i < 2; ++i) {
     Type l = opi->lhs;
     do {
       struct Op_Import opi2 = { .op=opi->op, .lhs=l, .rhs=opi->rhs, .data=opi->data };
-      struct OpChecker ock = { env, &nspc->info->op_map, &opi2 };
+      struct OpChecker ock = { .env=env, .map=&nspc->info->op_map, .opi=&opi2 };
       const Type ret = op_check_inner(&ock, i);
       if(ret) {
         if(ret == env->gwion->type[et_error])
           return NULL;
+        if(ock.effect.ptr) {
+          const Vector base = &ock.effect;
+          for(m_uint i = 0; i < vector_size(base); i++)
+            env_add_effect(env, (Symbol)vector_at(base, i), opi->pos);
+        }
         opi->nspc = nspc;
         return ret;
       }
index 2f5ef8a1b466ab7d12841ec8a58acbc6aad60bec..827b8715a847dbf2b0db9cbe3d1ef3064f1cd0d0 100644 (file)
@@ -41,11 +41,19 @@ scanx_body(const Env e, const Class_Def c, const _exp_func f, void* d) {
   return ret;
 }
 
-ANN m_bool scanx_cdef(const Env env, void* opt, const Type t,
-    const _exp_func f_cdef, const _exp_func f_union) {
+ANN static m_bool _scanx_cdef(const Env env, void* opt, const Type t,
+    const _exp_func f_cdef, const _exp_func f_udef) {
   if(t->info->parent !=  env->gwion->type[et_union])
      return f_cdef(opt, t->info->cdef);
-  const m_bool ret = f_union(opt, t->info->udef);
+  const m_bool ret = f_udef(opt, t->info->udef);
+  return ret;
+}
+
+ANN m_bool scanx_cdef(const Env env, void* opt, const Type t,
+    const _exp_func f_cdef, const _exp_func f_udef) {
+  const bool in_try = env->scope->in_try;
+  const m_bool ret = _scanx_cdef(env, opt, t, f_cdef, f_udef);
+  env->scope->in_try = in_try;
   return ret;
 }
 
@@ -53,8 +61,10 @@ ANN m_bool scanx_fdef(const Env env, void *data,
     const Func_Def fdef, const _exp_func func) {
   if(fdef->base->tmpl)
     CHECK_BB(template_push_types(env, fdef->base->tmpl))
+  const bool in_try = env->scope->in_try;
   const m_bool ret = func(data, fdef);
   if(fdef->base->tmpl)
     nspc_pop_type(env->gwion->mp, env->curr);
+  env->scope->in_try = in_try;
   return ret;
 }
index b83b1f365ae5c738f0eee893bbc1d619e892b257..5692ccd11317cfa371feda191abf65f926e01c48 100644 (file)
@@ -41,7 +41,7 @@ uint32_t gw_rand(uint32_t s[2]) {
 }
 
 ANN static bool unwind(VM_Shred shred, const Symbol effect) {
-  if(!shred->info->frame.ptr || !map_size(&shred->info->frame))
+  if(!shred->info->frame.ptr || !vector_size(&shred->info->frame))
     return true;
   if(shred->code->handlers.ptr) {
     const m_uint start = VKEY(&shred->info->frame, VLEN(&shred->info->frame) - 1);
@@ -63,13 +63,14 @@ ANN static bool unwind(VM_Shred shred, const Symbol effect) {
     }
     if(!pc) // outside of a try statement
       return true;
-    shred->reg = (m_bit*)VVAL(&shred->info->frame, VLEN(&shred->info->frame) - 1);
+    shred->reg = (m_bit*)VPTR(&shred->info->frame, VLEN(&shred->info->frame) - 1);
     shredule(shred->tick->shreduler, shred, 0);
     shred->pc = pc;//VKEY(m, i);
     return false;
   }
   // there might be no more stack to unwind
-  map_remove(&shred->info->frame, VLEN(&shred->info->frame)-1);
+  vector_pop(&shred->info->frame);
+  vector_pop(&shred->info->frame);
   if(shred->mem == (m_bit*)shred + sizeof(struct VM_Shred_) + SIZEOF_REG)
     return true;
   // literally unwind
@@ -1007,11 +1008,13 @@ gack:
   goto in;
 try_ini:
   if(!shred->info->frame.ptr) // ???
-    map_init(&shred->info->frame);
-  map_set(&shred->info->frame, PC, (m_uint)shred->reg);
+    vector_init(&shred->info->frame);
+  vector_add(&shred->info->frame, PC);
+  vector_add(&shred->info->frame, (m_uint)reg);
   DISPATCH();
 try_end:
-  map_remove(&shred->info->frame, VLEN(&shred->info->frame)-1);
+  vector_pop(&shred->info->frame);
+  vector_pop(&shred->info->frame);
 handleeffect:
 // this should check the *xid* of the exception
   DISPATCH();
index 8695a2a482965c0c78320abfe89cb91e9b4b2f54..737f8b783902f3cb5687ac1fac16e050f6105eff 100644 (file)
@@ -46,7 +46,7 @@ void free_vm_shred(VM_Shred shred) {
     release((M_Object)vector_at(&shred->gc, i - 1), shred);
   vector_release(&shred->gc);
   if(shred->info->frame.ptr)
-    map_release(&shred->info->frame);
+    vector_release(&shred->info->frame);
   vmcode_remref(shred->info->orig, shred->info->vm->gwion);
   const MemPool mp = shred->info->mp;
   mp_free(mp, ShredTick, shred->tick);
diff --git a/util b/util
index 7d52314d4e12c36a0b538a2cb0c1ad94086008c5..fae43107367388fda4c9755dfdd7abfa427de5b8 160000 (submodule)
--- a/util
+++ b/util
@@ -1 +1 @@
-Subproject commit 7d52314d4e12c36a0b538a2cb0c1ad94086008c5
+Subproject commit fae43107367388fda4c9755dfdd7abfa427de5b8