-Subproject commit 81c1475c08c875b30bf95a9ca1e8a1bf597ff389
+Subproject commit 317a4623e5e4cd1ca5c46d84d9b53b23a5159678
}
return GW_OK;
}
- if (!strncmp(v->type->name, "Ref:[", 5)) {
+ if (!strncmp(v->type->name, "Ref:[", 5) && (!prim_exp(data)->cast_to || strncmp(prim_exp(data)->cast_to->name, "Ref:[", 5))) {
if (exp_getvar(exp_self(prim_self(data)))) {
const Instr instr = emit_add_instr(emit, RegPushMem);
instr->m_val = v->from->offset;
back->m_val = (m_uint)f->code;
} else
back->m_val = (m_uint)f;
- }
+ } else // calling a local func not emitted yet
+ vector_pop(&emit->code->instr);
}
} else if ((f->value_ref->from->owner_class &&
tflag(f->value_ref->from->owner_class, tflag_struct)) ||
instr->execute = SetFunc;
instr->m_val = (m_uint)f;
} else {
- const Instr back = (Instr)vector_back(&emit->code->instr);
- if(back->execute != SetFunc) {
+// const Instr back = (Instr)vector_back(&emit->code->instr);
+// if(back->execute != SetFunc || back->m_val != f) {
const Instr instr = emit_add_instr(emit, SetFunc);
instr->m_val = (m_uint)f;
- }
+// }
}
}
const m_uint offset = emit_code_offset(emit);
ANN static Instr _flow(const Emitter emit, const Exp e, const m_bool b) {
CHECK_BO(emit_exp_pop_next(emit, e));
- emit_exp_addref1(emit, e, -exp_size(e));
+ emit_exp_addref1(emit, e, -exp_size(e)); // ????
struct Op_Import opi = {
.op = insert_symbol(b ? "@conditional" : "@unconditional"),
.rhs = e->type,
const Exp_Primary *prim = (Exp_Primary *)VKEY(map, i);
const Value v = prim->value;
CHECK_BB(emit_prim_novar(emit, prim));
- ;
if (isa(prim->value->type, emit->gwion->type[et_compound]) > 0) {
if (vflag(v, vflag_fglobal) && !vflag(v, vflag_closed))
emit_exp_addref1(emit, exp_self(prim), -v->type->size);
CHECK_BB(emit_exp(emit, stmt->exp)); // add ref?
regpop(emit, SZ_INT);
+// emit_exp_addref(emit, stmt->exp, 0);
const m_uint offset = emit_local(emit, emit->gwion->type[et_int]); // array?
emit_local(emit, emit->gwion->type[et_int]);
emit_local(emit, emit->gwion->type[et_int]);
static GACK(gack_class) {
const Type type = actual_type(shred->info->vm->gwion, t) ?: t;
- INTERP_PRINTF("class(%s)", type->name)
+ INTERP_PRINTF("%s", type->name)
}
static GACK(gack_function) { INTERP_PRINTF("%s", t->name) }
Exp_Call call = {.func = bin->rhs, .args = bin->lhs};
Exp e = exp_self(bin);
e->exp_type = ae_exp_call;
+ call.apms = true;
memcpy(&e->d.exp_call, &call, sizeof(Exp_Call));
return check_exp_call1(env, &e->d.exp_call) ?: env->gwion->type[et_error];
}
if (bin->rhs->type->info->func->def->base->tmpl)
fptr_instr(emit, bin->lhs->type->info->func, 2);
(void)emit_add_instr(emit, int_r_assign);
- if (!is_fptr(emit->gwion, bin->lhs->type) &&
- vflag(bin->rhs->type->info->func->value_ref, vflag_member)/*&&
- bin->lhs->exp_type != ae_exp_td*/) {
+ if (vflag(bin->lhs->type->info->func->value_ref, vflag_member) &&
+ !is_fptr(emit->gwion, bin->lhs->type)) {
const Instr pop = emit_add_instr(emit, RegMove);
pop->m_val = -SZ_INT;
const Instr cpy = emit_add_instr(emit, Reg2Reg);
ANN static m_bool fptr_args(const Env env, Func_Base *base[2]) {
Arg_List arg0 = base[0]->args, arg1 = base[1]->args;
+ if(!base[0]->func->value_ref->from->owner_class &&
+ base[1]->func->value_ref->from->owner_class)
+ arg0 = arg0->next;
+ if(!base[1]->func->value_ref->from->owner_class &&
+ base[0]->func->value_ref->from->owner_class)
+ arg1 = arg1->next;
while (arg0) {
CHECK_OB(arg1);
if (arg0->type && arg1->type)
// return GW_ERROR;
const Type l_type = info->lhs->value_ref->from->owner_class;
const Type r_type = info->rhs->value_ref->from->owner_class;
- if (!r_type && l_type)
+ if (!r_type && l_type) {
+ if (/*!GET_FLAG(info->lhs, global) && */(!info->rhs->def->base->args ||
+isa(l_type, info->rhs->def->base->args->var_decl->value->type) < 0)
+)
ERR_B(info->pos,
_("can't assign member function to non member function pointer"))
- else if (!l_type && r_type) {
- if (!GET_FLAG(info->rhs, global))
+ } else if (!l_type && r_type) {
+ if (!GET_FLAG(info->rhs, global) && (!info->lhs->def->base->args ||
+isa(r_type, info->lhs->def->base->args->var_decl->value->type) < 0)
+)
ERR_B(info->pos,
_("can't assign non member function to member function pointer"))
} else if (l_type && isa(r_type, l_type) < 0)
ERR_B(info->pos,
_("can't assign member function to a pointer of an other class"))
if (vflag(info->rhs->value_ref, vflag_member)) {
- if (!vflag(info->lhs->value_ref, vflag_member))
+ if (!vflag(info->lhs->value_ref, vflag_member) && l_type)
ERR_B(info->pos,
_("can't assign static function to member function pointer"))
- } else if (vflag(info->lhs->value_ref, vflag_member))
+ } else if (vflag(info->lhs->value_ref, vflag_member) && r_type)
ERR_B(info->pos,
_("can't assign member function to static function pointer"))
return GW_OK;
env->curr->info->value = l->def->base->values;
}
}
+
+ if(ret < 0) {
+ Arg_List args = l->def->base->args;
+ while(args) {
+ if(!args->var_decl->value) break;
+ free_value(args->var_decl->value, env->gwion);
+ args->var_decl->value = NULL;
+ args = args->next;
+ }
+
+ }
return ret;
}
if (bin->rhs->exp_type != ae_exp_decl &&
bin->rhs->d.exp_decl.td->xid != insert_symbol("auto"))
return env->gwion->type[et_error];
+ if (bin->lhs->exp_type == ae_exp_td)
+ ERR_N(bin->lhs->pos, "can't use {/}type decl expressions{0} in auto function pointer declarations");
// create a matching signature
// TODO: we could check first if there a matching existing one
Func_Base *const fbase =
const m_bool ret = traverse_fptr_def(env, fptr_def);
const Type t = fptr_def->type;
free_fptr_def(env->gwion->mp, fptr_def);
- type_remref(t, env->gwion);
+// type_remref(t, env->gwion);
bin->rhs->d.exp_decl.list->self->value->type = bin->rhs->type =
bin->rhs->d.exp_decl.type = t;
exp_setvar(bin->rhs, 1);
if (f->def->base->tmpl)
emit_add_instr(emit, DotTmplVal);
else if (is_static_call(emit, exp_self(member))) {
- if (f == emit->env->func) return;
+ if (member->is_call && f == emit->env->func) return;
const Instr func_i = emit_add_instr(emit, f->code ? RegPushImm : SetFunc);
func_i->m_val = (m_uint)f->code ?: (m_uint)f;
return;
return v->type;
if (is_class(env->gwion, v->type)) {
const Type parent = actual_type(env->gwion, v->type);
- if (isa(the_base, parent) > 0) { // beware templates
+ if (isa(the_base, parent) > 0 && parent->nspc) { // beware templates
const Symbol sym = insert_symbol(env->gwion->st, "new");
const Value ret = nspc_lookup_value1(parent->nspc, sym);
member->xid = sym;
const Instr instr = emit_add_instr(emit, RegPushImm);
instr->m_val = (m_uint)value->type;
}
- if(isa(value->type, emit->gwion->type[et_object]) > 0 &&
+ if((isa(value->type, emit->gwion->type[et_object]) > 0 || is_fptr(emit->gwion, value->type)) &&
!exp_getvar(exp_self(member)) &&
(GET_FLAG(value, static) || GET_FLAG(value, late))) {
const Instr instr = emit_add_instr(emit, GWOP_EXCEPT);
const m_int end = *(m_int *)REG(0);
const m_int op = start < end ? 1 : -1;
const m_uint sz = op > 0 ? end - start : start - end;
+ if(sz >= SIZE_MAX/SZ_INT) {
+ handle(shred, "RangeTooBig");
+ return;
+ }
const M_Object array = new_array(shred->info->mp, (Type)instr->m_val, sz);
for (m_int i = start, j = 0; i != end; i += op, ++j)
m_vector_set(ARRAY(array), j, &i);
return imp->t;
}
+static OP_CHECK(opck_implicit_ref) {
+ const struct Implicit *imp = (struct Implicit *)data;
+ CHECK_BN(ref_access(env, imp->e));
+ exp_setvar(imp->e, 1);
+ imp->e->cast_to = imp->t;
+ return imp->t;
+}
+
static OP_CHECK(opck_cast_similar) {
const Exp_Cast *cast = (Exp_Cast *)data;
return exp_self(cast)->type;
add_op(env->gwion, &opi);
}
+ANN static void ref2ref(Env env, const Type lhs, const Type rhs) {
+ struct Op_Func opfunc = {.ck = opck_implicit_ref };
+ struct Op_Import opi = {.op = insert_symbol("$"),
+ .lhs = lhs,
+ .ret = rhs,
+ .rhs = rhs,
+ .func=&opfunc, .data = eNoOp};
+ add_op(env->gwion, &opi);
+ opi.op = insert_symbol("@implicit");
+ add_op(env->gwion, &opi);
+}
+
static OP_CHECK(opck_ref_scan) {
struct TemplateScan *ts = (struct TemplateScan *)data;
struct tmpl_info info = {
SET_FLAG(t, abstract | ae_flag_final);
set_tflag(t, tflag_infer);
set_tflag(t, tflag_noret);
+ set_tflag(t, tflag_scan0);
+ set_tflag(t, tflag_scan1);
+ set_tflag(t, tflag_scan2);
+ set_tflag(t, tflag_check);
+ set_tflag(t, tflag_emit);
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);
ref2base(env, t, base);
+ ref2ref(env, t, t);
env_pop(env, scope);
+ t->info->tuple = new_tupleform(env->gwion->mp, base);
+ type_addref(base);
+ vector_add(&t->info->tuple->contains, (vtype)base);
nspc_add_type_front(t->info->value->from->owner, info.name, t);
return t;
}
}
const m_int op = start < end ? 1 : -1;
const m_uint sz = op > 0 ? end - start : start - end;
+ if(sz >= SIZE_MAX/SZ_INT) {
+ handle(shred, "SliceTooBig");
+ return;
+ }
char c[sz + 1];
for (m_int i = start, j = 0; i != end; i += op, ++j) c[j] = str[i];
c[sz] = '\0';
while (e) {
if (!e->type) // investigate
return NULL;
-// if (!strncmp(e->type->name, "Ref:[", 5)) exp_setvar(e, true);
+ if (!strncmp(e->type->name, "Ref:[", 5)) {
+if(!e->cast_to)e->cast_to = e->type;
+ }
if (!e1) {
if (fbflag(func->def->base, fbflag_variadic)) return func;
CHECK_OO(func->next);
}
ANN static Type check_exp_call(const Env env, Exp_Call *exp) {
- if (curried(env, exp->args))
+ if (exp->apms && curried(env, exp->args))
return env->gwion->type[et_curry];
if (exp->tmpl) {
DECL_BO(const m_bool, ret, = func_check(env, exp));
bool err = false;
for (m_uint i = 0; i < vector_size(&cdef->base.type->nspc->vtable); ++i) {
const Func f = (Func)vector_at(&cdef->base.type->nspc->vtable, i);
- if (f && GET_FLAG(f->def->base, abstract)) {
+ if (f && f->def->base && GET_FLAG(f->def->base, abstract)) {
if (!err) {
err = true;
gwerr_basic(_("missing function definition"),
return false;
}
+ANN static inline bool type_is_recurs(const Type t, const Type tgt) {
+ return isa(tgt, t) > 0 || isa(t, tgt) > 0 || (tgt->info->tuple && vector_find(&tgt->info->tuple->contains, (m_uint)t) > -1);
+}
+
ANN bool check_trait_requests(const Env env, const Type t, const ID_List list);
ANN static m_bool _check_class_def(const Env env, const Class_Def cdef) {
const Type t = cdef->base.type;
struct scope_iter iter = {t->nspc->info->value, 0, 0};
while (scope_iter(&iter, &value) > 0) {
if (isa(value->type, env->gwion->type[et_compound]) < 0) continue;
+// const Type t = array_base(value->type);
if (value->type->nspc && !GET_FLAG(value, late)) {
Value v;
struct scope_iter inner = {value->type->nspc->info->value, 0, 0};
+bool error = false;
while (scope_iter(&inner, &v) > 0) {
const Type tgt = array_base(v->type);
- if(isa(tgt, t) > 0 || isa(t, tgt) > 0 || (tgt->info->tuple &&vector_find(&tgt->info->tuple->contains, (m_uint)t) > -1)) {
+// if(isa(tgt, t) > 0 || isa(t, tgt) > 0 || (tgt->info->tuple && vector_find(&tgt->info->tuple->contains, (m_uint)t) > -1)) {
+ if(type_is_recurs(t, tgt)) {
env_err(env, v->from->loc, _("recursive type"));
env->context->error = false;
env_err(env, value->from->loc, _("recursive type"));
gw_err("use {+G}late{0} on one (or more) of the variables?\n");
- env_set_error(env);
- type_remref(t, env->gwion);
- return GW_ERROR;
+// env_set_error(env);
+vector_rem2(&t->info->tuple->contains, (m_uint)tgt);
+vector_rem2(&tgt->info->tuple->contains, (m_uint)t);
+type_remref(t, env->gwion);
+//type_remref(tgt, env->gwion);
+//nspc_add_type_front(t->nspc, insert_symbol(tgt->name), tgt);
+//nspc_add_type_front(tgt->nspc, insert_symbol(tgt->name), t);
+ set_tflag(t, tflag_infer);
+ set_tflag(tgt, tflag_infer);
+ unset_tflag(t, tflag_check);
+ unset_tflag(tgt, tflag_check);
+//value->type = env->gwion->type[et_error];
+//v->type = env->gwion->type[et_error];
+//env->gwion->type[et_error]->ref += 2;
+
+error = true;
+// return GW_OK;
}
}
+if(error)
+// return GW_OK;
+ return GW_ERROR;
}
}
nspc_allocdata(env->gwion->mp, t->nspc);
return exp;
}
-ANN static Ast scan0_func_def_default(const MemPool p, const Ast ast,
+ANN2(1,2) static Ast scan0_func_def_default(const MemPool p, const Ast ast,
const Ast next) {
const Func_Def base_fdef = ast->section->d.func_def;
Arg_List base_arg = base_fdef->base->args, former = NULL;
if (former) former->next = NULL;
// use cpy_func_base?
Func_Base *base = new_func_base(
- p, cpy_type_decl(p, base_fdef->base->td), base_fdef->base->xid,
+ p, base_fdef->base->td ? cpy_type_decl(p, base_fdef->base->td) : NULL, base_fdef->base->xid,
former ? cpy_arg_list(p, base_fdef->base->args) : NULL,
base_fdef->base->flag, base_fdef->base->pos);
const Exp efunc =
continue;
const Ast next = ast->next;
scan0_func_def_default(env->gwion->mp, ast, next);
- ast = next;
+ if(!(ast = next))break;
} while ((ast = ast->next));
return GW_OK;
}
ANN static Type scan1_type(const Env env, Type_Decl *td) {
DECL_OO(const Type, t, = known_type(env, td));
- if (!env->func && env->class_def && !GET_FLAG(td, late)) {
- CHECK_BO(type_cyclic(env, t, td));
- }
+ const Type base = array_base(t);
+ if (!env->func && env->class_def && !GET_FLAG(td, late))
+ CHECK_BO(type_cyclic(env, base, td));
CHECK_BO(ensure_scan1(env, t));
return t;
}
}
ANN static m_bool _scan1_func_def(const Env env, const Func_Def fdef) {
+ if(GET_FLAG(fdef->base, abstract) && !env->class_def)
+ ERR_B(fdef->base->pos, "file scope function can't be abstract");
+//exit(12);
const bool global = GET_FLAG(fdef->base, global);
const m_uint scope = !global ? env->scope->depth : env_push_global(env);
if (fdef->base->td)
const Exp_Binary *bin) {
CHECK_BB(scan2_exp(env, bin->lhs));
CHECK_BB(scan2_exp(env, bin->rhs));
+if(bin->rhs->exp_type == ae_exp_call)bin->rhs->d.exp_call.apms = true;
CHECK_BB(multi_decl(env, bin->lhs, bin->op));
return multi_decl(env, bin->rhs, bin->op);
}
return GW_OK;
if(!strcmp(s_name(fdef->base->xid), "new")) {
if(!env->class_def)
- ERR_B(fdef->base->pos, _("{G-}new{0} operator must be set inside {C+}class{0}"));
+ ERR_B(fdef->base->pos, _("{G+}new{0} operator must be set inside {C+}class{0}"));
if(!fdef->base->ret_type)
fdef->base->ret_type = env->class_def;
}
clean_values(shred);
// if (!size) return true;
if (!size) return false;
- if (size) {
- if (code->handlers.ptr)
- return find_handle(shred, effect, size);
- // there might be no more stack to unwind
- if (shred->mem == (m_bit *)shred + sizeof(struct VM_Shred_) + SIZEOF_REG)
-// return true;
- return false;
- } else
-// return true;
+// if (code->live_values.ptr)
+// clean_values(shred);
+ if (code->handlers.ptr)
+ return find_handle(shred, effect, size);
+ // there might be no more stack to unwind
+ if (shred->mem == (m_bit *)shred + sizeof(struct VM_Shred_) + SIZEOF_REG)
return false;
+// else
+// return true;
+// return false;
shred_unwind(shred);
return unwind(shred, effect, size - 1);
}
const m_uint line = vector_at(&shred->info->line, size - 1);
m_uint i;
bool can_skip = false;
+//printf("size %lu\n", size);
+if(!size)return;
for (i = size; --i;) {
const m_uint val = VPTR(&shred->info->line, i - 1);
if (!val)
return ME(o);
}
+#define handle(a, b) VM_OUT handle(a, b);
#define TEST0(t, pos) \
if (!*(t *)(reg - pos)) { \
- shred->pc = PC; \
+/* shred->pc = PC;*/ \
handle(shred, "ZeroDivideException"); \
break; \
}
DISPATCH()
overflow:
if (overflow_(mem + VAL2, shred)) {
- shred->pc = PC;
+// shred->pc = PC;
handle(shred, "StackOverflow");
continue;
}
if (idx < 0 || (m_uint)idx >= m_vector_size(ARRAY(a.obj))) {
gw_err(_("{-} ... at index {W}[{Y}%" INT_F "{W}]{0}\n"), idx);
// gw_err(_(" ... at dimension [%" INT_F "]\n"), VAL);
- VM_OUT
+// VM_OUT
handle(shred, "ArrayOutofBounds");
continue; // or break ?
}
* VAL2 = error message *
* grep for GWOP_EXCEPT and Except, exception... */
if (!*(m_bit **)(reg + (m_int)(VAL))) {
- shred->pc = PC;
handle(shred, "NullPtrException");
continue;
}
// this should check the *xid* of the exception
DISPATCH();
performeffect:
- VM_OUT
+// VM_OUT
handle(shred, (m_str)VAL);
break;
noop: