Explorar o código

fix: 修复字面量使用尾调递归优化的问题

字面量使用尾调递归优化可能会因为上层code被释放而无法访问literal_data
字面量调用函数中对字面量调用不再使用尾调递归优化
SongZihuan %!s(int64=3) %!d(string=hai) anos
pai
achega
a3e03d1739
Modificáronse 8 ficheiros con 84 adicións e 20 borrados
  1. 1 0
      include/env.h
  2. 3 0
      include/obj_api.h
  3. 4 5
      include/prefix_macro.h
  4. 1 0
      src/core/__env.h
  5. 2 1
      src/core/code.c
  6. 15 10
      src/core/env.c
  7. 4 2
      src/core/run.c
  8. 54 2
      src/main.c

+ 1 - 0
include/env.h

@@ -27,6 +27,7 @@ void freeEnvironment(af_Environment *env);
 /* 保护空间管理函数 */
 bool addVarToProtectVarSpace(af_Var *var, af_Environment *env);
 af_Object *getBaseObject(char *name, af_Environment *env);
+af_VarSpace *getProtectVarSpace(af_Environment *env);
 
 /* 消息创建与释放函数 */
 af_Message *makeMessage(char *type, size_t size);

+ 3 - 0
include/obj_api.h

@@ -38,4 +38,7 @@ typedef void obj_funcFreeMask(void *mark);  // 释放mask的函数
 /* Object 字面量设定 */
 typedef void obj_literalSetting(char *str, void *data, af_Object *obj, af_Environment *env);
 
+/* Object 变量专项 */
+typedef bool is_obj_func(af_Object *obj);  // 是否对象函数
+
 #endif //AFUN__OBJ_API_H

+ 4 - 5
include/prefix_macro.h

@@ -6,12 +6,11 @@
 #define AFUN__PREFIX_MACRO_H
 
 // 作为顶层代码,以及'()运行时
-#define L_NOT_REPEAT      (0)  /* 字面量前缀: 不重复构造 */
-#define V_QUOTE           (1)  /* 变量前缀: 引用 */
+#define V_QUOTE           (0)  /* 变量前缀: 引用 */
 
-#define B_EXEC            (2)  /* 括号前缀: 顺序执行 */
-#define B_EXEC_FIRST      (3)  /* 括号前缀: 顺序执行, 返回第一个 */
+#define B_EXEC            (1)  /* 括号前缀: 顺序执行 */
+#define B_EXEC_FIRST      (2)  /* 括号前缀: 顺序执行, 返回第一个 */
 
-#define PREFIX_SIZE       (4)  /* 前缀总数 */
+#define PREFIX_SIZE       (3)  /* 前缀总数 */
 
 #endif //AFUN__PREFIX_MACRO_H

+ 1 - 0
src/core/__env.h

@@ -89,6 +89,7 @@ struct af_Activity {  // 活动记录器
 
     /* 字面量专项 */
     bool is_literal;  // 处于字面量运算 意味着函数调用结束后会调用指定API
+    char *literal_data;  // bt->literal.literal_data
 };
 
 struct af_TopMsgProcess {  // 顶层msg处理器

+ 2 - 1
src/core/code.c

@@ -159,7 +159,8 @@ bool freeCodeWithElement(af_Code *bt, af_Code **next) {
             return false;
         bt = freeCode(bt);
     }
-    *next = bt;
+    if (next != NULL)
+        *next = bt;
     return true;
 }
 

+ 15 - 10
src/core/env.c

@@ -17,7 +17,7 @@ static void clearActivity(af_Activity *activity);
 
 /* 活动记录器相关处理函数 */
 static void freeMark(af_Environment *env);
-static void newActivity(af_Code *bt, const af_Code *next, bool return_first, af_Environment *env);
+static void newActivity(af_Code *bt, const af_Code *next, bool return_first, bool tail, af_Environment *env);
 static void freeMarkByActivity(af_Activity *activity);
 
 /* 环境变量创建与释放 */
@@ -42,9 +42,7 @@ static af_Core *makeCore(void) {
     addVarSpaceGCByCore(core->protect, core);
     gc_addReference(core->protect);  // protect被外部引用, 由gc管理, 此处标记一个Reference
 
-    core->prefix[L_NOT_REPEAT] = '\'';
     core->prefix[V_QUOTE] = '\'';
-
     core->prefix[B_EXEC] = '\'';
     core->prefix[B_EXEC_FIRST] = ',';
 
@@ -73,6 +71,10 @@ char getPrefix(size_t name, af_Environment *env) {
     return env->core->prefix[name];
 }
 
+af_VarSpace *getProtectVarSpace(af_Environment *env) {
+    return env->core->protect;
+}
+
 /*
  * 函数名: getBaseObjectFromCore
  * 目标: 从VarSpace中获取一个量
@@ -105,7 +107,6 @@ static void checkInherit(af_Inherit **ih, af_Object *obj) {
     *ih = makeInherit(obj);
 }
 
-
 static bool enableCore(af_Core *core) {
     af_Object *object = getBaseObjectFromCore("object", core);
     af_Object *global = getBaseObjectFromCore("global", core);
@@ -189,6 +190,7 @@ static af_Activity *freeActivity(af_Activity *activity) {
     freeAllArgCodeList(activity->acl_start);
     if (activity->fi != NULL)
         freeFuncInfo(activity->fi);
+    free(activity->literal_data);
     free(activity);
     return prev;
 }
@@ -465,8 +467,8 @@ bool changeTopMsgProcess(char *type, DLC_SYMBOL(TopMsgProcessFunc) func,
     return true;
 }
 
-static void newActivity(af_Code *bt, const af_Code *next, bool return_first, af_Environment *env){
-    if (next == NULL && env->activity->body_next == NULL) {
+static void newActivity(af_Code *bt, const af_Code *next, bool return_first, bool tail, af_Environment *env){
+    if (tail && next == NULL && env->activity->body_next == NULL) {
         printf("Tail tone recursive optimization\n");
         clearActivity(env->activity);
         env->activity->bt_top = bt;
@@ -490,7 +492,7 @@ bool pushExecutionActivity(af_Code *bt, bool return_first, af_Environment *env)
 
     env->activity->bt_next = next;
 
-    newActivity(bt, next, return_first, env);
+    newActivity(bt, next, return_first, true, env);
     env->activity->bt_start = bt->next;
     env->activity->bt_next = bt->next;
 
@@ -526,7 +528,7 @@ bool pushFuncActivity(af_Code *bt, af_Environment *env) {
 
     env->activity->bt_next = next;
 
-    newActivity(bt, next, false, env);
+    newActivity(bt, next, false, true, env);
     env->activity->bt_start = func;
     env->activity->bt_next = func;
 
@@ -538,10 +540,13 @@ bool pushFuncActivity(af_Code *bt, af_Environment *env) {
 }
 
 bool pushLiteralActivity(af_Code *bt, af_Object *func, af_Environment *env) {
+    char *literal_data = strCopy(bt->literal.literal_data);  // newActivity可能会导致code和literal_data释放
     env->activity->bt_next = bt->next;
 
-    newActivity(bt, bt->next, false, env);
+    /* 隐式调用不设置 bt_top */
+    newActivity(NULL, bt->next, false, !env->activity->is_literal, env);  // 如果原activity也是字面量, 则不进行尾调递归优化
     env->activity->is_literal = true;
+    env->activity->literal_data = literal_data;
     return setFuncActivityToArg(func, env);
 }
 
@@ -560,7 +565,7 @@ bool pushMacroFuncActivity(af_Object *func, af_Environment *env) {
     env->activity->new_vs_count = env->activity->macro_vs_count;
     env->activity->macro_vs_count = 0;
 
-    clearActivity(env->activity);
+    clearActivity(env->activity); /* 隐式调用不设置 bt_top */
     return setFuncActivityToArg(func, env);
 }
 

+ 4 - 2
src/core/run.c

@@ -33,7 +33,6 @@ static void codeVariable(af_Code *code, af_Environment *env) {
 
 static bool codeLiteral(af_Code *code, af_Environment *env) {
     af_Var *var;
-
     if (code->literal.in_protect)
         var = findVarFromVarSpace(code->literal.func, env->core->protect);
     else
@@ -102,7 +101,10 @@ static bool checkLiteral(af_Message **msg, af_Environment *env) {
         *msg = makeMessage("ERROR-STR", 0);
         return false;
     }
-    func(env->activity->bt_top->literal.literal_data, obj->data->data, obj, env);
+
+    func(env->activity->literal_data, obj->data->data, obj, env);
+    free(env->activity->literal_data);
+    env->activity->is_literal = false;
     return true;
 }
 

+ 54 - 2
src/main.c

@@ -31,8 +31,9 @@ bool getAcl(ArgCodeList **acl, af_Object *obj, af_Code *code, int **mark, af_Env
     return true;
 }
 
-bool getVsl(af_VarSpaceListNode **vsl, af_Object *obj, void *mark, af_Environment *env) {
-    *vsl = makeVarSpaceList(makeVarSpace());
+bool getVsl(af_VarSpaceListNode **vsl, af_Object *obj, void *mark, af_Environment *env) {  // [桩]
+    *vsl = makeVarSpaceList(getProtectVarSpace(env));
+    pushNewVarList(*vsl);
     return true;
 }
 
@@ -124,6 +125,12 @@ bool getInfo2(af_FuncInfo **fi, af_Object *obj, af_Code *code, void *mark, af_En
     return true;
 }
 
+bool getInfo3(af_FuncInfo **fi, af_Object *obj, af_Code *code, void *mark, af_Environment *env) {
+    *fi = makeFuncInfo(normal_scope, not_embedded, false, false);  // 获取FuncInfo [桩]
+    makeCodeFuncBodyToFuncInfo(makeLiteralCode("data3", "func", true, NUL, 0, "Unknow"), true, NULL, *fi);
+    return true;
+}
+
 int main() {
     aFunInit();
     printf("Hello World\n");
@@ -205,6 +212,34 @@ int main() {
         FREE_SYMBOL(free_mark);
     }
 
+    {
+        af_ObjectAPI *api = makeObjectAPI();
+        DLC_SYMBOL(objectAPIFunc) get_alc = MAKE_SYMBOL(getAcl, objectAPIFunc);
+        DLC_SYMBOL(objectAPIFunc) get_vsl = MAKE_SYMBOL(getVsl, objectAPIFunc);
+        DLC_SYMBOL(objectAPIFunc) get_al = MAKE_SYMBOL(getAl, objectAPIFunc);
+        DLC_SYMBOL(objectAPIFunc) get_info3 = MAKE_SYMBOL(getInfo3, objectAPIFunc);
+        DLC_SYMBOL(objectAPIFunc) free_mark = MAKE_SYMBOL(freeMark, objectAPIFunc);
+        if (addAPI(get_alc, "obj_funcGetArgCodeList", api) != 1)
+            return 2;
+        if (addAPI(get_vsl, "obj_funcGetVarList", api) != 1)
+            return 2;
+        if (addAPI(get_al, "obj_funcGetArgList", api) != 1)
+            return 2;
+        if (addAPI(get_info3, "obj_funcGetInfo", api) != 1)
+            return 2;
+        if (addAPI(free_mark, "obj_funcFreeMask", api) != 1)
+            return 2;
+
+        addVarToProtectVarSpace(makeVar("func3", 3, 3,
+                                        makeObject("func", true, api, true, NULL, NULL, env)),
+                                env);
+        FREE_SYMBOL(get_alc);
+        FREE_SYMBOL(get_vsl);
+        FREE_SYMBOL(get_al);
+        FREE_SYMBOL(get_info3);
+        FREE_SYMBOL(free_mark);
+    }
+
     addVarToProtectVarSpace(makeVar("object", 3, 3,
                                     makeObject("object", true, makeObjectAPI(), true, NULL, NULL, env)),
                             env);
@@ -386,6 +421,23 @@ int main() {
         printf("\n");
     }
 
+    {  // 双层尾调递归优化 (函数内调用函数)
+        printf("TAG M:\n");
+        af_Code *bt2 = makeVariableCode("func3", 0, 1, NULL);
+        af_Code *bt3 = makeBlockCode(curly, bt2, 0, 1, NULL, NULL);
+
+        af_Code *bt4 = makeVariableCode("func3", 0, 1, NULL);
+        af_Code *bt5 = makeBlockCode(curly, bt4, 0, 1, NULL, NULL);
+        connectCode(&bt3, bt5);
+
+        af_Code *bt6 = makeVariableCode("global", 0, 1, NULL);
+        connectCode(&bt5, bt6);
+
+        iterCode(bt3, env);
+        freeAllCode(bt3);
+        printf("\n");
+    }
+
     freeEnvironment(env);
     return 0;
 }