wiki:Doc/panc/dml/types

Types

Type Binding

The following statement will bind an existing type definition (either a built-in definition or a user-defined one) to a path in a machine configuration:

bind path = type-spec;

where 'path' is a valid path name and 'type-spec' is either a type specification or name of an existing type. The syntax:

type path = type-spec; # DEPRECATED

will also work, but its use is deprecated. Support for the latter form will disappear in a future release of the compiler.

Full type specifications are of the form:

identifier = constant with validation-dml

where 'constant' is a DML block that evaluates to a compile-time constant (the default value), and the 'validation-dml' is a DML block that will be run to validate paths associated with this type. Both the default value and validation block are optional. The identifier can be any legal name with an optional array specifier and/or range afterwards. For example, an array of 5 elements is written int[5] or a string of length 5 to 10 characters string(5..10).

Primitive Types

There are five primitive, atomic types in the pan language:

  1. boolean
  2. long
  3. double
  4. string
  5. link

The "link" type appears as a string, but must be a valid path name that exists at validation time. In addition, there are two primitive collection types:

  1. list
  2. nlist (or hash)

The 'list' is an ordered list of elements. The named list (nlist) or hash associates a string key with a value. These seven comprise the primitive types in the pan language.

There are actually three other types based on strings that are rarely used: fetch, stream, and embed.

User-Defined Types

Users can create new types built up from the primitive types and with optional validation functions. The general format for creating a new type is:

type identifier = type-spec;

where the general form for a type specification 'type-spec' is given above.

Probably the easiest way to understand the type definitions is by example. The following are "alias" types that associate a new name with an existing type, plus some restrictions.

type ulong1 = long with self >= 0;
type ulong2 = long(0..);
type port = long(0..65535);
type short_string = string(..255);
type small_even = long(-16..16) with self %2 == 0;

Similarly one can create link types for elements in the machine configuration:

type mylink = long(0..)* with match(self, 'r$'); 

Values associated to this type must be a string ending with 'r'; the value must be a valid path that references an unsigned long value.

Slightly more complex is to create uniform collections:

type long_list = long[10];
type matrix = long[3][4];
type double_hash = double{};
type small_even_hash = small_even{};

Here all of the elements of the collection have the same type. The last example shows that previously-defined, user types can be used as easily as the built-in primitive types.

A record is an nlist (or hash) that explicitly names and types its children. A record is by far, the most used type definition. For example, the type definition:

type cpu = {
  'vendor' : string
  'model' : string
  'speed' : double
  'fpu' ? boolean
};

defines an nlist with four children named 'vendor', 'model', etc. The first three use a colon (":") in the definition and are consequently required; the last uses a question mark ("?") and is optional. As defined, no other children may appear in nlists of this type. However, one can make the record extensible with:

type cpu = extensible {
  'vendor' : string
  'model' : string
  'speed' : double
  'fpu' ? boolean
};

This will check the types of 'vendor', 'model', etc., but will also allow children of the nlist with different unlisted names to appear. This provides some limited subclassing support. Each of the types for the children can be a full type specification and may contain default values and/or validation blocks. One can also attach default values or validation blocks to the record as a whole.

Last modified 17 years ago Last modified on Mar 7, 2007, 6:59:45 PM