Dear fellow enthusiasts(?) of obscure Glk trivia,
I have spent far too much time with the Glulx/Glk dispatch mechanism this year (mostly the C thing, the JS equivalent only in passing) and I came away with a decent understanding but also some very in-the-weeds questions about the Glk prototype strings. I’m probably the only person in the world right now who has this topic fresh in their mind and not paged out entirely, but I’d be very grateful if @zarf or other Glk experts could clarify some things for me.
I first implemented the Glulx side of Glk dispatching a few months ago. It took several careful reads through both specs as well as existing implementations, and I cut some corners, but I got it working well enough. These days I’m doing it a second time, in part to fix the minor bugs and potholes left over from the first round. To avoid having to do it a third time, I want to try doing everything “right” this time, which includes thinking about the future: stuff that could theoretically occur in a prototype strings but isn’t covered by any games or test cases out there, because no existing Glk API needs it. Quite often, there’s a sensible and apparently unique meaning to these things. It took me a while to figure all of these out, but I can implement them just fine and if desired I can propose some spec clarifications to maybe make things a bit easier for the next person in the same position.
However, there’s also a bunch of possibilities that are implied or outright stated by the spec, and sometimes are (partially) implemented in Glulxe’s
glkop.c, but which are of dubious value and/or wouldn’t actually work if a new Glk API tried to use them. I’ll list these below and explain my reasoning for each. For all of them, I have the same question: Should I just reject such prototype strings in my interpreter? Or am I missing something and setting myself up for having to go back and add it in the future? In other words: am I reading tea leaves and seeing things that were never intended, or were these possibilities once considered but since abandoned, or may they still come to life eventually?
Nested Structs: the Glk spec says: “Currently, structures in Glk contain only basic types.” – which leaves open the possibility of adding other types in the future. I’ll start with structs, or rather, references to them. Glulxe has code that appears to anticipate nested structs, but this support is admittedly incomplete, while Quixe doesn’t even try. It also doesn’t appear to be really necessary: even if nested structs appeared in a Glk API, they could be flattened for the purpose of dispatching (e.g.,
&[4IuIuIuIu] instead of
&[2&[2IuIu]&[2IuIu]]), which basically achieves the same effect with less ceremony.
References (to basic types) in structs: in theory this is a bit less complicated to support than arbitrary nesting of structs, but at the same time has even less motivation (from the Glulx perspective, it’s just extra indirection without any apparent benefit). I believe it also turns out that Glulxe and Quixe don’t support it for the same reasons as with nested structs.
Strings in structs: the structs in use today only contain integers and Glk objects, but if they may contain any basic type then that includes ‘S’ and ‘U’ strings. Glulxe appears to support this without any issue, but Quixe doesn’t: when converting struct fields, it handles integers and chars and Glk objects, but not strings. Once again, such a prototype wouldn’t really enable anything you couldn’t express differently, considering that ‘S’ and ‘U’ strings are read-only and thus could only be used with pass-in structs. Still, it’s conceivable from a C perspective and neither spec seems to explicitly support or forbid it.
References to strings: although the Glk spec notes that pass-in references to basic types are generally not useful, a pass-in reference to a string is conceivable and supported in Glulxe (as a side effect of how it handles references to basic types). There’s no ambiguity about how they should work, nor do I see anything ruling them out (useless as they may be). However, I’ll note that Quixe doesn’t support them, and I’m also unsure whether I want to bother carving out support for them in my interpreter. Currently it doesn’t fall out for free, but maybe this will change as I keep iterating on it.
Arrays of strings: as with structs and plain references, the read-only nature of strings means they could only sensibly be used for pass-in arrays. Unlike the other examples, they seem more plausibly useful, in that there’s no obvious way to easily achieve the same effect by other means. On the other hand, no existing interpreter supports them nor has any traces of ever trying to anticipate support for them.
Float values: among the basic types is ‘F’ for floats, with a note that it’s not currently used, and no interpreter implements them. Perhaps it’s better that they (the C-based ones at least) don’t try, since
gluniversal_t so far lacks a designated float field. One could try stuffing the float bits into the
uint field, as Glulx doesn’t have a float/int distinction to begin with and effectively mandates the interpreter to speak IEEE-754 anyway. But who knows if that’s actually what the dispatch layer addition for a hypothetical future Glk API with float arguments would expect?