Selaa lähdekoodia

fix: 修复函数调用的问题

act_arg执行C函数后需仍跳到act_normal处理msg等
popLastActivity去除, 一次只跳出一个Activity
因为Activity跳出前可能需要在act_normal做部分处理(如 macro)
activity: acl_next -> acl_done (表示当前正在执行的acl)
SongZihuan 3 vuotta sitten
vanhempi
sitoutus
c783ed4657
3 muutettua tiedostoa jossa 73 lisäystä ja 58 poistoa
  1. 2 2
      src/core/__env.h
  2. 56 17
      src/core/env.c
  3. 15 39
      src/core/run.c

+ 2 - 2
src/core/__env.h

@@ -86,7 +86,7 @@ struct af_Activity {  // 活动记录器
     enum af_BlockType call_type;  // 函数调用类型
     struct af_Object *parentheses_call;  // 类前缀调用
     struct af_ArgCodeList *acl_start;
-    struct af_ArgCodeList *acl_next;
+    struct af_ArgCodeList *acl_done;
     struct af_FuncInfo *fi;
     struct af_FuncBody *body_next;
     void *mark;  // 标记 [完全由API管理, 不随activity释放]
@@ -140,7 +140,7 @@ bool pushVariableActivity(af_Code *bt, af_Object *func, af_Environment *env);
 bool pushLiteralActivity(af_Code *bt, af_Object *func, af_Environment *env);
 bool pushMacroFuncActivity(af_Object *func, af_Environment *env);
 bool setFuncActivityToArg(af_Object *func, af_Environment *env);
-bool setFuncActivityAddVar(bool new_vsl, bool is_protect, af_Environment *env);
+bool setFuncActivityAddVar(af_Environment *env);
 int setFuncActivityToNormal(af_Environment *env);
 
 /* LiteralData 释放函数 */

+ 56 - 17
src/core/env.c

@@ -221,7 +221,7 @@ static void clearActivity(af_Activity *activity) {
     activity->bt_next = NULL;
 
     activity->acl_start = NULL;
-    activity->acl_next = NULL;
+    activity->acl_done = NULL;
     activity->fi = NULL;
     activity->body_next = NULL;
 }
@@ -637,20 +637,18 @@ bool setFuncActivityToArg(af_Object *func, af_Environment *env) {
     if (!get_var_list(&env->activity->func_var_list, func, env->activity->mark, env))  // 设置 func_var_list
         return false;
 
-    env->activity->acl_next = env->activity->acl_start;
-    if (env->activity->acl_next != NULL)
-        env->activity->bt_next = env->activity->acl_next->code;
+    env->activity->acl_done = env->activity->acl_start;
+    if (env->activity->acl_done != NULL)
+        env->activity->bt_next = env->activity->acl_done->code;
     else
         env->activity->bt_next = NULL;
     return true;
 }
 
-bool setFuncActivityAddVar(bool new_vsl, bool is_protect, af_Environment *env){
-    if (!new_vsl && is_protect)
-        return false;
-
+bool setFuncActivityAddVar(af_Environment *env){
     obj_funcGetInfo *get_info = findAPI("obj_funcGetInfo", env->activity->func->data->api);
     obj_funcGetArgList *get_arg_list = findAPI("obj_funcGetArgList", env->activity->func->data->api);
+    af_ArgList *al;
 
     if (get_info == NULL || get_arg_list == NULL) {
         pushMessageDown(makeMessage("ERROR-STR", 0), env);
@@ -663,32 +661,54 @@ bool setFuncActivityAddVar(bool new_vsl, bool is_protect, af_Environment *env){
         pushMessageDown(makeMessage("ERROR-STR", 0), env);
         return false;
     }
+    if (env->activity->fi->scope == super_pure_scope && env->activity->fi->scope == super_embedded) {
+        /* 超纯函数和超内嵌函数不得搭配使用 */
+        pushMessageDown(makeMessage("ERROR-STR", 0), env);
+        return false;
+    }
     env->activity->body_next = env->activity->fi->body;
 
     if (env->activity->fi->is_macro) {  // 是宏函数则保存变量空间
         env->activity->macro_vsl = env->activity->var_list;
         env->activity->macro_vs_count = env->activity->new_vs_count;
-    } else if (!freeVarSpaceListCount(env->activity->new_vs_count, env->activity->var_list)) { // 不是宏函数则释放外部变量空间
-        pushMessageDown(makeMessage("ERROR-STR", 0), env);
-        return false;
+    } else if (env->activity->fi->scope != inline_scope) {  // 非内联函数, 释放外部变量空间
+        if (!freeVarSpaceListCount(env->activity->new_vs_count, env->activity->var_list)) {
+            pushMessageDown(makeMessage("ERROR-STR", 0), env);  // 释放失败
+            return false;
+        }
     }
 
-    env->activity->var_list = env->activity->func_var_list;
-    env->activity->func_var_list = NULL;
-    env->activity->new_vs_count = 0; // 目前func_var_list引用自var_list, 故不设置此值 [桩]
-    if (new_vsl) {
+    if (env->activity->fi->scope == normal_scope) {  // 使用函数变量空间
+        env->activity->var_list = env->activity->func_var_list;
+        env->activity->new_vs_count = 0;
+    } else if (env->activity->fi->scope == pure_scope) {  // 纯函数只有 protect 变量空间
+        env->activity->var_list = makeVarSpaceList(env->core->protect);
+        env->activity->new_vs_count = 0;
+    } else if (env->activity->fi->scope == super_pure_scope) {  // 超纯函数没有变量空间, 因此不得为超内嵌函数(否则var_list就为NULL了)
+        env->activity->var_list = NULL;
+        env->activity->new_vs_count = 0;
+    }
+
+    if (env->activity->fi->embedded != super_embedded) {  // 不是超内嵌函数则引入一层新的变量空间
         env->activity->var_list = pushNewVarList(env->activity->var_list);
         env->activity->new_vs_count++;
     }
 
-    af_ArgList *al;
+    env->activity->func_var_list = NULL;
     if (!get_arg_list(&al, env->activity->func, env->activity->acl_start, env->activity->mark, env))
         return false;
     runArgList(al, env->activity->var_list);
     freeAllArgList(al);
 
-    if (new_vsl && is_protect)
+    if (env->activity->fi->embedded == protect_embedded)
         env->activity->var_list->vs->is_protect = true;
+
+    int status = setFuncActivityToNormal(env);
+    if (status == -1) {
+        popActivity(makeMessage("ERROR-STR", 0), env);
+        return false;
+    } else if (status == 0)
+        env->process_msg_first = true;  // 先不弹出activity, 通过act_normal处理msg
     return true;
 }
 
@@ -749,7 +769,25 @@ static void freeMark(af_Environment *env) {
 }
 
 void popActivity(af_Message *msg, af_Environment *env) {
+    env->process_msg_first = true;
+
+    if (env->activity->return_first) {
+        if (msg != NULL) {
+            gc_delReference(*(af_Object **)msg->msg);
+            freeMessage(msg);
+        }
+
+        if (env->activity->return_obj == NULL)
+            msg = makeMessage("ERROR-STR", 0);
+        else {
+            msg = makeMessage("NORMAL", sizeof(af_Object *));
+            *(af_Object **)msg->msg = env->activity->return_obj;  // env->activity->return_obj本来就有一个gc_Reference
+            env->activity->return_obj = NULL;
+        }
+    }
+
     freeMark(env);
+
     if (env->activity->prev != NULL) {
         af_Message *new_msg;
         if (msg != NULL) {
@@ -767,5 +805,6 @@ void popActivity(af_Message *msg, af_Environment *env) {
         }
         runTopMessageProcess(env);
     }
+
     env->activity = freeActivity(env->activity);
 }

+ 15 - 39
src/core/run.c

@@ -10,7 +10,6 @@ static bool codeBlock(af_Code *code, af_Environment *env);
 
 /* 工具函数 */
 static bool checkInMsgType(char *type, af_Environment *env);
-static void popLastActivity(af_Message *msg, af_Environment *env) ;
 
 static bool codeVariable(af_Code *code, af_Environment *env) {
     af_Var *var = findVarFromVarList(code->variable.name, env->activity->vsl);
@@ -74,29 +73,6 @@ static bool checkInMsgType(char *type, af_Environment *env) {
     return false;
 }
 
-static void popLastActivity(af_Message *msg, af_Environment *env) {
-    env->process_msg_first = true;
-
-    do {  // 如果返回一级后仍是执行完成则继续返回
-        if (env->activity->return_first) {
-            if (msg != NULL) {
-                gc_delReference(*(af_Object **)msg->msg);
-                freeMessage(msg);
-            }
-
-            if (env->activity->return_obj == NULL)
-                msg = makeMessage("ERROR-STR", 0);
-            else {
-                msg = makeMessage("NORMAL", sizeof(af_Object *));
-                *(af_Object **)msg->msg = env->activity->return_obj;  // env->activity->return_obj本来就有一个gc_Reference
-                env->activity->return_obj = NULL;
-            }
-        }
-        popActivity(msg, env);
-        msg = NULL;  // 随后几次执行popActivity时不需要压入新的msg
-    } while (env->activity != NULL && env->activity->bt_next == NULL);
-}
-
 static bool checkLiteral(af_Message **msg, af_Environment *env) {
     if (!env->activity->is_literal)
         return true;
@@ -144,7 +120,7 @@ bool iterCode(af_Code *code, af_Environment *env) {
         else
             env->activity->vsl = env->activity->var_list;
 
-        if (env->activity->bt_next != NULL) {
+        if (env->activity->bt_next != NULL || env->process_msg_first) {
             run_code = true;
             if (!env->process_msg_first) {
                 switch (env->activity->bt_next->type) {
@@ -176,7 +152,7 @@ bool iterCode(af_Code *code, af_Environment *env) {
                     if (env->activity->return_obj != NULL)
                         gc_delReference(env->activity->return_obj);
                     env->activity->return_obj = NULL;
-                    popLastActivity(NULL, env);  // msg 已经 push进去了
+                    popActivity(NULL, env);  // msg 已经 push进去了
                     continue;
                 }
             } else if (env->activity->return_first && env->activity->return_obj == NULL) {  // 设置return_first
@@ -188,14 +164,14 @@ bool iterCode(af_Code *code, af_Environment *env) {
         switch (env->activity->status) {
             case act_normal:
                 if (!run_code)
-                    popLastActivity(makeMessage("ERROR-STR", 0), env);
+                    popActivity(makeMessage("ERROR-STR", 0), env);
                 else if (env->activity->bt_next == NULL) { // 执行完成
                     switch (setFuncActivityToNormal(env)) {
                         case -1:  // 已经没有下一步了 (原msg不释放)
                             if (checkMacro(msg, env))  // 检查是否宏函数
                                 break;  // 继续执行
                             checkLiteral(&msg, env);  // 检查是否字面量
-                            popLastActivity(msg, env);
+                            popActivity(msg, env);
                             break;
                         case 0:  // 已经没有下一步了 (但原msg释放)
                             gc_delReference(*(af_Object **)(msg->msg));  // msg->msg是一个指针, 这个指针的内容是一个af_Object *
@@ -210,7 +186,7 @@ bool iterCode(af_Code *code, af_Environment *env) {
                                 checkLiteral(&msg, env);  // 检查是否字面量
                             }
 
-                            popLastActivity(msg, env);
+                            popActivity(msg, env);
                             break;
                         default:
                         case 1:  // 继续运行
@@ -229,29 +205,29 @@ bool iterCode(af_Code *code, af_Environment *env) {
                 break;
             case act_func: {
                 if (!run_code)
-                    popLastActivity(makeMessage("ERROR-STR", 0), env);
+                    popActivity(makeMessage("ERROR-STR", 0), env);
                 else {
                     af_Object *func = *(af_Object **)(msg->msg);  // func仍保留了msg的gc计数
                     gc_delReference(func);  // 释放计数
                     freeMessage(msg);
                     if (!setFuncActivityToArg(func, env))  // 该函数会设定bt_next到arg计算的bt上
-                        popLastActivity(NULL, env);  // setFuncActivityToArg中已设置msg
+                        popActivity(NULL, env);  // setFuncActivityToArg中已设置msg
                 }
                 break;
             }
             case act_arg: {
                 if (!run_code) {  // 无参数设定
-                    if (!setFuncActivityAddVar(true, false, env) || !setFuncActivityToNormal(env))
-                        popLastActivity(NULL, env);
+                    if (!setFuncActivityAddVar(env))
+                        popActivity(NULL, env);
                 } else {
-                    env->activity->acl_next->result = *(af_Object **)(msg->msg);
+                    env->activity->acl_done->result = *(af_Object **)(msg->msg);
                     freeMessage(msg);
-                    if (env->activity->acl_next->next == NULL) { // 参数设定结束
-                        if (!setFuncActivityAddVar(true, false, env) || !setFuncActivityToNormal(env))
-                            popLastActivity(NULL, env);
+                    if (env->activity->acl_done->next == NULL) { // 参数设定结束
+                        if (!setFuncActivityAddVar(env))
+                            popActivity(NULL, env);
                     } else {
-                        env->activity->acl_next = env->activity->acl_next->next;
-                        env->activity->bt_next = env->activity->acl_next->code;
+                        env->activity->acl_done = env->activity->acl_done->next;
+                        env->activity->bt_next = env->activity->acl_done->code;
                     }
                 }
                 break;