]> Nishi Git Mirror - gwion.git/commitdiff
:art: Improve upvalue handling
authorJérémie Astor <fennecdjay@gmail.com>
Wed, 27 Apr 2022 09:33:24 +0000 (11:33 +0200)
committerJérémie Astor <fennecdjay@gmail.com>
Wed, 27 Apr 2022 09:33:24 +0000 (11:33 +0200)
src/lib/deep_equal.c
src/lib/lib_func.c
src/parse/check.c

index 34fd7afef640fec6781cc52fc5335129fcaa0da7..ba177acbe196a8880727073dda3a9939d54c9bdc 100644 (file)
@@ -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) {
index 5ce1124288270598738a417a0d9d4183b60720c8..7ca4c554b9aa569dade42cf551a72ce756bfa5b6 100644 (file)
@@ -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;
index f9a8abc0d1dd0a399d1f3b32612dc3fe3d5f8515..c2a8074fc73ac158263a68da40755f31d3a00d40 100644 (file)
@@ -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);
 }