upd: include exception info in return value
This commit is contained in:
@ -14,24 +14,30 @@
|
|||||||
class InterpretException : public std::exception {
|
class InterpretException : public std::exception {
|
||||||
public:
|
public:
|
||||||
InterpretException() {}
|
InterpretException() {}
|
||||||
InterpretException(const char *message) : m_message(message) {}
|
InterpretException(const char *__message, int __code)
|
||||||
|
: message(__message), code(__code) {}
|
||||||
|
|
||||||
const char *what() const noexcept override { return m_message; }
|
const char *what() const noexcept override { return message.c_str(); }
|
||||||
|
const int GetCode() const noexcept { return code; }
|
||||||
|
|
||||||
~InterpretException() noexcept override {}
|
~InterpretException() noexcept override {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const char *m_message;
|
std::string message;
|
||||||
|
int code;
|
||||||
};
|
};
|
||||||
|
|
||||||
class FatalError : public std::exception {
|
class FatalError : public std::exception {
|
||||||
public:
|
public:
|
||||||
FatalError(const char *message) : m_message(message) {}
|
FatalError(const char *__message, int __code)
|
||||||
|
: message(__message), code(__code) {}
|
||||||
|
|
||||||
const char *what() const noexcept override { return m_message; }
|
const char *what() const noexcept override { return message.c_str(); }
|
||||||
|
const int GetCode() const noexcept { return code; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const char *m_message;
|
std::string message;
|
||||||
|
int code;
|
||||||
};
|
};
|
||||||
enum FlowControlStatusType { BREAK, CONTINUE, RETURN };
|
enum FlowControlStatusType { BREAK, CONTINUE, RETURN };
|
||||||
struct FlowType {
|
struct FlowType {
|
||||||
|
@ -80,7 +80,8 @@ std::any EvalVisitor::visitExpr_stmt(Python3Parser::Expr_stmtContext *ctx) {
|
|||||||
if (!ptr_var && !ptr_vec)
|
if (!ptr_var && !ptr_vec)
|
||||||
throw InterpretException(
|
throw InterpretException(
|
||||||
"visitExpr_stmt: Expect left value or tuple at the left of "
|
"visitExpr_stmt: Expect left value or tuple at the left of "
|
||||||
"augassign");
|
"augassign",
|
||||||
|
1);
|
||||||
if (ptr_var) {
|
if (ptr_var) {
|
||||||
std::any old_val = DeQuate(*ptr_var, Variables);
|
std::any old_val = DeQuate(*ptr_var, Variables);
|
||||||
if (ctx->augassign()->ADD_ASSIGN())
|
if (ctx->augassign()->ADD_ASSIGN())
|
||||||
@ -96,17 +97,17 @@ std::any EvalVisitor::visitExpr_stmt(Python3Parser::Expr_stmtContext *ctx) {
|
|||||||
else if (ctx->augassign()->MOD_ASSIGN())
|
else if (ctx->augassign()->MOD_ASSIGN())
|
||||||
SelfMod(old_val, right_value);
|
SelfMod(old_val, right_value);
|
||||||
else
|
else
|
||||||
throw FatalError("visitExpr_stmt: Unknown operator at augassign");
|
throw FatalError("visitExpr_stmt: Unknown operator at augassign", 2);
|
||||||
Variables.WriteVariable(ptr_var->name, old_val);
|
Variables.WriteVariable(ptr_var->name, old_val);
|
||||||
} else {
|
} else {
|
||||||
if (ptr_vec->size() !=
|
if (ptr_vec->size() !=
|
||||||
std::any_cast<std::vector<std::any>>(right_value).size())
|
std::any_cast<std::vector<std::any>>(right_value).size())
|
||||||
throw InterpretException("visitExpr_stmt: Tuple size not match");
|
throw InterpretException("visitExpr_stmt: Tuple size not match", 3);
|
||||||
for (int i = 0; i < ptr_vec->size(); i++) {
|
for (int i = 0; i < ptr_vec->size(); i++) {
|
||||||
ptr_var = std::any_cast<RawVarible>(&(*ptr_vec)[i]);
|
ptr_var = std::any_cast<RawVarible>(&(*ptr_vec)[i]);
|
||||||
if (!ptr_var)
|
if (!ptr_var)
|
||||||
throw InterpretException(
|
throw InterpretException(
|
||||||
"visitExpr_stmt: Expect left value at the left of augassign");
|
"visitExpr_stmt: Expect left value at the left of augassign", 4);
|
||||||
std::any old_val = DeQuate(*ptr_var, Variables);
|
std::any old_val = DeQuate(*ptr_var, Variables);
|
||||||
if (ctx->augassign()->ADD_ASSIGN())
|
if (ctx->augassign()->ADD_ASSIGN())
|
||||||
SelfAdd(old_val,
|
SelfAdd(old_val,
|
||||||
@ -127,7 +128,7 @@ std::any EvalVisitor::visitExpr_stmt(Python3Parser::Expr_stmtContext *ctx) {
|
|||||||
SelfMod(old_val,
|
SelfMod(old_val,
|
||||||
std::any_cast<std::vector<std::any>>(right_value)[i]);
|
std::any_cast<std::vector<std::any>>(right_value)[i]);
|
||||||
else
|
else
|
||||||
throw FatalError("visitExpr_stmt: Unknown operator at augassign");
|
throw FatalError("visitExpr_stmt: Unknown operator at augassign", 5);
|
||||||
Variables.WriteVariable(ptr_var->name, old_val);
|
Variables.WriteVariable(ptr_var->name, old_val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -146,31 +147,32 @@ std::any EvalVisitor::visitExpr_stmt(Python3Parser::Expr_stmtContext *ctx) {
|
|||||||
else if (ptr_dest_tuple) {
|
else if (ptr_dest_tuple) {
|
||||||
if (ptr_dest_tuple->size() !=
|
if (ptr_dest_tuple->size() !=
|
||||||
std::any_cast<std::vector<std::any>>(val).size())
|
std::any_cast<std::vector<std::any>>(val).size())
|
||||||
throw InterpretException("visitExpr_stmt: Tuple size not match");
|
throw InterpretException("visitExpr_stmt: Tuple size not match", 6);
|
||||||
for (int j = 0; j < ptr_dest_tuple->size(); j++) {
|
for (int j = 0; j < ptr_dest_tuple->size(); j++) {
|
||||||
ptr_dest_single = std::any_cast<RawVarible>(&(*ptr_dest_tuple)[j]);
|
ptr_dest_single = std::any_cast<RawVarible>(&(*ptr_dest_tuple)[j]);
|
||||||
if (!ptr_dest_single)
|
if (!ptr_dest_single)
|
||||||
throw InterpretException(
|
throw InterpretException(
|
||||||
"visitExpr_stmt: Expect left value at the left of assign");
|
"visitExpr_stmt: Expect left value at the left of assign", 7);
|
||||||
Variables.WriteVariable(ptr_dest_single->name,
|
Variables.WriteVariable(ptr_dest_single->name,
|
||||||
std::any_cast<std::vector<std::any>>(val)[j]);
|
std::any_cast<std::vector<std::any>>(val)[j]);
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
throw InterpretException(
|
throw InterpretException(
|
||||||
"visitExpr_stmt: Expect left value or tuple at the left of assign");
|
"visitExpr_stmt: Expect left value or tuple at the left of assign",
|
||||||
|
8);
|
||||||
}
|
}
|
||||||
return NoneType();
|
return NoneType();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::any EvalVisitor::visitAugassign(Python3Parser::AugassignContext *ctx) {
|
std::any EvalVisitor::visitAugassign(Python3Parser::AugassignContext *ctx) {
|
||||||
throw FatalError("Function visitAugassign Shouldn't be called");
|
throw FatalError("Function visitAugassign Shouldn't be called", 9);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::any EvalVisitor::visitFlow_stmt(Python3Parser::Flow_stmtContext *ctx) {
|
std::any EvalVisitor::visitFlow_stmt(Python3Parser::Flow_stmtContext *ctx) {
|
||||||
if (ctx->break_stmt()) return visitBreak_stmt(ctx->break_stmt());
|
if (ctx->break_stmt()) return visitBreak_stmt(ctx->break_stmt());
|
||||||
if (ctx->continue_stmt()) return visitContinue_stmt(ctx->continue_stmt());
|
if (ctx->continue_stmt()) return visitContinue_stmt(ctx->continue_stmt());
|
||||||
if (ctx->return_stmt()) return visitReturn_stmt(ctx->return_stmt());
|
if (ctx->return_stmt()) return visitReturn_stmt(ctx->return_stmt());
|
||||||
throw FatalError("Unknown flow statement");
|
throw FatalError("Unknown flow statement", 10);
|
||||||
return NoneType();
|
return NoneType();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,7 +202,7 @@ std::any EvalVisitor::visitCompound_stmt(
|
|||||||
if (ctx->if_stmt()) return visitIf_stmt(ctx->if_stmt());
|
if (ctx->if_stmt()) return visitIf_stmt(ctx->if_stmt());
|
||||||
if (ctx->while_stmt()) return visitWhile_stmt(ctx->while_stmt());
|
if (ctx->while_stmt()) return visitWhile_stmt(ctx->while_stmt());
|
||||||
if (ctx->funcdef()) return visitFuncdef(ctx->funcdef());
|
if (ctx->funcdef()) return visitFuncdef(ctx->funcdef());
|
||||||
throw FatalError("Unknown compound statement");
|
throw FatalError("Unknown compound statement", 11);
|
||||||
return NoneType();
|
return NoneType();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -209,7 +211,7 @@ std::any EvalVisitor::visitIf_stmt(Python3Parser::If_stmtContext *ctx) {
|
|||||||
auto suite_list = ctx->suite();
|
auto suite_list = ctx->suite();
|
||||||
if (test_list.size() - suite_list.size() != -1 &&
|
if (test_list.size() - suite_list.size() != -1 &&
|
||||||
test_list.size() - suite_list.size() != 0)
|
test_list.size() - suite_list.size() != 0)
|
||||||
throw InterpretException("test and suite doesn't match in If_stmt");
|
throw InterpretException("test and suite doesn't match in If_stmt", 12);
|
||||||
for (int i = 0; i < test_list.size(); i++)
|
for (int i = 0; i < test_list.size(); i++)
|
||||||
if (Any2Bool(DeQuate(visitTest(test_list[i]), Variables)))
|
if (Any2Bool(DeQuate(visitTest(test_list[i]), Variables)))
|
||||||
return visitSuite(suite_list[i]);
|
return visitSuite(suite_list[i]);
|
||||||
@ -303,7 +305,7 @@ std::any EvalVisitor::visitComparison(Python3Parser::ComparisonContext *ctx) {
|
|||||||
else if (op_list[i]->LT_EQ())
|
else if (op_list[i]->LT_EQ())
|
||||||
ok = LessEqual(last_val, cur);
|
ok = LessEqual(last_val, cur);
|
||||||
else
|
else
|
||||||
throw InterpretException("visitComparison: Unknown operator");
|
throw InterpretException("visitComparison: Unknown operator", 13);
|
||||||
if (!ok) return false;
|
if (!ok) return false;
|
||||||
last_val = cur;
|
last_val = cur;
|
||||||
}
|
}
|
||||||
@ -311,7 +313,7 @@ std::any EvalVisitor::visitComparison(Python3Parser::ComparisonContext *ctx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::any EvalVisitor::visitComp_op(Python3Parser::Comp_opContext *ctx) {
|
std::any EvalVisitor::visitComp_op(Python3Parser::Comp_opContext *ctx) {
|
||||||
throw FatalError("Function visitComp_op Shouldn't be called");
|
throw FatalError("Function visitComp_op Shouldn't be called", 14);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::any EvalVisitor::visitArith_expr(Python3Parser::Arith_exprContext *ctx) {
|
std::any EvalVisitor::visitArith_expr(Python3Parser::Arith_exprContext *ctx) {
|
||||||
@ -328,13 +330,13 @@ std::any EvalVisitor::visitArith_expr(Python3Parser::Arith_exprContext *ctx) {
|
|||||||
else if (op_list[i]->MINUS())
|
else if (op_list[i]->MINUS())
|
||||||
SelfSub(ans, cur);
|
SelfSub(ans, cur);
|
||||||
else
|
else
|
||||||
throw FatalError("visitArith_expr: Unknown operator");
|
throw FatalError("visitArith_expr: Unknown operator", 15);
|
||||||
}
|
}
|
||||||
return ans;
|
return ans;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::any EvalVisitor::visitAddorsub_op(Python3Parser::Addorsub_opContext *ctx) {
|
std::any EvalVisitor::visitAddorsub_op(Python3Parser::Addorsub_opContext *ctx) {
|
||||||
throw FatalError("Function visitAddorsub_op Shouldn't be called");
|
throw FatalError("Function visitAddorsub_op Shouldn't be called", 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::any EvalVisitor::visitTerm(Python3Parser::TermContext *ctx) {
|
std::any EvalVisitor::visitTerm(Python3Parser::TermContext *ctx) {
|
||||||
@ -355,14 +357,14 @@ std::any EvalVisitor::visitTerm(Python3Parser::TermContext *ctx) {
|
|||||||
else if (op_list[i]->MOD())
|
else if (op_list[i]->MOD())
|
||||||
SelfMod(ans, cur);
|
SelfMod(ans, cur);
|
||||||
else
|
else
|
||||||
throw FatalError("visitTerm: Unknown operator");
|
throw FatalError("visitTerm: Unknown operator", 17);
|
||||||
}
|
}
|
||||||
return ans;
|
return ans;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::any EvalVisitor::visitMuldivmod_op(
|
std::any EvalVisitor::visitMuldivmod_op(
|
||||||
Python3Parser::Muldivmod_opContext *ctx) {
|
Python3Parser::Muldivmod_opContext *ctx) {
|
||||||
throw FatalError("Function visitMuldivmod_op Shouldn't be called");
|
throw FatalError("Function visitMuldivmod_op Shouldn't be called", 18);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::any EvalVisitor::visitFactor(Python3Parser::FactorContext *ctx) {
|
std::any EvalVisitor::visitFactor(Python3Parser::FactorContext *ctx) {
|
||||||
@ -399,7 +401,7 @@ std::any EvalVisitor::visitArglist(Python3Parser::ArglistContext *ctx) {
|
|||||||
std::any EvalVisitor::visitArgument(Python3Parser::ArgumentContext *ctx) {
|
std::any EvalVisitor::visitArgument(Python3Parser::ArgumentContext *ctx) {
|
||||||
auto arg_list = ctx->test();
|
auto arg_list = ctx->test();
|
||||||
if (arg_list.size() != 1 && arg_list.size() != 2)
|
if (arg_list.size() != 1 && arg_list.size() != 2)
|
||||||
throw FatalError("visitArgument: arg_list.size()!=1&&arg_list!=2");
|
throw FatalError("visitArgument: arg_list.size()!=1&&arg_list!=2", 19);
|
||||||
if (arg_list.size() == 1)
|
if (arg_list.size() == 1)
|
||||||
return ParaArguItemType("", DeQuate(visitTest(arg_list[0]), Variables));
|
return ParaArguItemType("", DeQuate(visitTest(arg_list[0]), Variables));
|
||||||
else
|
else
|
||||||
|
47
src/main.cpp
47
src/main.cpp
@ -1,34 +1,32 @@
|
|||||||
|
#include <iostream>
|
||||||
|
|
||||||
#include "Evalvisitor.h"
|
#include "Evalvisitor.h"
|
||||||
#include "Python3Lexer.h"
|
#include "Python3Lexer.h"
|
||||||
#include "Python3Parser.h"
|
#include "Python3Parser.h"
|
||||||
#include "antlr4-runtime.h"
|
#include "antlr4-runtime.h"
|
||||||
#include <iostream>
|
|
||||||
#include "clipp/clipp.h"
|
#include "clipp/clipp.h"
|
||||||
using namespace antlr4;
|
using namespace antlr4;
|
||||||
// TODO: regenerating files in directory named "generated" is dangerous.
|
// TODO: regenerating files in directory named "generated" is dangerous.
|
||||||
// if you really need to regenerate,please ask TA for help.
|
// if you really need to regenerate,please ask TA for help.
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[]) {
|
||||||
{
|
// TODO: please don't modify the code below the construction of ifs if you
|
||||||
// TODO: please don't modify the code below the construction of ifs if you want to use visitor mode
|
// want to use visitor mode
|
||||||
std::string input_file;
|
std::string input_file;
|
||||||
bool need_help = false;
|
bool need_help = false;
|
||||||
auto cli = (clipp::option("-h", "--help").set(need_help).doc("show help") |
|
auto cli = (clipp::option("-h", "--help").set(need_help).doc("show help") |
|
||||||
clipp::opt_value("input file", input_file));
|
clipp::opt_value("input file", input_file));
|
||||||
if (!clipp::parse(argc, argv, cli))
|
if (!clipp::parse(argc, argv, cli)) {
|
||||||
{
|
|
||||||
std::cout << clipp::make_man_page(cli, argv[0]);
|
std::cout << clipp::make_man_page(cli, argv[0]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (need_help)
|
if (need_help) {
|
||||||
{
|
|
||||||
std::cout << clipp::make_man_page(cli, argv[0]);
|
std::cout << clipp::make_man_page(cli, argv[0]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
ANTLRInputStream *input_p;
|
ANTLRInputStream *input_p;
|
||||||
if (input_file.length() == 0)
|
if (input_file.length() == 0)
|
||||||
input_p = new ANTLRInputStream(std::cin);
|
input_p = new ANTLRInputStream(std::cin);
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
std::ifstream ifs(input_file);
|
std::ifstream ifs(input_file);
|
||||||
input_p = new ANTLRInputStream(ifs);
|
input_p = new ANTLRInputStream(ifs);
|
||||||
}
|
}
|
||||||
@ -38,25 +36,22 @@ int main(int argc, char *argv[])
|
|||||||
Python3Parser parser(&tokens);
|
Python3Parser parser(&tokens);
|
||||||
tree::ParseTree *tree = parser.file_input();
|
tree::ParseTree *tree = parser.file_input();
|
||||||
EvalVisitor visitor;
|
EvalVisitor visitor;
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
visitor.visit(tree);
|
visitor.visit(tree);
|
||||||
}
|
} catch (const InterpretException &e) {
|
||||||
catch (const InterpretException &e)
|
|
||||||
{
|
|
||||||
std::cerr << "[Interpret Error] " << e.what() << std::endl;
|
std::cerr << "[Interpret Error] " << e.what() << std::endl;
|
||||||
}
|
return e.GetCode();
|
||||||
catch (const FatalError &e)
|
} catch (const FatalError &e) {
|
||||||
{
|
std::cerr << "\e[7m\e[31m[Fatal Error] " << e.what() << "\e[0m"
|
||||||
std::cerr << "\e[7m\e[31m[Fatal Error] " << e.what() << "\e[0m" << std::endl;
|
<< std::endl;
|
||||||
}
|
return e.GetCode();
|
||||||
catch (const std::exception &e)
|
} catch (const std::exception &e) {
|
||||||
{
|
std::cerr << "\e[7m\e[31m[other std::exception] " << e.what() << "\e[0m"
|
||||||
std::cerr << "\e[7m\e[31m[other std::exception] " << e.what() << "\e[0m" << std::endl;
|
<< std::endl;
|
||||||
}
|
return 255;
|
||||||
catch (...)
|
} catch (...) {
|
||||||
{
|
|
||||||
std::cerr << "\e[7m\e[31m[Unknown Exception]\e[0m" << std::endl;
|
std::cerr << "\e[7m\e[31m[Unknown Exception]\e[0m" << std::endl;
|
||||||
|
return 255;
|
||||||
}
|
}
|
||||||
delete input_p;
|
delete input_p;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -6,7 +6,7 @@ inline void VariableContainer::CreateFrame() {
|
|||||||
StackScopes.push(std::unordered_map<std::string, std::any>());
|
StackScopes.push(std::unordered_map<std::string, std::any>());
|
||||||
}
|
}
|
||||||
void VariableContainer::DestroyFrame() {
|
void VariableContainer::DestroyFrame() {
|
||||||
if (StackScopes.empty()) throw FatalError("DestroyFrame: empty stack");
|
if (StackScopes.empty()) throw FatalError("DestroyFrame: empty stack", 20);
|
||||||
StackScopes.pop();
|
StackScopes.pop();
|
||||||
}
|
}
|
||||||
std::any VariableContainer::ReadVariable(const std::string &name) {
|
std::any VariableContainer::ReadVariable(const std::string &name) {
|
||||||
@ -15,7 +15,7 @@ std::any VariableContainer::ReadVariable(const std::string &name) {
|
|||||||
if (top.find(name) != top.end()) return top[name];
|
if (top.find(name) != top.end()) return top[name];
|
||||||
}
|
}
|
||||||
if (GlobalScope.find(name) != GlobalScope.end()) return GlobalScope[name];
|
if (GlobalScope.find(name) != GlobalScope.end()) return GlobalScope[name];
|
||||||
throw InterpretException(("ReadVariable: not found"));
|
throw InterpretException(("ReadVariable: not found"), 21);
|
||||||
}
|
}
|
||||||
void VariableContainer::WriteVariable(const std::string &name,
|
void VariableContainer::WriteVariable(const std::string &name,
|
||||||
const std::any &value, bool cover) {
|
const std::any &value, bool cover) {
|
||||||
@ -41,7 +41,7 @@ void VariableContainer::WriteVariable(const std::string &name,
|
|||||||
void FucntionContainer::AddFunction(const std::string &name,
|
void FucntionContainer::AddFunction(const std::string &name,
|
||||||
const FunctionItem &item) {
|
const FunctionItem &item) {
|
||||||
if (FunctionIndex.find(name) != FunctionIndex.end()) {
|
if (FunctionIndex.find(name) != FunctionIndex.end()) {
|
||||||
throw InterpretException("AddFunction: function already exists");
|
throw InterpretException("AddFunction: function already exists", 22);
|
||||||
}
|
}
|
||||||
FunctionIndex[name] = item;
|
FunctionIndex[name] = item;
|
||||||
}
|
}
|
||||||
@ -66,32 +66,32 @@ std::any FucntionContainer::CallFunction(const std::string &name,
|
|||||||
} else if (name == "str") {
|
} else if (name == "str") {
|
||||||
if (args.size() != 1)
|
if (args.size() != 1)
|
||||||
throw InterpretException(
|
throw InterpretException(
|
||||||
"CallFunction: str() should take exactly one argument");
|
"CallFunction: str() should take exactly one argument", 23);
|
||||||
return Any2String(args[0].value);
|
return Any2String(args[0].value);
|
||||||
} else if (name == "int") {
|
} else if (name == "int") {
|
||||||
if (args.size() == 1) {
|
if (args.size() == 1) {
|
||||||
return Any2Int(args[0].value);
|
return Any2Int(args[0].value);
|
||||||
} else {
|
} else {
|
||||||
throw InterpretException(
|
throw InterpretException(
|
||||||
"CallFunction: int() should take exactly one argument");
|
"CallFunction: int() should take exactly one argument", 24);
|
||||||
}
|
}
|
||||||
} else if (name == "float") {
|
} else if (name == "float") {
|
||||||
if (args.size() == 1) {
|
if (args.size() == 1) {
|
||||||
return Any2Float(args[0].value);
|
return Any2Float(args[0].value);
|
||||||
} else {
|
} else {
|
||||||
throw InterpretException(
|
throw InterpretException(
|
||||||
"CallFunction: float() should take exactly one argument");
|
"CallFunction: float() should take exactly one argument", 25);
|
||||||
}
|
}
|
||||||
} else if (name == "bool") {
|
} else if (name == "bool") {
|
||||||
if (args.size() == 1) {
|
if (args.size() == 1) {
|
||||||
return Any2Bool(args[0].value);
|
return Any2Bool(args[0].value);
|
||||||
} else {
|
} else {
|
||||||
throw InterpretException(
|
throw InterpretException(
|
||||||
"CallFunction: bool() should take exactly one argument");
|
"CallFunction: bool() should take exactly one argument", 26);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (FunctionIndex.find(name) == FunctionIndex.end()) {
|
if (FunctionIndex.find(name) == FunctionIndex.end()) {
|
||||||
throw InterpretException("CallFunction: function not found");
|
throw InterpretException("CallFunction: function not found", 27);
|
||||||
}
|
}
|
||||||
const FunctionItem &func = FunctionIndex[name];
|
const FunctionItem &func = FunctionIndex[name];
|
||||||
std::unordered_set<std::string> args_with_data;
|
std::unordered_set<std::string> args_with_data;
|
||||||
@ -121,7 +121,8 @@ std::any FucntionContainer::CallFunction(const std::string &name,
|
|||||||
i++;
|
i++;
|
||||||
if (i >= func.para_list.size()) break;
|
if (i >= func.para_list.size()) break;
|
||||||
if (!func.para_list[i].value.has_value())
|
if (!func.para_list[i].value.has_value())
|
||||||
throw InterpretException("CallFunction: function parameter not found");
|
throw InterpretException("CallFunction: function parameter not found",
|
||||||
|
28);
|
||||||
Variables.WriteVariable(func.para_list[i].name, func.para_list[i].value,
|
Variables.WriteVariable(func.para_list[i].name, func.para_list[i].value,
|
||||||
true);
|
true);
|
||||||
args_with_data.insert(func.para_list[i].name);
|
args_with_data.insert(func.para_list[i].name);
|
||||||
|
@ -25,7 +25,7 @@ inline ZYM::int2048 Any2Int(const std::any &value) {
|
|||||||
return std::move(ZYM::int2048(0));
|
return std::move(ZYM::int2048(0));
|
||||||
else {
|
else {
|
||||||
std::cerr << value.type().name() << std::endl;
|
std::cerr << value.type().name() << std::endl;
|
||||||
throw FatalError("Any2Int2048: unknown type");
|
throw FatalError("Any2Int2048: unknown type", 29);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,7 +48,7 @@ double Any2Float(const std::any &value) {
|
|||||||
else if (auto ptr = std::any_cast<std::string>(&value))
|
else if (auto ptr = std::any_cast<std::string>(&value))
|
||||||
return std::stod(*ptr);
|
return std::stod(*ptr);
|
||||||
else
|
else
|
||||||
throw FatalError("Any2Float: unknown type");
|
throw FatalError("Any2Float: unknown type", 30);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Any2String(const std::any &value) {
|
std::string Any2String(const std::any &value) {
|
||||||
@ -68,7 +68,7 @@ std::string Any2String(const std::any &value) {
|
|||||||
else if (auto ptr = std::any_cast<NoneType>(&value))
|
else if (auto ptr = std::any_cast<NoneType>(&value))
|
||||||
buf << "None";
|
buf << "None";
|
||||||
else
|
else
|
||||||
throw FatalError("Any2String: unknown type");
|
throw FatalError("Any2String: unknown type", 31);
|
||||||
std::getline(buf, res);
|
std::getline(buf, res);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@ -83,7 +83,7 @@ bool Any2Bool(const std::any &value) {
|
|||||||
} else if (auto ptr = std::any_cast<std::string>(&value)) {
|
} else if (auto ptr = std::any_cast<std::string>(&value)) {
|
||||||
return (*ptr) != "";
|
return (*ptr) != "";
|
||||||
} else
|
} else
|
||||||
throw FatalError("Any2Bool: unknown type");
|
throw FatalError("Any2Bool: unknown type", 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::any DeQuate(std::any val, VariableContainer &Variables) {
|
std::any DeQuate(std::any val, VariableContainer &Variables) {
|
||||||
@ -115,16 +115,19 @@ int ConverToSameArithType(std::any &a, std::any &b,
|
|||||||
if ((!allow_string_operation) && (ptr_a_string || ptr_b_string))
|
if ((!allow_string_operation) && (ptr_a_string || ptr_b_string))
|
||||||
throw InterpretException(
|
throw InterpretException(
|
||||||
"ConverToSameArithType: string operation not allowed in this "
|
"ConverToSameArithType: string operation not allowed in this "
|
||||||
"situation");
|
"situation",
|
||||||
|
33);
|
||||||
if (allow_string_operation && (ptr_a_string || ptr_b_string)) {
|
if (allow_string_operation && (ptr_a_string || ptr_b_string)) {
|
||||||
if (!(ptr_a_string || ptr_a_int2048))
|
if (!(ptr_a_string || ptr_a_int2048))
|
||||||
throw InterpretException(
|
throw InterpretException(
|
||||||
"ConverToSameArithType: string operation not allowed in this "
|
"ConverToSameArithType: string operation not allowed in this "
|
||||||
"situation");
|
"situation",
|
||||||
|
34);
|
||||||
if (!(ptr_b_string || ptr_b_int2048))
|
if (!(ptr_b_string || ptr_b_int2048))
|
||||||
throw InterpretException(
|
throw InterpretException(
|
||||||
"ConverToSameArithType: string operation not allowed in this "
|
"ConverToSameArithType: string operation not allowed in this "
|
||||||
"situation");
|
"situation",
|
||||||
|
35);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
int level_a = (ptr_a_bool != nullptr ? 1 : 0) +
|
int level_a = (ptr_a_bool != nullptr ? 1 : 0) +
|
||||||
@ -146,7 +149,7 @@ int ConverToSameArithType(std::any &a, std::any &b,
|
|||||||
b = Any2Float(b);
|
b = Any2Float(b);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw FatalError("ConverToSameArithType: unknown type");
|
throw FatalError("ConverToSameArithType: unknown type", 36);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -164,7 +167,7 @@ std::any Add(std::any a, std::any b) {
|
|||||||
if ((ptr_a_string != nullptr ? 1 : 0) + (ptr_b_string != nullptr ? 1 : 0) ==
|
if ((ptr_a_string != nullptr ? 1 : 0) + (ptr_b_string != nullptr ? 1 : 0) ==
|
||||||
1) {
|
1) {
|
||||||
throw InterpretException(
|
throw InterpretException(
|
||||||
"Add: string operation not allowed in this situation");
|
"Add: string operation not allowed in this situation", 37);
|
||||||
}
|
}
|
||||||
if ((ptr_a_string != nullptr ? 1 : 0) + (ptr_b_string != nullptr ? 1 : 0) ==
|
if ((ptr_a_string != nullptr ? 1 : 0) + (ptr_b_string != nullptr ? 1 : 0) ==
|
||||||
2)
|
2)
|
||||||
@ -176,7 +179,7 @@ std::any Add(std::any a, std::any b) {
|
|||||||
else if ((ptr_a_float != nullptr) && (ptr_b_float != nullptr))
|
else if ((ptr_a_float != nullptr) && (ptr_b_float != nullptr))
|
||||||
return (*ptr_a_float) + (*ptr_b_float);
|
return (*ptr_a_float) + (*ptr_b_float);
|
||||||
else
|
else
|
||||||
throw FatalError("Add: Type Error");
|
throw FatalError("Add: Type Error", 38);
|
||||||
}
|
}
|
||||||
std::any Sub(std::any a, std::any b) {
|
std::any Sub(std::any a, std::any b) {
|
||||||
ConverToSameArithType(a, b);
|
ConverToSameArithType(a, b);
|
||||||
@ -193,7 +196,7 @@ std::any Sub(std::any a, std::any b) {
|
|||||||
else if ((ptr_a_float != nullptr) && (ptr_b_float != nullptr))
|
else if ((ptr_a_float != nullptr) && (ptr_b_float != nullptr))
|
||||||
return (*ptr_a_float) - (*ptr_b_float);
|
return (*ptr_a_float) - (*ptr_b_float);
|
||||||
else
|
else
|
||||||
throw FatalError("Sub: Type Error");
|
throw FatalError("Sub: Type Error", 39);
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
std::any Mul(std::any a, std::any b) {
|
std::any Mul(std::any a, std::any b) {
|
||||||
@ -209,7 +212,7 @@ std::any Mul(std::any a, std::any b) {
|
|||||||
if ((ptr_a_string != nullptr ? 1 : 0) + (ptr_b_string != nullptr ? 1 : 0) ==
|
if ((ptr_a_string != nullptr ? 1 : 0) + (ptr_b_string != nullptr ? 1 : 0) ==
|
||||||
2) {
|
2) {
|
||||||
throw InterpretException(
|
throw InterpretException(
|
||||||
"Mul: string operation not allowed in this situation");
|
"Mul: string operation not allowed in this situation", 40);
|
||||||
} else if ((ptr_a_string != nullptr ? 1 : 0) +
|
} else if ((ptr_a_string != nullptr ? 1 : 0) +
|
||||||
(ptr_b_string != nullptr ? 1 : 0) ==
|
(ptr_b_string != nullptr ? 1 : 0) ==
|
||||||
1) {
|
1) {
|
||||||
@ -220,7 +223,7 @@ std::any Mul(std::any a, std::any b) {
|
|||||||
std::swap(ptr_a_float, ptr_b_float);
|
std::swap(ptr_a_float, ptr_b_float);
|
||||||
}
|
}
|
||||||
if (ptr_b_float != nullptr)
|
if (ptr_b_float != nullptr)
|
||||||
throw InterpretException("Mul: string*float not allowed");
|
throw InterpretException("Mul: string*float not allowed", 41);
|
||||||
if (ptr_b_bool != nullptr) {
|
if (ptr_b_bool != nullptr) {
|
||||||
if (*ptr_b_bool) {
|
if (*ptr_b_bool) {
|
||||||
return *ptr_a_string;
|
return *ptr_a_string;
|
||||||
@ -241,7 +244,7 @@ std::any Mul(std::any a, std::any b) {
|
|||||||
else if ((ptr_a_float != nullptr) && (ptr_b_float != nullptr))
|
else if ((ptr_a_float != nullptr) && (ptr_b_float != nullptr))
|
||||||
return (*ptr_a_float) * (*ptr_b_float);
|
return (*ptr_a_float) * (*ptr_b_float);
|
||||||
else
|
else
|
||||||
throw FatalError("Mul: Type Error");
|
throw FatalError("Mul: Type Error", 42);
|
||||||
}
|
}
|
||||||
std::any Div(std::any a, std::any b) {
|
std::any Div(std::any a, std::any b) {
|
||||||
bool *ptr_a_bool = std::any_cast<bool>(&a);
|
bool *ptr_a_bool = std::any_cast<bool>(&a);
|
||||||
@ -254,10 +257,10 @@ std::any Div(std::any a, std::any b) {
|
|||||||
std::string *ptr_b_string = std::any_cast<std::string>(&b);
|
std::string *ptr_b_string = std::any_cast<std::string>(&b);
|
||||||
if ((ptr_a_string != nullptr) || (ptr_b_string != nullptr))
|
if ((ptr_a_string != nullptr) || (ptr_b_string != nullptr))
|
||||||
throw InterpretException(
|
throw InterpretException(
|
||||||
"Div: string operation not allowed in this situation");
|
"Div: string operation not allowed in this situation", 43);
|
||||||
double t_a = Any2Float(a);
|
double t_a = Any2Float(a);
|
||||||
double t_b = Any2Float(b);
|
double t_b = Any2Float(b);
|
||||||
if (t_b == 0) throw InterpretException("Div: divided by zero");
|
if (t_b == 0) throw InterpretException("Div: divided by zero", 44);
|
||||||
t_a = t_a / t_b;
|
t_a = t_a / t_b;
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
@ -270,17 +273,19 @@ std::any Divv(std::any a, std::any b) {
|
|||||||
double *ptr_a_float = std::any_cast<double>(&a);
|
double *ptr_a_float = std::any_cast<double>(&a);
|
||||||
double *ptr_b_float = std::any_cast<double>(&b);
|
double *ptr_b_float = std::any_cast<double>(&b);
|
||||||
if ((ptr_a_float != nullptr) && (ptr_b_float != nullptr)) {
|
if ((ptr_a_float != nullptr) && (ptr_b_float != nullptr)) {
|
||||||
if ((*ptr_b_float) == 0) throw InterpretException("Divv: divided by zero");
|
if ((*ptr_b_float) == 0)
|
||||||
|
throw InterpretException("Divv: divided by zero", 45);
|
||||||
return ZYM::int2048(std::floor((*ptr_a_float) / (*ptr_b_float)));
|
return ZYM::int2048(std::floor((*ptr_a_float) / (*ptr_b_float)));
|
||||||
} else if ((ptr_a_int2048 != nullptr) && (ptr_b_int2048 != nullptr)) {
|
} else if ((ptr_a_int2048 != nullptr) && (ptr_b_int2048 != nullptr)) {
|
||||||
if ((*ptr_b_int2048) == 0)
|
if ((*ptr_b_int2048) == 0)
|
||||||
throw InterpretException("Divv: divided by zero");
|
throw InterpretException("Divv: divided by zero", 46);
|
||||||
return (*ptr_a_int2048) / (*ptr_b_int2048);
|
return (*ptr_a_int2048) / (*ptr_b_int2048);
|
||||||
} else if ((ptr_a_bool != nullptr) && (ptr_b_bool != nullptr)) {
|
} else if ((ptr_a_bool != nullptr) && (ptr_b_bool != nullptr)) {
|
||||||
if ((*ptr_b_bool) == 0) throw InterpretException("Divv: divided by zero");
|
if ((*ptr_b_bool) == 0)
|
||||||
|
throw InterpretException("Divv: divided by zero", 47);
|
||||||
return ZYM::int2048((*ptr_a_bool) / (*ptr_b_bool));
|
return ZYM::int2048((*ptr_a_bool) / (*ptr_b_bool));
|
||||||
} else
|
} else
|
||||||
throw FatalError("Divv: Type Error");
|
throw FatalError("Divv: Type Error", 48);
|
||||||
}
|
}
|
||||||
std::any Mod(std::any a, std::any b) {
|
std::any Mod(std::any a, std::any b) {
|
||||||
ConverToSameArithType(a, b);
|
ConverToSameArithType(a, b);
|
||||||
@ -291,18 +296,21 @@ std::any Mod(std::any a, std::any b) {
|
|||||||
double *ptr_a_float = std::any_cast<double>(&a);
|
double *ptr_a_float = std::any_cast<double>(&a);
|
||||||
double *ptr_b_float = std::any_cast<double>(&b);
|
double *ptr_b_float = std::any_cast<double>(&b);
|
||||||
if ((ptr_a_float != nullptr) && (ptr_b_float != nullptr)) {
|
if ((ptr_a_float != nullptr) && (ptr_b_float != nullptr)) {
|
||||||
if ((*ptr_b_float) == 0) throw InterpretException("Mod: divided by zero");
|
if ((*ptr_b_float) == 0)
|
||||||
|
throw InterpretException("Mod: divided by zero", 49);
|
||||||
return ZYM::int2048((*ptr_a_float) -
|
return ZYM::int2048((*ptr_a_float) -
|
||||||
(*ptr_b_float) *
|
(*ptr_b_float) *
|
||||||
std::floor((*ptr_a_float) / (*ptr_b_float)));
|
std::floor((*ptr_a_float) / (*ptr_b_float)));
|
||||||
} else if ((ptr_a_int2048 != nullptr) && (ptr_b_int2048 != nullptr)) {
|
} else if ((ptr_a_int2048 != nullptr) && (ptr_b_int2048 != nullptr)) {
|
||||||
if ((*ptr_b_int2048) == 0) throw InterpretException("Mod: divided by zero");
|
if ((*ptr_b_int2048) == 0)
|
||||||
|
throw InterpretException("Mod: divided by zero", 50);
|
||||||
return (*ptr_a_int2048) % (*ptr_b_int2048);
|
return (*ptr_a_int2048) % (*ptr_b_int2048);
|
||||||
} else if ((ptr_a_bool != nullptr) && (ptr_b_bool != nullptr)) {
|
} else if ((ptr_a_bool != nullptr) && (ptr_b_bool != nullptr)) {
|
||||||
if ((*ptr_b_bool) == 0) throw InterpretException("Mod: divided by zero");
|
if ((*ptr_b_bool) == 0)
|
||||||
|
throw InterpretException("Mod: divided by zero", 51);
|
||||||
return ZYM::int2048((*ptr_a_bool) % (*ptr_b_bool));
|
return ZYM::int2048((*ptr_a_bool) % (*ptr_b_bool));
|
||||||
} else
|
} else
|
||||||
throw FatalError("Mod: Type Error");
|
throw FatalError("Mod: Type Error", 52);
|
||||||
}
|
}
|
||||||
std::any &SelfAdd(std::any &a, std::any b) {
|
std::any &SelfAdd(std::any &a, std::any b) {
|
||||||
a = Add(a, b);
|
a = Add(a, b);
|
||||||
@ -339,7 +347,7 @@ std::any Neg(std::any a) {
|
|||||||
else if (ptr_a_float != nullptr)
|
else if (ptr_a_float != nullptr)
|
||||||
return -(*ptr_a_float);
|
return -(*ptr_a_float);
|
||||||
else
|
else
|
||||||
throw FatalError("Neg: Type Error");
|
throw FatalError("Neg: Type Error", 53);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Greater(std::any a, std::any b) {
|
bool Greater(std::any a, std::any b) {
|
||||||
@ -361,7 +369,7 @@ bool Greater(std::any a, std::any b) {
|
|||||||
else if ((ptr_a_string != nullptr) && (ptr_b_string != nullptr))
|
else if ((ptr_a_string != nullptr) && (ptr_b_string != nullptr))
|
||||||
return (*ptr_a_string) > (*ptr_b_string);
|
return (*ptr_a_string) > (*ptr_b_string);
|
||||||
else
|
else
|
||||||
throw FatalError("Greater: Type Error");
|
throw FatalError("Greater: Type Error", 54);
|
||||||
}
|
}
|
||||||
bool Less(std::any a, std::any b) {
|
bool Less(std::any a, std::any b) {
|
||||||
ConverToSameArithType(a, b, true);
|
ConverToSameArithType(a, b, true);
|
||||||
@ -382,7 +390,7 @@ bool Less(std::any a, std::any b) {
|
|||||||
else if ((ptr_a_string != nullptr) && (ptr_b_string != nullptr))
|
else if ((ptr_a_string != nullptr) && (ptr_b_string != nullptr))
|
||||||
return (*ptr_a_string) < (*ptr_b_string);
|
return (*ptr_a_string) < (*ptr_b_string);
|
||||||
else
|
else
|
||||||
throw FatalError("Less: Type Error");
|
throw FatalError("Less: Type Error", 55);
|
||||||
}
|
}
|
||||||
bool Equal(std::any a, std::any b) {
|
bool Equal(std::any a, std::any b) {
|
||||||
ConverToSameArithType(a, b, true);
|
ConverToSameArithType(a, b, true);
|
||||||
@ -403,7 +411,7 @@ bool Equal(std::any a, std::any b) {
|
|||||||
else if ((ptr_a_string != nullptr) && (ptr_b_string != nullptr))
|
else if ((ptr_a_string != nullptr) && (ptr_b_string != nullptr))
|
||||||
return (*ptr_a_string) == (*ptr_b_string);
|
return (*ptr_a_string) == (*ptr_b_string);
|
||||||
else
|
else
|
||||||
throw FatalError("Equal: Type Error");
|
throw FatalError("Equal: Type Error", 56);
|
||||||
}
|
}
|
||||||
bool NotEqual(std::any a, std::any b) {
|
bool NotEqual(std::any a, std::any b) {
|
||||||
ConverToSameArithType(a, b, true);
|
ConverToSameArithType(a, b, true);
|
||||||
@ -424,7 +432,7 @@ bool NotEqual(std::any a, std::any b) {
|
|||||||
else if ((ptr_a_string != nullptr) && (ptr_b_string != nullptr))
|
else if ((ptr_a_string != nullptr) && (ptr_b_string != nullptr))
|
||||||
return (*ptr_a_string) != (*ptr_b_string);
|
return (*ptr_a_string) != (*ptr_b_string);
|
||||||
else
|
else
|
||||||
throw FatalError("NotEqual: Type Error");
|
throw FatalError("NotEqual: Type Error", 57);
|
||||||
}
|
}
|
||||||
bool GreaterEqual(std::any a, std::any b) {
|
bool GreaterEqual(std::any a, std::any b) {
|
||||||
ConverToSameArithType(a, b, true);
|
ConverToSameArithType(a, b, true);
|
||||||
@ -445,7 +453,7 @@ bool GreaterEqual(std::any a, std::any b) {
|
|||||||
else if ((ptr_a_string != nullptr) && (ptr_b_string != nullptr))
|
else if ((ptr_a_string != nullptr) && (ptr_b_string != nullptr))
|
||||||
return (*ptr_a_string) >= (*ptr_b_string);
|
return (*ptr_a_string) >= (*ptr_b_string);
|
||||||
else
|
else
|
||||||
throw FatalError("GreaterEqual: Type Error");
|
throw FatalError("GreaterEqual: Type Error", 58);
|
||||||
}
|
}
|
||||||
bool LessEqual(std::any a, std::any b) {
|
bool LessEqual(std::any a, std::any b) {
|
||||||
ConverToSameArithType(a, b, true);
|
ConverToSameArithType(a, b, true);
|
||||||
@ -466,5 +474,5 @@ bool LessEqual(std::any a, std::any b) {
|
|||||||
else if ((ptr_a_string != nullptr) && (ptr_b_string != nullptr))
|
else if ((ptr_a_string != nullptr) && (ptr_b_string != nullptr))
|
||||||
return (*ptr_a_string) <= (*ptr_b_string);
|
return (*ptr_a_string) <= (*ptr_b_string);
|
||||||
else
|
else
|
||||||
throw FatalError("LessEqual: Type Error");
|
throw FatalError("LessEqual: Type Error", 59);
|
||||||
}
|
}
|
Reference in New Issue
Block a user