Skip to content

Commit

Permalink
scripting: Add support for returning Result types from bound functions
Browse files Browse the repository at this point in the history
  • Loading branch information
caseif committed Jul 11, 2024
1 parent c6cb4e2 commit 4acc4a4
Show file tree
Hide file tree
Showing 33 changed files with 582 additions and 109 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
#include "argus/lowlevel/debug.hpp"
#include "argus/lowlevel/math.hpp"

#include "argus/core/engine.hpp"

#include "argus/resman/resource_manager.hpp"

#include "argus/render/defines.hpp"
Expand Down
2 changes: 2 additions & 0 deletions engine/dynamic/render_opengl/src/renderer/bucket_proc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@

#include "argus/lowlevel/debug.hpp"

#include "argus/core/engine.hpp"

#include "argus/render/defines.hpp"

#include "internal/render_opengl/defines.hpp"
Expand Down
2 changes: 2 additions & 0 deletions engine/dynamic/render_opengl/src/renderer/compositing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
#include "argus/lowlevel/debug.hpp"
#include "argus/lowlevel/math.hpp"

#include "argus/core/engine.hpp"

#include "argus/resman/resource_manager.hpp"

#include "argus/render/common/canvas.hpp"
Expand Down
2 changes: 2 additions & 0 deletions engine/dynamic/render_opengl/src/renderer/texture_mgmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
#include "argus/lowlevel/debug.hpp"
#include "argus/lowlevel/logging.hpp"

#include "argus/core/engine.hpp"

#include "argus/resman/resource.hpp"
#include "argus/resman/resource_manager.hpp"

Expand Down
2 changes: 2 additions & 0 deletions engine/dynamic/render_opengl/src/state/renderer_state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include "argus/core/engine.hpp"

#include "argus/render/common/scene.hpp"

#include "internal/render_opengl/renderer/shader_mgmt.hpp"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
#include "argus/lowlevel/debug.hpp"
#include "argus/lowlevel/math.hpp"

#include "argus/core/engine.hpp"

#include "argus/resman/resource_manager.hpp"

#include "argus/render/defines.hpp"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@

#include "argus/lowlevel/debug.hpp"

#include "argus/core/engine.hpp"

#include "argus/render/defines.hpp"

#include "internal/render_opengl_legacy/defines.hpp"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
#include "argus/lowlevel/debug.hpp"
#include "argus/lowlevel/math.hpp"

#include "argus/core/engine.hpp"

#include "argus/resman/resource_manager.hpp"

#include "argus/render/common/canvas.hpp"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
#include "argus/lowlevel/debug.hpp"
#include "argus/lowlevel/logging.hpp"

#include "argus/core/engine.hpp"

#include "argus/resman/resource.hpp"
#include "argus/resman/resource_manager.hpp"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include "argus/core/engine.hpp"

#include "argus/render/common/scene.hpp"

#include "internal/render_opengl_legacy/renderer/shader_mgmt.hpp"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
#include "argus/lowlevel/debug.hpp"
#include "argus/lowlevel/math.hpp"

#include "argus/core/engine.hpp"

#include "argus/resman/resource_manager.hpp"

#include "argus/render/defines.hpp"
Expand Down
2 changes: 2 additions & 0 deletions engine/dynamic/render_opengles/src/renderer/bucket_proc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@

#include "argus/lowlevel/debug.hpp"

#include "argus/core/engine.hpp"

#include "argus/render/defines.hpp"

#include "internal/render_opengles/defines.hpp"
Expand Down
2 changes: 2 additions & 0 deletions engine/dynamic/render_opengles/src/renderer/compositing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
#include "argus/lowlevel/debug.hpp"
#include "argus/lowlevel/math.hpp"

#include "argus/core/engine.hpp"

#include "argus/resman/resource_manager.hpp"

#include "argus/render/common/canvas.hpp"
Expand Down
2 changes: 2 additions & 0 deletions engine/dynamic/render_opengles/src/renderer/texture_mgmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
#include "argus/lowlevel/debug.hpp"
#include "argus/lowlevel/logging.hpp"

#include "argus/core/engine.hpp"

#include "argus/resman/resource.hpp"
#include "argus/resman/resource_manager.hpp"

Expand Down
2 changes: 2 additions & 0 deletions engine/dynamic/render_opengles/src/state/renderer_state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include "argus/core/engine.hpp"

#include "argus/render/common/scene.hpp"

#include "internal/render_opengles/renderer/shader_mgmt.hpp"
Expand Down
2 changes: 2 additions & 0 deletions engine/dynamic/render_vulkan/src/setup/device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
#include "argus/lowlevel/logging.hpp"
#include "argus/lowlevel/macros.hpp"

#include "argus/core/engine.hpp"

#include "internal/render_vulkan/module_render_vulkan.hpp"
#include "internal/render_vulkan/setup/device.hpp"
#include "internal/render_vulkan/setup/queues.hpp"
Expand Down
20 changes: 20 additions & 0 deletions engine/libs/lowlevel/include/argus/lowlevel/result.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,26 @@ namespace argus {
template<typename T, typename E>
class Result;

template<typename T>
struct is_result : std::false_type {
};

template<typename T, typename E>
struct is_result<Result<T, E>> : std::true_type {
};

template<typename T>
constexpr bool is_result_v = is_result<T>::value;

template<typename T>
struct result_traits;

template<typename T, typename E>
struct result_traits<Result<T, E>> {
using value_type = T;
using error_type = E;
};

template<typename, typename T>
struct has_to_string_fn : std::false_type {
};
Expand Down
1 change: 1 addition & 0 deletions engine/static/game2d/include/argus/game2d/world2d.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#pragma once

#include "argus/lowlevel/math.hpp"
#include "argus/lowlevel/misc.hpp"
#include "argus/lowlevel/result.hpp"

#include "argus/render/2d/camera_2d.hpp"
Expand Down
2 changes: 1 addition & 1 deletion engine/static/game2d/src/script_bindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ namespace argus {
static void _bind_world_symbols(void) {
bind_type<World2D>("World2D").expect();
bind_member_static_function<World2D>("create", &World2D::create).expect();
bind_member_static_function<World2D>("get", &World2D::get_or_crash).expect();
bind_member_static_function<World2D>("get", &World2D::get).expect();
bind_member_instance_function("get_id", &World2D::get_id).expect();
bind_member_instance_function("get_scale_factor", &World2D::get_scale_factor).expect();
bind_member_instance_function("get_camera_transform", &World2D::get_camera_transform).expect();
Expand Down
88 changes: 68 additions & 20 deletions engine/static/scripting/include/argus/scripting/bind.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -183,26 +183,72 @@ namespace argus {

// _create_object_type is used to create function definitions
// too so it doesn't attempt to resolve the type name
if (ret_obj_type.type == IntegralType::Pointer
|| ret_obj_type.type == IntegralType::Struct) {
ret_obj_type.type_name = get_bound_type<ReturnType>()
.expect("Tried to create function wrapper with unbound return struct type").name;
} else if (ret_obj_type.type == IntegralType::Enum) {
ret_obj_type.type_name = get_bound_enum<ReturnType>()
.expect("Tried to create function wrapper with unbound return enum type").name;
} else if ((ret_obj_type.type == IntegralType::Vector || ret_obj_type.type == IntegralType::VectorRef)
&& (ret_obj_type.element_type.value()->type == IntegralType::Struct
|| ret_obj_type.element_type.value()->type == IntegralType::Pointer)) {
ret_obj_type.element_type.value()->type_name
= get_bound_type(ret_obj_type.element_type.value()->type_index.value())
.expect("Tried to create function wrapper with vector return type and "
"unbound element struct type").name;
} else if ((ret_obj_type.type == IntegralType::Vector || ret_obj_type.type == IntegralType::VectorRef)
&& ret_obj_type.element_type.value()->type == IntegralType::Enum) {
ret_obj_type.element_type.value()->type_name
= get_bound_enum(ret_obj_type.element_type.value()->type_index.value())
.expect("Tried to create function wrapper with vector return type and "
"unbound element enum type").name;
//TODO: figure out if we can move this to the .cpp file
switch (ret_obj_type.type) {
case IntegralType::Pointer:
case IntegralType::Struct: {
ret_obj_type.type_name = get_bound_type<ReturnType>()
.expect("Tried to create function wrapper with unbound return struct type").name;

break;
}
case IntegralType::Enum: {
ret_obj_type.type_name = get_bound_enum<ReturnType>()
.expect("Tried to create function wrapper with unbound return enum type").name;

break;
}
case IntegralType::Vector:
case IntegralType::VectorRef: {
if (ret_obj_type.primary_type.value()->type == IntegralType::Struct
|| ret_obj_type.primary_type.value()->type == IntegralType::Pointer) {
ret_obj_type.primary_type.value()->type_name
= get_bound_type(ret_obj_type.primary_type.value()->type_index.value())
.expect("Tried to create function wrapper with vector return type and "
"unbound element struct type").name;
} else if (ret_obj_type.primary_type.value()->type == IntegralType::Enum) {
ret_obj_type.primary_type.value()->type_name
= get_bound_enum(ret_obj_type.primary_type.value()->type_index.value())
.expect("Tried to create function wrapper with vector return type and "
"unbound element enum type").name;
}

break;
}
case IntegralType::Result: {
argus_assert(ret_obj_type.primary_type.has_value());
argus_assert(ret_obj_type.secondary_type.has_value());

if (ret_obj_type.primary_type.value()->type == IntegralType::Struct
|| ret_obj_type.primary_type.value()->type == IntegralType::Pointer) {
ret_obj_type.primary_type.value()->type_name
= get_bound_type(ret_obj_type.primary_type.value()->type_index.value())
.expect("Tried to create function wrapper with result return type and "
"unbound value struct type").name;
} else if (ret_obj_type.primary_type.value()->type == IntegralType::Enum) {
ret_obj_type.primary_type.value()->type_name
= get_bound_type(ret_obj_type.primary_type.value()->type_index.value())
.expect("Tried to create function wrapper with result return type and "
"unbound value enum type").name;
}

if (ret_obj_type.secondary_type.value()->type == IntegralType::Struct
|| ret_obj_type.secondary_type.value()->type == IntegralType::Pointer) {
ret_obj_type.secondary_type.value()->type_name
= get_bound_type(ret_obj_type.secondary_type.value()->type_index.value())
.expect("Tried to create function wrapper with result return type and "
"unbound error struct type").name;
} else if (ret_obj_type.secondary_type.value()->type == IntegralType::Enum) {
ret_obj_type.secondary_type.value()->type_name
= get_bound_type(ret_obj_type.secondary_type.value()->type_index.value())
.expect("Tried to create function wrapper with result return type and "
"unbound error enum type").name;
}

break;
}
default:
break; // nothing to do
}

if constexpr (std::is_same_v<std::remove_cv_t<std::remove_pointer_t<
Expand All @@ -217,6 +263,8 @@ namespace argus {
} else if constexpr (is_std_vector_v<std::remove_cv_t<
std::remove_reference_t<std::remove_pointer_t<ReturnType>>>>) {
return create_vector_object_wrapper_from_heap(ret_obj_type, ret);
} else if constexpr (is_result_v<std::remove_cv_t<ReturnType>>) {
return create_result_object_wrapper(ret_obj_type, ret);
} else if constexpr (std::is_reference_v<ReturnType>) {
ObjectWrapper wrapper(ret_obj_type, ret_obj_size);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,13 @@ namespace argus {
using E = typename B::value_type;
return { IntegralType::VectorRef, sizeof(void *), is_const, typeid(B), std::nullopt, std::nullopt,
create_object_type<E, flow_dir, is_const>() };
} else if constexpr (is_result_v<std::remove_cv_t<T>>) {
static_assert(flow_dir == DataFlowDirection::ToScript,
"Result types may not be passed or returned from scripts");
using V = typename result_traits<B>::value_type;
using E = typename result_traits<B>::error_type;
return { IntegralType::Result, sizeof(T), is_const, typeid(T), std::nullopt, std::nullopt,
create_object_type<V, flow_dir, is_const>(), create_object_type<E, flow_dir, is_const>() };
} else if constexpr (std::is_same_v<std::remove_cv_t<T>, bool>) {
return { IntegralType::Boolean, sizeof(bool), is_const };
} else if constexpr (std::is_integral_v<std::remove_cv_t<T>>) {
Expand All @@ -118,6 +125,8 @@ namespace argus {
} else if constexpr (std::is_reference_v<T> || std::is_pointer_v<std::remove_reference_t<T>>) {
// too much of a headache to worry about
static_assert(std::is_class_v<B>, "Non-class reference params in bound functions are not supported");
// no real use case for these, might as well simplify our implementation
static_assert(!is_result_v<B>, "Result references in bound functions are not supported");
// References passed to scripts must be invalidated when the
// underlying object is destroyed, which is only possible if the
// type derives from AutoCleanupable.
Expand Down
Loading

0 comments on commit 4acc4a4

Please sign in to comment.