浏览代码

feat: 添加了ByteCode文件的输出和输入函数

添加了相关函数
添加了测试程序
SongZihuan 3 年之前
父节点
当前提交
41a88a524a
共有 8 个文件被更改,包括 250 次插入13 次删除
  1. 3 1
      include/aFun.h
  2. 24 0
      include/bytecode.h
  3. 1 1
      include/macro.h
  4. 1 5
      src/core/__bytecode.h
  5. 152 3
      src/core/bytecode.c
  6. 1 1
      src/tool/byte.c
  7. 17 2
      test/CMakeLists.txt
  8. 51 0
      test/test_byte_code.c

+ 3 - 1
include/aFun.h

@@ -4,7 +4,9 @@
 #include "macro.h"
 #include "tool.h"
 
-typedef struct af_ByteCode af_ByteCode;
+#include "bytecode.h"
 
+// Init系列函数
 void aFunInit(void);
+
 #endif //AFUN__H

+ 24 - 0
include/bytecode.h

@@ -0,0 +1,24 @@
+#ifndef AFUN_BYTECODE_H
+#define AFUN_BYTECODE_H
+// 相关结构体的定义
+typedef struct af_ByteCode af_ByteCode;
+
+enum af_BlockType {
+    parentheses = 0,  // 小括号
+    brackets,  // 中括号
+    curly,  // 大括号
+};
+
+af_ByteCode *makeLiteralByteCode(char *literal_data, char *func, char prefix, FileLine line, FilePath path);
+af_ByteCode *makeVariableByteCode(char *var, char prefix, FileLine line, FilePath path);
+af_ByteCode *makeBlockByteCode(enum af_BlockType type, af_ByteCode *element, char prefix, FileLine line, FilePath path, af_ByteCode **next);
+af_ByteCode *connectByteCode(af_ByteCode **base, af_ByteCode *next);
+af_ByteCode *CopyByteCode(af_ByteCode *base, FilePath *path);
+af_ByteCode *freeByteCode(af_ByteCode *bt);
+bool freeByteCodeWithElement(af_ByteCode *bt, af_ByteCode **next);
+void freeAllByteCode(af_ByteCode *bt);
+bool writeAllByteCode(af_ByteCode *bt, FILE *file);
+bool readAllByteCode(af_ByteCode **bt, FILE *file);
+void printByteCode(af_ByteCode *bt);
+
+#endif //AFUN_BYTECODE_H

+ 1 - 1
include/macro.h

@@ -18,7 +18,7 @@
 #define NUL ((char)0)
 #define W_NUL ((wchar_t)0)
 
-typedef int32_t FileLine;  // 文件行号
+typedef uint32_t FileLine;  // 文件行号
 typedef char *FilePath;  // 文件路径
 
 typedef unsigned int ByteCodeUint;  // ByteCode int

+ 1 - 5
src/core/bytecode.h → src/core/__bytecode.h

@@ -6,6 +6,7 @@
 #ifndef BYTECODE__H
 #define BYTECODE__H
 #include "macro.h"
+#include "bytecode.h"
 
 enum af_ByteCodeType {
     literal = 0,
@@ -13,11 +14,6 @@ enum af_ByteCodeType {
     block,  // 括号
 };
 
-enum af_BlockType {
-    parentheses = 0,  // 小括号
-    brackets,  // 中括号
-    curly,  // 大括号
-};
 
 struct af_ByteCode {  // 一个 ByteCode 的结构体
     enum af_ByteCodeType type;

+ 152 - 3
src/core/bytecode.c

@@ -3,8 +3,10 @@
  * 目标: 管理ByteCode结构体的函数
  */
 
+#include <stdio.h>
 #include "aFun.h"
-#include "bytecode.h"
+#include "__bytecode.h"
+#include "tool.h"
 
 static af_ByteCode *makeByteCode(char prefix, FileLine line, FilePath path) {
     af_ByteCode *bt = calloc(1, sizeof(af_ByteCode));
@@ -55,8 +57,12 @@ static bool countElement(af_ByteCode *element, ByteCodeUint *count, af_ByteCode
 
 af_ByteCode *makeBlockByteCode(enum af_BlockType type, af_ByteCode *element, char prefix, FileLine line, FilePath path, af_ByteCode **next) {
     af_ByteCode *bt = NULL;
+    af_ByteCode *tmp = NULL;
     ByteCodeUint count = 0;
 
+    if (next == NULL)
+        next = &tmp;
+
     if (!countElement(element, &count, next))
         return NULL;
 
@@ -68,6 +74,17 @@ af_ByteCode *makeBlockByteCode(enum af_BlockType type, af_ByteCode *element, cha
     return bt;
 }
 
+af_ByteCode *connectByteCode(af_ByteCode **base, af_ByteCode *next) {
+    while ((*base) != NULL)
+        base = &((*base)->next);
+    *base = next;
+
+    while (next != NULL && next->next != NULL)
+        next = next->next;
+
+    return next;
+}
+
 af_ByteCode *CopyByteCode(af_ByteCode *base, FilePath *path) {
     af_ByteCode *dest = NULL;
     af_ByteCode **pdest = &dest;
@@ -108,20 +125,20 @@ af_ByteCode *freeByteCode(af_ByteCode *bt) {
         return NULL;
 
     af_ByteCode *next = bt->next;
+    free(bt->path);
     switch (bt->type) {
         case literal:
             free(bt->literal.literal_data);
             free(bt->literal.func);
             break;
-
         case variable:
             free(bt->variable.name);
             break;
-
         default:
             break;
     }
 
+    free(bt);
     return next;
 }
 
@@ -143,3 +160,135 @@ void freeAllByteCode(af_ByteCode *bt) {
     while (bt != NULL)
         bt = freeByteCode(bt);
 }
+
+#define Done(write) do{if(!(write)){return false;}}while(0)
+
+static bool writeByteCode(af_ByteCode *bt, FILE *file) {
+    Done(byteWriteUint_8(file, bt->type));
+    Done(byteWriteUint_8(file, bt->prefix));
+    Done(byteWriteUint_32(file, bt->line));
+
+    if (bt->path != NULL) {
+        Done(byteWriteUint_8(file, true));  // 表示有path
+        Done(byteWriteStr(file, bt->path));
+    } else {
+        Done(byteWriteUint_8(file, false));  // 表示无path
+    }
+
+    switch (bt->type) {
+        case literal:
+            Done(byteWriteStr(file, bt->literal.literal_data));
+            Done(byteWriteStr(file, bt->literal.func));
+            break;
+        case variable:
+            Done(byteWriteStr(file, bt->variable.name));
+            break;
+        case block:
+            Done(byteWriteUint_8(file, bt->block.type));
+            Done(byteWriteUint_32(file, bt->block.elements));
+            break;
+        default:
+            break;
+    }
+    return true;
+}
+
+/*
+ * 函数名: writeAllByteCode
+ * 目标: 将ByteCode写入字节码文件中
+ * 备注: 写入字节码时不做语义检查, 在读取时最语义检查即可
+ */
+bool writeAllByteCode(af_ByteCode *bt, FILE *file) {
+    uint32_t count = 0;
+
+    if (bt == NULL || bt->path == NULL)
+        return false;
+
+    for (af_ByteCode *tmp = bt; tmp != NULL; tmp = tmp->next)  // 统计个数
+        count++;
+
+    Done(byteWriteUint_32(file,count));
+    for (NULL; bt != NULL; bt = bt->next) {
+        if (!writeByteCode(bt, file))
+            return false;
+    }
+
+    return true;
+}
+
+static bool readByteCode(af_ByteCode **bt, FILE *file) {
+    uint8_t type;
+    uint8_t prefix;
+    uint32_t line;
+    uint8_t have_path;
+    char *path = NULL;
+
+    Done(byteReadUint_8(file, &type));
+    Done(byteReadUint_8(file, &prefix));
+    Done(byteReadUint_32(file,&line));
+    Done(byteReadUint_8(file, &(have_path)));
+
+    if (have_path)
+        Done(byteReadStr(file, &path));
+
+    *bt = makeByteCode((char)prefix, line, path);
+    free(path);
+    (*bt)->type = type;
+
+    switch (type) {
+        case literal:
+            Done(byteReadStr(file, &((*bt)->literal.literal_data)));
+            Done(byteReadStr(file, &((*bt)->literal.func)));
+            break;
+        case variable:
+            Done(byteReadStr(file, &((*bt)->variable.name)));
+            break;
+        case block: {
+            uint8_t block_type;
+            uint32_t elements;
+            Done(byteReadUint_8(file, &block_type));
+            Done(byteReadUint_32(file,&elements));
+            (*bt)->block.type = block_type;
+            (*bt)->block.elements = elements;
+            break;
+        }
+        default:
+            break;
+    }
+    return true;
+}
+
+/*
+ * 函数名: writeAllByteCode
+ * 目标: 将ByteCode写入字节码文件中
+ * 备注: 写入字节码时不做语义检查, 在读取时最语义检查即可 【语义检查还未实现】
+ */
+bool readAllByteCode(af_ByteCode **bt, FILE *file) {
+    uint32_t count;
+    Done(byteReadUint_32(file,&count));
+
+    for (NULL; count != 0; count--, bt = &((*bt)->next)) {
+        if(!readByteCode(bt, file))
+            return false;
+    }
+    return true;
+}
+
+void printByteCode(af_ByteCode *bt) {
+    for (NULL; bt != NULL; bt = bt->next) {
+        switch (bt->type) {
+            case literal:
+                printf("literal: %s %s prefix: %d\n", bt->literal.literal_data, bt->literal.func, bt->prefix);
+                break;
+            case variable:
+                printf("variable: %s prefix: %d\n", bt->variable.name, bt->prefix);
+                break;
+            case block:
+                printf("variable: %d %d prefix: %d\n", bt->block.elements, bt->block.type, bt->prefix);
+                break;
+            default:
+                printf("Unknow: %d prefix: %d\n", bt->type, bt->prefix);
+                break;
+        }
+    }
+}

+ 1 - 1
src/tool/byte.c

@@ -4,7 +4,7 @@
 #include "tool.h"
 
 enum af_EndianType endian = little_endian;
-enum af_EndianType save_as = big_endian;  // 以小端序存储
+enum af_EndianType save_as = little_endian;  // 默认以小端序存储
 
 void getEndian() {
     union {

+ 17 - 2
test/CMakeLists.txt

@@ -5,7 +5,7 @@ SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
 
 FUNCTION(ADD_aFunTest TEST_NAME TEST_SOURCE)
     ADD_EXECUTABLE(aFunTest_${TEST_NAME} ${TEST_SOURCE})
-    TARGET_LINK_LIBRARIES(aFunTest_${TEST_NAME} af_tool af_json)
+    TARGET_LINK_LIBRARIES(aFunTest_${TEST_NAME} af_tool af_json af_core)
     ADD_TEST(NAME aFunTest_${TEST_NAME} COMMAND $<TARGET_FILE:aFunTest_${TEST_NAME}>)
 ENDFUNCTION()
 
@@ -26,8 +26,23 @@ ADD_aFunTest(mem test_mem.c)
 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)
 
 SET_LINK(lib lib_Test1)  # 链接测试程序需要的动态库
 
 SET_PASS(lib "num = 100 test = 110")
-SET_PASS(dlc "a = 100, test = 110")
+SET_PASS(dlc "a = 100, test = 110")
+SET_PASS(byte_code
+"out:
+literal: data func prefix: 44
+variable: var1 prefix: 0
+variable: 2 0 prefix: 0
+literal: data2 func prefix: 0
+variable: var2 prefix: 0
+in:
+literal: data func prefix: 44
+variable: var1 prefix: 0
+variable: 2 0 prefix: 0
+literal: data2 func prefix: 0
+variable: var2 prefix: 0"
+        )

+ 51 - 0
test/test_byte_code.c

@@ -0,0 +1,51 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include "aFun.h"
+
+int main() {
+    af_ByteCode *bt1 = makeLiteralByteCode("data", "func", ',', 0, "Unknow");
+    af_ByteCode *bt2 = makeVariableByteCode("var1", 0, 1, NULL);
+
+    af_ByteCode *bt3 = makeLiteralByteCode("data2", "func", 0, 0, NULL);
+    af_ByteCode *bt4 = makeVariableByteCode("var2", 0, 1, NULL);
+
+    connectByteCode(&bt1, bt2);
+    connectByteCode(&bt3, bt4);
+
+    af_ByteCode *bt5 = makeBlockByteCode(parentheses, bt3, 0, 1, NULL, NULL);
+    connectByteCode(&bt2, bt5);
+
+    FILE *file = fopen("test.afb", "wb");
+    if (file == NULL) {
+        fprintf(stderr, "Can't not creat file: test.afb\n");
+        return EXIT_FAILURE;
+    }
+
+    if(!writeAllByteCode(bt1, file)) {
+        fprintf(stderr, "Write test.afb error.\n");
+        return EXIT_FAILURE;
+    }
+    fclose(file);
+
+    af_ByteCode *get;
+    file = fopen("test.afb", "rb");
+    if (file == NULL) {
+        fprintf(stderr, "Can't not read file: test.afb\n");
+        return EXIT_FAILURE;
+    }
+
+    if(!readAllByteCode(&get, file)) {
+        fprintf(stderr, "Read test.afb error.\n");
+        return EXIT_FAILURE;
+    }
+    fclose(file);
+
+    printf("out:\n");
+    printByteCode(bt1);
+    printf("in:\n");
+    printByteCode(get);
+    freeAllByteCode(bt1);
+    freeAllByteCode(get);
+    return EXIT_SUCCESS;
+}
+