Pārlūkot izejas kodu

feat: 添加尾调递归优化

SongZihuan 3 gadi atpakaļ
vecāks
revīzija
31c7302ad0
4 mainītis faili ar 122 papildinājumiem un 33 dzēšanām
  1. 1 0
      src/core/__env.h
  2. 55 18
      src/core/env.c
  3. 16 13
      src/core/run.c
  4. 50 2
      src/main.c

+ 1 - 0
src/core/__env.h

@@ -85,6 +85,7 @@ struct af_Activity {  // 活动记录器
     ArgCodeList *acl_start;
     ArgCodeList *acl_next;
     bool is_last;  // 最后一个函数体 (允许尾调递归优化)
+    bool in_call;  // 当重新执行该活动记录器时先不执行代码, 而是处理msg
 };
 
 struct af_TopMsgProcess {  // 顶层msg处理器

+ 55 - 18
src/core/env.c

@@ -185,6 +185,15 @@ static af_Activity *makeActivity(af_Code *bt_top, af_Code *bt_start, bool return
     return activity;
 }
 
+static void freeMsgType(char **msg_type) {
+    if (msg_type == NULL)
+        return;
+
+    for (char *tmp = *msg_type; tmp != NULL; tmp++)
+        free(tmp);
+    free(msg_type);
+}
+
 static af_Activity *freeActivity(af_Activity *activity) {
     af_Activity *prev = activity->prev;
     af_VarSpaceListNode *vs = activity->var_list;
@@ -194,9 +203,6 @@ static af_Activity *freeActivity(af_Activity *activity) {
     if (activity->func != NULL)
         gc_delReference(activity->func);
 
-    if (activity->return_obj != NULL)
-        gc_delReference(activity->return_obj);
-
     freeAllMessage(activity->msg_down);  // msg转移后需要将对应成员设置为NULL
     for (int i = activity->msg_up_count; i > 0; i--) {
         if (msg_up == NULL)  // 发生了错误
@@ -212,7 +218,14 @@ static af_Activity *freeActivity(af_Activity *activity) {
         vs = popLastVarList(vs);
     }
 
+    if (activity->return_obj != NULL)
+        gc_delReference(activity->return_obj);
+
+    if (activity->parentheses_call != NULL)
+        gc_delReference(activity->parentheses_call);
+
     freeAllArgCodeList(activity->acl_start);
+    freeMsgType(activity->msg_type);
     free(activity);
     return prev;
 }
@@ -464,34 +477,58 @@ bool pushExecutionActivity(af_Code *bt, bool return_first, af_Environment *env)
     if (!getCodeBlockNext(bt, &next))
         return false;
 
-    af_Activity *activity = makeActivity(bt, bt->next, return_first, env->activity->msg_up,
-                                         env->activity->var_list, env->activity->belong,
-                                         env->activity->func);
     env->activity->bt_next = next;
-    activity->prev = env->activity;
-    env->activity = activity;
+    if (next != NULL || !env->activity->is_last) {
+        env->activity->in_call = true;
+        af_Activity *activity = makeActivity(bt, bt->next, return_first, env->activity->msg_up,
+                                             env->activity->var_list, env->activity->belong,
+                                             env->activity->func);
+        activity->prev = env->activity;
+        env->activity = activity;
+    } else {
+        printf("Tail tone recursive optimization\n");
+        env->activity->bt_top = bt;
+        env->activity->bt_start = bt->next;
+        env->activity->bt_next = bt->next;
+        env->activity->is_last = false;
+        if (!env->activity->return_first)  // 若原本就有设置 return_first 则没有在设置的必要了, 因为该执行不会被返回
+            env->activity->return_first = return_first;
+    }
+
     env->activity->status = act_normal;
     return true;
 }
 
 bool pushFuncActivity(af_Code *bt, af_Environment *env) {
     af_Code *next;
+    af_Object **parentheses_call = &env->activity->parentheses_call;
     if (!getCodeBlockNext(bt, &next))
         return false;
 
-    af_Activity *activity = makeActivity(bt, bt->next, false, env->activity->msg_up,
-                                         env->activity->var_list, env->activity->belong,
-                                         env->activity->func);
     env->activity->bt_next = next;
-    activity->prev = env->activity;
-    env->activity = activity;
+
+    if (next != NULL || !env->activity->is_last) {
+        af_Activity *activity;
+        env->activity->in_call = true;
+        activity = makeActivity(bt, bt->next, false, env->activity->msg_up,
+                                env->activity->var_list, env->activity->belong, env->activity->func);
+        activity->prev = env->activity;
+        env->activity = activity;
+    } else {  // 尾调递归优化
+        printf("Tail tone recursive optimization\n");
+        env->activity->bt_top = bt;
+        env->activity->bt_start = bt->next;
+        env->activity->bt_next = bt->next;
+        env->activity->is_last = false;
+    }
+
     env->activity->call_type = env->activity->bt_top->block.type;
     env->activity->func_var_list = env->activity->var_list;  // 设置为函数变量空间 [桩]
 
     if (env->activity->call_type == parentheses) {  // 对于类前缀调用, 已经获得func的实际值了
-        setFuncActivityToArg(env->activity->prev->parentheses_call, env);
-        gc_delReference(env->activity->prev->parentheses_call);
-        env->activity->prev->parentheses_call = NULL;
+        setFuncActivityToArg(*parentheses_call, env);
+        gc_delReference(*parentheses_call);
+        *parentheses_call = NULL;
     } else
         env->activity->status = act_func;
 
@@ -530,10 +567,10 @@ bool setFuncActivityAddVar(bool new_vsl, bool is_protect, char **msg_type, af_En
 
     env->activity->var_list = env->activity->func_var_list;
     env->activity->func_var_list = NULL;
-    env->activity->new_vs_count = 0;
+    // env->activity->new_vs_count = 0; // 目前func_var_list引用自var_list, 故不设置此值
     if (new_vsl) {
         env->activity->var_list = pushNewVarList(env->activity->var_list);
-        env->activity->new_vs_count = 1;
+        env->activity->new_vs_count++;
     }
 
     env->activity->msg_type = msg_type;

+ 16 - 13
src/core/run.c

@@ -110,19 +110,22 @@ bool iterCode(af_Code *code, af_Environment *env) {
 
         if (env->activity->bt_next != NULL) {
             run_code = true;
-            switch (env->activity->bt_next->type) {
-                case literal:
-                    codeLiteral(env->activity->bt_next, env);
-                    break;
-                case variable:
-                    codeVariable(env->activity->bt_next, env);
-                    break;
-                case block:
-                    codeBlock(env->activity->bt_next, env);
-                    continue;  // 该步骤没有任何实质性运算
-                default:
-                    break;  // 错误
-            }
+            if (!env->activity->in_call) {
+                switch (env->activity->bt_next->type) {
+                    case literal:
+                        codeLiteral(env->activity->bt_next, env);
+                        break;
+                    case variable:
+                        codeVariable(env->activity->bt_next, env);
+                        break;
+                    case block:
+                        codeBlock(env->activity->bt_next, env);
+                        continue;  // 该步骤没有任何实质性运算
+                    default:
+                        break;  // 错误
+                }
+            } else
+                env->activity->in_call = false;
 
             if (env->activity->msg_down == NULL)  // 若未获得 msg
                 msg = makeMessage("ERROR-STR", 0);

+ 50 - 2
src/main.c

@@ -39,11 +39,29 @@ int main() {
 
         af_Code *bt3 = makeLiteralCode("data2", "func", false, 0, 0, NULL);
         af_Code *bt4 = makeVariableCode("object", 0, 1, NULL);
-        af_Code *bt6 = makeVariableCode("object", 0, 1, NULL);
 
         connectCode(&bt1, bt2);
         connectCode(&bt3, bt4);
-        connectCode(&bt4, bt6);
+
+        af_Code *bt5 = makeBlockCode(curly, bt3, 0, 1, NULL, NULL);
+        connectCode(&bt2, bt5);
+
+        af_Code *bt6 = makeVariableCode("global", 0, 1, NULL);
+        connectCode(&bt5, bt6);
+
+        iterCode(bt1, env);
+        freeAllCode(bt1);
+    }
+
+    {  // 尾调递归优化
+        af_Code *bt1 = makeLiteralCode("data", "func", false, ',', 0, "Unknow");
+        af_Code *bt2 = makeVariableCode("object", 0, 1, NULL);
+
+        af_Code *bt3 = makeLiteralCode("data2", "func", false, 0, 0, NULL);
+        af_Code *bt4 = makeVariableCode("object", 0, 1, NULL);
+
+        connectCode(&bt1, bt2);
+        connectCode(&bt3, bt4);
 
         af_Code *bt5 = makeBlockCode(curly, bt3, 0, 1, NULL, NULL);
         connectCode(&bt2, bt5);
@@ -96,6 +114,9 @@ int main() {
 
         af_Code *bt5 = makeBlockCode(parentheses, bt3, '\'', 1, NULL, NULL);
 
+        af_Code *bt6 = makeVariableCode("global", 0, 1, NULL);
+        connectCode(&bt5, bt6);
+
         iterCode(bt5, env);
         freeAllCode(bt5);
     }
@@ -108,6 +129,33 @@ int main() {
 
         af_Code *bt5 = makeBlockCode(brackets, bt3, ',', 1, NULL, NULL);
 
+        af_Code *bt6 = makeVariableCode("global", 0, 1, NULL);
+        connectCode(&bt5, bt6);
+
+        iterCode(bt5, env);
+        freeAllCode(bt5);
+    }
+
+    {  // 测试顺序执行 '(xxx) 【尾调递归优化】
+        af_Code *bt3 = makeLiteralCode("data2", "func", false, 0, 0, NULL);
+        af_Code *bt4 = makeVariableCode("global", 0, 1, NULL);
+
+        connectCode(&bt3, bt4);
+
+        af_Code *bt5 = makeBlockCode(parentheses, bt3, '\'', 1, NULL, NULL);
+
+        iterCode(bt5, env);
+        freeAllCode(bt5);
+    }
+
+    {  // 测试顺序执行 ,[xxx] 【尾调递归优化】
+        af_Code *bt3 = makeLiteralCode("data2", "func", false, 0, 0, NULL);
+        af_Code *bt4 = makeVariableCode("global", 0, 1, NULL);
+
+        connectCode(&bt3, bt4);
+
+        af_Code *bt5 = makeBlockCode(brackets, bt3, ',', 1, NULL, NULL);
+
         iterCode(bt5, env);
         freeAllCode(bt5);
     }