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:
  1. The topmost object on the operand stack is pushed onto the context stack, then popped off of the operand stack.
  2. 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.
  3. The method found in the previous step is evaluated.
  4. 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:
  1. 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.
  2. 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:
  1. The fetchable object is used as a key to search for data in the data dictionary of the topmost object on the context stack.
  2. 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