]> Nishi Git Mirror - gwion.git/commitdiff
:art: Various Bugfixes
authorJérémie Astor <astor.jeremie@wanadoo.fr>
Sat, 30 Nov 2019 21:13:32 +0000 (22:13 +0100)
committerJérémie Astor <astor.jeremie@wanadoo.fr>
Sat, 30 Nov 2019 21:14:57 +0000 (22:14 +0100)
src/lib/array.c
src/lib/engine.c
src/lib/tuple.c
src/parse/check.c
src/parse/operator.c
src/parse/scan0.c

index f0188be34607b99c75c2f7087d09b0b51a640c43..11b751efb882ab3d5d0b3a86dc0306f2ba004b25 100644 (file)
@@ -194,34 +194,32 @@ static inline m_bool bounds(const M_Vector v, const m_int i) {
 }
 
 static INSTR(ArraySlice) {
-  shred->reg -= SZ_INT *3;
-  const M_Object array = *(M_Object*)REG(0);
-  const M_Vector v = ARRAY(array);
-  const m_int start = *(m_uint*)REG(SZ_INT);
-  m_int end   = *(m_uint*)REG(SZ_INT*2);
+  shred->reg -= SZ_INT *2;
+  const M_Object array = *(M_Object*)REG(-SZ_INT);
+  const M_Vector in = ARRAY(array);
+  const m_int start = *(m_uint*)REG(0);
+  m_int end   = *(m_uint*)REG(SZ_INT);
   if(end < 0)
-    end = ARRAY_LEN(v) + end;
+    end = ARRAY_LEN(in) + end;
   const m_int op    = start < end ? 1 : -1;
   const m_uint sz    = op > 0 ? end - start : start - end;
-  if(bounds(v, start) < 0 || bounds(v, end) < 0)
+  if(bounds(in, start) < 0 || bounds(in, end) < 0)
     Except(shred, "OutOfBoundsArraySliceException");
-  for(m_int i = start, j = 0; i != end; i += op, ++j)
-    m_vector_get(v, i, REG(j * SZ_INT));
-  *(m_uint*)REG(sz * SZ_INT) = sz;
-  PUSH_REG(shred, sz * SZ_INT);
+  const M_Object out = new_array(shred->info->vm->gwion->mp, array->type_ref, sz);
+  for(m_int i = start, j = 0; i != end; i += op, ++j) {
+    m_bit buf[ARRAY_SIZE(in)];
+    m_vector_get(in, i, &buf);
+    m_vector_set(ARRAY(out), i, buf);
+  }
+  *(M_Object*)REG(-SZ_INT) = out;
 }
 
 static OP_EMIT(opem_array_slice) {
   const Exp exp = (Exp)data;
-  Exp_Slice *range = &exp->d.exp_slice;
   if(!GET_FLAG(exp->type, nonnull))
     emit_add_instr(emit, GWOP_EXCEPT);
   emit_add_instr(emit, ArraySlice);
-  const Instr instr = emit_add_instr(emit, ArrayInit);
-  instr->m_val = (m_uint)range->base->type;
-  instr->m_val2 = range->base->type->size;
-  emit_add_instr(emit, GcAdd);
-  return instr;
+  return emit_add_instr(emit, GcAdd);
 }
 
 static FREEARG(freearg_array) {
@@ -230,6 +228,24 @@ static FREEARG(freearg_array) {
   mp_free(((Gwion)gwion)->mp, ArrayInfo, info);
 }
 
+ANN Type at_depth(const Env env, const Array_Sub array);
+ANN static Type partial_depth(const Env env, const Array_Sub array) {
+  const Exp curr = take_exp(array->exp, array->type->array_depth);
+  struct Array_Sub_ next = { curr->next, array_base(array->type), array->depth - array->type->array_depth };
+  return at_depth(env, &next);
+}
+
+static OP_CHECK(opck_not_array) {
+  const Array_Sub array = (Array_Sub)data;
+    ERR_O(array->exp->pos, _("array subscripts (%"UINT_F") exceeds defined dimension (%"UINT_F")"),
+        array->depth, get_depth(array->type))
+}
+
+static OP_CHECK(opck_array) {
+  const Array_Sub array = (Array_Sub)data;
+  return partial_depth(env, array);
+}
+
 GWION_IMPORT(array) {
   const Type t_array  = gwi_class_ini(gwi, "@Array", NULL);
   gwi->gwion->type[et_array] = t_array;
@@ -264,6 +280,13 @@ GWION_IMPORT(array) {
   GWI_BB(gwi_oper_add(gwi, opck_array_slice))
   GWI_BB(gwi_oper_emi(gwi, opem_array_slice))
   GWI_BB(gwi_oper_end(gwi, "@slice", NULL))
+  GWI_BB(gwi_oper_add(gwi, opck_array_slice))
+  GWI_BB(gwi_oper_ini(gwi, "int", (m_str)OP_ANY_TYPE, NULL))
+  GWI_BB(gwi_oper_add(gwi, opck_not_array))
+  GWI_BB(gwi_oper_end(gwi, "@array", NULL))
+  GWI_BB(gwi_oper_ini(gwi, "int", "@Array", NULL))
+  GWI_BB(gwi_oper_add(gwi, opck_array))
+  GWI_BB(gwi_oper_end(gwi, "@array", NULL))
   gwi_register_freearg(gwi, ArrayAlloc, freearg_array);
   return GW_OK;
 }
index da27da59e555d4a41383802236ff556957e33072..338aee7335d67b13495a0266d9377207afbe669a 100644 (file)
@@ -116,8 +116,8 @@ ANN static m_bool import_core_libs(const Gwi gwi) {
   gwi->gwion->type[et_union] = t_union;
   GWI_BB(gwi_class_end(gwi))
 
-  GWI_BB(import_tuple(gwi))
   GWI_BB(import_array(gwi))
+  GWI_BB(import_tuple(gwi))
   GWI_BB(import_event(gwi))
   GWI_BB(import_ugen(gwi))
   GWI_BB(import_ptr(gwi))
index be60b75458b8c6e4ddde5c7468447e9395a6ed1e..4e6115b5c7eafb401f9d763d727f45bf38d03655 100644 (file)
@@ -211,7 +211,6 @@ static OP_CHECK(opck_cast_tuple) {
 static OP_CHECK(opck_impl_tuple) {
   struct Implicit *imp = (struct Implicit*)data;
   CHECK_BN(tuple_match(env, imp->e->type, imp->t))
-//  CHECK_BN(tuple_match(env, imp->t, imp->e->type))
   return imp->t;
 }
 
@@ -336,18 +335,31 @@ ANN void free_tupleform(MemPool p, const TupleForm tuple) {
     free_type_list(p, tuple->list);
 }
 
+ANN /*static*/ Type at_depth(const Env env, const Array_Sub array);
+static OP_CHECK(opck_tuple) {
+  const Array_Sub array = (Array_Sub)data;
+  const Vector v = &array->type->e->tuple->types;
+  const Exp exp = array->exp;
+  if(exp->exp_type != ae_exp_primary ||
+     exp->d.prim.prim_type != ae_prim_num)
+    ERR_O(exp->pos, _("tuple subscripts must be litteral"))
+  const m_uint idx = exp->d.prim.d.num;
+  if(idx >= vector_size(v))
+    ERR_O(exp->pos, _("tuple subscripts too big"))
+  const Type type = (Type)vector_at(v, idx);
+  if(type == env->gwion->type[et_undefined])
+    ERR_O(exp->pos, _("tuple subscripts is undefined at index %lu"), idx)
+  if(!exp->next)
+    return type;
+  struct Array_Sub_ next = { exp->next, type, array->depth - 1 };
+  return at_depth(env, &next);
+}
+
 GWION_IMPORT(tuple) {
   const Type t_tuple = gwi_mk_type(gwi, "Tuple", SZ_INT, "Object");
-//  const Type t_tuple = gwi_mk_type(gwi, "Tuple", SZ_INT, NULL);
-gwi_add_type(gwi, t_tuple);
-SET_FLAG(t_tuple, checked | ae_flag_scan2 | ae_flag_check | ae_flag_emit);
-//assert(!t_tuple->e->def);
-//  const Type t_tuple = gwi_class_ini(gwi, "Tuple", NULL);
-// this is a sign we should make the class_def optionnal
-// free def
-//t_tuple->e->def = NULL;
+  gwi_add_type(gwi, t_tuple);
+  SET_FLAG(t_tuple, checked | ae_flag_scan2 | ae_flag_check | ae_flag_emit);
   gwi->gwion->type[et_tuple] = t_tuple;
-//  GWI_BB(gwi_class_end(gwi))
   SET_FLAG(t_tuple, abstract | ae_flag_template);
   GWI_BB(gwi_oper_ini(gwi, "Object", "Tuple", NULL))
   GWI_BB(gwi_oper_add(gwi, opck_at_tuple))
@@ -370,6 +382,10 @@ SET_FLAG(t_tuple, checked | ae_flag_scan2 | ae_flag_check | ae_flag_emit);
   GWI_BB(gwi_oper_add(gwi, opck_at_tuple))
   GWI_BB(gwi_oper_emi(gwi, opem_at_tuple))
   GWI_BB(gwi_oper_end(gwi, "@=>", NULL))
+  GWI_BB(gwi_oper_ini(gwi, "int", "Tuple", NULL))
+  GWI_BB(gwi_oper_add(gwi, opck_tuple))
+//  GWI_BB(gwi_oper_emi(gwi, opem_at_tuple))
+  GWI_BB(gwi_oper_end(gwi, "@array", NULL))
   gwi_register_freearg(gwi, TupleUnpack, freearg_tuple_at);
   return GW_OK;
 }
index 5b6ee893ccd2228106e89464dbc747e9758caf7b..e7b629ea1b1ae902f760c6af15de86769a053d55 100644 (file)
@@ -206,7 +206,10 @@ ANN static m_bool check_range(const Env env, Range *range) {
     CHECK_OB(check_exp(env, range->start))
   if(range->end)
     CHECK_OB(check_exp(env, range->end))
-// check types match
+  if(range->start && range->end) {
+    if(isa(range->end->type, range->start->type) < 0)
+      ERR_B(range->start->pos, _("range types do not match"))
+  }
   return GW_OK;
 }
 
@@ -359,35 +362,7 @@ ANN static Type check_prim(const Env env, Exp_Primary *prim) {
   return exp_self(prim)->type = check_prim_func[prim->prim_type](env, &prim->d);
 }
 
-ANN static Type at_depth(const Env env, const Array_Sub array);
-ANN static Type tuple_depth(const Env env, const Array_Sub array) {
-  const Vector v = &array->type->e->tuple->types;
-  const Exp exp = array->exp;
-  if(exp->exp_type != ae_exp_primary ||
-     exp->d.prim.prim_type != ae_prim_num)
-    ERR_O(exp->pos, _("tuple subscripts must be litteral"))
-  const m_uint idx = exp->d.prim.d.num;
-  if(idx >= vector_size(v))
-    ERR_O(exp->pos, _("tuple subscripts too big"))
-  const Type type = (Type)vector_at(v, idx);
-  if(type == env->gwion->type[et_undefined])
-    ERR_O(exp->pos, _("tuple subscripts is undefined at index %lu"), idx)
-  if(!exp->next)
-    return type;
-  struct Array_Sub_ next = { exp->next, type, array->depth - 1 };
-  return at_depth(env, &next);
-}
-
-ANN static Type partial_depth(const Env env, const Array_Sub array) {
-  const Exp curr = take_exp(array->exp, array->type->array_depth);
-  if(!curr->next || !array_base(array->type))
-    ERR_O(array->exp->pos, _("array subscripts (%"UINT_F") exceeds defined dimension (%"UINT_F")"),
-        array->depth, get_depth(array->type))
-  struct Array_Sub_ next = { curr->next, array_base(array->type), array->depth - array->type->array_depth };
-  return at_depth(env, &next);
-}
-
-ANN static Type at_depth(const Env env, const Array_Sub array) {
+ANN Type at_depth(const Env env, const Array_Sub array) {
   const Type t = array->type;
   const m_uint depth = array->depth;
   if(GET_FLAG(t, typedef)) {
@@ -396,7 +371,10 @@ ANN static Type at_depth(const Env env, const Array_Sub array) {
   }
   if(t->array_depth >= depth)
     return array_type(env, array_base(array->type), t->array_depth - depth);
-  return (isa(t, env->gwion->type[et_tuple]) < 0 ? partial_depth : tuple_depth)(env, array);
+  const Symbol sym = insert_symbol("@array");
+  struct Op_Import opi = { .op=sym, .lhs=array->exp->type, .rhs=array->type, .pos=array->exp->pos, .data=(uintptr_t)array };
+  const Type ret = op_check(env, &opi);
+  return ret;
 }
 
 static ANN Type check_exp_array(const Env env, const Exp_Array* array) {
@@ -806,15 +784,15 @@ ANN Type check_exp_call1(const Env env, const Exp_Call *exp) {
 
 ANN static Type check_exp_binary(const Env env, const Exp_Binary* bin) {
   CHECK_OO(check_exp(env, bin->lhs))
+  const is_auto = bin->rhs->exp_type == ae_exp_decl && bin->rhs->d.exp_decl.type == env->gwion->type[et_auto];
+  if(is_auto)
+     bin->rhs->type = bin->rhs->d.exp_decl.type = bin->lhs->type;
   CHECK_OO(check_exp(env, bin->rhs))
-  const Type rhs =
-    !(bin->rhs->exp_type == ae_exp_decl && bin->rhs->d.exp_decl.type == env->gwion->type[et_auto]) ?
-      bin->rhs->type : bin->lhs->type;
   struct Op_Import opi = { .op=bin->op, .lhs=bin->lhs->type,
-    .rhs=rhs, .data=(uintptr_t)bin, .pos=exp_self(bin)->pos };
+    .rhs=bin->rhs->type, .data=(uintptr_t)bin, .pos=exp_self(bin)->pos };
   const Type ret = op_check(env, &opi);
-  if(ret && bin->rhs->exp_type == ae_exp_decl && bin->rhs->d.exp_decl.type == env->gwion->type[et_auto])
-    bin->rhs->type = bin->rhs->d.exp_decl.type = rhs;
+  if(!ret && is_auto)
+    bin->rhs->d.exp_decl.list->self->value->type = env->gwion->type[et_auto];
   return ret;
 }
 
@@ -1087,6 +1065,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(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"))
     const m_bool ret = check_implicit(env, stmt->val, env->func->def->base->ret_type);
     if(ret > 0)
       return ret;
index 454d9e48830eb7ebd450be7e143ab309d592c3de..e8a2a6535b497fd26b7577bf013d26a4fdff6a77 100644 (file)
@@ -48,7 +48,10 @@ ANN static Type op_parent(const Env env, const Type t) {
 static m_bool op_match(const restrict Type t, const restrict Type mo) {
   if(t == OP_ANY_TYPE || mo == OP_ANY_TYPE)
     return GW_OK;
-  if((t && mo && mo->xid == t->xid) || (!t && !mo))
+  Type type = t;
+  while(SAFE_FLAG(type, template) && type->e->def && type->e->def->base.tmpl && type->e->def->base.tmpl->call) type = type->e->parent;
+//  if((t && mo && mo->xid == t->xid) || (!t && !mo))
+  if((type && mo && mo->xid == type->xid) || (!type && !mo))
     return GW_OK;
   return 0;
 }
@@ -62,6 +65,23 @@ ANN2(1) static M_Operator* operator_find(const Vector v, const restrict Type lhs
   return NULL;
 }
 
+static m_bool op_match2(const restrict Type t, const restrict Type mo) {
+//  if(t == OP_ANY_TYPE || mo == OP_ANY_TYPE)
+//    return GW_OK;
+  if((t && mo && (t != OP_ANY_TYPE && mo != OP_ANY_TYPE && mo->xid == t->xid)) || (!t && !mo))
+    return GW_OK;
+  return 0;
+}
+
+ANN2(1) static M_Operator* operator_find2(const Vector v, const restrict Type lhs, const restrict Type rhs) {
+  for(m_uint i = vector_size(v) + 1; --i;) {
+    M_Operator* mo = (M_Operator*)vector_at(v, i - 1);
+    if(op_match2(lhs, mo->lhs) && op_match2(rhs, mo->rhs))
+      return mo;
+  }
+  return NULL;
+}
+
 
 ANN static M_Operator* new_mo(MemPool p, const struct Op_Import* opi) {
   M_Operator* mo = mp_calloc(p, M_Operator);
@@ -91,13 +111,16 @@ ANN static Vector op_vector(MemPool p, const struct OpChecker *ock) {
   return create;
 }
 
+static m_str type_name(const Type t) {
+  return t ? t == OP_ANY_TYPE ? "any" : t->name : "";
+}
+
 ANN static m_bool _op_exist(const struct OpChecker* ock, const Nspc n) {
   const Vector v = (Vector)map_get(&n->info->op_map, (vtype)ock->opi->op);
-  if(!v || !operator_find(v, ock->opi->lhs, ock->opi->rhs))
+  if(!v || !operator_find2(v, ock->opi->lhs, ock->opi->rhs))
     return GW_OK;
   env_err(ock->env, ock->opi->pos, _("operator '%s', for type '%s' and '%s' already imported"),
-        s_name(ock->opi->op), ock->opi->lhs ? ock->opi->lhs->name : NULL,
-        ock->opi->rhs ? ock->opi->rhs->name : NULL);
+        s_name(ock->opi->op), type_name(ock->opi->lhs), type_name(ock->opi->rhs));
   return GW_ERROR;
 }
 
@@ -121,6 +144,12 @@ ANN m_bool add_op(const Gwion gwion, const struct Op_Import* opi) {
 }
 
 ANN static void set_nspc(struct OpChecker* ock, const Nspc nspc) {
+  if(ock->opi->op == insert_symbol(ock->env->gwion->st, "@array")) {
+    Array_Sub array = (Array_Sub)ock->opi->data;
+    array->exp->nspc = nspc;
+    return;
+
+  }
   if(ock->opi->op == insert_symbol(ock->env->gwion->st, "@implicit") ||
      ock->opi->op == insert_symbol(ock->env->gwion->st, "@access") ||
      ock->opi->op == insert_symbol(ock->env->gwion->st, "@repeat")) {
@@ -153,10 +182,6 @@ ANN static Type op_check_inner(struct OpChecker* ock) {
   return NULL;
 }
 
-static m_str type_name(const Type t) {
-  return t ? t == OP_ANY_TYPE ? "any" : t->name : "";
-}
-
 ANN Type op_check(const Env env, struct Op_Import* opi) {
   Nspc nspc = env->curr;
   do {
index 33e7f7a14f723cf6a016d54bf18dc08931b2e254..c8fe689b334eaa1f860a64ba242ee43bb218a701 100644 (file)
@@ -67,11 +67,27 @@ static void fptr_def(const Env env, const Fptr_Def fptr) {
   def->base->func = fptr->base->func;
 }
 
+ANN static m_bool check_tmpl_args(const Env env, const Func_Base *base) {
+  ID_List id = base->tmpl->list;
+  do nspc_add_type(env->curr, id->xid, env->gwion->type[et_undefined]);
+  while((id = id->next));
+  Arg_List arg = base->args;
+  do CHECK_OB(known_type(env, arg->td))
+  while((arg = arg->next));
+  return GW_OK;
+}
+
 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_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);
+if(fptr->base->tmpl && fptr->base->args) {
+  nspc_push_type(env->gwion->mp, env->curr);
+  const m_bool ret = check_tmpl_args(env, fptr->base);
+  nspc_pop_type(env->gwion->mp, env->curr);
+  CHECK_BB(ret);
+}
   const Type t = scan0_type(env, env->gwion->type[et_fptr]->xid, name, env->gwion->type[et_fptr]);
   t->e->owner = !(!env->class_def && GET_FLAG(fptr->base->td, global)) ?
     env->curr : env->global_nspc;