Browse Source

feat: 调整code的相关函数

SongZihuan 3 years ago
parent
commit
8a9dcf52bd
3 changed files with 88 additions and 31 deletions
  1. 3 1
      include/core/code.h
  2. 83 24
      src/core/code.c
  3. 2 6
      src/core/env.c

+ 3 - 1
include/core/code.h

@@ -6,7 +6,8 @@
 #define CODE_STR_MAX_SIZE (50)
 typedef struct af_Code af_Code;
 
-typedef long CodeInt;  // Code uint
+typedef long CodeInt;  // Code int
+typedef long CodeUint;  // Code uint  TODO-szh 在code结构体使用该函数
 
 enum af_CodeType {
     code_element = 0,
@@ -28,6 +29,7 @@ AFUN_CORE_EXPORT void freeAllCode(af_Code *bt);
 
 /* 代码块 相关操作 */
 AFUN_CORE_EXPORT af_Code *pushCode(af_Code **base, af_Code *next);
+AFUN_CORE_EXPORT af_Code *copyAllCode(af_Code *base, FilePath *path);
 AFUN_CORE_EXPORT af_Code *copyCode(af_Code *base, FilePath *path);
 AFUN_CORE_EXPORT bool writeAllCode(af_Code *bt, FilePath path);
 AFUN_CORE_EXPORT bool readAllCode(af_Code **bt, FilePath path);

+ 83 - 24
src/core/code.c

@@ -14,7 +14,7 @@ static af_Code *makeCode(char prefix, FileLine line, FilePath path);
 static af_Code *freeCode(af_Code *bt);
 
 /* Code 相关操作 */
-static bool countElement(af_Code *element, CodeInt *elements, af_Code **next);
+static int countElement(af_Code *element, CodeInt *elements, af_Code **next);
 
 /* Code IO函数 */
 static bool readCode(af_Code **bt, FILE *file);
@@ -29,6 +29,8 @@ static bool checkElementData(char *data);
 static char *codeToStr_(af_Code *code, CodeInt *layer, struct af_BlockEnd **bn);
 static char *codeEndToStr(CodeInt code_end, CodeInt *layer, struct af_BlockEnd **bn);
 
+#define LAYER_ADD1(code) ((code)->type == code_block && (code)->block.elements != 0)
+
 static af_Code *makeCode(char prefix, FileLine line, FilePath path) {
     af_Code *bt = calloc(1, sizeof(af_Code));
     bt->line = line;
@@ -50,23 +52,33 @@ af_Code *makeElementCode(char *var, char prefix, FileLine line, FilePath path) {
 
 /*
  * 函数名: countElement
- * 目标: 统计元素个数(不包括元素的子元素)
+ * 目标: 统计元素个数(不包括元素的子元素
+ * 返回1 表示没有跳出过多层级
+ * 返回2 表示跳出了过多层级
+ * 返回0 表示错误
  */
-static bool countElement(af_Code *element, CodeInt *elements, af_Code **next) {
-    CodeInt layer = 0;
+static int countElement(af_Code *element, CodeInt *elements, af_Code **next) {
+    CodeInt layer = 0;  // layer 是相对于当前element的层级数, 可能为负数
+    af_Code *tmp = NULL;
+    if (next == NULL)
+        next = &tmp;
 
     for (*elements = 0; element != NULL; *next = element, element = element->next) {
         if (layer == 0)
             (*elements)++;
-        if (layer < 0)
-            return false;
 
         if (element->type == code_block)
             layer++;
-        if (element->code_end)
+        if (layer - element->code_end < 0)
+            return 2;
+        else
             layer = layer - element->code_end;
     }
-    return true;
+
+    if (layer == 0)
+        return 1;
+    else  // 大于0, 出现错误
+        return 0;
 }
 
 af_Code *makeBlockCode(enum af_BlockType type, af_Code *element, char prefix, FileLine line, FilePath path, af_Code **next) {
@@ -80,7 +92,7 @@ af_Code *makeBlockCode(enum af_BlockType type, af_Code *element, char prefix, Fi
     if (prefix != NUL && strchr(B_PREFIX, prefix) == NULL)
         prefix = NUL;
 
-    if (!countElement(element, &elements, next))
+    if (countElement(element, &elements, next) != 1)
         return NULL;
 
     bt = makeCode(prefix, line, path);
@@ -104,7 +116,7 @@ af_Code *pushCode(af_Code **base, af_Code *next) {
     return next;
 }
 
-af_Code *copyCode(af_Code *base, FilePath *path) {
+af_Code *copyAllCode(af_Code *base, FilePath *path) {
     af_Code *dest = NULL;
     af_Code **pdest = &dest;
 
@@ -133,6 +145,50 @@ af_Code *copyCode(af_Code *base, FilePath *path) {
     return dest;
 }
 
+/*
+ * 函数名: copyCode
+ * 目标: 拷贝 code, 并为末尾的code设置合适的code_end
+ */
+af_Code *copyCode(af_Code *base, FilePath *path) {
+    af_Code *dest = NULL;
+    af_Code **pdest = &dest;
+
+    CodeInt layer = 0;
+    for (NULL; base != NULL; base = base->next) {
+        *pdest = makeCode(base->prefix, base->line, base->path);
+        (*pdest)->type = base->type;
+        switch (base->type) {
+            case code_element:
+                (*pdest)->element.data = strCopy(base->element.data);
+                break;
+            case code_block:
+                (*pdest)->block.elements = base->block.elements;
+                (*pdest)->block.type = base->block.type;
+                break;
+            default:
+                break;
+        }
+
+        if (LAYER_ADD1(base))
+            layer++;
+
+        if ((layer - base->code_end) < 0) {  // base跳出layer, pdest不能按照base的code_end来, pdest只能刚好跳出layer
+            (*pdest)->code_end = layer;
+            break;
+        } else {  // 仍没跳出 layer
+            (*pdest)->code_end = base->code_end;
+            layer -= base->code_end;
+        }
+    }
+
+    if (dest != NULL && path != NULL) {
+        free(dest->path);
+        dest->path = pathCopy(path);
+    }
+
+    return dest;
+}
+
 static af_Code *freeCode(af_Code *bt) {
     af_Code *next = bt->next;
     free(bt->path);
@@ -154,14 +210,13 @@ void freeAllCode(af_Code *bt) {
 }
 
 af_Code *getCodeNext(af_Code *bt) {
-    if (bt->type == code_element || bt->block.elements == 0) {
+    if (!LAYER_ADD1(bt))
         return bt->next;
-    }
 
     CodeInt layer = 1;
     bt = bt->next;  // 跳过第一个code_block
     while (layer > 0) {
-        if (bt->type == code_block && bt->block.elements != 0)
+        if (LAYER_ADD1(bt))
             layer++;
         layer = layer - bt->code_end;
         bt = bt->next;
@@ -173,7 +228,7 @@ af_Code *getCodeNext(af_Code *bt) {
 }
 
 af_Code *getCodeElement(af_Code *bt) {
-    if (bt->type == code_element || bt->block.elements == 0)
+    if (!LAYER_ADD1(bt))
         return NULL;
     return bt->next;
 }
@@ -308,6 +363,9 @@ static bool checkElementData(char *data) {
 /*
  * 函数名: codeEndToStr
  * 目标: 转换element或开括号为字符串
+ * 若遇到开括号则设定bn, 并且设定layer
+ *
+ * bn中记录了开括号的顺序, 再打印闭括号时将按该顺序打印
  */
 static char *codeToStr_(af_Code *code, CodeInt *layer, struct af_BlockEnd **bn) {
     char *re = charToStr(code->prefix);
@@ -361,7 +419,7 @@ static char *codeToStr_(af_Code *code, CodeInt *layer, struct af_BlockEnd **bn)
 
 /*
  * 函数名: codeEndToStr
- * 目标: 转换收尾括号为字符串
+ * 目标: 转换括号为字符串
  */
 static char *codeEndToStr(CodeInt code_end, CodeInt *layer, struct af_BlockEnd **bn) {
     char *re = NEW_STR(code_end);
@@ -394,12 +452,9 @@ char *codeToStr(af_Code *code, int n) {
             break;
         }
 
-        char *get = codeToStr_(code, &layer, &bn);
-        re = strJoin(re, get, true, true);
-        if (code->code_end != 0) {
-            get = codeEndToStr(code->code_end, &layer, &bn);
-            re = strJoin(re, get, true, true);
-        }
+        re = strJoin(re, codeToStr_(code, &layer, &bn), true, true);
+        if (code->code_end != 0)
+            re = strJoin(re, codeEndToStr(code->code_end, &layer, &bn), true, true);
         if (n != -1 && layer == 0) /* 完成一个元素的打印 */
             n--;
     }
@@ -456,7 +511,11 @@ char *getCodeElementData(af_Code *code) {
 }
 
 CodeInt getCodeElementCount(af_Code *code) {
-    if (code->type != code_block)
-        return -1;
-    return code->block.elements;
+    if (!LAYER_ADD1(code))
+        return 0;
+
+    CodeInt count;
+    if (countElement(code->next, &count, NULL) == 0)
+        return 0;
+    return count;
 }

+ 2 - 6
src/core/env.c

@@ -770,23 +770,19 @@ bool pushFuncActivity(af_Code *bt, af_Environment *env) {
             }
             func = bt->next;
             break;
-        case brackets: {
-            af_Code *code = bt->next;
+        case brackets:
             func = NULL;
-            for (int i = 0; i < bt->block.elements; i++) {
+            for (af_Code *code = bt->next; code != NULL; code = getCodeNext(code)) {
                 if (isInfixFunc(code, env)) {
                     func = code;
                     break;
                 }
-                if ((code = getCodeNext(bt)) == NULL)
-                    break;
             }
             if (func == NULL) {
                 pushMessageDown(makeERRORMessage(CALL_ERROR, BRACKETS_FUNC_BODY_INFO, env), env);
                 return false;
             }
             break;
-        }
         case parentheses:
             func = NULL;  // 小括号则不在需要匹配
             break;