#include "names.h" #include "utils.h" inline void VariableContainer::CreateFrame() { StackScopes.push(std::unordered_map()); } void VariableContainer::DestroyFrame() { if (StackScopes.empty()) throw FatalError("DestroyFrame: empty stack"); StackScopes.pop(); } std::any VariableContainer::ReadVariable(const std::string &name) { if (StackScopes.size()) { auto &top = StackScopes.top(); if (top.find(name) != top.end()) return top[name]; } if (GlobalScope.find(name) != GlobalScope.end()) return GlobalScope[name]; throw InterpretException(("ReadVariable: not found")); } void VariableContainer::WriteVariable(const std::string &name, const std::any &value, bool cover) { if (StackScopes.empty()) { GlobalScope[name] = value; return; } auto &top = StackScopes.top(); if (top.find(name) != top.end()) { top[name] = value; return; } if (cover) { top[name] = value; return; } if (GlobalScope.find(name) != GlobalScope.end()) { GlobalScope[name] = value; return; } top[name] = value; } void FucntionContainer::AddFunction(const std::string &name, const FunctionItem &item) { if (FunctionIndex.find(name) != FunctionIndex.end()) { throw InterpretException("AddFunction: function already exists"); } FunctionIndex[name] = item; } std::any FucntionContainer::CallFunction( 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"); } 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); p_src++; } 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(); // std::cerr << "function called " << std::endl; FlowType *flow = std::any_cast(&res); if (flow) { if (flow->ReturnValueLists.size() == 0) return NoneType(); else if (flow->ReturnValueLists.size() == 1) return flow->ReturnValueLists[0]; else return flow->ReturnValueLists; } // std::cerr<<"Return value isn't FlowType"<