瀏覽代碼

feat: 函数参数设定

允许设定value形的形参和实参
确定name_value后不能跟only_value类型的值
SongZihuan 4 年之前
父節點
當前提交
9c80809285
共有 15 個文件被更改,包括 366 次插入22 次删除
  1. 1 1
      include/__macro.h
  2. 1 0
      include/__virtualmath.h
  3. 1 1
      include/inter.h
  4. 25 0
      include/parameter.h
  5. 4 2
      include/statement.h
  6. 3 1
      include/value.h
  7. 1 1
      include/var.h
  8. 0 1
      main.c
  9. 71 6
      parser/grammar.c
  10. 240 0
      src/parameter.c
  11. 3 3
      src/runbranch.c
  12. 6 2
      src/runcall.c
  13. 6 2
      src/statement.c
  14. 3 1
      src/value.c
  15. 1 1
      src/var.c

+ 1 - 1
include/__macro.h

@@ -15,7 +15,7 @@
 
 #define NUMBER_TYPE long int
 #define HASH_INDEX unsigned int
-#define INTER_FUNCTIONSIG_CORE Inter *inter, VarList *var_list
+#define INTER_FUNCTIONSIG_CORE struct globalInterpreter *inter, struct VirtualMathVarList *var_list
 #define INTER_FUNCTIONSIG Statement *st, INTER_FUNCTIONSIG_CORE
 #define CALL_INTER_FUNCTIONSIG_CORE(var_list) inter, var_list
 #define CALL_INTER_FUNCTIONSIG(st, var_list) st, CALL_INTER_FUNCTIONSIG_CORE(var_list)

+ 1 - 0
include/__virtualmath.h

@@ -13,6 +13,7 @@
 #include "value.h"
 #include "inter.h"
 #include "log.h"
+#include "parameter.h"
 
 struct Args{
     char *file;

+ 1 - 1
include/inter.h

@@ -5,7 +5,7 @@ typedef struct globalInterpreter{
     struct VirtualMathValue *base;
     struct VirtualMathLinkValue *link_base;
     struct VirtualMathHashTable *hash_base;
-    Statement *statement;
+    struct Statement *statement;
     struct VirtualMathVarList *var_list;
     char *log_dir;  // 记录log文件夹的位置
     FILE *debug;

+ 25 - 0
include/parameter.h

@@ -0,0 +1,25 @@
+#ifndef VIRTUALMATH_PARAMETER_H
+#define VIRTUALMATH_PARAMETER_H
+#include "__macro.h"
+
+typedef struct Parameter{
+    enum {
+        only_value,
+        name_value,
+    } type;
+    struct {
+        struct Statement *value;
+        struct Statement *name;  // 仅在name-value模式生效
+    } data;
+    struct Parameter *next;
+} Parameter;
+
+Parameter *makeParameter();
+Parameter *makeOnlyValueParameter(struct Statement *st);
+Parameter *makeNameValueParameter(Statement *value, Statement *name);
+Parameter *connectParameter(Parameter *new, Parameter *base);
+Parameter *connectOnlyValueParameter(struct Statement *st, Parameter *base);
+Parameter *connectNameValueParameter(Statement *value, Statement *name, Parameter *base);
+void freeParameter(Parameter *pt);
+Result setParameter(Parameter *call, Parameter *function, VarList *function_var, INTER_FUNCTIONSIG_CORE);
+#endif //VIRTUALMATH_PARAMETER_H

+ 4 - 2
include/statement.h

@@ -44,9 +44,11 @@ typedef struct Statement{
         struct {
             struct Statement *name;
             struct Statement *function;
+            struct Parameter *parameter;
         } set_function;
         struct {
             struct Statement *function;
+            struct Parameter *parameter;
         } call_function;
         struct {
             struct StatementList *if_list;  // if elif
@@ -121,8 +123,8 @@ Statement *makeStatement();
 Statement *makeOperationStatement(int type);
 struct Token *setOperationFromToken(Statement *st, struct Token *left, struct Token *right, int type);
 
-Statement *makeFunctionStatement(Statement *name, Statement *function);
-Statement *makeCallStatement(Statement *function);
+Statement *makeFunctionStatement(Statement *name, Statement *function, struct Parameter *pt);
+Statement *makeCallStatement(Statement *function, struct Parameter *pt);
 Statement *makeIfStatement();
 Statement *makeWhileStatement();
 Statement *makeTryStatement();

+ 3 - 1
include/value.h

@@ -19,6 +19,7 @@ typedef struct VirtualMathValue{
         struct {
             struct Statement *function;
             struct VirtualMathVarList *var;
+            struct Parameter *pt;
         } function;
     }data;
     struct VirtualMathValue *next;
@@ -47,13 +48,14 @@ typedef struct VirtualMathResult{
     int times;
 } Result;
 
+
 Value *makeValue(Inter *inter);
 void freeValue(Value *value, Inter *inter);
 LinkValue *makeLinkValue(Value *value, LinkValue *linkValue,Inter *inter);
 void freeLinkValue(LinkValue *value, Inter *inter);
 Value *makeNumberValue(long num, Inter *inter);
 Value *makeStringValue(char *str, Inter *inter);
-Value *makeFunctionValue(Statement *st, struct VirtualMathVarList *var_list, Inter *inter);
+Value *makeFunctionValue(Statement *st, struct Parameter *pt, struct VirtualMathVarList *var_list, Inter *inter);
 
 void setResult(Result *ru, bool link, Inter *inter);
 void setResultError(Result *ru, Inter *inter);

+ 1 - 1
include/var.h

@@ -30,7 +30,7 @@ void addFromVarList(char *name, VarList *var_list, NUMBER_TYPE times, LinkValue
 void freeHashTable(HashTable *ht, Inter *inter);
 
 VarList *pushVarList(VarList *base, Inter *inter);
-VarList *popVarList(VarList *base, Inter *inter);
+VarList *popVarList(VarList *base);
 VarList *copyVarList(VarList *base, bool n_new, Inter *inter);
 
 #endif //VIRTUALMATH_VAR_H

+ 0 - 1
main.c

@@ -118,7 +118,6 @@ void freeArgs(){
 }
 
 /*
- *  TODO-szh 抛出异常
  *  TODO-szh 函数参数
  *  TODO-szh 列表、字典
  */

+ 71 - 6
parser/grammar.c

@@ -411,23 +411,84 @@ void parserTry(PASERSSIGNATURE){
     return;
 }
 
+bool parserParameter(PASERSSIGNATURE, Parameter **pt){
+    Parameter *new_pt = NULL;
+    Token *tmp;
+    enum {
+        s_1,  // only_value模式
+        s_2,  // name_value模式
+    } status = s_1;
+    bool last_pt = false;
+    while (!last_pt){
+        tmp = NULL;
+        parserPolynomial(CALLPASERSSIGNATURE);
+        if (!call_success(pm))
+            goto error_;
+        if (readBackToken(pm) != POLYNOMIAL)
+            break;
+        tmp = popAheadToken(pm);
+
+        int pt_type;
+        if (status == s_1){
+            pt_type = only_value;
+            if (!checkToken_(pm, MATHER_COMMA)){
+                if (!checkToken_(pm, MATHER_ASSIGNMENT))
+                    last_pt = true;
+                else {
+                    pt_type = name_value;
+                    status = s_2;
+                }
+            }
+        }
+        else{
+            pt_type = name_value;
+            if (!checkToken_(pm, MATHER_ASSIGNMENT))
+                goto error_;
+        }
+
+        if (pt_type == only_value)
+            new_pt = connectOnlyValueParameter(tmp->data.st, new_pt);
+        else if (pt_type == name_value){
+            Statement *tmp_value;
+            if (!callChildStatement(CALLPASERSSIGNATURE, parserOperation, OPERATION, &tmp_value, "Don't get a parameter value"))
+                goto error_;
+            new_pt = connectNameValueParameter(tmp_value, tmp->data.st, new_pt);
+            if (!checkToken_(pm, MATHER_COMMA))
+                last_pt = true;
+        }
+        freeToken(tmp, true, false);
+    }
+    *pt = new_pt;
+    return true;
+
+    error_:
+    freeToken(tmp, true, true);
+    freeParameter(new_pt);
+    *pt = NULL;
+    return false;
+}
+
 void parserDef(PASERSSIGNATURE){
     struct Statement *st = NULL, *name_tmp = NULL, *code_tmp = NULL;
+    Parameter *pt = NULL;
     delToken(pm);
 
     if (!callChildStatement(CALLPASERSSIGNATURE, parserBaseValue, BASEVALUE, &name_tmp, "Don't get a function name"))
         goto error_;
 
-    if (!checkToken_(pm, MATHER_LP) || !checkToken_(pm, MATHER_RP)){
+    if (!checkToken_(pm, MATHER_LP))
+        goto error_;
+    if (!parserParameter(CALLPASERSSIGNATURE, &pt))
+        goto error_;
+    if (!checkToken_(pm, MATHER_RP))
         goto error_;
-    }
     writeLog_(pm->grammar_debug, GRAMMAR_DEBUG, "parserDef: get function title success\n", NULL);
     writeLog_(pm->grammar_debug, GRAMMAR_DEBUG, "parserDef: call parserCode\n", NULL);
 
     if (!callParserCode(CALLPASERSSIGNATURE, &code_tmp, "Don't get a function code"))
         goto error_;
 
-    st = makeFunctionStatement(name_tmp, code_tmp);
+    st = makeFunctionStatement(name_tmp, code_tmp, pt);
     addEnter(pm);
     addStatementToken(FUNCTION, st, pm);
     return;
@@ -566,15 +627,19 @@ void parserFactor(PASERSSIGNATURE){
 }
 
 int tailCall(PASERSSIGNATURE, Token *left_token, Statement **st){
-    if (readBackToken(pm) != MATHER_LP){
+    struct Parameter *pt = NULL;
+    if (readBackToken(pm) != MATHER_LP)
         return -1;
-    }
     delToken(pm);
+    if (!parserParameter(CALLPASERSSIGNATURE, &pt)) {
+        syntaxError(pm, syntax_error, 1, "Don't get call parameter");
+        return 0;
+    }
     if (!checkToken_(pm, MATHER_RP)){
         syntaxError(pm, syntax_error, 1, "Don't get ) from call back");
         return 0;
     }
-    *st = makeCallStatement(left_token->data.st);
+    *st = makeCallStatement(left_token->data.st, pt);
     return 1;
 }
 void parserCallBack(PASERSSIGNATURE){

+ 240 - 0
src/parameter.c

@@ -0,0 +1,240 @@
+#include "__virtualmath.h"
+
+Parameter *makeParameter(){
+    Parameter *tmp = memCalloc(1, sizeof(Parameter));
+    tmp->type = only_value;
+    tmp->data.value = NULL;
+    tmp->data.name = NULL;
+    tmp->next = NULL;
+    return tmp;
+}
+
+Parameter *makeOnlyValueParameter(Statement *st){
+    Parameter *tmp = makeParameter();
+    tmp->data.value = st;
+    return tmp;
+}
+
+Parameter *makeNameValueParameter(Statement *value, Statement *name){
+    Parameter *tmp = makeParameter();
+    tmp->type = name_value;
+    tmp->data.value = value;
+    tmp->data.name = name;
+    return tmp;
+}
+
+Parameter *connectParameter(Parameter *new, Parameter *base){
+    if (base == NULL)
+        return new;
+    while (base->next != NULL)
+        base = base->next;
+    base->next = new;
+    return base;
+}
+
+Parameter *connectOnlyValueParameter(Statement *st, Parameter *base){
+    Parameter *new = makeOnlyValueParameter(st);
+    return connectParameter(new, base);
+}
+
+Parameter *connectNameValueParameter(Statement *value, Statement *name, Parameter *base){
+    Parameter *new = makeNameValueParameter(value, name);
+    return connectParameter(new, base);
+}
+
+void freeParameter(Parameter *pt){
+    while (pt != NULL){
+        freeStatement(pt->data.value);
+        freeStatement(pt->data.name);
+        Parameter *tmp = pt->next;
+        memFree(pt);
+        pt = tmp;
+    }
+}
+
+/**
+ * 使用形式参数的默认值
+ * @param function_ad
+ * @param inter
+ * @param var_list
+ * @return
+ */
+Result varParameter(Parameter **function_ad, INTER_FUNCTIONSIG_CORE, int *num){
+    Parameter *function = *function_ad;
+    Result result;
+    while (function != NULL && function->type == name_value){
+        Result tmp, tmp_ass;
+        if(operationSafeInterStatement(&tmp, CALL_INTER_FUNCTIONSIG(function->data.value, var_list))) {
+            *function_ad = function;
+            return tmp;
+        }
+        tmp_ass = assCore(function->data.name, tmp.value, CALL_INTER_FUNCTIONSIG_CORE(var_list));
+        if (tmp_ass.type == error_return) {
+            *function_ad = function;
+            return tmp_ass;
+        }
+        (*num)++;
+        function = function->next;
+    }
+    setResult(&result, true, inter);
+
+    *function_ad = function;
+    return result;
+}
+
+/**
+ * 使用形式参数的默认值
+ * @param call_ad
+ * @param inter
+ * @param var_list
+ * @return
+ */
+Result nameParameter(Parameter **call_ad, VarList *function_var, INTER_FUNCTIONSIG_CORE, int *num){
+    Parameter *call = *call_ad;
+    Result result;
+    bool get;
+    while (call != NULL){
+        Result tmp, tmp_ass;
+        get = true;
+        Statement *name = call->type == only_value ? call->data.value : call->data.name;
+        if(operationSafeInterStatement(&tmp, CALL_INTER_FUNCTIONSIG(name, var_list))) {
+            get = false;
+            if (call->type == name_value && !operationSafeInterStatement(&tmp, CALL_INTER_FUNCTIONSIG(call->data.value, var_list))){
+                goto not_return;
+            }
+            *call_ad = call;
+            return tmp;
+        }
+        not_return:
+        tmp_ass = assCore(name, tmp.value, CALL_INTER_FUNCTIONSIG_CORE(function_var));
+        if (tmp_ass.type == error_return) {
+            *call_ad = call;
+            return tmp_ass;
+        }
+        if (get)
+            (*num)++;
+        call = call->next;
+    }
+    setResult(&result, true, inter);
+
+    *call_ad = call;
+    return result;
+}
+
+/**
+ * 根据形参和实参对位赋值
+ * @param call_ad
+ * @param function_ad
+ * @param function_var
+ * @param inter
+ * @param var_list
+ * @return
+ */
+Result valueParameter(Parameter **call_ad, Parameter **function_ad, VarList *function_var, INTER_FUNCTIONSIG_CORE){
+    Parameter *call = *call_ad, *function = *function_ad;
+    Result result;
+    while (call != NULL && function != NULL && call->type != name_value){
+        Result tmp, tmp_ass;
+        Statement *name = function->type == only_value ? function->data.value : function->data.name;
+
+        if(operationSafeInterStatement(&tmp, CALL_INTER_FUNCTIONSIG(call->data.value, var_list))) {
+            *call_ad = call;
+            *function_ad = function;
+            return tmp;
+        }
+
+        tmp_ass = assCore(name, tmp.value, CALL_INTER_FUNCTIONSIG_CORE(function_var));
+        if (tmp_ass.type == error_return) {
+            *call_ad = call;
+            *function_ad = function;
+            return tmp_ass;
+        }
+
+        call = call->next;
+        function = function->next;
+    }
+    setResult(&result, true, inter);
+    *call_ad = call;
+    *function_ad = function;
+    return result;
+}
+
+#define returnResult(result) do{ \
+if (result.type == error_return) { \
+return result; \
+} \
+}while(0)
+
+/**
+ * 参数设定
+ * [1] 形式参数和实际参数对位赋值
+ * [2] 形式参数默认值
+ * [1] -实参完成, 形参空缺-> [2]
+ * [3] 实际参数直接赋值, 形式默认值补充
+ * [1] -实参出现name_value类型-> [3]
+ * @param call
+ * @param function
+ * @param function_var
+ * @param inter
+ * @param var_list
+ * @return
+ */
+Result setParameter(Parameter *call, Parameter *function, VarList *function_var, INTER_FUNCTIONSIG_CORE){
+    enum {
+        p_1 = 1,
+        p_2 = 2,
+        p_3 = 3,
+        error = -1,
+        finished = 0
+    } status = p_1;
+    Result result;
+
+    while (true){
+        switch (status) {
+            case p_1: {
+                result = valueParameter(&call, &function, function_var, CALL_INTER_FUNCTIONSIG_CORE(var_list));
+                returnResult(result);
+                if (call != NULL && function != NULL && call->type == name_value)
+                    status = p_3;
+                else if (call == NULL && function != NULL && function->type == name_value)
+                    status = p_2;
+                else if (call != NULL || function != NULL)
+                    status = error;
+                else
+                    status = finished;
+                break;
+            }
+            case p_2: {
+                int num = 0;
+                result = varParameter(&function, CALL_INTER_FUNCTIONSIG_CORE(function_var), &num);
+                returnResult(result);
+                status = finished;
+                break;
+            }
+            case p_3: {
+                VarList *tmp = makeVarList(inter);
+                int set_num = 0, get_num = 0;
+                result = varParameter(&call, CALL_INTER_FUNCTIONSIG_CORE(tmp), &set_num);
+                returnResult(result);
+                result = nameParameter(&function, function_var, CALL_INTER_FUNCTIONSIG_CORE(tmp), &get_num);
+                returnResult(result);
+                freeVarList(tmp, true);
+                if (set_num > get_num) {
+                    status = error;
+                    break;
+                }
+                status = finished;
+                break;
+            }
+            case error:
+                setResultError(&result, inter);
+                return result;
+            default:
+                goto return_;
+        }
+    }
+    return_:
+    return result;
+}
+
+#undef returnResult

+ 3 - 3
src/runbranch.c

@@ -67,7 +67,7 @@ Result ifBranch(INTER_FUNCTIONSIG) {
         result = finally_tmp;
     }
 
-    var_list = popVarList(var_list, inter);
+    var_list = popVarList(var_list);
     if (set_result)
         setResult(&result, true, inter);
     return result;
@@ -127,7 +127,7 @@ Result whileBranch(INTER_FUNCTIONSIG) {
         result = finally_tmp;
     }
 
-    var_list = popVarList(var_list, inter);
+    var_list = popVarList(var_list);
     if (set_result)
         setResult(&result, true, inter);
     return result;
@@ -167,7 +167,7 @@ Result tryBranch(INTER_FUNCTIONSIG) {
         result = finally_tmp;
     }
 
-    var_list = popVarList(var_list, inter);
+    var_list = popVarList(var_list);
     if (set_result)
         setResult(&result, true, inter);
     return result;

+ 6 - 2
src/runcall.c

@@ -4,7 +4,7 @@ Result setFunction(INTER_FUNCTIONSIG) {
     Result result, tmp;
     setResultOperation(&tmp, inter);
 
-    tmp.value->value = makeFunctionValue(st->u.set_function.function, var_list, inter);
+    tmp.value->value = makeFunctionValue(st->u.set_function.function, st->u.set_function.parameter, var_list, inter);
     result = assCore(st->u.set_function.name, tmp.value, CALL_INTER_FUNCTIONSIG_CORE(var_list));
     return result;
 }
@@ -22,10 +22,14 @@ Result callFunction(INTER_FUNCTIONSIG) {
         goto return_;
     }
     VarList *function_var = call_function.value->value->data.function.var;
+    Result set_tmp;
+    set_tmp = setParameter(st->u.call_function.parameter, call_function.value->value->data.function.pt, function_var, CALL_INTER_FUNCTIONSIG_CORE(var_list));
+    if (set_tmp.type == error_return)
+        return set_tmp;
     function_var = pushVarList(function_var, inter);
     functionSafeInterStatement(&result,
                                CALL_INTER_FUNCTIONSIG(call_function.value->value->data.function.function, function_var));
-    popVarList(function_var, inter);
+    popVarList(function_var);
 
     return_:
     return result;

+ 6 - 2
src/statement.c

@@ -29,18 +29,20 @@ Token *setOperationFromToken(Statement *st, Token *left, Token *right, int type)
     return new_token;
 }
 
-Statement *makeFunctionStatement(Statement *name, Statement *function){
+Statement *makeFunctionStatement(Statement *name, Statement *function, Parameter *pt) {
     Statement *tmp = makeStatement();
     tmp->type = set_function;
     tmp->u.set_function.name = name;
     tmp->u.set_function.function = function;
+    tmp->u.set_function.parameter = pt;
     return tmp;
 }
 
-Statement *makeCallStatement(Statement *function){
+Statement *makeCallStatement(Statement *function, Parameter *pt) {
     Statement *tmp = makeStatement();
     tmp->type = call_function;
     tmp->u.call_function.function = function;
+    tmp->u.call_function.parameter = pt;
     return tmp;
 }
 
@@ -141,9 +143,11 @@ void freeStatement(Statement *st){
             case set_function:
                 freeStatement(st->u.set_function.name);
                 freeStatement(st->u.set_function.function);
+                // Parameter 在 value 的地方free掉
                 break;
             case call_function:
                 freeStatement(st->u.call_function.function);
+                freeParameter(st->u.call_function.parameter);
                 break;
             case if_branch:
                 freeStatementList(st->u.if_branch.if_list);

+ 3 - 1
src/value.c

@@ -37,11 +37,12 @@ Value *makeStringValue(char *str, Inter *inter) {
     return tmp;
 }
 
-Value *makeFunctionValue(Statement *st, VarList *var_list, Inter *inter) {
+Value *makeFunctionValue(Statement *st, Parameter *pt, VarList *var_list, Inter *inter) {
     Value *tmp;
     tmp = makeValue(inter);
     tmp->type = function;
     tmp->data.function.function = st;
+    tmp->data.function.pt = pt;
     tmp->data.function.var = copyVarList(var_list, false, inter);
     return tmp;
 }
@@ -63,6 +64,7 @@ void freeValue(Value *value, Inter *inter){
             break;
         case function: {
             VarList *tmp = value->data.function.var;
+            freeParameter(value->data.function.pt);
             while (tmp != NULL)
                 tmp = freeVarList(tmp, true);
             break;

+ 1 - 1
src/var.c

@@ -171,7 +171,7 @@ VarList *pushVarList(VarList *base, Inter *inter){
     return new;
 }
 
-VarList *popVarList(VarList *base, Inter *inter){
+VarList *popVarList(VarList *base) {
     if (base->next == NULL)
         return base;
     return freeVarList(base, true);