-Subproject commit 476773eed83abcd74bf28cccebc59cf9eccca8bb
+Subproject commit d7cc060e0fe49405ca5494810c181ef211daf7f2
Scope type;
Scope func;
Scope trait;
- struct Vector_ op_map_tmpl;
+ struct Vector_ op_tmpl;
uint16_t offset;
uint16_t class_data_size;
};
ANN m_bool op_emit(const Emitter, const struct Op_Import *);
ANN m_bool operator_set_func(const struct Op_Import *);
ANN void free_op_map(Map map, struct Gwion_ *gwion);
+ANN void free_op_tmpl(Vector v, struct Gwion_ *gwion);
ANN void operator_suspend(const Nspc, struct Op_Import *);
ANN static inline void operator_resume(struct Op_Import *opi) {
}
ANN m_bool emit_func_def(const Emitter emit, const Func_Def f) {
+ if (tmpl_base(f->base->tmpl) && fbflag(f->base, fbflag_op)) return GW_OK;
const Func func = f->base->func;
const Func_Def fdef = func->def;
const Func former = emit->env->func;
nspc_free_func(a, gwion);
nspc_free_trait(a, gwion);
if (a->info->op_map.ptr) free_op_map(&a->info->op_map, gwion);
+ if (a->info->op_tmpl.ptr) free_op_tmpl(&a->info->op_tmpl, gwion);
nspc_free_type(a, gwion);
if (a->info->class_data && a->info->class_data_size)
mp_free2(gwion->mp, a->info->class_data_size, a->info->class_data);
if (next) gw_err(", "); \
return next; \
}
-next_arg(Exp) next_arg(Arg_List)
+next_arg(Exp) next_arg(Arg_List);
- ANN static void print_current_args(Exp e) {
+ANN static void print_current_args(Exp e) {
gw_err(_("and not\n "));
do gw_err(" {G}%s{0}", e->type ? e->type->name : "{-/}Unknown");
while ((e = next_arg_Exp(e)));
}
ANN m_bool check_func_def(const Env env, const Func_Def f) {
+ if (tmpl_base(f->base->tmpl) && fbflag(f->base, fbflag_op)) return GW_OK;
const Func func = f->base->func;
const Func_Def fdef = func->def;
assert(func == fdef->base->func);
#include "operator.h"
#include "object.h"
#include "array.h"
+#include "import.h"
+#include "traverse.h"
+#include "clean.h"
typedef Type (*f_type)(const Env env, const Exp exp);
map_release(map);
}
+ANN void free_op_tmpl(Vector v, struct Gwion_ *gwion) {
+ LOOP_OPTIM
+ for (m_uint i = vector_size(v) + 1; --i;) {
+ const Func_Def fdef = (Func_Def)vector_at(v, i - 1);
+ free_func_def(gwion->mp, fdef);
+ }
+ vector_release(v);
+}
+
static m_str type_name(const Type t) {
return t ? t == OP_ANY_TYPE ? "any" : t->name : "";
}
return NULL;
}
+//! check if type matches for template operator
+ANN bool _tmpl_match(const Env env, const Type t, Type_Decl *const td,
+ Specialized_List *sl) {
+ if (!td->next && td->xid == (*sl)->xid) {
+ *sl = (*sl)->next;
+ return true;
+ }
+ const Type base = known_type(env, td);
+ return isa(t, base) > 0;
+}
+
+//! check Func_Base matches for template operator
+ANN bool tmpl_match(const Env env, const struct Op_Import *opi,
+ Func_Base *const base) {
+ Specialized_List sl = base->tmpl->list;
+ const Arg_List arg = base->args;
+ if (opi->lhs) {
+ if (fbflag(base, fbflag_unary) ||
+ !_tmpl_match(env, opi->lhs, arg->td, &sl) ||
+ (opi->rhs && fbflag(base, fbflag_postfix)) ||
+ !_tmpl_match(env, opi->rhs, arg->next->td, &sl))
+ return false;
+ } else {
+ if (!fbflag(base, fbflag_unary) ||
+ !_tmpl_match(env, opi->rhs, arg->td, &sl))
+ return false;
+ }
+ return true;
+}
+
+//! make template operator Type_List
+ANN2(1, 2)
+static Type_List op_type_list(const Env env, const Type t, const Type_List next,
+ const loc_t loc) {
+ Type_Decl *const td0 = type2td(env->gwion, t, loc);
+ return new_type_list(env->gwion->mp, td0, next);
+}
+
+//! make template operator Func_def
+ANN Type op_def(const Env env, struct Op_Import *const opi,
+ const Func_Def fdef) {
+ const Func_Def tmpl_fdef = cpy_func_def(env->gwion->mp, fdef);
+ tmpl_fdef->base->tmpl->base = 0;
+ if (opi->lhs) {
+ Type_List next =
+ opi->rhs ? op_type_list(env, opi->rhs, NULL, opi->pos) : NULL;
+ tmpl_fdef->base->tmpl->call = op_type_list(env, opi->lhs, next, opi->pos);
+ } else
+ tmpl_fdef->base->tmpl->call = op_type_list(env, opi->rhs, NULL, opi->pos);
+ if (traverse_func_def(env, tmpl_fdef) < 0) {
+ if (!tmpl_fdef->base->func) func_def_cleaner(env->gwion, tmpl_fdef);
+ return NULL;
+ }
+ return op_check(env, opi);
+}
+
+//! find template operator
+ANN static Type op_check_tmpl(const Env env, struct Op_Import *opi) {
+ Nspc nspc = env->curr;
+ do {
+ if (!nspc->info->op_tmpl.ptr) continue;
+ const Vector v = &nspc->info->op_tmpl;
+ for (m_uint i = vector_size(v) + 1; --i;) {
+ const Func_Def fdef = (Func_Def)vector_at(v, i - 1);
+ if (!tmpl_match(env, opi, fdef->base)) continue;
+ return op_def(env, opi, fdef);
+ }
+ } while ((nspc = nspc->parent));
+ return NULL;
+}
+
ANN Type op_check(const Env env, struct Op_Import *opi) {
for (int i = 0; i < 2; ++i) {
Nspc nspc = env->curr;
} while (l && (l = op_parent(env, l)));
} while ((nspc = nspc->parent));
}
+ const Type try_tmpl = op_check_tmpl(env, opi);
+ if (try_tmpl) return try_tmpl;
// this should be an any case
if (opi->op == insert_symbol(env->gwion->st, "$") && opi->rhs == opi->lhs)
return opi->rhs;
ERR_O(base->pos, _("Can't use type `{+G}%s{0}` for return"), t->name);
}
-ANN static m_bool _scan1_fdef_base_tmpl(const Env env, Func_Base *base) {
+ANN static m_bool _scan1_fbase_tmpl(const Env env, Func_Base *base) {
Specialized_List id = base->tmpl->list;
do nspc_add_type(env->curr, id->xid, env->gwion->type[et_auto]);
while ((id = id->next));
return GW_OK;
}
-ANN static m_bool scan1_fdef_base_tmpl(const Env env, Func_Base *base) {
+ANN static m_bool scan1_fbase_tmpl(const Env env, Func_Base *const base) {
nspc_push_type(env->gwion->mp, env->curr);
- const m_bool ret = _scan1_fdef_base_tmpl(env, base);
+ const m_bool ret = _scan1_fbase_tmpl(env, base);
nspc_pop_type(env->gwion->mp, env->curr);
return ret;
}
+ANN static m_bool scan1_fdef_base_tmpl(const Env env, const Func_Def fdef) {
+ Func_Base *const base = fdef->base;
+ if (!fbflag(base, fbflag_op)) return scan1_fbase_tmpl(env, base);
+ Arg_List arg = fdef->base->args;
+ Specialized_List sl = fdef->base->tmpl->list;
+ do {
+ if (!arg->td->next && sl && arg->td->xid == sl->xid) { sl = sl->next; }
+ } while ((arg = arg->next));
+ if (sl) ERR_B(base->pos, "too many template types for operator");
+ const Vector v = &env->curr->info->op_tmpl;
+ if (!v->ptr) vector_init(v);
+ vector_add(v, (m_uint)cpy_func_def(env->gwion->mp, fdef));
+ return GW_OK;
+}
+
ANN m_bool scan1_fptr_def(const Env env, const Fptr_Def fptr) {
- if (tmpl_base(fptr->base->tmpl)) return scan1_fdef_base_tmpl(env, fptr->base);
+ if (tmpl_base(fptr->base->tmpl)) return scan1_fbase_tmpl(env, fptr->base);
if (!fptr->base->func) {
fptr->base->func =
nspc_lookup_value0(env->curr, fptr->base->xid)->d.func_ref;
if (fdef->base->td)
CHECK_BB(env_storage(env, fdef->base->flag, fdef->base->td->pos));
CHECK_BB(scan1_fdef_defined(env, fdef));
- if (tmpl_base(fdef->base->tmpl)) return scan1_fdef_base_tmpl(env, fdef->base);
+ if (tmpl_base(fdef->base->tmpl)) return scan1_fdef_base_tmpl(env, fdef);
struct Func_ fake = {.name = s_name(fdef->base->xid)}, *const former =
env->func;
env->func = &fake;
}
ANN m_bool scan2_func_def(const Env env, const Func_Def fdef) {
+ if (tmpl_base(fdef->base->tmpl) && fbflag(fdef->base, fbflag_op))
+ return GW_OK;
if (GET_FLAG(fdef->base, global) && !env->class_def) env->context->global = 1;
const Func_Def f = !is_cpy(fdef) ? fdef : scan2_cpy_fdef(env, fdef);
const m_uint scope =
--- /dev/null
+operator int --- :[A,C] (A i, C j) { return i;}
+<<< 1 --- 2 >>>;
+<<< 2 --- 2 >>>;