From 6f9ca5c636d572a7a8b058afc336bb419fab60db Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=A9mie=20Astor?= Date: Fri, 6 Mar 2020 20:03:40 +0100 Subject: [PATCH] :art: use @scan operator --- include/operator.h | 6 ++ include/parse.h | 15 +++-- include/template.h | 1 + src/lib/object.c | 128 ++++++++++++++++++++++++++++++++++++ src/lib/tuple.c | 27 ++++++++ src/parse/check.c | 2 + src/parse/operator.c | 5 +- src/parse/scan1.c | 2 + src/parse/template.c | 152 +++---------------------------------------- src/parse/traverse.c | 3 + tests/new/dtor.gw | 6 +- 11 files changed, 195 insertions(+), 152 deletions(-) diff --git a/include/operator.h b/include/operator.h index a0466b5e..eae103e5 100644 --- a/include/operator.h +++ b/include/operator.h @@ -27,6 +27,12 @@ struct Implicit { Type t; loc_t pos; }; + +struct TemplateScan { + const Type t; + const Type_Decl *td; +}; + ANN m_bool add_op(const Gwion gwion, const struct Op_Import*); ANN Type op_check(const Env, struct Op_Import*); ANN struct Instr_* op_emit(const Emitter, const struct Op_Import*); diff --git a/include/parse.h b/include/parse.h index c9f62808..09f955a0 100644 --- a/include/parse.h +++ b/include/parse.h @@ -67,11 +67,18 @@ ANN m_bool scanx_cdef(const Env, void *,const Class_Def, #define xxx_cdef(prefix) \ static inline m_bool prefix##_cdef(const Env env, const Class_Def cdef) { \ return scanx_cdef(env, env, cdef, \ - (_exp_func)prefix##_class_def, (_exp_func)prefix##_union_def); \ + (_exp_func)prefix##_class_def, (_exp_func)prefix##_union_def); \ } -xxx_cdef(scan1) -xxx_cdef(scan2) -xxx_cdef(check) + +#define xxx_cdef_flag(prefix) \ +static inline m_bool prefix##_cdef(const Env env, const Class_Def cdef) { \ + SET_FLAG(cdef, prefix); \ + return scanx_cdef(env, env, cdef, \ + (_exp_func)prefix##_class_def, (_exp_func)prefix##_union_def); \ +} +xxx_cdef_flag(scan1) +xxx_cdef_flag(scan2) +xxx_cdef_flag(check) xxx_cdef(traverse) ANN m_bool scanx_fdef(const Env, void *, const Func_Def, const _exp_func); diff --git a/include/template.h b/include/template.h index a733a99b..b8db06a2 100644 --- a/include/template.h +++ b/include/template.h @@ -1,5 +1,6 @@ #ifndef __TEMPLATE #define __TEMPLATE ANN m_bool template_push_types(const Env, const Tmpl*); +ANN Tmpl* mk_tmpl(const Env, const Tmpl*, const Type_List); #define POP_RET(a) { nspc_pop_type(env->gwion->mp, env->curr); return (a); } #endif diff --git a/src/lib/object.c b/src/lib/object.c index 21d271b9..5c3cebf8 100644 --- a/src/lib/object.c +++ b/src/lib/object.c @@ -11,6 +11,7 @@ #include "import.h" #include "emit.h" #include "traverse.h" +#include "template.h" #include "parse.h" #include "specialid.h" @@ -225,6 +226,15 @@ static GACK(gack_object) { INTERP_PRINTF("%p", *(M_Object*)VALUE); } +ANN static Type scan_class(const Env env, const Type t, const Type_Decl* td); + +static OP_CHECK(opck_object_scan) { + struct TemplateScan *ts = (struct TemplateScan*)data; + if(ts->td->types) + return scan_class(env, ts->t, ts->td); + ERR_O(td_pos(ts->td), _("you must provide template types for type '%s'"), ts->t->name) +} + GWION_IMPORT(object) { const Type t_object = gwi_mk_type(gwi, "Object", SZ_INT, NULL); gwi_add_type(gwi, t_object); @@ -264,9 +274,127 @@ gwi_add_type(gwi, t_object); GWI_BB(gwi_oper_ini(gwi, NULL, "Object", "bool")) GWI_BB(gwi_oper_add(gwi, opck_unary_meta2)) GWI_BB(gwi_oper_end(gwi, "!", IntNot)) + GWI_BB(gwi_oper_ini(gwi, "Object", NULL, NULL)) + GWI_BB(gwi_oper_add(gwi, opck_object_scan)) + GWI_BB(gwi_oper_end(gwi, "@scan", NULL)) gwi_item_ini(gwi, "@null", "null"); gwi_item_end(gwi, 0, NULL); struct SpecialId_ spid = { .ck=check_this, .exec=RegPushMem, .is_const=1 }; gwi_specialid(gwi, "this", &spid); return GW_OK; } +struct tmpl_info { + const Class_Def cdef; + Type_List call; + struct Vector_ type; + struct Vector_ size; + uint8_t index; +}; + +ANN static inline size_t tmpl_set(struct tmpl_info* info, const Type t) { + vector_add(&info->type, (vtype)t); + const size_t len = strlen(t->name); + vector_add(&info->size, len); + return len; +} + +ANN static ssize_t template_size(const Env env, struct tmpl_info* info) { + ID_List base = info->cdef->base.tmpl->list; + Type_List call = info->call; + size_t size = tmpl_set(info, info->cdef->base.type); + do { + DECL_OB(const Type, t, = known_type(env, call->td)) + size += tmpl_set(info, t); + } while((call = call->next) && (base = base->next) && ++size); + return size + 16 + 3; +} + +ANN static inline m_str tmpl_get(struct tmpl_info* info, m_str str) { + const Type t = (Type)vector_at(&info->type, info->index); + strcpy(str, t->name); + return str += vector_at(&info->size, info->index); +} + +ANN static void template_name(struct tmpl_info* info, m_str s) { + m_str str = s; + str = tmpl_get(info, str); + *str++ = '<'; + *str++ = '~'; + const m_uint size = vector_size(&info->type); + for(info->index = 1; info->index < size; ++info->index) { + str = tmpl_get(info, str); + if(info->index < size - 1) + *str++ = ','; + else { + *str++ = '~'; + *str++ = '>'; + } + } + *str = '\0'; +} + +ANEW ANN static Symbol template_id(const Env env, const Class_Def c, const Type_List call) { + struct tmpl_info info = { .cdef=c, .call=call }; + vector_init(&info.type); + vector_init(&info.size); + ssize_t sz = template_size(env, &info); + char name[sz]; + if(sz > GW_ERROR) + template_name(&info, name); + vector_release(&info.type); + vector_release(&info.size); + return sz > GW_ERROR ? insert_symbol(env->gwion->st, name) : NULL; +} + +ANN m_bool template_match(ID_List base, Type_List call) { + while((call = call->next) && (base = base->next)); + return !call ? GW_OK : GW_ERROR; +} + +ANN static Class_Def template_class(const Env env, const Class_Def def, const Type_List call) { + DECL_OO(const Symbol, name, = template_id(env, def, call)) + if(env->class_def && name == insert_symbol(env->gwion->st, env->class_def->name)) + return env->class_def->e->def; + const Type t = nspc_lookup_type1(env->curr, name); + if(t) + return t->e->def; + const Class_Def c = cpy_class_def(env->gwion->mp, def); + c->base.xid = name; + SET_FLAG(c, template | ae_flag_ref); + return c; + +} + +extern ANN m_bool scan0_class_def(const Env, const Class_Def); +extern ANN m_bool scan1_class_def(const Env, const Class_Def); +extern ANN m_bool traverse_func_def(const Env, const Func_Def); +extern ANN m_bool traverse_class_def(const Env, const Class_Def); + +ANN static m_bool class2udef(const Env env, const Class_Def a, const Type t) { + a->union_def = new_union_def(env->gwion->mp, a->list, + loc_cpy(env->gwion->mp, t->e->def->pos)); + a->union_def->type_xid = a->base.xid; + CHECK_BB(scan0_union_def(env, a->union_def)) + SET_FLAG(a, scan0); + a->base.type = a->union_def->type; + a->base.type->e->def = a; + return GW_OK; +} + +ANN static Type scan_class(const Env env, const Type t, const Type_Decl* td) { + if(template_match(t->e->def->base.tmpl->list, td->types) < 0) + ERR_O(td->xid->pos, _("invalid template types number")) + DECL_OO(const Class_Def, a, = template_class(env, t->e->def, td->types)) + if(a->base.type) + return a->base.type; + a->base.tmpl = mk_tmpl(env, t->e->def->base.tmpl, td->types); + if(t->e->parent != env->gwion->type[et_union]) + CHECK_BO(scan0_class_def(env, a)) + else + CHECK_BO(class2udef(env, a, t)) + SET_FLAG(a->base.type, template); + if(GET_FLAG(t, builtin)) + SET_FLAG(a->base.type, builtin); + CHECK_BO(scan1_cdef(env, a)) + return a->base.type; +} diff --git a/src/lib/tuple.c b/src/lib/tuple.c index 780cd87b..ca97a433 100644 --- a/src/lib/tuple.c +++ b/src/lib/tuple.c @@ -416,6 +416,12 @@ static OP_EMIT(opem_at_unpack) { return (Instr)GW_OK; } +ANN static Type scan_tuple(const Env env, const Type_Decl *td); +static OP_CHECK(opck_tuple_scan) { + struct TemplateScan *ts = (struct TemplateScan*)data; + return ts->td->types ? scan_tuple(env, ts->td) : ts->t; +} + GWION_IMPORT(tuple) { const Type t_tuple = gwi_mk_type(gwi, "Tuple", SZ_INT, "Object"); gwi_add_type(gwi, t_tuple); @@ -426,6 +432,8 @@ GWION_IMPORT(tuple) { GWI_BB(gwi_oper_add(gwi, tuple_ck)) GWI_BB(gwi_oper_emi(gwi, tuple_em)) GWI_BB(gwi_oper_end(gwi, "@ctor", NULL)) + GWI_BB(gwi_oper_add(gwi, opck_tuple_scan)) + GWI_BB(gwi_oper_end(gwi, "@scan", NULL)) GWI_BB(gwi_oper_ini(gwi, "Object", "Tuple", NULL)) GWI_BB(gwi_oper_add(gwi, opck_at_object_tuple)) GWI_BB(gwi_oper_end(gwi, "@=>", ObjectAssign)) @@ -475,3 +483,22 @@ GWION_IMPORT(tuple) { GWI_BB(gwi_oper_end(gwi, "==", NULL)) return GW_OK; } + +static ANN Type scan_tuple(const Env env, const Type_Decl *td) { + struct Vector_ v; + vector_init(&v); + Type_List tl = td->types; + do { + const Type t = tl->td->xid->xid != insert_symbol("_") ? + known_type(env, tl->td) : (Type)1; + if(t) + vector_add(&v, (m_uint)t); + else { + vector_release(&v); + return env->gwion->type[et_null]; + } + } while((tl = tl->next)); + const Type ret = tuple_type(env, &v, td_pos(td)); + vector_release(&v); + return ret; +} diff --git a/src/parse/check.c b/src/parse/check.c index 67eb2d15..5f67e708 100644 --- a/src/parse/check.c +++ b/src/parse/check.c @@ -978,6 +978,8 @@ ANN static m_bool do_stmt_auto(const Env env, const Stmt_Auto stmt) { td.xid = &id; tl.td = &td0; td.types = &tl; + td0.xid->pos = stmt->exp->pos; + td.xid->pos = stmt->exp->pos; if(depth) { array.depth = depth; td.array = &array; diff --git a/src/parse/operator.c b/src/parse/operator.c index e8a2a653..e8395899 100644 --- a/src/parse/operator.c +++ b/src/parse/operator.c @@ -144,6 +144,7 @@ ANN m_bool add_op(const Gwion gwion, const struct Op_Import* opi) { } ANN static void set_nspc(struct OpChecker* ock, const Nspc nspc) { +printf("here %s\n", nspc->name); if(ock->opi->op == insert_symbol(ock->env->gwion->st, "@array")) { Array_Sub array = (Array_Sub)ock->opi->data; array->exp->nspc = nspc; @@ -164,7 +165,9 @@ ANN static void set_nspc(struct OpChecker* ock, const Nspc nspc) { ((Exp)ock->opi->data)->nspc = nspc; return; } - exp_self((union exp_data*)ock->opi->data)->nspc = nspc; +// use .mut + if(ock->opi->op != insert_symbol(ock->env->gwion->st, "@scan")) + exp_self((union exp_data*)ock->opi->data)->nspc = nspc; } ANN static Type op_check_inner(struct OpChecker* ock) { diff --git a/src/parse/scan1.c b/src/parse/scan1.c index 4fc66782..35c7b289 100644 --- a/src/parse/scan1.c +++ b/src/parse/scan1.c @@ -292,6 +292,8 @@ ANN m_bool scan1_type_def(const Env env, const Type_Def tdef) { ANN m_bool scan1_union_def_action(const Env env, const Union_Def udef, const Decl_List l) { + if(GET_FLAG(udef, scan1)) + return GW_OK; const Exp_Decl decl = l->self->d.exp_decl; SET_FLAG(decl.td, checked | udef->flag); const m_bool global = GET_FLAG(udef, global); diff --git a/src/parse/template.c b/src/parse/template.c index fb84336e..0ae30a9f 100644 --- a/src/parse/template.c +++ b/src/parse/template.c @@ -7,7 +7,7 @@ #include "vm.h" #include "parse.h" #include "gwion.h" -#include "tuple.h" +#include "operator.h" struct tmpl_info { const Class_Def cdef; @@ -17,80 +17,6 @@ struct tmpl_info { uint8_t index; }; -ANN static inline size_t tmpl_set(struct tmpl_info* info, const Type t) { - vector_add(&info->type, (vtype)t); - const size_t len = strlen(t->name); - vector_add(&info->size, len); - return len; -} - -ANN static ssize_t template_size(const Env env, struct tmpl_info* info) { - ID_List base = info->cdef->base.tmpl->list; - Type_List call = info->call; - size_t size = tmpl_set(info, info->cdef->base.type); - do { - DECL_OB(const Type, t, = known_type(env, call->td)) - size += tmpl_set(info, t); - } while((call = call->next) && (base = base->next) && ++size); - return size + 16 + 3; -} - -ANN static inline m_str tmpl_get(struct tmpl_info* info, m_str str) { - const Type t = (Type)vector_at(&info->type, info->index); - strcpy(str, t->name); - return str += vector_at(&info->size, info->index); -} - -ANN static void template_name(struct tmpl_info* info, m_str s) { - m_str str = s; - str = tmpl_get(info, str); - *str++ = '<'; - *str++ = '~'; - const m_uint size = vector_size(&info->type); - for(info->index = 1; info->index < size; ++info->index) { - str = tmpl_get(info, str); - if(info->index < size - 1) - *str++ = ','; - else { - *str++ = '~'; - *str++ = '>'; - } - } - *str = '\0'; -} - -ANEW ANN static Symbol template_id(const Env env, const Class_Def c, const Type_List call) { - struct tmpl_info info = { .cdef=c, .call=call }; - vector_init(&info.type); - vector_init(&info.size); - ssize_t sz = template_size(env, &info); - char name[sz]; - if(sz > GW_ERROR) - template_name(&info, name); - vector_release(&info.type); - vector_release(&info.size); - return sz > GW_ERROR ? insert_symbol(name) : NULL; -} - -ANN m_bool template_match(ID_List base, Type_List call) { - while((call = call->next) && (base = base->next)); - return !call ? GW_OK : GW_ERROR; -} - -ANN static Class_Def template_class(const Env env, const Class_Def def, const Type_List call) { - DECL_OO(const Symbol, name, = template_id(env, def, call)) - if(env->class_def && name == insert_symbol(env->class_def->name)) - return env->class_def->e->def; - const Type t = nspc_lookup_type1(env->curr, name); - if(t) - return t->e->def; - const Class_Def c = cpy_class_def(env->gwion->mp, def); - c->base.xid = name; - SET_FLAG(c, template | ae_flag_ref); - return c; - -} - ANN m_bool template_push_types(const Env env, const Tmpl *tmpl) { ID_List list = tmpl->list; Type_List call = tmpl->call; @@ -109,65 +35,13 @@ ANN m_bool template_push_types(const Env env, const Tmpl *tmpl) { POP_RET(-1); } -extern ANN m_bool scan0_class_def(const Env, const Class_Def); -extern ANN m_bool scan1_class_def(const Env, const Class_Def); -extern ANN m_bool traverse_func_def(const Env, const Func_Def); -extern ANN m_bool traverse_class_def(const Env, const Class_Def); - -ANN Type scan_tuple(const Env env, const Type_Decl *td) { - struct Vector_ v; - vector_init(&v); - Type_List tl = td->types; - do { - const Type t = tl->td->xid->xid != insert_symbol("_") ? - known_type(env, tl->td) : (Type)1; - if(t) - vector_add(&v, (m_uint)t); - else { - vector_release(&v); - return NULL; - } - } while((tl = tl->next)); - const Type ret = tuple_type(env, &v, td_pos(td)); - vector_release(&v); - return ret; -} - ANN Tmpl* mk_tmpl(const Env env, const Tmpl *tm, const Type_List types) { Tmpl *tmpl = new_tmpl(env->gwion->mp, tm->list, 0); tmpl->call = cpy_type_list(env->gwion->mp, types); return tmpl; } -ANN static m_bool class2udef(const Env env, const Class_Def a, const Type t) { - a->union_def = new_union_def(env->gwion->mp, a->list, - loc_cpy(env->gwion->mp, t->e->def->pos)); - a->union_def->type_xid = a->base.xid; - CHECK_BB(scan0_union_def(env, a->union_def)) - a->base.type = a->union_def->type; - a->base.type->e->def = a; - return GW_OK; -} - -ANN static Type scan_class(const Env env, const Type t, const Type_Decl* td) { - if(template_match(t->e->def->base.tmpl->list, td->types) < 0) - ERR_O(td->xid->pos, _("invalid template types number")) - DECL_OO(const Class_Def, a, = template_class(env, t->e->def, td->types)) - if(a->base.type) - return a->base.type; - a->base.tmpl = mk_tmpl(env, t->e->def->base.tmpl, td->types); - if(t->e->parent != env->gwion->type[et_union]) - CHECK_BO(scan0_class_def(env, a)) - else - CHECK_BO(class2udef(env, a, t)) - SET_FLAG(a->base.type, template); - if(GET_FLAG(t, builtin)) - SET_FLAG(a->base.type, builtin); - CHECK_BO(scan1_cdef(env, a)) - return a->base.type; -} - -ANN Type scan_func(const Env env, const Type t, const Type_Decl* td) { +static ANN Type scan_func(const Env env, const Type t, const Type_Decl* td) { DECL_OO(const m_str, tl_name, = tl2str(env, td->types)) const Symbol sym = func_symbol(env, t->e->owner->name, t->e->d.func->name, tl_name, 0); free_mstr(env->gwion->mp, tl_name); @@ -194,14 +68,7 @@ ANN Type scan_func(const Env env, const Type t, const Type_Decl* td) { return ret; } -ANN Type no_types(const Env env, const Type t) { - if(t != env->gwion->type[et_tuple]) - ERR_O(t->e->def->pos, - _("you must provide template types for type '%s'"), t->name) - return t; -} - -ANN Type maybe_func(const Env env, const Type t, const Type_Decl* td) { +static ANN Type maybe_func(const Env env, const Type t, const Type_Decl* td) { if(isa(t, env->gwion->type[et_function]) > 0 && t->e->d.func->def->base->tmpl) return scan_func(env, t, td); ERR_O(td->xid->pos, @@ -212,13 +79,10 @@ ANN Type scan_type(const Env env, const Type t, const Type_Decl* td) { if(GET_FLAG(t, template)) { if(GET_FLAG(t, ref)) return t; - if(!td->types) - return no_types(env, t); - if(t->e->def) - return scan_class(env, t, td); - else - return scan_tuple(env, td); - } else if(td->types) - return maybe_func(env, t, td); + struct TemplateScan ts = { .t=t, .td=td }; + struct Op_Import opi = { .op=insert_symbol("@scan"), .lhs=t, .data=(uintptr_t)&ts, .pos=td_pos(td) }; + return op_check(env, &opi); + } else if(td->types) + return maybe_func(env, t, td); return t; } diff --git a/src/parse/traverse.c b/src/parse/traverse.c index 79a13c5b..ae9fb3e5 100644 --- a/src/parse/traverse.c +++ b/src/parse/traverse.c @@ -28,7 +28,10 @@ ANN m_bool traverse_func_def(const Env env, const Func_Def def) { ANN m_bool traverse_union_def(const Env env, const Union_Def def) { if(!GET_FLAG(def, scan1)) CHECK_BB(scan1_union_def(env, def)) + if(!GET_FLAG(def, scan2)) CHECK_BB(scan2_union_def(env, def)) + if(!GET_FLAG(def, check)) + CHECK_BB(check_union_def(env, def)) return check_union_def(env, def); } diff --git a/tests/new/dtor.gw b/tests/new/dtor.gw index d549ea50..94de83a1 100644 --- a/tests/new/dtor.gw +++ b/tests/new/dtor.gw @@ -1,11 +1,11 @@ class <~A~>C { - operator @dtor void { <<< __func__ >>>; } + operator @dtor void () { <<< __func__ >>>; } } class <~A~>D extends <~A~>C { - operator @dtor { <<< __func__ >>>; } + operator @dtor void () { <<< __func__ >>>; } } class E extends <~int~>D { - operator @dtor { <<< __func__ >>>; } + operator @dtor void () { <<< __func__ >>>; } } E e; -- 2.43.0