]> Nishi Git Mirror - gwion.git/commitdiff
:bug: Fix macro argument on commas and newline, also capture scoping
authorJérémie Astor <fennecdjay@gmail.com>
Wed, 27 Apr 2022 13:52:26 +0000 (15:52 +0200)
committerJérémie Astor <fennecdjay@gmail.com>
Wed, 27 Apr 2022 13:52:26 +0000 (15:52 +0200)
ast
include/env/func.h
src/lib/lib_func.c
src/lib/object_op.c
src/parse/check.c

diff --git a/ast b/ast
index c24bc9c768b4521845b7b7b5e7947cd31ed993ef..f7a74f13840d253dc95ccdbf38adee626f7dd5e0 160000 (submodule)
--- a/ast
+++ b/ast
@@ -1 +1 @@
-Subproject commit c24bc9c768b4521845b7b7b5e7947cd31ed993ef
+Subproject commit f7a74f13840d253dc95ccdbf38adee626f7dd5e0
index 00ad969026820e099b899ec7da810c4f2d972c2b..113f8140c8f749da3cab58d3a206e71e98f9bac6 100644 (file)
@@ -36,4 +36,10 @@ Symbol     func_symbol(const Env, const m_str, const m_str, const m_str,
 ANN m_bool check_lambda(const Env, const Type, Exp_Lambda *);
 ANN Type   check_op_call(const Env env, Exp_Call *const exp);
 ANN void   builtin_func(const MemPool mp, const Func f, void *func_ptr);
+
+static inline Value upvalues_lookup(const Upvalues *upvalues, const Symbol sym) {
+  const Value v = (Value)scope_lookup1(upvalues->values, (m_uint)sym);
+  if(v) return v;
+  return upvalues->parent ? upvalues_lookup(upvalues->parent, sym) : NULL;
+}
 #endif
index 26e6c11621b290515e9c242f57933f79b915b52d..a9e6cb51fe30f3d882c760070aa26d458a5b10d5 100644 (file)
@@ -264,7 +264,10 @@ ANN static m_bool _check_lambda(const Env env, Exp_Lambda *l,
   //  if(GET_FLAG(def->base, global) && !l->owner &&
   //  def->base->func->value_ref->from->owner_class)
   UNSET_FLAG(l->def->base, global);
-  l->def->base->values = env->curr->info->value;
+  Upvalues upvalues = {
+    .values = env->curr->info->value
+  };
+  l->def->base->values = &upvalues;
   const m_uint scope   = env->scope->depth;
   if(GET_FLAG(fdef->base, global) && !l->owner &&
     fdef->base->func->value_ref->from->owner_class)
@@ -277,9 +280,9 @@ ANN static m_bool _check_lambda(const Env env, Exp_Lambda *l,
    env_pop(env, scope);
 
   if (l->def->base->func) {
-    if (env->curr->info->value != l->def->base->values) {
+    if (env->curr->info->value != l->def->base->values->values) {
       free_scope(env->gwion->mp, env->curr->info->value);
-      env->curr->info->value = l->def->base->values;
+      env->curr->info->value = l->def->base->values->values;
     }
   }
 
@@ -661,7 +664,11 @@ static OP_CHECK(opck_spork) {
       }
     }
     ++env->scope->depth;
-    const Scope scope = env->curr->info->value;
+    Upvalues values = {
+      .values = env->curr->info->value
+    };
+    if(env->func && env->func->def->base->values)
+      values.parent = env->func->def->base->values;
     env->curr->info->value = new_scope(env->gwion->mp);
     if(unary->captures) {
       for(uint32_t i = 0; i < unary->captures->len; i++) {
@@ -673,7 +680,7 @@ static OP_CHECK(opck_spork) {
     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};
+    struct Func_Base_ fbase = { .xid=insert_symbol("in spork"), .values = &values};
     set_fbflag(&fbase, fbflag_lambda);
     struct Func_Def_ fdef = { .base = &fbase};
     struct Func_ func = { .name = "in spork", .def = &fdef, .value_ref = &value};
@@ -681,7 +688,7 @@ static OP_CHECK(opck_spork) {
     const m_bool ret = check_stmt(env, unary->code);
     env->func = f;
     free_scope(env->gwion->mp, env->curr->info->value);
-    env->curr->info->value = scope;
+    env->curr->info->value = values.values;
     --env->scope->depth;
     CHECK_BN(ret);
     return env->gwion
index 99aad2bde92d66d6f3873578bfa1a85bcf05f7e4..12ff7c616dc77ed7e925d6825dadef7691652de2 100644 (file)
@@ -167,8 +167,7 @@ ANN static inline Value get_value(const Env env, const Exp_Dot *member,
   if (value)
     return value;
   if (env->func && env->func->def->base->values)
-    return (Value)scope_lookup1(env->func->def->base->values,
-                                (m_uint)member->xid);
+    return upvalues_lookup(env->func->def->base->values, member->xid);
   return NULL;
 }
 
index 676cea9e9e8a7f8e04ad8bb985928421f5842dfe..44aa72b37e57029d346a96356179594509d67994 100644 (file)
@@ -275,7 +275,7 @@ ANN static inline Value get_value(const Env env, const Symbol sym) {
       return value;
   }
   if (env->func && env->func->def->base->values) {
-    DECL_OO(const Value, v, = (Value)scope_lookup1(env->func->def->base->values, (vtype)sym));
+    DECL_OO(const Value, v, = upvalues_lookup(env->func->def->base->values, sym));
     if(isa(env->func->value_ref->type, env->gwion->type[et_lambda]) > 0)
       CHECK_OO(not_upvalue(env, v));
     return v;
@@ -362,8 +362,11 @@ ANN static Type prim_id_non_res(const Env env, const Symbol *data) {
       return env->gwion->type[et_op];
     }
     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));
+      const Value v = upvalues_lookup(env->func->def->base->values, sym);
+      if(v) {
+        CHECK_BO(check_upvalue(env, prim_self(data), v));
+        return v->type;
+      }
     }
     gwerr_basic(_("Invalid variable"), _("not legit at this point."), NULL,
                 env->name, prim_pos(data), 0);
@@ -786,11 +789,14 @@ ANN static Type check_lambda_call(const Env env, Exp_Call *const exp) {
   }
   if(e)
      ERR_O(exp_self(exp)->pos, _("argument number does not match for lambda"))
-  l->def->base->values = env->curr->info->value;
+  Upvalues upvalues = { .values = env->curr->info->value};
+  if(env->func && env->func->def->base->values)
+    upvalues.parent = env->func->def->base->values;
+  l->def->base->values = &upvalues;
   const m_bool ret     = traverse_func_def(env, l->def);
   if (l->def->base->func) {
     free_scope(env->gwion->mp, env->curr->info->value);
-    env->curr->info->value = l->def->base->values;
+    env->curr->info->value = l->def->base->values->values;
     if (env->class_def) set_vflag(l->def->base->func->value_ref, vflag_member);
     exp->func->type = l->def->base->func->value_ref->type;
     if (!l->def->base->ret_type)