Przeglądaj źródła

feat & fix: 添加了run模块和run简单测试

添加了run模块,可以迭代执行bt代码
添加了此次run模块的对标测试程序
为CTest添加了环境创建测试程序
修复了部分bug
SongZihuan 3 lat temu
rodzic
commit
230cd12f15
13 zmienionych plików z 224 dodań i 40 usunięć
  1. 1 0
      include/aFun.h
  2. 4 1
      include/env.h
  3. 2 2
      include/object.h
  4. 7 0
      include/run.h
  5. 1 1
      src/core/__gc.h
  6. 46 20
      src/core/env.c
  7. 3 0
      src/core/gc.c
  8. 15 11
      src/core/object.c
  9. 89 1
      src/core/run.c
  10. 4 4
      src/core/var.c
  11. 30 0
      src/main.c
  12. 1 0
      test/CMakeLists.txt
  13. 21 0
      test/test_env.c

+ 1 - 0
include/aFun.h

@@ -8,6 +8,7 @@
 #include "object.h"
 #include "var.h"
 #include "env.h"
+#include "run.h"
 #include "gc.h"
 
 // Init系列函数

+ 4 - 1
include/env.h

@@ -11,8 +11,10 @@ typedef struct af_Message af_Message;
 af_Object *getBaseObject(char *name, af_Environment *env);
 
 af_Environment *makeEnvironment(void);
-bool enableEnvironment(af_Code *bt, af_Environment *env);
+bool addTopActivity(af_Code *code, af_Environment *env);
+bool enableEnvironment(af_Environment *env);
 void freeEnvironment(af_Environment *env);
+bool addVarToProtectVarSpace(af_Var *var, af_Environment *env);
 
 af_Message *makeMessage(char *type, size_t size);
 af_Message *freeMessage(af_Message *msg);
@@ -22,6 +24,7 @@ void pushMessageDown(af_Message *msg, af_Environment *env);
 void *popMessageUp(char *type, af_Environment *env);
 void *getMessageData(af_Message *msg);
 af_Message *popMessageDown(char *type, af_Environment *env);
+af_Message *getFirstMessage(af_Environment *env);
 void connectMessage(af_Message **base, af_Message *msg);
 
 void setEnvVar(char *name, char *data, af_Environment *env);

+ 2 - 2
include/object.h

@@ -7,8 +7,8 @@ typedef struct af_Inherit af_Inherit;
 #include "env.h"
 #include "tool.h"
 
-af_Object *makeObject(char *id, size_t data_size, bool inherit_api, bool allow_iherit,
-                      af_Inherit *inherit, af_Environment *env);
+af_Object *makeObject(char *id, size_t data_size, bool inherit_api, bool allow_iherit, af_Object *belong,
+                      af_Inherit *iherit, af_Environment *env);
 void freeObject(af_Object *obj);
 
 af_Inherit *makeIherit(af_Object *obj);

+ 7 - 0
include/run.h

@@ -0,0 +1,7 @@
+#ifndef AFUN_RUN_H
+#define AFUN_RUN_H
+#include "macro.h"
+#include "code.h"
+
+bool iterCode(af_Code *code, af_Environment *env);
+#endif //AFUN_RUN_H

+ 1 - 1
src/core/__gc.h

@@ -17,7 +17,7 @@ typedef uint32_t GcCount;
 struct gc_info {
     bool start_gc;  // 启用gc
     bool not_clear;  // 不清除
-    GcCount *reference;  // 引用计数
+    GcCount reference;  // 引用计数
     bool reachable;  // 可达标记 [同时标识已迭代]
 };
 

+ 46 - 20
src/core/env.c

@@ -20,6 +20,8 @@ static af_Core *makeCore(void) {
     af_Core *core = calloc(sizeof(af_Core), 1);
     core->in_init = true;
     core->protect = makeVarSpace();
+    addVarSpaceGCByCore(core->protect, core);
+    gc_addReference(core->protect);  // protect被外部引用, 由gc管理, 此处标记一个Reference
     return core;
 }
 
@@ -28,8 +30,7 @@ static void freeCore(af_Core *core) {
         gc_delReference(core->object);
     if (core->global != NULL)
         gc_delReference(core->global);
-    if (core->protect != NULL)
-        freeVarSpace(core->protect);  // 无论是否gc接管都释放
+    gc_delReference(core->protect);
     gc_freeAllValue(core);
     free(core);
 }
@@ -119,6 +120,7 @@ static bool enableCore(af_Core *core) {
 
     gc_addReference(object);
     gc_addReference(global);
+    addVarSpaceGCByCore(global->data->var_space, core);  // global的vs是全局作用空间, 被外部引用, 所以由gc管理 (不需要要标记Reference, global已经标记了)
     core->in_init = false;
     return true;
 }
@@ -137,7 +139,8 @@ static af_Activity *makeActivity(af_Code *bt_top, af_Code *bt_start, bool return
     activity->belong = belong;
     activity->func = func;
     gc_addReference(belong);
-    gc_addReference(func);
+    if (func != NULL)
+        gc_addReference(func);
 
     activity->bt_top = bt_top;
     activity->bt_start = bt_start;
@@ -153,7 +156,8 @@ static af_Activity *freeActivity(af_Activity *activity) {
     af_Message *msg_up = activity->msg_up;
 
     gc_delReference(activity->belong);
-    gc_delReference(activity->func);
+    if (activity->func != NULL)
+        gc_delReference(activity->func);
 
     if (activity->return_msg != NULL)
         freeMessage(activity->return_msg);
@@ -190,6 +194,7 @@ af_Message *makeMessage(char *type, size_t size) {
 
 af_Message *freeMessage(af_Message *msg) {
     af_Message *next = msg->next;
+    free(msg->type);
     free(msg->msg);
     free(msg);
     return next;
@@ -239,6 +244,13 @@ af_Message *popMessageDown(char *type, af_Environment *env) {
     return NULL;
 }
 
+af_Message *getFirstMessage(af_Environment *env) {
+    af_Message *msg = env->activity->msg_down;
+    env->activity->msg_down = msg->next;
+    msg->next = NULL;
+    return msg;
+}
+
 void connectMessage(af_Message **base, af_Message *msg) {
     while (*base != NULL)
         base = &((*base)->next);
@@ -277,7 +289,7 @@ static void freeEnvVarSpace(af_EnvVarSpace *evs) {
 }
 
 void setEnvVar(char *name, char *data, af_Environment *env) {
-    time33_t index = time33(name);
+    time33_t index = time33(name) % ENV_VAR_HASH_SIZE;
     af_EnvVar **pvar = &env->esv->var[index];
 
     for (NULL; *pvar != NULL; pvar = &((*pvar)->next)) {
@@ -292,7 +304,7 @@ void setEnvVar(char *name, char *data, af_Environment *env) {
 }
 
 char *findEnvVar(char *name, af_Environment *env) {
-    time33_t index = time33(name);
+    time33_t index = time33(name) % ENV_VAR_HASH_SIZE;
     af_EnvVar **pvar = &env->esv->var[index];
 
     for (NULL; *pvar != NULL; pvar = &((*pvar)->next)) {
@@ -310,11 +322,11 @@ af_Environment *makeEnvironment(void) {
     return env;
 }
 
-bool enableEnvironment(af_Code *bt, af_Environment *env) {
-    if (!enableCore(env->core))
+bool addTopActivity(af_Code *code, af_Environment *env) {
+    if (env->activity != NULL)
         return false;
 
-    env->activity = makeActivity(NULL, bt, false, NULL, NULL, env->core->global, NULL);
+    env->activity = makeActivity(NULL, code, false, NULL, NULL, env->core->global, NULL);
     env->activity->new_vs_count = 2;
     env->activity->var_list = makeVarSpaceList(env->core->global->data->var_space);
     env->activity->var_list->next = makeVarSpaceList(env->core->protect);
@@ -322,6 +334,10 @@ bool enableEnvironment(af_Code *bt, af_Environment *env) {
     return true;
 }
 
+bool enableEnvironment(af_Environment *env) {
+    return enableCore(env->core);
+}
+
 void freeEnvironment(af_Environment *env) {
     freeCore(env->core);
     freeAllActivity(env->activity);
@@ -329,6 +345,10 @@ void freeEnvironment(af_Environment *env) {
     free(env);
 }
 
+bool addVarToProtectVarSpace(af_Var *var, af_Environment *env) {
+    return addVarToVarSpace(var, env->core->protect);
+}
+
 bool pushExecutionActivity(af_Code *bt, bool return_first, af_Environment *env) {
     af_Code *next;
     if (!getCodeBlockNext(bt, &next))
@@ -361,9 +381,10 @@ bool pushFuncActivity(af_Code *bt, af_Environment *env) {
 
 bool setFuncActivityToArg(af_Object *func, af_Environment *env) {
     gc_delReference(env->activity->belong);
-    gc_delReference(env->activity->func);
+    if (env->activity->func != NULL)
+        gc_delReference(env->activity->func);
     gc_addReference(func);
-    gc_addReference(func->belong);
+    gc_addReference(func->belong);  // TODO-szh 处理belong为NULL的情况 (global的belong)
 
     env->activity->func = func;
     env->activity->belong = func->belong;
@@ -397,14 +418,19 @@ bool setFuncActivityToNormal(af_Code *bt, af_Environment *env) {
 }
 
 void popActivity(af_Message *msg, af_Environment *env) {
-    if (env->activity->prev != NULL && msg != NULL) {
-        af_Message *new_msg = msg;
-        msg->next = env->activity->prev->msg_down;
-        env->activity->prev->msg_down = msg;
-        if (env->activity->msg_down != NULL) {
-            connectMessage(&new_msg, env->activity->msg_down);
-            env->activity->msg_down = NULL;
-        }
+    if (env->activity->prev != NULL) {
+        af_Message *new_msg;
+        if (msg != NULL) {
+            new_msg = msg;
+            msg->next = env->activity->msg_down;
+        } else
+            msg = env->activity->msg_down;
+        env->activity->msg_down = NULL;
+        connectMessage(&new_msg, env->activity->prev->msg_down);
+        env->activity->prev->msg_down = new_msg;
+    } else if (msg != NULL) {  // 到顶 且 msg != NULL
+        gc_delReference(*(af_Object **)msg->msg);
+        freeMessage(msg);
     }
-    env->activity = freeActivity(env->activity);  // TODO-szh activity需要添加gc
+    env->activity = freeActivity(env->activity);
 }

+ 3 - 0
src/core/gc.c

@@ -238,6 +238,9 @@ static void freeValue(af_Core *core) {
 #define GC_ADD_FUNC_DEFINED(type) \
 void gc_add##type(af_##type *obj, af_Environment *env) { \
     obj->gc.prev = NULL; \
+    if (env->core->gc_##type != NULL) { \
+        env->core->gc_##type->gc.prev = obj; \
+    }                             \
     obj->gc.next = env->core->gc_##type; \
     env->core->gc_##type = obj; \
 } \

+ 15 - 11
src/core/object.c

@@ -48,18 +48,23 @@ static af_Object *makeObject_Pri(char *id, size_t data_size, bool inherit_api, b
  * 目标: 生成Object和ObjectData, 并且添加到gc链表中
  * 若处于初始化模式, 则belong, inherit等可以设置为NULL, 由后期统一填上
  */
-af_Object *makeObject(char *id, size_t data_size, bool inherit_api, bool allow_iherit,
-                      af_Inherit *inherit, af_Environment *env) {
+af_Object *makeObject(char *id, size_t data_size, bool inherit_api, bool allow_iherit, af_Object *belong,
+                      af_Inherit *iherit, af_Environment *env) {
     af_Object *obj = makeObject_Pri(id, data_size, inherit_api, allow_iherit);
-    if (!env->core->in_init && env->activity->belong == NULL)
-        obj->belong = env->core->global;
-    else
+
+    if (env->core->in_init || belong != NULL)
+        obj->belong = belong;
+    else if (env->activity != NULL)
         obj->belong = env->activity->belong;
+    else
+        return NULL;
 
-    if (!env->core->in_init && inherit == NULL) {
+    if (env->core->in_init || iherit != NULL)
+        obj->data->iherit = iherit;
+    else if (env->core->object != NULL)
         obj->data->iherit = makeIherit(env->core->object);
-    } else
-        obj->data->iherit = inherit;
+    else
+        return NULL;
 
     if (!env->core->in_init && inherit_api)
         obj->data->api = obj->data->iherit->obj->data->api;
@@ -87,7 +92,6 @@ void freeObjectData(af_ObjectData *od) {
 }
 
 void freeObject(af_Object *obj) {
-    freeObjectData(obj->data);
     GC_FREE_EXCHANGE(obj);
     free(obj);
 }
@@ -153,7 +157,7 @@ static void freeObjectAPI(af_ObjectAPI *api) {
  */
 int addAPIToObjectData(DlcHandle *dlc, char *func_name, char *api_name,
                         af_ObjectData *od) {
-    time33_t index = time33(api_name);
+    time33_t index = time33(api_name) % API_HASHTABLE_SIZE;
     af_ObjectAPINode **pNode = &od->api->node[index];
 
     for (NULL; *pNode != NULL; pNode = &((*pNode)->next)) {
@@ -166,7 +170,7 @@ int addAPIToObjectData(DlcHandle *dlc, char *func_name, char *api_name,
 }
 
 af_ObjectAPINode *findObjectDataAPINode(char *api_name, af_ObjectData *od) {
-    time33_t index = time33(api_name);
+    time33_t index = time33(api_name) % API_HASHTABLE_SIZE;
     for (af_ObjectAPINode *node = od->api->node[index]; node != NULL; node = node->next) {
         if (EQ_STR(node->name, api_name))
             return node;

+ 89 - 1
src/core/run.c

@@ -1,7 +1,95 @@
 #include "aFun.h"
 
+#include "run.h"
 #include "__env.h"
 #include "__object.h"
 #include "__var.h"
 #include "__gc.h"
-#include "__code.h"
+#include "__code.h"
+
+static af_Code *codeVariable(af_Code *code, af_Environment *env) {
+    af_Var *var = findVarFromVarList(code->variable.name, env->activity->var_list);
+    af_Message *msg;
+
+    if (var != NULL) {
+        af_Object *obj = var->vn->obj;
+        msg = makeMessage("NORMAL", sizeof(af_Object *));
+        *((af_Object **)msg->msg) = obj;
+        gc_addReference(obj);
+    } else {
+        msg = makeMessage("ERROR-STR", 0);
+        printf("Var not found: %s\n", code->variable.name);
+    }
+
+    pushMessageDown(msg, env);
+    return code->next;
+}
+
+static af_Code *codeLiteral(af_Code *code, af_Environment *env) {
+    af_Message *msg;
+    af_Object *obj = makeObject("Literal", 0, true, true, NULL, NULL, env);
+    printf("Literal %s : %s\n", code->literal.func, code->literal.literal_data);
+    msg = makeMessage("NORMAL", sizeof(af_Object *));
+    *((af_Object **)msg->msg) = obj;
+    gc_addReference(obj);
+    pushMessageDown(msg, env);
+    return code->next;
+}
+
+bool iterCode(af_Code *code, af_Environment *env) {
+   if (!addTopActivity(code, env))
+       return false;
+
+    while (env->activity != NULL) {
+        af_Message *msg;
+        switch (env->activity->bt_next->type) {
+            case literal:
+                env->activity->bt_next = codeLiteral(env->activity->bt_next, env);
+                break;
+            case variable:
+                env->activity->bt_next = codeVariable(env->activity->bt_next, env);
+                break;
+            case block:  // TODO-szh 考虑前缀
+                pushFuncActivity(env->activity->bt_next, env);
+                continue;  // 该步骤没有任何实质性运算
+            default:
+                break;  // 错误
+        }
+
+        msg = getFirstMessage(env);  // TODO-szh 检查是否为 NORMAL
+
+        switch (env->activity->status) {
+            case act_normal:
+                if (env->activity->bt_next == NULL) { // 执行完成
+                    do {  // 如果返回一级后仍是执行完成则继续返回
+                        if (env->activity->prev == NULL)
+                            printf("top finished\n");
+                        popActivity(msg, env);
+                        msg = NULL;  // 随后几次执行popActivity时不需要压入新的msg
+                    } while (env->activity != NULL && env->activity->bt_next == NULL);
+                } else {
+                    gc_delReference(*(af_Object **)(msg->msg));  // msg->msg是一个指针, 这个指针的内容是一个af_Object *
+                    freeMessage(msg);
+                }
+                break;
+            case act_func: {
+                af_Object *func = *(af_Object **)(msg->msg);  // func仍保留了msg的gc计数
+                freeMessage(msg);
+                setFuncActivityToArg(func, env);  // 该函数会设定bt_next到arg计算的bt上
+                gc_delReference(func);  // 释放计数
+                break;
+            }
+            case act_arg: {  // TODO-szh 暂时跳过参数设定
+                setFuncActivityAddVar(NULL, true, false, NULL, env);
+                setFuncActivityToNormal(env->activity->bt_next, env);
+                gc_delReference(*(af_Object **)(msg->msg));  // 释放计数
+                freeMessage(msg);
+                break;
+            }
+            default:
+                break;
+        }
+
+    }
+    return true;
+}

+ 4 - 4
src/core/var.c

@@ -21,7 +21,7 @@ static af_VarNode *makeVarNode(af_Object *obj, char *id) {
 
 static af_VarNode *freeVarNode(af_VarNode *vn) {
     af_VarNode *next = vn->next;
-    free(next->id);
+    free(vn->id);
     free(vn);
     return next;
 }
@@ -148,7 +148,7 @@ void addVarGC(af_Var *var, af_Environment *env) {
  * 否则返回true
  */
 bool addVarToVarSpace(af_Var *var, af_VarSpace *vs) {
-    time33_t index = time33(var->name);
+    time33_t index = time33(var->name) % VAR_HASHTABLE_SIZE;
     af_VarCup **pCup = &vs->var[index];
 
     if (vs->is_protect)
@@ -204,7 +204,7 @@ static af_Var *findVarFromVarSpaceByIndex(time33_t index, char *name, af_VarSpac
  * 目标: 在VarSpace中搜索var
  */
 af_Var *findVarFromVarSpace(char *name, af_VarSpace *vs) {
-    return findVarFromVarSpaceByIndex(time33(name), name, vs);
+    return findVarFromVarSpaceByIndex(time33(name) % VAR_HASHTABLE_SIZE, name, vs);
 }
 
 /*
@@ -212,7 +212,7 @@ af_Var *findVarFromVarSpace(char *name, af_VarSpace *vs) {
  * 目标: 在VarSpaceListNode中搜索var
  */
 af_Var *findVarFromVarList(char *name, af_VarSpaceListNode *vsl) {
-    time33_t index = time33(name);
+    time33_t index = time33(name) % VAR_HASHTABLE_SIZE;
     af_Var *var = NULL;
 
     for (NULL; vsl != NULL; vsl = vsl->next) {

+ 30 - 0
src/main.c

@@ -4,5 +4,35 @@
 int main() {
     aFunInit();
     printf("Hello World\n");
+
+    af_Environment *env = makeEnvironment();
+    addVarToProtectVarSpace(makeVar("global", 3, 3, 3,
+                                    makeObject("global", 0, false, true, NULL, NULL, env)),
+                            env);
+    addVarToProtectVarSpace(makeVar("object", 3, 3, 3,
+                                    makeObject("object", 0, false, true, NULL, NULL, env)),
+                            env);
+    if (!enableEnvironment(env)) {
+        fprintf(stderr, "Enable Error.\n");
+        exit(EXIT_FAILURE);
+    }
+
+    af_Code *bt1 = makeLiteralCode("data", "func", ',', 0, "Unknow");
+    af_Code *bt2 = makeVariableCode("object", 0, 1, NULL);
+
+    af_Code *bt3 = makeLiteralCode("data2", "func", 0, 0, NULL);
+    af_Code *bt4 = makeVariableCode("global", 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);
+
+    iterCode(bt1, env);
+    freeAllCode(bt1);
+    freeEnvironment(env);
     return 0;
 }

+ 1 - 0
test/CMakeLists.txt

@@ -27,6 +27,7 @@ ADD_aFunTest(lib test_test_lib.c)
 ADD_aFunTest(dlc test_dlc.c)
 ADD_aFunTest(byte test_byte.c)
 ADD_aFunTest(byte_code test_byte_code.c)
+ADD_aFunTest(env test_env.c)
 
 SET_LINK(lib lib_Test1)  # 链接测试程序需要的动态库
 

+ 21 - 0
test/test_env.c

@@ -0,0 +1,21 @@
+#include <stdio.h>
+#include "aFun.h"
+
+int main() {
+    aFunInit();
+
+    af_Environment *env = makeEnvironment();
+    addVarToProtectVarSpace(makeVar("global", 3, 3, 3,
+                                    makeObject("global", 0, false, true, NULL, NULL, env)),
+                            env);
+    addVarToProtectVarSpace(makeVar("object", 3, 3, 3,
+                                    makeObject("object", 0, false, true, NULL, NULL, env)),
+                            env);
+    if (!enableEnvironment(env)) {
+        fprintf(stderr, "Enable Error.\n");
+        exit(EXIT_FAILURE);
+    }
+
+    freeEnvironment(env);
+    return 0;
+}