145 lines
4.9 KiB
C++
145 lines
4.9 KiB
C++
#include "names.h"
|
|
|
|
#include "utils.h"
|
|
|
|
inline void VariableContainer::CreateFrame() {
|
|
StackScopes.push(std::unordered_map<std::string, std::any>());
|
|
}
|
|
void VariableContainer::DestroyFrame() {
|
|
if (StackScopes.empty()) throw FatalError("DestroyFrame: empty stack", 20);
|
|
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"), 21);
|
|
}
|
|
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", 22);
|
|
}
|
|
FunctionIndex[name] = item;
|
|
}
|
|
|
|
std::any FucntionContainer::CallFunction(const std::string &name,
|
|
std::vector<ParaArguItemType> &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;
|
|
double *value_ptr = std::any_cast<double>(&args[i].value);
|
|
if (!value_ptr) {
|
|
std::string buf = std::move(Any2String(args[i].value));
|
|
std::cout << buf;
|
|
} else
|
|
std::cout << std::fixed << std::setprecision(6) << *value_ptr;
|
|
}
|
|
std::cout << '\n';
|
|
return NoneType();
|
|
} else if (name == "str") {
|
|
if (args.size() != 1)
|
|
throw InterpretException(
|
|
"CallFunction: str() should take exactly one argument", 23);
|
|
return std::move(Any2String(args[0].value));
|
|
} else if (name == "int") {
|
|
if (args.size() == 1) {
|
|
return std::move(Any2Int(args[0].value));
|
|
} else {
|
|
throw InterpretException(
|
|
"CallFunction: int() should take exactly one argument", 24);
|
|
}
|
|
} else if (name == "float") {
|
|
if (args.size() == 1) {
|
|
return Any2Float(args[0].value);
|
|
} else {
|
|
throw InterpretException(
|
|
"CallFunction: float() should take exactly one argument", 25);
|
|
}
|
|
} else if (name == "bool") {
|
|
if (args.size() == 1) {
|
|
return Any2Bool(args[0].value);
|
|
} else {
|
|
throw InterpretException(
|
|
"CallFunction: bool() should take exactly one argument", 26);
|
|
}
|
|
}
|
|
if (FunctionIndex.find(name) == FunctionIndex.end()) {
|
|
throw InterpretException("CallFunction: function not found", 27);
|
|
}
|
|
const FunctionItem &func = FunctionIndex[name];
|
|
std::unordered_set<std::string> 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",
|
|
28);
|
|
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 = std::move(vis.visit(func.code_address));
|
|
Variables.DestroyFrame();
|
|
// std::cerr << "function called " << std::endl;
|
|
FlowType *flow = std::any_cast<FlowType>(&res);
|
|
if (flow) {
|
|
if (flow->ReturnValueLists.size() == 0)
|
|
return NoneType();
|
|
else if (flow->ReturnValueLists.size() == 1)
|
|
return std::move(flow->ReturnValueLists[0]);
|
|
else
|
|
return std::move(flow->ReturnValueLists);
|
|
}
|
|
// std::cerr<<"Return value isn't FlowType"<<std::endl;
|
|
return NoneType();
|
|
} |