Explorar o código

feat & fix: file允许使用with分支

file设置了__enter__方法和__exit__方法
__enter__方法返回self
__exit__与close方法是等效的

添加了__del__函数关闭FILE
修复了gc机制运行__del__函数的时候无法释放result的问题

link #7
SongZihuan %!s(int64=4) %!d(string=hai) anos
pai
achega
f17e680173

+ 1 - 0
VirtulMathCore/CMakeLists.txt

@@ -19,6 +19,7 @@ AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/signalhandler HANDLER_LIST)
 AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/md5 MD5_LIST)
 
 ADD_LIBRARY(VirtualMathCore STATIC ${SRC_LIST} ${GC_LIST} ${PASER_LIST} ${MEM_LIST} ${FILE_LIST} ${ARGUMENT_LIST} ${OFUNC_LIST} ${HANDLER_LIST} ${CLIB_LIST} ${MD5_LIST})
+TARGET_LINK_LIBRARIES(VirtualMathCore ffi)
 IF (NOT (${CMAKE_SYSTEM_NAME} STREQUAL "Windows"))
     TARGET_LINK_LIBRARIES(VirtualMathCore dl)
 ELSE()

+ 2 - 2
VirtulMathCore/gc/gc.c

@@ -177,12 +177,12 @@ void gc_runDelAll(Inter *inter){
     Result result;
     setResultCore(&result);
     for (Value *value = inter->base; value != NULL; value = value->gc_next) {
-        freeResult(&result);
         gc_addTmpLink(&value->gc_status);
         if (needDel(value, inter)) {
             callDel(value, &result, inter, inter->var_list);
             if (!RUN_TYPE(result.type))
                 printError(&result, inter, true);
+            freeResult(&result);
         }
         gc_freeTmpLink(&value->gc_status);
     }
@@ -192,7 +192,6 @@ static void gc_runDel(Inter *inter, VarList *var_list){
     Result result;
     setResultCore(&result);
     for (Value *value = inter->base; value != NULL; value = value->gc_next) {
-        freeResult(&result);
         if (value->gc_status.c_value == run_del) {
             gc_addTmpLink(&value->gc_status);
             callDel(value, &result, inter, var_list);
@@ -200,6 +199,7 @@ static void gc_runDel(Inter *inter, VarList *var_list){
                 printError(&result, inter, true);
             gc_freeTmpLink(&value->gc_status);
             value->gc_status.c_value = need_free;
+            freeResult(&result);
         }
     }
 }

+ 2 - 1
VirtulMathCore/include/macro.h

@@ -15,6 +15,7 @@
 #include <wchar.h>
 #include <wctype.h>
 #include <locale.h>
+#include <ffi.h>
 
 #ifdef __linux__
 #include <dlfcn.h>
@@ -26,6 +27,6 @@
 #define bool int
 #define true 1
 #define false 0
-#define NUL 0
+#define NUL ((char)0)
 
 #endif //VIRTUALMATH_MACRO_H

+ 26 - 5
VirtulMathCore/ofunc/src/file_.c

@@ -163,15 +163,13 @@ ResultType file_close(O_FUNC){
     }
     freeResult(result);
 
-    if ((file = ap[0].value)->value->type != V_file || file->value->data.file.file == NULL) {
+    if ((file = ap[0].value)->value->type != V_file) {
         setResultError(E_TypeException, INSTANCE_ERROR(file), LINEFILE, true, CNEXT_NT);
         return R_error;
     }
 
-    if (file->value->data.file.is_std) {
-        setResultError(E_TypeException, L"stream cannot be closed", LINEFILE, true, CNEXT_NT);
-        return R_error;
-    }
+    if (file->value->data.file.file == NULL || file->value->data.file.is_std)
+        goto return_;
 
     fclose(file->value->data.file.file);
     file->value->data.file.file = NULL;
@@ -179,15 +177,38 @@ ResultType file_close(O_FUNC){
     memFree(file->value->data.file.mode);
     file->value->data.file.is_std = true;
 
+    return_:
     setResult(result, inter);
     return result->type;
 }
 
+ResultType file_enter(O_FUNC){
+    ArgumentParser ap[] = {{.type=only_value, .must=1, .long_arg=false},
+                           {.must=-1}};
+    setResultCore(result);
+    parserArgumentUnion(ap, arg, CNEXT_NT);
+    if (!CHECK_RESULT(result)) {
+        return result->type;
+    }
+    freeResult(result);
+
+    if (ap[0].value->value->type != V_file || ap[0].value->value->data.file.file == NULL) {
+        setResultError(E_TypeException, INSTANCE_ERROR(file), LINEFILE, true, CNEXT_NT);
+        return R_error;
+    }
+
+    setResultOperation(result, ap[0].value);
+    return result->type;
+}
+
 void registeredFile(R_FUNC){
     LinkValue *object = inter->data.file;
     NameFunc tmp[] = {{L"read", file_read, object_free_},
                       {L"write", file_write, object_free_},
                       {L"close", file_close, object_free_},
+                      {inter->data.object_enter, file_enter, object_free_},
+                      {inter->data.object_del, file_close, object_free_},
+                      {inter->data.object_exit, file_close, object_free_},
                       {inter->data.object_new, file_new, class_free_},
                       {inter->data.object_init, file_init, object_free_},
                       {NULL, NULL}};

+ 10 - 5
VirtulMathCore/src/runbranch.c

@@ -771,18 +771,23 @@ ResultType withBranch(FUNC) {
                 freeResult(&exit_tmp);
 
             if (!yield_run) {
-                gc_freeTmpLink(&value->gc_status);
                 gc_freeTmpLink(&_enter_->gc_status);
                 gc_freeTmpLink(&_exit_->gc_status);
-                value = NULL;
                 _enter_ = NULL;
                 _exit_ = NULL;
             }
         }
 
-        if (with_belong != NULL && !yield_run) {
-            gc_freeTmpLink(&with_belong->gc_status);
-            with_belong = NULL;
+        if (!yield_run) {
+            if (with_belong != NULL){
+                gc_freeTmpLink(&with_belong->gc_status);
+                with_belong = NULL;
+            }
+
+            if (value != NULL){
+                gc_freeTmpLink(&value->gc_status);
+                value = NULL;
+            }
         }
     }
 

+ 1 - 2
VirtulMathCore/src/value.c

@@ -207,8 +207,7 @@ void freeValue(Value **value) {
         case V_file:
             memFree(free_value->data.file.mode);
             memFree(free_value->data.file.path);
-            if (!free_value->data.file.is_std)
-                fclose(free_value->data.file.file);
+            // file在__del__中释放
             break;
         case V_func: {
             freeParameter(free_value->data.function.pt, true);