From d02b7dd7dc6b45853d726262304710fff9bc4b7f Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=A9mie=20Astor?= Date: Sat, 30 Nov 2019 22:13:32 +0100 Subject: [PATCH] :art: Various Bugfixes --- src/lib/array.c | 57 +++++++++++++++++++++++++++++++------------- src/lib/engine.c | 2 +- src/lib/tuple.c | 36 ++++++++++++++++++++-------- src/parse/check.c | 54 +++++++++++++---------------------------- src/parse/operator.c | 41 ++++++++++++++++++++++++------- src/parse/scan0.c | 16 +++++++++++++ 6 files changed, 133 insertions(+), 73 deletions(-) diff --git a/src/lib/array.c b/src/lib/array.c index f0188be3..11b751ef 100644 --- a/src/lib/array.c +++ b/src/lib/array.c @@ -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; } diff --git a/src/lib/engine.c b/src/lib/engine.c index da27da59..338aee73 100644 --- a/src/lib/engine.c +++ b/src/lib/engine.c @@ -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)) diff --git a/src/lib/tuple.c b/src/lib/tuple.c index be60b754..4e6115b5 100644 --- a/src/lib/tuple.c +++ b/src/lib/tuple.c @@ -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; } diff --git a/src/parse/check.c b/src/parse/check.c index 5b6ee893..e7b629ea 100644 --- a/src/parse/check.c +++ b/src/parse/check.c @@ -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; diff --git a/src/parse/operator.c b/src/parse/operator.c index 454d9e48..e8a2a653 100644 --- a/src/parse/operator.c +++ b/src/parse/operator.c @@ -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 { diff --git a/src/parse/scan0.c b/src/parse/scan0.c index 33e7f7a1..c8fe689b 100644 --- a/src/parse/scan0.c +++ b/src/parse/scan0.c @@ -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; -- 2.43.0