Next: 1.2 Syntax
Up: 1. Onyx Language Reference
Previous: 1. Onyx Language Reference
  Contents
  Index
1.1 Objects
An Onyx object has three aspects: type, attribute, and value.
Objects fall into two categories according to type: simple and composite. A
simple object takes up no memory of its own; it uses space within a stack,
array, or dictionary. A composite object requires space of its own in addition
to the space taken up in stacks, arrays, or dictionaries to refer to the
composite object. See Table 1.1 for object type
classifications.
Table 1.1:
Simple and composite types
Simple |
Composite |
boolean |
array |
fino |
condition |
integer |
dict |
mark |
file |
name |
hook |
null |
mutex |
operator |
stack |
pmark |
string |
real |
thread |
|
There can be multiple references that refer to the same memory backing composite
objects. In most cases, composite objects that refer to the same memory are
indistinguishable, but for arrays and strings, composite objects may only be
able to access a subset of the total memory backing them. This behavior is
described in detail later.
All objects have a literal, executable, or evaluatable attribute associated with
them. Composite objects each have their own attribute, even for composite
objects that share the same backing memory. Objects are ``interpreted'' when
they are encountered directly by the interpreter. Objects can also be
``evaluated''. One of two actions is taken when an object is interpreted or
evaluated:
- The object may be treated as code (executed). When executed, an object is
pushed onto the execution stack and executed.
- The object may be treated as data. A data object is push onto the operand
stack.
Table 1.2 enumerates under what circumstances object interpretation
results in execution. Table 1.3 enumerates under what circumstances
object evaluation results in execution. Note that executable arrays are the
only objects that behave differently when interpreted versus evaluated.
In practice, attributes are only useful for types that can be executed.
Attributes are not considered in equality test operations.
Table 1.2:
Interpretation of objects by type and attribute
Type |
Attribute |
|
literal |
executable |
evaluatable |
array |
data |
data |
code |
boolean |
data |
data |
data |
condition |
data |
data |
data |
dict |
data |
data |
data |
file |
data |
code |
code |
fino |
data |
data |
data |
hook |
data |
code |
code |
integer |
data |
data |
data |
mark |
data |
data |
data |
mutex |
data |
data |
data |
name |
data |
code |
code |
null |
data |
code |
code |
operator |
data |
code |
code |
pmark |
data |
data |
data |
real |
data |
data |
data |
stack |
data |
data |
data |
string |
data |
code |
code |
thread |
data |
data |
data |
|
Table 1.3:
Evaluation of objects by type and attribute
Type |
Attribute |
|
literal |
executable |
evaluatable |
array |
data |
code |
code |
boolean |
data |
data |
data |
condition |
data |
data |
data |
dict |
data |
data |
data |
file |
data |
code |
code |
fino |
data |
data |
data |
hook |
data |
code |
code |
integer |
data |
data |
data |
mark |
data |
data |
data |
mutex |
data |
data |
data |
name |
data |
code |
code |
null |
data |
code |
code |
operator |
data |
code |
code |
pmark |
data |
data |
data |
real |
data |
data |
data |
stack |
data |
data |
data |
string |
data |
code |
code |
thread |
data |
data |
data |
|
- array:
- An array is an ordered sequence of objects of any type. The
sequence of objects contained in an array is indexed starting at 0. References
to existing arrays may be constructed such that a contiguous subsequence is
visible. The following code creates such an array:
[0 1 2 3 4]
1 3 getinterval
After the code executes, the array left on the operand stack looks like:
[1 2 3]
Executable arrays are in effect procedures. When an array is executed, its
elements are sequentially interpreted.
- boolean:
- A boolean can have two values: true or false.
- condition:
- A condition is used for thread synchronization. The standard
operations on a condition are to wait and to signal.
- dict:
- A dict (short for dictionary) is a collection of key/value pairs.
Other names for dictionaries include ``associative array'' and ``hash''. A key
can be of any type, though in most cases, keys are of type name. A value can
also be of any type.
- file:
- A file is a handle to an ordered sequence of bytes with a current
position. Read and write permissions are set when a file object is created.
When an executable file is executed, it is used as a source of Onyx code. Data
are sequentially read from the file and interpreted until the end of the file is
reached.
- fino:
- A fino (first in, never out) is used as a stack marker when
constructing stacks.
- hook:
- The hook type is not used by the core Onyx language. It can be
used by applications that extend the interpreter as a container object. Hooks
can be executed, but the results are application dependent.
Each hook has a tag associated with it that can used by C extension code as a
form of type checking. By default, the tag is a null object. In most cases, an
application that extends the interpreter using hook objects will set hook tags
to be name objects.
- integer:
- An integer is a signed integer in the range
to
.
- mark:
- A mark is used as a stack marker for various stack operations.
- mutex:
- A mutex is a mutual exclusion lock. Mutexes cannot be acquired
recursively, and the application must take care to unlock mutexes before
allowing them to be garbage collected (whether during normal program execution
or at program termination).
- name:
- A name is a key that uniquely identifies a sequence of characters.
Two name objects that correspond to the same sequence of characters can be
compared for equality with the same approximate cost as comparing two integers
for equality. Names are typically used as keys in dictionaries.
When an executable name is executed, the topmost value in the dictionary stack
associated with the name is evaluated.
- null:
- A null has no significance other than its existence. When an
executable null is executed, it does nothing. Executable nulls can be useful as
place holders that can later be replaced with useful code, or for replacing
obsolete code so that the code is no longer executed.
- operator:
- An operator is an operation that is built in to the
interpreter. Operators can be executed.
- pmark:
- A pmark is used as a stack marker when creating procedures in
deferred execution mode (i.e. procedures that use the {} syntax). The
application will only encounter pmarks in error conditions, and there is never a
reason for an application to explicitly create a pmark.
- real:
- A real is a double precision (64 bit) floating point number.
- stack:
- A stack provides LIFO (last in, first out) access to objects that
it contains, as well as some more advanced access methods. An application can
create, then manipulate stacks in much the same way that the operand stack can
be manipulated.
- string:
- A string is an ordered sequence of 8 bit characters. The bytes
contained in an string are indexed starting at 0. References to existing
strings may be constructed such that a contiguous subsequence is visible. The
following code creates such a string:
`abcde'
1 3 getinterval
After the code executes, the string left on the operand stack looks like:
`bcd'
When an executable string is executed, its contents are used as a source of Onyx
code.
- thread:
- A thread object serves as a handle for operations such as
detaching and joining.
Next: 1.2 Syntax
Up: 1. Onyx Language Reference
Previous: 1. Onyx Language Reference
  Contents
  Index
Jason Evans
2002-03-30