|
@@ -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);
|