Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Access global Ink variables [v2] #14

Merged
merged 12 commits into from
Feb 17, 2021
Merged

Access global Ink variables [v2] #14

merged 12 commits into from
Feb 17, 2021

Conversation

JBenda
Copy link
Owner

@JBenda JBenda commented Feb 7, 2021

Enables reading and writing of INK global variables from C++ code.

Use template function in class global to access them.

class {
	// @brief access global variable from ink story
	// @param name name of variable (as defined in Ink Script)
	// @return nullptr if there is no such variable
	// @return pointer to variable
	template<typename T>
	T* get_global(const char* name);
}

@JBenda
Copy link
Owner Author

JBenda commented Feb 7, 2021

So here we are again ^^

There is still the thing with strings, a read access is no problem, therefor we can just stash them and handle the pointer, a write access is quite a tricky thing I would postpone to a later point.

I will think about it the next few days, but I am not optimistic.
Maybe a String access class which only give read access, but you can ask to privilege it to write access (which then will make a static string to an allocated and then edit this, but what happens when you want to set it to a static string, than you are not allowed to free it later on, etc. [maybe a maximal string size? -> no reallocation, but memory cost])

@JBenda JBenda marked this pull request as draft February 7, 2021 23:41
@brwarner
Copy link
Collaborator

brwarner commented Feb 8, 2021

I'm fine with string writing being added later. There's a bunch of holes in the runtime right now concerning strings. Thinking about how to implement it though...

I think you're right about returning some kind of special "container" class. It would support read-access (maybe via overloading []/==/etc.). For writing, maybe we'd just overload the assignment operator. When you assign, it asks the globals object to create a new string using its string_table (not sure if you've looked into it yet, but it's how I deal with dynamically allocating strings during runtime when it's necessary to do so) and then throw that pointer into the variable.

You don't have to worry about GC with the string table. The runtime periodically runs through all variables and deletes any entries in the string table it can't find in any of them.

I think we just wouldn't allow write access that wasn't assignment. I can hardly see a use case where someone wants to read a variable and just muck with a few of its characters. If they really want to do that, they can copy the value into a std;:string or something and just assign it back to our special string container.

@JBenda
Copy link
Owner Author

JBenda commented Feb 8, 2021

That's sounds good, I will try it this week ^^

@JBenda
Copy link
Owner Author

JBenda commented Feb 8, 2021

It's an idea of how it can work, it's only a scratch now, but it seems to work

friend class ink::runtime::internal::globals_impl;
global_string(const internal::globals_impl& globals, const char* string);

const internal::globals_impl& _globals;
Copy link
Collaborator

Choose a reason for hiding this comment

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

This should actually use the shared_ptr globals defined in types.h. Remember that it's possible for the globals object to be destroyed while one of these global_strings is in scope (imagine the user reads the value of a variable, stores that somewhere, then lets the ink story and runners die). The shared pointer can guard you against that. Just make sure you check it for validity and maybe throw an exception if they try to do a write when it's not valid.

}

const char * const * globals_impl::get_str(hash_t name) const {
return fetch_variable<const char*, &value::as_str_ptr>(
Copy link
Collaborator

Choose a reason for hiding this comment

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

This will fail if the value is a string composed of multiple concatenated data types that aren't strings. Example 5 + "hi" + 4. get_data_type() just returns the type of the first piece of data in the value. It's type() that does the resolution to realize that a value with a mix of numbers and strings is actually a string.

Copy link
Owner Author

Choose a reason for hiding this comment

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

Oh, yes, this is a thing, because:
The getter is const, but modifying a value is not, maybe we can make the _variables mutable? I don't realy see a other way to solve this problem,
creating each time a new string table entry and write it is also possible, but then we must parse it every time ...

also the get<const char*> should contain a warning that the value is only valid until the next runner call ^^

@brwarner
Copy link
Collaborator

Wasn't sure if this was ready for review yet but I went through it and only really found one issue.

@JBenda
Copy link
Owner Author

JBenda commented Feb 13, 2021

No problem, I would wrap it up this weekend.
I always appreciate when someone else (especially when he knows the code base better) take a look at my code.
But often I hesitate to ask, because it is a time investment. So I'm very grateful that you review so frequently, thank you.

@brwarner
Copy link
Collaborator

But often I hesitate to ask, because it is a time investment

Just leave a comment saying you'd like a review before proceeding and I'll do it when I can. Don't worry about sounding pestering. You're making this project move faster, not slower. I actually need to dedicate less time to it because of you :)

{
GIVEN ("a story with global variables")
{
story* ink = story::from_file("ink/GlobalStory.bin");
Copy link
Collaborator

Choose a reason for hiding this comment

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

I actually just merged in a PR that makes sure the Inklecate compiler is available on all OSs so you can go back to loading from the ink file directly.

#21

Copy link
Owner Author

Choose a reason for hiding this comment

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

nice

@JBenda
Copy link
Owner Author

JBenda commented Feb 14, 2021

This should be functional know :)
Pls check if I don't have done something silly.

@JBenda JBenda marked this pull request as ready for review February 14, 2021 16:38
@JBenda JBenda requested a review from brwarner February 15, 2021 11:25
@brwarner
Copy link
Collaborator

Cool. I'll take a look tomorrow :)

Copy link
Collaborator

@brwarner brwarner left a comment

Choose a reason for hiding this comment

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

Everything looks good and so do the test cases. Great job on this. I saw one errant FIXME comment which I think you can just remove now? Other than that, it's good to merge.

inkcpp/value.h Outdated Show resolved Hide resolved
@brwarner
Copy link
Collaborator

If you fix the merge conflict in value.cpp I'll merge the branch in.

@JBenda
Copy link
Owner Author

JBenda commented Feb 17, 2021

Thank you for the review.
The FIXME slipped me ^^

The branch is now rebased to master.

@brwarner brwarner merged commit 8c3f506 into JBenda:master Feb 17, 2021
@JBenda JBenda deleted the feature/GetGlobals branch February 22, 2021 11:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants