Selaa lähdekoodia

feat: 新增vobject的计算函数, 新增布尔运算

vobject写入实质运算的函数
新增bool运算, 与和非运算返回实质值而非布尔值

link #1
SongZihuan 4 vuotta sitten
vanhempi
sitoutus
8114e9f770

+ 2 - 1
VirtulMathCore/include/inter.h

@@ -6,7 +6,7 @@ struct Result;
 #define BASEOBJSZIE (17)
 #define VARNAMESIZE (8)
 #define BASEEXCESIZE (19)
-#define MAGFUNCSIZE (45)
+#define MAGFUNCSIZE (46)
 
 #define B_OBJECT (0)
 #define B_VOBJECT (1)
@@ -84,6 +84,7 @@ struct Result;
 #define M_AND (42)
 #define M_OR (43)
 #define M_NOT (44)
+#define M_NEGATE (45)
 
 struct Inter{
     struct Value *base;

+ 1 - 0
VirtulMathCore/include/macro.h

@@ -2,6 +2,7 @@
 #define VIRTUALMATH_MACRO_H
 
 #include <stdio.h>
+#include "errno.h"
 #include <math.h>
 #include <string.h>
 #include <stdlib.h>

+ 1 - 0
VirtulMathCore/include/statement.h

@@ -107,6 +107,7 @@ struct Statement{
                 OPT_AND = 24,
                 OPT_OR = 25,
                 OPT_NOT = 26,
+                OPT_NEGATE = 27,
             } OperationType;
             struct Statement *left;
             struct Statement *right;

+ 1 - 0
VirtulMathCore/include/token.h

@@ -141,6 +141,7 @@
 #define T_OR (-45)
 
 #define T_NOT (-46)
+#define T_NEGATE (-47)
 
 struct Token{
     int token_type;  // 记录token的类型,大于0的数字均为lex匹配器所匹配,小于0的为syntax解析器所匹配

+ 245 - 11
VirtulMathCore/ofunc/src/vobject.c

@@ -68,14 +68,152 @@ void vobject_div_base(LinkValue *belong, Result *result, struct Inter *inter, Va
         makeIntValue(div_result.quot, LINEFILE, CNEXT_NT);
     } else if (left->type == V_dou && right->type == V_int)
         makeDouValue(left->data.dou.num / (vdou)right->data.int_.num, LINEFILE, CNEXT_NT);
+    else if (left->type == V_int && right->type == V_dou)
+        makeDouValue((vdou)left->data.int_.num / right->data.dou.num, LINEFILE, CNEXT_NT);
     else if (left->type == V_dou && right->type == V_dou)
-        makeDouValue((vdou)left->data.dou.num / right->data.int_.num, LINEFILE, CNEXT_NT);
+        makeDouValue(left->data.dou.num / right->data.dou.num, LINEFILE, CNEXT_NT);
+    else
+        setResultError(E_TypeException, CUL_ERROR(Div), LINEFILE, true, CNEXT_NT);
+}
+
+void vobject_intdiv_base(LinkValue *belong, Result *result, struct Inter *inter, VarList *var_list, Value *left, Value *right) {
+    setResultCore(result);
+    if (right->type == V_int && right->data.int_.num == 0 || right->type == V_dou && (vint)right->data.dou.num == 0)  // !(right->data.dou.num != 0) 因为long double检查是否位0时容易出错
+        setResultError(E_TypeException, L"divisor mustn't be 0", LINEFILE, true, CNEXT_NT);
+    else if (left->type == V_int && right->type == V_int) {
+        lldiv_t div_result = lldiv(left->data.int_.num, right->data.int_.num);
+        makeIntValue(div_result.quot, LINEFILE, CNEXT_NT);
+    } else if (left->type == V_dou && right->type == V_int)
+        makeIntValue((vint)left->data.dou.num / right->data.int_.num, LINEFILE, CNEXT_NT);
+    else if (left->type == V_int && right->type == V_dou)
+        makeIntValue(left->data.int_.num / (vint)right->data.dou.num, LINEFILE, CNEXT_NT);
     else if (left->type == V_dou && right->type == V_dou)
-        makeDouValue(left->data.dou.num / right->data.int_.num, LINEFILE, CNEXT_NT);
+        makeIntValue((vint)left->data.dou.num / (vint)right->data.dou.num, LINEFILE, CNEXT_NT);
     else
         setResultError(E_TypeException, CUL_ERROR(Div), LINEFILE, true, CNEXT_NT);
 }
 
+void vobject_mod_base(LinkValue *belong, Result *result, struct Inter *inter, VarList *var_list, Value *left, Value *right) {
+    setResultCore(result);
+    if (right->type == V_int && right->data.int_.num == 0)  // !(right->data.dou.num != 0) 因为long double检查是否位0时容易出错
+        setResultError(E_TypeException, L"divisor mustn't be 0", LINEFILE, true, CNEXT_NT);
+    else if (left->type == V_int && right->type == V_int) {
+        lldiv_t div_result = lldiv(left->data.int_.num, right->data.int_.num);
+        makeIntValue(div_result.rem, LINEFILE, CNEXT_NT);
+    } else
+        setResultError(E_TypeException, CUL_ERROR(Div), LINEFILE, true, CNEXT_NT);
+}
+
+void vobject_pow_base(LinkValue *belong, Result *result, struct Inter *inter, VarList *var_list, Value *left, Value *right) {
+    setResultCore(result);
+    errno = 0;  // 初始化error
+    vdou re;
+    if (left->type == V_int && right->type == V_int)
+        re = pow(left->data.int_.num, right->data.int_.num);
+    else if (left->type == V_dou && right->type == V_int)
+        re = powl(left->data.dou.num, right->data.int_.num);
+    else if (left->type == V_int && right->type == V_dou)
+        re = powl(left->data.int_.num, right->data.dou.num);
+    else if (left->type == V_dou && right->type == V_dou)
+        re = powl(left->data.dou.num, right->data.dou.num);
+    else {
+        setResultError(E_TypeException, CUL_ERROR(Div), LINEFILE, true, CNEXT_NT);
+        return;
+    }
+    if (errno != 0) {
+        wchar_t *err = memStrToWcs(strerror(errno), false);
+        setResultError(E_TypeException, err, LINEFILE, true, CNEXT_NT);  // TODO-szh 设置计算错误
+        memFree(err);
+    } else
+        makeDouValue(re, LINEFILE, CNEXT_NT);
+}
+
+void vobject_eq_base(LinkValue *belong, Result *result, struct Inter *inter, VarList *var_list, Value *left, Value *right) {
+    setResultCore(result);
+    if (left->type == V_int && right->type == V_int)
+        makeBoolValue(left->data.int_.num == right->data.int_.num, LINEFILE, CNEXT_NT);
+    else if (left->type == V_int && right->type == V_dou)
+        makeBoolValue(left->data.int_.num == right->data.dou.num, LINEFILE, CNEXT_NT);
+    else if (left->type == V_dou && right->type == V_int)
+        makeBoolValue(left->data.dou.num == right->data.int_.num, LINEFILE, CNEXT_NT);
+    else if (left->type == V_dou && right->type == V_dou)
+        makeBoolValue(left->data.dou.num == right->data.dou.num, LINEFILE, CNEXT_NT);
+    else if (left->type == V_pointer && right->type == V_pointer)
+        makeBoolValue((char *)left->data.pointer.pointer == (char *)right->data.pointer.pointer, LINEFILE, CNEXT_NT);
+    else if (left->type == V_str && right->type == V_str)
+        makeBoolValue(eqWide(left->data.str.str, left->data.str.str), LINEFILE, CNEXT_NT);
+    else
+        makeBoolValue(left == right, LINEFILE, CNEXT_NT);
+}
+
+void vobject_noteq_base(LinkValue *belong, Result *result, struct Inter *inter, VarList *var_list, Value *left, Value *right) {
+    setResultCore(result);
+    if (left->type == V_int && right->type == V_int)
+        makeBoolValue(left->data.int_.num != right->data.int_.num, LINEFILE, CNEXT_NT);
+    else if (left->type == V_int && right->type == V_dou)
+        makeBoolValue(left->data.int_.num != right->data.dou.num, LINEFILE, CNEXT_NT);
+    else if (left->type == V_dou && right->type == V_int)
+        makeBoolValue(left->data.dou.num != right->data.int_.num, LINEFILE, CNEXT_NT);
+    else if (left->type == V_dou && right->type == V_dou)
+        makeBoolValue(left->data.dou.num != right->data.dou.num, LINEFILE, CNEXT_NT);
+    else if (left->type == V_pointer && right->type == V_pointer)
+        makeBoolValue((char *)left->data.pointer.pointer != (char *)right->data.pointer.pointer, LINEFILE, CNEXT_NT);
+    else if (left->type == V_str && right->type == V_str)
+        makeBoolValue(!(eqWide(left->data.str.str, left->data.str.str)), LINEFILE, CNEXT_NT);
+    else
+        makeBoolValue(left != right, LINEFILE, CNEXT_NT);
+}
+
+#define BITMACRO(SYMBOL, NAME, TYPE) void vobject_##NAME##_base(LinkValue *belong, Result *result, struct Inter *inter, VarList *var_list, Value *left, Value *right) { \
+    setResultCore(result); \
+    if (left->type == V_int && right->type == V_int) \
+        makeIntValue(left->data.int_.num SYMBOL right->data.int_.num, LINEFILE, CNEXT_NT); \
+    else \
+        setResultError(E_TypeException, CUL_ERROR(TYPE), LINEFILE, true, CNEXT_NT); \
+}
+
+BITMACRO(&, band, Bit And)
+BITMACRO(|, bor, Bit Or)
+BITMACRO(^, bxor, Bit Xor)
+#undef BITMACRO
+
+#define BITMOVEMACRO(SYMBOL1, SYMBOL2, NAME, TYPE) void vobject_##NAME##_base(LinkValue *belong, Result *result, struct Inter *inter, VarList *var_list, Value *left, Value *right) { \
+    setResultCore(result); \
+    if (left->type == V_int && right->type == V_int) { \
+        if (right->data.int_.num >= 0) \
+            makeIntValue(left->data.int_.num SYMBOL1 (unsigned)right->data.int_.num, LINEFILE, CNEXT_NT); \
+        else \
+            makeIntValue(left->data.int_.num SYMBOL2 (unsigned)(-right->data.int_.num), LINEFILE, CNEXT_NT); \
+    } else \
+        setResultError(E_TypeException, CUL_ERROR(TYPE), LINEFILE, true, CNEXT_NT); \
+}
+
+BITMOVEMACRO(<<, >>, bl, Bit Left)
+BITMOVEMACRO(>>, <<, br, Bit Right)
+#undef BITMOVEMACRO
+
+#define COMPAREMACRO(SYMBOL, NAME, TYPE) void vobject_##NAME##_base(LinkValue *belong, Result *result, struct Inter *inter, VarList *var_list, Value *left, Value *right) { \
+    setResultCore(result); \
+    if (left->type == V_int && right->type == V_int) \
+        makeBoolValue(left->data.int_.num SYMBOL right->data.int_.num, LINEFILE, CNEXT_NT); \
+    else if (left->type == V_int && right->type == V_dou) \
+        makeBoolValue(left->data.int_.num SYMBOL right->data.dou.num, LINEFILE, CNEXT_NT); \
+    else if (left->type == V_dou && right->type == V_int) \
+        makeBoolValue(left->data.dou.num SYMBOL right->data.int_.num, LINEFILE, CNEXT_NT); \
+    else if (left->type == V_dou && right->type == V_dou) \
+        makeBoolValue(left->data.dou.num SYMBOL right->data.dou.num, LINEFILE, CNEXT_NT); \
+    else if (left->type == V_pointer && right->type == V_pointer) \
+        makeBoolValue((char *)left->data.pointer.pointer SYMBOL (char *)right->data.pointer.pointer, LINEFILE, CNEXT_NT); \
+    else \
+        setResultError(E_TypeException, CUL_ERROR(TYPE), LINEFILE, true, CNEXT_NT); \
+}
+
+COMPAREMACRO(>, more, More)
+COMPAREMACRO(>=, moreeq, More Eq)
+COMPAREMACRO(<=, lesseq, Less Eq)
+COMPAREMACRO(<, less, Less Eq)
+#undef COMPAREMACRO
+
 ResultType vobject_opt_core(O_FUNC, base_opt func){
     Value *left = NULL;
     Value *right = NULL;
@@ -97,20 +235,97 @@ ResultType vobject_opt_core(O_FUNC, base_opt func){
     return result->type;
 }
 
-ResultType vobject_add(O_FUNC){
-    return vobject_opt_core(CO_FUNC(arg, var_list, result, belong), vobject_add_base);
+#define COMPAREFUNCMACRO(TYPE) ResultType vobject_##TYPE(O_FUNC){ \
+    return vobject_opt_core(CO_FUNC(arg, var_list, result, belong), vobject_##TYPE##_base); \
 }
 
-ResultType vobject_sub(O_FUNC){
-    return vobject_opt_core(CO_FUNC(arg, var_list, result, belong), vobject_sub_base);
-}
+COMPAREFUNCMACRO(add)
+COMPAREFUNCMACRO(sub)
+COMPAREFUNCMACRO(mul)
+COMPAREFUNCMACRO(div)
+COMPAREFUNCMACRO(intdiv)
+COMPAREFUNCMACRO(mod)
+COMPAREFUNCMACRO(pow)
+COMPAREFUNCMACRO(eq)
+COMPAREFUNCMACRO(noteq)
+COMPAREFUNCMACRO(moreeq)
+COMPAREFUNCMACRO(lesseq)
+COMPAREFUNCMACRO(more)
+COMPAREFUNCMACRO(less)
+COMPAREFUNCMACRO(band)
+COMPAREFUNCMACRO(bor)
+COMPAREFUNCMACRO(bxor)
+COMPAREFUNCMACRO(bl)
+COMPAREFUNCMACRO(br)
+#undef COMPAREFUNCMACRO
+
+ResultType vobject_negate(O_FUNC){
+    Value *left = NULL;
+    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);
+    }
 
-ResultType vobject_mul(O_FUNC){
-    return vobject_opt_core(CO_FUNC(arg, var_list, result, belong), vobject_mul_base);
+    left = ap[0].value->value;
+    switch (left->type) {
+        case V_int:
+            makeIntValue(-(left->data.int_.num), LINEFILE, CNEXT_NT);
+            break;
+        case V_dou:
+            makeDouValue(-(left->data.dou.num), LINEFILE, CNEXT_NT);
+            break;
+        case V_str: {
+            wchar_t *new = memWidecpySelf(left->data.str.str, -1);
+            makeStringValue(new, LINEFILE, CNEXT_NT);
+            memFree(new);
+            break;
+        }
+        case V_bool:
+            makeBoolValue(!(left->data.bool_.bool_), LINEFILE, CNEXT_NT);
+            break;
+        case V_none:
+            setResult(result, inter);
+            break;
+        default:
+            setResultError(E_TypeException, CUL_ERROR(Negate), LINEFILE, true, CNEXT_NT);
+            break;
+    }
+    return result->type;
 }
 
-ResultType vobject_div(O_FUNC){
-    return vobject_opt_core(CO_FUNC(arg, var_list, result, belong), vobject_div_base);
+ResultType vobject_bnot(O_FUNC){
+    Value *left = NULL;
+    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);
+    }
+
+    left = ap[0].value->value;
+    switch (left->type) {
+        case V_int:
+            makeIntValue(~(left->data.int_.num), LINEFILE, CNEXT_NT);
+            break;
+        case V_bool:
+            makeBoolValue(!(left->data.bool_.bool_), LINEFILE, CNEXT_NT);
+            break;
+        case V_none:
+            setResult(result, inter);
+            break;
+        default:
+            setResultError(E_TypeException, CUL_ERROR(Negate), LINEFILE, true, CNEXT_NT);
+            break;
+    }
+    return result->type;
 }
 
 ResultType vobject_bool(O_FUNC){
@@ -241,6 +456,25 @@ void registeredVObject(R_FUNC){
                       {inter->data.mag_func[M_BOOL], vobject_bool, object_free_},
                       {inter->data.mag_func[M_REPO], vobject_repo, object_free_},
                       {inter->data.mag_func[M_STR], vobject_repo, object_free_},
+                      {inter->data.mag_func[M_INTDIV], vobject_intdiv, object_free_},
+                      {inter->data.mag_func[M_MOD], vobject_mod, object_free_},
+                      {inter->data.mag_func[M_POW], vobject_pow, object_free_},
+
+                      {inter->data.mag_func[M_EQ], vobject_eq, object_free_},
+                      {inter->data.mag_func[M_NOTEQ], vobject_noteq, object_free_},
+                      {inter->data.mag_func[M_MOREEQ], vobject_moreeq, object_free_},
+                      {inter->data.mag_func[M_LESSEQ], vobject_lesseq, object_free_},
+                      {inter->data.mag_func[M_MORE], vobject_more, object_free_},
+                      {inter->data.mag_func[M_LESS], vobject_less, object_free_},
+
+                      {inter->data.mag_func[M_BAND], vobject_band, object_free_},
+                      {inter->data.mag_func[M_BOR], vobject_bor, object_free_},
+                      {inter->data.mag_func[M_BXOR], vobject_bxor, object_free_},
+                      {inter->data.mag_func[M_BL], vobject_bl, object_free_},
+                      {inter->data.mag_func[M_BR], vobject_br, object_free_},
+
+                      {inter->data.mag_func[M_NEGATE], vobject_negate, object_free_},
+                      {inter->data.mag_func[M_BNOT], vobject_bnot, object_free_},
                       {NULL, NULL}};
     gc_addTmpLink(&object->gc_status);
     addBaseClassVar(L"vobject", object, belong, inter);

+ 31 - 11
VirtulMathCore/parser/grammar.c

@@ -1001,8 +1001,7 @@ void parserDef(P_FUNC){
     int type = readBackToken(pm);
     long int line = delToken(pm);
 
-    if (!callChildStatement(CP_FUNC, parserBaseValue, T_BASEVALUE, &name_tmp,
-                            "Don't get a func/V_class name"))
+    if (!callChildStatement(CP_FUNC, parserBaseValue, T_BASEVALUE, &name_tmp, "Don't get a func/class name"))
         goto error_;
 
     if (!checkToken(pm, MATHER_LP))
@@ -1345,16 +1344,16 @@ void parserNot(P_FUNC){
         else if (left_token->token_type == MATHER_BITNOT)
             *pst = makeOperationBaseStatement(OPT_BNOT, left_token->line, pm->file);
         else {
-            backToken_(pm, left_token);
-            if (callChildStatement(CP_FUNC, parserCallBack, T_CALLFUNC, pst, NULL))
-                break;
-            else {
+            backToken_(pm, left_token);  // 当 left_token 非 MATHER_BOOLNOT 或 MATHER_BITNOT 则要退回该token
+            if (!callChildStatement(CP_FUNC, parserCallBack, T_CALLFUNC, pst, NULL)) {
                 freeStatement(st);
                 return;
             }
+            break;
         }
+
         pst = &(*pst)->u.operation.left;
-        freeToken(left_token, true);
+        freeToken(left_token, true);  // 当 left_token 是 MATHER_BOOLNOT 或 MATHER_BITNOT 则要删除该token
     }
     addStatementToken(T_NOT, st, pm);
     return;
@@ -1419,7 +1418,7 @@ bool tailSlice(P_FUNC, Token *left_token, Statement **st){
 bool taliPoint(P_FUNC, Token *left_token, Statement **st){
     Statement *right_st = NULL;
     delToken(pm);
-    if (!callChildStatement(CP_FUNC, parserBaseValue, T_BASEVALUE, &right_st, "Don't get a BaseValue after point"))
+    if (!callChildStatement(CP_FUNC, parserNegate, T_NEGATE, &right_st, "Don't get a Negate after point"))
         return false;
     *st = makeOperationStatement(OPT_POINT, left_token->data.st, right_st);
     return true;
@@ -1428,7 +1427,7 @@ bool taliPoint(P_FUNC, Token *left_token, Statement **st){
 bool taliLink(P_FUNC, Token *left_token, Statement **st){
     Statement *right_st = NULL;
     delToken(pm);
-    if (!callChildStatement(CP_FUNC, parserBaseValue, T_BASEVALUE, &right_st, "Don't get a BaseValue after link"))
+    if (!callChildStatement(CP_FUNC, parserNegate, T_NEGATE, &right_st, "Don't get a Negate after link"))
         return false;
     *st = makeOperationStatement(OPT_LINK, left_token->data.st, right_st);
     return true;
@@ -1441,8 +1440,7 @@ void parserCallBack(P_FUNC){
         struct Statement *st = NULL;
 
         if (readBackToken(pm) != T_CALLFUNC){
-
-            if (!callChildStatement(CP_FUNC, parserBaseValue, T_BASEVALUE, &st, NULL))
+            if (!callChildStatement(CP_FUNC, parserNegate, T_NEGATE, &st, NULL))
                 goto return_;
             addStatementToken(T_CALLFUNC, st, pm);
             continue;
@@ -1466,6 +1464,28 @@ void parserCallBack(P_FUNC){
     return_: return;
 }
 
+void parserNegate(P_FUNC){
+    struct Statement *st = NULL, **pst = &st;
+    while(true){
+        Token *left_token = popNewToken(pm->tm);
+        if (left_token->token_type == MATHER_SUB) {
+            *pst = makeOperationBaseStatement(OPT_NEGATE, left_token->line, pm->file);
+            freeToken(left_token, true);
+            pst = &(*pst)->u.operation.left;
+        } else {
+            backToken_(pm, left_token);
+            if (callChildStatement(CP_FUNC, parserBaseValue, T_BASEVALUE, pst, NULL))
+                break;
+            else {
+                freeStatement(st);
+                return;
+            }
+        }
+    }
+    addStatementToken(T_NEGATE, st, pm);
+    return;
+}
+
 /**
  * 字面量匹配
  * parserBaseValue:

+ 1 - 0
VirtulMathCore/parser/include/__grammar.h

@@ -42,6 +42,7 @@ void parserBor(P_FUNC);
 void parserBxor(P_FUNC);
 void parserAnd(P_FUNC);
 void parserOr(P_FUNC);
+void parserNegate(P_FUNC);
 
 void parserAssignment(P_FUNC);
 void parserTuple(P_FUNC);

+ 1 - 0
VirtulMathCore/src/inter.c

@@ -111,6 +111,7 @@ void setBaseInterData(struct Inter *inter){
     inter->data.mag_func[M_AND] = setName("__and__");
     inter->data.mag_func[M_OR] = setName("__or__");
     inter->data.mag_func[M_NOT] = setName("__not__");
+    inter->data.mag_func[M_NEGATE] = setName("__negate__");
 
     inter->data.default_pt_type = free_;
 }

+ 64 - 4
VirtulMathCore/src/runoperation.c

@@ -6,6 +6,8 @@ ResultType operationCore2(FUNC, wchar_t *name);
 ResultType assOperation(FUNC);
 ResultType pointOperation(FUNC);
 ResultType blockOperation(FUNC);
+ResultType boolNotOperation(FUNC);
+ResultType boolOperation(FUNC);
 
 /**
  * operation的整体操作
@@ -32,7 +34,6 @@ ResultType operationStatement(FUNC) {
         OPT_CASE(BAND);
         OPT_CASE(BOR);
         OPT_CASE(BXOR);
-        OPT_CASE2(BNOT);
         OPT_CASE(BL);
         OPT_CASE(BR);
 
@@ -43,9 +44,17 @@ ResultType operationStatement(FUNC) {
         OPT_CASE(LESS);
         OPT_CASE(NOTEQ);
 
-        OPT_CASE(AND);
-        OPT_CASE(OR);
-        OPT_CASE2(NOT);
+        OPT_CASE2(BNOT);
+        OPT_CASE2(NEGATE);
+
+        case OPT_NOT:
+            boolNotOperation(CNEXT);
+            break;
+
+        case OPT_OR:
+        case OPT_AND:
+            boolOperation(CNEXT);
+            break;
 
         case OPT_ASS:
             assOperation(CNEXT);
@@ -114,6 +123,57 @@ ResultType blockOperation(FUNC) {
     return result->type;
 }
 
+ResultType boolNotOperation(FUNC) {
+    bool new;
+    LinkValue *left;
+    setResultCore(result);
+    if (operationSafeInterStatement(CFUNC(st->u.operation.left, var_list, result, belong)))
+        return result->type;
+    left = result->value;
+    result->value = NULL;
+    freeResult(result);
+
+    new = !checkBool(left, st->line, st->code_file, CNEXT_NT);
+    gc_freeTmpLink(&left->gc_status);
+
+    if (CHECK_RESULT(result)) {
+        freeResult(result);
+        makeBoolValue(new, st->line, st->code_file, CNEXT_NT);
+    }
+    return result->type;
+}
+
+ResultType boolOperation(FUNC) {
+    bool left_bool;
+    LinkValue *left;
+    setResultCore(result);
+
+    if (operationSafeInterStatement(CFUNC(st->u.operation.left, var_list, result, belong)))
+        return result->type;
+    left = result->value;
+    result->value = NULL;
+    freeResult(result);
+
+    left_bool = checkBool(left, st->line, st->code_file, CNEXT_NT);
+    gc_freeTmpLink(&left->gc_status);
+    if (!CHECK_RESULT(result))
+        return result->type;
+
+    freeResult(result);
+    if (st->u.operation.OperationType == OPT_AND) {  // 与运算
+        if (left_bool)
+            operationSafeInterStatement(CFUNC(st->u.operation.right, var_list, result, belong));
+        else
+            setResultOperation(result, left);
+    } else {  // 或运算
+        if (left_bool)
+            setResultOperation(result, left);
+        else
+            operationSafeInterStatement(CFUNC(st->u.operation.right, var_list, result, belong));
+    }
+    return result->type;
+}
+
 ResultType pointOperation(FUNC) {
     LinkValue *left;
     VarList *object = NULL;