From 2f808206d0b14254b0b9d54b9a7a4e097a7412ce Mon Sep 17 00:00:00 2001 From: Julian Benda Date: Thu, 21 Dec 2023 14:02:24 +0100 Subject: [PATCH 1/3] Fixing saved output after finishingline --- inkcpp/output.cpp | 17 +++++---- inkcpp/runner_impl.cpp | 3 ++ inkcpp/value.h | 2 +- inkcpp_test/CMakeLists.txt | 1 + inkcpp_test/EmptyStringForDivert.cpp | 39 ++++++++++++++++++++ inkcpp_test/ThirdTierChoiceAfterBrackets.cpp | 8 ++-- inkcpp_test/ink/EmptyStringForDivert.ink | 13 +++++++ 7 files changed, 71 insertions(+), 12 deletions(-) create mode 100644 inkcpp_test/EmptyStringForDivert.cpp create mode 100644 inkcpp_test/ink/EmptyStringForDivert.ink diff --git a/inkcpp/output.cpp b/inkcpp/output.cpp index c8bcb823..c05266c5 100644 --- a/inkcpp/output.cpp +++ b/inkcpp/output.cpp @@ -341,11 +341,15 @@ char* basic_stream::get_alloc(string_table& strings, list_table& lists) // Return processed string end = clean_string(buffer, buffer + c_str_len(buffer)); *end = 0; - _last_char = end[-1]; - if constexpr (RemoveTail) { - if (_last_char == ' ') { - end[-1] = 0; + if (end != buffer) { + _last_char = end[-1]; + if constexpr (RemoveTail) { + if (_last_char == ' ') { + end[-1] = 0; + } } + } else { + _last_char = 'e'; } return buffer; @@ -365,9 +369,8 @@ size_t basic_stream::find_start() const if (_save != ~0 && start < _save) { // TODO: check if we don't reset save correct // at some point we can modifiy the output even behind save (probally discard?) and push a new - // element -> invalid save point inkAssert(false, "Trying to access output stream prior to save - // point!"); - const_cast(*this).clear(); + // element -> invalid save point + inkAssert(false, "Trying to access output stream prior to save point!"); } return start; diff --git a/inkcpp/runner_impl.cpp b/inkcpp/runner_impl.cpp index 24043299..725ee16f 100644 --- a/inkcpp/runner_impl.cpp +++ b/inkcpp/runner_impl.cpp @@ -515,6 +515,9 @@ void runner_impl::advance_line() // can be in save state becaues of choice // Garbage collection TODO: How often do we want to do this? _globals->gc(); + if (_output.saved()) { + _output.restore(); + } } bool runner_impl::can_continue() const { return _ptr != nullptr; } diff --git a/inkcpp/value.h b/inkcpp/value.h index e2bc97f3..3e949b7e 100644 --- a/inkcpp/value.h +++ b/inkcpp/value.h @@ -35,10 +35,10 @@ namespace ink::runtime::internal { list_flag, // a single list flag string, // Pointer to string OP_END, // END of types where we can operate on - value_pointer, // a pointer to an value newline = OP_END, // newline symbol PRINT_END, // END of printable values marker = PRINT_END, // special marker (used in output stream) + value_pointer, // a pointer to an value glue, // glue symbol func_start, // start of function marker func_end, // end of function marker diff --git a/inkcpp_test/CMakeLists.txt b/inkcpp_test/CMakeLists.txt index c515fd48..85f14219 100644 --- a/inkcpp_test/CMakeLists.txt +++ b/inkcpp_test/CMakeLists.txt @@ -18,6 +18,7 @@ add_executable(inkcpp_test catch.hpp Main.cpp NoEarlyTags.cpp ExternalFunctionsExecuteProperly.cpp LookaheadSafe.cpp + EmptyStringForDivert.cpp ) target_link_libraries(inkcpp_test PUBLIC inkcpp inkcpp_compiler inkcpp_shared) diff --git a/inkcpp_test/EmptyStringForDivert.cpp b/inkcpp_test/EmptyStringForDivert.cpp new file mode 100644 index 00000000..762e3cd9 --- /dev/null +++ b/inkcpp_test/EmptyStringForDivert.cpp @@ -0,0 +1,39 @@ +#include "catch.hpp" +#include "../inkcpp_cl/test.h" + +#include +#include +#include +#include + +using namespace ink::runtime; + +SCENARIO("a story with a white space infront of an conditional Divert", "[Output]") +{ + // based on https://github.com/JBenda/inkcpp/issues/71 + GIVEN("A story") + { + inklecate("ink/EmptyStringForDivert.ink", "EmptyStringForDivert.tmp"); + ink::compiler::run("EmptyStringForDivert.tmp", "EmptyStringForDivert.bin"); + auto ink = story::from_file("EmptyStringForDivert.bin"); + runner thread = ink->new_runner(); + + WHEN("run") + { + THEN("print 'This displays first'") + { + thread->getall(); + REQUIRE(thread->has_choices()); + thread->choose(0); + REQUIRE(thread->getall() == "This displays first\n"); + REQUIRE(thread->has_choices()); + thread->choose(0); + REQUIRE(thread->getall() == "This is the continuation.\n"); + REQUIRE(thread->has_choices()); + thread->choose(0); + REQUIRE(thread->getall() == ""); + REQUIRE(! thread->has_choices()); + } + } + } +} diff --git a/inkcpp_test/ThirdTierChoiceAfterBrackets.cpp b/inkcpp_test/ThirdTierChoiceAfterBrackets.cpp index 71fbfce6..b70e41e4 100644 --- a/inkcpp_test/ThirdTierChoiceAfterBrackets.cpp +++ b/inkcpp_test/ThirdTierChoiceAfterBrackets.cpp @@ -27,16 +27,16 @@ SCENARIO( THEN("thread doesn't error") { thread->getall(); - thread->has_choices(); + REQUIRE(thread->has_choices()); thread->choose(0); thread->getall(); - thread->has_choices(); + REQUIRE(thread->has_choices()); thread->choose(0); thread->getall(); - thread->has_choices(); + REQUIRE(thread->has_choices()); thread->choose(0); thread->getall(); - thread->has_choices(); + REQUIRE(!thread->has_choices()); } } } diff --git a/inkcpp_test/ink/EmptyStringForDivert.ink b/inkcpp_test/ink/EmptyStringForDivert.ink new file mode 100644 index 00000000..d3a32fbc --- /dev/null +++ b/inkcpp_test/ink/EmptyStringForDivert.ink @@ -0,0 +1,13 @@ + - (opts) + + + [Continue] + + {opts == 1: This displays first} + + {opts < 2: -> opts} + + - This is the continuation. + + * [OK] + + -> DONE From 3772b2ca8a4f5880f9e233c08dc23714c570814c Mon Sep 17 00:00:00 2001 From: Julian Benda Date: Thu, 21 Dec 2023 14:07:01 +0100 Subject: [PATCH 2/3] formatting --- inkcpp/output.cpp | 6 +- inkcpp/value.h | 1011 +++++++++++------- inkcpp_test/ThirdTierChoiceAfterBrackets.cpp | 2 +- 3 files changed, 612 insertions(+), 407 deletions(-) diff --git a/inkcpp/output.cpp b/inkcpp/output.cpp index c05266c5..66f5ce2e 100644 --- a/inkcpp/output.cpp +++ b/inkcpp/output.cpp @@ -339,8 +339,8 @@ char* basic_stream::get_alloc(string_table& strings, list_table& lists) _size = start; // Return processed string - end = clean_string(buffer, buffer + c_str_len(buffer)); - *end = 0; + end = clean_string(buffer, buffer + c_str_len(buffer)); + *end = 0; if (end != buffer) { _last_char = end[-1]; if constexpr (RemoveTail) { @@ -369,7 +369,7 @@ size_t basic_stream::find_start() const if (_save != ~0 && start < _save) { // TODO: check if we don't reset save correct // at some point we can modifiy the output even behind save (probally discard?) and push a new - // element -> invalid save point + // element -> invalid save point inkAssert(false, "Trying to access output stream prior to save point!"); } diff --git a/inkcpp/value.h b/inkcpp/value.h index 3e949b7e..171eefa8 100644 --- a/inkcpp/value.h +++ b/inkcpp/value.h @@ -13,448 +13,653 @@ #include "types.h" #ifdef INK_ENABLE_STL -#include +# include #endif -namespace ink::runtime::internal { - class basic_stream; - - /// different existing value_types - enum class value_type { - BEGIN, // To find the start of list - none = BEGIN, // no type -> invalid - OP_BEGIN, // first type to operate on - divert = OP_BEGIN, // divert to different story position - PRINT_BEGIN, // first printable value - boolean = PRINT_BEGIN, // boolean variable - uint32, // 32bit unsigned integer variable - int32, // 32bit integer variable - float32, // 32bit floating point value - list, // id of list in list_table - list_flag, // a single list flag - string, // Pointer to string - OP_END, // END of types where we can operate on - newline = OP_END, // newline symbol - PRINT_END, // END of printable values - marker = PRINT_END, // special marker (used in output stream) - value_pointer, // a pointer to an value - glue, // glue symbol - func_start, // start of function marker - func_end, // end of function marker - null, // void value, for function returns - ex_fn_not_found, // value for failed external function calls - tunnel_frame, // return from tunnel - function_frame, // return from function - thread_frame, // return from thread - thread_start, // start of thread frame - thread_end, // end of thread frame - jump_marker // callstack jump - }; - - // add operator for value_type (to simplify usage templates). - constexpr value_type operator+(value_type t, int i) { - return static_cast(static_cast(t)+i); - } - // add operator for Command (to simplify usage in templates). - constexpr Command operator+(Command c, int i) { - return static_cast(static_cast(c)+i); - } +namespace ink::runtime::internal +{ +class basic_stream; + +/// different existing value_types +enum class value_type { + BEGIN, // To find the start of list + none = BEGIN, // no type -> invalid + OP_BEGIN, // first type to operate on + divert = OP_BEGIN, // divert to different story position + PRINT_BEGIN, // first printable value + boolean = PRINT_BEGIN, // boolean variable + uint32, // 32bit unsigned integer variable + int32, // 32bit integer variable + float32, // 32bit floating point value + list, // id of list in list_table + list_flag, // a single list flag + string, // Pointer to string + OP_END, // END of types where we can operate on + newline = OP_END, // newline symbol + PRINT_END, // END of printable values + marker = PRINT_END, // special marker (used in output stream) + value_pointer, // a pointer to an value + glue, // glue symbol + func_start, // start of function marker + func_end, // end of function marker + null, // void value, for function returns + ex_fn_not_found, // value for failed external function calls + tunnel_frame, // return from tunnel + function_frame, // return from function + thread_frame, // return from thread + thread_start, // start of thread frame + thread_end, // end of thread frame + jump_marker // callstack jump +}; + +// add operator for value_type (to simplify usage templates). +constexpr value_type operator+(value_type t, int i) +{ + return static_cast(static_cast(t) + i); +} +// add operator for Command (to simplify usage in templates). +constexpr Command operator+(Command c, int i) +{ + return static_cast(static_cast(c) + i); +} - struct string_type{ - constexpr string_type(const char* string, bool allocated) - : str{string}, allocated{allocated}{} - constexpr string_type(const char* string) - : str{string}, allocated{true} {} - operator const char*() const { - return str; - } - const char* str; - bool allocated; - }; +struct string_type { + constexpr string_type(const char* string, bool allocated) + : str{string} + , allocated{allocated} + { + } - class value; - template - class redefine { - public: - redefine(const ENV&) {} - value operator()(const T& lh, const T& rh); - }; + constexpr string_type(const char* string) + : str{string} + , allocated{true} + { + } - /** - * @brief class to wrap stack value to common type. - */ - class value : public snapshot_interface { - public: - // snapshot interface - size_t snap(unsigned char* data, const snapper&) const; - const unsigned char* snap_load(const unsigned char* data, const loader&); - - /// help struct to determine cpp type which represent the value_type - template struct ret { using type = void; }; - - constexpr value() : snapshot_interface(), bool_value{ 0 }, _type{ value_type::none } {} - constexpr explicit value( value_type type ) : bool_value{ 0 }, _type{ type } {} - - explicit value(const ink::runtime::value& val); - bool set( const ink::runtime::value& val ); - ink::runtime::value to_interface_value(list_table&) const; - - /// get value of the type (if possible) - template - typename ret::type - get() const { static_assert(ty != ty, "No getter for this type defined!"); } - - /// check if value evaluates to true - bool truthy(const list_table& lists) const; - /// set value of type (if possible) - template - constexpr value& set(Args ...args) { - static_assert(sizeof...(Args)!=sizeof...(Args), "No setter for this type defined!"); - return *this; - } + operator const char*() const { return str; } - /// get type of value - constexpr value_type type() const { return _type; } + const char* str; + bool allocated; +}; - /// returns if type is printable (see value_type) - constexpr bool printable() const { - return _type >= value_type::PRINT_BEGIN && _type < value_type::PRINT_END; - } +class value; - friend basic_stream& operator<<(basic_stream& os, const value&); - // friend basic_stream& operator>>(basic_stream& is, value&); // TODO: implement -#ifdef INK_ENABLE_STL - /** write value string to ostream - * @param lists may set to list_table if list serelasation needed - */ - std::ostream& write(std::ostream&, const list_table* lists = nullptr) const; -#endif +template +class redefine +{ +public: + redefine(const ENV&) {} - /// execute the type exclusive overwrite function and return a new value with - /// this new type - template - value redefine(const value& oth, T& ... env) const { - inkAssert(type() == oth.type(), "try to redefine value of other type"); - return redefine(oth, {&env...}); - } + value operator()(const T& lh, const T& rh); +}; - private: - template - value redefine(const value& oth, const tuple& env) const { - if constexpr ( ty == value_type::OP_END) { - inkFail("Can't redefine value with this type! (It is not an variable type!)"); - return value{}; - } else if (ty != type()) { - return redefine(oth, env); - } else { - return internal::redefine::type, tuple>(env)(get(), oth.get()); - } - } +/** + * @brief class to wrap stack value to common type. + */ +class value : public snapshot_interface +{ +public: + // snapshot interface + size_t snap(unsigned char* data, const snapper&) const; + const unsigned char* snap_load(const unsigned char* data, const loader&); - /// actual storage - union { - bool bool_value; - int32_t int32_value; - string_type string_value; - uint32_t uint32_value; - float float_value; - struct { - uint32_t jump; - uint32_t thread_id; - } jump; - list_table::list list_value; - list_flag list_flag_value; - struct { - uint32_t addr; - bool eval; // was eval mode active in frame above - } frame_value; - struct { - hash_t name; - char ci; - } pointer; - }; - static constexpr size_t max_value_size = - sizeof_largest_type< - decltype(bool_value), - decltype(int32_value), - decltype(string_value), - decltype(uint32_value), - decltype(float_value), - decltype(jump), - decltype(list_value), - decltype(list_flag_value), - decltype(frame_value), - decltype(pointer) - >(); - value_type _type; + /// help struct to determine cpp type which represent the value_type + template + struct ret { + using type = void; }; - template - value redefine::operator()(const T& lh, const T& rh) { - return value{}.set(rh); + constexpr value() + : snapshot_interface() + , bool_value{0} + , _type{value_type::none} + { } - // define get and set for int32 - template<> struct value::ret { using type = int32_t; }; - template<> inline int32_t value::get() const { return int32_value; } - template<> - inline constexpr value& value::set(int32_t v) { - int32_value = v; - _type = value_type::int32; - return *this; + constexpr explicit value(value_type type) + : bool_value{0} + , _type{type} + { } + explicit value(const ink::runtime::value& val); + bool set(const ink::runtime::value& val); + ink::runtime::value to_interface_value(list_table&) const; - // define get and set for uint32 - template<> struct value::ret { using type = uint32_t; }; - template<> inline uint32_t value::get() const { return uint32_value; } - template<> - inline constexpr value& value::set(uint32_t v) { - uint32_value = v; - _type = value_type::uint32; - return *this; + /// get value of the type (if possible) + template + typename ret::type get() const + { + static_assert(ty != ty, "No getter for this type defined!"); } - // define get and set for divert - template<> struct value::ret { using type = uint32_t; }; - template<> inline uint32_t value::get() const { return uint32_value; } - template<> - inline constexpr value& value::set(uint32_t v) { - uint32_value = v; - _type = value_type::divert; - return *this; - } + /// check if value evaluates to true + bool truthy(const list_table& lists) const; - // define get and set for float - template<> struct value::ret { using type = float; }; - template<> inline float value::get() const { return float_value; } - template<> - inline constexpr value& value::set(float v) { - float_value = v; - _type = value_type::float32; + /// set value of type (if possible) + template + constexpr value& set(Args... args) + { + static_assert(sizeof...(Args) != sizeof...(Args), "No setter for this type defined!"); return *this; } - // define get and set for boolean - template<> struct value::ret { using type = bool; }; - template<> inline bool value::get() const { return bool_value; } - template<> - inline constexpr value& value::set(bool v) { - bool_value = v; - _type = value_type::boolean; - return *this; - } - template<> - inline constexpr value& value::set(int v) { - bool_value = static_cast(v); - _type = value_type::boolean; - return *this; - } + /// get type of value + constexpr value_type type() const { return _type; } - // define get and set for list - template<> struct value::ret { using type = list_table::list; }; - template<> inline list_table::list value::get() const { return list_value; } - template<> - inline constexpr value& value::set(list_table::list list) + /// returns if type is printable (see value_type) + constexpr bool printable() const { - list_value = list; - _type = value_type::list; - return *this; + return _type >= value_type::PRINT_BEGIN && _type < value_type::PRINT_END; } - // define get and set for list_flag - template<> struct value::ret { using type = list_flag; }; - template<> inline list_flag value::get() const { return list_flag_value; } - template<> - inline constexpr value& value::set(list_flag flag) + friend basic_stream& operator<<(basic_stream& os, const value&); + // friend basic_stream& operator>>(basic_stream& is, value&); // TODO: implement +#ifdef INK_ENABLE_STL + /** write value string to ostream + * @param lists may set to list_table if list serelasation needed + */ + std::ostream& write(std::ostream&, const list_table* lists = nullptr) const; +#endif + + /// execute the type exclusive overwrite function and return a new value with + /// this new type + template + value redefine(const value& oth, T&... env) const { - list_flag_value = flag; - _type = value_type::list_flag; - return *this; + inkAssert(type() == oth.type(), "try to redefine value of other type"); + return redefine(oth, {&env...}); } - // define get and set for string - template<> struct value::ret { using type = string_type; }; - template<> inline string_type value::get() const { return string_value; } - template<> - inline constexpr value& value::set(const char* v) { - string_value = {v}; - _type = value_type::string; - return *this; - } - template<> - inline constexpr value& value::set(char* v) { - string_value = {v}; - _type = value_type::string; - return *this; - } - template<> - inline constexpr value& value::set(const char* v, bool allocated) { - string_value = {v, allocated}; - _type = value_type::string; - return *this; - } - template<> - inline constexpr value& value::set( char* v, bool allocated) { - string_value = {v, allocated}; - _type = value_type::string; - return *this; - } - template<> - inline constexpr value& value::set( - string_type str) { - string_value = str; - _type = value_type::string; - return *this; +private: + template + value redefine(const value& oth, const tuple& env) const + { + if constexpr (ty == value_type::OP_END) { + inkFail("Can't redefine value with this type! (It is not an variable type!)"); + return value{}; + } else if (ty != type()) { + return redefine(oth, env); + } else { + return internal::redefine::type, tuple>(env)( + get(), oth.get() + ); + } } - // define get and set for pointer - template<> struct value::ret { using type = decltype(value::pointer); }; - template<> inline value::ret::type value::get() const - { return pointer; } - template<> - inline constexpr value& value::set(hash_t name, int ci) { - _type = value_type::value_pointer; - pointer.name = name; - pointer.ci = ci; - return *this; - } + /// actual storage + union { + bool bool_value; + int32_t int32_value; + string_type string_value; + uint32_t uint32_value; + float float_value; - // define getter and setter for jump_marker - template<> struct value::ret { using type = decltype(value::jump); }; - template<> inline value::ret::type value::get() const { return jump; } - template<> - inline constexpr value& value::set(decltype(value::jump) v) { - jump = v; - _type = value_type::jump_marker; - return *this; - } - template<> - inline constexpr value& value::set(uint32_t v, uint32_t j) { - jump.jump = v; - jump.thread_id = j; - _type = value_type::jump_marker; - return *this; - } + struct { + uint32_t jump; + uint32_t thread_id; + } jump; - // define getter and setter for thread_start - template<> struct value::ret { using type = decltype(value::jump); }; - template<> inline value::ret::type value::get() const { return jump; } - template<> - inline constexpr value& value::set(decltype(value::jump) v) - { - jump = v; - _type = value_type::thread_start; - return *this; - } - template<> - inline constexpr value& value::set(uint32_t v, uint32_t j) { - jump.jump = v; - jump.thread_id = j; - _type = value_type::thread_start; - return *this; - } + list_table::list list_value; + list_flag list_flag_value; - // define getter and setter for thread_end - template<> struct value::ret { using type = uint32_t; }; - template<> inline uint32_t value::get() const { return uint32_value; } - template<> - inline constexpr value& value::set(uint32_t v) { - uint32_value = v; - _type = value_type::thread_end; - return *this; - } + struct { + uint32_t addr; + bool eval; // was eval mode active in frame above + } frame_value; - // define setter for values without storage - template<> - inline constexpr value& value::set() { - _type = value_type::marker; - return *this; - } - template<> - inline constexpr value& value::set() { - _type = value_type::glue; - return *this; - } - template<> - inline constexpr value& value::set() { - _type = value_type::ex_fn_not_found; - return *this; - } - template<> - inline constexpr value& value::set() { - _type = value_type::newline; - return *this; - } - template<> struct value::ret { using type = const char*; }; - template<> - inline const char* value::get() const { - static const char line_break[] = "\n"; - return line_break; - } - template<> - inline constexpr value& value::set() { - _type = value_type::func_start; - return *this; - } - template<> - inline constexpr value& value::set() { - _type = value_type::func_end; - return *this; - } - template<> - inline constexpr value& value::set() { - _type = value_type::null; - return *this; - } - template<> - inline constexpr value& value::set() { - _type = value_type::none; - return *this; - } + struct { + hash_t name; + char ci; + } pointer; + }; - // getter and setter for different frame types - // FIXME: the getter are not used? - template<> struct value::ret{ using type = decltype(frame_value); }; - template<> inline typename value::ret::type value::get() const { return frame_value; } - template<> - inline constexpr value& value::set(uint32_t v, bool evalOn) { - frame_value.addr = v; - frame_value.eval = evalOn; - _type = value_type::function_frame; - return *this; - } - // FIXME: the getter are not used? - /* template<> struct value::ret{ using type = uint32_t; }; */ - /* template<> inline uint32_t value::get() const { return uint32_value; } */ - template<> - inline constexpr value& value::set(uint32_t v, bool evalOn) { - frame_value.addr = v; - frame_value.eval = evalOn; - _type = value_type::tunnel_frame; - return *this; - } - // FIXME: the getter are not used? - /* template<> struct value::ret{ using type = uint32_t; }; */ - /* template<> inline uint32_t value::get() const { return uint32_value; } */ - template<> - inline constexpr value& value::set(uint32_t v, bool evalOn) { - frame_value.addr = v; - frame_value.eval = evalOn; - _type = value_type::thread_frame; - return *this; - } + static constexpr size_t max_value_size = sizeof_largest_type< + decltype(bool_value), decltype(int32_value), decltype(string_value), decltype(uint32_value), + decltype(float_value), decltype(jump), decltype(list_value), decltype(list_flag_value), + decltype(frame_value), decltype(pointer)>(); + value_type _type; +}; + +template +value redefine::operator()(const T& lh, const T& rh) +{ + return value{}.set(rh); +} - // static constexpr instantiations of flag values - namespace values { - static constexpr value marker = value( value_type::marker ); - static constexpr value glue = value( value_type::glue ); - static constexpr value newline = value( value_type::newline ); - static constexpr value func_start = value( value_type::func_start ); - static constexpr value func_end = value( value_type::func_end ); - static constexpr value null = value( value_type::null ); - static constexpr value ex_fn_not_found = value(value_type::ex_fn_not_found); - } +// define get and set for int32 +template<> +struct value::ret { + using type = int32_t; +}; + +template<> +inline int32_t value::get() const +{ + return int32_value; +} + +template<> +inline constexpr value& value::set(int32_t v) +{ + int32_value = v; + _type = value_type::int32; + return *this; +} + +// define get and set for uint32 +template<> +struct value::ret { + using type = uint32_t; +}; + +template<> +inline uint32_t value::get() const +{ + return uint32_value; +} + +template<> +inline constexpr value& value::set(uint32_t v) +{ + uint32_value = v; + _type = value_type::uint32; + return *this; +} + +// define get and set for divert +template<> +struct value::ret { + using type = uint32_t; +}; + +template<> +inline uint32_t value::get() const +{ + return uint32_value; +} + +template<> +inline constexpr value& value::set(uint32_t v) +{ + uint32_value = v; + _type = value_type::divert; + return *this; +} + +// define get and set for float +template<> +struct value::ret { + using type = float; +}; + +template<> +inline float value::get() const +{ + return float_value; +} + +template<> +inline constexpr value& value::set(float v) +{ + float_value = v; + _type = value_type::float32; + return *this; +} + +// define get and set for boolean +template<> +struct value::ret { + using type = bool; +}; + +template<> +inline bool value::get() const +{ + return bool_value; +} + +template<> +inline constexpr value& value::set(bool v) +{ + bool_value = v; + _type = value_type::boolean; + return *this; +} + +template<> +inline constexpr value& value::set(int v) +{ + bool_value = static_cast(v); + _type = value_type::boolean; + return *this; } + +// define get and set for list +template<> +struct value::ret { + using type = list_table::list; +}; + +template<> +inline list_table::list value::get() const +{ + return list_value; +} + +template<> +inline constexpr value& value::set(list_table::list list) +{ + list_value = list; + _type = value_type::list; + return *this; +} + +// define get and set for list_flag +template<> +struct value::ret { + using type = list_flag; +}; + +template<> +inline list_flag value::get() const +{ + return list_flag_value; +} + +template<> +inline constexpr value& value::set(list_flag flag) +{ + list_flag_value = flag; + _type = value_type::list_flag; + return *this; +} + +// define get and set for string +template<> +struct value::ret { + using type = string_type; +}; + +template<> +inline string_type value::get() const +{ + return string_value; +} + +template<> +inline constexpr value& value::set(const char* v) +{ + string_value = {v}; + _type = value_type::string; + return *this; +} + +template<> +inline constexpr value& value::set(char* v) +{ + string_value = {v}; + _type = value_type::string; + return *this; +} + +template<> +inline constexpr value& + value::set(const char* v, bool allocated) +{ + string_value = {v, allocated}; + _type = value_type::string; + return *this; +} + +template<> +inline constexpr value& value::set(char* v, bool allocated) +{ + string_value = {v, allocated}; + _type = value_type::string; + return *this; +} + +template<> +inline constexpr value& value::set(string_type str) +{ + string_value = str; + _type = value_type::string; + return *this; +} + +// define get and set for pointer +template<> +struct value::ret { + using type = decltype(value::pointer); +}; + +template<> +inline value::ret::type value::get() const +{ + return pointer; +} + +template<> +inline constexpr value& value::set(hash_t name, int ci) +{ + _type = value_type::value_pointer; + pointer.name = name; + pointer.ci = ci; + return *this; +} + +// define getter and setter for jump_marker +template<> +struct value::ret { + using type = decltype(value::jump); +}; + +template<> +inline value::ret::type value::get() const +{ + return jump; +} + +template<> +inline constexpr value& + value::set(decltype(value::jump) v) +{ + jump = v; + _type = value_type::jump_marker; + return *this; +} + +template<> +inline constexpr value& + value::set(uint32_t v, uint32_t j) +{ + jump.jump = v; + jump.thread_id = j; + _type = value_type::jump_marker; + return *this; +} + +// define getter and setter for thread_start +template<> +struct value::ret { + using type = decltype(value::jump); +}; + +template<> +inline value::ret::type value::get() const +{ + return jump; +} + +template<> +inline constexpr value& + value::set(decltype(value::jump) v) +{ + jump = v; + _type = value_type::thread_start; + return *this; +} + +template<> +inline constexpr value& + value::set(uint32_t v, uint32_t j) +{ + jump.jump = v; + jump.thread_id = j; + _type = value_type::thread_start; + return *this; +} + +// define getter and setter for thread_end +template<> +struct value::ret { + using type = uint32_t; +}; + +template<> +inline uint32_t value::get() const +{ + return uint32_value; +} + +template<> +inline constexpr value& value::set(uint32_t v) +{ + uint32_value = v; + _type = value_type::thread_end; + return *this; +} + +// define setter for values without storage +template<> +inline constexpr value& value::set() +{ + _type = value_type::marker; + return *this; +} + +template<> +inline constexpr value& value::set() +{ + _type = value_type::glue; + return *this; +} + +template<> +inline constexpr value& value::set() +{ + _type = value_type::ex_fn_not_found; + return *this; +} + +template<> +inline constexpr value& value::set() +{ + _type = value_type::newline; + return *this; +} + +template<> +struct value::ret { + using type = const char*; +}; + +template<> +inline const char* value::get() const +{ + static const char line_break[] = "\n"; + return line_break; +} + +template<> +inline constexpr value& value::set() +{ + _type = value_type::func_start; + return *this; +} + +template<> +inline constexpr value& value::set() +{ + _type = value_type::func_end; + return *this; +} + +template<> +inline constexpr value& value::set() +{ + _type = value_type::null; + return *this; +} + +template<> +inline constexpr value& value::set() +{ + _type = value_type::none; + return *this; +} + +// getter and setter for different frame types +// FIXME: the getter are not used? +template<> +struct value::ret { + using type = decltype(frame_value); +}; + +template<> +inline typename value::ret::type + value::get() const +{ + return frame_value; +} + +template<> +inline constexpr value& value::set(uint32_t v, bool evalOn) +{ + frame_value.addr = v; + frame_value.eval = evalOn; + _type = value_type::function_frame; + return *this; +} + +// FIXME: the getter are not used? +/* template<> struct value::ret{ using type = uint32_t; }; */ +/* template<> inline uint32_t value::get() const { return uint32_value; } + */ +template<> +inline constexpr value& value::set(uint32_t v, bool evalOn) +{ + frame_value.addr = v; + frame_value.eval = evalOn; + _type = value_type::tunnel_frame; + return *this; +} + +// FIXME: the getter are not used? +/* template<> struct value::ret{ using type = uint32_t; }; */ +/* template<> inline uint32_t value::get() const { return uint32_value; } + */ +template<> +inline constexpr value& value::set(uint32_t v, bool evalOn) +{ + frame_value.addr = v; + frame_value.eval = evalOn; + _type = value_type::thread_frame; + return *this; +} + +// static constexpr instantiations of flag values +namespace values +{ + static constexpr value marker = value(value_type::marker); + static constexpr value glue = value(value_type::glue); + static constexpr value newline = value(value_type::newline); + static constexpr value func_start = value(value_type::func_start); + static constexpr value func_end = value(value_type::func_end); + static constexpr value null = value(value_type::null); + static constexpr value ex_fn_not_found = value(value_type::ex_fn_not_found); +} // namespace values +} // namespace ink::runtime::internal diff --git a/inkcpp_test/ThirdTierChoiceAfterBrackets.cpp b/inkcpp_test/ThirdTierChoiceAfterBrackets.cpp index b70e41e4..3997aead 100644 --- a/inkcpp_test/ThirdTierChoiceAfterBrackets.cpp +++ b/inkcpp_test/ThirdTierChoiceAfterBrackets.cpp @@ -36,7 +36,7 @@ SCENARIO( REQUIRE(thread->has_choices()); thread->choose(0); thread->getall(); - REQUIRE(!thread->has_choices()); + REQUIRE(! thread->has_choices()); } } } From c0ccabce06e20c2712a7be688031e3fe42ea1ed5 Mon Sep 17 00:00:00 2001 From: Julian Benda Date: Thu, 21 Dec 2023 14:31:42 +0100 Subject: [PATCH 3/3] Formatting again with older clang version --- inkcpp/value.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/inkcpp/value.h b/inkcpp/value.h index 171eefa8..36207989 100644 --- a/inkcpp/value.h +++ b/inkcpp/value.h @@ -183,9 +183,8 @@ class value : public snapshot_interface } else if (ty != type()) { return redefine(oth, env); } else { - return internal::redefine::type, tuple>(env)( - get(), oth.get() - ); + return internal::redefine::type, tuple>(env + )(get(), oth.get()); } }