]> Nishi Git Mirror - gwion.git/commitdiff
:art: More on effects
authorJérémie Astor <fennecdjay@gmail.com>
Thu, 29 Apr 2021 15:29:48 +0000 (17:29 +0200)
committerJérémie Astor <fennecdjay@gmail.com>
Thu, 29 Apr 2021 15:29:48 +0000 (17:29 +0200)
include/env/env.h
include/env/type.h
src/lib/lib_func.c
src/lib/ref.c
src/parse/check.c
src/parse/scan1.c

index 4425fabb7dd03fddf870dc95a1af516d97707b9b..8ff18c1209da67e7427b84a7e9f2f18abec778e5 100644 (file)
@@ -56,4 +56,5 @@ struct ScopeEffect {
 
 ANN void env_add_effect(const Env a, const Symbol effect, const loc_t pos);
 ANN void call_add_effect(const Env env, const Func func, const loc_t pos);
+ANN bool check_effect_overload(const Vector base, const Func override);
 #endif
index 6cc503f1f6204ba0f80eda7f74cb545c497fd685..70e9a5fa33d9a3304776527e57775c5c715e26ea 100644 (file)
@@ -15,24 +15,25 @@ struct TypeInfo_ {
 };
 
 enum tflag {
-  tflag_none    = 1 << 0,
-  tflag_scan0   = 1 << 1,//
-  tflag_scan1   = 1 << 2,//
-  tflag_scan2   = 1 << 3,//
-  tflag_check   = 1 << 4,//
-  tflag_emit    = 1 << 5,//
-  tflag_infer   = 1 << 6,
-  tflag_empty   = 1 << 7,
-  tflag_ftmpl   = 1 << 8,
-  tflag_ntmpl   = 1 << 9, // do NOT need types
-  tflag_udef    = 1 << 10,
-  tflag_cdef    = 1 << 11,
-  tflag_struct  = 1 << 12,
-  tflag_ctor    = 1 << 13,
-  tflag_dtor    = 1 << 14,
-  tflag_tmpl    = 1 << 15,
-  tflag_typedef = 1 << 16,
+  tflag_none     = 1 << 0,
+  tflag_scan0    = 1 << 1,//
+  tflag_scan1    = 1 << 2,//
+  tflag_scan2    = 1 << 3,//
+  tflag_check    = 1 << 4,//
+  tflag_emit     = 1 << 5,//
+  tflag_infer    = 1 << 6,
+  tflag_empty    = 1 << 7,
+  tflag_ftmpl    = 1 << 8,
+  tflag_ntmpl    = 1 << 9, // do NOT need types
+  tflag_udef     = 1 << 10,
+  tflag_cdef     = 1 << 11,
+  tflag_struct   = 1 << 12,
+  tflag_ctor     = 1 << 13,
+  tflag_dtor     = 1 << 14,
+  tflag_tmpl     = 1 << 15,
+  tflag_typedef  = 1 << 16,
   tflag_distinct = 1 << 17,
+  tflag_noret    = 1 << 17,
 } __attribute__((packed));
 
 struct Type_ {
@@ -41,6 +42,7 @@ struct Type_ {
   struct TypeInfo_ *info;
   size_t size;
   size_t array_depth;
+  struct Vector_ effects; // pre-ctor effects
   uint16_t ref;
   ae_flag flag;
   enum tflag tflag;
index 244b8b30257f6800802e4afeebfa9bdab67cda3f..8fb80a5c05128bbaf0eb8355aaab6fc32377406e 100644 (file)
@@ -427,9 +427,12 @@ static OP_CHECK(opck_op_impl){
   self.d.exp_binary.op = impl->e->d.prim.d.var;
   struct Op_Import opi = { .op=impl->e->d.prim.d.var, .lhs=func->def->base->args->type,
     .rhs=func->def->base->args->next->type, .data=(uintptr_t)&self.d.exp_binary, .pos=impl->e->pos };
+  vector_add(&env->scope->effects, 0);
   DECL_ON(const Type, t, = op_check(env, &opi));
-  CHECK_BN(isa(t, func->def->base->ret_type));
-  // Find if the function exists
+  CHECK_BN(isa(t, func->def->base->ret_type)); // error message?
+  const m_uint _eff = vector_back(&env->scope->effects);
+  if(!check_effect_overload((Vector)&_eff, func))
+    ERR_N(impl->pos, _("`{+Y}%s{0}` has effects not present in `{+G}%s{0}`\n"), s_name(impl->e->d.prim.d.var), func->name);
   Value v = nspc_lookup_value0(opi.nspc, impl->e->d.prim.d.var);
   if(v) {
       const m_uint scope = env_push(env, NULL, opi.nspc);
@@ -437,8 +440,14 @@ static OP_CHECK(opck_op_impl){
       Exp_Call call = { .args=&_lhs };
       const Func exists = (Func)find_func_match(env, v->d.func_ref, &call);
       env_pop(env, scope);
-      if(exists)
+      if(exists) { // improve me
+        if(_eff) {
+          const M_Vector eff = (M_Vector)&_eff;
+          m_vector_release(eff);
+          ERR_N(impl->pos, _("`{+Y}%s{0}` has effects not present in `{+G}%s{0}`\n"), s_name(impl->e->d.prim.d.var), func->name);
+        }
         return actual_type(env->gwion, func->value_ref->type);
+      }
   }
   const Arg_List args = cpy_arg_list(env->gwion->mp, func->def->base->args);
   // beware shadowing ?
@@ -446,6 +455,15 @@ static OP_CHECK(opck_op_impl){
   args->next->var_decl->xid = rhs_sym;
   Func_Base *base = new_func_base(env->gwion->mp, type2td(env->gwion, t, impl->e->pos),
        impl->e->d.prim.d.var, args, ae_flag_none, impl->e->pos);
+  if(_eff) {
+    const M_Vector eff = (M_Vector)&_eff;
+    for (m_uint i = 0; i < m_vector_size(eff); i++) {
+      struct ScopeEffect effect;
+      m_vector_get(eff, i, &effect);
+      vector_add(&base->effects, (m_uint)effect.sym);
+    }
+    m_vector_release(eff);
+  }
   const Exp lhs = new_prim_id(env->gwion->mp, args->var_decl->xid, impl->e->pos);
   const Exp rhs = new_prim_id(env->gwion->mp, args->next->var_decl->xid, impl->e->pos);
   const Exp bin = new_exp_binary(env->gwion->mp, lhs, impl->e->d.prim.d.var, rhs, impl->e->pos);
index eabcb74ddea9301af034bc82848b16b1871e62c2..e938b231ad5e3588cc25d502020d5de544a538e7 100644 (file)
@@ -63,6 +63,7 @@ static OP_CHECK(opck_ref_scan) {
   const Type t = new_type(env->gwion->mp, s_name(info.name), base);
   SET_FLAG(t, abstract | ae_flag_final);
   set_tflag(t, tflag_infer);
+  set_tflag(t, tflag_noret);
   const m_uint scope = env_push(env, base->info->value->from->owner_class, base->info->value->from->owner);
   mk_class(env, t, (loc_t){});
   base2ref(env, base, t);
index f141fe9863a547c90fbe5281d19f92be980bbac9..e2fc0ce56d5609f346ab3925dffcf545f530b964 100644 (file)
@@ -87,6 +87,11 @@ ANN static m_bool check_fptr_decl(const Env env, const Var_Decl var) {
 ANN static m_bool check_var(const Env env, const Var_Decl var) {
   if(env->class_def && !env->scope->depth && env->class_def->info->parent)
     CHECK_BB(check_exp_decl_parent(env, var));
+  if(var->value->type->effects.ptr) {
+    const Vector v = &var->value->type->effects;
+    for(m_uint i = 0; i < vector_size(v); i++)
+      env_add_effect(env, (Symbol)vector_at(v, i), var->pos);
+  }
   if(var->array && var->array->exp)
     return check_subscripts(env, var->array, 1);
   return GW_OK;
@@ -749,6 +754,7 @@ ANN void call_add_effect(const Env env, const Func func, const loc_t pos) {
       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)
@@ -1128,6 +1134,8 @@ ANN static m_bool check_stmt_return(const Env env, const Stmt_Exp stmt) {
   }
   if(isa(ret_type, env->func->def->base->ret_type) > 0)
     return GW_OK;
+  if(tflag(ret_type, tflag_noret))
+    ERR_B(stmt->val->pos, _("Can't use type `{+G}%s{+G}` for return"));
   if(stmt->val) {
     if(env->func->def->base->xid == insert_symbol("@implicit") && ret_type == env->func->def->base->args->type)
       ERR_B(stmt_self(stmt)->pos, _("can't use implicit casting while defining it"))
@@ -1397,14 +1405,14 @@ ANN static m_bool check_func_overload(const Env env, const Func_Def fdef) {
   return GW_OK;
 }
 
-ANN bool check_effect_overload(const Func_Base *base, const Value override) {
-  if(!base->effects.ptr)
+ANN bool check_effect_overload(const Vector base, const Func override) {
+  if(!base->ptr)
     return true;
-  if(!override->d.func_ref->def->base->effects.ptr)
+  if(!override->def->base->effects.ptr)
     return false; // TODO: error message
-  const Vector v = &override->d.func_ref->def->base->effects;
+  const Vector v = &override->def->base->effects;
   for(m_uint i = 0; i < vector_size(v); i++) {
-    if(vector_find((Vector)&base->effects, vector_at(v, i)) == -1)
+    if(vector_find((Vector)base, vector_at(v, i)) == -1)
       return false;
   }
   return true;
@@ -1462,8 +1470,10 @@ ANN m_bool check_func_def(const Env env, const Func_Def f) {
   }
   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);
+  const m_uint _v = vector_back(&env->scope->effects);
   if(_v) {
+    if(fdef->base->xid == insert_symbol("@dtor"))
+      ERR_B(fdef->base->pos, _("can't use effects in destructors"));
     const Vector v = (Vector)&_v;
     const Vector base = &fdef->base->effects;
     if(!base->ptr)
@@ -1475,6 +1485,7 @@ ANN m_bool check_func_def(const Env env, const Func_Def f) {
     }
     vector_release(v);
   }
+  vector_pop(&env->scope->effects);
   if(fbflag(fdef->base, fbflag_op))
     operator_resume(&opi);
   nspc_pop_value(env->gwion->mp, env->curr);
@@ -1482,7 +1493,7 @@ ANN m_bool check_func_def(const Env env, const Func_Def f) {
   env->func = former;
   if(ret > 0) {
     set_fflag(fdef->base->func, fflag_valid);
-    if(env->class_def && !check_effect_overload(fdef->base, override))
+    if(env->class_def && !check_effect_overload(&fdef->base->effects, override->d.func_ref))
       ERR_B(fdef->base->pos,
           _("too much effects in override."),
           s_name(fdef->base->xid))
@@ -1548,26 +1559,25 @@ 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) {
+ANN static inline void ctor_effects(const Env env) {
   const Vector v = &env->scope->effects;
   const m_uint _w = vector_back(v);
   if(!_w)
     return;
+  vector_init(&env->class_def->effects);
   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;
+    vector_add(&env->class_def->effects, (m_uint)eff.sym);
   }
   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);
+  ctor_effects(env);
   return ret;
 }
 
@@ -1601,6 +1611,22 @@ ANN m_bool check_class_def(const Env env, const Class_Def cdef) {
   return _check_class_def(env, cdef);
 }
 
+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 m_bool check_ast(const Env env, Ast ast) {
   do CHECK_BB(check_section(env, ast->section));
   while((ast = ast->next));
index 3eda95478962b422678df189dd3de44ab3b47e51..6d7d971f0e64805b0d31ccfee85a288d5693d249 100644 (file)
@@ -383,6 +383,9 @@ ANN static m_bool _scan1_fdef_base_tmpl(const Env env, Func_Base *base) {
   do nspc_add_type(env->curr, id->xid, env->gwion->type[et_auto]);
   while((id = id->next));
   CHECK_OB((base->ret_type = known_type(env, base->td)));
+  if(tflag(base->ret_type, tflag_noret))
+        ERR_B(base->pos, _("Can't use type `{+G}%s{0}` for return"),
+             base->ret_type->name);
   if(base->args) {
     Arg_List arg = base->args;
     do CHECK_OB(known_type(env, arg->td));
@@ -407,6 +410,9 @@ ANN m_bool scan1_fptr_def(const Env env, const Fptr_Def fptr) {
   }
   const Func_Def fdef = fptr->base->func->def;
   CHECK_OB((fdef->base->ret_type = scan1_type(env, fdef->base->td)));
+  if(tflag(fdef->base->ret_type, tflag_noret))
+       ERR_B(fdef->base->pos, _("Can't use type `{+G}%s{0}` for return"),
+             fdef->base->ret_type->name);
   if(!fdef->base->args)
     return GW_OK;
   RET_NSPC(scan1_args(env, fdef->base->args))
@@ -566,8 +572,12 @@ ANN m_bool scan1_fbody(const Env env, const Func_Def fdef) {
 }
 
 ANN m_bool scan1_fdef(const Env env, const Func_Def fdef) {
-  if(fdef->base->td)
+  if(fdef->base->td) {
     CHECK_OB((fdef->base->ret_type = known_type(env, fdef->base->td)));
+    if(tflag(fdef->base->ret_type, tflag_noret))
+         ERR_B(fdef->base->pos, _("Can't use type `{+G}%s{0}` for return"),
+             fdef->base->ret_type->name);
+  }
   if(fbflag(fdef->base, fbflag_internal))
     CHECK_BB(scan_internal(env, fdef->base));
   else if(fbflag(fdef->base, fbflag_op) && env->class_def)