JBenda / inkcpp

Inkle Ink C++ Runtime with JSON>Binary Compiler
MIT License
70 stars 13 forks source link

Add ListSupport (+Ink Proof completed) #17

Closed JBenda closed 3 years ago

JBenda commented 3 years ago

Add List support and tweak output and logic to pass ink-proof and run complex ink stories.

brwarner commented 3 years ago

A couple thoughts I had while reading

Since each story has a fixed number of possible lists/values which we know at runtime, could lists be stored as one giant bit mask instead of a set? For example, suppose we open a story file and see it has 5 lists each with 4 possible values. We know that means there's only 20 possible flags for each variable and thus any list variable only has to be a single 32-bit uint. However, if there's 20 lists of 10 values, we'd know each list variable needs to be 8 32-bit uints. I guess the downside of this is that each list variable would be the largest it possibly has to be (even if it only ever holds one flag). It would mean however that changing the value of a list requires less memory management.

But that brings me to another question... which is, are lists variables immutable? Would we ever actually modify one? I guess it depends how we handle things. If I set a variable equal to another variable's value, does it copy or simply copy the ref to our list value in the table? If it copies the ref, we basically can never mutate them and any modifications result in a copy and mutate.

Anyway, none of these are really concrete requests to go one way or another. Just me thinking aloud. Either way we need to have a list table.

JBenda commented 3 years ago

An example of the encoding desrcipt in the notes, just for clarification ^^

InkCode:

LIST animals = tiger, cat, (dog), bird
LIST rooms = kitchen, garage, (living_room)

InkJson:

{
    ...,
    {
        "global decl": [
            "ev",
            {
                "list": {
                    "animals.dog": 3
                }
            },
            {
                "VAR=": "animals"
            },
            {
                "list": {
                    "rooms.living_room": "3"
                }
            },
            {
                "VAR=": "rooms"
            }
            ...
        ]
    }
    "listDefs": {
        "animals": {
            "tiger": 1,
            "cat": 2,
            "dog": 3,
            "bird": 4
        },
        "rooms": {
            "kitchen": 1,
            "garage": 2,
            "living_room": 3
        }
    }
}

Encoding:

keys: ["tiger", "cat", "dog", "bird", "kitchen", "garage", "living_room"]
fid: [0,4]
entries: [0b100010000..., 0b010000001...]

encoding:
entry[0] = contains flags from list animals?
entry[1] = contains flags from list rooms?
entry[2] = tiger?
entry[3] = cat?
entry[4] = dog?
entry[5] = bird?
entry[6] = kitchen?
entry[7] = garage
entry[8] = living_room
JBenda commented 3 years ago

The mutable thing is a good point, It seems like that's each result of an operation results in a new list, and assignment is just an assignment of reference

brwarner commented 3 years ago

Got it to compile and run the intercept on my machine successfully. I saw a few whitespace issues (newlines where there shouldn't be) but I got no errors. I did some looking over the code (I'd looked over a lot of the new value stuff in the old PR) but honestly it's just way to much for me to review personally. I think at this point, unless there's something specific you're worried about you want me to look at, I can just merge this in and we see what happens. I'm confident in your judgements.

JBenda commented 3 years ago

It feels quite completed for me. The string output logic is quite a mess with the gluing :sweat_smile:. And with the tests now also running on Windows, it should be fine. :+1: pls merge ^^