From 259ffff98da0d67ae7453c7d6f2a57e91a2a1b80 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=A9mie=20Astor?= Date: Sun, 10 May 2020 21:56:52 +0200 Subject: [PATCH] :art: Improve Operator checking --- include/env/env.h | 1 + include/operator.h | 9 +++++++++ src/lib/object.c | 2 ++ src/lib/object_op.c | 24 +----------------------- src/parse/check.c | 7 +++++++ src/parse/operator.c | 14 ++++++++++++++ src/parse/scan0.c | 1 + src/parse/scan2.c | 11 +++-------- src/parse/type_decl.c | 26 +++++++++++++++++++++++--- 9 files changed, 61 insertions(+), 34 deletions(-) diff --git a/include/env/env.h b/include/env/env.h index 1615a0fd..231cd078 100644 --- a/include/env/env.h +++ b/include/env/env.h @@ -43,6 +43,7 @@ ANEW ANN m_str tl2str(const Env, const Type_List); // in type_decl.c ANN m_bool compat_func(const __restrict__ Func_Def, const __restrict__ Func_Def); ANN Type known_type(const Env env, Type_Decl*); ANN Type type_nonnull(const Env env, const Type base); +ANN Type force_type(const Env env, const Type t); ANN Type prim_ref(const Env env, const Type t, const Type_Decl* td); ANN m_bool env_access(const Env env, const ae_flag flag, const loc_t pos); ANN m_bool env_storage(const Env env, ae_flag flag, const loc_t pos); diff --git a/include/operator.h b/include/operator.h index e6fc6c9d..51a12ccb 100644 --- a/include/operator.h +++ b/include/operator.h @@ -56,10 +56,19 @@ ANN struct Instr_* op_emit(const Emitter, const struct Op_Import*); ANN m_bool operator_set_func(const struct Op_Import*); ANN void free_op_map(Map map, struct Gwion_* gwion); + +ANN void operator_suspend(const Nspc, struct Op_Import*); +ANN static inline void operator_resume(struct Op_Import *opi) { + *(uintptr_t*)opi->ret = opi->data; +} + ANN static inline void set_decl_ref(const Exp e) { if(e->exp_type == ae_exp_decl) { SET_FLAG(e->d.exp_decl.td, ref); SET_FLAG(e->d.exp_decl.list->self->value, ref); } } + + +ANN void func_operator(const Func_Def fdef, struct Op_Import *opi); #endif diff --git a/src/lib/object.c b/src/lib/object.c index 4590ec5f..1b3df38d 100644 --- a/src/lib/object.c +++ b/src/lib/object.c @@ -115,6 +115,8 @@ static ID_CHECK(opck_this) { if(env->func && !strcmp(s_name(env->func->def->base->xid), "@gack") && GET_FLAG(env->class_def, struct)) ERR_O(exp_self(prim)->pos, _("can't use 'this' in struct @gack")) + if(env->func && !strcmp(s_name(env->func->def->base->xid), "@gack")) + return force_type(env, env->class_def->e->parent); return env->class_def; } diff --git a/src/lib/object_op.c b/src/lib/object_op.c index 6a789a67..3541eb86 100644 --- a/src/lib/object_op.c +++ b/src/lib/object_op.c @@ -76,35 +76,13 @@ static OP_EMIT(opem_at_object) { return emit_add_instr(emit, ObjectAssign); } -#define STR_FORCE ":force" -#define STRLEN_FORCE strlen(STR_FORCE) - -static inline Type new_force_type(MemPool p, const Type t, const Symbol sym) { - const Type ret = type_copy(p, t); - if(ret->nspc) - ADD_REF(ret->nspc) - ret->name = s_name(sym); - ret->flag = t->flag | ae_flag_force; - nspc_add_type_front(t->e->owner, sym, ret); - return ret; - } - -static Type get_force_type(const Env env, const Type t) { - const size_t len = strlen(t->name); - char name[len + STRLEN_FORCE + 2]; - strcpy(name, t->name); - strcpy(name + len, STR_FORCE); - const Symbol sym = insert_symbol(env->gwion->st, name); - return nspc_lookup_type1(t->e->owner, sym) ?: new_force_type(env->gwion->mp, t, sym); -} - static OP_CHECK(opck_object_cast) { const Exp_Cast* cast = (Exp_Cast*)data; const Type l = cast->exp->info->type; const Type r = exp_self(cast)->info->type; if(check_nonnull(env, l, r, "cast", exp_self(cast)->pos) == env->gwion->type[et_null]) return env->gwion->type[et_null]; - return get_force_type(env, r); + return force_type(env, r); } static OP_EMIT(opem_object_cast) { diff --git a/src/parse/check.c b/src/parse/check.c index da30da9a..56fbd646 100644 --- a/src/parse/check.c +++ b/src/parse/check.c @@ -1331,7 +1331,14 @@ ANN m_bool check_func_def(const Env env, const Func_Def f) { env->func = func; ++env->scope->depth; nspc_push_value(env->gwion->mp, env->curr); + struct Op_Import opi = { }; + if(GET_FLAG(fdef, op)) { + func_operator(f, &opi); + operator_suspend(env->curr, &opi); + } const m_bool ret = scanx_fdef(env, env, fdef, (_exp_func)check_fdef); + if(GET_FLAG(fdef, op)) + operator_resume(&opi); nspc_pop_value(env->gwion->mp, env->curr); --env->scope->depth; env->func = former; diff --git a/src/parse/operator.c b/src/parse/operator.c index 15c2bdd7..1d8b5eca 100644 --- a/src/parse/operator.c +++ b/src/parse/operator.c @@ -56,6 +56,8 @@ static m_bool op_match(const restrict Type t, const restrict Type mo) { ANN2(1) static M_Operator* operator_find(const Vector v, const restrict Type lhs, const restrict Type rhs) { for(m_uint i = vector_size(v) + 1; --i;) { M_Operator* mo = (M_Operator*)vector_at(v, i - 1); + if(!mo) + continue; if(op_match(lhs, mo->lhs) && op_match(rhs, mo->rhs)) return mo; } @@ -79,6 +81,18 @@ ANN2(1) static M_Operator* operator_find2(const Vector v, const restrict Type lh return NULL; } +ANN void operator_suspend(const Nspc n, struct Op_Import *opi) { + const Vector v = (Vector)map_get(&n->info->op_map, (vtype)opi->op); + for(m_uint i = vector_size(v) + 1; --i;) { + M_Operator* mo = (M_Operator*)vector_at(v, i - 1); + if(op_match2(opi->lhs, mo->lhs) && op_match2(opi->rhs, mo->rhs)) { + opi->data = (uintptr_t)mo; + opi->ret = (Type)&VPTR(v, i-1); + VPTR(v, i-1) = 0; + break; + } + } +} ANN static M_Operator* new_mo(MemPool p, const struct Op_Import* opi) { M_Operator* mo = mp_calloc(p, M_Operator); diff --git a/src/parse/scan0.c b/src/parse/scan0.c index a4ba6276..ee022da9 100644 --- a/src/parse/scan0.c +++ b/src/parse/scan0.c @@ -107,6 +107,7 @@ ANN m_bool scan0_fptr_def(const Env env, const Fptr_Def fptr) { fptr_assign(env, fptr); SET_FLAG(fptr->value, func); add_type(env, t->e->owner, t); + mk_class(env, t); return GW_OK; } diff --git a/src/parse/scan2.c b/src/parse/scan2.c index 12a987a1..31698025 100644 --- a/src/parse/scan2.c +++ b/src/parse/scan2.c @@ -406,15 +406,10 @@ ANN2(1, 2) static m_bool scan2_fdef_tmpl(const Env env, const Func_Def f, const ANN static m_bool scan2_func_def_op(const Env env, const Func_Def f) { const m_str str = s_name(f->base->xid); - const uint is_unary = GET_FLAG(f, unary) + (!strcmp(str, "@conditionnal") || !strcmp(str, "@unconditionnal")); - const Type l = is_unary ? NULL : - f->base->args ? f->base->args->var_decl->value->type : NULL; - const Type r = f->base->args ? is_unary ? f->base->args->var_decl->value->type : - f->base->args->next ? f->base->args->next->var_decl->value->type : - f->base->ret_type : NULL; struct Op_Func opfunc = { .ck=strcmp(str, "@implicit") ? 0 : opck_usr_implicit }; - struct Op_Import opi = { .op=f->base->xid, .lhs=l, .rhs=r, .ret=f->base->ret_type, - .pos=f->pos, .data=(uintptr_t)f->base->func, .func=&opfunc }; + struct Op_Import opi = { .ret=f->base->ret_type, .pos=f->pos, + .data=(uintptr_t)f->base->func, .func=&opfunc }; + func_operator(f, &opi); CHECK_BB(add_op(env->gwion, &opi)) operator_set_func(&opi); return GW_OK; diff --git a/src/parse/type_decl.c b/src/parse/type_decl.c index ea9746d0..9771edd9 100644 --- a/src/parse/type_decl.c +++ b/src/parse/type_decl.c @@ -20,13 +20,33 @@ ANN Type type_nonnull(const Env env, const Type base) { if(t->nspc) ADD_REF(t->nspc) t->name = s_name(sym); - t->flag = base->flag; - SET_FLAG(t, nonnull); + t->flag = base->flag | ae_flag_nonnull; nspc_add_type_front(t->e->owner, sym, t); - mk_class(env, t); return t; } +#define STR_FORCE ":force" +#define STRLEN_FORCE strlen(STR_FORCE) + +ANN static inline Type new_force_type(MemPool p, const Type t, const Symbol sym) { + const Type ret = type_copy(p, t); + if(ret->nspc) + ADD_REF(ret->nspc) + ret->name = s_name(sym); + ret->flag = t->flag | ae_flag_force; + nspc_add_type_front(t->e->owner, sym, ret); + return ret; + } + +ANN Type force_type(const Env env, const Type t) { + const size_t len = strlen(t->name); + char name[len + STRLEN_FORCE + 2]; + strcpy(name, t->name); + strcpy(name + len, STR_FORCE); + const Symbol sym = insert_symbol(name); + return nspc_lookup_type1(t->e->owner, sym) ?: new_force_type(env->gwion->mp, t, sym); +} + ANN Type type_decl_resolve(const Env env, Type_Decl* td) { DECL_OO(const Type, base, = find_type(env, td)) if(base->e->ctx && base->e->ctx->error) -- 2.43.0