Appendix E – Inform language¶

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: |
|
||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Hexadecimal: |
|
||||||||||||||||||
Binary: |
|
||||||||||||||||||
Action: |
|
||||||||||||||||||
Character: |
|
||||||||||||||||||
Dictionary word: | |||||||||||||||||||
|
|||||||||||||||||||
Plural word: |
|
||||||||||||||||||
Single-character word: | |||||||||||||||||||
|
|||||||||||||||||||
String: |
|
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 valuep--
decrements p
, returns orig value--p
decrements p
, returns new valuep & 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 toq
p ~= q
p
isn’t equal toq
p > q
p
is greater thanq
p < q
p
is less thanq
p >= q
p
is greater than or equal toq
p <= q
p
is less than or equal toq
p ofclass q
object p
is of classq
p in q
object p
is a child of objectq
p notin q
object p
isn’t a child of objectq
p provides q
object p
provides propertyq
p has q
object p
has attributeq
p hasnt q
object p
hasn’t attributeq
Boolean expressions return true
or false
; if p
has determined the
result, q
is not evaluated:
p && q
both p
andq
are true (non-zero)p || q
either p
orq
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 usingindirect(routine_id,a1,a2, ... a7)
can take arguments, using
routine_id(a1,a2, ... a7)
, whose values initialise the equivalent local variablesreturns
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
attributeheld
an object held by the player noun
an object in scope noun=routine_id
an object for which routine_id
returnstrue
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 objectmultiinside
as multi
, omitting those in specified objecttopic
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;