Ivory Language Meanings

This page describes the meanings of various constructs in the Ivory language.

Types

There are three basic classes of types in the ivory language: primitive types, derived types, and collection types. Primitive types represent types of data that are directly supported by the underlying hardware. In reality, this is not always 100% true. For instance, some architectures have no support for floating point math. In this case, it is necessary for either the compiler or the operating system to emulate floating point math. Another example is the case of 64-bit math on a 32-bit platform. Ivory handles these on a platform-by-platform basis.

Derived types are more complex. They represent language features rather than hardware features. Derived types cannot exist alone; they require a base type. One derived type may serve as a base type for another derived type.

Collection types represent a type created from a collection of other types. The most direct example is a structure, which represents a set of data.

Primitive Types

Most primitives fall into two categories. The first grouping of primitive types are integer types. They consist of byte, short, int, and long. Unlike in C, the sizes of these are fixed. They represent 1, 2, 4, and 8 byte numbers respectively. The second group are the floating point types. These are float and double. These represent real numbers (with a decimal point). These represent 32 and 64 bit IEEE-format floating point numbers respectively.

The char type represents unicode characters. Normally, this will be equal in size to int. Compiler options may allow the char to be stored in a different format, in which case the size may change.

The bool type represents a true or false value. Its exact size is unspecified, as some platforms store them in a special format (such as IA-64's predicate registers).

The void type is special. It cannot be used directly. Instead, void is used solely to act as a base type in a derived type.

Derived Types

Ivory has three derived types: pointers, arrays, and functions. Each of these requires a base type (or several, in the case of functions).

Pointers represent the memory address of some other type of data. All pointers are the same size, though the data to which they point is not. Some environments, most notably POSIX, may guarantee that a pointer is the same size as another primitive. However, this is not guaranteed by Ivory itself. All that is guaranteed is that all pointers are the same size.

Arrays represent a collection of some base type, indexable by an integer. In reality, they are a block of memory whose size is some multiple of the base type's size. A strict array, however, has no specified form.

Normal arrays and pointers are very similar. In fact, a pointer pointing to a block of memory holding multiple objects of the same type can be used as an array. For this reason, pointers and arrays are assignment-compatible.

Pointers with the strict keyword, however are only allowed to point to one object. They cannot be treated like arrays.

Functions represent a procedure that takes some number of arguments and optionally returns a value. Functions have a return base type, and some number of argument base types. Functions with the pure qualifier have no side-effects, nor are affected by anything aside from the arguments. Functions with the strict qualifier strictly obey architecture calling conventions.

Collection Types

There are four types of collections: structs, unions, exceptions, and enums.

A struct is simply a collection of data. A struct has one or more fields, which are named data elements. A struct may also define inner functions. The functions within a struct may access all the fields of the struct directly. A struct is guaranteed to be represented the same in all parts of a given program. However, it is not guaranteed to be represented the same from one program to the next. A strict struct, however, is aligned in memory exactly as it is given.

A union is similar to a struct, except the fields are mutually exclusive. A union is for some set of data wherein only one of the elements is ever used at a time. Additionally, strict unions are guaranteed to store all data beginning at the same point in memory. They provide a way to directly convert one type's representation into another type. Casts do not exist in Ivory. This is the only way to accomplish this other than with void pointers.

An exception is identical in nature to a struct, except that it can be thrown. Declaring an exception declares a throwable type. The optional collection that may be defined along with it is called its "metadata". Aside from this, the exception behaves exactly like a struct.

An enum represents a type that holds one of several possible values. Internally, enums are really integers. Regular enums can actually have any value, while strict enums are restricted to the values specified.

Statements

Statements represent the structure of an imperitive programming language. Each statement modfies some part of the program's state, or controls the execution of other statements. Ivory has a number of statements which comprise the body of a function.

The expression statement is simply composed simply of an expression. It evaluates the expression, which presumably has some side effect on the program.

The compound statement groups statements into one statement. It is most commonly seen in loop bodies. Any declaration that occurs inside a compound statement is limited in scope to that statement.

The if statement represents a decision. If the test expression evaluates true, the body of the if is executed. The statement may have an optional else clause, which is executed if the test expression is false.

The switch statement represents a selection of several possible cases. The expression is evaluated, and the appropriate case is executed, or the default case if no appropriate case exists. Each case must usually end with a break statement. Otherwise, execution will continue on to the next case. However, this is sometimes the desired effect.

The while and do statements represent loops. The test expression is evaluated each loop cycle, and the loop continues as long as the test evaluates to true. In a while loop, the test is performed at the beginning of the loop body, whereas in the do loop, it is performed at the end

The for loop is a complex loop. The first statement in the for body is executed prior to entering the loop. Usually, this initializes some counter. The next statement is the test expression, which is evaluated as in a while loop. The last statement is executed an the end of every loop body and usually updates some counter.

The continue statement is used to stop the current loop cycle and go on to the next. The break statement either stops the execution of the current loop, or case in a switch.

The return statement ends the execution of the function and returns the given value. If no value is given, then no value is returned (this is appropriate for void-returning functions)

The catch statement defines handlers for exceptions. Should any of the exceptions for which handlers are defined be thrown while executing the statement to which the catch applies, control will transfer to the appropriate handler. An optional final block is executed after an handler finishes.

The throw statement throws the given exception. Control will transfer to the most recently defined handler. If no catch statement handles the exception, then an implementation-defined default will be executed (which typically terminates the program).

Expressions

Expressions represent the calculation of some value. Some expressions also have a side effect.

The conditional expression, denoted by the ? operator, represent a decision. The test is evaluated, and if it is true, conditional expression evaluates to the first expression, otherwise it evaluates to the expression following the :.

The assignment expression modifies the left side of the expression to the value of the right side. The expression evaluates to the value of the right side. This statement is side-affecting.

The following table describes the binary operators:

OperatorFunction
+Add
-Subtract
*Multiply
/Divide
%Modulus
<<Bitshift Left
>>Bitshift Right
&Bitwise And
|Bitwise Or
^Bitwise Xor
||Logical Or
&&Logical And
<Less
>Greater
<=Less or Equal
>=Greater or Equal
==Equal
!=Not Equal

The following table describes the unary operators:

OperatorFunction
+Absolute Value
-Sign Invert
*Dereference
&Address of
~Bitwise Not
!Logical Not
|<Bitscan Left
>|Bitscan Right

The sizeof expression evaluates the size of a given type or the type of the result of a given expression.

The call expression calls a function and evaluates to its return value. This expression has is considered side-effecting.

The subscript expression is equivalent to pointer arithmetic, followed by the dereference operator on a non-strict array or pointer. It evaluates to the element at the given index in an array.

The field expression evaluates to the given field in the collection given by the rest of the expression.

The variable expression evaluates to the given variable.

A value expression evaluates to the value of the literal.