diff --git a/script_exe/main.cpp b/script_exe/main.cpp index 1d553d2..b843045 100644 --- a/script_exe/main.cpp +++ b/script_exe/main.cpp @@ -9,18 +9,22 @@ #include #include "UserScript.h" -void print_value(std::ostream& stream, const scripting::script_value& res) { +void print_value(std::ostream& stream, const scripting::script_value& res, bool array_print = false) { if(std::holds_alternative(res)) { stream << "["; auto max = std::get(res).value.size(); auto no_comma = max - 1; for(size_t idx = 0; idx < max; ++idx) { - print_value(stream, std::get(res).value[idx]); + print_value(stream, std::get(res).value[idx], true); stream << (idx != no_comma ? ", " : ""); } stream << "]"; } else if(std::holds_alternative(res)) { - stream << std::get(res); + if(array_print) { + stream << std::quoted(std::get(res)); + } else { + stream << std::get(res); + } } else if(std::holds_alternative(res)) { stream << "null"; } else { diff --git a/src/std/array.cpp b/src/std/array.cpp index 2c34273..0045088 100644 --- a/src/std/array.cpp +++ b/src/std/array.cpp @@ -319,6 +319,92 @@ struct fn_array_index final : public scripting::function_impl { ~fn_array_index() final = default; }; +struct fn_array_set final : public scripting::function_impl { + fn_array_set() = default; + + std::optional apply(UserScript* self, std::vector n, std::optional& error) final { + if(n.size() != 3) { + error = script_error{ + .message = "/array_set takes exactly 3 argument of type (array, integer, value), provided a different amount" + }; + return std::nullopt; + } + + auto& arg = n.back(); + + if(std::holds_alternative(arg)) { + error = script_error{ + .message = "/array_set takes exactly 3 argument of type (array, integer, value), the array needs to be a variable" + }; + return std::nullopt; + } + + auto target = self->getValue(std::get(arg).name); + + if(not target) { + error = script_error{ + .message = "/array_set takes exactly 3 argument of type (array, integer, value), provided array variable is undefined" + }; + return std::nullopt; + } + + if(not std::holds_alternative(target.value().get())) { + error = script_error{ + .message = "/array_set takes exactly 1 argument of type array followed by an integer, argument 1 is not an array" + }; + return std::nullopt; + } + + + auto& concrete_target = std::get(target.value().get()); + + auto& idx_arg = n[1]; + script_value idx; + + if(std::holds_alternative(idx_arg)) { + idx = std::get(idx_arg); + } else { + idx = self->resolve(std::get(idx_arg).name); + } + + if(not std::holds_alternative(idx)) { + error = script_error{ + .message = "/array_set takes exactly 1 argument of type array followed by an integer, argument 2 is not an integer" + }; + return std::nullopt; + } + + if(static_cast(concrete_target.value.size()) <= std::get(idx)) { + error = script_error{ + .message = "/array_set index must be smaller that the array size, the first element of the array has index 0" + }; + return std::nullopt; + } + + if(std::get(idx) < 0) { + error = script_error{ + .message = "/array_set index must be 0 or more" + }; + return std::nullopt; + } + + auto& value_arg = n.front(); + script_value value; + + if(std::holds_alternative(value_arg)) { + value = std::get(value_arg); + } else { + value = self->resolve(std::get(value_arg).name); + } + + concrete_target.value.at(std::get(idx)) = value; + + return concrete_target.value[std::get(idx)]; + } + + ~fn_array_set() final = default; +}; + namespace scripting { interpreter register_array_lib(interpreter target, bool recursive_arrays, int32_t size_limit) { @@ -329,6 +415,7 @@ namespace scripting { target->registerFunction("array_pop", std::make_unique()); target->registerFunction("array_size", std::make_unique()); target->registerFunction("array_index", std::make_unique()); + target->registerFunction("array_set", std::make_unique()); return std::move(target); }