#include "specialid.h"
#include "tmp_resolve.h"
+struct ResolverArgs {
+ Value v;
+ const Exp_Call *e;
+ m_str tmpl_name;
+ Func m_func;
+ Type_List types;
+};
+
ANN static inline Value template_get_ready(const Env env, const Value v, const m_str tmpl, const m_uint i) {
const Symbol sym = func_symbol(env, v->from->owner->name, v->name, tmpl, i);
return v->from->owner_class ? find_value(v->from->owner_class, sym) :
return NULL;
}
+ANN static Func fptr_match(const Env env, struct ResolverArgs* f_ptr_args) {
+ const Value v = f_ptr_args->v;
+ const m_str tmpl_name = f_ptr_args->tmpl_name;
+ const Exp_Call *exp = f_ptr_args->e;
+ Type_List types = f_ptr_args->types;
+ const Symbol sym = func_symbol(env, v->from->owner->name, v->name, tmpl_name, 0);
+ const Type exists = nspc_lookup_type0(v->from->owner, sym);
+ if(exists)
+ return exists->e->d.func;
+
+ Func m_func = f_ptr_args->m_func;
+ Func_Def base = v->d.func_ref ? v->d.func_ref->def : exp->func->info->type->e->d.func->def;
+ Func_Base *fbase = cpy_func_base(env->gwion->mp, base->base);
+ fbase->xid = sym;
+ fbase->tmpl->base = 0;
+ fbase->tmpl->call = cpy_type_list(env->gwion->mp, types);
+ if(template_push_types(env, fbase->tmpl) > 0) {
+ const Fptr_Def fptr = new_fptr_def(env->gwion->mp, fbase);
+ if(traverse_fptr_def(env, fptr) > 0 &&
+ (base->base->ret_type = known_type(env, base->base->td)) &&
+ (!exp->args || !!check_exp(env, exp->args))) {
+ m_func = find_func_match(env, fbase->func, exp->args);
+ nspc_pop_type(env->gwion->mp, env->curr);
+ if(m_func)
+ nspc_add_type_front(v->from->owner, sym, actual_type(env->gwion, m_func->value_ref->type));
+ }
+ if(fptr->type)
+ REM_REF(fptr->type, env->gwion)
+ free_fptr_def(env->gwion->mp, fptr);
+ }
+ return m_func;
+}
+
+ANN static Func func_match(const Env env, struct ResolverArgs* f_ptr_args) {
+ const Value v = f_ptr_args->v;
+ const m_str tmpl_name = f_ptr_args->tmpl_name;
+ const Exp_Call *exp = f_ptr_args->e;
+ Func m_func = f_ptr_args->m_func;
+ Type_List types = f_ptr_args->types;
+ for(m_uint i = 0; i < v->from->offset + 1; ++i) {
+ const Value exists = template_get_ready(env, v, tmpl_name, i);
+ if(exists) {
+ if(env->func == exists->d.func_ref) {
+ if(check_call(env, exp) < 0 ||
+ !find_func_match(env, env->func, exp->args))
+ continue;
+ m_func = env->func;
+ break;
+ }
+ if((m_func = ensure_tmpl(env, exists->d.func_ref->def, exp)))
+ break;
+ } else {
+ const Value value = template_get_ready(env, v, "template", i);
+ if(!value)
+ continue;
+ if(GET_FLAG(v, builtin)) {
+ SET_FLAG(value, builtin);
+ SET_FLAG(value->d.func_ref, builtin);
+ }
+ const Func_Def fdef = (Func_Def)cpy_func_def(env->gwion->mp, value->d.func_ref->def);
+ SET_FLAG(fdef->base, template);
+ fdef->base->tmpl->call = cpy_type_list(env->gwion->mp, types);
+ fdef->base->tmpl->base = i;
+ if((m_func = ensure_tmpl(env, fdef, exp))) {
+ break;
+ }
+ if(!fdef->base->func) {
+ free_func_def(env->gwion->mp, fdef);
+ }
+ }
+ }
+ return m_func;
+}
+
ANN static Func _find_template_match(const Env env, const Value v, const Exp_Call* exp) {
CHECK_BO(check_call(env, exp))
const Type_List types = exp->tmpl->call;
const m_uint scope = env->scope->depth;
struct EnvSet es = { .env=env, .data=env, .func=(_exp_func)check_cdef,
.scope=scope, .flag=ae_flag_check };
+ struct ResolverArgs f_ptr_args = {.v = v, .e = exp, .tmpl_name = tmpl_name, m_func = m_func, .types = types};
CHECK_BO(envset_push(&es, v->from->owner_class, v->from->owner))
(void)env_push(env, v->from->owner_class, v->from->owner);
if(is_fptr(env->gwion, v->type)) {
- const Symbol sym = func_symbol(env, v->from->owner->name, v->name, tmpl_name, 0);
- const Type exists = nspc_lookup_type0(v->from->owner, sym);
- if(exists)
- m_func = exists->e->d.func;
- else {
- Func_Def base = v->d.func_ref ? v->d.func_ref->def : exp->func->info->type->e->d.func->def;
- Func_Base *fbase = cpy_func_base(env->gwion->mp, base->base);
- fbase->xid = sym;
- fbase->tmpl->base = 0;
- fbase->tmpl->call = cpy_type_list(env->gwion->mp, types);
- if(template_push_types(env, fbase->tmpl) > 0) {
- const Fptr_Def fptr = new_fptr_def(env->gwion->mp, fbase);
- if(traverse_fptr_def(env, fptr) > 0 &&
- (base->base->ret_type = known_type(env, base->base->td)) &&
- (!exp->args || !!check_exp(env, exp->args))) {
- m_func = find_func_match(env, fbase->func, exp->args);
- nspc_pop_type(env->gwion->mp, env->curr);
- if(m_func)
- nspc_add_type_front(v->from->owner, sym, actual_type(env->gwion, m_func->value_ref->type));
- }
- free_fptr_def(env->gwion->mp, fptr);
- if(fptr->type)
- REM_REF(fptr->type, env->gwion)
- }
- }
+ m_func = fptr_match(env, &f_ptr_args);
} else {
- for(m_uint i = 0; i < v->from->offset + 1; ++i) {
- const Value exists = template_get_ready(env, v, tmpl_name, i);
- if(exists) {
- if(env->func == exists->d.func_ref) {
- if(check_call(env, exp) < 0 ||
- !find_func_match(env, env->func, exp->args))
- continue;
- m_func = env->func;
- break;
- }
- if((m_func = ensure_tmpl(env, exists->d.func_ref->def, exp)))
- break;
- } else {
- const Value value = template_get_ready(env, v, "template", i);
- if(!value)
- continue;
- if(GET_FLAG(v, builtin)) {
- SET_FLAG(value, builtin);
- SET_FLAG(value->d.func_ref, builtin);
- }
- const Func_Def fdef = (Func_Def)cpy_func_def(env->gwion->mp, value->d.func_ref->def);
- SET_FLAG(fdef->base, template);
- fdef->base->tmpl->call = cpy_type_list(env->gwion->mp, types);
- fdef->base->tmpl->base = i;
- if((m_func = ensure_tmpl(env, fdef, exp)))
- break;
- }
- }
+ m_func = func_match(env, &f_ptr_args);
}
free_mstr(env->gwion->mp, tmpl_name);
if(es.run)