Procházet zdrojové kódy

feat: 支持exec函数

可以通过exec函数运行字符串形式的vm代码

link #9
SongZihuan před 4 roky
rodič
revize
570393adda

+ 2 - 2
VirtulMathCore/include/grammar.h

@@ -17,9 +17,9 @@ struct ParserMessage{
 
 typedef struct ParserMessage ParserMessage;
 
-ParserMessage *makeParserMessage(char *file_dir);
+ParserMessage *makeParserMessageFile(char *file_dir);
+ParserMessage *makeParserMessageStr(wchar_t *str);
 void freeParserMessage(ParserMessage *pm, bool self);
 void parserCommandList(ParserMessage *pm, Inter *inter, bool global, bool is_one, Statement *st);
-// PASERSSIGNATURE 位于__grammar
 
 #endif //VIRTUALMATH_GRAMMAR_H

+ 4 - 1
VirtulMathCore/include/lexical.h

@@ -4,7 +4,9 @@
 
 struct LexFile{
     FILE *file;
-    bool is_std;  // 是否位stdin
+    wchar_t *str;
+    int status;  // 0-stdin模式 1-文件模式 2-字符串模式
+    size_t seek;  // 字符串模式下需要使用
     struct LexFileBack{
         bool is_back;
         wint_t p;
@@ -49,6 +51,7 @@ void backChar(LexFile *file);
 void clearLexFile(LexFile *file);
 
 LexFile *makeLexFile(char *dir);
+LexFile *makeLexStr(wchar_t *str);
 void freeLexFile(LexFile *file);
 
 void setupMather(LexMather *mather);

+ 1 - 0
VirtulMathCore/include/run.h

@@ -20,6 +20,7 @@ ResultType globalIterStatement(Result *result, Inter *inter, Statement *st);
 bool operationSafeInterStatement(FUNC);
 bool ifBranchSafeInterStatement(FUNC);
 bool functionSafeInterStatement(FUNC);
+bool includeSafeInterStatement(FUNC);
 bool blockSafeInterStatement(FUNC);
 bool cycleBranchSafeInterStatement(FUNC);
 bool withBranchSafeInterStatement(FUNC);

+ 2 - 1
VirtulMathCore/include/token.h

@@ -158,7 +158,8 @@ typedef struct Token Token;
 typedef struct TokenStream TokenStream;
 typedef struct TokenMessage TokenMessage;
 
-TokenMessage *makeTokenMessage(char *file_dir);
+TokenMessage *makeTokenMessageFile(char *file_dir);
+TokenMessage *makeTokenMessageStr(wchar_t *str);
 void freeTokenMessage(TokenMessage *tm, bool self, bool free_st);
 
 Token *makeToken(long int line);

+ 2 - 2
VirtulMathCore/ofunc/src/list.c

@@ -64,7 +64,7 @@ ResultType list_slice(O_FUNC){
         if (ap[i + 1].value != NULL && ap[i + 1].value->value->type == V_num)
             *(list[i]) = ap[i + 1].value->value->data.num.num;
         else if (ap[i + 1].value != NULL && ap[i + 1].value->value->type != V_none) {
-            setResultError(E_TypeException, ONLY_ACC(first/second/stride, V_num or V_none), LINEFILE, true, CNEXT_NT);
+            setResultError(E_TypeException, ONLY_ACC(first/second/stride, num or null), LINEFILE, true, CNEXT_NT);
             return R_error;
         }
     }
@@ -231,7 +231,7 @@ ResultType list_down_assignment(O_FUNC){
         return R_error;
     }
     if (ap[2].value->value->type != V_num){
-        setResultError(E_TypeException, ONLY_ACC(list index, V_num), LINEFILE, true, CNEXT_NT);
+        setResultError(E_TypeException, ONLY_ACC(list index, num), LINEFILE, true, CNEXT_NT);
         return R_error;
     }
 

+ 85 - 0
VirtulMathCore/ofunc/src/sys.c

@@ -136,6 +136,90 @@ ResultType vm_quit(O_FUNC){
     return R_error;
 }
 
+ResultType vm_exec(O_FUNC){
+    ArgumentParser ap[] = {{.type=name_value, .name=L"cm", .must=1, .long_arg=false},
+                           {.type=name_value, .name=L"var", .must=0, .long_arg=false},
+                           {.type=name_value, .name=L"out", .must=0, .long_arg=false},
+                           {.must=-1}};
+    LinkValue *str;
+    LinkValue *var;
+    LinkValue *out;
+    bool out_;
+    Statement *new_st;
+    VarList *run;
+
+    setResultCore(result);
+    parserArgumentUnion(ap, arg, CNEXT_NT);
+    if (!CHECK_RESULT(result))
+        return result->type;
+    freeResult(result);
+
+    str = ap[0].value;
+    var = ap[1].value;
+    out = ap[2].value;
+    if (str->value->type != V_str) {
+        setResultError(E_TypeException, ONLY_ACC(cm, str), LINEFILE, true, CNEXT_NT);
+        return result->type;
+    }
+
+    if (var != NULL && var->value->type != V_dict) {
+        setResultError(E_TypeException, ONLY_ACC(var, dict), LINEFILE, true, CNEXT_NT);
+        return R_error;
+    }
+
+    if (out != NULL) {
+        if (out->value->type != V_bool) {
+            setResultError(E_TypeException, ONLY_ACC(out, bool), LINEFILE, true, CNEXT_NT);
+            return R_error;
+        } else if (var == NULL) {
+            setResultError(E_TypeException, L"missing parameters: var", LINEFILE, true, CNEXT_NT);
+            return R_error;
+        }
+        out_ = out->value->data.bool_.bool_;
+    } else
+        out = false;
+
+    {
+        ParserMessage *pm = makeParserMessageStr(str->value->data.str.str);
+        new_st = makeStatement(0, "exec");
+        parserCommandList(pm, inter, true, false, new_st);
+
+        if (pm->status == int_error) {
+            setResultError(E_KeyInterrupt, KEY_INTERRUPT, LINEFILE, true, CNEXT_NT);
+            return R_error;
+        }
+        else if (pm->status != success) {
+            wchar_t *wcs_message = memStrToWcs(pm->status_message, false);
+            setResultError(E_TypeException, wcs_message, LINEFILE, true, CNEXT_NT);
+            memFree(wcs_message);
+            return R_error;
+        }
+
+        freeParserMessage(pm, true);
+    }
+
+    if (var != NULL) {
+        run = makeVarList(inter, false);
+        run->hashtable = var->value->data.dict.dict;
+        if (out)
+            run->next = var_list;
+        else
+            gc_freeze(inter, var_list, run, true);
+    } else
+        run = var_list;
+
+    includeSafeInterStatement(CFUNC(new_st, run, result, belong));
+    freeStatement(new_st);
+
+    if (var != NULL) {
+        if (!out)
+            gc_freeze(inter, var_list, run, false);
+        freeVarList(run);
+    }
+
+    return result->type;
+}
+
 void registeredSysFunction(R_FUNC){
     NameFunc tmp[] = {{L"super", vm_super, free_},
                       {L"freemethod", vm_freemethod, free_},
@@ -151,6 +235,7 @@ void registeredSysFunction(R_FUNC){
                       {L"isnowrun", vm_isnowrun, free_},
                       {L"disnowrun", vm_disnowrun, free_},
                       {L"quit", vm_quit, free_},
+                      {L"exec", vm_exec, free_},
                       {NULL, NULL}};
     iterBaseNameFunc(tmp, belong, CFUNC_CORE(var_list));
 }

+ 17 - 3
VirtulMathCore/parser/grammar.c

@@ -1,14 +1,28 @@
 #include "__grammar.h"
 
-ParserMessage *makeParserMessage(char *file_dir) {
+static ParserMessage *makeParserMessageCore() {
     ParserMessage *tmp = memCalloc(1, sizeof(ParserMessage));
-    tmp->file = memStrcpy(file_dir == NULL ? "stdin" : file_dir);
-    tmp->tm = makeTokenMessage(file_dir);
+    tmp->file = NULL;
+    tmp->tm = NULL;
     tmp->status = success;
     tmp->status_message = NULL;
     return tmp;
 }
 
+ParserMessage *makeParserMessageFile(char *file_dir) {
+    ParserMessage *tmp = makeParserMessageCore();
+    tmp->file = memStrcpy(file_dir == NULL ? "stdin" : file_dir);
+    tmp->tm = makeTokenMessageFile(file_dir);
+    return tmp;
+}
+
+ParserMessage *makeParserMessageStr(wchar_t *str) {
+    ParserMessage *tmp = makeParserMessageCore();
+    tmp->file = memStrcpy("exec");
+    tmp->tm = makeTokenMessageStr(str);
+    return tmp;
+}
+
 void freeParserMessage(ParserMessage *pm, bool self) {
     FREE_BASE(pm, return_);
     freeTokenMessage(pm->tm, true, true);

+ 35 - 9
VirtulMathCore/parser/lexical.c

@@ -9,8 +9,16 @@
 wint_t readChar(LexFile *file){
     if (file->back.is_back)
         file->back.is_back = false;
-    else
-        file->back.p = fgetwc(file->file);
+    else {
+        if (file->status == 2) {
+            file->back.p = file->str[file->seek];
+            if (file->back.p != NUL)
+                file->seek ++;
+            else
+                file->back.p = WEOF;
+        } else
+            file->back.p = fgetwc(file->file);
+    }
     if (file->back.p == L'\n')
         file->line++;
     return file->back.p;
@@ -33,13 +41,12 @@ void clearLexFile(LexFile *file) {
         PASS;
 }
 
-LexFile *makeLexFile(char *dir){
+static LexFile *makeLexCore(){
     LexFile *tmp = memCalloc(1, sizeof(LexFile));
-    tmp->is_std = (bool)(dir == NULL);
-    if (tmp->is_std)
-        tmp->file = stdin;
-    else
-        tmp->file = fopen(dir, "r");
+    tmp->status = 1;
+    tmp->file = stdin;
+    tmp->str = NULL;
+    tmp->seek = 0;
     tmp->back.is_back = false;
     tmp->back.p = WEOF;
     tmp->line = 1;
@@ -47,10 +54,29 @@ LexFile *makeLexFile(char *dir){
     return tmp;
 }
 
+LexFile *makeLexFile(char *dir){
+    LexFile *tmp = makeLexCore();
+    tmp->status = dir == NULL ? 1 : 0;
+    if (dir != NULL) {
+        tmp->file = fopen(dir, "r");
+        tmp->status = 0;
+    }
+    return tmp;
+}
+
+LexFile *makeLexStr(wchar_t *str){
+    LexFile *tmp = makeLexCore();
+    tmp->status = 2;
+    tmp->file = NULL;
+    tmp->str = memWidecpy(str);
+    return tmp;
+}
+
 void freeLexFile(LexFile *file) {
     FREE_BASE(file, return_);
-    if (!file->is_std)
+    if (file->status == 0)
         fclose(file->file);
+    memFree(file->str);
     memFree(file);
     return_:
     return;

+ 14 - 2
VirtulMathCore/parser/token.c

@@ -57,14 +57,26 @@ void freeToekStream(TokenStream *ts, bool free_st) {
     return;
 }
 
-TokenMessage *makeTokenMessage(char *file_dir) {
+static TokenMessage *makeTokenMessageCore() {
     TokenMessage *tm = memCalloc(1, sizeof(TokenMessage));
-    tm->file = makeLexFile(file_dir);
+    tm->file = NULL;
     tm->mathers = makeMathers(MATHER_MAX);
     tm->ts = makeTokenStream();
     return tm;
 }
 
+TokenMessage *makeTokenMessageFile(char *file_dir) {
+    TokenMessage *tm = makeTokenMessageCore();
+    tm->file = makeLexFile(file_dir);
+    return tm;
+}
+
+TokenMessage *makeTokenMessageStr(wchar_t *str) {
+    TokenMessage *tm = makeTokenMessageCore();
+    tm->file = makeLexStr(str);
+    return tm;
+}
+
 void freeTokenMessage(TokenMessage *tm, bool self, bool free_st) {
     freeLexFile(tm->file);
     freeToekStream(tm->ts, free_st);

+ 1 - 1
VirtulMathCore/src/__run.c

@@ -74,7 +74,7 @@ wchar_t *setNumVarName(vnum num, struct Inter *inter) {
 wchar_t *getNameFromValue(Value *value, struct Inter *inter) {
     switch (value->type){
         case V_str:
-            return setStrVarName(value->data.str.str, true, inter);
+            return setStrVarName(value->data.str.str, false, inter);
         case V_num:
             return setNumVarName(value->data.num.num, inter);
         case V_bool:

+ 5 - 0
VirtulMathCore/src/run.c

@@ -333,6 +333,11 @@ bool functionSafeInterStatement(FUNC){
     return false;
 }
 
+bool includeSafeInterStatement(FUNC){
+    iterStatement(CNEXT);
+    return !CHECK_RESULT(result);
+}
+
 bool blockSafeInterStatement(FUNC){
     ResultType type;
     type = iterStatement(CNEXT);

+ 3 - 3
VirtulMathCore/src/runfile.c

@@ -139,12 +139,12 @@ ResultType includeFile(FUNC) {
         goto return_;
 
     new_st = makeStatement(0, file_dir);
-    pm = makeParserMessage(file_dir);
+    pm = makeParserMessageFile(file_dir);
 
     if (!importRunParser(pm, st->line, st->code_file, new_st, CNEXT_NT))
         goto return_;
 
-    functionSafeInterStatement(CFUNC(new_st, var_list, result, belong));
+    includeSafeInterStatement(CFUNC(new_st, var_list, result, belong));
     if (result->type == R_yield)
         setResult(result, inter);
     else if (!CHECK_RESULT(result))
@@ -162,7 +162,7 @@ ResultType importVMFileCore(Inter *import_inter, char *path, fline line, char *c
     Statement *run_st = NULL;
     setResultCore(result);
 
-    pm = makeParserMessage(path);
+    pm = makeParserMessageFile(path);
     run_st = makeStatement(0, path);
 
     if (!importRunParser(pm, line, code_file, run_st, CNEXT_NT))

+ 1 - 1
src/virtualmath.c

@@ -52,7 +52,7 @@ void runCodeStdin(Inter *inter, char *hello_string) {
 }
 
 bool runParser(char *code_file, Inter *inter, bool is_one, Statement **st) {
-    ParserMessage *pm = makeParserMessage(code_file);
+    ParserMessage *pm = makeParserMessageFile(code_file);
     *st = makeStatement(0, (code_file == NULL) ? "stdin" : code_file);
     parserCommandList(pm, inter, true, is_one, *st);