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 + qaddition p - qsubtraction p * qmultiplication p / qinteger division p % qremainder p++increments p, returns orig value++pincrements p, returns new valuep--decrements p, returns orig value--pdecrements p, returns new valuep & qbitwise AND p | qbitwise OR ~pbitwise NOT (inversion)
Conditional expressions return true or false; q may be a list of
choices q1 or q2 or ... qN:
p == qpis equal toqp ~= qpisn’t equal toqp > qpis greater thanqp < qpis less thanqp >= qpis greater than or equal toqp <= qpis less than or equal toqp ofclass qobject pis of classqp in qobject pis a child of objectqp notin qobject pisn’t a child of objectqp provides qobject pprovides propertyqp has qobject phas attributeqp hasnt qobject phasn’t attributeq
Boolean expressions return true or false; if p has determined the
result, q is not evaluated:
p && qboth pandqare true (non-zero)p || qeither porqis true (non-zero)~~ppis 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_idwith 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_idclass class_id class_id... class_idwith 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):
propertyproperty valueproperty 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
trueat the final “]“[ routine_idlocal_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
falseat 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_blockif (expr)statement_blockelsestatement_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:
constantlo_constant to hi_constantconstant,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:
dostatement_blockuntil (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) exprthe exprin words(char) exprthe expras a single character(string) addrthe string at the addr(address) addrthe dictionary word at the addr(name) obj_idthe external (short) name of the obj_id(a) obj_idthe short name preceded by “ a/an”, by “some”, or by nothing for proper nouns(A) obj_idthe short name preceded by “ A/An”, by “Some”, or by nothing for proper nouns(the) obj_idthe short name preceded by “ the“(The) obj_idthe short name preceded by “ The“(routine_id)valuethe 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 thesestyle 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 attributean object with that attribute creaturean object with animateattributeheldan object held by the player nounan object in scope noun=routine_idan object for which routine_idreturnstruescope=routine_idan object in this re-definition of scope multiheldone or more objects held by the player multione or more objects in scope multiexceptas multi, omitting the specified objectmultiinsideas multi, omitting those in specified objecttopicany text numberany number routine_ida 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 theseIfndef 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;