From 6b9fa3ac97ed604fc67b2a7480ca86435b195b10 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=A9mie=20Astor?= Date: Wed, 27 Apr 2022 11:33:24 +0200 Subject: [PATCH] :art: Improve upvalue handling --- src/lib/deep_equal.c | 1 + src/lib/lib_func.c | 3 ++- src/parse/check.c | 27 +++++++++++++++++---------- 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/src/lib/deep_equal.c b/src/lib/deep_equal.c index 34fd7afe..ba177acb 100644 --- a/src/lib/deep_equal.c +++ b/src/lib/deep_equal.c @@ -156,6 +156,7 @@ ANN static void deep_emit_init(const Emitter emit, struct DeepEmit *d, const m_i const Instr instr = emit_add_instr(emit, Reg2Mem); instr->m_val2 = offset; d->val->from->offset = instr->m_val = emit_localn(emit, d->val->type); + d->val->from->loc = d->exp->pos; } ANN static void deep_emit_release(const Emitter emit, struct DeepEmit *d) { diff --git a/src/lib/lib_func.c b/src/lib/lib_func.c index 5ce11242..7ca4c554 100644 --- a/src/lib/lib_func.c +++ b/src/lib/lib_func.c @@ -684,10 +684,11 @@ static OP_CHECK(opck_spork) { } } const Func f = env->func; - struct Value_ value = {}; + struct Value_ value = { .type = env->gwion->type[et_lambda]}; if(env->class_def) set_vflag(&value, vflag_member); struct Func_Base_ fbase = { .xid=insert_symbol("in spork"), .values = scope}; + set_fbflag(&fbase, fbflag_lambda); struct Func_Def_ fdef = { .base = &fbase}; struct Func_ func = { .name = "in spork", .def = &fdef, .value_ref = &value}; env->func = &func; diff --git a/src/parse/check.c b/src/parse/check.c index f9a8abc0..c2a8074f 100644 --- a/src/parse/check.c +++ b/src/parse/check.c @@ -274,8 +274,12 @@ ANN static inline Value get_value(const Env env, const Symbol sym) { if (!value->from->owner_class || isa(env->class_def, value->from->owner_class) > 0) return value; } - if (env->func && env->func->def->base->values) - return (Value)scope_lookup1(env->func->def->base->values, (vtype)sym); + if (env->func && env->func->def->base->values) { + DECL_OO(const Value, v, = (Value)scope_lookup1(env->func->def->base->values, (vtype)sym)); + if(isa(env->func->value_ref->type, env->gwion->type[et_lambda]) > 0) + CHECK_OO(not_upvalue(env, v)); + return v; + } return NULL; } @@ -326,8 +330,7 @@ static inline Nspc value_owner(const Env env, const Value v) { return v ? v->from->owner : env->curr; } -ANN static m_bool check_upvalue(const Env env, const Exp_Primary *prim) { - const Value v = prim->value; +ANN static m_bool check_upvalue(const Env env, const Exp_Primary *prim, const Value v) { if(not_upvalue(env, v)) return GW_OK; gwerr_basic(_("value not in lambda scope"), NULL, NULL, env->name, exp_self(prim)->pos, 4242); @@ -358,9 +361,11 @@ ANN static Type prim_id_non_res(const Env env, const Symbol *data) { prim_self(data)->value = env->gwion->type[et_op]->info->value; return env->gwion->type[et_op]; } - const m_str hint = (!env->func || strcmp(env->func->name, "in spork")) ? - NULL : "vapturelist?"; - gwerr_basic(_("Invalid variable"), _("not legit at this point."), hint, + if (env->func && fbflag(env->func->def->base, fbflag_lambda) && env->func->def->base->values) { + const Value v = (Value)scope_lookup1(env->func->def->base->values, (vtype)sym); + if(v) CHECK_BO(check_upvalue(env, prim_self(data), v)); + } + gwerr_basic(_("Invalid variable"), _("not legit at this point."), NULL, env->name, prim_pos(data), 0); did_you_mean_nspc(v ? value_owner(env, v) : env->curr, s_name(sym)); env_set_error(env); @@ -373,7 +378,7 @@ ANN static Type prim_id_non_res(const Env env, const Symbol *data) { if (!GET_FLAG(v, const) && v->from->owner) unset_fflag(env->func, fflag_pure); if (fbflag(env->func->def->base, fbflag_lambda)) - CHECK_BO(check_upvalue(env, prim_self(data))); + CHECK_BO(check_upvalue(env, prim_self(data), v)); } // set_vflag(v->vflag, vflag_used); return v->type; @@ -1217,8 +1222,9 @@ ANN static inline m_bool for_empty(const Env env, const Stmt_For stmt) { ANN static void check_idx(const Env env, const Type base, struct EachIdx_ *const idx) { idx->v = new_value(env->gwion->mp, base, s_name(idx->sym)); - valuefrom(env, idx->v->from, idx->pos); valid_value(env, idx->sym, idx->v); + idx->v->from->loc = idx->pos; + idx->v->from->filename = env->name; SET_FLAG(idx->v, const); } @@ -1254,7 +1260,8 @@ ANN static m_bool do_stmt_each(const Env env, const Stmt_Each stmt) { DECL_OB(const Type, ret, = check_each_val(env, stmt->exp)); stmt->v = new_value(env->gwion->mp, ret, s_name(stmt->sym)); valid_value(env, stmt->sym, stmt->v); - valuefrom(env, stmt->v->from, stmt->vpos); + stmt->v->from->loc = stmt->vpos; + stmt->v->from->filename = env->name; return check_conts(env, stmt_self(stmt), stmt->body); } -- 2.43.0