From 48d0806f8df80dd6016e37d1de49e0a34737b9aa Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=A9mie=20Astor?= Date: Thu, 7 May 2020 18:57:37 +0200 Subject: [PATCH] :bug: Fix cyclic types and imporve flaging --- src/emit/emit.c | 11 ++++----- src/env/env.c | 4 ---- src/env/type.c | 3 +-- src/import/tdef.c | 3 --- src/lib/object_op.c | 1 - src/parse/check.c | 15 +++---------- src/parse/scan0.c | 28 ++++++++++++++++++----- src/parse/scan1.c | 53 ++++++++++++++++++++++++++++++-------------- src/parse/scan2.c | 13 +++++------ src/parse/traverse.c | 13 ++++++----- 10 files changed, 79 insertions(+), 65 deletions(-) diff --git a/src/emit/emit.c b/src/emit/emit.c index 888bd3fc..93af7968 100644 --- a/src/emit/emit.c +++ b/src/emit/emit.c @@ -1568,7 +1568,6 @@ ANN static m_bool emit_union_def(const Emitter emit, const Union_Def udef) { const Var_Decl_List var_decl_list = new_var_decl_list(emit->gwion->mp, var_decl, NULL); const Exp exp = new_exp_decl(emit->gwion->mp, type_decl, var_decl_list); exp->d.exp_decl.type = udef->value->type; - SET_FLAG(udef->value->type, emit); var_decl->value = udef->value; const m_bool ret = emit_exp_decl(emit, &exp->d.exp_decl); free_exp(emit->gwion->mp, exp); @@ -1582,7 +1581,6 @@ ANN static m_bool emit_union_def(const Emitter emit, const Union_Def udef) { scope = emit_push_type(emit, udef->value->type); } else if(udef->type_xid) { union_allocdata(emit->gwion->mp, udef); - SET_FLAG(udef->type, emit); scope = emit_push_type(emit, udef->type); } else if(global) { // TODO: use mpool allocation @@ -1604,6 +1602,7 @@ ANN static m_bool emit_union_def(const Emitter emit, const Union_Def udef) { emit_union_offset(udef->l, udef->o); if(udef->xid || udef->type_xid || global) emit_pop(emit, scope); + union_flag(udef, ae_flag_emit); return GW_OK; } @@ -1994,11 +1993,10 @@ ANN static m_bool emit_struct_body2(const Emitter emit, Section *const section) emit_section(emit, section) : GW_OK; } -ANN static m_bool emit_class_def(const Emitter emit, const Class_Def c) { - if(tmpl_base(c->base.tmpl)) +ANN static m_bool emit_class_def(const Emitter emit, const Class_Def cdef) { + if(tmpl_base(cdef->base.tmpl)) return GW_OK; - const Type t = c->base.type; - const Class_Def cdef = t->e->def; + const Type t = cdef->base.type; if(GET_FLAG(t, emit)) return GW_OK; if(cdef->base.ext && t->e->parent->e->def && !GET_FLAG(t->e->parent, emit)) @@ -2013,7 +2011,6 @@ ANN static m_bool emit_class_def(const Emitter emit, const Class_Def c) { } else CHECK_BB(scanx_body(emit->env, cdef, (_exp_func)emit_struct_body2, emit)) } - SET_FLAG(t, emit); return GW_OK; } diff --git a/src/env/env.c b/src/env/env.c index c0d606b4..40065470 100644 --- a/src/env/env.c +++ b/src/env/env.c @@ -87,10 +87,6 @@ ANN void env_add_type(const Env env, const Type type) { const Value v = new_value(env->gwion->mp, v_type, s_name(sym)); SET_FLAG(v, checked | ae_flag_const | ae_flag_global | ae_flag_builtin); nspc_add_value(env->curr, insert_symbol(type->name), v); -// valuefrom(env, v->from); -// typefrom(env, type->e->from); -// v->from->owner = type->e->from->owner = env->curr; -// type->e->owner = env->curr; v->from->owner = type->e->owner = env->curr; v->from->owner_class = type->e->owner_class = env->class_def; // t owner_class ? type->xid = ++env->scope->type_xid; diff --git a/src/env/type.c b/src/env/type.c index 46fe3001..829cff69 100644 --- a/src/env/type.c +++ b/src/env/type.c @@ -7,8 +7,7 @@ #include "gwion.h" ANN static inline m_bool freeable(const Type a) { - return !GET_FLAG(a, nonnull) && - (GET_FLAG(a, template) || GET_FLAG(a, global)); + return !GET_FLAG(a, nonnull) && GET_FLAG(a, template); } ANN static void free_type(Type a, Gwion gwion) { diff --git a/src/import/tdef.c b/src/import/tdef.c index 4fa9d050..46bd7bcb 100644 --- a/src/import/tdef.c +++ b/src/import/tdef.c @@ -21,9 +21,6 @@ ANN m_int gwi_typedef_ini(const Gwi gwi, const restrict m_str type, const restri gwi->ck->name = name; CHECK_BB(check_typename_def(gwi, gwi->ck)) return (gwi->ck->td = str2decl(gwi, type)) ? GW_OK : GW_ERROR; -// if(check_typename_def(gwi, gwi->ck) > 0) -// return (gwi->ck->td = str2decl(gwi, type)) ? GW_OK : GW_ERROR; -// return GW_ERROR; } ANN Type gwi_typedef_end(const Gwi gwi, const ae_flag flag) { diff --git a/src/lib/object_op.c b/src/lib/object_op.c index a900ad8d..7bf90320 100644 --- a/src/lib/object_op.c +++ b/src/lib/object_op.c @@ -378,7 +378,6 @@ ANN static m_bool class2udef(const Env env, const Class_Def a, const Type t) { if(GET_FLAG(t, global)) SET_FLAG(a->union_def, global); 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; a->union_def->tmpl = cpy_tmpl(env->gwion->mp, a->base.tmpl); diff --git a/src/parse/check.c b/src/parse/check.c index 93bc1244..6c8cefae 100644 --- a/src/parse/check.c +++ b/src/parse/check.c @@ -167,14 +167,6 @@ ANN Type check_exp_decl(const Env env, const Exp_Decl* decl) { ERR_O(td_pos(decl->td), _("can't find type")); { const Type t = get_type(decl->type); - if(env->class_def && !env->scope->depth){ - Type parent = t; - while(parent) { - if(parent == env->class_def && !GET_FLAG(decl->td, ref)) - ERR_O(decl->td->pos, "declaration cycle detected. (declare as ref?)") - parent = parent->e->parent; - } - } if(!GET_FLAG(t, check) && t->e->def) CHECK_BO(ensure_check(env, t)) } @@ -1363,11 +1355,10 @@ ANN static m_bool cdef_parent(const Env env, const Class_Def cdef) { return ret; } -ANN m_bool check_class_def(const Env env, const Class_Def c) { - if(tmpl_base(c->base.tmpl)) +ANN m_bool check_class_def(const Env env, const Class_Def cdef) { + if(tmpl_base(cdef->base.tmpl)) return GW_OK; - const Type t = c->base.type; - const Class_Def cdef = t->e->def; + const Type t = cdef->base.type; if(t->e->owner_class && !GET_FLAG(t->e->owner_class, check)) CHECK_BB(check_class_def(env, t->e->owner_class->e->def)) if(GET_FLAG(t, check))return GW_OK; diff --git a/src/parse/scan0.c b/src/parse/scan0.c index 1cc3d60e..0af9b5b3 100644 --- a/src/parse/scan0.c +++ b/src/parse/scan0.c @@ -231,10 +231,9 @@ ANN static Type union_type(const Env env, const Symbol s, const m_bool add) { t->e->owner_class = env->class_def; t->e->parent = env->gwion->type[et_union]; add_type(env, env->curr, t); - if(add) { + if(add) mk_class(env, t); - } - SET_FLAG(t, union | ae_flag_scan0); + SET_FLAG(t, union); return t; } @@ -246,7 +245,6 @@ ANN static void union_tmpl(const Env env, const Union_Def udef) { udef->type->e->def = cdef; cdef->base.tmpl = cpy_tmpl(env->gwion->mp, udef->tmpl); cdef->base.type = udef->type; -// cdef->list = cpy_decl_list(env->gwion->mp, udef->l); SET_FLAG(cdef, union); SET_FLAG(udef->type, pure); SET_FLAG(udef, template); @@ -296,6 +294,7 @@ ANN m_bool scan0_union_def(const Env env, const Union_Def udef) { union_tmpl(env, udef); if(GET_FLAG(udef, global)) env_pop(env, scope); + union_flag(udef, ae_flag_scan0); return GW_OK; } @@ -314,9 +313,26 @@ ANN static void cdef_flag(const Class_Def cdef, const Type t) { SET_FLAG(t, typedef); } +ANN static Type get_parent(const Env env, const Class_Def cdef) { + if(GET_FLAG(cdef, struct)) + return NULL; + if(!cdef->base.ext) + return env->gwion->type[et_object]; + if(tmpl_base(cdef->base.tmpl)) + return nspc_lookup_type1(env->curr, cdef->base.ext->xid); + if(cdef->base.tmpl) + template_push_types(env, cdef->base.tmpl); + const Type t = known_type(env, cdef->base.ext); + if(cdef->base.tmpl) + nspc_pop_type(env->gwion->mp, env->curr); + return t ?: (Type)GW_ERROR; +} + ANN static Type scan0_class_def_init(const Env env, const Class_Def cdef) { CHECK_BO(scan0_defined(env, cdef->base.xid, cdef->pos)) - const Type parent = !GET_FLAG(cdef, struct) ? env->gwion->type[et_object] : NULL; + const Type parent = get_parent(env, cdef); + if(parent == (Type)GW_ERROR) + return NULL; const Type t = scan0_type(env, ++env->scope->type_xid, s_name(cdef->base.xid), parent); if(GET_FLAG(cdef, struct)) { SET_FLAG(t, struct); @@ -360,7 +376,7 @@ ANN static m_bool scan0_class_def_inner(const Env env, const Class_Def cdef) { } ANN m_bool scan0_class_def(const Env env, const Class_Def c) { - const Class_Def cdef = !(GET_FLAG(c, global) || (c->base.tmpl && !c->base.tmpl->call)) ? + const Class_Def cdef = !tmpl_base(c->base.tmpl) ? c : cpy_class_def(env->gwion->mp, c); if(GET_FLAG(cdef, global)) { vector_add(&env->scope->nspc_stack, (vtype)env->curr); diff --git a/src/parse/scan1.c b/src/parse/scan1.c index 2cef2840..a78ae058 100644 --- a/src/parse/scan1.c +++ b/src/parse/scan1.c @@ -9,6 +9,22 @@ ANN static m_bool scan1_stmt_list(const Env env, Stmt_List list); ANN static m_bool scan1_stmt(const Env env, Stmt stmt); +ANN static inline m_bool type_cyclic(const Env env, const Type t, const Type_Decl *td) { + Type parent = t->e->parent; + while(parent) { + if(parent == env->class_def) + ERR_B(td_pos(td), _("%s declared inside %s\n. (make it a ref ?)"), t->name, t == env->class_def ? "itself" : env->class_def->name); + parent = parent->e->parent; + } + return GW_OK; +} + +ANN static inline m_bool ensure_scan1(const Env env, const Type t) { + struct EnvSet es = { .env=env, .data=env, .func=(_exp_func)scan1_cdef, + .scope=env->scope->depth, .flag=ae_flag_scan1 }; + return envset_run(&es, t); +} + ANN static m_bool type_recursive(const Env env, const Type_Decl *td, const Type t) { if(env->class_def && !env->scope->depth) { const m_int idx = vector_find(&env->scope->class_stack, (vtype)t); @@ -19,11 +35,19 @@ ANN static m_bool type_recursive(const Env env, const Type_Decl *td, const Type return GW_OK; } -ANN static Type void_type(const Env env, Type_Decl* td) { +ANN static Type scan1_type(const Env env, Type_Decl* td) { DECL_OO(const Type, type, = known_type(env, td)) const Type t = get_type(type); - if(isa(t, env->gwion->type[et_object]) > 0 || GET_FLAG(t, struct)) - CHECK_BO(type_recursive(env, td, t)) + CHECK_BO(type_cyclic(env, t, td)) + if(!GET_FLAG(t, scan1) && t->e->def) + CHECK_BO(ensure_scan1(env, t)) + return type; +} + +ANN static Type void_type(const Env env, Type_Decl* td) { + DECL_OO(const Type, type, = scan1_type(env, td)) + if(isa(type, env->gwion->type[et_object]) > 0 || GET_FLAG(type, struct)) + CHECK_BO(type_recursive(env, td, type)) if(type->size) return type; ERR_O(td_pos(td), _("cannot declare variables of size '0' (i.e. 'void')...")) @@ -301,7 +325,7 @@ ANN m_bool scan1_fptr_def(const Env env, const Fptr_Def fptr) { fptr->type = nspc_lookup_type0(env->curr, fptr->base->xid); } const Func_Def fdef = fptr->base->func->def; - CHECK_OB((fdef->base->ret_type = known_type(env, fdef->base->td))) + CHECK_OB((fdef->base->ret_type = scan1_type(env, fdef->base->td))) return fdef->base->args ? scan1_args(env, fdef->base->args) : GW_OK; } @@ -314,8 +338,6 @@ 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); @@ -327,7 +349,6 @@ ANN m_bool scan1_union_def_action(const Env env, const Union_Def udef, SET_FLAG(decl.td, static); if(udef->tmpl && udef->tmpl->call) CHECK_BB(template_push_types(env, udef->tmpl)) - SET_FLAG(decl.td, ref); const m_bool ret = scan1_exp(env, l->self); if(udef->tmpl && udef->tmpl->call) nspc_pop_type(env->gwion->mp, env->curr); @@ -339,7 +360,6 @@ ANN m_bool scan1_union_def_action(const Env env, const Union_Def udef, if(global) SET_FLAG(decl.td, global); - union_flag(udef, ae_flag_scan1); return GW_OK; } @@ -360,8 +380,7 @@ ANN m_bool scan1_union_def(const Env env, const Union_Def udef) { } const m_bool ret = scan1_union_def_inner(env, udef); union_pop(env, udef, scope); - const Type type = udef->xid || !udef->type_xid ? udef->value->type : udef->type; - SET_FLAG(type, scan1); + union_flag(udef, ae_flag_scan1); return ret; } @@ -505,15 +524,15 @@ ANN static m_bool cdef_parent(const Env env, const Class_Def cdef) { return ret; } -ANN m_bool scan1_class_def(const Env env, const Class_Def c) { - if(tmpl_base(c->base.tmpl)) +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; + if(GET_FLAG(t, scan1)) return GW_OK; - const Type t = c->base.type; - const Class_Def cdef = t->e->def; - if(GET_FLAG(t, scan1))return GW_OK; - SET_FLAG(cdef, scan1); + SET_FLAG(t, scan1); if(t->e->owner_class && !GET_FLAG(t->e->owner_class, scan1)) - CHECK_BB(scan1_class_def(env, t->e->owner_class->e->def)) + CHECK_BB(ensure_scan1(env, t->e->owner_class)) SET_FLAG(cdef->base.type, scan1); if(cdef->base.ext) CHECK_BB(cdef_parent(env, cdef)) diff --git a/src/parse/scan2.c b/src/parse/scan2.c index 8f38e935..69b3bfeb 100644 --- a/src/parse/scan2.c +++ b/src/parse/scan2.c @@ -21,7 +21,7 @@ ANN static inline m_bool ensure_scan2(const Env env, const Type t) { ANN static m_bool scan2_decl(const Env env, const Exp_Decl* decl) { const Type t = get_type(decl->type); - if(!GET_FLAG(t, scan2) && t->e->def) + if(t->e->def && !GET_FLAG(t, scan2)) CHECK_BB(ensure_scan2(env, t)) Var_Decl_List list = decl->list; do { @@ -276,7 +276,6 @@ ANN m_bool scan2_union_def(const Env env, const Union_Def udef) { const m_uint scope = union_push(env, udef); const m_bool ret = scan2_union_decl(env, udef->l); union_pop(env, udef, scope); - SET_FLAG(udef, scan2); union_flag(udef, ae_flag_scan2); return ret; } @@ -560,7 +559,8 @@ HANDLE_SECTION_FUNC(scan2, m_bool, Env) ANN static m_bool scan2_parent(const Env env, const Class_Def cdef) { const Type parent = cdef->base.type->e->parent; - if(parent->e->def && !GET_FLAG(parent, scan2)) +// if(parent->e->def && !GET_FLAG(parent, scan2)) + if(!GET_FLAG(parent, scan2)) CHECK_BB(scanx_parent(parent, scan2_cdef, env)) if(cdef->base.ext->array) CHECK_BB(scan2_exp(env, cdef->base.ext->array->exp)) @@ -576,11 +576,10 @@ ANN static m_bool cdef_parent(const Env env, const Class_Def cdef) { return ret; } -ANN m_bool scan2_class_def(const Env env, const Class_Def c) { - if(tmpl_base(c->base.tmpl)) +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 = c->base.type; - const Class_Def cdef = t->e->def; + const Type t = cdef->base.type; if(GET_FLAG(t, scan2))return GW_OK; if(t->e->owner_class && !GET_FLAG(t->e->owner_class, scan2)) CHECK_BB(scan2_class_def(env, t->e->owner_class->e->def)) diff --git a/src/parse/traverse.c b/src/parse/traverse.c index ae9fb3e5..a21df7ba 100644 --- a/src/parse/traverse.c +++ b/src/parse/traverse.c @@ -26,11 +26,11 @@ 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)) +// if(!GET_FLAG(def, scan1)) CHECK_BB(scan1_union_def(env, def)) - if(!GET_FLAG(def, scan2)) +// if(!GET_FLAG(def, scan2)) CHECK_BB(scan2_union_def(env, def)) - if(!GET_FLAG(def, check)) +// if(!GET_FLAG(def, check)) CHECK_BB(check_union_def(env, def)) return check_union_def(env, def); } @@ -57,11 +57,12 @@ ANN m_bool traverse_type_def(const Env env, const Type_Def def) { } ANN m_bool traverse_class_def(const Env env, const Class_Def def) { - if(!GET_FLAG(def, scan1)) + const Type t = def->base.type; + if(!GET_FLAG(t, scan1)) CHECK_BB(scan1_class_def(env, def)) - if(!GET_FLAG(def, scan2)) + if(!GET_FLAG(t, scan2)) CHECK_BB(scan2_class_def(env, def)) - if(!GET_FLAG(def, checked)) + if(!GET_FLAG(t, checked)) return check_class_def(env, def); return GW_OK; } -- 2.43.0