ANN void env_add_effect(const Env a, const Symbol effect, const loc_t pos);
ANN void call_add_effect(const Env env, const Func func, const loc_t pos);
+ANN bool check_effect_overload(const Vector base, const Func override);
#endif
};
enum tflag {
- tflag_none = 1 << 0,
- tflag_scan0 = 1 << 1,//
- tflag_scan1 = 1 << 2,//
- tflag_scan2 = 1 << 3,//
- tflag_check = 1 << 4,//
- tflag_emit = 1 << 5,//
- tflag_infer = 1 << 6,
- tflag_empty = 1 << 7,
- tflag_ftmpl = 1 << 8,
- tflag_ntmpl = 1 << 9, // do NOT need types
- tflag_udef = 1 << 10,
- tflag_cdef = 1 << 11,
- tflag_struct = 1 << 12,
- tflag_ctor = 1 << 13,
- tflag_dtor = 1 << 14,
- tflag_tmpl = 1 << 15,
- tflag_typedef = 1 << 16,
+ tflag_none = 1 << 0,
+ tflag_scan0 = 1 << 1,//
+ tflag_scan1 = 1 << 2,//
+ tflag_scan2 = 1 << 3,//
+ tflag_check = 1 << 4,//
+ tflag_emit = 1 << 5,//
+ tflag_infer = 1 << 6,
+ tflag_empty = 1 << 7,
+ tflag_ftmpl = 1 << 8,
+ tflag_ntmpl = 1 << 9, // do NOT need types
+ tflag_udef = 1 << 10,
+ tflag_cdef = 1 << 11,
+ tflag_struct = 1 << 12,
+ tflag_ctor = 1 << 13,
+ tflag_dtor = 1 << 14,
+ tflag_tmpl = 1 << 15,
+ tflag_typedef = 1 << 16,
tflag_distinct = 1 << 17,
+ tflag_noret = 1 << 17,
} __attribute__((packed));
struct Type_ {
struct TypeInfo_ *info;
size_t size;
size_t array_depth;
+ struct Vector_ effects; // pre-ctor effects
uint16_t ref;
ae_flag flag;
enum tflag tflag;
self.d.exp_binary.op = impl->e->d.prim.d.var;
struct Op_Import opi = { .op=impl->e->d.prim.d.var, .lhs=func->def->base->args->type,
.rhs=func->def->base->args->next->type, .data=(uintptr_t)&self.d.exp_binary, .pos=impl->e->pos };
+ vector_add(&env->scope->effects, 0);
DECL_ON(const Type, t, = op_check(env, &opi));
- CHECK_BN(isa(t, func->def->base->ret_type));
- // Find if the function exists
+ CHECK_BN(isa(t, func->def->base->ret_type)); // error message?
+ const m_uint _eff = vector_back(&env->scope->effects);
+ if(!check_effect_overload((Vector)&_eff, func))
+ ERR_N(impl->pos, _("`{+Y}%s{0}` has effects not present in `{+G}%s{0}`\n"), s_name(impl->e->d.prim.d.var), func->name);
Value v = nspc_lookup_value0(opi.nspc, impl->e->d.prim.d.var);
if(v) {
const m_uint scope = env_push(env, NULL, opi.nspc);
Exp_Call call = { .args=&_lhs };
const Func exists = (Func)find_func_match(env, v->d.func_ref, &call);
env_pop(env, scope);
- if(exists)
+ if(exists) { // improve me
+ if(_eff) {
+ const M_Vector eff = (M_Vector)&_eff;
+ m_vector_release(eff);
+ ERR_N(impl->pos, _("`{+Y}%s{0}` has effects not present in `{+G}%s{0}`\n"), s_name(impl->e->d.prim.d.var), func->name);
+ }
return actual_type(env->gwion, func->value_ref->type);
+ }
}
const Arg_List args = cpy_arg_list(env->gwion->mp, func->def->base->args);
// beware shadowing ?
args->next->var_decl->xid = rhs_sym;
Func_Base *base = new_func_base(env->gwion->mp, type2td(env->gwion, t, impl->e->pos),
impl->e->d.prim.d.var, args, ae_flag_none, impl->e->pos);
+ if(_eff) {
+ const M_Vector eff = (M_Vector)&_eff;
+ for (m_uint i = 0; i < m_vector_size(eff); i++) {
+ struct ScopeEffect effect;
+ m_vector_get(eff, i, &effect);
+ vector_add(&base->effects, (m_uint)effect.sym);
+ }
+ m_vector_release(eff);
+ }
const Exp lhs = new_prim_id(env->gwion->mp, args->var_decl->xid, impl->e->pos);
const Exp rhs = new_prim_id(env->gwion->mp, args->next->var_decl->xid, impl->e->pos);
const Exp bin = new_exp_binary(env->gwion->mp, lhs, impl->e->d.prim.d.var, rhs, impl->e->pos);
const Type t = new_type(env->gwion->mp, s_name(info.name), base);
SET_FLAG(t, abstract | ae_flag_final);
set_tflag(t, tflag_infer);
+ set_tflag(t, tflag_noret);
const m_uint scope = env_push(env, base->info->value->from->owner_class, base->info->value->from->owner);
mk_class(env, t, (loc_t){});
base2ref(env, base, t);
ANN static m_bool check_var(const Env env, const Var_Decl var) {
if(env->class_def && !env->scope->depth && env->class_def->info->parent)
CHECK_BB(check_exp_decl_parent(env, var));
+ if(var->value->type->effects.ptr) {
+ const Vector v = &var->value->type->effects;
+ for(m_uint i = 0; i < vector_size(v); i++)
+ env_add_effect(env, (Symbol)vector_at(v, i), var->pos);
+ }
if(var->array && var->array->exp)
return check_subscripts(env, var->array, 1);
return GW_OK;
env_add_effect(env, (Symbol)vector_at(v, i), pos);
}
}
+
ANN Type check_exp_call1(const Env env, Exp_Call *const exp) {
DECL_BO(const m_bool, ret, = func_check(env, exp));
if(!ret)
}
if(isa(ret_type, env->func->def->base->ret_type) > 0)
return GW_OK;
+ if(tflag(ret_type, tflag_noret))
+ ERR_B(stmt->val->pos, _("Can't use type `{+G}%s{+G}` for return"));
if(stmt->val) {
if(env->func->def->base->xid == insert_symbol("@implicit") && ret_type == env->func->def->base->args->type)
ERR_B(stmt_self(stmt)->pos, _("can't use implicit casting while defining it"))
return GW_OK;
}
-ANN bool check_effect_overload(const Func_Base *base, const Value override) {
- if(!base->effects.ptr)
+ANN bool check_effect_overload(const Vector base, const Func override) {
+ if(!base->ptr)
return true;
- if(!override->d.func_ref->def->base->effects.ptr)
+ if(!override->def->base->effects.ptr)
return false; // TODO: error message
- const Vector v = &override->d.func_ref->def->base->effects;
+ const Vector v = &override->def->base->effects;
for(m_uint i = 0; i < vector_size(v); i++) {
- if(vector_find((Vector)&base->effects, vector_at(v, i)) == -1)
+ if(vector_find((Vector)base, vector_at(v, i)) == -1)
return false;
}
return true;
}
vector_add(&env->scope->effects, 0);
const m_bool ret = scanx_fdef(env, env, fdef, (_exp_func)check_fdef);
- const m_uint _v = vector_pop(&env->scope->effects);
+ const m_uint _v = vector_back(&env->scope->effects);
if(_v) {
+ if(fdef->base->xid == insert_symbol("@dtor"))
+ ERR_B(fdef->base->pos, _("can't use effects in destructors"));
const Vector v = (Vector)&_v;
const Vector base = &fdef->base->effects;
if(!base->ptr)
}
vector_release(v);
}
+ vector_pop(&env->scope->effects);
if(fbflag(fdef->base, fbflag_op))
operator_resume(&opi);
nspc_pop_value(env->gwion->mp, env->curr);
env->func = former;
if(ret > 0) {
set_fflag(fdef->base->func, fflag_valid);
- if(env->class_def && !check_effect_overload(fdef->base, override))
+ if(env->class_def && !check_effect_overload(&fdef->base->effects, override->d.func_ref))
ERR_B(fdef->base->pos,
_("too much effects in override."),
s_name(fdef->base->xid))
return !err ? GW_OK : GW_ERROR;
}
-ANN static inline void check_unhandled(const Env env) {
+ANN static inline void ctor_effects(const Env env) {
const Vector v = &env->scope->effects;
const m_uint _w = vector_back(v);
if(!_w)
return;
+ vector_init(&env->class_def->effects);
const M_Vector w = (M_Vector)&_w;
for(m_uint j = 0; j < m_vector_size(w); j++) {
struct ScopeEffect eff;
m_vector_get(w, j, &eff);
- gwerr_secondary("Unhandled effect", env->name, eff.pos);
- env->context->error = false;
+ vector_add(&env->class_def->effects, (m_uint)eff.sym);
}
m_vector_release(w);
vector_pop(v);
}
-
ANN static m_bool check_body(const Env env, Section *const section) {
const m_bool ret = check_section(env, section);
- check_unhandled(env);
+ ctor_effects(env);
return ret;
}
return _check_class_def(env, cdef);
}
+ANN static inline void check_unhandled(const Env env) {
+ const Vector v = &env->scope->effects;
+ const m_uint _w = vector_back(v);
+ if(!_w)
+ return;
+ const M_Vector w = (M_Vector)&_w;
+ for(m_uint j = 0; j < m_vector_size(w); j++) {
+ struct ScopeEffect eff;
+ m_vector_get(w, j, &eff);
+ gwerr_secondary("Unhandled effect", env->name, eff.pos);
+ env->context->error = false;
+ }
+ m_vector_release(w);
+ vector_pop(v);
+}
+
ANN m_bool check_ast(const Env env, Ast ast) {
do CHECK_BB(check_section(env, ast->section));
while((ast = ast->next));
do nspc_add_type(env->curr, id->xid, env->gwion->type[et_auto]);
while((id = id->next));
CHECK_OB((base->ret_type = known_type(env, base->td)));
+ if(tflag(base->ret_type, tflag_noret))
+ ERR_B(base->pos, _("Can't use type `{+G}%s{0}` for return"),
+ base->ret_type->name);
if(base->args) {
Arg_List arg = base->args;
do CHECK_OB(known_type(env, arg->td));
}
const Func_Def fdef = fptr->base->func->def;
CHECK_OB((fdef->base->ret_type = scan1_type(env, fdef->base->td)));
+ if(tflag(fdef->base->ret_type, tflag_noret))
+ ERR_B(fdef->base->pos, _("Can't use type `{+G}%s{0}` for return"),
+ fdef->base->ret_type->name);
if(!fdef->base->args)
return GW_OK;
RET_NSPC(scan1_args(env, fdef->base->args))
}
ANN m_bool scan1_fdef(const Env env, const Func_Def fdef) {
- if(fdef->base->td)
+ if(fdef->base->td) {
CHECK_OB((fdef->base->ret_type = known_type(env, fdef->base->td)));
+ if(tflag(fdef->base->ret_type, tflag_noret))
+ ERR_B(fdef->base->pos, _("Can't use type `{+G}%s{0}` for return"),
+ fdef->base->ret_type->name);
+ }
if(fbflag(fdef->base, fbflag_internal))
CHECK_BB(scan_internal(env, fdef->base));
else if(fbflag(fdef->base, fbflag_op) && env->class_def)