DavidKinder / Inform6

The latest version of the Inform 6 compiler, used for generating interactive fiction games.
http://inform-fiction.org/
Other
199 stars 32 forks source link

Meta flag for grammar/action lines #278

Closed erkyrath closed 3 months ago

erkyrath commented 3 months ago

Currently when you write

Verb meta 'restart'
    * -> Restart;

...the meta flag is attached to the dict word 'restart'.

This isn't ideal. You could reasonably think about verbs which are meta in some phrasings but not others:

Verb meta 'restart'
    * -> Restart
    * noun -> SwitchOn;

Verb meta 'help'
    * -> DisplayHint
    * animate -> Help;

In these examples you'd want only the first line to be meta.

It would be better to attach the meta flag to the grammar line, as reverse already is:

Verb 'restart'
    * -> Restart meta
    * noun -> SwitchOn;

Verb 'help'
    * -> DisplayHint meta
    * animate -> Help;

In GV2, there is unused space in the grammar line flags (five free bits in Z, seven in G) so adding meta here would not be difficult. (The GV3 proposal is more compact but we could still wedge it in.)

As usual, I'd make this feature opt-in ($GRAMMAR_META_FLAG=1) and reject the new syntax if $GRAMMAR_META_FLAG was not set. To aid the library in parsing this feature, we'd define an I6 symbol GRAMMAR_META_FLAG when it was in use. (So library code could say #ifdef GRAMMAR_META_FLAG;.)

To support old game code, meta at the beginning of the declaration would roll down to all grammar lines. It would also still set the meta dict flag as it always has.

(I thought about also allowing reverse at the beginning of the declaration, again rolling down to all grammar lines. I decided that was silly.)

erkyrath commented 3 months ago

Graham sent in an alternative idea:

[...] to number the actions so that the meta-actions are exactly the ones with numbers in the range 1 <= A <= M, where M would be some compiler-declared constant like "#largest_meta_action". Code would then be able to test whether an action is meta with a single comparison instruction, we needn't store 1 bit in each grammar line, and it's impossible to get into inconsistencies where the same action is sometimes invoked as meta and sometimes not.

This fits into the existing syntax rather nicely. The standard library contains

Verb meta 'restart'
    * -> Restart;

So if you wrote

Extend 'restart'
    * noun -> SwitchOn;

...the compiler would naturally apply meta to the ##Restart action but not ##SwitchOn, and then sort them appropriately.

(I guess we'd need Extend meta to really close the loop, but that's doable.)

heasm66 commented 3 months ago

Sorting the actions and placing the meta ones first is pragmatic and would work well. It will create problem for unpacking tools, though.

I assume that the verb still get the meta-flag as before? Would it be possible to sort them so that the #largest_meta_action is of an action on a verb that got meta-flags on all actions (if there is one), like, for example, restore? Then the unpacker could scan all meta-verbs and identify the one with the largest action-number and assume that this one is the #largest_meta_number.

erkyrath commented 3 months ago

The dict word will have the meta flag if you say "Verb meta", old-style. I want to support "Verb * -> Action meta", too. In that case the dict word won't have a flag.

Anyhow, it's a bunch of extra complexity to support the disassembler case, which isn't the primary customer, as it were. I don't think it's worth it. The proposal doesn't have meta flag info anywhere in the grammar table, so the disassembler can't display meta flag info.

heasm66 commented 3 months ago

Started sketching on a solution to this issue and ran into a possible problem with ambiguity, I think?

Consider

Verb 'bother' 'curses' 'darn' 'drat'
    *                                           -> Mild meta
    * topic                                     -> Mild;

Should the action Mild be meta or not?

erkyrath commented 3 months ago

I'd say yes. Dict word flags are cumulative; might as well handle action falgs the same way.