|
#include "UserScript.h"
|
|
#include <algorithm>
|
|
#include <span>
|
|
#include <utility>
|
|
#include "UserScriptWizardry.h"
|
|
#include "UserScriptRequire.h"
|
|
|
|
using interpreter = decltype(scripting::prepare_interpreter({}));
|
|
using namespace scripting;
|
|
|
|
namespace scripting {
|
|
|
|
struct fn_identity : public scripting::function_impl {
|
|
std::optional<scripting::script_value> apply(scripting::UserScript* self,std::vector<scripting::argument> args, std::optional<scripting::script_error>& errors) final {
|
|
// TODO: use the requirement sets here
|
|
if(args.size() != 1) {
|
|
errors = scripting::script_error{.message = "identity expects a single argument"};
|
|
} else {
|
|
if(std::holds_alternative<scripting::script_value>(args.front())) {
|
|
return std::get<scripting::script_value>(args.front());
|
|
} else {
|
|
return self->resolve(std::get<scripting::script_variable>(args.front()).name);
|
|
}
|
|
}
|
|
return scripting::script_value({});
|
|
}
|
|
};
|
|
|
|
struct fn_var_clear : public scripting::function_impl {
|
|
std::optional<scripting::script_value> apply(scripting::UserScript* self,std::vector<scripting::argument> args, std::optional<scripting::script_error>& errors) final {
|
|
using verifier = Verify<
|
|
details::SizeEquals<0>
|
|
>;
|
|
|
|
if(not verifier{}.verify(self, args)) {
|
|
errors = scripting::script_error{.message = "var_clear argument error"};
|
|
} else {
|
|
self->clear_variables();
|
|
}
|
|
return scripting::script_value({});
|
|
}
|
|
};
|
|
|
|
struct fn_var_name : public scripting::function_impl {
|
|
std::optional<scripting::script_value> apply(scripting::UserScript* self,std::vector<scripting::argument> args, std::optional<scripting::script_error>& errors) final {
|
|
using verifier = Verify<
|
|
details::SizeEquals<1>,
|
|
details::TypeVerifier<0, int32_t>
|
|
>;
|
|
|
|
if(not verifier{}.verify(self, args)) {
|
|
errors = scripting::script_error{.message = "var_name argument error"};
|
|
} else {
|
|
int32_t idx = 0;
|
|
|
|
if(std::holds_alternative<scripting::script_value>(args.front())) {
|
|
idx = std::get<int32_t>(std::get<scripting::script_value>(args.front()));
|
|
} else {
|
|
idx = std::get<int32_t>(self->resolve(std::get<scripting::script_variable>(args.front()).name));
|
|
}
|
|
|
|
if(auto val = self->varname_by_idx(idx); val) return val;
|
|
}
|
|
return scripting::script_value({});
|
|
}
|
|
};
|
|
|
|
struct fn_var_count : public scripting::function_impl {
|
|
std::optional<scripting::script_value> apply(scripting::UserScript* self,std::vector<scripting::argument> args, std::optional<scripting::script_error>& errors) final {
|
|
using verifier = Verify<
|
|
details::SizeEquals<0>
|
|
>;
|
|
|
|
if(not verifier{}.verify(self, args)) {
|
|
errors = scripting::script_error{.message = "var_count argument error"};
|
|
} else {
|
|
return self->var_count();
|
|
}
|
|
return scripting::script_value({});
|
|
}
|
|
};
|
|
|
|
struct fn_null : public scripting::function_impl {
|
|
std::optional<scripting::script_value> apply(scripting::UserScript* self,std::vector<scripting::argument> args, std::optional<scripting::script_error>& errors) final {
|
|
using verifier = Verify<
|
|
details::SizeEquals<0>
|
|
>;
|
|
|
|
if(not verifier{}.verify(self, args)) {
|
|
errors = scripting::script_error{.message = "null argument error"};
|
|
}
|
|
return scripting::script_value({});
|
|
}
|
|
};
|
|
|
|
struct fn_var_cap : public scripting::function_impl {
|
|
int32_t var_cap;
|
|
|
|
explicit fn_var_cap(int32_t _var_cap)
|
|
: var_cap(_var_cap) {}
|
|
|
|
std::optional<scripting::script_value> apply(scripting::UserScript* self,std::vector<scripting::argument> args, std::optional<scripting::script_error>& errors) final {
|
|
using verifier = Verify<
|
|
details::SizeEquals<0>
|
|
>;
|
|
|
|
if(not verifier{}.verify(self, args)) {
|
|
errors = scripting::script_error{.message = "var_cap argument error"};
|
|
return scripting::script_value({});
|
|
}
|
|
return var_cap;
|
|
}
|
|
};
|
|
|
|
struct fn_var_type : public scripting::function_impl {
|
|
std::optional<scripting::script_value> apply(scripting::UserScript* self,std::vector<scripting::argument> args, std::optional<scripting::script_error>& errors) final {
|
|
using verifier = Verify<
|
|
details::SizeEquals<1>
|
|
>;
|
|
|
|
if(not verifier{}.verify(self, args)) {
|
|
errors = scripting::script_error{.message = "var_type argument error"};
|
|
} else {
|
|
script_value var;
|
|
|
|
if(std::holds_alternative<scripting::script_value>(args.front())) {
|
|
var = std::get<scripting::script_value>(args.front());
|
|
} else {
|
|
var = self->resolve(std::get<scripting::script_variable>(args.front()).name);
|
|
}
|
|
return std::visit(
|
|
wizardry::overloaded{
|
|
[](int32_t&) {return "integer";},
|
|
[](array&) {return "array";},
|
|
[](null&) {return "null";},
|
|
[](std::string&) {return "string";}
|
|
},
|
|
var
|
|
);
|
|
}
|
|
return scripting::script_value({});
|
|
}
|
|
};
|
|
|
|
struct fn_var_dump : public scripting::function_impl {
|
|
std::optional<scripting::script_value> apply(scripting::UserScript* self,std::vector<scripting::argument> args, std::optional<scripting::script_error>& errors) final {
|
|
using verifier = Verify<
|
|
details::SizeEquals<1>,
|
|
details::TypeVerifier<0, int32_t>
|
|
>;
|
|
|
|
if(not verifier{}.verify(self, args)) {
|
|
errors = scripting::script_error{.message = "var_dump argument error"};
|
|
} else {
|
|
int32_t idx = 0;
|
|
|
|
if(std::holds_alternative<scripting::script_value>(args.front())) {
|
|
idx = std::get<int32_t>(std::get<scripting::script_value>(args.front()));
|
|
} else {
|
|
idx = std::get<int32_t>(self->resolve(std::get<scripting::script_variable>(args.front()).name));
|
|
}
|
|
|
|
if(auto val = self->var_by_idx(idx); val) {
|
|
return val.value();
|
|
}
|
|
}
|
|
return scripting::script_value({});
|
|
}
|
|
};
|
|
|
|
struct fn_set : public scripting::function_impl {
|
|
int32_t max_variable_count;
|
|
|
|
explicit fn_set(int32_t _max_variable_count)
|
|
: max_variable_count(_max_variable_count) {}
|
|
|
|
std::optional<scripting::script_value> apply(scripting::UserScript* self,std::vector<scripting::argument> args, std::optional<scripting::script_error>& errors) final {
|
|
// TODO: use the requirement sets here
|
|
if(args.size() != 2) {
|
|
errors = scripting::script_error{
|
|
.message = "set expects 2 arguments"
|
|
};
|
|
return scripting::script_value{};
|
|
}
|
|
|
|
auto& var = args.back();
|
|
if(not holds_alternative<scripting::script_variable>(var)) {
|
|
errors = scripting::script_error{
|
|
.message = "set expects the first argument to be a target variable"
|
|
};
|
|
return scripting::script_value{};
|
|
}
|
|
|
|
auto& arg = args.front();
|
|
|
|
if(std::holds_alternative<scripting::script_value>(arg)) {
|
|
if(self->getValue(get<scripting::script_variable>(var).name) && self->var_count() >= max_variable_count) {
|
|
errors = scripting::script_error{
|
|
.message = "set expects 2 arguments"
|
|
};
|
|
return scripting::script_value{};
|
|
}
|
|
self->setValue(get<scripting::script_variable>(var).name, std::get<scripting::script_value>(arg));
|
|
} else {
|
|
self->setValue(get<scripting::script_variable>(var).name, self->resolve(std::get<scripting::script_variable>(arg).name));
|
|
}
|
|
if(auto v = self->getValue(get<scripting::script_variable>(var).name); v) {
|
|
return v.value();
|
|
} else {
|
|
return scripting::script_value{};
|
|
}
|
|
}
|
|
};
|
|
|
|
interpreter register_utils_lib(interpreter target, const UserScriptLibraryParameters& params) {
|
|
target->registerFunction("identity", std::make_unique<fn_identity>());
|
|
target->registerFunction("var_clear", std::make_unique<fn_var_clear>());
|
|
target->registerFunction("var_name", std::make_unique<fn_var_name>());
|
|
target->registerFunction("var_count", std::make_unique<fn_var_count>());
|
|
target->registerFunction("var_cap", std::make_unique<fn_var_cap>(params.variables_count));
|
|
target->registerFunction("var_dump", std::make_unique<fn_var_dump>());
|
|
target->registerFunction("var_type", std::make_unique<fn_var_type>());
|
|
target->registerFunction("null", std::make_unique<fn_null>());
|
|
target->registerFunction("set", std::make_unique<fn_set>(params.variables_count));
|
|
return std::move(target);
|
|
}
|
|
}
|