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_*);
#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;
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);
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;
}
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;
}
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);
}
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;
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;
}
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;
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);
}
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);
}
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;
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;
}
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) {
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;
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,
}
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) {
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;
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) {
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;
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))
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);
}
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) {
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;
if(f) {
if(!f->code) {
dt->def = f->def;//
- dt->owner = t; //
+ dt->owner_class = t; //
if(traverse_dot_tmpl(emit, dt) < 0)
continue;
}
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;
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;
}
#include <stdlib.h>
+#include <string.h>
#include "gwion_util.h"
#include "gwion_ast.h"
#include "oo.h"
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;
}
}
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);
}
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;
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) {
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)
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));
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);
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)
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)
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;
}
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;
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)
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))
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;
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;
}
-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);
// 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))
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;
}
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));
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))
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,
}
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))
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;
}
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;
-// [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;