Next: 2.2 Syntax
Up: 2. Onyx Language Reference
Previous: 2. Onyx Language Reference
Contents
Index
2.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 another object
(typically a stack, array, or dictionary). A composite object requires space of
its own in addition to the space taken up in another object to refer to the
composite object. See Table 2.1 for object type
classifications.
Table 2.1:
Simple and composite types
Simple |
Composite |
boolean |
array |
fino |
class |
integer |
condition |
mark |
dict |
name |
file |
null |
handle |
operator |
instance |
pmark |
mutex |
real |
regex |
|
regsub |
|
stack |
|
string |
|
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, evaluable, callable, invokable, or
fetchable 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''. Objects are handled as one of
the following cases when interpreted or evaluated:
- code:
- An object may be treated as code and be executed. When executed, an
object is pushed onto the execution stack and executed.
- data:
- An object may be treated as data. A data object is push onto the
operand stack. All literal objects are treated as data.
- mkey:
- A callable object is executed and treated as a method key. When a
callable object is executed, the following steps are taken:
- The topmost object on the operand stack is pushed onto the context
stack, then popped off of the operand stack.
- The callable object is used as a key to search for a method in
the class hierarchy of the topmost object on the context stack.
- The method found in the previous step is evaluated.
- All objects on the context stack down to and including the object
pushed in step 1 are popped off of the context stack.
- cmkey:
- A invokable object is executed and treated as a method key in the
context of the topmost object on the context stack. When a
invokable object is executed, the following steps are taken:
- The invokable object is used as a key to search for a method in
the class hierarchy of the topmost object on the context stack.
- The method found in the previous step is evaluated.
- cdkey:
- A fetchable object is executed and treated as a data key in the context
of the topmost object on the context stack. When a fetchable object is
executed, the following steps are taken:
- The fetchable object is used as a key to search for data in
the data dictionary of the topmost object on the context stack.
- The data found in the previous step is pushed onto the operand
stack.
Table 2.2 enumerates what action is taken during
interpretation/evaluation for all object type/attribute combinations. Note that
executable arrays are the only objects that behave differently when interpreted
versus evaluated.
Attributes are not considered in equality test operations.
Table 2.2:
Interpretation/evaluation of objects by type and attribute
Type |
Attribute |
|
literal |
executable |
evaluable |
callable |
invokable |
fetchable |
array |
data |
data/code |
code |
mkey |
cmkey |
cdkey |
boolean |
data |
data |
data |
mkey |
cmkey |
cdkey |
class |
data |
data |
data |
mkey |
cmkey |
cdkey |
condition |
data |
data |
data |
mkey |
cmkey |
cdkey |
dict |
data |
data |
data |
mkey |
cmkey |
cdkey |
file |
data |
code |
code |
mkey |
cmkey |
cdkey |
fino |
data |
data |
data |
mkey |
cmkey |
cdkey |
handle |
data |
code |
code |
mkey |
cmkey |
cdkey |
instance |
data |
data |
data |
mkey |
cmkey |
cdkey |
integer |
data |
data |
data |
mkey |
cmkey |
cdkey |
mark |
data |
data |
data |
mkey |
cmkey |
cdkey |
mutex |
data |
data |
data |
mkey |
cmkey |
cdkey |
name |
data |
code |
code |
mkey |
cmkey |
cdkey |
null |
data |
code |
code |
mkey |
cmkey |
cdkey |
operator |
data |
code |
code |
mkey |
cmkey |
cdkey |
pmark |
data |
data |
data |
mkey |
cmkey |
cdkey |
real |
data |
data |
data |
mkey |
cmkey |
cdkey |
regex |
data |
data |
data |
mkey |
cmkey |
cdkey |
regsub |
data |
data |
data |
mkey |
cmkey |
cdkey |
stack |
data |
data |
data |
mkey |
cmkey |
cdkey |
string |
data |
code |
code |
mkey |
cmkey |
cdkey |
thread |
data |
data |
data |
mkey |
cmkey |
cdkey |
|
- 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.
- class:
- A class is a class, in the object-oriented sense of the word.
Class objects provide explicit object-oriented programming support. Classes
allow single inheritance, and provide dynamic lookup/dispatch capabilities.
- 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,
where all keys in a dict are unique. 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.
- handle:
- The handle type is not used by the core Onyx language. It can
be used by applications that extend the interpreter as a container object.
Handles can be executed, but the results are application dependent.
Each handle has a tag associated with it that can be 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 handle objects will set handle
tags to be name objects.
- instance:
- An instance is an instance of a class, in the object-oriented
sense of the word. Instances primarily depend on classes for their
functionality, but they also have per-instance data storage.
- 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.
- regex:
- A regex encapsulates a regular expression and associated flags,
which can be used to find substring matches within an input string.
- regsub:
- A regsub encapsulates a regular expression, substitution
template, and associated flags, which can be used to do substring substitutions
and create an output string from an input string.
- 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: 2.2 Syntax
Up: 2. Onyx Language Reference
Previous: 2. Onyx Language Reference
Contents
Index
Jason Evans
2005-03-16