]> Nishi Git Mirror - gwion.git/commitdiff
:art: Allow no types in variadic
authorfennecdjay <fennecdjay@gmail.com>
Sat, 30 Jul 2022 05:34:07 +0000 (07:34 +0200)
committerfennecdjay <fennecdjay@gmail.com>
Sat, 30 Jul 2022 05:34:07 +0000 (07:34 +0200)
src/import/import_checker.c
src/parse/func_resolve_tmpl.c
src/parse/template.c

index b21721aeeefb0d30b6e9d0aa449e2a8bf8934911..0dea184ffa01d743104bdd7edbcd5f4b303befd4 100644 (file)
@@ -84,6 +84,15 @@ ANN m_bool str2var(const Gwion gwion, Var_Decl *vd, const m_str path, const loc_
 #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 = {
@@ -286,6 +295,10 @@ ANN static void td_fullname(const Env env, GwText *text, const Type t) {
 
 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));
index 23dccba0b612f15f983e979895e47e7f3188657b..1cbeff5ecce0d3ee0606b463d8955a4ee26b02e7 100644 (file)
@@ -147,12 +147,14 @@ ANN static Func find_tmpl(const Env env, const Value v, Exp_Call *const exp,
       .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);
index 302626091ad5f1e9836cb99291d4f7a258e2685a..d6b273b302f40f82e59d693c7b0b2dbc1e713a73 100644 (file)
@@ -134,16 +134,44 @@ static ANN Type maybe_func(const Env env, const Type t, const Type_Decl *td) {
         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;
@@ -152,20 +180,8 @@ ANN static Type _scan_type(const Env env, const Type t, Type_Decl *td) {
     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,