選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

227 行
7.9 KiB

#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);
}
}