Allowing for that, is this kind of writing clear?
-----------------------------------------
0.0: Introduction to IARM
This is a description of the Inform language, as precisely as I can
codify it. It is entirely didactic; Mr. Blobby has been shot. Consider
this to be the ANSI standard document for Inform and its libraries. In
contrast, GN's _The Inform Designer's Manual_ is a tutorial manual for
writing Inform games.
In most cases I have tried to codify exactly what GN's code (both C
and
Inform) actually does. There are a few exceptions, and in all of them
I
have erred on the side of tightness. That is, in some places I fail to
document usages which Inform accepts -- usually because they are
deprecated, obsolete, or redundant. All such places are marked with
footnotes.
It is, of course, incredibly presumptuous of me to write a standard
for
a language which someone else invented and wrote the only compiler
for.
Now that that's settled, let's get on with it.
Fit the First: The Bare Language
1.0 Introduction
This chapter describes the Inform language, as implemented by Inform
5.5. It contains nothing about anything defined in the standard
libraries. [fn: some differences from 5.4 are footnoted.]
The phrase "This behavior is undefined" is hacker-speak for "This may
crash your program, your computer, and possibly your telephone. Don't
do it."
1.1. Typographical Conventions
[### explain how I write grammar; [ x ] means optional x, [ x ... ]
means zero or more x, and the use of italics and boldface if I ever
get
this thing into a real format.]
1.2. Values in the Z-machine
1.2.1. Numeric Values
Numeric values are stored as 8-bit or 16-bit signed integers.
1.2.2. Addresses
Memory addresses can be stored in two ways: byte addresses or packed
addresses. Both are 16-bit unsigned values.
A byte address is a "normal" address, and thus can only refer to
locations in the range 0..65535.
A packed address is a normal address "encoded" by a fixed formula;
language constructs which accept packed addresses automatically decode
them by the inverse formula. The exact encoding and decoding formulas
depend on the version of Z-machine being compiled for:
V3: packed_address = real_address / 2; real_address =
packed_address * 2
V5: packed_address = real_address / 4; real_address =
packed_address * 4
V8: packed_address = real_address / 8; real_address =
packed_address * 8
A packed address can thus refer to any location in memory which is a
multiple of 2 (or 4, or 8.) The compiler ensures that any object which
is represented by a packed address is placed at such a location.
1.3 Variables
Variables are the parts of an Inform program which can be directly
manipulated in expressions. All variables store 16-bit signed values.
Variables have names; the scope of a variable's name can be global
(see
###) or local to a routine (see ###).
### how many globals? Probably not here.
1.4. Abstract Types and Representations
1.4.0. Introduction
Abstract objects are the parts of an Inform program which cannot be
manipulated directly. The compiler represents them in some internal
format which is better suited to the Z-machine. Each abstract object
has a name. In most cases, there is syntax to convert the name of an
abstract object to a numeric value or address; this allows the user to
manipulate references to abstract objects in expressions, and store
such references in the same way that other values are stored.
An abstract object may have more than one name. In some cases
(embedded
routines) an abstract object may have no name.
[fn: don't confuse "abstract object" with "object". ###Actually I'll
think of a better name for them.]
There are six types of abstract objects in Inform: objects, routines,
actions, properties, attributes, and dictionary words.
1.4.1. Objects
An object is a collection of related data.
An object consists of: a short-name (a string), a position in the
object
tree (see below); a set of attributes (a subset of the attributes
defined in the program; see ###); and a set of properties (a subset of
the properties defined in the program, and a storage region for each
property in that subset; see ###.)
The object tree is a set of relationships whereby an object may be
contained within another (called its parent) and may contain other
objects (called its children.) The children of an object are ordered;
the first is called the eldest child, the last its youngest child. The
predecessor and successor of an object in this ordered set are called
the object's elder and younger siblings, respectively.
Objects can be represented by numeric values. If the name of an object
appears in an expression, it is automatically converted to that
object's numeric value; no special syntax is necessary. The predefined
name "nothing" is converted to 0, which is never the numeric value of
any object.
The directed graph thus formed must be acyclic; that is, no object may
contain itself, or be its own sibling, or contain another object that
contains it, or so on. The built-in statements which manipulate the
object tree enforce this. A V3 Inform program may have up to 255
objects (whose values are in the range 1..255); a V4 or later program
may have up to 65535 objects.
1.4.2. Routines
A routine is an executable object, a function in the usual sense.
Every
Inform routine returns a numeric value.
The concepts of function arguments and local variables are merged in
Inform. A function can be defined with up to 7 local variables. When
the function is called, up to 7 arguments can be supplied. The N
arguments are copied into the first N local variables; the remaining
local variables (if any) are set to 0. (If there are more arguments
than local variables, the behavior is ###undefined?) [fn: in V3 and
earlier, no more than 3 arguments can be supplied when calling a
function.]
Routines can be represented by their addresses, normally stored as
packed addresses. If RoutineName is the name of a routine,
#r$RoutineName is an expression which evaluates to its packed address.
There is no syntax for executing a routine given its packed address;
the built-in function indirect() serves this purpose.
Neither 0 nor 65535 is ever the packed address of any routine.
1.4.3. Actions
An action is an object whose purpose is chiefly to be a constant
value.
There are a couple of syntactic constructs which use actions rather
than numeric values, but the difference is more for semantic reasons
than syntactic ones. See chapter ### for the meaning of actions.
Actions can be represented by numeric values. If ActionName is the
name
of an action, ##ActionName is an expression which evaluates to its
value.
For each action, there must also be defined an associated routine,
with
the name ActionNameSub. If actionval is the numeric value of an
action,
the expression (#actions_table-->actionval) evaluates to the packed
address of that action's associated routine. (The precise meaning of
this syntax is described in ###.)
There may be up to 256 actions defined (whose values are in the range
0..255.)
1.4.4. Properties
A property is an object which holds a region of memory for certain
objects, plus another "default" region of memory. The property may be
thought of as a function which maps an object to a storage region.
Certain objects "have the property", and thus are mapped to their own
region; all other objects "do not have the property" and thus are
mapped to the default region. The set of objects that have any given
property is determined at compile-time; a property cannot be given to
or taken from an object during execution. The sizes of the storage
regions are also determined at compile time.
The storage region can be treated either as a single value or an array
of values. There is syntax to support both usages. It is up to the
user
to keep this straight.
Properties can be represented by numeric values. If the name of a
property appears in an expression, it is automatically converted to
that property's numeric value; no special syntax is necessary. 0 is
never the value of any property; they are sequentially numbered
starting from 1.
A V3 Inform program may define up to 30 properties, and V4 or later up
to 62.
1.4.5. Attributes
An attribute is an object which either is or is not associated with
each
object. The attribute may be thought of as a set of objects; more
commonly, each object may be thought of as having a set of attributes.
Attributes may be given to or removed from objects during execution.
Attributes cannot be converted to manipulable values. The only way to
refer to an attribute is by its name.
A V3 Inform program may define up to 32 properties, and V4 or later up
to 48.
1.4.6. Dictionary Words
A dictionary word is an object which represents an input word. (There
are routines (###where?) to parse input text, which converts it to a
list of dictionary words.)
Dictionary words, unlike variables and other abstract objects, need
not
be defined to be used. The use of a dictionary word defines it
automatically, if it has not already been defined.
Dictionary words can be represented by their addresses, normally
stored
as byte addresses. The expression #n$theword evaluates to the byte
address of the word "theword" in the dictionary, defining it if it
isn't already. If the word has two or more letters, 'theword' (the
word
enclosed in single-quotes) is equivalent to #n$theword. (A single
character enclosed in single-quotes is a character literal, not a
dictionary word.)
1.5. The Structure of an Inform Program
1.5.0. Introduction
An Inform program consists of a series of directives. Each directive
defines something (an abstract object, a constant, a variable, etc.)
or
sets some condition which affects further compilation.
Most directives begin with a directive keyword (optionally preceded by
a hash sign). The exception is the routine definition, which begins
with a left square bracket. All directives are terminated by
semicolons.
1.5.1. Lexical Conventions
[### explain identifiers, whitespace, comments]
1.5.2. Expressions
1.5.3. Statements
1.5.#. Defining Attributes
attributedefinition :
Attribute attribute_id [ alias attribute_id2 ] ;
If no "alias" clause is given, this defines a new attribute with the
name attribute_id.
If an "alias" clause is given, this defines attribute_id to be a new
name for the attribute whose name is attribute_id2. attribute_id2 must
already have been defined.
1.5.#. Defining Objects
objname : object_id
parentobjname : object_id
shortnamestring : string
propertyname : property_id
attributevalue : attribute_id | ~ attribute_id
propertyvalue : numericexpression | stringexpression | embeddedroutine
objectdefinition :
Object objname [ objname ... ] shortnamestring [ parentobjname ] [ , ]
[ class classname [ classname ... ] [ , ] ]
[ with propertyname propertyvalue [ , propertyname propertyvalue ...
] [ , ] ]
[ has attributevalue [ attributevalue ... ] ] ;
objectneardefinition:
Nearby objname [ objname ... ] shortnamestring [ , ]
[ class classname [ classname ... ] [ , ] ]
[ with propertyname propertyvalue [ , propertyname propertyvalue ...
] [ , ] ]
[ has attributevalue [ attributevalue ... ] ] ;
For an object defined with Object, the parentobjname must be the name
of
an object defined earlier in the program (in which case the defined
object is initially contained within parentobjname), or nothing (0)
(in
which case the defined object is initially not contained within
anything.) An object defined with Nearby is initially contained within
the object most recently defined with Object. When several objects are
defined as being contained within another, their order (eldest to
youngest) is the order in which they are defined.
The object initially has those attributes listed in the "has" clause,
and lacks those attributes listed with a "~". If an attribute is not
listed, the object will not have it.
The object has those properties listed in the "with" clause, and the
initial values are the values given. [### explain propertyvalue,
including the special case for the name property.]
[### explain "class"]
### explain other directives
-------------------------------------------
"And Aholibamah bare Jeush, and Jaalam, and Korah: these were the borogoves..."