Browse Source

feat: 支持使用with分支

支持使用with打开一个object
支持使用with as进入一个object
SongZihuan 4 years ago
parent
commit
7f708b789b
12 changed files with 208 additions and 15 deletions
  1. 1 0
      include/run.h
  2. 1 0
      include/statement.h
  3. 1 0
      include/token.h
  4. 2 1
      include/var.h
  5. 62 1
      parser/grammar.c
  6. 1 0
      parser/include/__grammar.h
  7. 1 1
      src/inter.c
  8. 3 0
      src/run.c
  9. 113 0
      src/runbranch.c
  10. 6 7
      src/runcall.c
  11. 9 0
      src/statement.c
  12. 8 5
      src/var.c

+ 1 - 0
include/run.h

@@ -34,6 +34,7 @@ ResultType setDefault(INTER_FUNCTIONSIG);
 
 ResultType ifBranch(INTER_FUNCTIONSIG);
 ResultType whileBranch(INTER_FUNCTIONSIG);
+ResultType withBranch(INTER_FUNCTIONSIG);
 ResultType tryBranch(INTER_FUNCTIONSIG);
 ResultType breakCycle(INTER_FUNCTIONSIG);
 ResultType continueCycle(INTER_FUNCTIONSIG);

+ 1 - 0
include/statement.h

@@ -211,6 +211,7 @@ Statement *makeIfStatement(long int line, char *file);
 Statement *makeWhileStatement(long int line, char *file);
 Statement *makeTryStatement(long int line, char *file);
 Statement *makeBreakStatement(Statement *times, long int line, char *file);
+Statement *makeWithStatement(long int line, char *file);
 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);

+ 1 - 0
include/token.h

@@ -118,6 +118,7 @@
 #define VARCONTROL -28
 #define ASSERT -29
 #define DO_BRANCH -30
+#define WITH_BRANCH -31
 
 #define printTokenEnter(tk, debug, type, message) do{ \
 writeLog(debug, type, message, NULL); \

+ 2 - 1
include/var.h

@@ -43,7 +43,7 @@ void freeVar(Var **var);
 HashTable *makeHashTable(Inter *inter);
 void freeHashTable(HashTable **value);
 
-VarList *makeVarList(Inter *inter);
+VarList *makeVarList(Inter *inter, bool make_hash);
 VarList *freeVarList(VarList *vl);
 
 HASH_INDEX time33(char *key);
@@ -55,6 +55,7 @@ void addFromVarList(char *name, LinkValue *name_, NUMBER_TYPE times, LinkValue *
 
 VarList *pushVarList(VarList *base, Inter *inter);
 VarList *popVarList(VarList *base);
+VarList *copyVarListCore(VarList *base, Inter *inter);
 VarList *copyVarList(VarList *base, bool n_new, Inter *inter);
 VarList *connectVarListBack(VarList *base, VarList *back);
 bool comparVarList(VarList *dest, VarList *src);

+ 62 - 1
parser/grammar.c

@@ -102,6 +102,9 @@ void parserCommand(PASERSSIGNATURE){
         case MATHER_DO :
             status = commandCallBack_(CALLPASERSSIGNATURE, parserDo, DO_BRANCH, &st, "Command: call do\n");
             break;
+        case MATHER_WITH :
+            status = commandCallBack_(CALLPASERSSIGNATURE, parserWith, WITH_BRANCH, &st, "Command: call with\n");
+            break;
         case MATHER_IF :
             status = commandCallBack_(CALLPASERSSIGNATURE, parserIf, IF_BRANCH, &st, "Command: call if\n");
             break;
@@ -349,6 +352,64 @@ void parserDo(PASERSSIGNATURE){
     return;
 }
 
+void parserWith(PASERSSIGNATURE){
+    Statement *st = NULL;
+    Statement *code_tmp = NULL;
+    Statement *var_tmp = NULL;
+    Statement *condition_tmp = NULL;
+    Statement *else_st = NULL;
+    Statement *finally_st = NULL;
+    StatementList *sl = NULL;
+    long int line = 0;
+    long int tmp_line;
+
+    line = delToken(pm);
+    if (!callChildStatement(CALLPASERSSIGNATURE, parserOperation, OPERATION, &condition_tmp, "Don't get a with operation"))
+        goto error_;
+    if (!callParserAs(CALLPASERSSIGNATURE, &var_tmp, "Don't get a with var"))
+        goto error_;
+    if (!callParserCode(CALLPASERSSIGNATURE, &code_tmp, "Don't get a with code", line))
+        goto error_;
+    sl = makeConnectStatementList(sl, condition_tmp, var_tmp, code_tmp, if_b);
+    condition_tmp = NULL;
+    var_tmp = NULL;
+    code_tmp = NULL;
+
+    for (int tk=readBackToken(pm); tk == MATHER_ENTER; tk = readBackToken(pm))
+        delToken(pm);
+
+    if (readBackToken(pm) == MATHER_ELSE) {
+        tmp_line = delToken(pm);
+        if (!callParserCode(CALLPASERSSIGNATURE, &else_st, "Don't get a with...else code", tmp_line))
+            goto error_;
+    }
+
+    for (int tk=readBackToken(pm); tk == MATHER_ENTER; tk = readBackToken(pm))
+        delToken(pm);
+
+    if (readBackToken(pm) == MATHER_FINALLY) {
+        tmp_line = delToken(pm);
+        if (!callParserCode(CALLPASERSSIGNATURE, &finally_st, "Don't get a wilt...finally code", tmp_line))
+            goto error_;
+    }
+
+    addLexToken(pm, MATHER_ENTER);
+    st = makeWithStatement(line, pm->file);
+    st->u.with_branch.with_list = sl;
+    st->u.with_branch.else_list = else_st;
+    st->u.with_branch.finally = finally_st;
+    addStatementToken(WITH_BRANCH, st, pm);
+    return;
+
+    error_:
+    freeStatement(condition_tmp);
+    freeStatement(var_tmp);
+    freeStatement(else_st);
+    freeStatement(finally_st);
+    freeStatementList(sl);
+    return;
+}
+
 /**
  * 条件分支匹配
  * parserIf:
@@ -427,7 +488,7 @@ void parserIf(PASERSSIGNATURE){
         }
         case MATHER_FINALLY: {
             long int tmp_line = delToken(pm);
-            if (!callParserCode(CALLPASERSSIGNATURE, &finally_st, "Don't get a if...else code", tmp_line))
+            if (!callParserCode(CALLPASERSSIGNATURE, &finally_st, "Don't get a if...finally code", tmp_line))
                 goto error_;
             break;
         }

+ 1 - 0
parser/include/__grammar.h

@@ -22,6 +22,7 @@ void parserCommand(PASERSSIGNATURE);
 void parserControl(PASERSSIGNATURE, MakeControlFunction callBack, int type, bool must_operation, char *message);
 void parserDef(PASERSSIGNATURE);
 void parserDo(PASERSSIGNATURE);
+void parserWith(PASERSSIGNATURE);
 void parserIf(PASERSSIGNATURE);
 void parserWhile(PASERSSIGNATURE);
 void parserTry(PASERSSIGNATURE);

+ 1 - 1
src/inter.c

@@ -9,7 +9,7 @@ Inter *makeInter(char *debug) {
     tmp->hash_base = NULL;
     tmp->base_var = NULL;
 
-    tmp->var_list = makeVarList(tmp);
+    tmp->var_list = makeVarList(tmp, true);
     tmp->data.log_dir = memStrcpy(debug);
 
     if (debug != NULL && !args.stdout_inter){

+ 3 - 0
src/run.c

@@ -49,6 +49,9 @@ ResultType runStatement(INTER_FUNCTIONSIG) {
         case while_branch:
             type = whileBranch(CALL_INTER_FUNCTIONSIG(st, var_list, result, father));
             break;
+        case with_branch:
+            type = withBranch(CALL_INTER_FUNCTIONSIG(st, var_list, result, father));
+            break;
         case try_branch:
             type = tryBranch(CALL_INTER_FUNCTIONSIG(st, var_list, result, father));
             break;

+ 113 - 0
src/runbranch.c

@@ -182,6 +182,8 @@ ResultType whileBranch(INTER_FUNCTIONSIG) {
         set_result = false;
         *result = finally_tmp;
     }
+    else
+        freeResult(&finally_tmp);
 
     var_list = popVarList(var_list);
     if (set_result)
@@ -189,6 +191,115 @@ ResultType whileBranch(INTER_FUNCTIONSIG) {
     return result->type;
 }
 
+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;
+    VarList *new = NULL;
+    LinkValue *_enter_ = NULL;
+    LinkValue *_exit_ = NULL;
+    LinkValue *value = NULL;
+    bool set_result = true;
+
+    Result finally_tmp;
+    Result else_tmp;
+    Result exit_tmp;
+    setResultCore(result);
+    setResultCore(&finally_tmp);
+    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;
+    }
+    else {
+        LinkValue *enter_value = NULL;
+        char *enter_name = setStrVarName("__Enter__", false, CALL_INTER_FUNCTIONSIG_CORE(var_list));
+        char *exit_name = setStrVarName("__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;
+            setResultError(result, inter, "EnterException", "Get Not Support Value to Enter with", st, father, true);
+            set_result = false;
+            goto not_else;
+        }
+
+        gc_addTmpLink(&_enter_->gc_status);
+        gc_addTmpLink(&_exit_->gc_status);
+        callFunction(_enter_, NULL, CALL_INTER_FUNCTIONSIG_NOT_ST(var_list, result, value));
+        if (!run_continue(result)){
+            set_result = false;
+            goto not_else;
+        }
+
+        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 (tryBranchSafeInterStatement(CALL_INTER_FUNCTIONSIG(with_list->code, new, result, father)))
+        set_result = false;
+    else
+        freeResult(result);
+
+    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;
+    }
+    else
+        freeResult(&else_tmp);
+
+    popVarList(new);
+    if (_exit_ != NULL && _enter_ != NULL) {
+        callFunction(_exit_, NULL, 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
+            freeResult(&exit_tmp);
+        gc_freeTmpLink(&_enter_->gc_status);
+        gc_freeTmpLink(&_exit_->gc_status);
+    }
+
+    not_else:
+    if (finally != NULL && tryBranchSafeInterStatement(CALL_INTER_FUNCTIONSIG(finally, var_list, &finally_tmp, father))){
+        if (!set_result)
+            freeResult(result);
+        set_result = false;
+        *result = finally_tmp;
+    }
+    else
+        freeResult(&finally_tmp);
+
+    if (set_result)
+        setResult(result, inter, father);
+    return result->type;
+}
+
 ResultType tryBranch(INTER_FUNCTIONSIG) {
     StatementList *except_list = st->u.try_branch.except_list;
     Statement *try = st->u.try_branch.try;
@@ -241,6 +352,8 @@ ResultType tryBranch(INTER_FUNCTIONSIG) {
         set_result = false;
         *result = finally_tmp;
     }
+    else
+        freeResult(&finally_tmp);
 
     var_list = popVarList(var_list);
     if (set_result)

+ 6 - 7
src/runcall.c

@@ -97,7 +97,7 @@ ResultType callBack(INTER_FUNCTIONSIG) {
 ResultType callClass(LinkValue *class_value, Parameter *parameter, INTER_FUNCTIONSIG_NOT_ST) {
     VarList *function_var = NULL;
     LinkValue *value = NULL;
-    LinkValue *__init__ = NULL;
+    LinkValue *_init_ = NULL;
     setResultCore(result);
 
     value = makeLinkValue(makeObject(inter, NULL,copyVarList(class_value->value->object.out_var, false, inter),
@@ -105,17 +105,16 @@ ResultType callClass(LinkValue *class_value, Parameter *parameter, INTER_FUNCTIO
     setResultOperation(result, value, inter);
 
     char *init_name = setStrVarName(inter->data.object_init, false, CALL_INTER_FUNCTIONSIG_CORE(var_list));
-    __init__ = findFromVarList(init_name, 0, false, CALL_INTER_FUNCTIONSIG_CORE(value->value->object.var));
+    _init_ = findFromVarList(init_name, 0, false, CALL_INTER_FUNCTIONSIG_CORE(value->value->object.var));
     memFree(init_name);
 
-    if (__init__ != NULL && __init__->value->type == function){
+    if (_init_ != NULL && _init_->value->type == function){
         Result __init__result;
         setResultCore(&__init__result);
-        __init__ = makeLinkValue(__init__->value, value, inter);
 
-        gc_addTmpLink(&__init__->gc_status);
-        callFunction(__init__, parameter, CALL_INTER_FUNCTIONSIG_NOT_ST(var_list, &__init__result, value));
-        gc_freeTmpLink(&__init__->gc_status);
+        gc_addTmpLink(&_init_->gc_status);
+        callFunction(_init_, parameter, CALL_INTER_FUNCTIONSIG_NOT_ST(var_list, &__init__result, value));
+        gc_freeTmpLink(&_init_->gc_status);
 
         if (!run_continue_type(__init__result.type)){
             freeResult(result);

+ 9 - 0
src/statement.c

@@ -166,6 +166,15 @@ Statement *makeTryStatement(long int line, char *file) {
     return tmp;
 }
 
+Statement *makeWithStatement(long int line, char *file) {
+    Statement *tmp = makeStatement(line, file);
+    tmp->type = with_branch;
+    tmp->u.with_branch.with_list = NULL;
+    tmp->u.with_branch.else_list = NULL;
+    tmp->u.with_branch.finally = NULL;
+    return tmp;
+}
+
 Statement *makeBreakStatement(Statement *times, long int line, char *file){
     Statement *tmp = makeStatement(line, file);
     tmp->type = break_cycle;

+ 8 - 5
src/var.c

@@ -78,10 +78,13 @@ void freeHashTable(HashTable **value) {
     return_: return;
 }
 
-VarList *makeVarList(Inter *inter) {
+VarList *makeVarList(Inter *inter, bool make_hash) {
     VarList *tmp = calloc(1, sizeof(VarList));
     tmp->next = NULL;
-    tmp->hashtable = makeHashTable(inter);
+    if (make_hash)
+        tmp->hashtable = makeHashTable(inter);
+    else
+        tmp->hashtable = NULL;
     tmp->default_var = NULL;
     return tmp;
 }
@@ -208,7 +211,7 @@ void addFromVarList(char *name, LinkValue *name_, NUMBER_TYPE times, LinkValue *
 }
 
 VarList *pushVarList(VarList *base, Inter *inter){
-    VarList *new = makeVarList(inter);
+    VarList *new = makeVarList(inter, true);
     new->next = base;
     return new;
 }
@@ -220,7 +223,7 @@ VarList *popVarList(VarList *base) {
 }
 
 VarList *copyVarListCore(VarList *base, Inter *inter){
-    VarList *tmp = makeVarList(inter);
+    VarList *tmp = makeVarList(inter, false);
     tmp->hashtable = base->hashtable;
     return tmp;
 }
@@ -263,7 +266,7 @@ VarList *connectSafeVarListBack(VarList *base, VarList *back){
 }
 
 VarList *makeObjectVarList(FatherValue *value, Inter *inter){
-    VarList *tmp = makeVarList(inter);
+    VarList *tmp = makeVarList(inter, true);
     for (PASS; value != NULL; value = value->next) {
         VarList *new = copyVarList(value->value->value->object.var, false, inter);
         tmp = connectVarListBack(tmp, new);