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.
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.
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).
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