From af185e3c47b4ace20738016b9b0836bd77199f7d Mon Sep 17 00:00:00 2001 From: fennecdjay Date: Thu, 6 Jun 2019 17:56:51 +0200 Subject: [PATCH] :art: A Better type system --- include/instr.h | 6 +- include/type.h | 19 +-- src/emit/emit.c | 57 ++++++--- src/lib/func.c | 211 ++++++++++++++++++++++---------- src/lib/gack.c | 16 +-- src/lib/instr.c | 59 +++++++-- src/lib/opfunc.c | 3 +- src/oo/context.c | 1 + src/oo/type.c | 10 +- src/parse/check.c | 137 +++++++++++++-------- src/parse/scan1.c | 43 +++++-- src/parse/scan2.c | 25 ++-- src/parse/template.c | 17 ++- src/parse/traverse.c | 2 +- src/parse/traverse_template.c | 5 +- src/vm/vm.c | 2 +- tests/error/ptr_assign_other.gw | 2 +- 17 files changed, 419 insertions(+), 196 deletions(-) diff --git a/include/instr.h b/include/instr.h index f311e2b5..a84f8d4a 100644 --- a/include/instr.h +++ b/include/instr.h @@ -61,13 +61,15 @@ INSTR(VecMember); INSTR(PopArrayClass); INSTR(DotTmpl); +INSTR(GTmpl); struct dottmpl_ { size_t len; m_str name; Func_Def base, def; - Type owner; - size_t overload; // => vtindex ? + Type owner_class; + Nspc owner; + size_t vt_index; Type_List tl; }; ANN void free_dottmpl(struct dottmpl_*); diff --git a/include/type.h b/include/type.h index f286ca8d..e9cc2a34 100644 --- a/include/type.h +++ b/include/type.h @@ -1,15 +1,16 @@ #ifndef __TYPE #define __TYPE - struct TypeInfo_ { - Type parent; - Nspc owner; - Class_Def def; - union type_data { - Func func; - Type base_type; - } d; - }; +struct TypeInfo_ { + Type parent; + Nspc owner; + Class_Def def; + union type_data { + Func func; + Type base_type; + } d; + struct Vector_ contains; +}; struct Type_ { m_str name; diff --git a/src/emit/emit.c b/src/emit/emit.c index d64392d2..44487123 100644 --- a/src/emit/emit.c +++ b/src/emit/emit.c @@ -305,7 +305,7 @@ ANN static inline Exp dot_static_exp(const Emitter emit, const Exp_Primary* prim ANN static m_bool emit_symbol_owned(const Emitter emit, const Exp_Primary* prim) { const Value v = prim->value; const Exp dot = (!GET_FLAG(v, static) ? dot_this_exp : dot_static_exp)(emit, prim, v->owner_class); - dot->type = v->type; + dot->type = exp_self(prim)->type; dot->emit_var = exp_self(prim)->emit_var; const m_bool ret = emit_exp_dot(emit, &dot->d.exp_dot); free_exp(emit->gwion->mp, dot); @@ -349,6 +349,8 @@ ANN static m_bool emit_symbol(const Emitter emit, const Exp_Primary* prim) { const m_uint size = v->type->size; const Instr instr = emit_kind(emit, size, exp_self(prim)->emit_var, !GET_FLAG(v, global) ? regpushmem : regpushbase); instr->m_val = v->offset; + if(isa(v->type, t_function) > 0 && isa(v->type, t_fptr) < 0) + instr->m_val = exp_self(prim)->type->e->d.func->value_ref->offset; return GW_OK; } @@ -684,6 +686,9 @@ ANN static m_bool prepare_call(const Emitter emit, const Exp_Call* exp_call) { ANN static inline m_int push_tmpl_func(const Emitter emit, const Func f) { const Value v = f->value_ref; + if(isa(v->type, t_class) > 0 && + isa(actual_type(v->type), t_fptr) > 0) + return emit->env->scope->depth; const m_uint scope = emit_push(emit, v->owner_class, v->owner); CHECK_BB(traverse_func_template(emit->env, f->def)) return (m_int)scope; @@ -751,10 +756,11 @@ ANN static Type_List tmpl_tl(const Env env, const m_str name) { } ANN m_bool traverse_dot_tmpl(const Emitter emit, const struct dottmpl_ *dt) { - const m_uint scope = emit_push_type(emit, dt->owner); + const m_uint scope = dt->owner_class ? + emit_push_type(emit, dt->owner_class) : emit_push(emit, NULL, dt->owner); m_bool ret = GW_ERROR; dt->def->base->tmpl->call = dt->tl;// in INSTR - if(traverse_func_template(emit->env, dt->def) > 0) { + if(!dt->def->base->func &&traverse_func_template(emit->env, dt->def) > 0) { ret = emit_func_def(emit, dt->def); nspc_pop_type(emit->gwion->mp, emit->env->curr); } @@ -773,7 +779,7 @@ static inline m_bool push_func_code(const Emitter emit, const Func f) { c[sz] = '\0'; struct dottmpl_ *dt = mp_calloc(emit->gwion->mp, dottmpl); dt->name = s_name(insert_symbol(c)); - dt->overload = f->def->base->tmpl->base; + dt->vt_index = f->def->base->tmpl->base; dt->tl = tmpl_tl(emit->env, c); dt->base = f->def; instr->opcode = eOP_MAX; @@ -782,11 +788,11 @@ static inline m_bool push_func_code(const Emitter emit, const Func f) { instr->execute = DotTmpl; return GW_OK; } -if(vector_size(&emit->code->instr)) { - const Instr instr = (Instr)vector_back(&emit->code->instr); - instr->opcode = eRegPushImm; - instr->m_val = (m_uint)f->code; -} + if(vector_size(&emit->code->instr)) { + const Instr instr = (Instr)vector_back(&emit->code->instr); + instr->opcode = eRegPushImm; + instr->m_val = (m_uint)f->code; + } return GW_OK; } @@ -807,6 +813,23 @@ ANN static Instr get_prelude(const Emitter emit, const Func f) { instr = emit_add_instr(emit, !GET_FLAG(f, builtin) ? FuncUsr : SetCode); else { emit_add_instr(emit, GWOP_EXCEPT); + if(f->def->base->tmpl) { // TODO: put in func + struct dottmpl_ *dt = (struct dottmpl_*)mp_calloc(emit->gwion->mp, dottmpl); + size_t len = strlen(f->name); + size_t sz = len - strlen(f->value_ref->owner->name); + char c[sz + 1]; + memcpy(c, f->name, sz); + c[sz] = '\0'; + dt->tl = tmpl_tl(emit->env, c); + dt->name = s_name(insert_symbol(c)); + dt->vt_index = f->def->base->tmpl->base; + dt->base = f->def; + dt->owner = f->value_ref->owner; + dt->owner_class = f->value_ref->owner_class; + const Instr gtmpl = emit_add_instr(emit, GTmpl); + gtmpl->m_val = (m_uint)dt; + gtmpl->m_val2 = strlen(c); + } instr = emit_add_instr(emit, FuncPtr); } instr->m_val2 = 1; @@ -842,7 +865,8 @@ ANN m_bool emit_exp_call1(const Emitter emit, const Func f) { if(GET_FLAG(f, template) && emit->env->func != f) CHECK_BB(emit_template_code(emit, 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)) + !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)){ const Instr back = (Instr)vector_back(&emit->code->instr); @@ -975,8 +999,9 @@ ANN static m_bool emit_exp_unary(const Emitter emit, const Exp_Unary* unary) { } ANN static m_bool emit_implicit_cast(const Emitter emit, - const restrict Type from, const restrict Type to) { - struct Op_Import opi = { .op=op_impl, .lhs=from, .rhs=to, .data=(m_uint)from }; + const restrict Exp from, const restrict Type to) { + const struct Implicit imp = { from, to }; + struct Op_Import opi = { .op=op_impl, .lhs=from->type, .rhs=to, .data=(m_uint)&imp }; return op_emit(emit, &opi); } @@ -1024,7 +1049,7 @@ ANN2(1) static m_bool emit_exp(const Emitter emit, Exp exp, const m_bool ref) { do { CHECK_BB(exp_func[exp->exp_type](emit, &exp->d)) if(exp->cast_to) - CHECK_BB(emit_implicit_cast(emit, exp->type, exp->cast_to)) + CHECK_BB(emit_implicit_cast(emit, exp, exp->cast_to)) if(ref && isa(exp->type, t_object) > 0 && isa(exp->type, t_shred) < 0 ) { // beware fork const Instr instr = emit_add_instr(emit, RegAddRef); instr->m_val = exp->emit_var; @@ -1563,7 +1588,7 @@ ANN static m_bool emit_member_func(const Emitter emit, const Exp_Dot* member, co emit_add_instr(emit, DotTmplVal); else { const Instr instr = emit_add_instr(emit, GET_FLAG(func, member) ? DotFunc : DotStaticFunc); - instr->m_val = func->vt_index; + instr->m_val = exp_self(member)->type->e->d.func->vt_index; } return GW_OK; } @@ -1651,6 +1676,8 @@ ANN static void emit_func_def_code(const Emitter emit, const Func func) { instr->m_val = (m_uint)emit->gwion->mp; ADD_REF(func->code) } + // TODO: find why we need this + func->def->stack_depth = func->code->stack_depth; } ANN static m_bool emit_func_def_body(const Emitter emit, const Func_Def func_def) { @@ -1658,7 +1685,7 @@ ANN static m_bool emit_func_def_body(const Emitter emit, const Func_Def func_def emit_func_def_args(emit, func_def->base->args); if(GET_FLAG(func_def, variadic)) stack_alloc(emit); - if(func_def->d.code->d.stmt_code.stmt_list) + if(func_def->d.code) CHECK_BB(emit_stmt_code(emit, &func_def->d.code->d.stmt_code)) emit_func_def_ensure(emit, func_def); return GW_OK; diff --git a/src/lib/func.c b/src/lib/func.c index a757862c..ca08dcdb 100644 --- a/src/lib/func.c +++ b/src/lib/func.c @@ -36,30 +36,113 @@ static OP_CHECK(opck_func_call) { return check_exp_call1(env, &e->d.exp_call) ?: t_null; } +static inline void fptr_instr(const Emitter emit, const Func f, const m_uint i) { + const Instr set = emit_add_instr(emit, RegSetImm); + set->m_val = (m_uint)f; + set->m_val2 = -SZ_INT*i; +} + static OP_EMIT(opem_func_assign) { Exp_Binary* bin = (Exp_Binary*)data; + if(bin->rhs->type->e->d.func->def->base->tmpl) + fptr_instr(emit, bin->lhs->type->e->d.func, 2); emit_add_instr(emit, int_r_assign); - if((bin->lhs->type != t_lambda && isa(bin->lhs->type, t_fptr) < 0) && GET_FLAG(bin->rhs->type->e->d.func, member)) { + if((bin->lhs->type != t_lambda && isa(bin->lhs->type, t_fptr) < 0) && + GET_FLAG(bin->rhs->type->e->d.func, member)) { const Instr instr = emit_add_instr(emit, LambdaAssign); instr->m_val = SZ_INT; } return GW_OK; } -ANN static Type fptr_type(const Env env, Exp_Binary* bin) { - const Func l_func = bin->lhs->type->e->d.func; - const Func r_func = bin->rhs->type->e->d.func; - const Nspc nspc = l_func->value_ref->owner; - const m_str c = s_name(l_func->def->base->xid); - const Value v = l_func->value_ref; - for(m_uint i = 0; i <= v->offset; ++i) { - const Symbol sym = func_symbol(env, nspc->name, c, NULL, i); - const Func f = nspc_lookup_func1(nspc, sym); // was lookup2 - CHECK_OO(f) - if(compat_func(r_func->def, f->def) > 0) - return r_func->value_ref->type->e->d.base_type; +struct FptrInfo { + Func lhs; + const Func rhs; + const Exp exp; + const loc_t pos; +}; + +ANN static m_bool fptr_tmpl_push(const Env env, struct FptrInfo *info) { + if(!info->rhs->def->base->tmpl) + return GW_OK; + ID_List t0 = info->lhs->def->base->tmpl->list, + t1 = info->rhs->def->base->tmpl->list; + nspc_push_type(env->gwion->mp, env->curr); + while(t0) { + CHECK_OB(t1) + nspc_add_type(env->curr, t0->xid, t_undefined); + nspc_add_type(env->curr, t1->xid, t_undefined); + t0 = t0->next; + t1 = t1->next; } - return NULL; + return GW_OK; +} + +ANN static m_bool fptr_args(const Env env, struct Func_Base_ *base[2]) { + Arg_List arg0 = base[0]->args, arg1 = base[1]->args; + while(arg0) { + CHECK_OB(arg1) + const Type t0 = known_type(env, base[0]->td); + CHECK_OB(t0) + const Type t1 = known_type(env, base[1]->td); + CHECK_OB(t1) + CHECK_BB(isa(t0, t1)) + arg0 = arg0->next; + arg1 = arg1->next; + } + return !arg1 ? GW_OK : GW_ERROR; +} + +ANN static m_bool fptr_check(const Env env, struct FptrInfo *info) { + const Type l_type = info->lhs->value_ref->owner_class; + const Type r_type = info->rhs->value_ref->owner_class; + if(!r_type && l_type) + 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)) + 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(GET_FLAG(info->rhs, member)) { + if(!GET_FLAG(info->lhs, member)) + ERR_B(info->pos, "can't assign static function to member function pointer") + } else if(GET_FLAG(info->lhs, member)) + ERR_B(info->pos, "can't assign member function to static function pointer") + return GW_OK; +} + +ANN static m_bool fptr_rettype(const Env env, struct FptrInfo *info) { + const Type t0 = known_type(env, info->lhs->def->base->td); + CHECK_OB(t0) + const Type t1 = known_type(env, info->rhs->def->base->td); + CHECK_OB(t1) + return isa(t0, t1); +} + +ANN static inline m_bool fptr_arity(struct FptrInfo *info) { + return GET_FLAG(info->lhs->def, variadic) == + GET_FLAG(info->rhs->def, variadic); +} + +ANN static Type fptr_type(const Env env, struct FptrInfo *info) { + const Value v = info->lhs->value_ref; + const Nspc nspc = v->owner; + const m_str c = s_name(info->lhs->def->base->xid), + stmpl = !info->rhs->def->base->tmpl ? NULL : "template"; + Type type = NULL; + for(m_uint i = 0; i <= v->offset && !type; ++i) { + const Symbol sym = (!info->lhs->def->base->tmpl || i != 0) ? + func_symbol(env, nspc->name, c, stmpl, i) : info->lhs->def->base->xid; + info->lhs = nspc_lookup_func1(nspc, sym); + assert(info->lhs); + struct Func_Base_ *base[2] = { info->lhs->def->base, info->rhs->def->base }; + if(fptr_tmpl_push(env, info) > 0 && fptr_rettype(env, info) > 0 && + fptr_arity(info) && fptr_args(env, base) > 0) + type = info->lhs->value_ref->type; + if(info->rhs->def->base->tmpl) + nspc_pop_type(env->gwion->mp, env->curr); + } + return type; } ANN2(1,3,4) m_bool check_lambda(const Env env, const Type owner, @@ -74,8 +157,9 @@ ANN2(1,3,4) m_bool check_lambda(const Env env, const Type owner, } if(base || arg) ERR_B(exp_self(l)->pos, "argument number does not match for lambda") - l->def = new_func_def(env->gwion->mp, new_func_base(env->gwion->mp, def->base->td, l->name, l->args), l->code, def->flag, - loc_cpy(env->gwion->mp, def->pos)); + l->def = new_func_def(env->gwion->mp, + new_func_base(env->gwion->mp, def->base->td, l->name, l->args), + l->code, def->flag, loc_cpy(env->gwion->mp, def->pos)); CHECK_BB(traverse_func_def(env, l->def)) arg = l->args; while(arg) { @@ -87,63 +171,44 @@ ANN2(1,3,4) m_bool check_lambda(const Env env, const Type owner, return GW_OK; } +ANN static m_bool fptr_lambda(const Env env, struct FptrInfo *info) { + Exp_Lambda *l = &info->exp->d.exp_lambda; + const Type owner = info->rhs->value_ref->owner_class; + return check_lambda(env, owner, l, info->rhs->def); +} + +ANN static m_bool fptr_do(const Env env, struct FptrInfo *info) { + if(isa(info->exp->type, t_lambda) < 0) { + CHECK_BB(fptr_check(env, info)) + return (info->exp->type = fptr_type(env, info)) ? GW_OK : GW_ERROR; + } + return fptr_lambda(env, info); +} + static OP_CHECK(opck_fptr_at) { Exp_Binary* bin = (Exp_Binary*)data; + struct FptrInfo info = { bin->lhs->type->e->d.func, bin->rhs->type->e->d.func, + bin->lhs, exp_self(bin)->pos }; + CHECK_BO(fptr_do(env, &info)) bin->rhs->emit_var = 1; - if(isa(bin->lhs->type, t_lambda) > 0) { - Exp_Lambda *l = &bin->lhs->d.exp_lambda; - const Type owner = nspc_lookup_type1(bin->rhs->type->e->owner->parent, - insert_symbol(bin->rhs->type->e->owner->name)); - CHECK_BO(check_lambda(env, owner, l, bin->rhs->type->e->d.func->def)) - return bin->rhs->type; - } - const Func l_func = bin->lhs->type->e->d.func; - const Func_Def l_fdef = l_func->def; - const Type l_type = l_func->value_ref->owner_class; - const Func r_func = bin->rhs->type->e->d.func; - const Func_Def r_fdef = r_func->def; - const Type r_type = r_func->value_ref->owner_class; - if(!r_type && l_type) - ERR_N(exp_self(bin)->pos, "can't assign member function to non member function pointer") - else if(r_type && !l_type) { - if(!GET_FLAG(r_func, global)) - ERR_N(exp_self(bin)->pos, "can't assign non member function to member function pointer") - } else if(r_type && isa(r_type, l_type) < 0) - ERR_N(exp_self(bin)->pos, "can't assign member function to member function pointer" - " of an other class") - if(GET_FLAG(r_func, member)) { - if(!GET_FLAG(l_func, member)) - ERR_N(exp_self(bin)->pos, "can't assign static function to member function pointer") - } else if(GET_FLAG(l_func, member)) - ERR_N(exp_self(bin)->pos, "can't assign member function to static function pointer") - if(isa(r_fdef->base->ret_type, l_fdef->base->ret_type) < 0) - ERR_N(exp_self(bin)->pos, "return type '%s' does not match '%s'\n\t... in pointer assignement", - r_fdef->base->ret_type->name, l_fdef->base->ret_type->name) - if(GET_FLAG(l_fdef, variadic) != GET_FLAG(r_fdef, variadic)) - ERR_N(exp_self(bin)->pos, "function must be of same argument kind.", - r_fdef->base->ret_type->name, l_fdef->base->ret_type->name) - if(isa(bin->lhs->type, t_fptr) > 0 && isa(bin->lhs->type, bin->rhs->type) > 0) - return bin->rhs->type; - return fptr_type(env, bin); + return bin->rhs->type; } static OP_CHECK(opck_fptr_cast) { Exp_Cast* cast = (Exp_Cast*)data; const Type t = exp_self(cast)->type; - const Value v = nspc_lookup_value1(env->curr, cast->exp->d.exp_primary.d.var); - CHECK_OO(v) - const Func f = isa(v->type, t_fptr) > 0 ? - v->type->e->d.func : - nspc_lookup_func1(env->curr, insert_symbol(v->name)); - CHECK_OO(f) - CHECK_BO(compat_func(t->e->d.func->def, f->def)) - cast->func = f; + struct FptrInfo info = { cast->exp->type->e->d.func, t->e->d.func, + cast->exp, exp_self(cast)->pos }; + CHECK_BO(fptr_do(env, &info)) + cast->func = cast->exp->type->e->d.func; return t; } static OP_EMIT(opem_fptr_cast) { CHECK_BB(opem_basic_cast(emit, data)) Exp_Cast* cast = (Exp_Cast*)data; + if(exp_self(cast)->type->e->d.func->def->base->tmpl) + fptr_instr(emit, cast->exp->type->e->d.func, 1); if(GET_FLAG(cast->exp->type->e->d.func, member)) { const Instr instr = emit_add_instr(emit, RegPop); instr->m_val = SZ_INT*2; @@ -153,6 +218,25 @@ static OP_EMIT(opem_fptr_cast) { return GW_OK; } +static OP_CHECK(opck_fptr_impl) { + struct Implicit *impl = (struct Implicit*)data; + struct FptrInfo info = { ((Exp)impl->e)->type->e->d.func, impl->t->e->d.func, + (Exp)impl->e, ((Exp)impl->e)->pos }; + CHECK_BO(fptr_do(env, &info)) + return ((Exp)impl->e)->cast_to = impl->t; +} + +static OP_EMIT(opem_fptr_impl) { + struct Implicit *impl = (struct Implicit*)data; + if(GET_FLAG(impl->t->e->d.func, member)) { + const Instr pop = emit_add_instr(emit, RegPop); + pop->m_val = SZ_INT; + } + if(impl->t->e->d.func->def->base->tmpl) + fptr_instr(emit, ((Exp)impl->e)->type->e->d.func, 1); + return GW_OK; +} + ANN Type check_exp_unary_spork(const Env env, const Stmt code); static OP_CHECK(opck_spork) { @@ -163,10 +247,10 @@ static OP_CHECK(opck_spork) { if(unary->exp && unary->exp->exp_type == ae_exp_call) return unary->op == op_spork ? t_shred : t_fork; else if(unary->code) { - ++env->scope->depth; \ - nspc_push_value(env->gwion->mp, env->curr); \ + ++env->scope->depth; + nspc_push_value(env->gwion->mp, env->curr); const m_bool ret = check_stmt(env, unary->code); - nspc_pop_value(env->gwion->mp, env->curr); \ + nspc_pop_value(env->gwion->mp, env->curr); --env->scope->depth; CHECK_BO(ret) return unary->op == op_spork ? t_shred : t_fork; @@ -202,6 +286,9 @@ GWION_IMPORT(func) { CHECK_BB(gwi_oper_add(gwi, opck_fptr_cast)) CHECK_BB(gwi_oper_emi(gwi, opem_fptr_cast)) CHECK_BB(gwi_oper_end(gwi, op_cast, NULL)) + CHECK_BB(gwi_oper_add(gwi, opck_fptr_impl)) + CHECK_BB(gwi_oper_emi(gwi, opem_fptr_impl)) + CHECK_BB(gwi_oper_end(gwi, op_impl, NULL)) CHECK_BB(gwi_oper_ini(gwi, NULL, (m_str)OP_ANY_TYPE, NULL)) CHECK_BB(gwi_oper_add(gwi, opck_spork)) CHECK_BB(gwi_oper_emi(gwi, opem_spork)) diff --git a/src/lib/gack.c b/src/lib/gack.c index a80e1ccd..775a0a09 100644 --- a/src/lib/gack.c +++ b/src/lib/gack.c @@ -15,7 +15,7 @@ static void print_type(const Type type) { const m_bool is_func = isa(type, t_function) > 0 && isa(type, t_fptr) < 0; const m_str name = is_func ? strdup("@function") : strdup(type->name); gw_out("(%s) ", name); - free(name); + xfree(name); if(GET_FLAG(type, typedef)) { gw_out(" aka "); print_type(type->e->parent); @@ -76,12 +76,14 @@ ANN2(1) static inline void print_object(const Type type, const M_Object obj) { } ANN static inline void print_func(const Type type, const m_bit* stack) { - 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 - gw_out("%s %p", type->name, NULL); + if(isa(type, t_fptr) > 0 && type->e->d.func->def->base->tmpl) { + const Func f = *(Func*)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); } ANN static void print_prim(const Type type, const m_bit* stack) { diff --git a/src/lib/instr.c b/src/lib/instr.c index 8529b8cd..cac9c040 100644 --- a/src/lib/instr.c +++ b/src/lib/instr.c @@ -58,21 +58,58 @@ INSTR(PopArrayClass) { ADD_REF(obj->type_ref) // add ref to typedef array type } -ANN static Func_Def from_base(const Env env, const struct dottmpl_ *dt, const Type t) { - const Symbol sym = func_symbol(env, t->name, s_name(dt->base->base->xid), - "template", dt->overload); - const Value v = nspc_lookup_value1(t->nspc, sym); +ANN static Func_Def from_base(const Env env, const struct dottmpl_ *dt, const Nspc nspc) { + const Func_Def fdef = dt->def ?: dt->base; + const Symbol sym = func_symbol(env, nspc->name, s_name(fdef->base->xid), + "template", dt->vt_index); + const Value v = nspc_lookup_value1(nspc, sym); CHECK_OO(v) const Func_Def base = v->d.func_ref->def; - const Func_Def def = new_func_def(env->gwion->mp, new_func_base(env->gwion->mp, base->base->td, insert_symbol(env->gwion->st, v->name), - base->base->args), base->d.code, base->flag, loc_cpy(env->gwion->mp, base->pos)); - def->base->tmpl = new_tmpl(env->gwion->mp, base->base->tmpl->list, dt->overload); + const Func_Def def = new_func_def(env->gwion->mp, new_func_base(env->gwion->mp, fdef->base->td, insert_symbol(env->gwion->st, v->name), + fdef->base->args), fdef->d.code, fdef->flag, loc_cpy(env->gwion->mp, base->pos)); + def->base->tmpl = new_tmpl(env->gwion->mp, base->base->tmpl->list, dt->vt_index); SET_FLAG(def, template); return def; } +INSTR(GTmpl) { + struct dottmpl_ *dt = (struct dottmpl_*)instr->m_val; + const Func f = *(Func*)REG(-SZ_INT); + const m_str name = f->name; + const Emitter emit = shred->info->vm->gwion->emit; + emit->env->name = "runtime"; + m_str tmpl_name = tl2str(emit->env, dt->tl); + for(m_uint i = 0 ; i <= f->value_ref->offset; ++i) { + const Symbol sym = func_symbol(emit->env, f->value_ref->owner->name, + name, tmpl_name, i); + const Func base = nspc_lookup_func1(f->value_ref->owner, sym); + if(base) { + xfree(tmpl_name); + assert(base->code); + if(GET_FLAG(base->def, static)) + shred->reg -= SZ_INT; + *(VM_Code*)(shred->reg -SZ_INT) = base->code; + return; + } + } + xfree(tmpl_name); + dt->def = f->def; + const Func_Def def = from_base(emit->env, dt, f->value_ref->owner); + if(!def) + Except(shred, "MissigTmplPtrException[internal]"); + dt->def = def; + dt->owner = f->value_ref->owner; + dt->owner_class = f->value_ref->owner_class; + if(traverse_dot_tmpl(emit, dt) > 0) { + if(GET_FLAG(def, static)) + shred->reg -= SZ_INT; + *(VM_Code*)(shred->reg -SZ_INT) = def->base->func->code; + return; + } +} + INSTR(DotTmpl) { - struct dottmpl_ * dt = (struct dottmpl_*)instr->m_val; + 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; @@ -86,7 +123,7 @@ INSTR(DotTmpl) { if(f) { if(!f->code) { dt->def = f->def;// - dt->owner = t; // + dt->owner_class = t; // if(traverse_dot_tmpl(emit, dt) < 0) continue; } @@ -96,11 +133,11 @@ INSTR(DotTmpl) { shred->reg += SZ_INT; return; } else { - const Func_Def def = from_base(emit->env, dt, t); + const Func_Def def = from_base(emit->env, dt, t->nspc); if(!def) continue; dt->def = def; // - dt->owner = t; // + dt->owner_class = t; // if(traverse_dot_tmpl(emit, dt) > 0) { if(GET_FLAG(def, static)) shred->reg -= SZ_INT; diff --git a/src/lib/opfunc.c b/src/lib/opfunc.c index 9d02745f..b186ea72 100644 --- a/src/lib/opfunc.c +++ b/src/lib/opfunc.c @@ -65,7 +65,8 @@ OP_CHECK(opck_unary_meta2_uniq) { const Exp_Unary* unary = (Exp_Unary*)data; CHECK_OO(opck_unary_meta2(env, data)) if(unary->exp->next) - ERR_N(exp_self(unary)->pos, "fuck!!") + ERR_N(exp_self(unary)->pos, + "'%s' must be applied to a unique expression", op2str(unary->op)) return t_int; } diff --git a/src/oo/context.c b/src/oo/context.c index a9230850..98486df1 100644 --- a/src/oo/context.c +++ b/src/oo/context.c @@ -1,4 +1,5 @@ #include +#include #include "gwion_util.h" #include "gwion_ast.h" #include "oo.h" diff --git a/src/oo/type.c b/src/oo/type.c index 2505fab7..41926714 100644 --- a/src/oo/type.c +++ b/src/oo/type.c @@ -13,13 +13,9 @@ ANN static void free_type(Type a, Gwion gwion) { if(GET_FLAG(a, template)) { if(GET_FLAG(a, union)) { - if(a->e->def->stmt) { - if(GET_FLAG(a, pure)) - free_decl_list(gwion->mp, a->e->def->list); - else { + if(a->e->def->stmt && !GET_FLAG(a, pure)) { // <=> decl_list UNSET_FLAG(&a->e->def->stmt->d.stmt_union, global); free_stmt(gwion->mp, a->e->def->stmt); - } } a->e->def->stmt = NULL; } @@ -27,6 +23,10 @@ ANN static void free_type(Type a, Gwion gwion) { } if(a->nspc) REM_REF(a->nspc, gwion); + if(a->e->contains.ptr) + vector_release(&a->e->contains); +// TODO: commenting this should not happen +// mp_free(gwion->mp, TypeInfo, a->e); mp_free(gwion->mp, Type, a); } diff --git a/src/parse/check.c b/src/parse/check.c index 8ec65bec..3b5a745c 100644 --- a/src/parse/check.c +++ b/src/parse/check.c @@ -367,6 +367,13 @@ ANN2(1,2) static Func find_func_match_actual(const Env env, Func func, const Exp CHECK_OO(func->next); return find_func_match_actual(env, func->next, args, implicit, specific); } + if(e1->type == t_undefined) { + if(func->value_ref->owner_class) + CHECK_BO(template_push_types(env, func->value_ref->owner_class->e->def->base.tmpl)) + e1->type = known_type(env, e1->td); + if(func->value_ref->owner_class) + nspc_pop_type(env->gwion->mp, env->curr); + } if(func_match_inner(env, e, e1->type, implicit, specific) < 0) break; e = e->next; @@ -394,7 +401,7 @@ ANN static m_bool check_call(const Env env, const Exp_Call* exp) { if(et != ae_exp_primary && et != ae_exp_dot && et != ae_exp_cast) ERR_B(exp->func->pos, "invalid expression for function call.") CHECK_OB(check_exp(env, exp->func)) - return exp->args ? !!check_exp(env, exp->args) : -1; + return exp->args ? !!check_exp(env, exp->args) : GW_OK; } ANN static inline Value template_get_ready(const Env env, const Value v, const m_str tmpl, const m_uint i) { @@ -403,69 +410,111 @@ ANN static inline Value template_get_ready(const Env env, const Value v, const m nspc_lookup_value1(v->owner, sym); } +static Func ensure_tmpl(const Env env, const Func f, const Exp_Call *exp) { + nspc_pop_type(env->gwion->mp, env->curr); + if(check_call(env, exp) > 0) { + const Func next = f->next; + f->next = NULL; + const Func func = find_func_match(env, f, exp->args); + f->next = next; + if(func) { + SET_FLAG(func, checked | ae_flag_template); + return func; + } + } + return NULL; +} +ANN static m_bool check_func_args(const Env env, Arg_List arg_list) { + do { + const Var_Decl decl = arg_list->var_decl; + const Value v = decl->value; + if(arg_list->td && !arg_list->td->xid) + arg_list->type = v->type = check_td(env, arg_list->td); + if(isa(v->type, t_object) > 0 || isa(v->type, t_function) > 0) + UNSET_FLAG(env->func, pure); + CHECK_BB(already_defined(env, decl->xid, decl->pos)) + SET_FLAG(v, checked); + nspc_add_value(env->curr, decl->xid, v); + } while((arg_list = arg_list->next)); + return GW_OK; +} + ANN static Func _find_template_match(const Env env, const Value v, const Exp_Call* exp) { - const Exp args = exp->args; const Type_List types = exp->tmpl->call; - Func m_func = exp->m_func, former = env->func; -if(types->td->types)exit(12); + Func m_func = NULL, former = env->func; const m_str tmpl_name = tl2str(env, types); - const m_uint sz = vector_size((Vector)env->curr->info->type); const m_uint scope = env_push(env, v->owner_class, v->owner); + if(isa(actual_type(v->type), t_fptr) > 0) { + const Symbol sym = func_symbol(env, v->owner->name, v->name, tmpl_name, 0); + const Value value = nspc_lookup_value1(v->owner, sym); + Func_Def base = v->d.func_ref->def; + struct Func_Base_ *fbase = /*value ? value->type->e->d.func->def :*/ + new_func_base(env->gwion->mp, base->base->td, sym, base->base->args); + fbase->tmpl = new_tmpl(env->gwion->mp, base->base->tmpl->list, 0); + fbase->tmpl->call = types; + CHECK_BO(template_push_types(env, fbase->tmpl)) + const Stmt stmt = new_stmt_fptr(env->gwion->mp, fbase, base->flag); + if(value) { + stmt->d.stmt_fptr.type = actual_type(value->type); + stmt->d.stmt_fptr.value = value; + } + CHECK_BO(traverse_stmt_fptr(env, &stmt->d.stmt_fptr)) + free_stmt(env->gwion->mp, stmt); + CHECK_OO((base->base->ret_type = known_type(env, base->base->td))) + if(exp->args) + CHECK_OO(check_exp(env, exp->args)) + const Func func = find_func_match(env, fbase->func, exp->args); + // nspc_pop_type(env->gwion->mp, env->curr); + // env_pop(env, scope); + if(!value) + map_set(&v->owner->info->type->map, (vtype)sym, (vtype)actual_type(func->value_ref->type)); + xfree(tmpl_name); + env->func = former; + return func; + } for(m_uint i = 0; i < v->offset + 1; ++i) { - Func_Def def = NULL; + Func_Def fdef = NULL; Func_Def base = NULL; Value value = template_get_ready(env, v, tmpl_name, i); if(value) { if(env->func == value->d.func_ref) { - free(tmpl_name); CHECK_BO(check_call(env, exp)) - return env->func; + m_func = env->func; + break; } - base = def = value->d.func_ref->def; - if(!def->base->tmpl) { + base = fdef = value->d.func_ref->def; + if(!fdef->base->tmpl) { if(!(value = template_get_ready(env, v, "template", i))) continue; base = value->d.func_ref->def; - def->base->tmpl = new_tmpl(env->gwion->mp, base->base->tmpl->list, (m_int)i); + fdef->base->tmpl = new_tmpl(env->gwion->mp, base->base->tmpl->list, (m_int)i); } } else { if(!(value = template_get_ready(env, v, "template", i))) continue; base = value->d.func_ref->def; - def = new_func_def(env->gwion->mp, new_func_base(env->gwion->mp, base->base->td, insert_symbol(v->name), + fdef = new_func_def(env->gwion->mp, new_func_base(env->gwion->mp, base->base->td, insert_symbol(v->name), base->base->args), base->d.code, base->flag, loc_cpy(env->gwion->mp, base->pos)); - def->base->tmpl = new_tmpl(env->gwion->mp, base->base->tmpl->list, (m_int)i); - SET_FLAG(def, template); - } - def->base->tmpl->call = types; - if(traverse_func_template(env, def) > 0) { - nspc_pop_type(env->gwion->mp, env->curr); - if(check_call(env, exp) > 0) { - const Func next = def->base->func->next; - def->base->func->next = NULL; - m_func = find_func_match(env, def->base->func, args); - def->base->func->next = next; - if(m_func) { - SET_FLAG(m_func, checked | ae_flag_template); - goto end; - } - } + fdef->base->tmpl = new_tmpl(env->gwion->mp, base->base->tmpl->list, (m_int)i); + SET_FLAG(fdef, template); } - if(sz != vector_size((Vector)env->curr->info->type)) - nspc_pop_type(env->gwion->mp, env->curr); - SET_FLAG(base, template); + fdef->base->tmpl->call = types; + if(traverse_func_template(env, fdef) > 0 && + (m_func = ensure_tmpl(env, fdef->base->func, exp))) + break; } -end: - free(tmpl_name); + xfree(tmpl_name); env_pop(env, scope); env->func = former; return m_func; } + ANN Func find_template_match(const Env env, const Value value, const Exp_Call* exp) { Type t = value->owner_class; const Func f = _find_template_match(env, value, exp); - if(f) + if(f) { return f; + } while(t) { Value v = nspc_lookup_value1(t->nspc, value->d.func_ref->def->base->xid); if(!v) @@ -963,7 +1012,7 @@ ANN m_bool check_stmt_union(const Env env, const Stmt_Union stmt) { if(isa(l->self->type, t_object) > 0) { if(!GET_FLAG(l->self->d.exp_decl.td, ref) && !GET_FLAG(stmt->type, template)) ERR_B(l->self->pos, "In union, Objects must be declared as reference (use '@')") - SET_FLAG(l->self->d.exp_decl.td, ref); +// SET_FLAG(l->self->d.exp_decl.td, ref); Var_Decl_List list = l->self->d.exp_decl.list; do SET_FLAG(list->self->value, pure); while((list = list->next)); @@ -1046,21 +1095,6 @@ ANN static m_bool check_parent_match(const Env env, const Func_Def f) { return GW_OK; } -ANN static m_bool check_func_args(const Env env, Arg_List arg_list) { - do { - const Var_Decl decl = arg_list->var_decl; - const Value v = decl->value; - if(arg_list->td && !arg_list->td->xid) - arg_list->type = v->type = check_td(env, arg_list->td); - if(isa(v->type, t_object) > 0 || isa(v->type, t_function) > 0) - UNSET_FLAG(env->func, pure); - CHECK_BB(already_defined(env, decl->xid, decl->pos)) - SET_FLAG(v, checked); - nspc_add_value(env->curr, decl->xid, v); - } while((arg_list = arg_list->next)); - return GW_OK; -} - ANN static inline Func get_overload(const Env env, const Func_Def def, const m_uint i) { const Symbol sym = func_symbol(env, env->curr->name, s_name(def->base->xid), NULL, i); return nspc_lookup_func1(env->curr, sym); @@ -1136,7 +1170,8 @@ ANN m_bool check_func_def(const Env env, const Func_Def f) { ret = check_func_args(env, f->base->args); if(ret > 0) { const Value variadic = GET_FLAG(f, variadic) ? set_variadic(env) : NULL; - if(!GET_FLAG(f, builtin) && check_stmt_code(env, &f->d.code->d.stmt_code) < 0) + if(!GET_FLAG(f, builtin) && f->d.code && + check_stmt_code(env, &f->d.code->d.stmt_code) < 0) ret = GW_ERROR; if(variadic) REM_REF(variadic, env->gwion) diff --git a/src/parse/scan1.c b/src/parse/scan1.c index bad13338..106390d0 100644 --- a/src/parse/scan1.c +++ b/src/parse/scan1.c @@ -15,9 +15,6 @@ ANN static m_bool scan1_stmt_list(const Env env, Stmt_List list); ANN static m_bool scan1_stmt(const Env env, Stmt stmt); ANN static Type void_type(const Env env, const Type_Decl* td) { -// could be more precise - if(SAFE_FLAG(env->class_def, template) && td->types) - return t_undefined; const Type t = known_type(env, td); CHECK_OO(t) if(t->size) @@ -25,25 +22,47 @@ ANN static Type void_type(const Env env, const Type_Decl* td) { ERR_O(td_pos(td), "cannot declare variables of size '0' (i.e. 'void')...") } + +ANN static inline Type get_base_type(const Env env, const Type t) { + const m_str decl_name = get_type_name(env, t->name, 0); + return nspc_lookup_type1(env->curr, insert_symbol(decl_name)); +} + +ANN static m_bool type_recursive(const Env env, Exp_Decl* decl, const Type t) { + const Type decl_base = get_base_type(env, t); + const Type base = get_base_type(env, env->class_def); + if(decl_base && base) { + if(!base->e->contains.ptr) + vector_init(&base->e->contains); + vector_add(&base->e->contains, (vtype)decl_base); + if(decl_base->e->contains.ptr) { + for(m_uint i = 0; i < vector_size(&decl_base->e->contains); ++i) { + if(base == (Type)vector_at(&decl_base->e->contains, i) && !GET_FLAG(decl->td, ref)) + ERR_B(exp_self(decl)->pos, "%s declared inside %s\n. (make it a ref ?)", + decl_base->name, decl_base == base ? "itself" : base->name); + } + } + } + return GW_OK; +} + ANN static Type scan1_exp_decl_type(const Env env, Exp_Decl* decl) { const Type t = void_type(env, decl->td); CHECK_OO(t); if(decl->td->xid && decl->td->xid->xid == insert_symbol("auto") && decl->type) return decl->type; + if(!env->scope->depth && env->class_def) { + if(isa(t, t_object) > 0) + CHECK_BO(type_recursive(env, decl, t)) + if(!GET_FLAG(decl->td, static)) + SET_FLAG(decl->td, member); + } if(GET_FLAG(t, abstract) && !GET_FLAG(decl->td, ref)) ERR_O(exp_self(decl)->pos, "Type '%s' is abstract, declare as ref. (use @)", t->name) if(GET_FLAG(t, private) && t->e->owner != env->curr) ERR_O(exp_self(decl)->pos, "can't use private type %s", t->name) if(GET_FLAG(t, protect) && (!env->class_def || isa(t, env->class_def) < 0)) ERR_O(exp_self(decl)->pos, "can't use protected type %s", t->name) - if(env->class_def) { - if(!env->scope->depth) { - if(!GET_FLAG(decl->td, ref) && t == env->class_def) - ERR_O(exp_self(decl)->pos, "...(note: object of type '%s' declared inside itself)", t->name) - if(!GET_FLAG(decl->td, static)) - SET_FLAG(decl->td, member); - } - } decl->base = t->e->def; return decl->type = t; } @@ -303,7 +322,7 @@ ANN m_bool scan1_func_def(const Env env, const Func_Def fdef) { CHECK_OB((fdef->base->ret_type = known_type(env, fdef->base->td))) if(fdef->base->args) CHECK_BB(scan1_args(env, fdef->base->args)) - if(!GET_FLAG(fdef, builtin)) + if(!GET_FLAG(fdef, builtin) && fdef->d.code) CHECK_BB(scan1_stmt_code(env, &fdef->d.code->d.stmt_code)) env->func = former; --env->scope->depth; diff --git a/src/parse/scan2.c b/src/parse/scan2.c index bc4e999e..7fba103e 100644 --- a/src/parse/scan2.c +++ b/src/parse/scan2.c @@ -20,22 +20,21 @@ ANN static m_bool scan2_stmt_list(const Env, Stmt_List); ANN static m_bool scan2_exp_decl_template(const Env env, const Exp_Decl* decl) { CHECK_BB(scan1_cdef(env, decl->type->e->def)) - CHECK_BB(scan2_cdef(env, decl->type->e->def)) - return GW_OK; + return scan2_cdef(env, decl->type->e->def); } ANN m_bool scan2_exp_decl(const Env env, const Exp_Decl* decl) { - Var_Decl_List list = decl->list; + const m_bool global = GET_FLAG(decl->td, global); + const m_uint scope = !global ? env->scope->depth : env_push_global(env); const Type type = decl->type; if(GET_FLAG(type, template) && !GET_FLAG(type, scan2)) CHECK_BB(scan2_exp_decl_template(env, decl)) - const m_bool global = GET_FLAG(decl->td, global); - const m_uint scope = !global ? env->scope->depth : env_push_global(env); + Var_Decl_List list = decl->list; do { const Var_Decl var = list->self; - const Array_Sub array = var->array; - if(array && array->exp) - CHECK_BB(scan2_exp(env, array->exp)) + const Exp array = var->array ? var->array->exp : NULL; + if(array) + CHECK_BB(scan2_exp(env, array)) nspc_add_value(env->curr, var->xid, var->value); } while((list = list->next)); if(global) @@ -92,6 +91,7 @@ ANN m_bool scan2_stmt_fptr(const Env env, const Stmt_Fptr ptr) { ptr->value->d.func_ref = ptr->base->func; ptr->base->func->value_ref = ptr->value; ptr->type->e->d.func = ptr->base->func; + def->base->tmpl = ptr->base->tmpl; SET_FLAG(ptr->value, func | ae_flag_checked); if(ptr->base->args) CHECK_BB(scan2_args(env, def)) @@ -301,8 +301,10 @@ ANN static m_bool scan2_stmt_list(const Env env, Stmt_List list) { ANN static m_bool scan2_func_def_overload(const Env env, const Func_Def f, const Value overload) { const m_bool base = tmpl_base(f->base->tmpl); const m_bool tmpl = GET_FLAG(overload, template); - if(isa(overload->type, t_function) < 0 || isa(overload->type, t_fptr) > 0) + if(isa(overload->type, t_function) < 0 || isa(overload->type, t_fptr) > 0) { + if(isa(actual_type(overload->type), t_function) < 0) ERR_B(f->pos, "function name '%s' is already used by another value", overload->name) +} if((!tmpl && base) || (tmpl && !base && !GET_FLAG(f, template))) ERR_B(f->pos, "must overload template function with template") return GW_OK; @@ -387,6 +389,7 @@ ANN2(1, 2) static m_bool scan2_func_def_template(const Env env, const Func_Def f func->vt_index = i; ADD_REF(value) nspc_add_value(env->curr, f->base->xid, value); + nspc_add_func(env->curr, f->base->xid, func); } else func->vt_index = ++overload->offset; return GW_OK; @@ -467,7 +470,7 @@ ANN static m_str func_tmpl_name(const Env env, const Func_Def f) { } -ANN2(1,2,4) static Value func_create(const Env env, const Func_Def f, +ANN2(1,2,4) /*static */Value func_create(const Env env, const Func_Def f, const Value overload, const m_str name) { const Func func = scan_new_func(env, f, name); nspc_add_func(env->curr, insert_symbol(func->name), func); @@ -531,7 +534,7 @@ ANN m_bool scan2_func_def(const Env env, const Func_Def f) { // body if(f->base->args) CHECK_BB(scan2_args(env, f)) - if(!GET_FLAG(f, builtin) && f->d.code->d.stmt_code.stmt_list) + if(!GET_FLAG(f, builtin) && f->d.code) CHECK_BB(scan2_func_def_code(env, f)) // gpop if(GET_FLAG(f, global)) diff --git a/src/parse/template.c b/src/parse/template.c index b1e7d178..081a4bd6 100644 --- a/src/parse/template.c +++ b/src/parse/template.c @@ -73,8 +73,11 @@ ANN static size_t template_size(const Env env, struct tmpl_info* info) { ID_List base = info->cdef->base.tmpl->list; Type_List call = info->call; size_t size = tmpl_set(info, info->cdef->base.type); - do size += tmpl_set(info, type_decl_resolve(env, call->td)); - while((call = call->next) && (base = base->next) && ++size); + do { + const Type t = type_decl_resolve(env, call->td); + CHECK_OB(t) + size += tmpl_set(info, t); + } while((call = call->next) && (base = base->next) && ++size); return size + 16 + 3; } @@ -114,6 +117,8 @@ ANN m_bool template_match(ID_List base, Type_List call) { ANN static Class_Def template_class(const Env env, const Class_Def def, const Type_List call) { const Symbol name = template_id(env, def, call); + if(env->class_def && name == insert_symbol(env->class_def->name)) + return env->class_def->e->def; const Type t = nspc_lookup_type1(env->curr, name); return t ? t->e->def : new_class_def(env->gwion->mp, def->flag, name, def->base.ext, def->body, loc_cpy(env->gwion->mp, def->pos)); @@ -157,9 +162,11 @@ ANN Type scan_type(const Env env, const Type t, const Type_Decl* type) { return a->base.type; a->base.tmpl = new_tmpl(env->gwion->mp, get_total_type_list(env, t), 0); a->base.tmpl->call = type->types; - if(isa(t, t_union) < 0) + if(isa(t, t_union) < 0) { CHECK_BO(scan0_class_def(env, a)) - else { + map_set(&t->e->owner->info->type->map, (vtype)insert_symbol(a->base.type->name), + (vtype)a->base.type); + } else { a->stmt = new_stmt_union(env->gwion->mp, (Decl_List)a->body, t->e->def->pos); a->stmt->d.stmt_union.type_xid = a->base.xid; CHECK_BO(scan0_stmt_union(env, &a->stmt->d.stmt_union)) @@ -177,8 +184,6 @@ ANN Type scan_type(const Env env, const Type t, const Type_Decl* type) { SET_FLAG(a->base.type, dtor); ADD_REF(t->nspc->dtor) } -// nspc_add_type(t->e->owner, insert_symbol(a->base.type->name), a->base.type); - map_set(&t->e->owner->info->type->map, insert_symbol(a->base.type->name), a->base.type); return a->base.type; } else if(type->types) ERR_O(type->xid->pos, diff --git a/src/parse/traverse.c b/src/parse/traverse.c index 637d93e3..00ee4ce5 100644 --- a/src/parse/traverse.c +++ b/src/parse/traverse.c @@ -40,7 +40,7 @@ ANN m_bool traverse_stmt_enum(const Env env, const Stmt_Enum def) { } ANN m_bool traverse_stmt_fptr(const Env env, const Stmt_Fptr def) { - CHECK_BB(scan0_stmt_fptr(env, def)) +// CHECK_BB(scan0_stmt_fptr(env, def)) CHECK_BB(scan1_stmt_fptr(env, def)) return scan2_stmt_fptr(env, def); // CHECK_BB(check_stmt_fptr(env, def)) diff --git a/src/parse/traverse_template.c b/src/parse/traverse_template.c index 8b32476f..1a49596a 100644 --- a/src/parse/traverse_template.c +++ b/src/parse/traverse_template.c @@ -10,5 +10,8 @@ ANN m_bool traverse_func_template(const Env env, const Func_Def def) { CHECK_BB(template_push_types(env, def->base->tmpl)) - return traverse_func_def(env, def); + if(traverse_func_def(env, def) > 0) + return GW_OK; + nspc_pop_type(env->gwion->mp, env->curr); + return GW_ERROR; } diff --git a/src/vm/vm.c b/src/vm/vm.c index 51237539..11610db1 100644 --- a/src/vm/vm.c +++ b/src/vm/vm.c @@ -301,7 +301,7 @@ ANN void vm_run(const VM* vm) { // lgtm [cpp/use-of-goto] do { register Instr instr; DISPATCH(); regsetimm: - *(m_uint*)reg = instr->m_val; + *(m_uint*)(reg + (m_int)instr->m_val2) = instr->m_val; DISPATCH(); regpushimm: *(m_uint*)reg = instr->m_val; diff --git a/tests/error/ptr_assign_other.gw b/tests/error/ptr_assign_other.gw index cdbf537d..7f18d51a 100644 --- a/tests/error/ptr_assign_other.gw +++ b/tests/error/ptr_assign_other.gw @@ -1,4 +1,4 @@ -// [contains] can't assign member function to member function pointer of an other class +// [contains] can't assign member function to a pointer of an other class class C { typedef void Test(); Test test; -- 2.43.0