From 9bf1ae545bea2783be5fee4bb6fcaf68bf0bae61 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=A9mie=20Astor?= Date: Tue, 27 Apr 2021 17:15:14 +0200 Subject: [PATCH] :fire: Update Effects --- ast | 2 +- include/array.h | 27 ------ include/env/env.h | 11 ++- include/vm.h | 2 +- src/emit/emit.c | 2 +- src/env/env.c | 22 +++++ src/lib/array.c | 64 -------------- src/lib/lib_func.c | 24 +++++- src/parse/check.c | 153 +++++++++++++++++++++++++++++----- src/parse/func_resolve_tmpl.c | 4 +- src/parse/operator.c | 17 ++-- src/parse/scanx.c | 16 +++- src/vm/vm.c | 15 ++-- src/vm/vm_shred.c | 2 +- util | 2 +- 15 files changed, 228 insertions(+), 135 deletions(-) diff --git a/ast b/ast index 3b040d5d..ded33ab4 160000 --- a/ast +++ b/ast @@ -1 +1 @@ -Subproject commit 3b040d5d5d552df2fb7413545aab0c90055d8634 +Subproject commit ded33ab49b042a39ae473a0b2e1841081891f47a diff --git a/include/array.h b/include/array.h index 49c9b31c..6fe233a4 100644 --- a/include/array.h +++ b/include/array.h @@ -7,15 +7,6 @@ struct ArrayAccessInfo { const bool is_var; }; -typedef struct M_Vector_ { - m_bit* ptr; -} * M_Vector; -#define ARRAY_OFFSET SZ_INT * 4 -#define ARRAY_PTR(array) (array->ptr + ARRAY_OFFSET) -#define ARRAY_LEN(array) *(m_uint*)(array->ptr) -#define ARRAY_SIZE(array) *(m_uint*)(array->ptr + SZ_INT) -#define ARRAY_CAP(array) *(m_uint*)(array->ptr + SZ_INT*2) - typedef struct ArrayInfo_ { m_int depth; struct Vector_ type; @@ -28,24 +19,6 @@ typedef struct ArrayInfo_ { uint is_obj; } ArrayInfo; -ANN static inline m_uint m_vector_size(const M_Vector v) { - return ARRAY_LEN(v); -} - -ANN static inline void m_vector_get(const M_Vector v, const m_uint i, void* c) { - const m_uint size = ARRAY_SIZE(v); - memcpy(c, ARRAY_PTR(v) + i * size, size); -} - -ANN static inline m_bit* m_vector_addr(const M_Vector v, const m_uint i) { - return &*(m_bit*)(ARRAY_PTR(v) + i * ARRAY_SIZE(v)); -} - -ANN void m_vector_set(const M_Vector, const m_uint, const void*); -ANN void m_vector_add(const M_Vector, const void*); -ANN void m_vector_rem(const M_Vector, const m_uint); -ANEW M_Vector new_m_vector(MemPool, const m_uint size, const m_uint len); -ANN void free_m_vector(MemPool, M_Vector); ANN Type check_array_access(const Env env, const Array_Sub array); ANN m_bool emit_array_access(const Emitter emit, struct ArrayAccessInfo *const info); #endif diff --git a/include/env/env.h b/include/env/env.h index 0962ba9e..72683789 100644 --- a/include/env/env.h +++ b/include/env/env.h @@ -11,7 +11,9 @@ struct Env_Scope_ { struct Vector_ conts; struct Vector_ known_ctx; struct Match_ *match; - size_t depth; + struct Vector_ effects; // a vector of Effect[] + uint depth; + bool in_try; }; typedef struct Env_ { @@ -46,4 +48,11 @@ ANN void env_err(const Env, const loc_t pos, const m_str fmt, ...); ANN void env_warn(const Env, const loc_t pos, const m_str fmt, ...); ANN Value global_string(const Env env, const m_str str); ANN void release_ctx(struct Env_Scope_ *a, struct Gwion_* gwion); + +struct ScopeEffect { + Symbol sym; + loc_t pos; +}; + +ANN void env_add_effect(const Env a, const Symbol effect, const loc_t pos); #endif diff --git a/include/vm.h b/include/vm.h index 3e3b8cf2..3e2944c5 100644 --- a/include/vm.h +++ b/include/vm.h @@ -53,7 +53,7 @@ struct ShredInfo_ { Vector args; MemPool mp; VM_Code orig; - struct Map_ frame; + struct Vector_ frame; }; struct ShredTick_ { diff --git a/src/emit/emit.c b/src/emit/emit.c index 21874c26..6f1ce8f2 100644 --- a/src/emit/emit.c +++ b/src/emit/emit.c @@ -2127,7 +2127,7 @@ ANN static m_bool emit_stmt_defer(const Emitter emit, const struct Stmt_Defer_* ANN static m_bool emit_stmt_retry(const Emitter emit, const struct Stmt_Index_* stmt NUSED) { const Instr instr = emit_add_instr(emit, Goto); - instr->m_val = emit->code->frame->try_top; + instr->m_val = emit->code->frame->try_top + 1; return GW_OK; } diff --git a/src/env/env.c b/src/env/env.c index 5eda5517..4105abba 100644 --- a/src/env/env.c +++ b/src/env/env.c @@ -16,6 +16,7 @@ ANN static struct Env_Scope_ *new_envscope(MemPool p) { vector_init(&a->class_stack); vector_init(&a->nspc_stack); vector_init(&a->known_ctx); + vector_init(&a->effects); return a; } @@ -35,6 +36,7 @@ ANN void env_reset(const Env env) { vector_add(&env->scope->nspc_stack, (vtype)env->global_nspc); vector_clear(&env->scope->class_stack); vector_add(&env->scope->class_stack, (vtype)NULL); + vector_add(&env->scope->effects, 0); env->curr = env->global_nspc; env->class_def = NULL; env->func = NULL; @@ -58,9 +60,25 @@ ANN static void free_env_scope(struct Env_Scope_ *a, Gwion gwion) { vector_release(&a->class_stack); vector_release(&a->breaks); vector_release(&a->conts); + const Vector v = &a->effects; + for(m_uint i = 0; i < vector_size(v); i++) { + m_uint _v = vector_at(v, i); + if(_v) + m_vector_release((M_Vector)&_v); + } + vector_release(&a->effects); mp_free(gwion->mp, Env_Scope, a); } +ANN void env_add_effect(const Env a, const Symbol effect, const loc_t pos) { + const Vector v = &a->scope->effects; + const M_Vector w = (M_Vector)&VPTR(v, VLEN(v) - 1); + if(!w->ptr) + m_vector_init(w, sizeof(struct ScopeEffect), 0); + struct ScopeEffect eff = { effect, pos }; + m_vector_add(w, &eff); +} + ANN void free_env(const Env a) { free_env_scope(a->scope, a->gwion); while(pop_global(a->gwion)); @@ -72,6 +90,7 @@ ANN2(1,3) m_uint env_push(const Env env, const Type type, const Nspc nspc) { vector_add(&env->scope->class_stack, (vtype)env->class_def); env->class_def = type; vector_add(&env->scope->nspc_stack, (vtype)env->curr); + vector_add(&env->scope->effects, 0); env->curr = nspc; env->scope->depth = 0; return scope; @@ -80,6 +99,9 @@ ANN2(1,3) m_uint env_push(const Env env, const Type type, const Nspc nspc) { ANN void env_pop(const Env env, const m_uint scope) { env->class_def = (Type)vector_pop(&env->scope->class_stack); env->curr = (Nspc)vector_pop(&env->scope->nspc_stack); + const m_uint _v = vector_pop(&env->scope->effects); + if(_v) + m_vector_release((M_Vector)&_v); env->scope->depth = scope; } diff --git a/src/lib/array.c b/src/lib/array.c index 1f8d9180..ff4e74e3 100644 --- a/src/lib/array.c +++ b/src/lib/array.c @@ -16,24 +16,6 @@ #include "gwi.h" #include "emit.h" -M_Vector new_m_vector(MemPool p, const m_uint size, const m_uint len) { - const M_Vector array = mp_calloc(p, M_Vector); - const size_t sz = (ARRAY_OFFSET*SZ_INT) + (len*size); - array->ptr = (m_bit*)xcalloc(1, sz); - m_uint cap = 1; - while(cap < len) - cap *= 2; - ARRAY_CAP(array) = cap; - ARRAY_SIZE(array) = size; - ARRAY_LEN(array) = len; - return array; -} - -void free_m_vector(MemPool p, M_Vector a) { - xfree(a->ptr); - mp_free(p, M_Vector, a); -} - static DTOR(array_dtor) { if(*(void**)(o->data + SZ_INT)) xfree(*(void**)(o->data + SZ_INT)); @@ -61,52 +43,6 @@ ANN M_Object new_array(MemPool p, const Type t, const m_uint length) { return a; } -ANN void m_vector_add(const M_Vector v, const void* data) { - const m_uint size = ARRAY_SIZE(v); - if(++ARRAY_LEN(v) >= ARRAY_CAP(v)) { - const m_uint cap = ARRAY_CAP(v) *=2; - v->ptr = (m_bit*)xrealloc(v->ptr, ARRAY_OFFSET + cap * size); - } - memcpy(ARRAY_PTR(v) + (ARRAY_LEN(v) - 1) * size, data, size); -} - -ANN void m_vector_add_front(const M_Vector v, const void* data) { - const m_uint size = ARRAY_SIZE(v); - if(++ARRAY_LEN(v) >= ARRAY_CAP(v)) { - const m_uint cap = ARRAY_CAP(v) *=2; - v->ptr = (m_bit*)xrealloc(v->ptr, ARRAY_OFFSET + cap * size); - } - memmove(ARRAY_PTR(v) + size, ARRAY_PTR(v), ARRAY_LEN(v) * size); - memmove(ARRAY_PTR(v), data, size); -} - -ANN void m_vector_set(const M_Vector v, const m_uint i, const void* data) { - const m_uint size = ARRAY_SIZE(v); - memcpy(ARRAY_PTR(v) + i * size, data, size); -} - -ANN void m_vector_rem(const M_Vector v, m_uint index) { - const m_uint size = ARRAY_SIZE(v); - if(index < ARRAY_LEN(v) - 1) - memmove(ARRAY_PTR(v) + index * size, ARRAY_PTR(v) + (index + 1) * size, - (ARRAY_LEN(v) - index - 1) *size); - --ARRAY_LEN(v); - if(ARRAY_LEN(v) < ARRAY_CAP(v) / 2) { - const m_uint cap = ARRAY_CAP(v) /= 2; - v->ptr = (m_bit*)xrealloc(v->ptr, ARRAY_OFFSET + cap * size); - } -} - -ANN void m_vector_insert(const M_Vector v, m_uint index, const void* data) { - const size_t size = ARRAY_SIZE(v); - if(++ARRAY_LEN(v) >= ARRAY_CAP(v)) { - const m_uint cap = ARRAY_CAP(v) *=2; - v->ptr = (m_bit*)xrealloc(v->ptr, ARRAY_OFFSET + cap * size); - } - memmove(ARRAY_PTR(v) + (index+1) * size, ARRAY_PTR(v) + index*size, (ARRAY_LEN(v) - index + 1)* size); - memcpy(ARRAY_PTR(v) + index*size, data, size); -} - static MFUN(vm_vector_rem) { const m_int index = *(m_int*)(shred->mem + SZ_INT); const M_Vector v = ARRAY(o); diff --git a/src/lib/lib_func.c b/src/lib/lib_func.c index ac0d16b4..d101d108 100644 --- a/src/lib/lib_func.c +++ b/src/lib/lib_func.c @@ -104,6 +104,24 @@ ANN static m_bool fptr_args(const Env env, Func_Base *base[2]) { return !arg1 ? GW_OK : GW_ERROR; } +ANN static bool fptr_effects(const Env env, struct FptrInfo *info) { + if(!info->lhs->def->base->effects.ptr) + return true; + if(!info->rhs->def->base->effects.ptr) { + puts("too many effects"); + return false; + } + const Vector lhs = &info->lhs->def->base->effects; + const Vector rhs = &info->rhs->def->base->effects; + for(m_uint i = 0; i < vector_size(lhs); i++) { + if(vector_find(rhs, vector_at(lhs, 0)) == -1) { + gwerr_secondary("effect not handled", env->name, info->pos); + return false; + } + } + return true; +} + ANN static m_bool fptr_check(const Env env, struct FptrInfo *info) { // if(!info->lhs->def->base->tmpl != !info->rhs->def->base->tmpl) // return GW_ERROR; @@ -157,8 +175,8 @@ ANN static Type fptr_type(const Env env, struct FptrInfo *info) { Type type = NULL; Func_Base *base[2] = { info->lhs->def->base, info->rhs->def->base }; CHECK_BO(fptr_tmpl_push(env, info)) - if(fptr_rettype(env, info) > 0 && - fptr_arity(info) && fptr_args(env, base) > 0) + if (fptr_rettype(env, info) > 0 && fptr_arity(info) && + fptr_args(env, base) > 0 && fptr_effects(env, info)) type = actual_type(env->gwion, info->lhs->value_ref->type) ?: info->lhs->value_ref->type; if(info->rhs->def->base->tmpl) nspc_pop_type(env->gwion->mp, env->curr); @@ -181,7 +199,7 @@ ANN static m_bool _check_lambda(const Env env, Exp_Lambda *l, const Func_Def def l->def->base->td = type2td(env->gwion, known_type(env, def->base->td), exp_self(l)->pos); if(is_tmpl) nspc_pop_type(env->gwion->mp, env->curr); - if(base || arg) // beware, error between pops + if(base || arg) ERR_B(exp_self(l)->pos, _("argument number does not match for lambda")) l->def->base->flag = def->base->flag; // if(GET_FLAG(def->base, global) && !l->owner && def->base->func->value_ref->from->owner_class) diff --git a/src/parse/check.c b/src/parse/check.c index df1622c3..31d24917 100644 --- a/src/parse/check.c +++ b/src/parse/check.c @@ -345,7 +345,8 @@ ANN static Type check_prim_id(const Env env, const Symbol *data) { return prim_id_non_res(env, data); } -ANN static Type check_prim_perform(const Env env, const Symbol *data NUSED) { +ANN static Type check_prim_perform(const Env env, const Symbol *data) { + env_add_effect(env, *data, prim_pos(data)); return env->gwion->type[et_void]; } @@ -741,6 +742,13 @@ ANN m_bool func_check(const Env env, Exp_Call *const exp) { GW_OK : GW_ERROR; } +ANN void call_add_effect(const Env env, const Func func, const loc_t pos) { + if(func != env->func && func->def->base->effects.ptr) { + const Vector v = &func->def->base->effects; + for(m_uint i = 0; i < vector_size(v); i++) + 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) @@ -754,7 +762,7 @@ ANN Type check_exp_call1(const Env env, Exp_Call *const exp) { } if(t == env->gwion->type[et_op]) return check_op_call(env, exp); - if(t == env->gwion->type[et_lambda]) + if(t == env->gwion->type[et_lambda]) // TODO: effects? return check_lambda_call(env, exp); if(fflag(t->info->func, fflag_ftmpl)) { const Value value = t->info->func->value_ref; @@ -764,10 +772,21 @@ ANN Type check_exp_call1(const Env env, Exp_Call *const exp) { if(exp->args) CHECK_OO(check_exp(env, exp->args)) if(tflag(t, tflag_ftmpl)) - return check_exp_call_template(env, (Exp_Call*)exp); + return check_exp_call_template(env, (Exp_Call*)exp); // TODO: effects? const Func func = find_func_match(env, t->info->func, exp); if(func) { + if(!is_fptr(env->gwion, func->value_ref->type))// skip function pointers + if(func != env->func && func->def && !fflag(func, fflag_valid)) { +// if(!fflag(func, fflag_valid)) { + struct EnvSet es = { .env=env, .data=env, .func=(_exp_func)check_cdef, + .scope=env->scope->depth, .flag=tflag_check }; + CHECK_BO(envset_push(&es, func->value_ref->from->owner_class, func->value_ref->from->owner)) + CHECK_BO(check_func_def(env, func->def)) + if(es.run) + envset_pop(&es, func->value_ref->from->owner_class); + } exp->func->type = func->value_ref->type; + call_add_effect(env, func, exp->func->pos); return func->def->base->ret_type; } const loc_t pos = exp->args ? exp->args->pos : exp->func->pos; @@ -1226,10 +1245,41 @@ ANN static inline m_bool check_handler_list(const restrict Env env, const Handle RET_NSPC(check_stmt(env, handler->stmt)) } -ANN static inline m_bool check_stmt_try(const restrict Env env, const Stmt_Try stmt) { - CHECK_BB(check_handler_list(env, stmt->handler)) +ANN static inline m_bool check_stmt_try_start(const restrict Env env, const Stmt_Try stmt) { RET_NSPC(check_stmt(env, stmt->stmt)) } +ANN static inline m_bool _check_stmt_try(const restrict Env env, const Stmt_Try stmt) { + CHECK_BB(check_handler_list(env, stmt->handler)) + vector_add(&env->scope->effects, 0); + const m_bool ret = check_stmt_try_start(env, stmt); + const m_uint _v = vector_pop(&env->scope->effects); + if(_v) { + const M_Vector v = (M_Vector)&_v; + for(m_uint i = 0; i < m_vector_size(v); i++) { + struct ScopeEffect eff; + m_vector_get(v, i, &eff); + Handler_List handler = stmt->handler; + bool found = false; + do { // check there is no duplicate handler + if(eff.sym == handler->xid) { + found = true; + break; + } + } while((handler = handler->next)); + if(!found) + env_add_effect(env, eff.sym, eff.pos); + } + m_vector_release(v); + } + return ret; +} + +ANN static inline m_bool check_stmt_try(const restrict Env env, const Stmt_Try stmt) { + const bool in_try = env->scope->in_try; + const m_bool ret = _check_stmt_try(env, stmt); + env->scope->in_try = in_try; + return ret; +} ANN static m_bool _check_stmt_match(const Env env, const Stmt_Match stmt) { CHECK_OB(check_exp(env, stmt->cond)) @@ -1347,15 +1397,29 @@ ANN static m_bool check_func_overload(const Env env, const Func_Def fdef) { return GW_OK; } -ANN static m_bool check_func_def_override(const Env env, const Func_Def fdef) { +ANN bool check_effect_overload(const Func_Base *base, const Value override) { + if(!base->effects.ptr) + return true; + if(!override->d.func_ref->def->base->effects.ptr) + return false; // TODO: error message + const Vector v = &override->d.func_ref->def->base->effects; + for(m_uint i = 0; i < vector_size(v); i++) { + if(vector_find((Vector)&base->effects, vector_at(v, i)) == -1) + return false; + } + return true; +} + +ANN static m_bool check_func_def_override(const Env env, const Func_Def fdef, Value *ov) { const Func func = fdef->base->func; if(env->class_def && env->class_def->info->parent) { const Value override = find_value(env->class_def->info->parent, fdef->base->xid); if(override && override->from->owner_class && isa(override->type, env->gwion->type[et_function]) < 0) - ERR_B(fdef->base->pos, + ERR_B(fdef->base->pos, _("function name '%s' conflicts with previously defined value...\n" " from super class '%s'..."), s_name(fdef->base->xid), override->from->owner_class->name) + *ov = override; } if(func->value_ref->from->offset && (!fdef->base->tmpl || !fdef->base->tmpl->base)) CHECK_BB(check_func_overload(env, fdef)) @@ -1384,7 +1448,8 @@ ANN m_bool check_func_def(const Env env, const Func_Def f) { CHECK_BB(check_parent_match(env, fdef)) if(tmpl_base(fdef->base->tmpl)) return GW_OK; - CHECK_BB(check_func_def_override(env, fdef)) + Value override = NULL; + CHECK_BB(check_func_def_override(env, fdef, &override)) DECL_BB(const m_int, scope, = GET_FLAG(fdef->base, global) ? env_push_global(env) : env->scope->depth) const Func former = env->func; env->func = func; @@ -1395,14 +1460,33 @@ ANN m_bool check_func_def(const Env env, const Func_Def f) { func_operator(f, &opi); operator_suspend(env->curr, &opi); } + 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); + if(_v) { + const Vector v = (Vector)&_v; + const Vector base = &fdef->base->effects; + if(!base->ptr) + vector_init(base); + for(m_uint i = 0; i < vector_size(v); i += 2) { + const Symbol effect = (Symbol)vector_at(v, i); + if(vector_find(base, (m_uint)effect) == -1) + vector_add(base, (m_uint)effect); + } + vector_release(v); + } if(fbflag(fdef->base, fbflag_op)) operator_resume(&opi); nspc_pop_value(env->gwion->mp, env->curr); --env->scope->depth; env->func = former; - if(ret > 0) + if(ret > 0) { set_fflag(fdef->base->func, fflag_valid); + if(env->class_def && !check_effect_overload(fdef->base, override)) + ERR_B(fdef->base->pos, + _("too much effects in override."), + s_name(fdef->base->xid)) + } if(GET_FLAG(fdef->base, global)) env_pop(env,scope); return ret; @@ -1464,6 +1548,44 @@ ANN m_bool check_abstract(const Env env, const Class_Def cdef) { return !err ? GW_OK : GW_ERROR; } +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 static m_bool check_body(const Env env, Section *const section) { + const m_bool ret = check_section(env, section); + check_unhandled(env); + return ret; +} + +ANN static m_bool _check_class_def(const Env env, const Class_Def cdef) { + const Type t = cdef->base.type; + if(cdef->base.ext) + CHECK_BB(cdef_parent(env, cdef)) + if(!tflag(t, tflag_struct)) + inherit(t); + if(cdef->body) { + CHECK_BB(env_body(env, cdef, check_body)) + set_tflag(t, tflag_ctor); + } + if(!GET_FLAG(cdef, abstract)) + CHECK_BB(check_abstract(env, cdef)) + return GW_OK; +} + ANN m_bool check_class_def(const Env env, const Class_Def cdef) { if(tmpl_base(cdef->base.tmpl)) return GW_OK; @@ -1476,21 +1598,12 @@ ANN m_bool check_class_def(const Env env, const Class_Def cdef) { if(tflag(t, tflag_check)) return GW_OK; set_tflag(t, tflag_check); - if(cdef->base.ext) - CHECK_BB(cdef_parent(env, cdef)) - if(!tflag(t, tflag_struct)) - inherit(t); - if(cdef->body) { - CHECK_BB(env_body(env, cdef, check_section)) - set_tflag(t, tflag_ctor); - } - if(!GET_FLAG(cdef, abstract)) - CHECK_BB(check_abstract(env, cdef)) - return GW_OK; + return _check_class_def(env, cdef); } ANN m_bool check_ast(const Env env, Ast ast) { do CHECK_BB(check_section(env, ast->section)) while((ast = ast->next)); + check_unhandled(env); return GW_OK; } diff --git a/src/parse/func_resolve_tmpl.c b/src/parse/func_resolve_tmpl.c index 2b3eb49b..f81d223e 100644 --- a/src/parse/func_resolve_tmpl.c +++ b/src/parse/func_resolve_tmpl.c @@ -54,8 +54,10 @@ ANN static Func ensure_tmpl(const Env env, const Func_Def fdef, Exp_Call *const const Func func = find_func_match(env, f, exp); nspc_pop_type(env->gwion->mp, env->curr); f->next = next; - if(func) + if(func) { set_fflag(func, fflag_tmpl | fflag_valid); + call_add_effect(env, func, exp->func->pos); + } return func; } diff --git a/src/parse/operator.c b/src/parse/operator.c index 28b89484..0c145e12 100644 --- a/src/parse/operator.c +++ b/src/parse/operator.c @@ -100,6 +100,7 @@ struct OpChecker { const Env env; const Map map; const struct Op_Import* opi; + struct Vector_ effect; }; __attribute__((returns_nonnull)) @@ -128,12 +129,12 @@ ANN static m_bool op_exist(const struct OpChecker* ock, const Nspc n) { ANN m_bool add_op(const Gwion gwion, const struct Op_Import* opi) { Nspc n = gwion->env->curr; do { - struct OpChecker ock = { gwion->env, &n->info->op_map, opi }; + struct OpChecker ock = { .env=gwion->env, .map=&n->info->op_map, .opi=opi }; CHECK_BB(op_exist(&ock, n)) } while((n = n->parent)); if(!gwion->env->curr->info->op_map.ptr) map_init(&gwion->env->curr->info->op_map); - struct OpChecker ock = { gwion->env, &gwion->env->curr->info->op_map, opi }; + struct OpChecker ock = { .env=gwion->env, .map=&gwion->env->curr->info->op_map, .opi=opi }; const Vector v = op_vector(gwion->mp, &ock); const M_Operator* mo = new_mo(gwion->mp, opi); vector_add(v, (vtype)mo); @@ -153,9 +154,10 @@ ANN static Type op_check_inner(struct OpChecker* ock, const uint i) { const M_Operator* mo; const Vector v = (Vector)map_get(ock->map, (vtype)ock->opi->op); if(v && (mo = !i ? operator_find2(v, ock->opi->lhs, r) : operator_find(v, ock->opi->lhs, r))) { - if((mo->ck && (t = mo->ck(ock->env, (void*)ock->opi->data)))) + if((mo->ck && (t = mo->ck(ock->env, (void*)ock->opi->data)))) { + ock->effect.ptr = mo->effect.ptr; return t; - else + } else return mo->ret; } } while(r && (r = r->info->parent)); @@ -171,11 +173,16 @@ for(int i = 0; i < 2; ++i) { Type l = opi->lhs; do { struct Op_Import opi2 = { .op=opi->op, .lhs=l, .rhs=opi->rhs, .data=opi->data }; - struct OpChecker ock = { env, &nspc->info->op_map, &opi2 }; + struct OpChecker ock = { .env=env, .map=&nspc->info->op_map, .opi=&opi2 }; const Type ret = op_check_inner(&ock, i); if(ret) { if(ret == env->gwion->type[et_error]) return NULL; + if(ock.effect.ptr) { + const Vector base = &ock.effect; + for(m_uint i = 0; i < vector_size(base); i++) + env_add_effect(env, (Symbol)vector_at(base, i), opi->pos); + } opi->nspc = nspc; return ret; } diff --git a/src/parse/scanx.c b/src/parse/scanx.c index 2f5ef8a1..827b8715 100644 --- a/src/parse/scanx.c +++ b/src/parse/scanx.c @@ -41,11 +41,19 @@ scanx_body(const Env e, const Class_Def c, const _exp_func f, void* d) { return ret; } -ANN m_bool scanx_cdef(const Env env, void* opt, const Type t, - const _exp_func f_cdef, const _exp_func f_union) { +ANN static m_bool _scanx_cdef(const Env env, void* opt, const Type t, + const _exp_func f_cdef, const _exp_func f_udef) { if(t->info->parent != env->gwion->type[et_union]) return f_cdef(opt, t->info->cdef); - const m_bool ret = f_union(opt, t->info->udef); + const m_bool ret = f_udef(opt, t->info->udef); + return ret; +} + +ANN m_bool scanx_cdef(const Env env, void* opt, const Type t, + const _exp_func f_cdef, const _exp_func f_udef) { + const bool in_try = env->scope->in_try; + const m_bool ret = _scanx_cdef(env, opt, t, f_cdef, f_udef); + env->scope->in_try = in_try; return ret; } @@ -53,8 +61,10 @@ ANN m_bool scanx_fdef(const Env env, void *data, const Func_Def fdef, const _exp_func func) { if(fdef->base->tmpl) CHECK_BB(template_push_types(env, fdef->base->tmpl)) + const bool in_try = env->scope->in_try; const m_bool ret = func(data, fdef); if(fdef->base->tmpl) nspc_pop_type(env->gwion->mp, env->curr); + env->scope->in_try = in_try; return ret; } diff --git a/src/vm/vm.c b/src/vm/vm.c index b83b1f36..5692ccd1 100644 --- a/src/vm/vm.c +++ b/src/vm/vm.c @@ -41,7 +41,7 @@ uint32_t gw_rand(uint32_t s[2]) { } ANN static bool unwind(VM_Shred shred, const Symbol effect) { - if(!shred->info->frame.ptr || !map_size(&shred->info->frame)) + if(!shred->info->frame.ptr || !vector_size(&shred->info->frame)) return true; if(shred->code->handlers.ptr) { const m_uint start = VKEY(&shred->info->frame, VLEN(&shred->info->frame) - 1); @@ -63,13 +63,14 @@ ANN static bool unwind(VM_Shred shred, const Symbol effect) { } if(!pc) // outside of a try statement return true; - shred->reg = (m_bit*)VVAL(&shred->info->frame, VLEN(&shred->info->frame) - 1); + shred->reg = (m_bit*)VPTR(&shred->info->frame, VLEN(&shred->info->frame) - 1); shredule(shred->tick->shreduler, shred, 0); shred->pc = pc;//VKEY(m, i); return false; } // there might be no more stack to unwind - map_remove(&shred->info->frame, VLEN(&shred->info->frame)-1); + vector_pop(&shred->info->frame); + vector_pop(&shred->info->frame); if(shred->mem == (m_bit*)shred + sizeof(struct VM_Shred_) + SIZEOF_REG) return true; // literally unwind @@ -1007,11 +1008,13 @@ gack: goto in; try_ini: if(!shred->info->frame.ptr) // ??? - map_init(&shred->info->frame); - map_set(&shred->info->frame, PC, (m_uint)shred->reg); + vector_init(&shred->info->frame); + vector_add(&shred->info->frame, PC); + vector_add(&shred->info->frame, (m_uint)reg); DISPATCH(); try_end: - map_remove(&shred->info->frame, VLEN(&shred->info->frame)-1); + vector_pop(&shred->info->frame); + vector_pop(&shred->info->frame); handleeffect: // this should check the *xid* of the exception DISPATCH(); diff --git a/src/vm/vm_shred.c b/src/vm/vm_shred.c index 8695a2a4..737f8b78 100644 --- a/src/vm/vm_shred.c +++ b/src/vm/vm_shred.c @@ -46,7 +46,7 @@ void free_vm_shred(VM_Shred shred) { release((M_Object)vector_at(&shred->gc, i - 1), shred); vector_release(&shred->gc); if(shred->info->frame.ptr) - map_release(&shred->info->frame); + vector_release(&shred->info->frame); vmcode_remref(shred->info->orig, shred->info->vm->gwion); const MemPool mp = shred->info->mp; mp_free(mp, ShredTick, shred->tick); diff --git a/util b/util index 7d52314d..fae43107 160000 --- a/util +++ b/util @@ -1 +1 @@ -Subproject commit 7d52314d4e12c36a0b538a2cb0c1ad94086008c5 +Subproject commit fae43107367388fda4c9755dfdd7abfa427de5b8 -- 2.43.0