diff --git a/include/utils.h b/include/utils.h index 5c99a2b..4f62cd5 100644 --- a/include/utils.h +++ b/include/utils.h @@ -73,9 +73,11 @@ struct FunctionItem { }; class FucntionContainer { std::unordered_map FunctionIndex; - public: + + public: void AddFunction(const std::string &name, const FunctionItem &item); - std::any CallFunction(const std::string &name, const std::vector &args); + std::any CallFunction(const std::string &name, + const std::vector &args); }; class VariableContainer { std::unordered_map GlobalScope; @@ -87,29 +89,28 @@ class VariableContainer { std::any ReadVariable(const std::string &name); void WriteVariable(const std::string &name, const std::any &value); }; -std::any DeQuate(std::any val,VariableContainer &Variables); +std::any DeQuate(std::any val, VariableContainer &Variables); -std::any Add(const std::any &a, const std::any &b); -std::any& SelfAdd(std::any &a, const std::any &b); +int ConverToSameArithType(std::any &a, std::any &b, + bool allow_string_operation = false); +std::any Add(std::any a, std::any b); +std::any Sub(std::any a, std::any b); +std::any Mul(std::any a, std::any b); +std::any Div(std::any a, std::any b); +std::any Divv(std::any a, std::any b); +std::any Mod(std::any a, std::any b); +std::any &SelfAdd(std::any &a, std::any b); +std::any &SelfSub(std::any &a, std::any b); +std::any &SelfMul(std::any &a, std::any b); +std::any &SelfDiv(std::any &a, std::any b); +std::any &SelfDivv(std::any &a, std::any b); +std::any &SelfMod(std::any &a, std::any b); +std::any Neg(std::any a); -std::any Sub(const std::any &a, const std::any &b); -std::any& SelfSub(std::any &a, const std::any &b); - -std::any Mul(const std::any &a, const std::any &b); -std::any& SelfMul(std::any &a, const std::any &b); - -std::any Div(const std::any &a, const std::any &b); -std::any& SelfDiv(std::any &a, const std::any &b); - -std::any Mod(const std::any &a, const std::any &b); -std::any& SelfMod(std::any &a, const std::any &b); - -std::any Neg(const std::any &a); - -bool Greater(const std::any &a, const std::any &b); -bool Less(const std::any &a, const std::any &b); -bool Equal(const std::any &a, const std::any &b); -bool NotEqual(const std::any &a, const std::any &b); -bool GreaterEqual(const std::any &a, const std::any &b); -bool LessEqual(const std::any &a, const std::any &b); +bool Greater(std::any a, std::any b); +bool Less(std::any a, std::any b); +bool Equal(std::any a, std::any b); +bool NotEqual(std::any a, std::any b); +bool GreaterEqual(std::any a, std::any b); +bool LessEqual(std::any a, std::any b); #endif \ No newline at end of file diff --git a/src/utils.cpp b/src/utils.cpp index 90b184d..3ec51d1 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -95,26 +95,369 @@ std::any DeQuate(std::any val, VariableContainer &Variables) { throw FatalError("DeQuate: unknown type"); } -std::any Add(const std::any &a, const std::any &b); -std::any& SelfAdd(std::any &a, const std::any &b); +int ConverToSameArithType(std::any &a, std::any &b, + bool allow_string_operation) { + ZYM::int2048 *ptr_a_int2048 = std::any_cast(&a); + ZYM::int2048 *ptr_b_int2048 = std::any_cast(&b); + double *ptr_a_float = std::any_cast(&a); + double *ptr_b_float = std::any_cast(&b); + bool *ptr_a_bool = std::any_cast(&a); + bool *ptr_b_bool = std::any_cast(&b); + std::string *ptr_a_string = std::any_cast(&a); + std::string *ptr_b_string = std::any_cast(&b); + if ((!allow_string_operation) && (ptr_a_string || ptr_b_string)) + throw InterpretException( + "ConverToSameArithType: string operation not allowed in this " + "situation"); + if (allow_string_operation && (ptr_a_string || ptr_b_string)) { + if (!(ptr_a_string || ptr_a_int2048)) + throw InterpretException( + "ConverToSameArithType: string operation not allowed in this " + "situation"); + if (!(ptr_b_string || ptr_b_int2048)) + throw InterpretException( + "ConverToSameArithType: string operation not allowed in this " + "situation"); + return 1; + } + int level_a = (ptr_a_bool != nullptr ? 1 : 0) + + (ptr_a_int2048 != nullptr ? 2 : 0) + + (ptr_a_float != nullptr ? 3 : 0); + int level_b = (ptr_b_bool != nullptr ? 1 : 0) + + (ptr_b_int2048 != nullptr ? 2 : 0) + + (ptr_b_float != nullptr ? 3 : 0); + int res_level = std::max(level_a, level_b); + switch (res_level) { + case 1: + break; + case 2: + a = Any2Int(a); + b = Any2Int(b); + break; + case 3: + a = Any2Float(a); + b = Any2Float(b); + break; + default: + throw FatalError("ConverToSameArithType: unknown type"); + } + return 0; +} -std::any Sub(const std::any &a, const std::any &b); -std::any& SelfSub(std::any &a, const std::any &b); +std::any Add(std::any a, std::any b) { + int status = ConverToSameArithType(a, b, true); + bool *ptr_a_bool = std::any_cast(&a); + bool *ptr_b_bool = std::any_cast(&b); + ZYM::int2048 *ptr_a_int2048 = std::any_cast(&a); + ZYM::int2048 *ptr_b_int2048 = std::any_cast(&b); + double *ptr_a_float = std::any_cast(&a); + double *ptr_b_float = std::any_cast(&b); + std::string *ptr_a_string = std::any_cast(&a); + std::string *ptr_b_string = std::any_cast(&b); + if ((ptr_a_string != nullptr ? 1 : 0) + (ptr_b_string != nullptr ? 1 : 0) == + 1) { + throw InterpretException( + "Add: string operation not allowed in this situation"); + } + if ((ptr_a_string != nullptr ? 1 : 0) + (ptr_b_string != nullptr ? 1 : 0) == + 2) + return (*ptr_a_string) + (*ptr_b_string); + if ((ptr_a_bool != nullptr) && (ptr_b_bool != nullptr)) + return (*ptr_a_bool) + (*ptr_b_bool); + else if ((ptr_a_int2048 != nullptr) && (ptr_b_int2048 != nullptr)) + return (*ptr_a_int2048) + (*ptr_b_int2048); + else if ((ptr_a_float != nullptr) && (ptr_b_float != nullptr)) + return (*ptr_a_float) + (*ptr_b_float); + else + throw FatalError("Add: Type Error"); +} +std::any Sub(std::any a, std::any b) { + ConverToSameArithType(a, b); + bool *ptr_a_bool = std::any_cast(&a); + bool *ptr_b_bool = std::any_cast(&b); + ZYM::int2048 *ptr_a_int2048 = std::any_cast(&a); + ZYM::int2048 *ptr_b_int2048 = std::any_cast(&b); + double *ptr_a_float = std::any_cast(&a); + double *ptr_b_float = std::any_cast(&b); + if ((ptr_a_bool != nullptr) && (ptr_b_bool != nullptr)) + return (*ptr_a_bool) - (*ptr_b_bool); + else if ((ptr_a_int2048 != nullptr) && (ptr_b_int2048 != nullptr)) + return (*ptr_a_int2048) - (*ptr_b_int2048); + else if ((ptr_a_float != nullptr) && (ptr_b_float != nullptr)) + return (*ptr_a_float) - (*ptr_b_float); + else + throw FatalError("Sub: Type Error"); + return a; +} +std::any Mul(std::any a, std::any b) { + int status = ConverToSameArithType(a, b, true); + bool *ptr_a_bool = std::any_cast(&a); + bool *ptr_b_bool = std::any_cast(&b); + ZYM::int2048 *ptr_a_int2048 = std::any_cast(&a); + ZYM::int2048 *ptr_b_int2048 = std::any_cast(&b); + double *ptr_a_float = std::any_cast(&a); + double *ptr_b_float = std::any_cast(&b); + std::string *ptr_a_string = std::any_cast(&a); + std::string *ptr_b_string = std::any_cast(&b); + if ((ptr_a_string != nullptr ? 1 : 0) + (ptr_b_string != nullptr ? 1 : 0) == + 2) { + throw InterpretException( + "Mul: string operation not allowed in this situation"); + } else if ((ptr_a_string != nullptr ? 1 : 0) + + (ptr_b_string != nullptr ? 1 : 0) == + 1) { + if (ptr_a_string == nullptr) { + std::swap(ptr_a_string, ptr_b_string); + std::swap(ptr_a_bool, ptr_b_bool); + std::swap(ptr_a_int2048, ptr_b_int2048); + std::swap(ptr_a_float, ptr_b_float); + } + if (ptr_b_float != nullptr) + throw InterpretException("Mul: string*float not allowed"); + if (ptr_b_bool != nullptr) { + if (*ptr_b_bool) { + return *ptr_a_string; + } else { + return ""; + } + } + if (ptr_b_int2048 != nullptr) { + std::string res; + for (int i = 0; i < (*ptr_b_int2048); i++) res += *ptr_a_string; + return res; + } + } + if ((ptr_a_bool != nullptr) && (ptr_b_bool != nullptr)) + return (*ptr_a_bool) * (*ptr_b_bool); + else if ((ptr_a_int2048 != nullptr) && (ptr_b_int2048 != nullptr)) + return (*ptr_a_int2048) * (*ptr_b_int2048); + else if ((ptr_a_float != nullptr) && (ptr_b_float != nullptr)) + return (*ptr_a_float) * (*ptr_b_float); + else + throw FatalError("Mul: Type Error"); +} +std::any Div(std::any a, std::any b) { + bool *ptr_a_bool = std::any_cast(&a); + bool *ptr_b_bool = std::any_cast(&b); + ZYM::int2048 *ptr_a_int2048 = std::any_cast(&a); + ZYM::int2048 *ptr_b_int2048 = std::any_cast(&b); + double *ptr_a_float = std::any_cast(&a); + double *ptr_b_float = std::any_cast(&b); + std::string *ptr_a_string = std::any_cast(&a); + std::string *ptr_b_string = std::any_cast(&b); + if ((ptr_a_string != nullptr) || (ptr_b_string != nullptr)) + throw InterpretException( + "Div: string operation not allowed in this situation"); + double t_a = Any2Float(a); + double t_b = Any2Float(b); + if (t_b == 0) throw InterpretException("Div: divided by zero"); + t_a = t_a / t_b; + return a; +} +std::any Divv(std::any a, std::any b) { + ConverToSameArithType(a, b); + bool *ptr_a_bool = std::any_cast(&a); + bool *ptr_b_bool = std::any_cast(&b); + ZYM::int2048 *ptr_a_int2048 = std::any_cast(&a); + ZYM::int2048 *ptr_b_int2048 = std::any_cast(&b); + double *ptr_a_float = std::any_cast(&a); + double *ptr_b_float = std::any_cast(&b); + if ((ptr_a_float != nullptr) && (ptr_b_float != nullptr)) { + if ((*ptr_b_float) == 0) throw InterpretException("Divv: divided by zero"); + return ZYM::int2048(std::floor((*ptr_a_float) / (*ptr_b_float))); + } else if ((ptr_a_int2048 != nullptr) && (ptr_b_int2048 != nullptr)) { + if ((*ptr_b_int2048) == 0) + throw InterpretException("Divv: divided by zero"); + return (*ptr_a_int2048) / (*ptr_b_int2048); + } else if ((ptr_a_bool != nullptr) && (ptr_b_bool != nullptr)) { + if ((*ptr_b_bool) == 0) throw InterpretException("Divv: divided by zero"); + return ZYM::int2048((*ptr_a_bool) / (*ptr_b_bool)); + } else + throw FatalError("Divv: Type Error"); +} +std::any Mod(std::any a, std::any b) { + ConverToSameArithType(a, b); + bool *ptr_a_bool = std::any_cast(&a); + bool *ptr_b_bool = std::any_cast(&b); + ZYM::int2048 *ptr_a_int2048 = std::any_cast(&a); + ZYM::int2048 *ptr_b_int2048 = std::any_cast(&b); + double *ptr_a_float = std::any_cast(&a); + double *ptr_b_float = std::any_cast(&b); + if ((ptr_a_float != nullptr) && (ptr_b_float != nullptr)) { + if ((*ptr_b_float) == 0) throw InterpretException("Mod: divided by zero"); + return ZYM::int2048((*ptr_a_float) - + (*ptr_b_float) * + std::floor((*ptr_a_float) / (*ptr_b_float))); + } else if ((ptr_a_int2048 != nullptr) && (ptr_b_int2048 != nullptr)) { + if ((*ptr_b_int2048) == 0) throw InterpretException("Mod: divided by zero"); + return (*ptr_a_int2048) % (*ptr_b_int2048); + } else if ((ptr_a_bool != nullptr) && (ptr_b_bool != nullptr)) { + if ((*ptr_b_bool) == 0) throw InterpretException("Mod: divided by zero"); + return ZYM::int2048((*ptr_a_bool) % (*ptr_b_bool)); + } else + throw FatalError("Mod: Type Error"); +} +std::any &SelfAdd(std::any &a, std::any b) { + a = Add(a, b); + return a; +} +std::any &SelfSub(std::any &a, std::any b) { + a = Sub(a, b); + return a; +} +std::any &SelfMul(std::any &a, std::any b) { + a = Mul(a, b); + return a; +} +std::any &SelfDiv(std::any &a, std::any b) { + a = Div(a, b); + return a; +} +std::any &SelfDivv(std::any &a, std::any b) { + a = Divv(a, b); + return a; +} +std::any &SelfMod(std::any &a, std::any b) { + a = Mod(a, b); + return a; +} +std::any Neg(std::any a) { + bool *ptr_a_bool = std::any_cast(&a); + ZYM::int2048 *ptr_a_int2048 = std::any_cast(&a); + double *ptr_a_float = std::any_cast(&a); + if (ptr_a_bool != nullptr) + return ZYM::int2048(-(*ptr_a_bool)); + else if (ptr_a_int2048 != nullptr) + return -(*ptr_a_int2048); + else if (ptr_a_float != nullptr) + return -(*ptr_a_float); + else + throw FatalError("Neg: Type Error"); +} -std::any Mul(const std::any &a, const std::any &b); -std::any& SelfMul(std::any &a, const std::any &b); - -std::any Div(const std::any &a, const std::any &b); -std::any& SelfDiv(std::any &a, const std::any &b); - -std::any Mod(const std::any &a, const std::any &b); -std::any& SelfMod(std::any &a, const std::any &b); - -std::any Neg(const std::any &a); - -bool Greater(const std::any &a, const std::any &b); -bool Less(const std::any &a, const std::any &b); -bool Equal(const std::any &a, const std::any &b); -bool NotEqual(const std::any &a, const std::any &b); -bool GreaterEqual(const std::any &a, const std::any &b); -bool LessEqual(const std::any &a, const std::any &b); \ No newline at end of file +bool Greater(std::any a, std::any b) { + ConverToSameArithType(a, b); + bool *ptr_a_bool = std::any_cast(&a); + bool *ptr_b_bool = std::any_cast(&b); + ZYM::int2048 *ptr_a_int2048 = std::any_cast(&a); + ZYM::int2048 *ptr_b_int2048 = std::any_cast(&b); + double *ptr_a_float = std::any_cast(&a); + double *ptr_b_float = std::any_cast(&b); + std::string *ptr_a_string = std::any_cast(&a); + std::string *ptr_b_string = std::any_cast(&b); + if ((ptr_a_bool != nullptr) && (ptr_b_bool != nullptr)) + return (*ptr_a_bool) > (*ptr_b_bool); + else if ((ptr_a_int2048 != nullptr) && (ptr_b_int2048 != nullptr)) + return (*ptr_a_int2048) > (*ptr_b_int2048); + else if ((ptr_a_float != nullptr) && (ptr_b_float != nullptr)) + return (*ptr_a_float) > (*ptr_b_float); + else if ((ptr_a_string != nullptr) && (ptr_b_string != nullptr)) + return (*ptr_a_string) > (*ptr_b_string); + else + throw FatalError("Greater: Type Error"); +} +bool Less(std::any a, std::any b) { + ConverToSameArithType(a, b); + bool *ptr_a_bool = std::any_cast(&a); + bool *ptr_b_bool = std::any_cast(&b); + ZYM::int2048 *ptr_a_int2048 = std::any_cast(&a); + ZYM::int2048 *ptr_b_int2048 = std::any_cast(&b); + double *ptr_a_float = std::any_cast(&a); + double *ptr_b_float = std::any_cast(&b); + std::string *ptr_a_string = std::any_cast(&a); + std::string *ptr_b_string = std::any_cast(&b); + if ((ptr_a_bool != nullptr) && (ptr_b_bool != nullptr)) + return (*ptr_a_bool) < (*ptr_b_bool); + else if ((ptr_a_int2048 != nullptr) && (ptr_b_int2048 != nullptr)) + return (*ptr_a_int2048) < (*ptr_b_int2048); + else if ((ptr_a_float != nullptr) && (ptr_b_float != nullptr)) + return (*ptr_a_float) < (*ptr_b_float); + else if ((ptr_a_string != nullptr) && (ptr_b_string != nullptr)) + return (*ptr_a_string) < (*ptr_b_string); + else + throw FatalError("Less: Type Error"); +} +bool Equal(std::any a, std::any b) { + ConverToSameArithType(a, b); + bool *ptr_a_bool = std::any_cast(&a); + bool *ptr_b_bool = std::any_cast(&b); + ZYM::int2048 *ptr_a_int2048 = std::any_cast(&a); + ZYM::int2048 *ptr_b_int2048 = std::any_cast(&b); + double *ptr_a_float = std::any_cast(&a); + double *ptr_b_float = std::any_cast(&b); + std::string *ptr_a_string = std::any_cast(&a); + std::string *ptr_b_string = std::any_cast(&b); + if ((ptr_a_bool != nullptr) && (ptr_b_bool != nullptr)) + return (*ptr_a_bool) == (*ptr_b_bool); + else if ((ptr_a_int2048 != nullptr) && (ptr_b_int2048 != nullptr)) + return (*ptr_a_int2048) == (*ptr_b_int2048); + else if ((ptr_a_float != nullptr) && (ptr_b_float != nullptr)) + return (*ptr_a_float) == (*ptr_b_float); + else if ((ptr_a_string != nullptr) && (ptr_b_string != nullptr)) + return (*ptr_a_string) == (*ptr_b_string); + else + throw FatalError("Equal: Type Error"); +} +bool NotEqual(std::any a, std::any b) { + ConverToSameArithType(a, b); + bool *ptr_a_bool = std::any_cast(&a); + bool *ptr_b_bool = std::any_cast(&b); + ZYM::int2048 *ptr_a_int2048 = std::any_cast(&a); + ZYM::int2048 *ptr_b_int2048 = std::any_cast(&b); + double *ptr_a_float = std::any_cast(&a); + double *ptr_b_float = std::any_cast(&b); + std::string *ptr_a_string = std::any_cast(&a); + std::string *ptr_b_string = std::any_cast(&b); + if ((ptr_a_bool != nullptr) && (ptr_b_bool != nullptr)) + return (*ptr_a_bool) != (*ptr_b_bool); + else if ((ptr_a_int2048 != nullptr) && (ptr_b_int2048 != nullptr)) + return (*ptr_a_int2048) != (*ptr_b_int2048); + else if ((ptr_a_float != nullptr) && (ptr_b_float != nullptr)) + return (*ptr_a_float) != (*ptr_b_float); + else if ((ptr_a_string != nullptr) && (ptr_b_string != nullptr)) + return (*ptr_a_string) != (*ptr_b_string); + else + throw FatalError("NotEqual: Type Error"); +} +bool GreaterEqual(std::any a, std::any b) { + ConverToSameArithType(a, b); + bool *ptr_a_bool = std::any_cast(&a); + bool *ptr_b_bool = std::any_cast(&b); + ZYM::int2048 *ptr_a_int2048 = std::any_cast(&a); + ZYM::int2048 *ptr_b_int2048 = std::any_cast(&b); + double *ptr_a_float = std::any_cast(&a); + double *ptr_b_float = std::any_cast(&b); + std::string *ptr_a_string = std::any_cast(&a); + std::string *ptr_b_string = std::any_cast(&b); + if ((ptr_a_bool != nullptr) && (ptr_b_bool != nullptr)) + return (*ptr_a_bool) >= (*ptr_b_bool); + else if ((ptr_a_int2048 != nullptr) && (ptr_b_int2048 != nullptr)) + return (*ptr_a_int2048) >= (*ptr_b_int2048); + else if ((ptr_a_float != nullptr) && (ptr_b_float != nullptr)) + return (*ptr_a_float) >= (*ptr_b_float); + else if ((ptr_a_string != nullptr) && (ptr_b_string != nullptr)) + return (*ptr_a_string) >= (*ptr_b_string); + else + throw FatalError("GreaterEqual: Type Error"); +} +bool LessEqual(std::any a, std::any b) { + ConverToSameArithType(a, b); + bool *ptr_a_bool = std::any_cast(&a); + bool *ptr_b_bool = std::any_cast(&b); + ZYM::int2048 *ptr_a_int2048 = std::any_cast(&a); + ZYM::int2048 *ptr_b_int2048 = std::any_cast(&b); + double *ptr_a_float = std::any_cast(&a); + double *ptr_b_float = std::any_cast(&b); + std::string *ptr_a_string = std::any_cast(&a); + std::string *ptr_b_string = std::any_cast(&b); + if ((ptr_a_bool != nullptr) && (ptr_b_bool != nullptr)) + return (*ptr_a_bool) <= (*ptr_b_bool); + else if ((ptr_a_int2048 != nullptr) && (ptr_b_int2048 != nullptr)) + return (*ptr_a_int2048) <= (*ptr_b_int2048); + else if ((ptr_a_float != nullptr) && (ptr_b_float != nullptr)) + return (*ptr_a_float) <= (*ptr_b_float); + else if ((ptr_a_string != nullptr) && (ptr_b_string != nullptr)) + return (*ptr_a_string) <= (*ptr_b_string); + else + throw FatalError("LessEqual: Type Error"); +} \ No newline at end of file