25.28. Invocation labels, counters and storage

| Chapter 25: Extensions |

| 25.28. Invocation labels, counters and storage

The process of expanding the I6 code which represents a phrase is called "invocation". As we have seen, when a phrase is defined using a single piece of I6 code, invocation consists of copying out that I6 code, except that tokens in braces "{thus}" are replaced:

> To say (something - number): (- print {something}; -).

Ordinarily the only token names allowed are those matching up with names in the prototype, as here, but we have already seen one special syntax: "{phrase options}", which expands as a bitmap of the options chosen. And in fact the invocation language is larger still, as a skim through the Standard Rules will show. The notes below deliberately cover only some of its features: those which are likely to remain part of the permanent design of Inform, and which are adaptable to many uses. Please do not use any of the undocumented invocation syntaxes: they change frequently, without notice or even mention in the change log.

The first special syntaxes are textual tricks. {-delete} deletes the most recent character in the I6 expansion of the phrase so far. {-erase} erases the I6 expansion of the phrase so far. {-open-brace} and {-close-brace} produce literal "{" and "}" characters.

The following:

> {-counter:NAME}
> {-advance-counter:NAME}
> {-zero-counter:NAME}
> {-allocate-storage:NAME}

create (if one does not already exist) a counter called NAME. This is initially zero, and can be reset back to zero using "{-zero-counter:NAME}", which expands into no text. The token "{-counter:NAME}" expands into the current value of the counter, as a literal decimal number. The token "{-advance-counter:NAME}" does the same, but then also increases it by one. Finally, the token "{-allocate-storage:NAME}" expands to nothing, but tells Inform to create an "-->" array called "I7_ST_NAME" which includes entries from 0 up to the final value of the NAME counter.

This allows each instance in the source text of a given phrase to have both (i) a unique ID number for that invocation, and (ii) its own word of run-time storage, which can allow it to have a state preserved in between times when it is executed. For example:

> To say once only -- beginning say_once_only:
> (- {-allocate-storage:say_once_only}if (I7_ST_say_once_only-->{-counter:say_once_only} == false) {-open-brace} I7_ST_say_once_only-->{-advance-counter:say_once_only} = true; -).
> To say end once only -- ending say_once_only:
> (- {-close-brace} -).

To complete the tools available for defining a segmented substitution, we need a way for the definition of the head to know about the middle segments and the tail:

When invoking either the head or the tail, {-segment-count} expands to the literal decimal number of pieces of text in between the two, which is always one more than the number of middle segments, since the text comes in between the segments. When invoking any middle segment, {-segment-count} expands to the number of pieces of text so far -- thus it expands to 1 on the first middle segment invoked, 2 on the next, and so on.

Lastly {-final-segment-marker} expands to the I6 identifier which marks the end segment, or to I6_NULL if the end segment has no marker. The idea of markers is to enable the head's definition to know which of a number of choices has been used for the tail, supposing that this is a construction with a variety of legal endings. For example:

> To say emphasise -- beginning say_emphasise:
> (- style {-final-segment-marker}; -).
> To say with italics -- ending say_emphasise with marker underline:
> (- style roman; -).
> To say with fixed space type -- ending say_emphasise with marker fixed:
> (- style roman; -).

The markers used for the tails here are "underline" and "fixed", and when the head is invoked, the marker for its tail is expanded into the argument of I6's "style" statement.

The examples above are all to do with segmented substitutions, which is where they are most useful, but most of the syntaxes above work equally well for ordinary "To..." phrase definitions.

Previous | Contents | Next