|
@@ -0,0 +1,145 @@
|
|
|
|
+/*
|
|
|
|
+ * 文件名: bytecode.c
|
|
|
|
+ * 目标: 管理ByteCode结构体的函数
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+#include "aFun.h"
|
|
|
|
+#include "bytecode.h"
|
|
|
|
+
|
|
|
|
+static af_ByteCode *makeByteCode(char prefix, FileLine line, FilePath path) {
|
|
|
|
+ af_ByteCode *bt = calloc(1, sizeof(af_ByteCode));
|
|
|
|
+ bt->line = line;
|
|
|
|
+ bt->prefix = prefix;
|
|
|
|
+ if (path != NULL)
|
|
|
|
+ bt->path = pathCopy(path);
|
|
|
|
+ return bt;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+af_ByteCode *makeLiteralByteCode(char *literal_data, char *func, char prefix, FileLine line, FilePath path) {
|
|
|
|
+ af_ByteCode *bt = makeByteCode(prefix, line, path);
|
|
|
|
+ bt->type = literal;
|
|
|
|
+ bt->literal.literal_data = strCopy(literal_data);
|
|
|
|
+ bt->literal.func = strCopy(func);
|
|
|
|
+ return bt;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+af_ByteCode *makeVariableByteCode(char *var, char prefix, FileLine line, FilePath path) {
|
|
|
|
+ af_ByteCode *bt = makeByteCode(prefix, line, path);
|
|
|
|
+ bt->type = variable;
|
|
|
|
+ bt->variable.name = strCopy(var);
|
|
|
|
+ return bt;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * 函数名: countElement
|
|
|
|
+ * 目标: 统计元素个数(不包括元素的子元素)
|
|
|
|
+ */
|
|
|
|
+static bool countElement(af_ByteCode *element, ByteCodeUint *count, af_ByteCode **next) {
|
|
|
|
+ ByteCodeUint to_next = 0; // 表示紧接着的元素都不纳入统计(指block的子元素)
|
|
|
|
+
|
|
|
|
+ for (*count = 0; element != NULL; *next = element, element = element->next) {
|
|
|
|
+ if (to_next == 0)
|
|
|
|
+ (*count)++;
|
|
|
|
+ else
|
|
|
|
+ to_next--;
|
|
|
|
+
|
|
|
|
+ if (element->type == block)
|
|
|
|
+ to_next += element->block.elements;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (to_next != 0)
|
|
|
|
+ return false;
|
|
|
|
+ return true;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+af_ByteCode *makeBlockByteCode(enum af_BlockType type, af_ByteCode *element, char prefix, FileLine line, FilePath path, af_ByteCode **next) {
|
|
|
|
+ af_ByteCode *bt = NULL;
|
|
|
|
+ ByteCodeUint count = 0;
|
|
|
|
+
|
|
|
|
+ if (!countElement(element, &count, next))
|
|
|
|
+ return NULL;
|
|
|
|
+
|
|
|
|
+ bt = makeByteCode(prefix, line, path);
|
|
|
|
+ bt->type = block;
|
|
|
|
+ bt->block.type = type;
|
|
|
|
+ bt->block.elements = count;
|
|
|
|
+ bt->next = element;
|
|
|
|
+ return bt;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+af_ByteCode *CopyByteCode(af_ByteCode *base, FilePath *path) {
|
|
|
|
+ af_ByteCode *dest = NULL;
|
|
|
|
+ af_ByteCode **pdest = &dest;
|
|
|
|
+
|
|
|
|
+ for (NULL; base != NULL; base = base->next) {
|
|
|
|
+ *pdest = makeByteCode(base->prefix, base->line, base->path);
|
|
|
|
+ (*pdest)->type = base->type;
|
|
|
|
+ switch (base->type) {
|
|
|
|
+ case literal:
|
|
|
|
+ (*pdest)->literal.literal_data = strCopy(base->literal.literal_data);
|
|
|
|
+ (*pdest)->literal.func = strCopy(base->literal.func);
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case variable:
|
|
|
|
+ (*pdest)->variable.name = strCopy(base->variable.name);
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case block:
|
|
|
|
+ (*pdest)->block.elements = base->block.elements;
|
|
|
|
+ (*pdest)->block.type = base->block.type;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ default:
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (dest != NULL && path != NULL) {
|
|
|
|
+ free(dest->path);
|
|
|
|
+ dest->path = pathCopy(path);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return dest;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+af_ByteCode *freeByteCode(af_ByteCode *bt) {
|
|
|
|
+ if (bt == NULL)
|
|
|
|
+ return NULL;
|
|
|
|
+
|
|
|
|
+ af_ByteCode *next = bt->next;
|
|
|
|
+ switch (bt->type) {
|
|
|
|
+ case literal:
|
|
|
|
+ free(bt->literal.literal_data);
|
|
|
|
+ free(bt->literal.func);
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case variable:
|
|
|
|
+ free(bt->variable.name);
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ default:
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return next;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+bool freeByteCodeWithElement(af_ByteCode *bt, af_ByteCode **next) {
|
|
|
|
+ ByteCodeUint count = 1; // 要释放的元素个数
|
|
|
|
+ for (NULL; count != 0; count--) {
|
|
|
|
+ if (bt == NULL)
|
|
|
|
+ return false;
|
|
|
|
+ if (bt->type == block)
|
|
|
|
+ count += bt->block.elements;
|
|
|
|
+ bt = freeByteCode(bt);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ *next = bt;
|
|
|
|
+ return true;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void freeAllByteCode(af_ByteCode *bt) {
|
|
|
|
+ while (bt != NULL)
|
|
|
|
+ bt = freeByteCode(bt);
|
|
|
|
+}
|