]> Nishi Git Mirror - gwion.git/commitdiff
:bug: AFL ... again
authorfennecdjay <astor.jeremie@wanadoo.fr>
Tue, 10 Sep 2019 12:15:39 +0000 (14:15 +0200)
committerfennecdjay <astor.jeremie@wanadoo.fr>
Tue, 10 Sep 2019 12:16:02 +0000 (14:16 +0200)
14 files changed:
include/type.h
src/emit/emit.c
src/lib/gack.c
src/lib/instr.c
src/lib/object.c
src/lib/string.c
src/lib/vararg.c
src/oo/type.c
src/parse/check.c
src/parse/scan0.c
src/parse/scan2.c
src/parse/type_decl.c
src/vm/vm.c
src/vm/vm_code.c

index 4880184dc3c4be372efe4a3a0b1e04ffc22af64e..e55834ac29e1ae26fff267c3d5dde778378739b2 100644 (file)
@@ -26,7 +26,7 @@ struct Type_ {
 
 extern Type t_void, t_int, t_bool, t_float, t_dur, t_time, t_now, t_complex, t_polar, t_vec3, t_vec4,
   t_null, t_object, t_shred, t_fork, t_event, t_ugen, t_string, t_ptr, t_array, t_gack,
-  t_function, t_fptr, t_vararg, t_lambda, t_class, t_union, t_undefined, t_auto, t_tuple;
+  t_function, t_fptr, t_varloop, t_vararg, t_lambda, t_class, t_union, t_undefined, t_auto, t_tuple;
 
 ANN2(1,3) ANEW Type new_type(MemPool, const m_uint xid, const m_str name, const Type);
 ANEW ANN Type type_copy(MemPool, const Type type);
index e68bda2d55c0b0149907d71ce0c677de3ad70990..eb0de8e0026902d80bd8e5fae3944e4f446b5b52 100644 (file)
@@ -235,7 +235,7 @@ ANN m_bool emit_array_extend(const Emitter emit, const Type t, const Exp e) {
 }
 
 ANN static inline void emit_notpure(const Emitter emit) {
-  ++VPTR(&emit->pure, VLEN(&emit->pure));
+  ++VPTR(&emit->pure, VLEN(&emit->pure) - 1);
 }
 
 ANN static Array_Sub instantiate_typedef(MemPool p, const m_uint depth) {
@@ -577,6 +577,7 @@ ANN static m_bool prim_str(const Emitter emit, const Exp_Primary* prim) {
 
 ANN static m_bool prim_gack(const Emitter emit, const Exp_Primary* primary) {
   const Exp exp = primary->d.exp;
+  CHECK_BB(emit_exp(emit, exp, 0))
   const Vector v = new_vector(emit->gwion->mp);
   m_uint offset = 0;
   Exp e = exp;
@@ -584,10 +585,6 @@ ANN static m_bool prim_gack(const Emitter emit, const Exp_Primary* primary) {
     vector_add(v, (vtype)e->type);
     offset += e->type->size;
   } while((e = e->next));
-  if(emit_exp(emit, exp, 0) < 0) {
-    free_vector(emit->gwion->mp, v);
-    ERR_B(exp->pos, _("  ... in 'gack' expression."))
-  }
   const Instr instr = emit_add_instr(emit, Gack);
   instr->m_val = offset;
   instr->m_val2 = (m_uint)v;
@@ -972,15 +969,15 @@ ANN m_bool emit_exp_call1(const Emitter emit, const Func f) {
         back->opcode = ePushStaticCode;
         back->m_val = 0;
       }
-    }else if(emit->env->func != f && !f->value_ref->owner_class && !f->code && !is_fptr(f->value_ref->type)) {
-      const Instr back = emit_add_instr(emit, PushStaticCode);
+    } else if(emit->env->func != f && !f->value_ref->owner_class && !f->code && !is_fptr(f->value_ref->type)) {
+      const Instr back = !GET_FLAG(f->def, op) ? emit_add_instr(emit, PushStaticCode) : (Instr)vector_back(&emit->code->instr);
       back->m_val = (m_uint)f;
     }
   } else if((f->value_ref->owner_class && is_special(f->value_ref->owner_class) > 0) ||
         !f->value_ref->owner_class || (GET_FLAG(f, template) &&
         isa(f->value_ref->type, t_fptr) < 0))
     push_func_code(emit, f);
-  else if(vector_size(&emit->code->instr)){
+  else if(vector_size(&emit->code->instr)) {
     const Instr back = (Instr)vector_back(&emit->code->instr);
     if((f_instr)(m_uint)back->opcode == DotFunc || (f_instr)(m_uint)back->opcode == DotStaticFunc)
       back->m_val = f->vt_index;
index 2bf97e841f2e6abf795be13653a875cd85b49d83..3749a3db3dc9fcebd85c29e6112d857d40448e1a 100644 (file)
@@ -79,9 +79,12 @@ ANN static inline void print_func(const Type type, const m_bit* stack) {
     gw_out("%s", f ? f->name : "(nil)");
     return;
   }
-  const VM_Code code = isa(type, t_fptr) > 0 ?
-    *(VM_Code*)stack : type->e->d.func->code;
-  gw_out("%s %s %p", type->name, (void*)code ? code->name : NULL, code);
+  if(type->e->d.func) {
+    const VM_Code code = isa(type, t_fptr) > 0 ?
+        *(VM_Code*)stack : type->e->d.func->code;
+    gw_out("%s %s %p", type->name, (void*)code ? code->name : NULL, code);
+  } else // uncalled lambda
+    gw_out("%p", NULL);
 }
 
 ANN static void print_prim(const Type type, const m_bit* stack) {
index 311d884ab904e02032e620e5e8d983d2dedfec30..634a78685c1ea062fbda0cd6df31beeec5a17beb 100644 (file)
@@ -100,7 +100,7 @@ INSTR(DotTmpl) {
   struct dottmpl_ *dt = (struct dottmpl_*)instr->m_val;
   const m_str name = dt->name;
   const M_Object o = *(M_Object*)REG(-SZ_INT);
-  Type t = o->type_ref;
+  Type t = !GET_FLAG(o->type_ref, nonnull) ? o->type_ref : o->type_ref->e->parent;
   do {
     const Emitter emit = shred->info->vm->gwion->emit;
     emit->env->name = "runtime";
@@ -109,6 +109,8 @@ INSTR(DotTmpl) {
     strcpy(str + instr->m_val2, t->name);
     const Func f = nspc_lookup_func0(t->nspc, insert_symbol(emit->env->gwion->st, str));
     if(f) {
+      if(!f->code)
+        break;
       *(VM_Code*)shred->reg = f->code;
       shred->reg += SZ_INT;
       return;
index e0f103e2a514e5590bf0f0535f1a71be9f0a947e..48c09e405105b6ae04a43aaf6fc78d0fa1d3f0c4 100644 (file)
@@ -109,6 +109,8 @@ static inline Type check_nonnull(const Env env, const Type l, const Type r,
   if(GET_FLAG(r, nonnull)) {
     if(isa(l, t_null) > 0)
       ERR_N(pos, _("can't %s '%s' to '%s'"), action, l->name, r->name);
+    if(isa(l, r) < 0)
+      ERR_N(pos, _("can't %s '%s' to '%s'"), action, l->name, r->name);
     return r->e->parent;
   }
   if(nonnull_check(l, r))
index 311011a37fa21eadf1a6da5253e9b4eb524cfb3e..dd66025a14de59367d1ef655fc3edabb470cf2c8 100644 (file)
@@ -74,10 +74,10 @@ describe_string_assign(Polar_, m_complex, SZ_COMPLEX,,
   num_digit((m_uint)creal(lhs)) + num_digit((m_uint)cimag(lhs) / M_PI) + 16,
   "#(%.4f, %.4f)", creal(lhs), cimag(lhs)/M_PI)
 describe_string_assign(Vec3_, m_vec3, SZ_VEC3,,
-  num_digit((m_uint)lhs.x) + num_digit((m_uint)lhs.y) + num_digit((m_uint)lhs.z) + 23,
+  num_digit((m_uint)lhs.x) + num_digit((m_uint)lhs.y) + num_digit((m_uint)lhs.z) + 25,
   "#(%.4f, %.4f, %.4f)", lhs.x, lhs.y, lhs.z)
 describe_string_assign(Vec4_, m_vec4, SZ_VEC4,,
-  num_digit((m_uint)lhs.x) + num_digit((m_uint)lhs.y) + num_digit((m_uint)lhs.z) + num_digit((m_uint)lhs.w) + 30,
+  num_digit((m_uint)lhs.x) + num_digit((m_uint)lhs.y) + num_digit((m_uint)lhs.z) + num_digit((m_uint)lhs.w) + 40,
   "#(%.4f, %.4f, %.4f, %.4f)", lhs.x, lhs.y, lhs.z, lhs.w)
 describe_string_assign(Object_, M_Object, SZ_INT, release(lhs, shred),
   16,
@@ -118,15 +118,15 @@ describe_string(Complex, m_complex, SZ_COMPLEX,
   "#(%.4f, %.4f)%s", creal(lhs), cimag(lhs), rhs ? STRING(rhs) : "")
 describe_string(Polar, m_complex, SZ_COMPLEX,
   num_digit((m_uint)creal(lhs)) + num_digit((m_uint)cimag(lhs) / M_PI) + (rhs ? strlen(STRING(rhs)) : 0) +  12,,
-  "%%(%.4f, %4f*pi)%s", creal(lhs), cimag(lhs) / M_PI, rhs ? STRING(rhs) : "")
+  "%%(%.4f, %.4f*pi)%s", creal(lhs), cimag(lhs) / M_PI, rhs ? STRING(rhs) : "")
 describe_string(Vec3, m_vec3, SZ_VEC3,
   (rhs ? strlen(STRING(rhs)) : 0) + 23 + num_digit((m_uint)lhs.x) +
                                       num_digit((m_uint)lhs.y) + num_digit((m_uint)lhs.z),,
   "@(%.4f, %.4f, %.4f)%s", lhs.x, lhs.y, lhs.z, rhs ? STRING(rhs) : "")
 describe_string(Vec4, m_vec4, SZ_VEC4,
-  (rhs ? strlen(STRING(rhs)) : 0) + 28 + num_digit((m_uint)lhs.x) +
+  (rhs ? strlen(STRING(rhs)) : 0) + 30 + num_digit((m_uint)lhs.x) +
   num_digit((m_uint)lhs.y) + num_digit((m_uint)lhs.z) + num_digit((m_uint)lhs.w),,
-  "@(%4f, %4f, %4f, %4f)%s", lhs.x, lhs.y, lhs.z, lhs.w, rhs ? STRING(rhs) : "")
+  "@(%.4f, %.4f, %.4f, %.4f)%s", lhs.x, lhs.y, lhs.z, lhs.w, rhs ? STRING(rhs) : "")
 describe_string(Object, M_Object, SZ_INT,
   16 + (rhs ? strlen(STRING(rhs)) : 0), release(lhs, shred),
   "%p%s", (void*)lhs, rhs ? STRING(rhs) : "")
index dc7a68c35a2c66c126d9b1970e6cc4e9655cb873..b6acd692e2d35a981640d1df2106a1d3a556020d 100644 (file)
@@ -34,7 +34,7 @@ INSTR(VarargTop) {
 
 INSTR(VarargIni) {
   struct Vararg_* arg = mp_calloc(shred->info->mp, Vararg);
-  POP_REG(shred,  instr->m_val - SZ_INT)
+  POP_REG(shred, instr->m_val - SZ_INT)
   arg->d = (m_bit*)xmalloc(round2szint(instr->m_val));
   for(m_uint i = 0; i < instr->m_val; i += SZ_INT)
     *(m_uint*)(arg->d + i) = *(m_uint*)(shred->reg - SZ_INT + i);
@@ -85,10 +85,8 @@ static FREEARG(freearg_vararg) {
 GWION_IMPORT(vararg) {
   GWI_OB((t_vararg  = gwi_mk_type(gwi, "@Vararg", SZ_INT, t_object)))
   const Type t_varobj  = gwi_mk_type(gwi, "VarObject", SZ_INT, t_vararg);
-  GWI_OB(t_varobj)
   SET_FLAG(t_varobj, abstract);
-  const Type t_varloop = gwi_mk_type(gwi, "@VarLoop",  SZ_INT, NULL);
-  GWI_OB(t_varloop)
+  t_varloop = gwi_mk_type(gwi, "@VarLoop",  SZ_INT, NULL);
   GWI_BB(gwi_add_type(gwi,  t_varobj))
   GWI_BB(gwi_add_type(gwi,  t_varloop))
   GWI_BB(gwi_class_ini(gwi, t_vararg, NULL, NULL))
index 37ed44b97745debeb7e00d1b29a208004563df3e..aeb172234492be766197a04823812ad498417bc7 100644 (file)
@@ -139,8 +139,15 @@ ANN m_bool type_ref(Type t) {
     if(GET_FLAG(t, empty))
       return GW_OK;
     if(GET_FLAG(t, typedef) && t->e->def)
-      if(t->e->def->base.ext && t->e->def->base.ext->array && !t->e->def->base.ext->array->exp)
-        return GW_OK;
+      if(t->e->def->base.ext && t->e->def->base.ext->array) {
+        if(!t->e->def->base.ext->array->exp)
+          return GW_OK;
+        else {
+          const Type type = t->e->parent->e->d.base_type;
+          if(GET_FLAG(type, empty))
+            return GW_OK;
+        }
+      }
   } while((t = t->e->parent));
   return 0;
 }
@@ -192,4 +199,4 @@ ANN m_uint get_depth(const Type type) {
 
 Type t_void, t_int, t_bool, t_float, t_dur, t_time, t_now, t_complex, t_polar, t_vec3, t_vec4,
   t_null, t_object, t_shred, t_fork, t_event, t_ugen, t_string, t_ptr, t_array, t_gack,
-  t_function, t_fptr, t_vararg, t_lambda, t_class, t_union, t_undefined, t_auto, t_tuple;
+  t_function, t_fptr, t_varloop, t_vararg, t_lambda, t_class, t_union, t_undefined, t_auto, t_tuple;
index f71804c30db6ae7000b49086e87cb43951876f94..f5ba6d9706f9977769140c6905c23f6bf3f77ae8 100644 (file)
@@ -62,7 +62,7 @@ ANN static m_bool check_fptr_decl(const Env env, const Var_Decl var) {
       return GW_OK;
     ERR_B(var->pos, _("can't use non public typedef at global scope."))
   }
-  if(isa(type, env->class_def) < 0 && !GET_FLAG(func, global))
+  if(type && isa(type, env->class_def) < 0 && !GET_FLAG(func, global))
     ERR_B(var->pos, _("can't use non global fptr of other class."))
   if(GET_FLAG(func, member) && GET_FLAG(v, static))
       ERR_B(var->pos, _("can't use static variables for member function."))
@@ -463,7 +463,7 @@ ANN static m_bool func_match_inner(const Env env, const Exp e, const Type t,
       if(implicit) {
         const struct Implicit imp = { e, t, e->pos };
         struct Op_Import opi = { .op=insert_symbol("@implicit"), .lhs=e->type, .rhs=t, .data=(m_uint)&imp, .pos=e->pos };
-      return op_check(env, &opi) ? 1 : -1;
+        return op_check(env, &opi) ? GW_OK : GW_ERROR;
     }
   }
   return match ? 1 : -1;
@@ -596,6 +596,7 @@ CHECK_BO(check_call(env, exp))
         if(env->func == exists->d.func_ref) {
           if(check_call(env, exp) < 0)
             continue;
+          CHECK_OO(find_func_match(env, env->func, exp->args))
           m_func = env->func;
           break;
         }
@@ -700,7 +701,7 @@ ANN static Type check_exp_call_template(const Env env, Exp_Call *exp) {
   DECL_OO(const Value, value, = nspc_lookup_value1(call->type->e->owner, insert_symbol(call->type->name)))
   Tmpl *tm = value->d.func_ref ? value->d.func_ref->def->base->tmpl : call->type->e->d.func->def->base->tmpl;
   if(tm->call) {
-    const Func func = value->d.func_ref ?: predefined_func(env, value, exp, tm);
+    DECL_OO(const Func, func, = value->d.func_ref ?: predefined_func(env, value, exp, tm))
     if(!func->def->base->ret_type) { // template fptr
       const m_uint scope = env_push(env, value->owner_class, value->owner);
       CHECK_BO(traverse_func_def(env, func->def))
@@ -774,7 +775,8 @@ ANN Type check_exp_call1(const Env env, const Exp_Call *exp) {
     return check_lambda_call(env, exp);
   if(GET_FLAG(exp->func->type->e->d.func, ref)) {
     const Value value = exp->func->type->e->d.func->value_ref;
-    CHECK_BO(traverse_class_def(env, value->owner_class->e->def))
+    if(value->owner_class)
+      CHECK_BO(traverse_class_def(env, value->owner_class->e->def))
   }
   if(exp->args)
     CHECK_OO(check_exp(env, exp->args))
@@ -834,9 +836,9 @@ ANN static m_bool predefined_call(const Env env, const Type t, const loc_t pos)
 ANN static Type check_exp_call(const Env env, Exp_Call* exp) {
   if(exp->tmpl) {
     CHECK_OO(check_exp(env, exp->func))
-    const Type t = actual_type(exp->func->type);
+    const Type t = actual_type(!GET_FLAG(exp->func->type, nonnull) ?
+       exp->func->type : exp->func->type->e->parent);
     const Value v = nspc_lookup_value1(t->e->owner, insert_symbol(t->name));
-    assert(v);
     if(!GET_FLAG(v, func) && !GET_FLAG(exp->func->type, func) )
       ERR_O(exp_self(exp)->pos, _("template call of non-function value."))
     if(!v->d.func_ref || !v->d.func_ref->def->base->tmpl)
@@ -936,13 +938,16 @@ static const _type_func exp_func[] = {
 };
 
 ANN static inline Type check_exp(const Env env, const Exp exp) {
-  Exp curr = exp;
+  Exp curr = exp, next = NULL, prev = NULL;
   do {
+    next = curr->next;
     CHECK_OO((curr->type = exp_func[curr->exp_type](env, &curr->d)))
+    if(isa(curr->type, t_varloop) > 0 && (prev || next))
+      ERR_O(exp->pos, _("Varloop must be the only expression"))
     if(env->func && isa(curr->type, t_lambda) < 0 && isa(curr->type, t_function) > 0 &&
         !GET_FLAG(curr->type->e->d.func, pure))
       UNSET_FLAG(env->func, pure);
-  } while((curr = curr->next));
+  } while((prev = curr) && (curr = next));
   return exp->type;
 }
 
index e87b5614f1070be228d0ad564bafbc8d98e8b2b1..b05e8d764175bd7e50d562c0c40213b9250387cc 100644 (file)
@@ -70,7 +70,7 @@ static void fptr_def(const Env env, const Fptr_Def fptr) {
 
 ANN m_bool scan0_fptr_def(const Env env, const Fptr_Def fptr) {
   CHECK_BB(env_access(env, fptr->base->td->flag, td_pos(fptr->base->td)))
-  CHECK_OO(known_type(env, fptr->base->td))
+  CHECK_OB(known_type(env, fptr->base->td))
   CHECK_BB(scan0_defined(env, fptr->base->xid, td_pos(fptr->base->td)));
   const m_str name = s_name(fptr->base->xid);
   const Type t = new_type(env->gwion->mp, t_fptr->xid, name, t_fptr);
index 451d3efb168f2207a04bf0b02148f5d41b490633..80e9f934902b2c941dc6d5ecb0b4cfefd6a8625e 100644 (file)
@@ -81,13 +81,15 @@ ANN static Value scan2_func_assign(const Env env, const Func_Def d,
 
 
 ANN m_bool scan2_fptr_def(const Env env, const Fptr_Def fptr) {
-  const Func_Def def = fptr->type->e->d.func->def;
   if(!tmpl_base(fptr->base->tmpl)) {
+    const Func_Def def = fptr->type->e->d.func->def;
     def->base->ret_type = fptr->base->ret_type;
     if(fptr->base->args)
       CHECK_BB(scan2_args(env, def))
-  } else
+  } else {
+    CHECK_OB(fptr->type) // should happen before
     SET_FLAG(fptr->type, func);
+  }
   return GW_OK;
 }
 
index e9fb5dcc711137e3f75a067c690e2d868953d84f..245d5db3c7ed3a0e6841cba851a24d340fa65e4c 100644 (file)
@@ -18,6 +18,8 @@ ANN Type type_decl_resolve(const Env env, const Type_Decl* td) {
   DECL_OO(const Type, t, = scan_type(env, base, td))
   const Type ret = !td->array ? t : array_type(env, t, td->array->depth);
   if(GET_FLAG(td, nonnull)) {
+    if(isa(ret, t_void) > 0)
+      ERR_O(td_pos(td), _("void types can't be nonnull."))
     if(isa(ret, t_object) < 0 && isa(ret, t_function) < 0)
       return ret;
     char c[strlen(t->name) + 9];
index 129eba1d2dd6a1424af43dd45525786c791026e5..0ef90a006105fff2094ea4da583b2ee4477aaee7 100644 (file)
@@ -306,7 +306,7 @@ ANN void vm_run(const VM* vm) { // lgtm [cpp/use-of-goto]
     &&newobj, &&addref, &&objassign, &&assign, &&remref,
     &&except, &&allocmemberaddr, &&dotmember, &&dotfloat, &&dotother, &&dotaddr,
     &&staticint, &&staticfloat, &&staticother,
-    &&dotfunc, &&dotstaticfunc, &&eoc, &&pushstr,
+    &&dotfunc, &&dotstaticfunc, &&pushstaticcode, &&pushstr,
     &&gcini, &&gcadd, &&gcend,
     &&gack, &&regpushimm, &&other, &&eoc
   };
@@ -801,6 +801,11 @@ PRAGMA_PUSH()
   *(VM_Code*)(reg-SZ_INT) = ((Func)vector_at(a.obj->vtable, VAL))->code;
 PRAGMA_POP()
   DISPATCH()
+pushstaticcode:
+  *(m_bit*)byte = eRegPushImm;
+  VAL = (*(m_uint*)(reg) = (m_uint)((Func)VAL)->code);
+  reg += SZ_INT;
+  DISPATCH()
 pushstr:
   *(M_Object*)reg = new_string2(vm->gwion->mp, shred, (m_str)VAL);
   reg += SZ_INT;
index 6a6d29f3e48e60d84f946ed2f7f55afbfca265bd..bcb1e2bc7bb589d301bdb79e886c49bb77df0ba8 100644 (file)
@@ -52,9 +52,12 @@ ANN static m_bit* tobytecode(MemPool p, const VM_Code code) {
         instr->opcode = eRegPushImm;
         instr->m_val = (m_uint)code;
       } else {
-        instr->opcode = eRegSetImm;
-        instr->m_val = (m_uint)((Func)instr->m_val)->code;
-        instr->m_val2 = -SZ_INT;
+        const Func f = (Func)instr->m_val;
+        if(f->code) {
+          instr->opcode = eRegSetImm;
+          instr->m_val = (m_uint)((Func)instr->m_val)->code;
+          instr->m_val2 = -SZ_INT;
+        }
       }
     }
     if(instr->opcode < eGack)