Skip to content

Commit ea71901

Browse files
authored
Fix external function types (#137)
fixes(type/casting): for external function arguments and return values. * Adds support for uint/float/bool push/pop of function args. * Adds missing int32->uint32 numeric_cast. * Adds missing boolean output (toStr and string size) * Fixed toStr(string) which only worked for strings of one character. * Added test case roundtripping values of the supported types to the host.
1 parent 27d3053 commit ea71901

File tree

7 files changed

+119
-7
lines changed

7 files changed

+119
-7
lines changed

inkcpp/functional.cpp

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "value.h"
1010
#include "stack.h"
1111
#include "string_table.h"
12+
#include "operations.h"
1213

1314
#ifdef INK_ENABLE_UNREAL
1415
# include "InkVar.h"
@@ -28,8 +29,28 @@ template<>
2829
int32_t function_base::pop<int32_t>(basic_eval_stack* stack, list_table& lists)
2930
{
3031
value val = stack->pop();
31-
inkAssert(val.type() == value_type::int32, "Type mismatch!");
32-
return val.get<value_type::int32>();
32+
return casting::numeric_cast<value_type::int32>(val);
33+
}
34+
35+
template<>
36+
uint32_t function_base::pop<uint32_t>(basic_eval_stack* stack, list_table& lists)
37+
{
38+
value val = stack->pop();
39+
return casting::numeric_cast<value_type::uint32>(val);
40+
}
41+
42+
template<>
43+
bool function_base::pop<bool>(basic_eval_stack* stack, list_table& lists)
44+
{
45+
value val = stack->pop();
46+
return casting::numeric_cast<value_type::int32>(val) != 0;
47+
}
48+
49+
template<>
50+
float function_base::pop<float>(basic_eval_stack* stack, list_table& lists)
51+
{
52+
value val = stack->pop();
53+
return casting::numeric_cast<value_type::float32>(val);
3354
}
3455

3556
template<>
@@ -46,6 +67,24 @@ void function_base::push<int32_t>(basic_eval_stack* stack, const int32_t& v)
4667
stack->push(value{}.set<value_type::int32>(v));
4768
}
4869

70+
template<>
71+
void function_base::push<uint32_t>(basic_eval_stack* stack, const uint32_t& v)
72+
{
73+
stack->push(value{}.set<value_type::uint32>(v));
74+
}
75+
76+
template<>
77+
void function_base::push<float>(basic_eval_stack* stack, const float& v)
78+
{
79+
stack->push(value{}.set<value_type::float32>(v));
80+
}
81+
82+
template<>
83+
void function_base::push<bool>(basic_eval_stack* stack, const bool& v)
84+
{
85+
stack->push(value{}.set<value_type::boolean>(v));
86+
}
87+
4988
void function_base::push_void(basic_eval_stack* stack) { stack->push(values::null); }
5089

5190
void function_base::push_string(basic_eval_stack* stack, const char* dynamic_string)

inkcpp/numeric_operations.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ namespace casting
8888
numeric_cast<value_type::uint32>(const value& v)
8989
{
9090
switch (v.type()) {
91+
case value_type::int32: return v.get<value_type::int32>();
9192
case value_type::uint32: return v.get<value_type::uint32>();
9293
/// bool value can cast to uint32
9394
case value_type::boolean: return static_cast<uint32_t>(v.get<value_type::boolean>());

inkcpp/output.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,7 @@ char* basic_stream::get_alloc(string_table& strings, list_table& lists)
362362
case value_type::int32:
363363
case value_type::float32:
364364
case value_type::uint32:
365+
case value_type::boolean:
365366
// Convert to string and advance
366367
toStr(ptr, end - ptr, _data[i]);
367368
while (*ptr != 0)

inkcpp/string_utils.h

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -85,18 +85,18 @@ inline int toStr(char* buffer, size_t size, float value)
8585
return ec;
8686
}
8787

88-
inline int toStr(char* buffer, size_t size, const char* c)
88+
inline int toStr(char* buffer, size_t size, const char* str)
8989
{
9090
char* ptr = buffer;
9191
size_t i = 0;
92-
while (*c && i < size) {
93-
*ptr++ = *c;
92+
while (i < size && str[i]) {
93+
ptr[i] = str[i];
9494
++i;
9595
}
9696
if (i >= size) {
9797
return EINVAL;
9898
}
99-
*ptr = 0;
99+
ptr[i] = 0;
100100
return 0;
101101
}
102102

@@ -113,7 +113,7 @@ inline int toStr(char* buffer, size_t size, const value& v)
113113
case value_type::float32: return toStr(buffer, size, v.get<value_type::float32>());
114114
case value_type::boolean: return toStr(buffer, size, v.get<value_type::boolean>());
115115
case value_type::newline: return toStr(buffer, size, "\n");
116-
default: inkFail("only support toStr for numeric types"); return -1;
116+
default: inkFail("No toStr implementation for this type"); return -1;
117117
}
118118
}
119119

@@ -148,6 +148,8 @@ inline constexpr size_t value_length(const value& v)
148148
case value_type::uint32: return decimal_digits(v.get<value_type::uint32>());
149149
case value_type::float32: return decimal_digits(v.get<value_type::float32>());
150150
case value_type::string: return c_str_len(v.get<value_type::string>());
151+
case value_type::boolean:
152+
return v.get<value_type::boolean>() ? c_str_len("true") : c_str_len("false");
151153
case value_type::newline: return 1;
152154
default: inkFail("Can't determine length of this value type"); return -1;
153155
}

inkcpp_test/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ add_executable(inkcpp_test catch.hpp Main.cpp
1717
ThirdTierChoiceAfterBrackets.cpp
1818
NoEarlyTags.cpp
1919
ExternalFunctionsExecuteProperly.cpp
20+
ExternalFunctionTypes.cpp
2021
LookaheadSafe.cpp
2122
EmptyStringForDivert.cpp
2223
MoveTo.cpp
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#include "catch.hpp"
2+
3+
#include <../runner_impl.h>
4+
#include <story.h>
5+
#include <globals.h>
6+
#include <runner.h>
7+
#include <compiler.h>
8+
9+
using namespace ink::runtime;
10+
11+
SCENARIO("a story with external functions support types", "[story]")
12+
{
13+
GIVEN("a story with external functions")
14+
{
15+
auto ink = story::from_file(INK_TEST_RESOURCE_DIR "ExternalFunctionTypes.bin");
16+
auto thread = ink->new_runner().cast<internal::runner_impl>();
17+
18+
std::stringstream debug;
19+
thread->set_debug_enabled(&debug);
20+
21+
bool b = false;
22+
int i = 0;
23+
unsigned int u = 0;
24+
float f = 0;
25+
std::string s;
26+
27+
thread->bind("SET_BOOL", [&b](bool o) { b = o; });
28+
thread->bind("SET_INT", [&i](int o) { i = o; });
29+
thread->bind("SET_UINT", [&u](unsigned int o) { u = o; });
30+
thread->bind("SET_FLOAT", [&f](float o) { f = o; });
31+
thread->bind("SET_STRING", [&s](std::string o) { s = o; });
32+
33+
thread->bind("GET_BOOL", [&b]() { return b; });
34+
thread->bind("GET_INT", [&i]() { return i; });
35+
thread->bind("GET_UINT", [&u]() { return u; });
36+
thread->bind("GET_FLOAT", [&f]() { return f; });
37+
thread->bind("GET_STRING", [&s]() { return s; });
38+
39+
WHEN("run thread")
40+
{
41+
THEN("output shows values from ink")
42+
{
43+
auto line = thread->getline();
44+
REQUIRE(line == "true 1.5 -5 17 foo\n");
45+
}
46+
}
47+
}
48+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
EXTERNAL GET_BOOL()
2+
EXTERNAL GET_FLOAT()
3+
EXTERNAL GET_INT()
4+
EXTERNAL GET_UINT()
5+
EXTERNAL GET_STRING()
6+
EXTERNAL SET_BOOL(b)
7+
EXTERNAL SET_FLOAT(f)
8+
EXTERNAL SET_INT(i)
9+
EXTERNAL SET_UINT(i)
10+
EXTERNAL SET_STRING(s)
11+
12+
~ SET_BOOL(true)
13+
~ SET_FLOAT(1.5)
14+
~ SET_INT(-5)
15+
~ SET_UINT(17)
16+
~ SET_STRING("foo")
17+
18+
{GET_BOOL()} {GET_FLOAT()} {GET_INT()} {GET_UINT()} {GET_STRING()}
19+
20+
-> DONE

0 commit comments

Comments
 (0)