瀏覽代碼

feat: 支持运行字节码文件

SongZihuan 3 年之前
父節點
當前提交
77075299e0
共有 7 個文件被更改,包括 124 次插入17 次删除
  1. 3 1
      include/runtime/aFunlang.h
  2. 3 0
      include/tool/file.h
  3. 2 2
      src/core/code.c
  4. 2 2
      src/main_run.c
  5. 76 4
      src/runtime/aFunlang.c
  6. 33 8
      src/tool/file.c
  7. 5 0
      test/af/test1.af

+ 3 - 1
include/runtime/aFunlang.h

@@ -12,8 +12,10 @@ AFUN_LANG_EXPORT void destructAFunEnvironment(af_Environment *env);
 
 /* 源文件运行 */
 AFUN_LANG_EXPORT int runCodeFromString(char *code, char *string_name, FILE *error_file, af_Environment *env);
-AFUN_LANG_EXPORT int runCodeFromFile(FilePath file, FILE *error_file, af_Environment *env);
+AFUN_LANG_EXPORT int runCodeFromFileSource(FilePath file, FILE *error_file, af_Environment *env);
 AFUN_LANG_EXPORT int runCodeFromStdin(char *name, FILE *error_file, af_Environment *env);
 AFUN_LANG_EXPORT int runCodeFromMemory(af_Code *code, af_Environment *env);
 AFUN_LANG_EXPORT int runCodeFromMemoryAsImport(af_Code *code, af_Environment *env);
+AFUN_LANG_EXPORT int runCodeFromFileByte(FilePath file, FILE *error_file, af_Environment *env);
+AFUN_LANG_EXPORT int runCodeFromFile(FilePath file, FILE *error_file, af_Environment *env);
 #endif //AFUN_AFUNLANG_H

+ 3 - 0
include/tool/file.h

@@ -4,7 +4,10 @@
 
 /* 文件处理工具 */
 AFUN_TOOL_EXPORT int checkFile(char *path);
+AFUN_TOOL_EXPORT time_t getFileMTime(char *path);
 AFUN_TOOL_EXPORT char *getFileName(char *path_1);
+AFUN_TOOL_EXPORT char *getFileNameWithPath(char *path_1);
+AFUN_TOOL_EXPORT char *getFileSurfix(char *path);
 AFUN_TOOL_EXPORT char *fileNameToVar(char *name, bool need_free);
 AFUN_TOOL_EXPORT char *findPath(char *path, char *env, bool need_free);
 

+ 2 - 2
src/core/code.c

@@ -248,7 +248,7 @@ static bool readCode(af_Code **bt, FILE *file) {
     *bt = makeCode((char)prefix, line, path);
     free(path);
     (*bt)->type = type;
-    (*bt)->code_end = code_end;
+    (*bt)->code_end = (CodeInt)code_end;
 
     switch (type) {
         case code_element:
@@ -260,7 +260,7 @@ static bool readCode(af_Code **bt, FILE *file) {
             Done(byteReadUint_8(file, &block_type));
             Done(byteReadUint_32(file,&elements));
             (*bt)->block.type = block_type;
-            (*bt)->block.elements = elements;
+            (*bt)->block.elements = (CodeInt)elements;
             break;
         }
         default:

+ 2 - 2
src/main_run.c

@@ -69,10 +69,10 @@ int runCodeFromRunList(RunList *run_list, RunList **bak, af_Environment *env) {
                 exit_code = runCodeFromFile(run_list->file, stderr, env);
                 break;
             case rl_file_b:
-                printf("run code byte.\n");
+                exit_code = runCodeFromFileByte(run_list->file, stderr, env);
                 break;
             case rl_file_s:
-                exit_code = runCodeFromFile(run_list->file, stderr, env);
+                exit_code = runCodeFromFileSource(run_list->file, stderr, env);
                 break;
             default:
                 break;

+ 76 - 4
src/runtime/aFunlang.c

@@ -32,6 +32,9 @@ void destructAFunEnvironment(af_Environment *env) {
 }
 
 static int runCode_(FilePath name, af_Parser *parser, int mode, af_Environment *env) {
+    if (parser == NULL)
+        return -1;
+
     af_Code *bt_code = parserCode(name, parser);
     freeParser(parser);
     if (bt_code == NULL)
@@ -63,13 +66,17 @@ int runCodeFromString(char *code, char *string_name, FILE *error_file, af_Enviro
 }
 
 /*
- * 函数名: runCodeFromString
+ * 函数名: runCodeFromFileSource
  * 目标: 运行文件中的程序 (源码形式)
  */
-int runCodeFromFile(FilePath file, FILE *error_file, af_Environment *env) {
+int runCodeFromFileSource(FilePath file, FILE *error_file, af_Environment *env) {
     if (env == NULL || file == NULL)
         return -1;
 
+    char *sufix = getFileSurfix(file);
+    if (sufix == NULL || !EQ_STR(".af", sufix))
+        return -2;
+
     if (error_file == NULL)
         error_file = stderr;
     af_Parser *parser = makeParserByFile(file, error_file);
@@ -77,7 +84,7 @@ int runCodeFromFile(FilePath file, FILE *error_file, af_Environment *env) {
 }
 
 /*
- * 函数名: runCodeFromString
+ * 函数名: runCodeFromStdin
  * 目标: 运行stdin的程序 (源码形式)
  */
 int runCodeFromStdin(char *name, FILE *error_file, af_Environment *env) {
@@ -94,7 +101,7 @@ int runCodeFromStdin(char *name, FILE *error_file, af_Environment *env) {
 }
 
 /*
- * 函数名: runCodeFromString
+ * 函数名: runCodeFromMemory
  * 目标: 运行内存中的程序 (字节码形式)
  */
 int runCodeFromMemory(af_Code *code, af_Environment *env) {
@@ -114,3 +121,68 @@ int runCodeFromMemoryAsImport(af_Code *code, af_Environment *env) {
         return env->core->exit_code;
     return 0;
 }
+
+/*
+ * 函数名: runCodeFromFileByte
+ * 目标: 运行文件中的程序 (字节码形式)
+ */
+int runCodeFromFileByte(FilePath file, FILE *error_file, af_Environment *env) {
+    if (env == NULL || file == NULL)
+        return -1;
+
+    char *sufix = getFileSurfix(file);
+    if (sufix == NULL || !EQ_STR(".afb", sufix))
+        return -2;
+
+    if (error_file == NULL)
+        error_file = stderr;
+    af_Code *code;
+    FILE *file_ = fopen(file, "rb");
+    if (file_ == NULL) {
+        return -3;
+    }
+
+    if(!readAllCode(&code, file_)) {
+        freeAllCode(code);
+        return -2;
+    }
+
+    int exit_code = runCodeFromMemoryAsImport(code, env);
+    freeAllCode(code);
+
+    return exit_code;
+}
+
+/*
+ * 函数名: runCodeFromFileByte
+ * 目标: 运行文件中的程序 (字节码/源码形式)
+ * 注意: 必须传入.af文件
+ */
+int runCodeFromFile(FilePath file, FILE *error_file, af_Environment *env) {
+    if (env == NULL || file == NULL)
+        return -1;
+
+    char *sufix = getFileSurfix(file);
+    if (sufix == NULL || !EQ_STR(".af", sufix))
+        return -2;
+
+    char *path = getFileNameWithPath(file);
+    char *path_1 = strJoin(path, ".af", false, false);
+    char *path_2 = strJoin(path, ".afb", true, false);  // 此时释放path
+
+    time_t time_1 = getFileMTime(path_1);
+    time_t time_2 = getFileMTime(path_2);
+
+    if (time_1 == 0 && time_2 == 0)
+        return -3;
+
+    int exit_code;
+    if (time_2 >= time_1)
+        exit_code = runCodeFromFileByte(path_2, error_file, env);
+    else
+        exit_code = runCodeFromFileSource(path_1, error_file, env);
+
+    free(path_1);
+    free(path_2);
+    return exit_code;
+}

+ 33 - 8
src/tool/file.c

@@ -33,6 +33,13 @@ int checkFile(char *path){
         return 0;
 }
 
+time_t getFileMTime(char *path) {
+    struct stat my_stat;
+    if (path == NULL || stat(path, &my_stat) != 0)
+        return 0;
+    return my_stat.st_mtime;
+}
+
 /*
  * 函数: getFileName
  * 目标: 给定路径获取该路径所指定的文件名
@@ -40,7 +47,6 @@ int checkFile(char *path){
 char *getFileName(char *path_1){
     char *slash = NULL;  // 名字开始的字符的指针
     char *point = NULL;  // 后缀名.所在的字符的指针
-    char *name = NULL;  // 返回值
     char *path = strCopy(path_1);  // 复制数组, 避免path_1是常量字符串导致无法修改其值
 
     if (path[STR_LEN(path) - 1] == SEP_CH)  // 若路径的最后一个字符为SEP, 则忽略此SEP
@@ -54,15 +60,34 @@ char *getFileName(char *path_1){
     if ((point = strchr(path, '.')) != NULL)
         *point = NUL;
 
-    name = strCopy(slash);
+    char *res = strCopy(slash);
     free(path);
+    return res;
+}
 
-    if (!isalpha(*name) && *name != '_')
-        name = strJoin("_", name, false, true);
-    for (char *tmp = name; *tmp != 0; tmp++)
-        if (!isalnum(*tmp) &&'_' != *tmp)
-            *tmp = '_';
-    return name;
+/*
+ * 函数名: getFileNameWithPath
+ * 目标: 取出指定路径的文件后缀
+ */
+char *getFileNameWithPath(char *path_1){
+    char *point = NULL;  // 后缀名.所在的字符的指针
+    char *path = strCopy(path_1);  // 复制数组, 避免path_1是常量字符串导致无法修改其值
+    char *res;
+
+    if ((point = strchr(path, '.')) != NULL)
+        *point = NUL;
+
+    res = strCopy(path);
+    free(path);
+    return res;
+}
+
+/*
+ * 函数名: getFileSurfix
+ * 目标: 获取文件后缀 (不会生成新字符串)
+ */
+char *getFileSurfix(char *path) {
+    return strchr(path, '.');
 }
 
 /*

+ 5 - 0
test/af/test1.af

@@ -0,0 +1,5 @@
+global
+{str}
+str()
+"Hello"
+str