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);
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
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;
}
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))
} else
CHECK_BB(scanx_body(emit->env, cdef, (_exp_func)emit_struct_body2, emit))
}
- SET_FLAG(t, emit);
return GW_OK;
}
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;
#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) {
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) {
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);
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))
}
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;
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;
}
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);
union_tmpl(env, udef);
if(GET_FLAG(udef, global))
env_pop(env, scope);
+ union_flag(udef, ae_flag_scan0);
return GW_OK;
}
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);
}
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);
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);
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')..."))
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;
}
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);
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);
if(global)
SET_FLAG(decl.td, global);
- union_flag(udef, ae_flag_scan1);
return GW_OK;
}
}
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;
}
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))
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 {
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;
}
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))
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))
}
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);
}
}
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;
}