Jelajahi Sumber

feat: 加入yield关键词

允许使用yield设置生成器
yield可以在函数块、分支语句和内嵌block内允许
SongZihuan 4 tahun lalu
induk
melakukan
68e100dcfb
12 mengubah file dengan 541 tambahan dan 110 penghapusan
  1. 16 0
      include/run.h
  2. 27 0
      include/statement.h
  3. 1 0
      include/token.h
  4. 7 5
      include/value.h
  5. 4 0
      parser/grammar.c
  6. 4 6
      src/inter.c
  7. 23 11
      src/run.c
  8. 323 67
      src/runbranch.c
  9. 69 11
      src/runcall.c
  10. 26 9
      src/runoperation.c
  11. 40 1
      src/statement.c
  12. 1 0
      src/value.c

+ 16 - 0
include/run.h

@@ -2,11 +2,13 @@
 #define VIRTUALMATH_RUN_H
 #include "__macro.h"
 
+enum StatementInfoStatus;
 typedef struct Result Result;
 typedef enum ResultType ResultType;
 typedef struct LinkValue LinkValue;
 typedef struct Value Value;
 typedef struct Statement Statement;
+typedef struct StatementList StatementList;
 typedef struct Inter Inter;
 typedef struct VarList VarList;
 typedef struct Parameter Parameter;
@@ -17,6 +19,7 @@ ResultType globalIterStatement(Result *result, LinkValue *base_father, Inter *in
 bool operationSafeInterStatement(INTER_FUNCTIONSIG);
 bool ifBranchSafeInterStatement(INTER_FUNCTIONSIG);
 bool functionSafeInterStatement(INTER_FUNCTIONSIG);
+bool blockSafeInterStatement(INTER_FUNCTIONSIG);
 bool cycleBranchSafeInterStatement(INTER_FUNCTIONSIG);
 bool tryBranchSafeInterStatement(INTER_FUNCTIONSIG);
 Statement *checkLabel(Statement *base, char *label);
@@ -45,6 +48,7 @@ ResultType continueCycle(INTER_FUNCTIONSIG);
 ResultType regoIf(INTER_FUNCTIONSIG);
 ResultType restartCode(INTER_FUNCTIONSIG);
 ResultType returnCode(INTER_FUNCTIONSIG);
+ResultType yieldCode(INTER_FUNCTIONSIG);
 ResultType raiseCode(INTER_FUNCTIONSIG);
 ResultType assertCode(INTER_FUNCTIONSIG);
 ResultType gotoLabel(INTER_FUNCTIONSIG);
@@ -64,4 +68,16 @@ ResultType getBaseVarInfo(char **name, int *times, INTER_FUNCTIONSIG);
 ResultType getBaseSVarInfo(char **name, int *times, INTER_FUNCTIONSIG);
 ResultType getVarInfo(char **name, int *times, INTER_FUNCTIONSIG);
 
+Statement *getRunInfoStatement(Statement *funtion_st);
+bool popStatementVarList(Statement *funtion_st, VarList **function_var, VarList *out_var, Inter *inter);
+
+void newFunctionYield(Statement *funtion_st, Statement *node, VarList *new_var, Inter *inter);
+void updateFunctionYield(Statement *function_st, Statement *node);
+void freeFunctionYield(Statement *function_st, Inter *inter);
+
+void updateBranchYield(Statement *branch_st, Statement *node, StatementList *sl_node, enum StatementInfoStatus status);
+void newWithBranchYield(Statement *branch_st, Statement *node, StatementList *sl_node, VarList *new_var, enum StatementInfoStatus status,
+                        Inter *inter, LinkValue *value, LinkValue *_exit_, LinkValue *_enter_);
+void updateBranchYield(Statement *branch_st, Statement *node, StatementList *sl_node, enum StatementInfoStatus status);
+
 #endif //VIRTUALMATH_RUN_H

+ 27 - 0
include/statement.h

@@ -28,6 +28,7 @@ struct Statement{
         rego_if,
         restart,
         return_code,
+        yield_code,
         raise_code,
         include_file,
         import_file,
@@ -148,6 +149,9 @@ struct Statement{
         struct {
             struct Statement *value;
         } return_code;
+        struct {
+            struct Statement *value;
+        } yield_code;
         struct {
             struct Statement *value;
         } raise_code;
@@ -185,6 +189,26 @@ struct Statement{
             struct Statement *label;
         } goto_;
     }u;
+    struct {  // 运行info信息
+        bool have_info;
+        struct VarList *var_list;
+        struct Statement *node;
+        struct {
+            struct StatementList *sl_node;
+            enum StatementInfoStatus{
+                info_vl_branch,
+                info_else_branch,
+                info_finally_branch,
+                info_first_do,
+                info_after_do,
+            } status;
+            struct{
+                LinkValue *value;
+                LinkValue *_exit_;
+                LinkValue *_enter_;
+            } with_;
+        } branch;
+    } info;
     long int line;
     char *code_file;
     struct Statement *next;
@@ -214,6 +238,8 @@ typedef struct StatementList StatementList;
 typedef struct DecorationStatement DecorationStatement;
 
 Statement *makeStatement(long int line, char *file);
+void setRunInfo(Statement *st);
+void freeRunInfo(Statement *st);
 void freeStatement(Statement *st);
 Statement *copyStatement(Statement *st);
 Statement *copyStatementCore(Statement *st);
@@ -241,6 +267,7 @@ Statement *makeContinueStatement(Statement *times, long int line, char *file);
 Statement *makeRegoStatement(Statement *times, long int line, char *file);
 Statement *makeRestartStatement(Statement *times, long int line, char *file);
 Statement *makeReturnStatement(Statement *value, long int line, char *file);
+Statement *makeYieldStatement(Statement *value, long int line, char *file);
 Statement *makeRaiseStatement(Statement *value, long int line, char *file);
 Statement *makeAssertStatement(Statement *conditions, long int line, char *file);
 Statement *makeIncludeStatement(Statement *file, long int line, char *file_dir);

+ 1 - 0
include/token.h

@@ -113,6 +113,7 @@
 #define CONTINUE -18
 #define REGO -19
 #define RETURN -20
+#define YIELD -20
 #define RESTART -21
 #define TRY_BRANCH -22
 #define RAISE -23

+ 7 - 5
include/value.h

@@ -81,16 +81,18 @@ struct Result{
         function_return=2,  // 函数返回值
         operation_return=3,  // 表达式返回值
         error_return=4,  // 错误
-        break_return,
-        continue_return,
-        rego_return,
-        restart_return,
-        goto_return,
+        break_return=5,
+        continue_return=6,
+        rego_return=7,
+        restart_return=8,
+        goto_return=9,
+        yield_return=10,
     } type;
     char *label;
     struct LinkValue *value;
     struct Error *error;
     int times;
+    struct Statement *node;
 };
 
 struct Error{

+ 4 - 0
parser/grammar.c

@@ -147,6 +147,10 @@ void parserCommand(PASERSSIGNATURE){
             status = commandCallControl_(CALLPASERSSIGNATURE, makeReturnStatement, RETURN, &st,
                                          "Command: call return\n", false, NULL);
             break;
+        case MATHER_YIELD :
+            status = commandCallControl_(CALLPASERSSIGNATURE, makeYieldStatement, YIELD, &st,
+                                         "Command: call yield\n", false, NULL);
+            break;
         case MATHER_RAISE :
             status = commandCallControl_(CALLPASERSSIGNATURE, makeRaiseStatement, RAISE, &st,
                                          "Command: call raise\n", false, NULL);

+ 4 - 6
src/inter.c

@@ -59,6 +59,9 @@ void freeBaseInterData(struct Inter *inter){
 void freeInter(Inter *inter, bool show_gc) {
     freeBase(inter, return_);
 
+    freeVarList(inter->var_list);
+    freeBaseInterData(inter);
+
     if (show_gc && (printf("Enter '1' to show gc: "), getc(stdin) == '1')) {
         printLinkValueGC("\n\nprintLinkValueGC TAG : freeInter", inter);
         printValueGC("\nprintValueGC TAG : freeInter", inter);
@@ -68,8 +71,6 @@ void freeInter(Inter *inter, bool show_gc) {
             PASS;
     }
 
-    freeVarList(inter->var_list);
-    freeBaseInterData(inter);
     while (inter->base != NULL)
         freeValue(&inter->base);
     while (inter->base_var != NULL)
@@ -114,10 +115,7 @@ void printLinkValueGC(char *tag, Inter *inter){
     LinkValue *base = inter->link_base;
     printf("%s\n", tag);
     while (base != NULL) {
-        if (base->gc_status.tmp_link == 0)
-            fprintf(stdout, "inter->link_base.tmp_link       = %ld :: %p\n", base->gc_status.tmp_link, base);
-        else
-            fprintf(stderr, "inter->link_base.tmp_link       = %ld :: %p\n", base->gc_status.tmp_link, base);
+        printf("inter->link_base.tmp_link       = %ld :: %p\n", base->gc_status.tmp_link, base);
         printf("inter->link_base.statement_link = %ld :: %p\n", base->gc_status.statement_link, base);
         printf("inter->link_base.link           = %ld :: %p\n", base->gc_status.link, base);
         printLinkValue(base, "value = ", "\n", stdout);

+ 23 - 11
src/run.c

@@ -70,6 +70,9 @@ ResultType runStatement(INTER_FUNCTIONSIG) {
         case return_code:
             type = returnCode(CALL_INTER_FUNCTIONSIG(st, var_list, result, father));
             break;
+        case yield_code:
+            type = yieldCode(CALL_INTER_FUNCTIONSIG(st, var_list, result, father));
+            break;
         case raise_code:
             type = raiseCode(CALL_INTER_FUNCTIONSIG(st, var_list, result, father));
             break;
@@ -98,6 +101,7 @@ ResultType runStatement(INTER_FUNCTIONSIG) {
 
     if (run_continue_type(type) && result->value->aut == auto_aut)
         result->value->aut = st->aut;
+    result->node = st;
     gc_run(inter, 1, 0, 0, var_list);
     return type;
 }
@@ -144,7 +148,7 @@ ResultType iterStatement(INTER_FUNCTIONSIG) {
 
     if (type == not_return || type == restart_return)
         setResultOperationNone(result, inter, father);
-
+    result->node = base_st;
     gc_run(inter, 1, 0, 0, var_list);
     return result->type;
 }
@@ -184,7 +188,7 @@ ResultType globalIterStatement(Result *result, LinkValue *base_father, Inter *in
 
     if (type != error_return && type != function_return)
         setResultOperationNone(result, inter, father);
-
+    result->node = base_st;
     gc_run(inter, 1, 0, 0, var_list);
     return result->type;
 }
@@ -195,8 +199,10 @@ bool operationSafeInterStatement(INTER_FUNCTIONSIG){
     type = iterStatement(CALL_INTER_FUNCTIONSIG(st, var_list, result, father));
     if (run_continue_type(type))
         return false;
-    else if (type != return_code && type != error_return)
+    else if (type != return_code && type != error_return) {
+        printf("type = %d\n", type);
         setResultErrorSt(result, inter, "ResultException", "Get Not Support Result", st, father, true);
+    }
     return true;
 }
 
@@ -218,9 +224,8 @@ bool ifBranchSafeInterStatement(INTER_FUNCTIONSIG){
 bool cycleBranchSafeInterStatement(INTER_FUNCTIONSIG){
     ResultType type;
     type = iterStatement(CALL_INTER_FUNCTIONSIG(st, var_list, result, father));
-    if (run_continue_type(type)){
+    if (run_continue_type(type))
         return false;
-    }
     if (type == break_return || type == continue_return){
         result->times--;
         if (result->times < 0)
@@ -234,9 +239,8 @@ bool cycleBranchSafeInterStatement(INTER_FUNCTIONSIG){
 bool tryBranchSafeInterStatement(INTER_FUNCTIONSIG){
     ResultType type;
     type = iterStatement(CALL_INTER_FUNCTIONSIG(st, var_list, result, father));
-    if (run_continue_type(type)){
+    if (run_continue_type(type))
         return false;
-    }
     if (type == restart_return || type == goto_return)
         result->times--;
     return true;
@@ -245,13 +249,21 @@ bool tryBranchSafeInterStatement(INTER_FUNCTIONSIG){
 bool functionSafeInterStatement(INTER_FUNCTIONSIG){
     ResultType type;
     type = iterStatement(CALL_INTER_FUNCTIONSIG(st, var_list, result, father));
-    if (type == error_return)
+    if (type == error_return || result->type == yield_return)
         return true;
-    else if (type == function_return){
+    else if (type == function_return)
         result->type = operation_return;
+    else
+        result->type = not_return;
+    return false;
+}
+
+bool blockSafeInterStatement(INTER_FUNCTIONSIG){
+    ResultType type;
+    type = iterStatement(CALL_INTER_FUNCTIONSIG(st, var_list, result, father));
+    if (type == error_return || type == yield_return)
         return true;
-    }
-    result->type = not_return;
+    result->type = operation_return;
     return false;
 }
 

+ 323 - 67
src/runbranch.c

@@ -1,6 +1,6 @@
 #include "__run.h"
 
-bool checkNumber(INTER_FUNCTIONSIG){
+static bool checkNumber(INTER_FUNCTIONSIG){
     if (!isType(result->value->value, number)) {
         setResultErrorSt(result, inter, "TypeException", "Don't get a number value", st, father, true);
         return false;
@@ -8,7 +8,7 @@ bool checkNumber(INTER_FUNCTIONSIG){
     return true;
 }
 
-bool checkString(INTER_FUNCTIONSIG){
+static bool checkString(INTER_FUNCTIONSIG){
     if (!isType(result->value->value, string)) {
         setResultErrorSt(result, inter, "TypeException", "Don't get a string value", st, father, true);
         return false;
@@ -16,7 +16,7 @@ bool checkString(INTER_FUNCTIONSIG){
     return true;
 }
 
-bool checkBool(Value *value){
+static bool checkBool(Value *value){
     switch (value->type) {
         case number:
             return value->data.num.num != 0;
@@ -36,21 +36,74 @@ bool checkBool(Value *value){
     }
 }
 
+void newBranchYield(Statement *branch_st, Statement *node, StatementList *sl_node, VarList *new_var, enum StatementInfoStatus status, Inter *inter){
+    if (new_var != NULL)
+        new_var->next = NULL;
+    gc_freeze(inter, new_var, NULL, true);
+    branch_st->info.var_list = new_var;
+    branch_st->info.node = node->type == yield_code ? node->next : node;
+    branch_st->info.branch.sl_node = sl_node;
+    branch_st->info.branch.status = status;
+    branch_st->info.have_info = true;
+}
+
+void newWithBranchYield(Statement *branch_st, Statement *node, StatementList *sl_node, VarList *new_var, enum StatementInfoStatus status,
+                        Inter *inter, LinkValue *value, LinkValue *_exit_, LinkValue *_enter_){
+    newBranchYield(branch_st, node, sl_node, new_var, status, inter);
+    branch_st->info.branch.with_.value = value;
+    branch_st->info.branch.with_._exit_ = _exit_;
+    branch_st->info.branch.with_._enter_ = _enter_;
+
+}
+
+void updateBranchYield(Statement *branch_st, Statement *node, StatementList *sl_node, enum StatementInfoStatus status){
+    branch_st->info.node = node->type == yield_code ? node->next : node;
+    branch_st->info.branch.sl_node = sl_node;
+    branch_st->info.branch.status = status;
+    branch_st->info.have_info = true;
+}
+
 ResultType ifBranch(INTER_FUNCTIONSIG) {
     StatementList *if_list = st->u.if_branch.if_list;
     Statement *else_st = st->u.if_branch.else_list;
     Statement *finally = st->u.if_branch.finally;
+    Statement *info_vl = NULL;
     bool set_result = true;
     bool is_rego = false;
+    bool yield_run = false;
+    enum StatementInfoStatus result_from = info_vl_branch;
 
     Result finally_tmp;
     setResultCore(result);
     setResultCore(&finally_tmp);
 
-    var_list = pushVarList(var_list, inter);
+    yield_run = popStatementVarList(st, &var_list, var_list, inter);
+    if (yield_run && st->info.branch.status == info_vl_branch){
+        if_list = st->info.branch.sl_node;
+        info_vl = st->info.node;
+    }
+    else if (yield_run && st->info.branch.status == info_else_branch){
+        if_list = NULL;
+        else_st = st->info.node;
+    }
+    else if (yield_run && st->info.branch.status == info_finally_branch){
+        finally = st->info.node;
+        goto not_else;
+    }
+
     for (PASS; if_list != NULL; if_list = if_list->next){
         freeResult(result);
-        if (if_list->type == if_b){
+        if (info_vl != NULL){
+            if (ifBranchSafeInterStatement(CALL_INTER_FUNCTIONSIG(info_vl, var_list, result, father))){
+                set_result = false;
+                goto not_else;
+            }
+            if (result->type == rego_return)
+                is_rego = true;
+            freeResult(result);
+            info_vl = NULL;
+        }
+        else if (if_list->type == if_b){
             LinkValue *condition_value = NULL;
             if (operationSafeInterStatement(CALL_INTER_FUNCTIONSIG(if_list->condition, var_list, result, father))){
                 set_result = false;
@@ -94,8 +147,10 @@ ResultType ifBranch(INTER_FUNCTIONSIG) {
             freeResult(result);
         }
     }
-    if (else_st != NULL && ifBranchSafeInterStatement(CALL_INTER_FUNCTIONSIG(else_st, var_list, result, father)))
+    if (else_st != NULL && ifBranchSafeInterStatement(CALL_INTER_FUNCTIONSIG(else_st, var_list, result, father))) {
         set_result = false;
+        result_from = info_else_branch;
+    }
     else
         freeResult(result);
 
@@ -104,12 +159,22 @@ ResultType ifBranch(INTER_FUNCTIONSIG) {
         if (!set_result)
             freeResult(result);
         set_result = false;
+        result_from = info_finally_branch;
         *result = finally_tmp;
     }
     else
         freeResult(&finally_tmp);
 
-    var_list = popVarList(var_list);
+    if (yield_run)
+        if (result->type == yield_return)
+            updateBranchYield(st, result->node, if_list, result_from);
+        else
+            freeRunInfo(st);
+    else
+        if (result->type == yield_return)
+            newBranchYield(st, result->node, if_list, var_list, result_from, inter);
+        else
+            var_list = popVarList(var_list);
     if (set_result)
         setResult(result, inter, father);
     return result->type;
@@ -121,26 +186,64 @@ ResultType whileBranch(INTER_FUNCTIONSIG) {
     Statement *after = st->u.while_branch.after;
     Statement *else_st = st->u.while_branch.else_list;
     Statement *finally = st->u.while_branch.finally;
+    Statement *info_vl = NULL;
+    Statement *after_vl = NULL;
     bool set_result = true;
     bool is_break = false;
     bool do_while = st->u.while_branch.type == do_while_;
+    int yield_run = false;
+    enum StatementInfoStatus result_from = info_vl_branch;
 
     Result finally_tmp;
     setResultCore(result);
     setResultCore(&finally_tmp);
 
-    var_list = pushVarList(var_list, inter);
+    yield_run = popStatementVarList(st, &var_list, var_list, inter);
+    if (yield_run && st->info.branch.status == info_first_do)
+        first = st->info.node;
+    else if (yield_run && st->info.branch.status == info_vl_branch){
+        first = NULL;
+        info_vl = st->info.node;
+    }
+    else if (yield_run && st->info.branch.status == info_after_do){
+        first = NULL;
+        after_vl = st->info.node;
+    }
+    else if (yield_run && st->info.branch.status == info_else_branch){
+        else_st = st->info.node;
+        goto run_else;
+    }
+    else if (yield_run && st->info.branch.status == info_finally_branch){
+        finally = st->info.node;
+        goto not_else;
+    }
+
 
-    if (first != NULL && cycleBranchSafeInterStatement(CALL_INTER_FUNCTIONSIG(first, var_list, result, father)))
+    if (first != NULL && cycleBranchSafeInterStatement(CALL_INTER_FUNCTIONSIG(first, var_list, result, father))) {
+        result_from = info_first_do;
         set_result = false;
+    }
     else
         freeResult(result);
 
     while (!is_break){
         LinkValue *condition_value = NULL;
+        Statement *after_st = after;
+        Statement *while_st = while_list->code;
         bool condition = false;
-
         freeResult(result);
+
+        if (info_vl != NULL){
+            while_st = info_vl;
+            info_vl = NULL;
+            goto do_while_st;
+        }
+        else if (after_vl != NULL){
+            after_st = after_vl;
+            after_vl = NULL;
+            goto do_after;
+        }
+
         if (operationSafeInterStatement(CALL_INTER_FUNCTIONSIG(while_list->condition, var_list, result, father))){
             set_result = false;
             goto not_else;
@@ -160,7 +263,8 @@ ResultType whileBranch(INTER_FUNCTIONSIG) {
         condition = do_while || checkBool(condition_value->value);
         do_while = false;
         if (condition){
-            if (cycleBranchSafeInterStatement(CALL_INTER_FUNCTIONSIG(while_list->code, var_list, result, father))){
+            do_while_st:
+            if (cycleBranchSafeInterStatement(CALL_INTER_FUNCTIONSIG(while_st, var_list, result, father))){
                 set_result = false;
                 goto not_else;
             }
@@ -171,10 +275,11 @@ ResultType whileBranch(INTER_FUNCTIONSIG) {
         else
             break;
 
-        if (after == NULL)
+        do_after:
+        if (after_st == NULL)
             continue;
-
-        if (cycleBranchSafeInterStatement(CALL_INTER_FUNCTIONSIG(after, var_list, result, father))){
+        if (cycleBranchSafeInterStatement(CALL_INTER_FUNCTIONSIG(after_st, var_list, result, father))){
+            result_from = info_after_do;
             set_result = false;
             goto not_else;
         }
@@ -185,8 +290,12 @@ ResultType whileBranch(INTER_FUNCTIONSIG) {
 
         freeResult(result);
     }
-    if (!is_break && else_st != NULL && cycleBranchSafeInterStatement(CALL_INTER_FUNCTIONSIG(else_st, var_list, result, father)))
+
+    run_else:
+    if (!is_break && else_st != NULL && cycleBranchSafeInterStatement(CALL_INTER_FUNCTIONSIG(else_st, var_list, result, father))) {
+        result_from = info_else_branch;
         set_result = false;
+    }
     else
         freeResult(result);
 
@@ -195,12 +304,22 @@ ResultType whileBranch(INTER_FUNCTIONSIG) {
         if (!set_result)
             freeResult(result);
         set_result = false;
+        result_from = info_finally_branch;
         *result = finally_tmp;
     }
     else
         freeResult(&finally_tmp);
 
-    var_list = popVarList(var_list);
+    if (yield_run)
+        if (result->type == yield_return)
+            updateBranchYield(st, result->node, while_list, result_from);
+        else
+            freeRunInfo(st);
+    else
+        if (result->type == yield_return)
+            newBranchYield(st, result->node, while_list, var_list, result_from, inter);
+        else
+            var_list = popVarList(var_list);
     if (set_result)
         setResult(result, inter, father);
     return result->type;
@@ -210,11 +329,14 @@ ResultType withBranch(INTER_FUNCTIONSIG) {
     StatementList *with_list = st->u.with_branch.with_list;
     Statement *else_st = st->u.with_branch.else_list;
     Statement *finally = st->u.with_branch.finally;
+    Statement *vl_info = NULL;
     VarList *new = NULL;
     LinkValue *_enter_ = NULL;
     LinkValue *_exit_ = NULL;
     LinkValue *value = NULL;
     bool set_result = true;
+    bool yield_run;
+    enum StatementInfoStatus result_from = info_vl_branch;
 
     Result finally_tmp;
     Result else_tmp;
@@ -224,92 +346,167 @@ ResultType withBranch(INTER_FUNCTIONSIG) {
     setResultCore(&else_tmp);
     setResultCore(&exit_tmp);
 
-    if (operationSafeInterStatement(CALL_INTER_FUNCTIONSIG(with_list->condition, var_list, result, father))){
-        set_result = false;
-        goto not_else;
-    }
-
-    value = result->value;
-    if (with_list->var == NULL) {
-        new = copyVarListCore(result->value->value->object.var, inter);
-        new->next = var_list;
+    if ((yield_run = st->info.have_info)){
+        value = st->info.branch.with_.value;
+        _enter_ = st->info.branch.with_._enter_;
+        _exit_ = st->info.branch.with_._exit_;
+        if (st->info.var_list != NULL) {
+            new = st->info.var_list;
+            new->next = var_list;
+        }
+        if (st->info.branch.status == info_vl_branch)
+            vl_info = st->info.node;
+        else if (st->info.branch.status == info_else_branch) {
+            else_st = st->info.node;
+            goto run_else;
+        }
+        else if (st->info.branch.status == info_finally_branch){
+            finally = st->info.node;
+            goto run_finally;
+        }
     }
     else {
-        LinkValue *enter_value = NULL;
-        char *enter_name = setStrVarName(inter->data.object_enter, false, CALL_INTER_FUNCTIONSIG_CORE(var_list));
-        char *exit_name = setStrVarName(inter->data.object_exit, false, CALL_INTER_FUNCTIONSIG_CORE(var_list));
-        _enter_ = findFromVarList(enter_name, 0, false, CALL_INTER_FUNCTIONSIG_CORE(value->value->object.var));
-        _exit_ = findFromVarList(exit_name, 0, false, CALL_INTER_FUNCTIONSIG_CORE(value->value->object.var));
-        memFree(enter_name);
-        memFree(exit_name);
-
-        freeResult(result);
-        if (_enter_ == NULL || _exit_ == NULL){
-            _enter_ = NULL;
-            _exit_ = NULL;
-            setResultErrorSt(result, inter, "EnterException", "Get Not Support Value to Enter with", st, father, true);
+        if (operationSafeInterStatement(CALL_INTER_FUNCTIONSIG(with_list->condition, var_list, result, father))) {
             set_result = false;
-            goto not_else;
+            goto run_finally;
         }
 
-        gc_addTmpLink(&_enter_->gc_status);
-        gc_addTmpLink(&_exit_->gc_status);
-        callBackCore(_enter_, NULL, st->line, st->code_file, CALL_INTER_FUNCTIONSIG_NOT_ST(var_list, result, value));
-        if (!run_continue(result)){
-            set_result = false;
-            goto not_else;
-        }
+        if (with_list->var == NULL) {
+            new = copyVarListCore(result->value->value->object.var, inter);
+            new->next = var_list;
+            freeResult(result);
+        } else {
+            LinkValue *enter_value = NULL;
+            char *enter_name = NULL;
+            char *exit_name = NULL;
+            value = result->value;
+            result->value = NULL;
+
+            enter_name = setStrVarName(inter->data.object_enter, false, CALL_INTER_FUNCTIONSIG_CORE(var_list));
+            exit_name = setStrVarName(inter->data.object_exit, false, CALL_INTER_FUNCTIONSIG_CORE(var_list));
+            _enter_ = findFromVarList(enter_name, 0, false, CALL_INTER_FUNCTIONSIG_CORE(value->value->object.var));
+            _exit_ = findFromVarList(exit_name, 0, false, CALL_INTER_FUNCTIONSIG_CORE(value->value->object.var));
+            memFree(enter_name);
+            memFree(exit_name);
 
-        new = pushVarList(var_list, inter);
-        enter_value = result->value;
-        freeResult(result);
-        assCore(with_list->var, enter_value, CALL_INTER_FUNCTIONSIG_NOT_ST (new, result, father));
-        if (!run_continue(result)){
-            set_result = false;
-            popVarList(new);
-            goto not_else;
+            freeResult(result);
+            if (_enter_ == NULL || _exit_ == NULL) {
+                gc_freeTmpLink(&value->gc_status);
+                _enter_ = NULL;
+                _exit_ = NULL;
+                value = NULL;
+                setResultErrorSt(result, inter, "EnterException", "Get Not Support Value to Enter with", st, father, true);
+                set_result = false;
+                goto run_finally;
+            }
+
+            gc_addTmpLink(&_enter_->gc_status);
+            gc_addTmpLink(&_exit_->gc_status);
+            callBackCore(_enter_, NULL, st->line, st->code_file, CALL_INTER_FUNCTIONSIG_NOT_ST(var_list, result, value));
+            if (!run_continue(result)) {
+                set_result = false;
+                gc_freeTmpLink(&value->gc_status);
+                gc_freeTmpLink(&_enter_->gc_status);
+                gc_freeTmpLink(&_exit_->gc_status);
+                goto run_finally;
+            }
+
+            new = pushVarList(var_list, inter);
+            enter_value = result->value;
+            freeResult(result);
+            assCore(with_list->var, enter_value, CALL_INTER_FUNCTIONSIG_NOT_ST (new, result, father));
+            if (!run_continue(result)) {
+                set_result = false;
+                popVarList(new);
+                gc_freeTmpLink(&value->gc_status);
+                gc_freeTmpLink(&_enter_->gc_status);
+                gc_freeTmpLink(&_exit_->gc_status);
+                goto run_finally;
+            }
+            freeResult(result);
         }
-        freeResult(result);
     }
 
-    if (tryBranchSafeInterStatement(CALL_INTER_FUNCTIONSIG(with_list->code, new, result, father)))
+    gc_freeze(inter, new, var_list, true);
+    if (vl_info == NULL)
+        vl_info = with_list->code;
+    if (tryBranchSafeInterStatement(CALL_INTER_FUNCTIONSIG(vl_info, new, result, father))) {
         set_result = false;
+        if (result->type == yield_return)
+            goto run_finally;
+    }
     else
         freeResult(result);
 
+    run_else:
     if (else_st != NULL && tryBranchSafeInterStatement(CALL_INTER_FUNCTIONSIG(else_st, new, &else_tmp, father))) {
         if (!set_result)
             freeResult(result);
         set_result = false;
         *result = else_tmp;
+        result_from = info_else_branch;
+        if (result->type == yield_return)
+            goto run_finally;
     }
     else
         freeResult(&else_tmp);
 
-    popVarList(new);
-    if (_exit_ != NULL && _enter_ != NULL) {
+    if (_exit_ != NULL) {
         callBackCore(_exit_, NULL, st->line, st->code_file, CALL_INTER_FUNCTIONSIG_NOT_ST(var_list, &exit_tmp, value));
         if (!run_continue_type(exit_tmp.type)) {
             if (!set_result)
                 freeResult(result);
             set_result = false;
             *result = exit_tmp;
-        } else
+        }
+        else
             freeResult(&exit_tmp);
-        gc_freeTmpLink(&_enter_->gc_status);
-        gc_freeTmpLink(&_exit_->gc_status);
+        if (!yield_run){
+            gc_freeTmpLink(&value->gc_status);
+            gc_freeTmpLink(&_enter_->gc_status);
+            gc_freeTmpLink(&_exit_->gc_status);
+        }
     }
 
-    not_else:
+    run_finally:
     if (finally != NULL && tryBranchSafeInterStatement(CALL_INTER_FUNCTIONSIG(finally, var_list, &finally_tmp, father))){
         if (!set_result)
             freeResult(result);
         set_result = false;
         *result = finally_tmp;
+        result_from = info_finally_branch;
     }
     else
         freeResult(&finally_tmp);
 
+    gc_freeze(inter, new, var_list, false);
+    if (yield_run)
+        if (result->type == yield_return)
+            if (result_from == info_finally_branch) {
+                freeRunInfo(st);
+                newBranchYield(st, result->node, with_list, NULL, result_from, inter);
+            }
+            else
+                updateBranchYield(st, result->node, with_list, result_from);
+        else
+            freeRunInfo(st);
+    else {
+        if (result->type == yield_return)
+            if (result_from == info_finally_branch) {
+                if (value != NULL) {
+                    gc_freeTmpLink(&value->gc_status);
+                    gc_freeTmpLink(&_enter_->gc_status);
+                    gc_freeTmpLink(&_exit_->gc_status);
+                }
+                newBranchYield(st, result->node, with_list, NULL, result_from, inter);
+                popVarList(new);
+            }
+            else
+                newWithBranchYield(st, result->node, with_list, new, result_from, inter, value, _exit_, _enter_);
+        else
+            popVarList(new);
+    }
+
     if (set_result)
         setResult(result, inter, father);
     return result->type;
@@ -320,21 +517,46 @@ ResultType tryBranch(INTER_FUNCTIONSIG) {
     Statement *try = st->u.try_branch.try;
     Statement *else_st = st->u.try_branch.else_list;
     Statement *finally = st->u.try_branch.finally;
+    Statement *info_vl = NULL;
     LinkValue *error_value = NULL;
     bool set_result = true;
+    bool yield_run;
+    enum StatementInfoStatus result_from = info_first_do;
 
     Result finally_tmp;
     setResultCore(result);
     setResultCore(&finally_tmp);
 
-    var_list = pushVarList(var_list, inter);
-    if (!tryBranchSafeInterStatement(CALL_INTER_FUNCTIONSIG(try, var_list, result, father))){
+    yield_run = popStatementVarList(st, &var_list, var_list, inter);
+    if (yield_run && st->info.branch.status == info_first_do)
+        try = st->info.node;
+    else if (yield_run && st->info.branch.status == info_vl_branch){
+        try = NULL;
+        info_vl = st->info.node;
+        goto run_except;
+    }
+    else if (yield_run && st->info.branch.status == info_else_branch){
+        try = NULL;
+        else_st = st->info.node;
+        goto not_except;
+    }
+    else if (yield_run && st->info.branch.status == info_finally_branch){
+        try = NULL;
+        else_st = NULL;
+        finally = st->info.node;
+        goto not_else;
+    }
+
+    if (try == NULL || !tryBranchSafeInterStatement(CALL_INTER_FUNCTIONSIG(try, var_list, result, father))){
         freeResult(result);
         goto not_except;
     }
+    if (result->type == yield_return)
+        goto not_else;
 
     if (except_list == NULL) {
         set_result = false;
+        result_from = info_first_do;
         goto not_else;
     }
 
@@ -348,15 +570,23 @@ ResultType tryBranch(INTER_FUNCTIONSIG) {
         }
         freeResult(result);
     }
-    if (tryBranchSafeInterStatement(CALL_INTER_FUNCTIONSIG(except_list->code, var_list, result, father)))
+
+    run_except:
+    if (info_vl == NULL)
+        info_vl = except_list->code;
+    if (tryBranchSafeInterStatement(CALL_INTER_FUNCTIONSIG(info_vl, var_list, result, father))) {
+        result_from = info_vl_branch;
         set_result = false;
+    }
     else
         freeResult(result);
     goto not_else;
 
     not_except:
-    if (else_st != NULL && tryBranchSafeInterStatement(CALL_INTER_FUNCTIONSIG(else_st, var_list, result, father)))
+    if (else_st != NULL && tryBranchSafeInterStatement(CALL_INTER_FUNCTIONSIG(else_st, var_list, result, father))) {
         set_result = false;
+        result_from = info_else_branch;
+    }
     else
         freeResult(result);
 
@@ -366,11 +596,22 @@ ResultType tryBranch(INTER_FUNCTIONSIG) {
             freeResult(result);
         set_result = false;
         *result = finally_tmp;
+        result_from = info_finally_branch;
     }
     else
         freeResult(&finally_tmp);
 
-    var_list = popVarList(var_list);
+    if (yield_run)
+        if (result->type == yield_return)
+            updateBranchYield(st, result->node, except_list, result_from);
+        else
+            freeRunInfo(st);
+    else
+        if (result->type == yield_return)
+            newBranchYield(st, result->node, except_list, var_list, result_from, inter);
+        else
+            var_list = popVarList(var_list);
+
     if (set_result)
         setResult(result, inter, father);
     return result->type;
@@ -480,6 +721,21 @@ ResultType returnCode(INTER_FUNCTIONSIG){
     return result->type;
 }
 
+ResultType yieldCode(INTER_FUNCTIONSIG){
+    setResultCore(result);
+    if (st->u.yield_code.value == NULL) {
+        setResult(result, inter, father);
+        goto set_result;
+    }
+
+    if (operationSafeInterStatement(CALL_INTER_FUNCTIONSIG(st->u.yield_code.value, var_list, result, father)))
+        return result->type;
+
+    set_result:
+    result->type = yield_return;
+    return result->type;
+}
+
 ResultType raiseCode(INTER_FUNCTIONSIG){
     setResultCore(result);
     if (st->u.raise_code.value == NULL) {

+ 69 - 11
src/runcall.c

@@ -1,5 +1,27 @@
 #include "__run.h"
 
+void newFunctionYield(Statement *funtion_st, Statement *node, VarList *new_var, Inter *inter){
+    new_var->next = NULL;
+    gc_freeze(inter, new_var, NULL, true);
+    funtion_st->info.var_list = new_var;
+    funtion_st->info.node = node->type == yield_code ? node->next : node;
+    funtion_st->info.have_info = true;
+}
+
+void updateFunctionYield(Statement *function_st, Statement *node){
+    function_st->info.node = node->type == yield_code ? node->next : node;
+    function_st->info.have_info = true;
+}
+
+void freeFunctionYield(Statement *function_st, Inter *inter){  // TODO-szh 去除该函数
+    function_st->info.var_list->next = NULL;
+    gc_freeze(inter, function_st->info.var_list, NULL, false);
+    freeVarList(function_st->info.var_list);
+    function_st->info.var_list = NULL;
+    function_st->info.have_info = false;
+    function_st->info.node = NULL;
+}
+
 ResultType setClass(INTER_FUNCTIONSIG) {
     Argument *call = NULL;
     LinkValue *tmp = NULL;
@@ -158,30 +180,66 @@ ResultType callClass(LinkValue *class_value, Parameter *parameter, long int line
     return result->type;
 }
 
+bool popStatementVarList(Statement *funtion_st, VarList **function_var, VarList *out_var, Inter *inter){
+    bool yield_run;
+    if ((yield_run = funtion_st->info.have_info)) {
+        *function_var = funtion_st->info.var_list;
+        (*function_var)->next = out_var;
+    }
+    else
+        *function_var = pushVarList(out_var, inter);
+    return yield_run;
+}
+
+Statement *getRunInfoStatement(Statement *funtion_st){  // TODO-szh 去除该函数
+    return funtion_st->info.node;
+}
+
 ResultType callFunction(LinkValue *function_value, Parameter *parameter, long int line, char *file, INTER_FUNCTIONSIG_NOT_ST) {
     VarList *function_var = NULL;
+    Statement *funtion_st = NULL;
+    bool yield_run = false;
     setResultCore(result);
     gc_addTmpLink(&function_value->gc_status);
+    funtion_st = function_value->value->data.function.function;
+    if ((yield_run = popStatementVarList(funtion_st, &function_var, function_value->value->object.out_var, inter)))
+        funtion_st = getRunInfoStatement(funtion_st);
 
-    function_var = pushVarList(function_value->value->object.out_var, inter);
-    gc_addTmpLink(&function_var->hashtable->gc_status);
     gc_freeze(inter, var_list, function_var, true);
-
-    setParameter(line, file, parameter, function_value->value->data.function.pt, function_var, function_value, CALL_INTER_FUNCTIONSIG_NOT_ST(var_list, result, father));
+    gc_addTmpLink(&function_var->hashtable->gc_status);
+    setParameter(line, file, parameter, function_value->value->data.function.pt, function_var, function_value,
+                 CALL_INTER_FUNCTIONSIG_NOT_ST(var_list, result, father));
+    gc_freeTmpLink(&function_var->hashtable->gc_status);
     if (!run_continue(result)) {
-        gc_addTmpLink(&function_var->hashtable->gc_status);
         gc_freeze(inter, var_list, function_var, false);
-        popVarList(function_var);
+        funtion_st = function_value->value->data.function.function;
+        if (yield_run)
+            freeFunctionYield(funtion_st, inter);
+        else
+            popVarList(function_var);
         goto return_;
     }
-
     freeResult(result);
-    functionSafeInterStatement(CALL_INTER_FUNCTIONSIG(function_value->value->data.function.function, function_var, result, function_value));
+    functionSafeInterStatement(CALL_INTER_FUNCTIONSIG(funtion_st, function_var, result, function_value));
 
-    gc_freeTmpLink(&function_var->hashtable->gc_status);
     gc_freeze(inter, var_list, function_var, false);
-    popVarList(function_var);
-
+    funtion_st = function_value->value->data.function.function;
+    if (yield_run) {
+        if (result->type == yield_return){
+            updateFunctionYield(funtion_st, result->node);
+            result->type = operation_return;
+        }
+        else
+            freeFunctionYield(funtion_st, inter);
+    }
+    else {
+        if (result->type == yield_return){
+            newFunctionYield(funtion_st, result->node, function_var, inter);
+            result->type = operation_return;
+        }
+        else
+            popVarList(function_var);
+    }
     return_:
     gc_freeTmpLink(&function_value->gc_status);
     return result->type;

+ 26 - 9
src/runoperation.c

@@ -154,16 +154,33 @@ ResultType divOperation(INTER_FUNCTIONSIG) {
     return result->type;
 }
 
-ResultType blockOperation(INTER_FUNCTIONSIG) {
-    ResultType type;
-    var_list = pushVarList(var_list, inter);
-    type = functionSafeInterStatement(CALL_INTER_FUNCTIONSIG(st->u.operation.left, var_list, result, father));
-    if (type == not_return)
-        setResult(result, inter, father);
-    if (run_continue_type(type) && st->aut != auto_aut)
+ResultType blockOperation(INTER_FUNCTIONSIG) {  // TODO-szh 处理yield
+    Statement *info_st = st->u.operation.left;
+    bool yield_run;
+    if ((yield_run = popStatementVarList(st, &var_list, var_list, inter)))
+        info_st = st->info.node;
+    blockSafeInterStatement(CALL_INTER_FUNCTIONSIG(info_st, var_list, result, father));
+    if (result->type == error_return)
+        return result->type;
+    else if (yield_run) {
+        if (result->type == yield_return){
+            updateFunctionYield(st, result->node);
+            result->type = operation_return;
+        }
+        else
+            freeFunctionYield(st, inter);
+    }
+    else {
+        if (result->type == yield_return){
+            newFunctionYield(st, result->node, var_list, inter);
+            result->type = operation_return;
+        }
+        else
+            popVarList(var_list);
+    }
+    if (run_continue(result) && st->aut != auto_aut)
         result->value->aut = st->aut;
-    popVarList(var_list);
-    return type;
+    return result->type;
 }
 
 ResultType pointOperation(INTER_FUNCTIONSIG) {

+ 40 - 1
src/statement.c

@@ -7,9 +7,35 @@ Statement *makeStatement(long int line, char *file) {
     tmp->aut = auto_aut;
     tmp->line = line;
     tmp->code_file = memStrcpy(file);
+    setRunInfo(tmp);
     return tmp;
 }
 
+void setRunInfo(Statement *st){
+    st->info.have_info = false;
+    st->info.node = NULL;
+    st->info.var_list = NULL;
+    st->info.branch.sl_node = NULL;
+    st->info.branch.status = info_vl_branch;
+    st->info.branch.with_.value = NULL;
+    st->info.branch.with_._exit_ = NULL;
+    st->info.branch.with_._enter_ = NULL;
+}
+
+void freeRunInfo(Statement *st) {
+    if (st->info.var_list != NULL) {
+        gc_freeTmpLink(&st->info.var_list->hashtable->gc_status);
+        freeVarList(st->info.var_list);
+    }
+    if (st->info.branch.with_.value != NULL)
+        gc_freeTmpLink(&st->info.branch.with_.value->gc_status);
+    if (st->info.branch.with_._exit_ != NULL)
+        gc_freeTmpLink(&st->info.branch.with_._exit_->gc_status);
+    if (st->info.branch.with_._enter_ != NULL)
+        gc_freeTmpLink(&st->info.branch.with_._enter_->gc_status);
+    setRunInfo(st);
+}
+
 Token *setOperationFromToken(Statement **st_ad, struct Token *left, struct Token *right, enum OperationType type, bool is_right) {
     Token *new_token = NULL;
     Statement *st = *st_ad, *left_st = left->data.st;
@@ -221,6 +247,13 @@ Statement *makeReturnStatement(Statement *value, long int line, char *file){
     return tmp;
 }
 
+Statement *makeYieldStatement(Statement *value, long int line, char *file){
+    Statement *tmp = makeStatement(line, file);
+    tmp->type = yield_code;
+    tmp->u.yield_code.value = value;
+    return tmp;
+}
+
 Statement *makeRaiseStatement(Statement *value, long int line, char *file){
     Statement *tmp = makeStatement(line, file);
     tmp->type = raise_code;
@@ -294,7 +327,6 @@ void connectStatement(Statement *base, Statement *new){
 void freeStatement(Statement *st){
     Statement *next_tmp = NULL;
     freeBase(st, return_);
-
     for (PASS; st != NULL; st = next_tmp){
         next_tmp = st->next;
         switch (st->type) {
@@ -387,6 +419,9 @@ void freeStatement(Statement *st){
             case return_code:
                 freeStatement(st->u.return_code.value);
                 break;
+            case yield_code:
+                freeStatement(st->u.yield_code.value);
+                break;
             case raise_code:
                 freeStatement(st->u.raise_code.value);
                 break;
@@ -421,6 +456,7 @@ void freeStatement(Statement *st){
             default:
                 break;
         }
+        freeRunInfo(st);
         memFree(st->code_file);
         memFree(st);
     }
@@ -538,6 +574,9 @@ Statement *copyStatementCore(Statement *st){
         case return_code:
             new->u.return_code.value = copyStatement(st->u.return_code.value);
             break;
+        case yield_code:
+            new->u.yield_code.value = copyStatement(st->u.yield_code.value);
+            break;
         case raise_code:
             new->u.raise_code.value = copyStatement(st->u.raise_code.value);
             break;

+ 1 - 0
src/value.c

@@ -203,6 +203,7 @@ void setResultCore(Result *ru) {
     ru->error = NULL;
     ru->value = NULL;
     ru->label = NULL;
+    ru->node = NULL;
 }
 
 void setResult(Result *ru, Inter *inter, LinkValue *father) {