OADL Types

Most variables in OADL are dynamically typed - it is valid to store a string in a variable at one point, and then store an integer in it later. Despite this, OADL is a strongly typed language - there are several different types in OADL, and each represents different kinds of values, and the different types allow different kinds of operations on them.

Scalar types

There are 20 "scalar" object types in OADL - "scalar" in that only one value is stored:

Type Minimum Maximum Description
Null n/a n/a The type of nil. Every Null object is identical to every other Null object.
Bool false true Typically the result of boolean expressions
Type n/a n/a Typicaly returned by the typeof intrinsic
Exception n/a n/a Typically thrown by OADL's runtime error checking protocols
Char '\0' (or 0 => Char) '\x7F' Unsigned 7-bit character values. They may also be used in arithmetic expressions as integers with values from 0 to 127.
Byte -128 127 Signed 8-bit integers
Ubyte 0 255 Unsigned 8-bit integers
Short -32_768 32_767 Signed 16-bit integers
Ushort 0 65_535 Unsigned 16-bit integers
Half approx. ± 6.10e-5 approx. ± 6.55e+4 16-bit floating point numbers with approximately 3 decimal digits of precision
WideChar '\0'L '\x1FFFFF'L Unsigned 21-bit Unicode character values. They may also be used in arithmetic expressions as integers with values from 0 to 2,097,151
Public n/a n/a Associative indexes into Classes and Objects. They have no arithmetic value. Operators (such as operator +) are also of type Public.
Extern n/a n/a External procedure (typically a library procedure)
Uint 0U 0xFFFF_FFFFU Unsigned 32-bit integers with an approximate range from 0 to 4.3e9
Int -0x2000_0000 0x1FFF_FFFF Signed 30-bit integers with an approximate range of ± 5.4e8 see note
Float approx. ± 1.18e-38 approx. ± 3.40e+38 31-bit floating point numbers with approximately 7 decimal digits of precision see note
Long -0x2000_0000_0000_0000L 0x1FFF_FFFF_FFFF_FFFFL Signed 62-bit integers with an approximate range of ± 2.3e18
Ulong 0UL 0xFFFF_FFFF_FFFF_FFFFUL Unsigned 64-bit integers with an approximate range from 0 to 1.8e19
Pointer n/a n/a Strictly for use with external library procedures
Double approx. ± 2.23e-308D approx. ± 1.80e+308D 63-bit floating point numbers with approximately 16 decimal digits of precision

Note: On native 64-bit implementations, Int and Float objects are full 32-bit values. Int objects will have an approximate range of ± 2.1e9.

Dynamic types

There are 25 "dynamic" types in OADL - "dynamic" in that they refer to dynamically-allocated memory managed by the OADL machine.

Type Description
Class An OADL class. Mostly useful with the new operator.
Object An instance of a class. Only the public or protected constants, data, and procedures of the Object are accessible outside the scope of the Object
Dict An associative dictionary of key/value pairs
Proc A read-only executable byte stream of instructions.
Array A heterogeneous multi-dimensional ordered list of objects.
List A heterogenous single-dimensional list of objects
PackBool A packed homogeneous array of Bool objects
String A packed single-dimensional homogeneous array of Char objects
PackChar A packed multi-dimensional homogeneous array of Char objects
PackByte A packed homogeneous array of Byte objects
PackUbyte A packed homogeneous array of Ubyte objects
PackShort A packed homogeneous array of Short objects
PackUshort A packed homogeneous array of Ushort objects
PackHalf A packed homogeneous array of Half objects
WideString A packed single-dimensional homogeneous array of WideChar objects
PackWideChar A packed multi-dimensional homogeneous array of WideChar objects
PackInt A packed homogeneous array of Int objects
PackUint A packed homogeneous array of Uint objects
PackFloat A packed homogeneous array of Float objects
PackLong A packed homogeneous array of Long objects
PackUlong A packed homogeneous array of Ulong objects
PackDouble A packed homogeneous array of Double objects
Enclosure An array enclosed as a scalar via arr.enclose()
ArrayType An array type which includes shape information
File An opened file system file, for use with OADL I/O intrinsics

Packed arrays typically are more efficient than heterogeneous arrays, both in space and in execution efficiency. PackInt, PackFloat, PackLong, and PackDouble arrays have full 32- or 64-bit precision since the type information is not stored per-element.

Dynamic values in OADL are implicitly memory-managed. There is no need for an OADL programmer to keep track of which values are no longer in use and then free them. Instead, when OADL detects that there are no longer any references to a compound value, the value is freed. If the value is an Object, and if the Object has a destroy method, then the destroy method will be called at that time. The order in which compound values is freed is non-deterministic, and therefore destroy method calls may occur in any order.

There are some similarities between Object, Dict, and Array values. All contain a group of several other values - the elements. However, there are some key differences:

Type Access Time Private elems? Accessor Multi-index? Undef query? Undef assign?
Array O(1) No [ Num... ] Yes No No
Dict O(log(n)) No [ Any ] No Yes Yes
Object O(log(n)) Yes . Public No Yes No

Note that Array in this table encompasses all array types: PackInt, String, etc.

Access time refers to the typical time to access one of the elements of the compound value. Only Objects allow private elements - elements not accessible outside the class definition of the Object. An Array may only be accessed via (possibly multiple) numeric indexes and an Object may only be accessed via a Public index. Dict and Object variables allow queries of undefined elements - these queries return nil. And, finally, only Dict variables allow assignments to previously undefined values (this adds a new key/value pair into the dictionary if it is not full).

Type descriptors

The type of an OADL value may be queried by an OADL program. Additionally, variables and procedures may have a "type decoration" indicating that they only store / return values of the given type. Finally, the OADL I/O read() intrinsic can accept type descriptors to indicate the type of the items to be read. All of the type names described in this chapter may be used as type descriptors. In addition, array types may have a shape included as part of the descriptor; for example:

var aPak : PackInt[2,3];

The following tree describes the type hierarchy that OADL follows for type compatibility:

Type
  |
  +-------+-------+---    ...
  |       |       |
 Int    Float   Array[*]  ...
                  |
    +-------------+-------------+-------------+---------------+---       ...
    |             |             |             |               |
  List          Array        String        PackInt        PackFloat      ...
    |             |             |             |               |
  List[n]   Array[n,m,...]   String[n] PackInt[n,...]  PackFloat[n,...]  ...
    |             |             |             |               |
  new List()  new Array()    "hello"       [1,2,3]        [1.,2.,3.]     ...

When queried via oadl::typecheck(), each type in this tree will return true for values having the types of each of its children. For example:

    aList = {"one", "two", "three"} // A List

    oadl::typecheck(List, aList) // aList is, in fact, a List
true

    oadl::typecheck(List[3], aList) // aList is, in fact, a List with shape 3
true

    oadl::typecheck(Array, aList) // aList is *not* an Array of any kind
Illegal type

    aPak = [2,3].iterate() // A PackInt array

    oadl::typecheck(PackInt, aPak) // aPak is, in fact, a PackInt
true

    oadl::typecheck(PackInt[2,3], aPak) // aPak is a PackInt with shape [2,3]
true

    oadl::typecheck(Array, aPak) // aPak is not a heterogeneous Array
Illegal type

    // Both aList and aPak are, generically, arrays
    oadl::typecheck(Array[*], aList) && oadl::typecheck(Array[*], aPak)
true

Back to OADL Program Syntax

Continue to Arrays, Lists, and Strings

Return to Introduction