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 &&
- is_fptr(v->type))
+ if(isa(v->type, t_class) > 0 && is_fptr(v->type))
return emit->env->scope->depth;
const m_uint scope = emit_push(emit, v->owner_class, v->owner);
CHECK_BB(traverse_func_def(emit->env, f->def))
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);
+ size_t slen = strlen(f->value_ref->owner->name);
+ assert(len > slen);
+ size_t sz = len - slen;
char c[sz + 1];
memcpy(c, f->name, sz);
c[sz] = '\0';
static OP_CHECK(opck_fptr_at) {
Exp_Binary* bin = (Exp_Binary*)data;
+ if(bin->rhs->type->e->d.func->def->base->tmpl &&
+ bin->rhs->type->e->d.func->def->base->tmpl->call) {
+ struct FptrInfo info = { bin->lhs->type->e->d.func, bin->rhs->type->e->parent->e->d.func,
+ bin->lhs, exp_self(bin)->pos };
+ CHECK_BO(fptr_do(env, &info))
+ bin->rhs->emit_var = 1;
+ return bin->rhs->type;
+}
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))
dt->owner = f->value_ref->owner;
dt->owner_class = f->value_ref->owner_class;
if(traverse_dot_tmpl(emit, dt) > 0) {
+ if(GET_FLAG(f, member)) // TODO: CHECK ME
+ shred->reg += SZ_INT; else
if(GET_FLAG(def, static))
shred->reg -= SZ_INT;
*(VM_Code*)(shred->reg -SZ_INT) = def->base->func->code;
return;
- }
+ } else
+ Except(shred, "TemplateException");
}
INSTR(DotTmpl) {
if(is_fptr(v->type)) {
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;
+ Func_Def base = v->d.func_ref ? v->d.func_ref->def : exp->func->type->e->d.func->def;
struct Func_Base_ *fbase = 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;
m_func = find_func_match(env, fbase->func, exp->args);
nspc_pop_type(env->gwion->mp, env->curr);
if(!value && m_func) {
-printf("m_func %p\n", m_func);
-if(!m_func->def->base->ret_type)
-CHECK_BO(traverse_func_def(env, m_func->def))
+ if(!m_func->def->base->ret_type)
+ CHECK_BO(traverse_func_def(env, m_func->def))
map_set(&v->owner->info->type->map, (vtype)sym, (vtype)actual_type(m_func->value_ref->type));
-}
+ }
}
free_stmt(env->gwion->mp, stmt);
}
const Func f = find_template_match(env, v, func);
if(f) {
Tmpl* tmpl = new_tmpl_call(env->gwion->mp, func->tmpl->call);
- tmpl->list = v->d.func_ref->def->base->tmpl->list;
+ tmpl->list = v->d.func_ref ? v->d.func_ref->def->base->tmpl->list : func->func->type->e->d.func->def->base->tmpl->list;
((Exp_Call*)func)->tmpl = tmpl;
return ((Exp_Call*)func)->m_func = f;
}
const Exp args = exp->args;
m_uint args_number = 0;
DECL_OO(const Value, value, = nspc_lookup_value1(call->type->e->owner, insert_symbol(call->type->name)))
- const m_uint type_number = get_type_number(value->d.func_ref->def->base->tmpl->list);
+ Tmpl *tm = value->d.func_ref ? value->d.func_ref->def->base->tmpl : call->type->e->d.func->def->base->tmpl;
+ const m_uint type_number = get_type_number(tm->list);
Type_List tl[type_number];
- ID_List list = value->d.func_ref->def->base->tmpl->list;
+ ID_List list = tm->list;
+ if(tm->call) {
+ if(!value->d.func_ref) {
+ Tmpl tmpl = { .call=tm->call };
+ ((Exp_Call*)exp)->tmpl = &tmpl;
+ DECL_OO(const Func,func, = get_template_func(env, exp, value))
+ assert(func->def->base->ret_type);
+ value->d.func_ref = func;
+ return func->def->base->ret_type;
+ } else {
+ const Func func = value->d.func_ref;
+ if(!func->def->base->ret_type) { // template fptr
+ const m_uint scope = env_push(env, value->owner_class, value->owner);
+ CHECK_BO(traverse_func_def(env, func->def))
+ env_pop(env, scope);
+ }
+ ((Exp_Call*)exp)->m_func = func;
+ return func->def->base->ret_type;
+ }
+ }
while(list) {
Arg_List arg = value->d.func_ref->def->base->args;
Exp template_arg = args;
DECL_OO(const Func,func, = get_template_func(env, exp, value))
if(!func->def->base->ret_type) // template fptr
CHECK_BO(traverse_func_def(env, func->def))
- return func->def->base->ret_type;
+ return func->def->base->ret_type;
}
ANN static m_bool check_exp_call1_check(const Env env, const Exp exp) {
return t;
}
+ANN static m_bool predefined_call(const Env env, const Type t, const loc_t pos) {
+ const m_str str = tl2str(env, t->e->d.func->def->base->tmpl->call);
+ env_err(env, pos, _("Type '%s' has '%s' as pre-defined types."),
+ t->name, str);
+ free_mstr(env->gwion->mp, str);
+ if(GET_FLAG(t, typedef)) {
+ loc_header(t->e->d.func->def->pos, env->name);
+ gw_err(_("from definition:\n"));
+ loc_err(t->e->d.func->def->pos, env->name);
+ }
+ return GW_ERROR;
+}
+
ANN static Type check_exp_call(const Env env, Exp_Call* exp) {
if(exp->tmpl) {
CHECK_OO(check_exp(env, exp->func))
const Type t = actual_type(exp->func->type);
const Value v = nspc_lookup_value1(t->e->owner, insert_symbol(t->name));
if(!v)
- ERR_O(exp_self(exp)->pos, _(" template call of non-existant function."))
- if(!GET_FLAG(v, func))
+ ERR_O(exp_self(exp)->pos, _("template call of non-existant function."))
+ if(!GET_FLAG(v, func) && !GET_FLAG(exp->func->type, func))
ERR_O(exp_self(exp)->pos, _("template call of non-function value."))
if(!v->d.func_ref->def->base->tmpl)
ERR_O(exp_self(exp)->pos, _("template call of non-template function."))
+ if(t->e->d.func->def->base->tmpl->call)
+ CHECK_BO(predefined_call(env, t, exp_self(exp)->pos))
const Func ret = find_template_match(env, v, exp);
CHECK_OO((exp->m_func = ret))
return ret->def->base->ret_type;
}
ANN m_bool check_stmt_type(const Env env, const Stmt_Type stmt) {
- return stmt->type->e->def ? check_class_def(env, stmt->type->e->def) : 1;
+ return stmt->type->e->def ? check_class_def(env, stmt->type->e->def) : GW_OK;
}
ANN static Type check_exp_lambda(const Env env NUSED,
const Exp_If* exp_if NUSED) { return t_lambda; }
return already_defined(env, s, pos);
}
+static void fptr_def(const Env env, const Stmt_Fptr stmt) {
+ const Func_Def def = new_func_def(env->gwion->mp, new_func_base(env->gwion->mp, stmt->base->td, stmt->base->xid, stmt->base->args),
+ NULL,stmt->base->td->flag, loc_cpy(env->gwion->mp, stmt_self(stmt)->pos));
+ stmt->base->func = new_func(env->gwion->mp, s_name(stmt->base->xid), def);
+ stmt->value->d.func_ref = stmt->base->func;
+ stmt->base->func->value_ref = stmt->value;
+ stmt->type->e->d.func = stmt->base->func;
+ def->base->tmpl = stmt->base->tmpl;
+ def->base->func = stmt->base->func;
+}
+
ANN m_bool scan0_stmt_fptr(const Env env, const Stmt_Fptr stmt) {
CHECK_BB(env_access(env, stmt->base->td->flag, stmt_self(stmt)->pos))
CHECK_BB(scan0_defined(env, stmt->base->xid, td_pos(stmt->base->td)));
t->flag = stmt->base->td->flag;
stmt->type = t;
stmt->value = mk_class(env, t);
+ stmt->value->owner = env->curr;
+ stmt->value->owner_class = env->class_def;
+ fptr_def(env, stmt);
+ SET_FLAG(stmt->value, func);
add_type(env, t->e->owner, t);
return GW_OK;
}
+ANN static void typedef_simple(const Env env, const Stmt_Type stmt, const Type base) {
+ const Type t = new_type(env->gwion->mp, ++env->scope->type_xid, s_name(stmt->xid), base);
+ t->size = base->size;
+ const Nspc nspc = (!env->class_def && GET_FLAG(stmt->ext, global)) ?
+ env->global_nspc : env->curr;
+ add_type(env, nspc, t);
+ t->e->owner = nspc;
+ stmt->type = t;
+ t->flag = stmt->ext->flag | ae_flag_checked;
+ if(stmt->ext->array && !stmt->ext->array->exp)
+ SET_FLAG(t, empty);
+}
+
+ANN static void typedef_complex(const Env env, const Stmt_Type stmt, const Type base) {
+ const ae_flag flag = base->e->def ? base->e->def->flag : 0;
+ const Class_Def cdef = new_class_def(env->gwion->mp, flag, stmt->xid, stmt->ext, NULL,
+ loc_cpy(env->gwion->mp, td_pos(stmt->ext)));
+ CHECK_BB(scan0_class_def(env, cdef))
+ stmt->type = cdef->base.type;
+ cdef->base.tmpl = stmt->tmpl;
+}
+
+ANN static void typedef_fptr(const Env env, const Stmt_Type stmt, const Type base) {
+ stmt->type = type_copy(env->gwion->mp, base);
+ stmt->type->name = s_name(stmt->xid);
+ stmt->type->e->parent = base;
+ add_type(env, env->curr, stmt->type);
+ mk_class(env, stmt->type);
+ if(base->e->d.func->def->base->tmpl)
+ SET_FLAG(stmt->type, func);
+}
+
ANN m_bool scan0_stmt_type(const Env env, const Stmt_Type stmt) {
CHECK_BB(env_access(env, stmt->ext->flag, stmt_self(stmt)->pos))
DECL_OB(const Type, base, = stmt->tmpl ? find_type(env, stmt->ext->xid) : known_type(env, stmt->ext))
CHECK_BB(scan0_defined(env, stmt->xid, td_pos(stmt->ext)))
- if(!stmt->ext->types && (!stmt->ext->array || !stmt->ext->array->exp)) {
- const Type t = new_type(env->gwion->mp, ++env->scope->type_xid, s_name(stmt->xid), base);
- t->size = base->size;
- const Nspc nspc = (!env->class_def && GET_FLAG(stmt->ext, global)) ?
- env->global_nspc : env->curr;
- add_type(env, nspc, t);
- t->e->owner = nspc;
- stmt->type = t;
- t->flag = stmt->ext->flag | ae_flag_checked;
- if(stmt->ext->array && !stmt->ext->array->exp)
- SET_FLAG(t, empty);
- } else {
- const ae_flag flag = base->e->def ? base->e->def->flag : 0;
- const Class_Def cdef = new_class_def(env->gwion->mp, flag, stmt->xid, stmt->ext, NULL,
- loc_cpy(env->gwion->mp, td_pos(stmt->ext)));
- CHECK_BB(scan0_class_def(env, cdef))
- stmt->type = cdef->base.type;
- cdef->base.tmpl = stmt->tmpl;
- }
+ if(isa(base, t_function) < 0) {
+ if(!stmt->ext->types && (!stmt->ext->array || !stmt->ext->array->exp))
+ typedef_simple(env, stmt, base);
+ else
+ typedef_complex(env, stmt, base);
+ } else
+ typedef_fptr(env, stmt, base);
SET_FLAG(stmt->type, typedef);
return GW_OK;
}
ANN m_bool scan1_stmt_type(const Env env, const Stmt_Type stmt) {
if(!stmt->type)
CHECK_BB(scan0_stmt_type(env, stmt))
- return stmt->type->e->def ? scan1_class_def(env, stmt->type->e->def) : 1;
+ return stmt->type->e->def ? scan1_class_def(env, stmt->type->e->def) : GW_OK;
}
ANN m_bool scan1_stmt_union(const Env env, const Stmt_Union stmt) {
#include "nspc.h"
#include "operator.h"
-//ANN /* static */ m_bool scan2_exp(const Env, const Exp);
ANN static m_bool scan2_stmt(const Env, const Stmt);
ANN static m_bool scan2_stmt_list(const Env, Stmt_List);
}
ANN m_bool scan2_stmt_fptr(const Env env, const Stmt_Fptr ptr) {
- const Func_Def def = new_func_def(env->gwion->mp, new_func_base(env->gwion->mp, ptr->base->td, ptr->base->xid, ptr->base->args),
- NULL,ptr->base->td->flag, loc_cpy(env->gwion->mp, stmt_self(ptr)->pos));
- def->base->ret_type = ptr->base->ret_type;
- ptr->base->func = new_func(env->gwion->mp, s_name(ptr->base->xid), def);
- 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->tmpl)//
- if(ptr->base->args)
- CHECK_BB(scan2_args(env, def))
+ const Func_Def def = ptr->type->e->d.func->def;
+ if(!ptr->base->tmpl) {
+ def->base->ret_type = ptr->base->ret_type;
+ if(ptr->base->args)
+ CHECK_BB(scan2_args(env, def))
+ }
if(env->class_def) {
if(GET_FLAG(ptr->base->td, global)) {
SET_FLAG(ptr->value, global);
}
ANN m_bool scan2_stmt_type(const Env env, const Stmt_Type stmt) {
- return stmt->type->e->def ? scan2_class_def(env, stmt->type->e->def) : 1;
+ return stmt->type->e->def ? scan2_class_def(env, stmt->type->e->def) : GW_OK;
}
ANN static inline Value prim_value(const Env env, const Symbol s) {
#include "vm.h"
#include "env.h"
#include "type.h"
+#include "func.h"
+#include "value.h"
#include "nspc.h"
#include "traverse.h"
#include "template.h"
return list;
}
-ANN static ID_List get_total_type_list(const Env env, const Type t) {
+ANN2(1,2) static ID_List get_total_type_list(const Env env, const Type t, const Tmpl *tmpl) {
const Type parent = owner_type(env, t);
if(!parent)
- return t->e->def->base.tmpl ? t->e->def->base.tmpl->list : NULL;
+ return tmpl ? tmpl->list : NULL;
const Vector v = get_types(env, parent);
const ID_List base = (ID_List)vector_pop(v);
if(!base) {
free_vector(env->gwion->mp, v);
- return t->e->def->base.tmpl ? t->e->def->base.tmpl->list : NULL;
+ return tmpl ? tmpl->list : NULL;
}
const ID_List types = id_list_copy(env->gwion->mp, base);
ID_List list, tmp = types;
list = (ID_List)vector_pop(v);
tmp = (tmp->next = id_list_copy(env->gwion->mp, list));
}
- tmp->next = t->e->def->base.tmpl->list;
+ tmp->next = tmpl->list;
free_vector(env->gwion->mp, v);
return types;
}
extern ANN m_bool traverse_func_def(const Env, const Func_Def);
extern ANN m_bool traverse_class_def(const Env, const Class_Def);
+ANN Tmpl* mk_tmpl(const Env env, const Type t, const Tmpl *tm, const Type_List types) {
+ Tmpl *tmpl = new_tmpl(env->gwion->mp, get_total_type_list(env, t, tm), 0);
+ tmpl->call = types;
+ return tmpl;
+}
+
ANN Type scan_type(const Env env, const Type t, const Type_Decl* type) {
if(GET_FLAG(t, template)) {
if(GET_FLAG(t, ref))
SET_FLAG(a, ref);
if(a->base.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;
+ a->base.tmpl = mk_tmpl(env, t, t->e->def->base.tmpl, type->types);
if(isa(t, t_union) < 0) {
CHECK_BO(scan0_class_def(env, a))
map_set(&t->e->owner->info->type->map, (vtype)a->base.xid, (vtype)a->base.type);
ADD_REF(t->nspc->dtor)
}
return a->base.type;
- } else if(type->types)
- ERR_O(type->xid->pos,
- _("type '%s' is not template. You should not provide template types"), t->name)
+ } else if(type->types) { // TODO: clean me
+ if(isa(t, t_function) > 0 && t->e->d.func->def->base->tmpl) {
+ const m_str tl_name = tl2str(env, type->types);
+ const Symbol sym = func_symbol(env, t->e->owner->name, t->e->d.func->name, tl_name, 0);
+ free_mstr(env->gwion->mp, tl_name);
+ const Type base_type = nspc_lookup_type1(t->e->owner, sym);
+ if(base_type)
+ return base_type;
+ const Type ret = type_copy(env->gwion->mp, t);
+ ret->e->parent = t;
+ ret->name = s_name(sym);
+ SET_FLAG(ret, func);
+ nspc_add_type(env->curr, sym, ret);
+ const Func_Def def = new_func_def(env->gwion->mp,
+ new_func_base(env->gwion->mp, t->e->d.func->def->base->td, sym, t->e->d.func->def->base->args),
+ NULL, type->flag, loc_cpy(env->gwion->mp, td_pos(type)));
+ const Func func = ret->e->d.func = new_func(env->gwion->mp, s_name(sym), def);
+ const Value value = new_value(env->gwion->mp, ret, s_name(sym));
+ value->d.func_ref = func;
+ value->owner = t->e->owner;
+ value->owner_class = t->e->d.func->value_ref->owner_class;
+ func->value_ref = value;
+ func->def->base->tmpl = mk_tmpl(env, t, t->e->d.func->def->base->tmpl, type->types);
+ def->base->func = func;
+ nspc_add_value(env->curr, sym, value);
+ return ret;
+ }
+ ERR_O(type->xid->pos,
+ _("type '%s' is not template. You should not provide template types"), t->name)
+ }
return t;
}