Skip to content

Commit 9cbb758

Browse files
committed
WIP
1 parent 974b2e8 commit 9cbb758

6 files changed

Lines changed: 344 additions & 60 deletions

File tree

include/cmcpp/monostate.hpp

Lines changed: 103 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -123,83 +123,172 @@ namespace cmcpp
123123

124124
// std::tuple_size and std::tuple_element specializations for result wrappers
125125
// These are needed for std::apply to work with result_ok_wrapper/result_err_wrapper
126-
// The wrappers act as single-element tuples containing their wrapped value
126+
// Wrappers for tuple types forward to the wrapped tuple
127+
// Wrappers for non-tuple types act as single-element tuples
127128
namespace std
128129
{
130+
// Helper to detect if type is tuple-like
131+
template <typename T, typename = void>
132+
struct is_tuple_like : std::false_type
133+
{
134+
};
135+
136+
template <typename T>
137+
struct is_tuple_like<T, std::void_t<decltype(std::tuple_size<T>::value)>> : std::true_type
138+
{
139+
};
140+
141+
// For tuple-wrapped types, forward the size
129142
template <typename T>
130-
struct tuple_size<cmcpp::result_ok_wrapper<T>> : std::integral_constant<std::size_t, std::tuple_size_v<T>>
143+
struct tuple_size<cmcpp::result_ok_wrapper<T>> : std::conditional_t<
144+
is_tuple_like<T>::value,
145+
std::integral_constant<std::size_t, std::tuple_size_v<T>>,
146+
std::integral_constant<std::size_t, 1>>
131147
{
132148
};
133149

150+
// For tuple-wrapped types, forward the element type; for non-tuple, return T
134151
template <std::size_t I, typename T>
135152
struct tuple_element<I, cmcpp::result_ok_wrapper<T>>
136153
{
137-
using type = std::tuple_element_t<I, T>;
154+
using type = std::conditional_t<is_tuple_like<T>::value, std::tuple_element_t<I, T>, T>;
138155
};
139156

140157
template <typename T>
141-
struct tuple_size<cmcpp::result_err_wrapper<T>> : std::integral_constant<std::size_t, std::tuple_size_v<T>>
158+
struct tuple_size<cmcpp::result_err_wrapper<T>> : std::conditional_t<
159+
is_tuple_like<T>::value,
160+
std::integral_constant<std::size_t, std::tuple_size_v<T>>,
161+
std::integral_constant<std::size_t, 1>>
142162
{
143163
};
144164

145165
template <std::size_t I, typename T>
146166
struct tuple_element<I, cmcpp::result_err_wrapper<T>>
147167
{
148-
using type = std::tuple_element_t<I, T>;
168+
using type = std::conditional_t<is_tuple_like<T>::value, std::tuple_element_t<I, T>, T>;
149169
};
150170
}
151171

152172
// std::get specializations for result wrappers to support structured bindings and std::apply
153-
// Forward get<I> calls to the wrapped tuple
173+
// For tuple-wrapped types, forward get<I> calls to the wrapped tuple
174+
// For non-tuple types, return the value directly when I == 0
154175
namespace std
155176
{
177+
// result_ok_wrapper - tuple wrapped types
156178
template <std::size_t I, typename T>
157-
constexpr decltype(auto) get(cmcpp::result_ok_wrapper<T> &wrapper) noexcept
179+
constexpr std::enable_if_t<is_tuple_like<T>::value, decltype(std::get<I>(std::declval<T &>()))>
180+
get(cmcpp::result_ok_wrapper<T> &wrapper) noexcept
158181
{
159182
return std::get<I>(wrapper.value);
160183
}
161184

162185
template <std::size_t I, typename T>
163-
constexpr decltype(auto) get(const cmcpp::result_ok_wrapper<T> &wrapper) noexcept
186+
constexpr std::enable_if_t<is_tuple_like<T>::value, decltype(std::get<I>(std::declval<const T &>()))>
187+
get(const cmcpp::result_ok_wrapper<T> &wrapper) noexcept
164188
{
165189
return std::get<I>(wrapper.value);
166190
}
167191

168192
template <std::size_t I, typename T>
169-
constexpr decltype(auto) get(cmcpp::result_ok_wrapper<T> &&wrapper) noexcept
193+
constexpr std::enable_if_t<is_tuple_like<T>::value, decltype(std::get<I>(std::declval<T &&>()))>
194+
get(cmcpp::result_ok_wrapper<T> &&wrapper) noexcept
170195
{
171196
return std::get<I>(std::move(wrapper.value));
172197
}
173198

174199
template <std::size_t I, typename T>
175-
constexpr decltype(auto) get(const cmcpp::result_ok_wrapper<T> &&wrapper) noexcept
200+
constexpr std::enable_if_t<is_tuple_like<T>::value, decltype(std::get<I>(std::declval<const T &&>()))>
201+
get(const cmcpp::result_ok_wrapper<T> &&wrapper) noexcept
176202
{
177203
return std::get<I>(std::move(wrapper.value));
178204
}
179205

206+
// result_ok_wrapper - non-tuple wrapped types (I must be 0)
207+
template <std::size_t I, typename T>
208+
constexpr std::enable_if_t<!is_tuple_like<T>::value && I == 0, T &>
209+
get(cmcpp::result_ok_wrapper<T> &wrapper) noexcept
210+
{
211+
return wrapper.value;
212+
}
213+
214+
template <std::size_t I, typename T>
215+
constexpr std::enable_if_t<!is_tuple_like<T>::value && I == 0, const T &>
216+
get(const cmcpp::result_ok_wrapper<T> &wrapper) noexcept
217+
{
218+
return wrapper.value;
219+
}
220+
180221
template <std::size_t I, typename T>
181-
constexpr decltype(auto) get(cmcpp::result_err_wrapper<T> &wrapper) noexcept
222+
constexpr std::enable_if_t<!is_tuple_like<T>::value && I == 0, T &&>
223+
get(cmcpp::result_ok_wrapper<T> &&wrapper) noexcept
224+
{
225+
return std::move(wrapper.value);
226+
}
227+
228+
template <std::size_t I, typename T>
229+
constexpr std::enable_if_t<!is_tuple_like<T>::value && I == 0, const T &&>
230+
get(const cmcpp::result_ok_wrapper<T> &&wrapper) noexcept
231+
{
232+
return std::move(wrapper.value);
233+
}
234+
235+
// result_err_wrapper - tuple wrapped types
236+
template <std::size_t I, typename T>
237+
constexpr std::enable_if_t<is_tuple_like<T>::value, decltype(std::get<I>(std::declval<T &>()))>
238+
get(cmcpp::result_err_wrapper<T> &wrapper) noexcept
182239
{
183240
return std::get<I>(wrapper.value);
184241
}
185242

186243
template <std::size_t I, typename T>
187-
constexpr decltype(auto) get(const cmcpp::result_err_wrapper<T> &wrapper) noexcept
244+
constexpr std::enable_if_t<is_tuple_like<T>::value, decltype(std::get<I>(std::declval<const T &>()))>
245+
get(const cmcpp::result_err_wrapper<T> &wrapper) noexcept
188246
{
189247
return std::get<I>(wrapper.value);
190248
}
191249

192250
template <std::size_t I, typename T>
193-
constexpr decltype(auto) get(cmcpp::result_err_wrapper<T> &&wrapper) noexcept
251+
constexpr std::enable_if_t<is_tuple_like<T>::value, decltype(std::get<I>(std::declval<T &&>()))>
252+
get(cmcpp::result_err_wrapper<T> &&wrapper) noexcept
194253
{
195254
return std::get<I>(std::move(wrapper.value));
196255
}
197256

198257
template <std::size_t I, typename T>
199-
constexpr decltype(auto) get(const cmcpp::result_err_wrapper<T> &&wrapper) noexcept
258+
constexpr std::enable_if_t<is_tuple_like<T>::value, decltype(std::get<I>(std::declval<const T &&>()))>
259+
get(const cmcpp::result_err_wrapper<T> &&wrapper) noexcept
200260
{
201261
return std::get<I>(std::move(wrapper.value));
202262
}
263+
264+
// result_err_wrapper - non-tuple wrapped types (I must be 0)
265+
template <std::size_t I, typename T>
266+
constexpr std::enable_if_t<!is_tuple_like<T>::value && I == 0, T &>
267+
get(cmcpp::result_err_wrapper<T> &wrapper) noexcept
268+
{
269+
return wrapper.value;
270+
}
271+
272+
template <std::size_t I, typename T>
273+
constexpr std::enable_if_t<!is_tuple_like<T>::value && I == 0, const T &>
274+
get(const cmcpp::result_err_wrapper<T> &wrapper) noexcept
275+
{
276+
return wrapper.value;
277+
}
278+
279+
template <std::size_t I, typename T>
280+
constexpr std::enable_if_t<!is_tuple_like<T>::value && I == 0, T &&>
281+
get(cmcpp::result_err_wrapper<T> &&wrapper) noexcept
282+
{
283+
return std::move(wrapper.value);
284+
}
285+
286+
template <std::size_t I, typename T>
287+
constexpr std::enable_if_t<!is_tuple_like<T>::value && I == 0, const T &&>
288+
get(const cmcpp::result_err_wrapper<T> &&wrapper) noexcept
289+
{
290+
return std::move(wrapper.value);
291+
}
203292
}
204293

205294
#endif // CMCPP_MONOSTATE_HPP

include/cmcpp/traits.hpp

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,22 @@ namespace cmcpp
228228
struct result_ok_monostate;
229229
struct result_err_monostate;
230230

231+
// Helper to detect result wrapper types (must be declared before concepts that use it)
232+
template <typename T>
233+
struct is_result_wrapper : std::false_type
234+
{
235+
};
236+
237+
template <typename T>
238+
struct is_result_wrapper<result_ok_wrapper<T>> : std::true_type
239+
{
240+
};
241+
242+
template <typename T>
243+
struct is_result_wrapper<result_err_wrapper<T>> : std::true_type
244+
{
245+
};
246+
231247
template <>
232248
struct ValTrait<result_ok_monostate>
233249
{
@@ -281,7 +297,7 @@ namespace cmcpp
281297
static constexpr std::array<WasmValType, 1> flat_types = {WasmValType::i32};
282298
};
283299
template <typename T>
284-
concept Boolean = ValTrait<T>::type == ValType::Bool;
300+
concept Boolean = !is_result_wrapper<T>::value && ValTrait<T>::type == ValType::Bool;
285301
// Char --------------------------------------------------------------------
286302
using char_t = char32_t;
287303

@@ -404,14 +420,14 @@ namespace cmcpp
404420
};
405421

406422
template <typename T>
407-
concept Integer = ValTrait<T>::type == ValType::S8 || ValTrait<T>::type == ValType::S16 || ValTrait<T>::type == ValType::S32 || ValTrait<T>::type == ValType::S64 ||
408-
ValTrait<T>::type == ValType::U8 || ValTrait<T>::type == ValType::U16 || ValTrait<T>::type == ValType::U32 || ValTrait<T>::type == ValType::U64;
423+
concept Integer = !is_result_wrapper<T>::value && (ValTrait<T>::type == ValType::S8 || ValTrait<T>::type == ValType::S16 || ValTrait<T>::type == ValType::S32 || ValTrait<T>::type == ValType::S64 ||
424+
ValTrait<T>::type == ValType::U8 || ValTrait<T>::type == ValType::U16 || ValTrait<T>::type == ValType::U32 || ValTrait<T>::type == ValType::U64);
409425

410426
template <typename T>
411-
concept SignedInteger = std::is_signed_v<T> && Integer<T>;
427+
concept SignedInteger = !is_result_wrapper<T>::value && std::is_signed_v<T> && Integer<T>;
412428

413429
template <typename T>
414-
concept UnsignedInteger = !std::is_signed_v<T> && Integer<T>;
430+
concept UnsignedInteger = !is_result_wrapper<T>::value && !std::is_signed_v<T> && Integer<T>;
415431

416432
template <>
417433
struct ValTrait<float32_t>
@@ -440,7 +456,7 @@ namespace cmcpp
440456
};
441457

442458
template <typename T>
443-
concept Float = ValTrait<T>::type == ValType::F32 || ValTrait<T>::type == ValType::F64;
459+
concept Float = !is_result_wrapper<T>::value && (ValTrait<T>::type == ValType::F32 || ValTrait<T>::type == ValType::F64);
444460

445461
template <typename T>
446462
concept Numeric = Integer<T> || Float<T>;
@@ -734,7 +750,7 @@ namespace cmcpp
734750
static constexpr std::array<WasmValType, flat_types_len> flat_types = compute_tuple_flat_types<flat_types_len, Ts...>();
735751
};
736752
template <typename T>
737-
concept Tuple = ValTrait<T>::type == ValType::Tuple;
753+
concept Tuple = !is_result_wrapper<T>::value && ValTrait<T>::type == ValType::Tuple;
738754

739755
// Record ------------------------------------------------------------------
740756
template <typename S>
@@ -757,22 +773,6 @@ namespace cmcpp
757773
static constexpr std::array<WasmValType, flat_types_len> flat_types = ValTrait<tuple_type>::flat_types;
758774
};
759775

760-
// Helper to detect wrapper types
761-
template <typename T>
762-
struct is_result_wrapper : std::false_type
763-
{
764-
};
765-
766-
template <typename T>
767-
struct is_result_wrapper<result_ok_wrapper<T>> : std::true_type
768-
{
769-
};
770-
771-
template <typename T>
772-
struct is_result_wrapper<result_err_wrapper<T>> : std::true_type
773-
{
774-
};
775-
776776
template <typename T>
777777
concept Record = ValTrait<T>::type == ValType::Record && !is_result_wrapper<T>::value;
778778

samples/wamr/generated/sample_wamr.hpp

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,111 @@ extern const uint32_t DEFAULT_HEAP_SIZE;
4343
// Note: Helper functions create_guest_realloc() and create_lift_lower_context()
4444
// are now available directly from <wamr.hpp> in the cmcpp namespace
4545

46+
// ==============================================================================
47+
// Guest Function Wrappers (Exports - Guest implements, Host calls)
48+
// ==============================================================================
49+
// These functions create pre-configured guest function wrappers for all exported
50+
// functions from the guest module. Use these instead of manually calling
51+
// guest_function<T>() with the export name.
52+
53+
namespace guest_wrappers {
54+
55+
// Interface: example:sample/booleans
56+
namespace booleans {
57+
inline auto and_(wasm_module_inst_t module_inst, wasm_exec_env_t exec_env,
58+
cmcpp::LiftLowerContext& ctx) {
59+
return cmcpp::guest_function<guest::booleans::and_t>(
60+
module_inst, exec_env, ctx, "example:sample/booleans#and");
61+
}
62+
} // namespace booleans
63+
64+
// Interface: example:sample/floats
65+
namespace floats {
66+
inline auto add(wasm_module_inst_t module_inst, wasm_exec_env_t exec_env,
67+
cmcpp::LiftLowerContext& ctx) {
68+
return cmcpp::guest_function<guest::floats::add_t>(
69+
module_inst, exec_env, ctx, "example:sample/floats#add");
70+
}
71+
} // namespace floats
72+
73+
// Interface: example:sample/strings
74+
namespace strings {
75+
inline auto reverse(wasm_module_inst_t module_inst, wasm_exec_env_t exec_env,
76+
cmcpp::LiftLowerContext& ctx) {
77+
return cmcpp::guest_function<guest::strings::reverse_t>(
78+
module_inst, exec_env, ctx, "example:sample/strings#reverse");
79+
}
80+
inline auto lots(wasm_module_inst_t module_inst, wasm_exec_env_t exec_env,
81+
cmcpp::LiftLowerContext& ctx) {
82+
return cmcpp::guest_function<guest::strings::lots_t>(
83+
module_inst, exec_env, ctx, "example:sample/strings#lots");
84+
}
85+
} // namespace strings
86+
87+
// Interface: example:sample/tuples
88+
namespace tuples {
89+
inline auto reverse(wasm_module_inst_t module_inst, wasm_exec_env_t exec_env,
90+
cmcpp::LiftLowerContext& ctx) {
91+
return cmcpp::guest_function<guest::tuples::reverse_t>(
92+
module_inst, exec_env, ctx, "example:sample/tuples#reverse");
93+
}
94+
} // namespace tuples
95+
96+
// Interface: example:sample/lists
97+
namespace lists {
98+
inline auto filter_bool(wasm_module_inst_t module_inst, wasm_exec_env_t exec_env,
99+
cmcpp::LiftLowerContext& ctx) {
100+
return cmcpp::guest_function<guest::lists::filter_bool_t>(
101+
module_inst, exec_env, ctx, "example:sample/lists#filter-bool");
102+
}
103+
} // namespace lists
104+
105+
// Interface: example:sample/variants
106+
namespace variants {
107+
inline auto variant_func(wasm_module_inst_t module_inst, wasm_exec_env_t exec_env,
108+
cmcpp::LiftLowerContext& ctx) {
109+
return cmcpp::guest_function<guest::variants::variant_func_t>(
110+
module_inst, exec_env, ctx, "example:sample/variants#variant-func");
111+
}
112+
} // namespace variants
113+
114+
// Interface: example:sample/enums
115+
namespace enums {
116+
inline auto enum_func(wasm_module_inst_t module_inst, wasm_exec_env_t exec_env,
117+
cmcpp::LiftLowerContext& ctx) {
118+
return cmcpp::guest_function<guest::enums::enum_func_t>(
119+
module_inst, exec_env, ctx, "example:sample/enums#enum-func");
120+
}
121+
} // namespace enums
122+
123+
// Standalone function: void-func
124+
inline auto void_func(wasm_module_inst_t module_inst, wasm_exec_env_t exec_env,
125+
cmcpp::LiftLowerContext& ctx) {
126+
return cmcpp::guest_function<guest::void_func_t>(
127+
module_inst, exec_env, ctx, "void-func");
128+
}
129+
130+
// Standalone function: ok-func
131+
inline auto ok_func(wasm_module_inst_t module_inst, wasm_exec_env_t exec_env,
132+
cmcpp::LiftLowerContext& ctx) {
133+
return cmcpp::guest_function<guest::ok_func_t>(
134+
module_inst, exec_env, ctx, "ok-func");
135+
}
136+
137+
// Standalone function: err-func
138+
inline auto err_func(wasm_module_inst_t module_inst, wasm_exec_env_t exec_env,
139+
cmcpp::LiftLowerContext& ctx) {
140+
return cmcpp::guest_function<guest::err_func_t>(
141+
module_inst, exec_env, ctx, "err-func");
142+
}
143+
144+
// Standalone function: option-func
145+
inline auto option_func(wasm_module_inst_t module_inst, wasm_exec_env_t exec_env,
146+
cmcpp::LiftLowerContext& ctx) {
147+
return cmcpp::guest_function<guest::option_func_t>(
148+
module_inst, exec_env, ctx, "option-func");
149+
}
150+
151+
} // namespace guest_wrappers
152+
46153
#endif // GENERATED_WAMR_BINDINGS_HPP

0 commit comments

Comments
 (0)