14#include <fmt/format.h>
17#include <libassert/assert.hpp>
18#include <range/v3/action/split.hpp>
19#include <range/v3/view/enumerate.hpp>
38template <
typename Ret,
typename... Args>
43 constexpr AsmFunctionResult(std::tuple<std::decay_t<Args>...> args_, std::string_view function_name_)
52 std::tuple<std::decay_t<Args>...>
args;
55 std::string
repr(std::span<const inspection::Token> tokens, std::string_view raw_str)
const {
108 std::array stringized_args = std::apply(
109 []<
typename... Ts>(
const Ts&... fn_args) {
return std::array{
stringize::str(fn_args).original...}; },
args);
111 return fmt::format(
"{}({})",
function_name, fmt::join(stringized_args,
", "));
120 static_assert(
always_false_v<T>,
"AsmFunction is not specialized for non-function types!");
127 { val.has_value() } -> std::same_as<bool>;
138using UnwrapInnerT = std::remove_reference_t<decltype(std::declval<T>().value())>;
140static_assert(std::same_as<UnwrapInnerT<std::optional<int>>,
int>);
141static_assert(std::same_as<UnwrapInnerT<Expected<int>>,
int>);
142static_assert(std::same_as<UnwrapInnerT<Expected<>>,
void>);
164static_assert(std::same_as<UnwrapInnerOrT<std::optional<int>>,
int>);
165static_assert(std::same_as<UnwrapInnerOrT<const std::optional<int>>,
const int>);
166static_assert(std::same_as<UnwrapInnerOrT<int>,
int>);
167static_assert(std::same_as<UnwrapInnerOrT<int&>,
int&>);
171template <
typename Ret,
typename... Args>
178 template <
typename... Ts>
179 requires(
sizeof...(Ts) ==
sizeof...(Args)) &&
182 static_assert((
true && ... && std::copyable<std::decay_t<detail::UnwrapInnerOrT<Ts>>>),
183 "All arguments must be copyable");
184 (check_ptr_arg<Ts>(), ...);
189 if (resolution_err_.has_value()) {
190 res.set_result(*resolution_err_);
195 std::optional unwrapped_args = try_unwrap_args(args...);
197 if (!unwrapped_args) {
207 const auto& prog_call_fn =
209 auto call_res = std::apply(prog_call_fn, *unwrapped_args);
211 res.set_result(std::move(call_res));
216 const std::string&
get_name()
const {
return name_; }
219 template <
typename T>
220 void check_ptr_arg() {
221 using NormT = std::decay_t<T>;
222 static_assert(!std::is_pointer_v<NormT> && !std::is_array_v<NormT>,
223 "Passing a raw pointer as argument for an asm function, which is probably not what you meant to "
224 "do. See docs on program memory for more info.");
229 template <
typename T>
230 bool check_valid_unwrappable(
const T& arg) {
231 if constexpr (detail::IsUnwrappable<T>) {
232 return arg.has_value();
247 template <
typename... Ts>
248 auto try_unwrap_args(
const Ts&... args) -> std::optional<std::tuple<const detail::UnwrapInnerOrT<Ts>&...>> {
249 if ((
false || ... || !check_valid_unwrappable(args))) {
255 auto maybe_unwrap = []<
typename T>(
const T& arg) ->
decltype(
auto) {
256 if constexpr (detail::IsUnwrappable<T>) {
263 return std::tuple<const detail::UnwrapInnerOrT<Ts>&...>{maybe_unwrap(args)...};
268 std::uintptr_t address_;
270 std::optional<ErrorKind> resolution_err_;
273template <
typename Ret,
typename... Args>
277 , name_{
std::move(name)} {}
279template <
typename Ret,
typename... Args>
283 , name_{
std::move(name)}
284 , resolution_err_{resolution_err} {}
288template <
typename Ret,
typename... Ts>
Transparent wrapper around Result<Ret>, as far as the user is concerned.
Definition asm_function.hpp:40
std::string repr(std::span< const inspection::Token > tokens, std::string_view raw_str) const
Definition asm_function.hpp:55
constexpr AsmFunctionResult(std::tuple< std::decay_t< Args >... > args_, std::string_view function_name_)
Definition asm_function.hpp:43
std::string_view function_name
Definition asm_function.hpp:53
std::tuple< std::decay_t< Args >... > args
Definition asm_function.hpp:52
void set_result(U &&val)
Definition asm_function.hpp:48
const std::string & get_name() const
Definition asm_function.hpp:216
Definition asm_function.hpp:119
std::variant wrapper for a partial implementation of C++23's expected type
Definition expected.hpp:34
Definition program.hpp:32
Result< typename FunctionTraits< Func >::Ret > call_function(std::string_view name, Args &&... args)
Returns the result of the function call, or nullopt if the symbol name was not found or some other er...
Definition program.hpp:146
A trait for types that are compatible in how they are read and written to memory.
Definition concepts.hpp:80
Definition asm_function.hpp:126
UnwrapInnerOr< T >::type UnwrapInnerOrT
Definition asm_function.hpp:162
std::remove_reference_t< decltype(std::declval< T >().value())> UnwrapInnerT
Obtain the inner type of a T satisfying IsUnwrappable (e.g., std::optional or asmgrader::Expected)
Definition asm_function.hpp:138
constexpr const auto & str
str customization point object The return value of this function is guaranteed to be parsable by high...
Definition stringize.hpp:190
Definition asm_buffer.hpp:20
constexpr bool always_false_v
Definition always_false.hpp:16
Expected< T, ErrorKind > Result
Definition error_types.hpp:25
ErrorKind
Definition error_types.hpp:11
@ BadArgument
Bad argument to an AsmFunction. For an unwrappable type with no inner value.
Definition byte_array.hpp:94
See asmgrader::stringize.
T type
Definition asm_function.hpp:151
Definition asm_function.hpp:145