Appendix E – Inform language

../_images/picR.png

efer to this appendix for a succinct but essentially complete summary of the Inform programming language; it covers everything that we’ve met in this guide, plus various constructs which didn’t occur naturally, and others of an advanced or obscure nature.

Literals

In the specialised language of computing, the basic unit of data storage is an eight-bit byte, able to store a value 0..255. That’s too small to be useful for holding anything other than a single character, so most computers also work with a group of two, four or eight bytes known as a word (not to be confused with Inform’s dictionary word). In the Z-machine a storage word comprises two bytes, and you can specify in various ways the literal values to be stored.

Decimal:

-32768 to 32767

Hexadecimal:

$0 to $FFFF

Binary:

$$0 to $$1111111111111111

Action:

##Look

Character:

'a'

Dictionary word:
 

'aardvark' (up to nine characters significant); use circumflex “^” to denote apostrophe.

Plural word:

'aardvarks//p'

Single-character word:
 

"a" (name property only) or 'a//'

String:

"aardvark's adventure" (maximum around 4000 characters); can include special values including:

^ newline
~ double quotes “"
@@64 at sign “@
@@92 backslash “\
@@94 circumflex “^
@@126 tilde “~
@`a a with a grave accent “à”, et al
@LL pound sign “£”, et al
@00 ... @31 low string 0..31

Names

The identifier of an Inform const_id, var_id, array, class_id, obj_id, property, attribute, routine_id or label. Up to 32 characters: alphabetic (case not significant), numeric and underscore, with the first character not a digit.

Constants

Named word values, unchanging at run-time, which are by default initialised to zero:

Constant const_id;
Constant const_id = expr;

Standard constants are true (1), false (0) and nothing (0), also NULL (-1). Additionally, WORDSIZE is the number of bytes in a storage word: 2 for the Z-machine, 4 for Glulx.

To define a constant (unless it already exists):

Default const_id expr;

Variables and arrays

Named word/byte values which can change at run-time and are by default initialised to zero.

A global variable is a single word:

Global var_id;
Global var_id = expr;

A word array is a set of global words accessed using array->0,array->1,... array->(N-1):

Array array --> N;
Array array --> expr1 expr2... exprN;
Array array --> "string";

A table array is a set of global words accessed using array->1, array->2,... array->N, with array->0 initialised to N:

Array array table N;
Array array table expr1... exprN;
Array array table "string";

A byte array is a set of global bytes accessed using array->0, array->1,... array->(N-1):

Array array -> N;
Array array -> expr1 expr2... exprN;
Array array -> "string";

A string array is a set of global bytes accessed using array->1, array->2,... array->N, with array->0 initialised to N:

Array array string N;
Array array string expr1... exprN;
Array array string "string";

A buffer array is a set of global bytes accessed using array->(WORDSIZE), array->(WORDSIZE+1), ... array->(WORDSIZE+N-1), with the first word array->0 initialised to N:

Array array buffer N;
Array array buffer expr1... exprN;
Array array buffer "string";

In all these cases, the characters of the initialising string are unpacked to the individual word/byte elements of the array.

See also Objects (for property variables) and Routines (for local variables).

Expressions and operators

Use parentheses (...) to control the order of evaluation.

Arithmetic/logical expressions support these operators:

p + q addition
p - q subtraction
p * q multiplication
p / q integer division
p % q remainder
p++ increments p, returns orig value
++p increments p, returns new value
p-- decrements p, returns orig value
--p decrements p, returns new value
p & q bitwise AND
p | q bitwise OR
~p bitwise NOT (inversion)

Conditional expressions return true or false; q may be a list of choices q1 or q2 or ... qN:

p == q p is equal to q
p ~= q p isn’t equal to q
p > q p is greater than q
p < q p is less than q
p >= q p is greater than or equal to q
p <= q p is less than or equal to q
p ofclass q object p is of class q
p in q object p is a child of object q
p notin q object p isn’t a child of object q
p provides q object p provides property q
p has q object p has attribute q
p hasnt q object p hasn’t attribute q

Boolean expressions return true or false; if p has determined the result, q is not evaluated:

p && q both p and q are true (non-zero)
p || q either p or q is true (non-zero)
~~p p is false (zero)

To return -1, 0 or 1 based on unsigned comparison:

UnsignedCompare(p,q)

To return true if object q is a child or grandchild or... of p:

IndirectlyContains(p,q)

To return the closest common parent of two objects (or nothing):

CommonAncestor(p,q)

To return a random number 1..N, or one from a list of constant values:

random(N)
random(value,value, ... value)

Classes and objects

To declare a class_id - a template for a family of objects - where the optional (N) limits instances created at run-time:

Class class_id(N)
class class_id class_id... class_id
with prop_def,
...
prop_def,
has   attr_def attr_def... attr_def;

To declare an obj_id, “Object” can instead be a class_id, the remaining four header items are all optional, and arrows (->, -> ->, ...) and parent_obj_id are incompatible:

Object arrows obj_id "ext_name" parent_obj_id
class class_id class_id... class_id
with prop_def,
...
prop_def,
has    attr_def attr_def... attr_def;

The class, with and has (and also the rarely-used private) segments are all optional, and can appear in any order.

To determine an object’s class as one of Class, Object, Routine, String (or nothing):

metaclass(obj_id)

has segment: Each attr_def is either of:

attribute
~attribute

To change attributes at run-time:

give obj_id attr_def... attr_def;

with/private segments: Each prop_def declares a variable (or word array) and can take any of these forms (where a value is an expression, a string or an embedded routine):

property
property value
property value value... value

A property variable is addressed by obj_id.property (or within the object’s declaration as self.property).

Multiple values create a property array; in this case obj_id.#property is the number of bytes occupied by the array, the entries can be accessed using obj_id.&property-->0, obj_id.&property->1, ..., and obj_id.property refers to the value of the first entry.

A property variable inherited from an object’s class is addressed by obj_id.class_id::property; this gives the original value prior to any changes within the object.

Manipulating the object tree

To change object relationships at run-time:

move obj_id to parent_obj_id;
remove obj_id;

To return the parent of an object (or nothing):

parent(obj_id)

To return the first child of an object (or nothing):

child(obj_id)

To return the adjacent child of an object’s parent (or nothing):

sibling(obj_id)

To return the number of child objects directly below an object:

children(obj_id)

Message passing

To a class:

class_id.remaining()
class_id.create()
class_id.destroy(obj_id)
class_id.recreate(obj_id)
class_id.copy(to_obj_id,from_obj_id)

To an object:

obj_id.property(a1,a2, ... a7)

To a routine:

routine_id.call(a1,a2, ... a7)

To a string:

string.print()
string.print_to_array(array)

Uncommon and deprecated statements

To jump to a labelled statement:

jump label;
...
.label; statement;

To terminate the program:

quit;

To save and restore the program state:

save label;
...
restore label;

To output the Inform compiler version number:

inversion;

To accept data from the current input stream:

read text_array parse_array routine_id;

To assign to one of 32 ‘low string’ variables:

string N "string";
Lowstring string_var "string";
string N string_var;

Statements

Each statement is terminated by a semicolon “;”.

A statement_block is a single statement or a series of statements enclosed in braces {...}.

An exclamation “!” starts a comment - the rest of the line is ignored.

A common statement is the assignment:

var_id = expr;

There are two forms of multiple assignment:

var_id = var_id = ... = expr;
var_id = expr, var_id = expr, ... ;

Routines

A routine can have up to 15 local variables: word values which are private to the routine and which by default are set to zero on each call.

Recursion is permitted.

A standalone routine:

  • has a name, by which it is called using routine_id(); can also be called indirectly using indirect(routine_id,a1,a2, ... a7)

  • can take arguments, using routine_id(a1,a2, ... a7), whose values initialise the equivalent local variables

  • returns true at the final “]

    [ routine_id
    local_var local_var... local_var;
    statement;
    statement;
    ...
    statement;
    ];

A routine embedded as the value of an object property:

  • has no name, and is called when the property is invoked; can also be called explicitly using obj_id.property()

  • accepts arguments only when called explicitly

  • returns false at the final “]

    property [
    local_var local_var... local_var;
    statement;
    statement;
    ...
    statement;
    ]

Routines return a single value, when execution reaches the final “]” or an explicit return statement:

return expr;
return;
rtrue;
rfalse;

Flow control

To execute statements if expr is true; optionally, to execute other statements if expr is false:

if (expr)
statement_block

if (expr)
statement_block
else
statement_block

To execute statements depending on the value of expr:

switch (expr) {
value: statement;... statement;
value: statement;... statement;
...
default: statement;... statement;
}

where each value can be given as:

constant
lo_constant to hi_constant
constant,constant,... constant

And, if you really must:

jump label;
...
.label; statement;

Loop control

To execute statements while expr is true:

while (expr)
statement_block

To execute statements until expr is true:

do
statement_block
until (expr)

To execute statements while a variable changes:

for (set_var : loop_while_expr : update_var)
statement_block

To execute statements for all defined objects:

objectloop (var_id)
statement_block

To execute statements for all objects selected by expr:

objectloop (expr_starting_with_var)
statement_block

To jump out of the current innermost loop or switch:

break;

To immediately start the next iteration of the current loop:

continue;

Displaying information

To output a list of values:

print value,value,... value;

To output a list of values followed by a newline, then return true from the current routine:

print_ret value,value,... value;

If the first (or only) value is a string, “print_ret” can be omitted:

"string",value, ... value;

Each value can be an expression, a string or a rule.

An expression is output as a signed decimal value.

A string in quotes “...” is output as text.

A rule is one of:

(number) expr the expr in words
(char) expr the expr as a single character
(string) addr the string at the addr
(address) addr the dictionary word at the addr
(name) obj_id the external (short) name of the obj_id
(a) obj_id the short name preceded by “a/an”, by “some”, or by nothing for proper nouns
(A) obj_id the short name preceded by “A/An”, by “Some”, or by nothing for proper nouns
(the) obj_id the short name preceded by “the
(The) obj_id the short name preceded by “The
(routine_id)value the output when calling routine_id(value)

To output a newline character:

new_line;

To output multiple spaces:

spaces expr;

To output text in a display box:

box "string" "string"... "string";

To change from regular to fixed-pitch font:

font off;
...
font on;

To change the font attributes:

style bold;          ! use any of these
style underline;     !
style reverse;       !
...
style roman;

Verbs and actions

To specify a new verb:

Verb 'verb' 'verb'... 'verb'
* token token... token -> action
* token token... token -> action
...
* token token... token -> action

where instead “Verb” can be “Verb meta”, “action” can be “action reverse”; tokens are optional and each is one of:

'word' that literal word
'w1'/'w2'/... any one of those literal words
attribute an object with that attribute
creature an object with animate attribute
held an object held by the player
noun an object in scope
noun=routine_id an object for which routine_id returns true
scope=routine_id an object in this re-definition of scope
multiheld one or more objects held by the player
multi one or more objects in scope
multiexcept as multi, omitting the specified object
multiinside as multi, omitting those in specified object
topic any text
number any number
routine_id a general parsing routine

To add synonyms to an existing verb:

Verb 'verb' 'verb'... =
'existing_verb';

To modify an existing verb:

Extend 'existing_verb' last
* token token... token -> action
* token token... token -> action
...
* token token... token -> action

where instead “Extend” can be “Extend only” and “last” can be omitted, or changed to “first” or “replace”.

To explicitly trigger a defined action (both noun and second are optional, depending on the action):

<action noun second>;

To explicitly trigger a defined action, then return true from the current routine:

<<action noun second>>;

Other useful directives

To set compiler switches at the very start of the source file:

!% list_of_compiler_switches;

To include a directive within a routine definition [...], insert a hash “#” as its first character.

To conditionally compile:

Ifdef name;       ! use any one of these
Ifndef name;      !
Iftrue expr;      !
Iffalse expr;     !
...
Ifnot;
...
Endif;

To display a compile-time message:

Message "string";

To include the contents of a file, searching the Library path:

Include "source_file";

To include the contents of a file in the same location as the current file:

Include ">source_file";

To specify that a library routine is to be replaced:

Replace routine_id;

To set the game’s release number (default is 1), serial number (default is today’s yymmdd) and status line format (default is score):

Release expr;
Serial "yymmdd";
Statusline score;
Statusline time;

To declare a new attribute common to all objects:

Attribute attribute;

To declare a new property common to all objects:

Property property;
Property property expr;

Uncommon and deprecated directives

You’re unlikely to need these; look them up in the Inform Designer’s Manual if necessary.

Abbreviate "string"... "string";
End;
Import var_id var_id ... var_id;
Link "compiled_file";
Stub routine_id N;
Switches list_of_compiler_switches;
System_file;