#define SPEC_ERROR (Specialized_List) GW_ERROR
ANN static bool _tmpl_list(const Gwion gwion,
struct td_checker *tdc, Specialized_List *sl) {
+ if(unlikely(!strncmp(tdc->str, "...", 3))) {
+ tdc->str += 3;
+ Specialized spec = {
+ .xid = insert_symbol(gwion->st, "..."),
+ .pos = tdc->pos
+ };
+ mp_vector_add(gwion->mp, sl, Specialized, spec);
+ return true;
+ }
DECL_OO(const Symbol, sym, = __str2sym(gwion, tdc));
// TODO: handle traits?
Specialized spec = {
ANN static m_bool td_info_run(const Env env, struct td_info *info) {
Type_List tl = info->tl;
+ if(unlikely(!tl->len)) {
+ text_add(&info->text, "");
+ return GW_OK;
+ }
for(uint32_t i = 0; i < tl->len; i++) {
if (i) text_add(&info->text, ",");
DECL_OB(Type_Decl *, td, = *mp_vector_at(tl, Type_Decl*, i));
.v = v, .e = exp, .tmpl_name = tmpl_name, .types = types};
CHECK_BO(envset_pushv(&es, v));
(void)env_push(env, v->from->owner_class, v->from->owner);
- if (v->from->owner_class && v->from->owner_class->info->cdef->base.tmpl)
+ const bool in_tmpl = v->from->owner_class && v->from->owner_class->info->cdef &&
+ v->from->owner_class->info->cdef->base.tmpl;
+ if(in_tmpl)
(void)template_push_types(env, v->from->owner_class->info->cdef->base.tmpl);
const bool is_clos = isa(exp->func->type, env->gwion->type[et_closure]) > 0;
const Func m_func = !is_clos ? func_match(env, &ra)
: fptr_match(env, &ra);
- if (v->from->owner_class && v->from->owner_class->info->cdef->base.tmpl)
+ if(in_tmpl)
nspc_pop_type(env->gwion->mp, env->curr);
env_pop(env, scope);
if (es.run) envset_pop(&es, v->from->owner_class);
t->name)
}
+static ANN bool is_single_variadic(const MP_Vector *v) {
+ if(v->len != 1) return false;
+ const Specialized *spec = mp_vector_at(v, Specialized, 0);
+ return !strcmp(s_name(spec->xid), "...");
+}
+
+ANN2(1,2) static m_bool check_tmpl(const Env env, const Type_List tl, const Specialized_List sl, const loc_t pos, const bool is_spread) {
+ if (!sl || sl->len > tl->len || (tl->len != sl->len && !is_spread))
+ ERR_B(pos, "invalid template type number");
+ for (uint32_t i = 0; i < sl->len; i++) {
+ Type_Decl *tmp = *mp_vector_at(tl, Type_Decl*, i);
+ DECL_OB(const Type, t, = known_type(env, tmp));
+ Specialized *spec = mp_vector_at(sl, Specialized, i);
+ if(spec->traits) {
+ Symbol missing = miss_traits(t, spec);
+ if (missing) {
+ ERR_B(pos, "does not implement requested trait '{/}%s{0}'",
+ s_name(missing));
+ }
+ }
+ }
+ return GW_OK;
+}
+
ANN static Type _scan_type(const Env env, const Type t, Type_Decl *td) {
if (tflag(t, tflag_tmpl) && !is_func(env->gwion, t)) { // is_callable
if (tflag(t, tflag_ntmpl) && !td->types) return t;
+ const bool single_variadic = is_single_variadic(t->info->cdef->base.tmpl->list);
if(!td->types) {
const Type new_type = nspc_lookup_type1(env->curr, td->xid);
Type_Decl *new_td = type2td(env->gwion, new_type, td->pos);
Type_Decl *d = new_td;
while(d->next) d = d->next;
- if(!d->types)
- ERR_N(td->pos, _("you must provide template types for type '%s' !!!"), t->name);
+ if(!d->types) {
+ if(!single_variadic)
+ ERR_N(td->pos, _("you must provide template types for type '%s' !!!"), t->name);
+ d->types = new_mp_vector(env->gwion->mp, Type_Decl*, 0);
+ }
const Type ret = _scan_type(env, t, d);
free_type_decl(env->gwion->mp, new_td);
return ret;
Type_List tl = td->types;
Specialized_List sl = t->info->cdef->base.tmpl
? t->info->cdef->base.tmpl->list : NULL;
- if (!sl || sl->len > tl->len || (tl->len != sl->len && !is_spread_tmpl(t->info->cdef->base.tmpl)))
- ERR_O(td->pos, "invalid template type number");
- for (uint32_t i = 0; i < sl->len; i++) {
- Type_Decl *tmp = *mp_vector_at(tl, Type_Decl*, i);
- DECL_OO(const Type, t, = known_type(env, tmp));
- Specialized *spec = mp_vector_at(sl, Specialized, i);
- if(spec->traits) {
- Symbol missing = miss_traits(t, spec);
- if (missing) {
- ERR_O(td->pos, "does not implement requested trait '{/}%s{0}'",
- s_name(missing));
- }
- }
- }
+ const bool is_spread = is_spread_tmpl(t->info->cdef->base.tmpl);
+ if(!single_variadic) CHECK_BO(check_tmpl(env, tl, sl, td->pos, is_spread));
struct Op_Import opi = {.op = insert_symbol("@scan"),
.lhs = t,
.data = (uintptr_t)&ts,