From 5ad5615586db4ee2e44d449b3f5aefa6ae0cf091 Mon Sep 17 00:00:00 2001 From: ZhuangYumin Date: Thu, 9 Nov 2023 17:28:41 +0800 Subject: [PATCH] upd: first version of function call --- include/names.h | 1 + include/utils.h | 21 ++++++----- src/Evalvisitor.cpp | 2 +- src/names.cpp | 89 +++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 100 insertions(+), 13 deletions(-) diff --git a/include/names.h b/include/names.h index 57c6531..398db0a 100644 --- a/include/names.h +++ b/include/names.h @@ -5,6 +5,7 @@ #include #include #include +#include #include #include "utils.h" diff --git a/include/utils.h b/include/utils.h index 4f62cd5..ec19f01 100644 --- a/include/utils.h +++ b/include/utils.h @@ -8,6 +8,7 @@ #include #include +#include "Evalvisitor.h" #include "Python3ParserBaseVisitor.h" #include "int2048/int2048.h" class InterpretException : public std::exception { @@ -71,14 +72,6 @@ struct FunctionItem { const std::vector ¶_list) : code_address(code_address), para_list(para_list) {} }; -class FucntionContainer { - std::unordered_map FunctionIndex; - - public: - void AddFunction(const std::string &name, const FunctionItem &item); - std::any CallFunction(const std::string &name, - const std::vector &args); -}; class VariableContainer { std::unordered_map GlobalScope; std::stack> StackScopes; @@ -87,7 +80,17 @@ class VariableContainer { void CreateFrame(); void DestroyFrame(); std::any ReadVariable(const std::string &name); - void WriteVariable(const std::string &name, const std::any &value); + void WriteVariable(const std::string &name, const std::any &value, + bool cover = false); +}; +class FucntionContainer { + std::unordered_map FunctionIndex; + + public: + void AddFunction(const std::string &name, const FunctionItem &item); + std::any CallFunction(const std::string &name, + const std::vector &args, + VariableContainer &Varables); }; std::any DeQuate(std::any val, VariableContainer &Variables); diff --git a/src/Evalvisitor.cpp b/src/Evalvisitor.cpp index 8047532..5abbeeb 100644 --- a/src/Evalvisitor.cpp +++ b/src/Evalvisitor.cpp @@ -347,7 +347,7 @@ std::any EvalVisitor::visitAtom_expr(Python3Parser::Atom_exprContext *ctx) { std::vector args = std::any_cast>( visitTrailer(ctx->trailer())); - return Functions.CallFunction(func_name, args); + return Functions.CallFunction(func_name, args, Variables); } std::any EvalVisitor::visitTrailer(Python3Parser::TrailerContext *ctx) { diff --git a/src/names.cpp b/src/names.cpp index 1cbc786..06c1210 100644 --- a/src/names.cpp +++ b/src/names.cpp @@ -18,7 +18,7 @@ std::any VariableContainer::ReadVariable(const std::string &name) { throw InterpretException(("ReadVariable: " + name + " not found").c_str()); } void VariableContainer::WriteVariable(const std::string &name, - const std::any &value) { + const std::any &value, bool cover) { if (StackScopes.empty()) { GlobalScope[name] = value; return; @@ -28,6 +28,10 @@ void VariableContainer::WriteVariable(const std::string &name, top[name] = value; return; } + if (cover) { + top[name] = value; + return; + } if (GlobalScope.find(name) != GlobalScope.end()) { GlobalScope[name] = value; return; @@ -43,9 +47,88 @@ void FucntionContainer::AddFunction(const std::string &name, } std::any FucntionContainer::CallFunction( - const std::string &name, const std::vector &args) { + const std::string &name, const std::vector &args, + VariableContainer &Variables) { + if (name == "print") { + bool is_first = true; + for (int i = 0; i < args.size(); i++) { + if (is_first) std::cout << ' '; + is_first = false; + std::string buf = Any2String(args[i].value); + std::cout << buf; + } + std::cout << '\n'; + return nullptr; + } else if (name == "str") { + if (args.size() != 1) + throw InterpretException( + "CallFunction: str() should take exactly one argument"); + return Any2String(args[0].value); + } else if (name == "int") { + if (args.size() == 1) { + return Any2Int(args[0].value); + } else { + throw InterpretException( + "CallFunction: int() should take exactly one argument"); + } + } else if (name == "float") { + if (args.size() == 1) { + return Any2Float(args[0].value); + } else { + throw InterpretException( + "CallFunction: float() should take exactly one argument"); + } + } else if (name == "bool") { + if (args.size() == 1) { + return Any2Bool(args[0].value); + } else { + throw InterpretException( + "CallFunction: bool() should take exactly one argument"); + } + } if (FunctionIndex.find(name) == FunctionIndex.end()) { throw InterpretException("CallFunction: function not found"); } - // TODO + const FunctionItem &func = FunctionIndex[name]; + std::unordered_set args_with_data; + Variables.CreateFrame(); + for (int i = 0; i < args.size(); i++) + if (args[i].name != "") { + Variables.WriteVariable(args[i].name, args[i].value, true); + args_with_data.insert(args[i].name); + } + int p_src = 0; + for (int i = 0; i < func.para_list.size(); i++) { + while (p_src < args.size() && + args_with_data.find(args[p_src].name) != args_with_data.end()) + p_src++; + if (p_src >= args.size()) break; + while (i < func.para_list.size() && + args_with_data.find(func.para_list[i].name) != args_with_data.end()) + i++; + if (i >= func.para_list.size()) break; + Variables.WriteVariable(func.para_list[i].name, args[p_src].value, true); + args_with_data.insert(func.para_list[i].name); + } + for (int i = 0; i < func.para_list.size(); i++) { + while (i < func.para_list.size() && + args_with_data.find(func.para_list[i].name) != args_with_data.end()) + i++; + if (i >= func.para_list.size()) break; + if (!func.para_list[i].value.has_value()) + throw InterpretException("CallFunction: function parameter not found"); + Variables.WriteVariable(func.para_list[i].name, func.para_list[i].value, + true); + args_with_data.insert(func.para_list[i].name); + } + EvalVisitor vis; + std::any res = vis.visit(func.code_address); + Variables.DestroyFrame(); + FlowType *flow = std::any_cast(&res); + if(!flow) + { + if(flow->ReturnValueLists.size()==1) return flow->ReturnValueLists[0]; + else return flow->ReturnValueLists; + } + return NoneType(); } \ No newline at end of file