From: fennecdjay Date: Fri, 29 Sep 2023 18:23:59 +0000 (+0200) Subject: :art: update towards const generics X-Git-Tag: nightly~131 X-Git-Url: http://10.10.0.4:5575/?a=commitdiff_plain;h=ace36c89a322c643cb54ca1f9bf487282ce99204;p=gwion.git :art: update towards const generics --- diff --git a/src/clean.c b/src/clean.c index d5308ab1..aa7d57df 100644 --- a/src/clean.c +++ b/src/clean.c @@ -15,8 +15,11 @@ ANN static void clean_array_sub(Clean *a, Array_Sub b) { ANN static void clean_type_list(Clean *a, Type_List b) { for(uint32_t i = 0; i < b->len; i++) { - Type_Decl *td = *mp_vector_at(b, Type_Decl*, i); - clean_type_decl(a, td); + TmplArg arg = *mp_vector_at(b, TmplArg, i); + if(arg.type == tmplarg_td) + clean_type_decl(a, arg.d.td); + else if(arg.type == tmplarg_exp) + clean_exp(a, arg.d.exp); } } diff --git a/src/emit/emit.c b/src/emit/emit.c index 4da51eff..52d37347 100644 --- a/src/emit/emit.c +++ b/src/emit/emit.c @@ -2913,6 +2913,37 @@ ANN static m_bool cdef_parent(const Emitter emit, const Class_Def cdef) { return ret; } +static INSTR(set) { + Value v = *(Value*)(shred->reg + -SZ_INT); + shred->reg -= instr->m_val; + memcpy(&v->d.ptr, shred->reg, instr->m_val2); +} + +ANN static m_bool emit_class_tmpl(const Emitter emit, const Tmpl *tmpl, const Nspc nspc) { + if(tmplarg_ntypes(tmpl->list) != tmpl->list->len) { + emit_push_code(emit, "tmpl"); + for(uint32_t i = 0; i < tmpl->list->len; i++) { + const TmplArg targ = *mp_vector_at(tmpl->call, TmplArg, i); + if(likely(targ.type == tmplarg_td)) continue; + CHECK_BB(emit_exp(emit, targ.d.exp)); + const Specialized spec = *mp_vector_at(tmpl->list, Specialized, i); + const Value v = nspc_lookup_value1(nspc, spec.xid); + emit_pushimm(emit, (m_uint)v); + const Instr instr = emit_add_instr(emit, set); + instr->m_val2 = targ.d.exp->type->size; + instr->m_val = instr->m_val2 + SZ_INT; + } + VM_Code code = finalyze(emit, EOC); + VM_Shred shred = new_vm_shred(emit->gwion->mp, code); + vm_add_shred(emit->gwion->vm, shred); + const bool loop = emit->gwion->vm->shreduler->loop; + vm_run(emit->gwion->vm); + emit->gwion->vm->bbq->is_running = true; + emit->gwion->vm->shreduler->loop = loop; + } + return GW_OK; +} + ANN static m_bool _emit_class_def(const Emitter emit, const Class_Def cdef) { const Type t = cdef->base.type; set_tflag(t, tflag_emit); @@ -2920,6 +2951,7 @@ ANN static m_bool _emit_class_def(const Emitter emit, const Class_Def cdef) { if (c->base.ext && t->info->parent->info->cdef && !tflag(t->info->parent, tflag_emit)) // ????? CHECK_BB(cdef_parent(emit, c)); + if (c->base.tmpl) CHECK_BB(emit_class_tmpl(emit, c->base.tmpl, c->base.type->nspc)); if (c->body) return scanx_body(emit->env, c, (_exp_func)emit_section, emit); return GW_OK; diff --git a/src/env/context.c b/src/env/context.c index 207062b3..e5f5639e 100644 --- a/src/env/context.c +++ b/src/env/context.c @@ -44,7 +44,7 @@ ANN static void clean(const Nspc nspc, const Env env) { ANN void unload_context(const Context ctx, const Env env) { const Nspc global = ctx->nspc->parent; - if(global != env->global_nspc) exit(3); + if(global != env->global_nspc) exit(53); context_remref(ctx, env->gwion); env->curr = (Nspc)vector_pop(&env->scope->nspc_stack); const Nspc user = (Nspc)vector_at(&env->scope->nspc_stack, 1); diff --git a/src/env/func.c b/src/env/func.c index 4a17896e..d06873dd 100644 --- a/src/env/func.c +++ b/src/env/func.c @@ -40,14 +40,20 @@ ANN void builtin_func(const Gwion gwion, const Func f, void *func_ptr) { f->code = new_vmcode(gwion->mp, NULL, NULL, f->name, f->def->stack_depth, true, false); f->code->native_func = (m_uint)func_ptr; f->code->ret_type = f->def->base->ret_type; - if(f->def->base->tmpl && f->def->base->tmpl->call) { + if(f->def->base->tmpl) { + const Type_List tl = f->def->base->tmpl->call; + if(!tl) return; const Specialized *spec = mp_vector_at(f->def->base->tmpl->list, Specialized, f->def->base->tmpl->list->len - 1); if(!strcmp(s_name(spec->xid), "...")) { - f->code->types = new_mp_vector(gwion->mp, Type_Decl*, f->def->base->tmpl->call->len); - for(uint32_t i = 0; i < f->def->base->tmpl->call->len; i++) { - Type_Decl *const td = *mp_vector_at(f->def->base->tmpl->call, Type_Decl*, i); - mp_vector_set(f->code->types, Type, i, known_type(gwion->env, td)); + const uint32_t len = tmplarg_ntypes(tl); + f->code->types = new_mp_vector(gwion->mp, Type, len); + uint32_t n = 0; + for(uint32_t i = 0; i < tl->len; i++) { + const TmplArg arg = *mp_vector_at(tl, TmplArg, i); + if(likely(arg.type == tmplarg_td)) + mp_vector_set(f->code->types, Type, n++, known_type(gwion->env, arg.d.td)); } +// f->code->types->len = n; } } } diff --git a/src/import/import_checker.c b/src/import/import_checker.c index 1b0109bd..68203126 100644 --- a/src/import/import_checker.c +++ b/src/import/import_checker.c @@ -133,14 +133,19 @@ ANN m_bool check_typename_def(const Gwi gwi, ImportCK *ck) { ANN static Type_Decl *_str2td(const Gwion gwion, struct td_checker *tdc); ANN bool str2tl(const Gwion gwion, struct td_checker *tdc, Type_List *tl) { - Type_Decl *td = _str2td(gwion, tdc); - if (!td) GWION_ERR_B(tdc->pos, "invalid types"); - mp_vector_add(gwion->mp, tl, Type_Decl*, td); - if (*tdc->str == ',') { - ++tdc->str; - if (!str2tl(gwion, tdc, tl)) - return false; - } + if(isalpha(*tdc->str)) { + TmplArg targ = { + .type = tmplarg_td, + .d = { .td = _str2td(gwion, tdc) } + }; + if (!targ.d.td) GWION_ERR_B(tdc->pos, "invalid types"); + mp_vector_add(gwion->mp, tl, TmplArg, targ); + if (*tdc->str == ',') { + ++tdc->str; + if (!str2tl(gwion, tdc, tl)) + return false; + } + } else exit(6); return true; } @@ -152,7 +157,7 @@ ANN static Type_List td_tmpl(const Gwion gwion, struct td_checker *tdc) { return (Type_List)GW_ERROR; } ++tdc->str; - Type_List tl = new_mp_vector(gwion->mp, Type_Decl*, 0); + Type_List tl = new_mp_vector(gwion->mp, TmplArg, 0); if (!str2tl(gwion, tdc, &tl)) { free_type_list(gwion->mp, tl); return (Type_List)GW_ERROR; @@ -281,7 +286,7 @@ ANN Type str2type(const Gwion gwion, const m_str str, const loc_t pos) { struct td_info { Type_List tl; - GwText text; + Gwfmt *fmt; }; ANN static void td_fullname(const Env env, GwText *text, const Type t) { @@ -295,15 +300,13 @@ 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)); - DECL_OB(const Type, t, = known_type(env, td)); - td_fullname(env, &info->text, t); + if (i) text_add(&info->fmt->ls->text, ","); + TmplArg targ = *mp_vector_at(tl, TmplArg, i); + if(targ.type == tmplarg_td) { + DECL_OB(const Type, t, = known_type(env, targ.d.td)); + td_fullname(env, &info->fmt->ls->text, t); + } else gwfmt_exp(info->fmt, targ.d.exp); } return GW_OK; } @@ -318,10 +321,12 @@ ANEW ANN m_str type2str(const Gwion gwion, const Type t, ANEW ANN m_str tl2str(const Gwion gwion, const Type_List tl, const loc_t pos NUSED) { - struct td_info info = {.tl = tl}; - text_init(&info.text, gwion->mp); + struct GwfmtState ls = {.minimize=true, .ppa = gwion->ppa}; + text_init(&ls.text, gwion->mp); + Gwfmt l = {.mp = gwion->mp, .st = gwion->st, .ls = &ls, .line = 1, .last = cht_nl }; + struct td_info info = {.tl = tl, .fmt = &l }; CHECK_BO(td_info_run(gwion->env, &info)); - return info.text.str; + return ls.text.str; } ANN static inline m_bool ac_finish(const Gwion gwion, const struct AC *ac) { diff --git a/src/lib/array.c b/src/lib/array.c index aede652d..8b0f0a69 100644 --- a/src/lib/array.c +++ b/src/lib/array.c @@ -799,7 +799,7 @@ static OP_CHECK(opck_array_scan) { const Type t_array = env->gwion->type[et_array]; const Class_Def c = t_array->info->cdef; DECL_ON(const Type, base, - = ts->t != t_array ? ts->t : known_type(env, *mp_vector_at(ts->td->types, Type_Decl*, 0))); + = ts->t != t_array ? ts->t : known_type(env, mp_vector_at(ts->td->types, TmplArg, 0)->d.td)); if (base->size == 0) { gwerr_basic("Can't use type of size 0 as array base", NULL, NULL, "/dev/null", (loc_t) {}, 0); @@ -818,8 +818,9 @@ static OP_CHECK(opck_array_scan) { const Class_Def cdef = cpy_class_def(env->gwion->mp, c); cdef->base.ext = type2td(env->gwion, t_array, (loc_t) {}); cdef->base.xid = sym; - cdef->base.tmpl->call = new_mp_vector(env->gwion->mp, Type_Decl*, 1); - mp_vector_set(cdef->base.tmpl->call, Type_Decl*, 0, type2td(env->gwion, base, (loc_t) {})); + cdef->base.tmpl->call = new_mp_vector(env->gwion->mp, TmplArg, 1); + TmplArg arg = {.type = tmplarg_td, .d = {.td = type2td(env->gwion, base, (loc_t) {})} }; + mp_vector_set(cdef->base.tmpl->call, TmplArg, 0, arg); const Context ctx = env->context; env->context = base->info->value->from->ctx; const m_uint scope = env_push(env, base->info->value->from->owner_class, diff --git a/src/lib/closure.c b/src/lib/closure.c index 73e5b3d9..2c1754a1 100644 --- a/src/lib/closure.c +++ b/src/lib/closure.c @@ -167,8 +167,10 @@ ANN static void _fptr_tmpl_push(const Env env, const Func f) { Specialized_List sl = tmpl->list; for(uint32_t i = 0; i < sl->len; i++) { Specialized *spec = mp_vector_at(sl, Specialized, i); - Type_Decl *td = *mp_vector_at(tl, Type_Decl*, i); - const Type t = known_type(env, td); + // can it be called with consts? + if(spec->td) continue; + TmplArg arg = *mp_vector_at(tl, TmplArg, i); + const Type t = known_type(env, arg.d.td); nspc_add_type(env->curr, spec->xid, t); } } @@ -659,8 +661,10 @@ static FREEARG(freearg_dottmpl) { ANN static bool is_base(const Env env, const Type_List tl) { for(uint32_t i = 0; i < tl->len; i++) { - Type_Decl *td = *mp_vector_at(tl, Type_Decl*, i); - if(known_type(env, td) == env->gwion->type[et_auto]) + // can call with const happen? + TmplArg arg = *mp_vector_at(tl, TmplArg, i); + if(unlikely(arg.type == tmplarg_exp)) continue; + if(known_type(env, arg.d.td) == env->gwion->type[et_auto]) return true; } return false; diff --git a/src/lib/dict.c b/src/lib/dict.c index 9d5ba6a5..d8e9f250 100644 --- a/src/lib/dict.c +++ b/src/lib/dict.c @@ -560,8 +560,8 @@ static OP_CHECK(opck_dict_scan) { const Type exists = tmpl_exists(env, &info); if (exists) return exists != env->gwion->type[et_error] ? exists : NULL; if(!ts->td->types || ts->td->types->len != 2) return env->gwion->type[et_error]; - DECL_ON(const Type, key, = known_type(env, *mp_vector_at(ts->td->types, Type_Decl*, 0))); - DECL_ON(const Type, val, = known_type(env, *mp_vector_at(ts->td->types, Type_Decl*, 1))); + DECL_ON(const Type, key, = known_type(env, mp_vector_at(ts->td->types, TmplArg, 0)->d.td)); + DECL_ON(const Type, val, = known_type(env, mp_vector_at(ts->td->types, TmplArg, 1)->d.td)); if(tflag(key, tflag_ref) || tflag(val, tflag_ref)) ERR_N(ts->td->pos, "can't use Ref:[] in dicts"); const Class_Def cdef = cpy_class_def(env->gwion->mp, env->gwion->type[et_dict]->info->cdef); diff --git a/src/lib/ref.c b/src/lib/ref.c index 521822b8..3a0b8076 100644 --- a/src/lib/ref.c +++ b/src/lib/ref.c @@ -149,7 +149,8 @@ static OP_CHECK(opck_ref_scan) { .base = ts->t, .td = ts->td, .list = ts->t->info->cdef->base.tmpl->list}; const Type exists = tmpl_exists(env, &info); if (exists) return exists != env->gwion->type[et_error] ? exists : NULL; - const Type base = known_type(env, *mp_vector_at(ts->td->types, Type_Decl*, 0)); + const TmplArg arg = *mp_vector_at(ts->td->types, TmplArg, 0); + const Type base = known_type(env, arg.d.td); const Type t = new_type(env->gwion->mp, s_name(info.name), base); t->size = SZ_INT; SET_FLAG(t, abstract | ae_flag_final); diff --git a/src/lib/tmpl_info.c b/src/lib/tmpl_info.c index 4a0121c8..3033d5c3 100644 --- a/src/lib/tmpl_info.c +++ b/src/lib/tmpl_info.c @@ -99,8 +99,9 @@ ANN Type tmpl_exists(const Env env, struct tmpl_info *const info) { ANN bool tmpl_global(const Env env, Type_List tl) { for(uint32_t i = 0; i < tl->len; i++) { - Type_Decl *td = *mp_vector_at(tl, Type_Decl*, i); - const Type t = known_type(env, td); + TmplArg arg = *mp_vector_at(tl, TmplArg, i); + if(unlikely(arg.type == tmplarg_exp)) continue; + const Type t = known_type(env, arg.d.td); if(!t || !type_global(env, t)) return false; } diff --git a/src/lib/union.c b/src/lib/union.c index 68605fc8..868df059 100644 --- a/src/lib/union.c +++ b/src/lib/union.c @@ -188,28 +188,14 @@ ANN GWION_IMPORT(union) { GWI_BB(gwi_func_arg(gwi, "int", "id")) GWI_BB(gwi_func_arg(gwi, "T", "value")) GWI_BB(gwi_func_end(gwi, union_new, ae_flag_none)) - + GWI_BB(gwi_class_end(gwi)) - const Func f = (Func)vector_at(&t_union->nspc->vtable, 0); - const struct Op_Func opfunc = {.ck = opck_union_is}; - const struct Op_Import opi = { - .rhs = f->value_ref->type, - .func = &opfunc, - .data = (uintptr_t)f, - .pos = gwi->loc, - .op = insert_symbol(gwi->gwion->st, "@func_check")}; - CHECK_BB(add_op(gwi->gwion, &opi)); - - const Func f1 = (Func)vector_at(&t_union->nspc->vtable, 1); + const struct Op_Func opfunc0 = {.ck = opck_union_is}; + GWI_BB(add_op_func_check(gwi->gwion->env, t_union, &opfunc0, 0)); + const struct Op_Func opfunc1 = {.ck = opck_union_new}; - const struct Op_Import opi1 = { - .rhs = f1->value_ref->type, - .func = &opfunc1, - .data = (uintptr_t)f1, - .pos = gwi->loc, - .op = insert_symbol(gwi->gwion->st, "@func_check")}; - CHECK_BB(add_op(gwi->gwion, &opi1)); + GWI_BB(add_op_func_check(gwi->gwion->env, t_union, &opfunc1, 1)); GWI_BB(gwi_oper_ini(gwi, "union", (m_str)OP_ANY_TYPE, NULL)) GWI_BB(gwi_oper_emi(gwi, opem_union_dot)) diff --git a/src/parse/check.c b/src/parse/check.c index 8274b15d..3a35d7e1 100644 --- a/src/parse/check.c +++ b/src/parse/check.c @@ -751,7 +751,7 @@ ANN static Type_List check_template_args(const Env env, Exp_Call *exp, Specialized_List sl = tm->list; const bool spread = is_spread_tmpl(fdef->base->tmpl); const uint32_t len = sl->len - spread; - Type_List tl = new_mp_vector(env->gwion->mp, Type_Decl*, len); + Type_List tl = new_mp_vector(env->gwion->mp, TmplArg, len); m_uint args_number = 0; if(exp->other) { @@ -760,15 +760,21 @@ ANN static Type_List check_template_args(const Env env, Exp_Call *exp, if (tmpl_arg_match(env, spec->xid, fdef->base->td->xid, fdef->base->ret_type)) { CHECK_OO(check_exp(env, exp->other)); if(!is_func(env->gwion, exp->other->type)) { - Type_Decl *td = type2td(env->gwion, exp->other->type, fdef->base->td->pos); - mp_vector_set(tl, Type_Decl*, 0, td); + TmplArg targ = { + .type = tmplarg_td, + .d = { .td = type2td(env->gwion, exp->other->type, fdef->base->td->pos) } + }; + mp_vector_set(tl, TmplArg, 0, targ); } else { Func func = exp->other->type->info->func; do { if(mp_vector_len(func->def->base->args) == 1) { Arg *arg = mp_vector_at(func->def->base->args, Arg, 0); - Type_Decl *td = cpy_type_decl(env->gwion->mp, arg->td); - mp_vector_set(tl, Type_Decl*, 0, td); + TmplArg targ = { + .type = tmplarg_td, + .d = { .td = cpy_type_decl(env->gwion->mp, arg->td) } + }; + mp_vector_set(tl, TmplArg, 0, targ); break; } } while((func = func->next)); @@ -787,8 +793,11 @@ ANN static Type_List check_template_args(const Env env, Exp_Call *exp, while (count < args_len && template_arg) { Arg *arg = mp_vector_at(args, Arg, count); if (tmpl_arg_match(env, spec->xid, arg->td->xid, template_arg->type)) { - mp_vector_set(tl, Type_Decl*, args_number, - mk_td(env, arg->td, template_arg->type, fdef->base->pos)); + TmplArg targ = { + .type = tmplarg_td, + .d = { .td = mk_td(env, arg->td, template_arg->type, fdef->base->pos) } + }; + mp_vector_set(tl, TmplArg, args_number, targ); ++args_number; break; } @@ -804,7 +813,11 @@ ANN static Type_List check_template_args(const Env env, Exp_Call *exp, if(fdef->base->args) for(uint32_t i = 0; i < fdef->base->args->len && e; i++) e = e->next; while(e) { - mp_vector_add(env->gwion->mp, &tl, Type_Decl*, type2td(env->gwion, e->type, e->pos)); + TmplArg targ = { + .type = tmplarg_td, + .d = { .td = type2td(env->gwion, e->type, e->pos) } + }; + mp_vector_add(env->gwion->mp, &tl, TmplArg, targ); e = e->next; } } @@ -1130,10 +1143,12 @@ ANN2(1) static inline bool is_partial(const Env env, Exp exp) { ANN static bool tl_match(const Env env, const Type_List tl0, const Type_List tl1) { if (tl0->len != tl1->len) return false; for(uint32_t i = 0; i < tl0->len; i++) { - Type_Decl *td0 = *mp_vector_at(tl0, Type_Decl*, i); - Type_Decl *td1 = *mp_vector_at(tl1, Type_Decl*, i); - if(known_type(env, td0) != known_type(env, td1)) + TmplArg targ0 = *mp_vector_at(tl0, TmplArg, i); + TmplArg targ1 = *mp_vector_at(tl1, TmplArg, i); + if (targ0.type != targ1.type) return false; + if(targ0.type == tmplarg_td && known_type(env, targ0.d.td) != known_type(env, targ1.d.td)) return false; + // how do we check exps??? } return true; } @@ -2047,25 +2062,6 @@ ANN m_bool check_abstract(const Env env, const Class_Def cdef) { } return !err ? GW_OK : GW_ERROR; } -/* -ANN static inline void ctor_effects(const Env env) { - const Vector v = &env->scope->effects; - MP_Vector *const w = (MP_Vector*)vector_back(v); - if (!w) return; - vector_init(&env->class_def->effects); - for (uint32_t j = 0; j < w->len; j++) { - struct ScopeEffect *eff = mp_vector_at(w, struct ScopeEffect, j); - vector_add(&env->class_def->effects, (m_uint)eff->sym); - } - free_mp_vector(env->gwion->mp, struct ScopeEffect, w); - vector_pop(v); -} -*/ -ANN static m_bool check_body(const Env env, Section *const section) { - const m_bool ret = check_section(env, section); -// ctor_effects(env); - return ret; -} ANN static bool class_def_has_body(Ast ast) { const Section *section = mp_vector_at(ast, Section, 0); @@ -2166,12 +2162,36 @@ ANN static m_bool recursive_type_base(const Env env, const Type t) { } ANN bool check_trait_requests(const Env env, const Type t, const ID_List list, const ValueFrom *from); + +ANN static m_bool check_class_tmpl(const Env env, const Tmpl *tmpl, const Nspc nspc) { + if(tmplarg_ntypes(tmpl->list) != tmpl->list->len) { + for(uint32_t i = 0; i < tmpl->list->len; i++) { + const TmplArg targ = *mp_vector_at(tmpl->call, TmplArg, i); + if(likely(targ.type == tmplarg_td)) continue; + CHECK_OB(check_exp(env, targ.d.exp)); +// if(isa(targ.d.exp->type, known_type(env, spec) + const Specialized spec = *mp_vector_at(tmpl->list, Specialized, i); + const Value v = new_value(env, targ.d.exp->type, s_name(spec.xid), targ.d.exp->pos); + valuefrom(env, v->from); + set_vflag(v, vflag_valid); + nspc_add_value(nspc, spec.xid, v); +// valid_value(env, spec.xid, v); + SET_FLAG(v, const| ae_flag_static); + set_vflag(v, vflag_builtin); + + // set value type + } + } + return GW_OK; +} + ANN static m_bool _check_class_def(const Env env, const Class_Def cdef) { const Type t = cdef->base.type; if (cdef->base.ext) CHECK_BB(cdef_parent(env, cdef)); if (!tflag(t, tflag_struct)) inherit(t); + if(cdef->base.tmpl) CHECK_BB(check_class_tmpl(env, cdef->base.tmpl, cdef->base.type->nspc)); if (cdef->body) { - CHECK_BB(env_body(env, cdef, check_body)); + CHECK_BB(env_body(env, cdef, check_section)); if (cflag(cdef, cflag_struct) || class_def_has_body(cdef->body)) // if (class_def_has_body(cdef->body)) set_tflag(t, tflag_ctor); diff --git a/src/parse/func_resolve_tmpl.c b/src/parse/func_resolve_tmpl.c index 97daeab2..f2ef19cb 100644 --- a/src/parse/func_resolve_tmpl.c +++ b/src/parse/func_resolve_tmpl.c @@ -109,8 +109,8 @@ ANN static Func create_tmpl(const Env env, struct ResolverArgs *ra, for(uint32_t idx = 0; idx < ra->types->len; idx++) { char c[256]; sprintf(c, "arg%u", idx); - Type_Decl *td = *mp_vector_at(ra->types, Type_Decl*, idx); - Arg arg = { .td = cpy_type_decl(env->gwion->mp, td), .var_decl = {.xid = insert_symbol(c), /*.value = v*/ }}; + TmplArg targ = *mp_vector_at(ra->types, TmplArg, idx); + Arg arg = { .td = cpy_type_decl(env->gwion->mp, targ.d.td), .var_decl = {.xid = insert_symbol(c), /*.value = v*/ }}; mp_vector_add(env->gwion->mp, &args, Arg, arg); } fdef->base->args = args; @@ -181,12 +181,16 @@ ANN static Func _find_template_match(const Env env, const Value v, Type_List tl = exp->tmpl->call; Specialized_List sl = f->def->base->tmpl->list; for(uint32_t i = 0; i < tl->len; i++) { - Type_Decl *td = *mp_vector_at(tl, Type_Decl*, i); - DECL_OO(const Type, t, = known_type(env, td)); - if(t->info->traits) { - Specialized * spec = mp_vector_at(sl, Specialized, i); - if (miss_traits(t, spec)) return NULL; + Specialized * spec = mp_vector_at(sl, Specialized, i); + TmplArg arg = *mp_vector_at(tl, TmplArg, i); + if(unlikely(spec->td)) { +// check argument in call exp + continue; + } + DECL_OO(const Type, t, = known_type(env, arg.d.td)); + if(t->info->traits && miss_traits(t, spec)) + return NULL; } return f; } diff --git a/src/parse/operator.c b/src/parse/operator.c index 478b16bd..022ac4c9 100644 --- a/src/parse/operator.c +++ b/src/parse/operator.c @@ -228,22 +228,24 @@ ANN bool tmpl_match(const Env env, const struct Op_Import *opi, return true; } +ANN static void op_tmpl_set(const Gwion gwion, Type_List tl, + const Type t, const loc_t pos, const uint32_t idx) { + TmplArg arg = {.type = tmplarg_td, .d = { .td = type2td(gwion, t, pos)}}; + mp_vector_set(tl, TmplArg, idx, arg); +} + //! make template operator Func_def ANN static 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->call = new_mp_vector(env->gwion->mp, - Type_Decl*, fdef->base->tmpl->list->len); + TmplArg, fdef->base->tmpl->list->len); // we need to check op def for type, maybe if (opi->lhs) { - uint32_t idx = 0; - const Type lhs = find_type(env, mp_vector_at(fdef->base->args, Arg, 0)->td); - if(!lhs) - mp_vector_set(tmpl_fdef->base->tmpl->call, Type_Decl*, idx++, type2td(env->gwion, opi->lhs, opi->pos)); - const Type rhs = find_type(env, mp_vector_at(fdef->base->args, Arg, 1)->td); - if(!rhs) - mp_vector_set(tmpl_fdef->base->tmpl->call, Type_Decl*, idx, type2td(env->gwion, opi->rhs, opi->pos)); + op_tmpl_set(env->gwion, tmpl_fdef->base->tmpl->call, opi->lhs, opi->pos, 0); + if(opi->rhs) + op_tmpl_set(env->gwion, tmpl_fdef->base->tmpl->call, opi->rhs, opi->pos, 1); } else - mp_vector_set(tmpl_fdef->base->tmpl->call, Type_Decl*, 0, type2td(env->gwion, opi->rhs, opi->pos)); + op_tmpl_set(env->gwion, tmpl_fdef->base->tmpl->call, opi->rhs, opi->pos, 0); if (traverse_func_def(env, tmpl_fdef) < 0) { if (!tmpl_fdef->base->func) func_def_cleaner(env->gwion, tmpl_fdef); return NULL; @@ -485,3 +487,13 @@ ANN void op_cpy(const Env env, const struct Op_Import *opi) { op_visit(env->gwion->mp, env->curr, opi, &visited); vector_release(&visited); } + +ANN m_bool add_op_func_check(const Env env, const Type t, const struct Op_Func *opfunc, const m_uint idx) { + const Func f = (Func)vector_at(&t->nspc->vtable, idx); + const struct Op_Import opi = { + .rhs = f->value_ref->type, + .func = opfunc, + .data = (uintptr_t)f, + .op = insert_symbol(env->gwion->st, "@func_check")}; + return add_op(env->gwion, &opi); +} diff --git a/src/parse/scan1.c b/src/parse/scan1.c index 95eef097..2eab1fe2 100644 --- a/src/parse/scan1.c +++ b/src/parse/scan1.c @@ -835,6 +835,33 @@ ANN static m_bool scan1_class_def_body(const Env env, const Class_Def cdef) { return env_body(env, cdef, scan1_section); } +ANN static m_bool scan1_class_tmpl(const Env env, const Class_Def c) { + Specialized_List sl = c->base.tmpl->list; + Type_List tl = c->base.tmpl->call; + env_push_type(env, c->base.type); + m_bool ret = GW_OK; +// check len + for(uint32_t i = 0; i < sl->len; i++) { + const TmplArg targ = *mp_vector_at(tl, TmplArg, i); +// const Specialized spec = *mp_vector_at(sl, Specialized, i); + if (targ.type == tmplarg_td) continue; + if(scan1_exp(env, targ.d.exp) < 0) { + ret = GW_ERROR; + break; + } +/* + const Value v = new_value(env, env->gwion->type[et_int], s_name(spec.xid), targ.d.exp->pos); + valuefrom(env, v->from); + valid_value(env, spec.xid, v); + SET_FLAG(v, const| ae_flag_static); + set_vflag(v, vflag_builtin); + v->d.num = targ.d.exp->d.prim.d.gwint.num; +*/ + } + env_pop(env, 0); + return ret; +} + ANN m_bool scan1_class_def(const Env env, const Class_Def cdef) { if (tmpl_base(cdef->base.tmpl)) return GW_OK; const Type t = cdef->base.type; @@ -843,6 +870,7 @@ ANN m_bool scan1_class_def(const Env env, const Class_Def cdef) { const Class_Def c = t->info->cdef; if (c->base.ext) CHECK_BB(cdef_parent(env, c)); if (c->body) CHECK_BB(scan1_class_def_body(env, c)); + if (c->base.tmpl) CHECK_BB(scan1_class_tmpl(env, c)); return GW_OK; } diff --git a/src/parse/scan2.c b/src/parse/scan2.c index 7a90296e..6d473406 100644 --- a/src/parse/scan2.c +++ b/src/parse/scan2.c @@ -568,6 +568,18 @@ ANN static m_bool cdef_parent(const Env env, const Class_Def cdef) { return ret; } +ANN m_bool scan2_class_body(const Env env, const Class_Def c) { + const Tmpl *tmpl = c->base.tmpl; + if(tmpl && tmplarg_ntypes(tmpl->list) != tmpl->list->len) { + for(uint32_t i = 0; i < tmpl->list->len; i++) { + const TmplArg targ = *mp_vector_at(tmpl->call, TmplArg, i); + if(unlikely(targ.type != tmplarg_td)) + CHECK_BB(scan2_exp(env, targ.d.exp)); + } + } + return scan2_ast(env, &c->body); +} + ANN m_bool scan2_class_def(const Env env, const Class_Def cdef) { if (tmpl_base(cdef->base.tmpl)) return GW_OK; const Type t = cdef->base.type; @@ -580,7 +592,7 @@ ANN m_bool scan2_class_def(const Env env, const Class_Def cdef) { const Tmpl *tmpl = cdef->base.tmpl; if(tmpl && tmpl->call && tmpl->call != (Type_List)1 && tmpl->list) template_push_types(env, tmpl); - const m_bool ret = scan2_ast(env, &c->body); + const m_bool ret = scan2_class_body(env, c); if(tmpl && tmpl->call && tmpl->call != (Type_List)1 && tmpl->list) nspc_pop_type(env->gwion->mp, env->curr); env_pop(env, scope); diff --git a/src/parse/spread.c b/src/parse/spread.c index 6fd7c799..923efdf3 100644 --- a/src/parse/spread.c +++ b/src/parse/spread.c @@ -17,10 +17,12 @@ ANN m_bool spread_ast(const Env env, const Spread_Def spread, const Tmpl *tmpl) DECL_OB(FILE *,f, = fmemopen(data, strlen(data), "r")); for(uint32_t i = tmpl->list->len - 1; i < tmpl->call->len; i++) { fseek(f, 0, SEEK_SET); - Type_Decl* td = *mp_vector_at(tmpl->call, Type_Decl*, i); - DECL_OB(const Type, t, = known_type(env, td)); + const TmplArg targ = *mp_vector_at(tmpl->call, TmplArg, i); + // skip or error on const? + // or do smth else? + DECL_OB(const Type, t, = known_type(env, targ.d.td)); struct AstGetter_ arg = {env->name, f, env->gwion->st, .ppa = env->gwion->ppa}; - const m_str type = type2str(env->gwion, t, td->pos); + const m_str type = type2str(env->gwion, t, targ.d.td->pos); sprintf(c, "%s=%s", s_name(spread->xid), type); free_mstr(env->gwion->mp, type); pparg_add(env->gwion->ppa, c); diff --git a/src/parse/template.c b/src/parse/template.c index cf4940af..c44a7977 100644 --- a/src/parse/template.c +++ b/src/parse/template.c @@ -23,12 +23,13 @@ ANN static m_bool _push_types(const Env env, const Nspc nspc, if(!tl) return GW_OK; for(uint32_t i = 0; i < len; i++) { if (i >= tl->len) return GW_OK; - Type_Decl *td = *mp_vector_at(tl, Type_Decl*, i); - const Type t = known_type(env, td); + TmplArg arg = *mp_vector_at(tl, TmplArg, i); + if(unlikely(arg.type == tmplarg_exp)) continue; + const Type t = known_type(env, arg.d.td); Specialized *spec = mp_vector_at(sl, Specialized, i); nspc_add_type(nspc, spec->xid, t); }; -if(len != sl->len) return GW_OK; + if(len != sl->len) return GW_OK; return tl->len == sl->len ? GW_OK : GW_ERROR; } @@ -59,22 +60,33 @@ ANN m_bool template_push(const Env env, const Type t) { return _template_push(env, t); } +#include ANN void check_call(const Env env, const Tmpl *tmpl) { for(uint32_t i = 0; i < tmpl->call->len; i++) { - Specialized *spec = mp_vector_at(tmpl->list, Specialized, i); - Type_Decl *call = *mp_vector_at(tmpl->call, Type_Decl*, i); - if(spec->xid == call->xid) { - if (!nspc_lookup_type1(env->curr, spec->xid)) - call->xid = insert_symbol("auto"); - else { - const Type t = nspc_lookup_type1(env->curr, spec->xid); - Type_Decl *td = type2td(env->gwion, t, call->pos); - free_type_decl(env->gwion->mp, call); - mp_vector_set(tmpl->call, Type_Decl*, i, td); + Specialized *spec = i < tmpl->list->len + ? mp_vector_at(tmpl->list, Specialized, i) + : NULL; + TmplArg *targ = mp_vector_at(tmpl->call, TmplArg, i); + if(spec && strcmp(s_name(spec->xid), "...")) { + //spec->is_const) exit(12); + if(spec->xid == targ->d.td->xid) { + if (!nspc_lookup_type1(env->curr, spec->xid)) + targ->d.td->xid = insert_symbol("auto"); + else { + const Type t = nspc_lookup_type1(env->curr, spec->xid); + Type_Decl *td = type2td(env->gwion, t, targ->d.td->pos); + free_type_decl(env->gwion->mp, targ->d.td); + targ->d.td = td; + } } + } else { + //if(targ->type == tmplarg_td) + // targ->d.td->xid = insert_symbol("auto"); + //else what } } } + ANN m_bool template_push_types(const Env env, const Tmpl *tmpl) { nspc_push_type(env->gwion->mp, env->curr); if (tmpl->call) check_call(env, tmpl); @@ -144,15 +156,69 @@ ANN2(1,2) static m_bool check_tmpl(const Env env, const Type_List tl, const Spec 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)); + TmplArg *arg = mp_vector_at(tl, TmplArg, i); 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}'", + if(arg->type == tmplarg_td) { + + // could be an enum or smth + if(spec->td) { + +Type_Decl *base = arg->d.td; +Type_Decl *next = base; +Type_Decl *last = next->next; +while(next && last) { + if(!last->next) break; + last = last->next; + next = next->next; +} + +if(last) { + next->next = NULL; +const Type t = known_type(env, base); +// check no array? +// no template? +if(t) { + arg->type = tmplarg_exp; + Exp e = new_exp_td(env->gwion->mp, base, base->pos); + arg->d.exp = new_exp_dot(env->gwion->mp, e, last->xid, base->pos); +free_type_decl(env->gwion->mp, last); +// arg->d + +//turn into an exp; +i--;continue; +} + next->next = last; + +} + +//exit(3); + ERR_B(pos, "template type argument mismatch. expected %s", + spec->td ? "constant" : "type"); + } + + DECL_OB(const Type, t, = known_type(env, arg->d.td)); + if(spec->traits) { + Symbol missing = miss_traits(t, spec); + if (missing) { + ERR_B(pos, "does not implement requested trait '{/}%s{0}'", s_name(missing)); + } + } + } else { + if(!spec->td) { + ERR_B(pos, "template const argument mismatch. expected %s", + spec->td ? "constant" : "type"); } + + DECL_OB(const Type, t, = known_type(env, spec->td)); +CHECK_OB(check_exp(env, arg->d.exp)); +// DECL_OB(const Type, t, = nspc_lookup_valueh); +if(isa(arg->d.exp->type,t) < 0) + ERR_B(pos, "invalid type %s for template argument. expected %s", + arg->d.exp->type->name, t->name); + +// exit(13); +//puts("we could check here"); } } return GW_OK; @@ -170,7 +236,7 @@ ANN static Type _scan_type(const Env env, const Type t, Type_Decl *td) { if(!d->types) { if(!single_variadic) ERR_O(td->pos, _("you must provide template types for type '%s'"), t->name); - d->types = new_mp_vector(env->gwion->mp, Type_Decl*, 0); + d->types = new_mp_vector(env->gwion->mp, TmplArg, 0); } const Type ret = _scan_type(env, t, d); free_type_decl(env->gwion->mp, new_td); diff --git a/src/parse/type_decl.c b/src/parse/type_decl.c index 81916624..a95f1ed3 100644 --- a/src/parse/type_decl.c +++ b/src/parse/type_decl.c @@ -12,12 +12,13 @@ ANN static Type _option(const Env env, Type_Decl *td, const uint8_t n) { const Array_Sub array = td->array; td->array = NULL; - Type_List tl = new_mp_vector(env->gwion->mp, Type_Decl*, 1); - mp_vector_set(tl, Type_Decl*, 0, td); + Type_List tl = new_mp_vector(env->gwion->mp, TmplArg, 1); + TmplArg arg = { .type = tmplarg_td, .d = { .td = td } }; + mp_vector_set(tl, TmplArg, 0, arg); Type_Decl tmp = { .xid = insert_symbol("Option"), .types = tl, .pos = td->pos}; const Type t = !(n - 1) ? known_type(env, &tmp) : _option(env, &tmp, n - 1); - free_mp_vector(env->gwion->mp, Type_Decl*, tl); + free_mp_vector(env->gwion->mp, TmplArg, tl); td->array = array; return t; } @@ -31,11 +32,12 @@ ANN static Type option(const Env env, Type_Decl *td) { } ANN static Type _ref(const Env env, Type_Decl *td) { - Type_List tl = new_mp_vector(env->gwion->mp, Type_Decl*, 1); - mp_vector_set(tl, Type_Decl*, 0, td); + Type_List tl = new_mp_vector(env->gwion->mp, TmplArg, 1); + TmplArg arg = { .type = tmplarg_td, .d = { .td = td } }; + mp_vector_set(tl, TmplArg, 0, arg); Type_Decl tmp = {.xid = insert_symbol("Ref"), .types = tl, .pos = td->pos}; const Type t = known_type(env, &tmp); - free_mp_vector(env->gwion->mp, Type_Decl*, tl); + free_mp_vector(env->gwion->mp, TmplArg, tl); return t; }