Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions inkcpp/globals_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ namespace ink::runtime::internal
for(const char* i = val; *i; ++i) {
*ptr++ = *i;
}
*ptr = 0;
internal::data d;
d.set_string(new_string, true);
*v = internal::value(d);
Expand Down
6 changes: 5 additions & 1 deletion inkcpp/include/runner.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,10 @@ namespace ink::runtime
*/
virtual void choose(size_t index) = 0;

virtual bool has_tags() const = 0;
virtual size_t num_tags() const = 0;
virtual const char* get_tag(size_t index) const = 0;

protected:
// internal bind implementation. not for calling.
virtual void internal_bind(hash_t name, internal::function_base* function) = 0;
Expand Down Expand Up @@ -236,4 +240,4 @@ namespace ink::runtime
inline const choice* operator[](size_t index) { return get_choice(index); }
#pragma endregion
};
}
}
26 changes: 26 additions & 0 deletions inkcpp/runner_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@ namespace ink::runtime::internal
_num_choices = 0;
}

void runner_impl::clear_tags()
{
_num_tags = 0;
}

void runner_impl::jump(ip_t dest, bool record_visits)
{
// Optimization: if we are _is_falling, then we can
Expand Down Expand Up @@ -388,6 +393,7 @@ namespace ink::runtime::internal
// Jump to destination and clear choice list
jump(_story->instructions() + _choices[index].path());
clear_choices();
clear_tags();
}

void runner_impl::getline_silent()
Expand All @@ -397,6 +403,22 @@ namespace ink::runtime::internal
_output.clear();
}

bool runner_impl::has_tags() const
{
return _num_tags > 0;
}

size_t runner_impl::num_tags() const
{
return _num_tags;
}

const char* runner_impl::get_tag(size_t index) const
{
inkAssert(index < _num_tags, "Tag index exceeds _num_tags");
return _tags[index];
}

#ifdef INK_ENABLE_CSTD
char* runner_impl::getline_alloc()
{
Expand Down Expand Up @@ -948,6 +970,10 @@ namespace ink::runtime::internal
// Push the read count for the requested container index
_eval.push((int)_globals->visits(container));
} break;
case Command::TAG:
{
_tags[_num_tags++] = read<const char*>();
} break;
default:
inkAssert(false, "Unrecognized command!");
break;
Expand Down
12 changes: 12 additions & 0 deletions inkcpp/runner_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ namespace ink::runtime::internal
// runs silently
void getline_silent();

virtual bool has_tags() const override;
virtual size_t num_tags() const override;
virtual const char* get_tag(size_t index) const override;


#ifdef INK_ENABLE_CSTD
// c-style getline
virtual char* getline_alloc() override;
Expand Down Expand Up @@ -112,6 +117,8 @@ namespace ink::runtime::internal
choice& add_choice();
void clear_choices();

void clear_tags();

// Special code for jumping from the current IP to another
void jump(ip_t, bool record_visits = true);

Expand Down Expand Up @@ -156,6 +163,11 @@ namespace ink::runtime::internal
choice _choices[MAX_CHOICES];
size_t _num_choices = 0;

// Tag list
static const size_t MAX_TAGS = 100;
const char* _tags[MAX_TAGS];
size_t _num_tags = 0;

// TODO: Move to story? Both?
functions _functions;

Expand Down
9 changes: 8 additions & 1 deletion inkcpp_cl/inkcpp_cl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,13 @@ int main(int argc, const char** argv)
while (thread->can_continue())
std::cout << thread->getline();

if (thread->has_tags()){
std::cout << "# tags: ";
for (int i = 0; i < thread->num_tags(); ++i) {
std::cout << thread->get_tag(i) << ", ";
}
std::cout << std::endl;
}
if (thread->has_choices())
{
// Extra end line
Expand Down Expand Up @@ -175,4 +182,4 @@ int main(int argc, const char** argv)
std::cerr << "Unhandled ink runtime exception: " << e.what() << std::endl;
return 1;
}
}
}
1 change: 1 addition & 0 deletions inkcpp_compiler/command.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ namespace ink
"\n",
"<>",
"void",
"#",
"DIVERT",
"DIVERT_TO_VARIABLE",
"TUNNEL",
Expand Down
6 changes: 5 additions & 1 deletion inkcpp_compiler/json_compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ namespace ink::compiler::internal
else if (get(command, "CNT?", val))
{
// TODO: Why is this true again?
_emitter->write_path(Command::READ_COUNT, CommandFlag::NO_FLAGS, val, true);
_emitter->write_path(Command::READ_COUNT, CommandFlag::NO_FLAGS, val, false);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm going to investigate this before I approve. Just to make sure...

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, this actually needs to be true and the fact it's failing means there's another issue. With your change, the CNT? command actually won't work anymore because it's expecting an index in the container visits table, not the actual byte offset of the container in the instruction data. Can you create a new issue in GitHub with the failing file and the error message?

}

// Internal function call
Expand All @@ -318,5 +318,9 @@ namespace ink::compiler::internal
// Encode argument count into command flag and write out the hash of the function name
_emitter->write(Command::CALL_EXTERNAL, hash_string(val.c_str()), (CommandFlag)numArgs);
}
else if (get(command, "#", val))
{
_emitter->write_string(Command::TAG, CommandFlag::NO_FLAGS, val);
}
}
}
1 change: 1 addition & 0 deletions inkcpp_test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ add_executable(inkcpp_test catch.hpp Main.cpp
Restorable.cpp
Value.cpp
Globals.cpp
Tags.cpp
)

target_link_libraries(inkcpp_test PUBLIC inkcpp inkcpp_compiler)
Expand Down
96 changes: 96 additions & 0 deletions inkcpp_test/Tags.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
#include "catch.hpp"
#include "../inkcpp_cl/test.h"

#include <story.h>
#include <globals.h>
#include <runner.h>
#include <compiler.h>
#include <choice.h>

using namespace ink::runtime;

SCENARIO("run story with tags", "[tags]")
{
GIVEN("a story with tags")
{
inklecate("ink/TagsStory.ink", "TagsStory.tmp");
ink::compiler::run("TagsStory.tmp", "TagsStory.bin");
auto ink = story::from_file("TagsStory.bin");
runner thread = ink->new_runner();
WHEN("start thread")
{
THEN("No tags")
{
REQUIRE(thread->has_tags() == false);
}
WHEN("approach first line")
{
std::string line = thread->getall();
THEN("print no tags")
{
REQUIRE(line == "Hello\n");
}
THEN("collect all previous Tags (global, knot, line) in correct order")
{
REQUIRE(thread->has_tags() == true);
REQUIRE(thread->num_tags() == 4);
REQUIRE(std::string(thread->get_tag(0)) == "global_tag");
REQUIRE(std::string(thread->get_tag(1)) == "knot_tag_start");
REQUIRE(std::string(thread->get_tag(2)) == "second_knot_tag_start");
REQUIRE(std::string(thread->get_tag(3)) == "output_tag_h");
}
WHEN("print choices")
{
auto itr = thread->begin();
std::string choices[2] = {
(itr++)->text(),
(itr++)->text()
};
THEN("choices won't print tags, tags are still the same")
{
REQUIRE(choices[0] == "a");
REQUIRE(choices[1] == "b");
REQUIRE(thread->has_tags() == true);
REQUIRE(thread->num_tags() == 4);
REQUIRE(std::string(thread->get_tag(0)) == "global_tag");
REQUIRE(std::string(thread->get_tag(1)) == "knot_tag_start");
REQUIRE(std::string(thread->get_tag(2)) == "second_knot_tag_start");
REQUIRE(std::string(thread->get_tag(3)) == "output_tag_h");
}
WHEN("choose divert")
{
thread->choose(1);
THEN("choosing won't add tags!")
{
REQUIRE(thread->has_tags() == false);
REQUIRE(thread->num_tags() == 0);
}
WHEN("proceed")
{
std::string line = thread->getline();
THEN("new knot tag and now line tag, also choice tag. AND dont print tag in choice")
{
REQUIRE(line == "bKnot2\n");
REQUIRE(thread->has_tags() == true);
REQUIRE(thread->num_tags() == 3);
REQUIRE(std::string(thread->get_tag(0)) == "choice_tag_b");
REQUIRE(std::string(thread->get_tag(1)) == "knot_tag_2");
REQUIRE(std::string(thread->get_tag(2)) == "output_tag_k");
}
WHEN("choose choice without tag, and proceed to end")
{
thread->choose(0);
thread->getline();
THEN("no tags, tags behind END are ignored")
{
REQUIRE(thread->has_tags() == false);
REQUIRE(thread->num_tags() == 0);
}
}
}
}
}
}
}
}
}
21 changes: 21 additions & 0 deletions inkcpp_test/ink/TagsStory.ink
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# global_tag
->start
===start
# knot_tag_start
# second_knot_tag_start

Hello # output_tag_h
* a
* b->knot2 # choice_tag_b
- World! # output_tag_w
* c # choice_tag_c
* d # choice_tag_d
- ->END

===knot2
# knot_tag_2

Knot2 # output_tag_k
* e
* f # choice_tag_f
- out->END # close_tag
24 changes: 24 additions & 0 deletions notes/TagsNotes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
Tags are accessible via runner functions:

- `bool has_tags()` are there any tags now?
- `size_t num_tags()` how many tags are there right now?
- `const char* get_tag(size_t i)` get string value of tag

Tags are acquired until a choice appears. After choosing the acquired tags will
be cleared.
```
# Tag1
# Tag 2
Some Text # Tag3
* A # Tag 4
* B # Tag 5
- out # Tag6
```

Will produce:
> Some Text: Tag1, Tag2, Tag3
> * A
> * B
> <1
> A
> out: Tag4, Tag6
1 change: 1 addition & 0 deletions shared/private/command.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ namespace ink
NEWLINE,
GLUE,
VOID,
TAG,

// == Diverts
DIVERT,
Expand Down