}
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) {
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;
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;
}
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))
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;
}
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))
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;
}
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;
}
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)) {
}
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) {
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;
}
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;
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;
}
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);
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;
}
}
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")) {
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 {
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;