Types

Type Definitions

Users can define types in type models stored in files with extension '.types' or in interface signature models.

A type model may import other type models by the following file import statement:

import "myTypes.types"

This file import mechanism works transitively: when a type model is imported, the models imported by it are also imported.

It is also possible to import namespaces:

import myproject.types.*

File imports and namespace imports cannot be used together (see the Help page on namespaces).

There are a number of aspects in using types: the definition of a type, using a type in a declaration (e.g. by name or inline constructor), and the syntax of the values of a type when used in CommaSuite models. In the following explanations these aspects are addressed for every kind of CommaSuite types.

Predefined basic types: bool, int, real, string, bulkdata, void.

bool, int, real, and string are commonly found in many programming and modeling languages.

The values of bulkdata are uninterpreted byte arrays.

void can only be used as a return type of interface commands and indicates that no result is produced.

The following example shows the usage of these types in variable declarations and the syntax of their values.

...
variables

int i
bool b
real f
string s
bulkdata bd //variable of type bulkdata

init

i := 23
b := true
s := "John Smith"
f := 3.2
f := 2.0e-5 // values of type real can also use the exponential notation with 'e'.
bd := Bulkdata<1024> // value of type bulkdata with length 1024 bytes
bd := Bulkdata<> // value of type bulkdata with unknown length

Observe that the values of type bulkdata only declare the size in bytes but do not actually have a content.

User-defined basic types. Users can define their own basic types:

   type unit
   type uint
   type wstring
   type Pixel
   type Time
   type Command

User-defined basic types are uninterpreted, their set of values is unknown. It is possible to relate a basic type to one of the predefined types int, string, and real. In this way values of the predefined type can be used for the basic type:

type unit based on int

Enumeration types. An example of enumeration type definition:

enum Mode {
    updating
    working
    sleeping
}

Optionally, enumeration literals may be assigned with non-negative integers:

enum Mode {
    updating = 1 //if not explicitly given, the first literal assumes value 0
    working  //if not given, the value will increment the previous one, i.e. 2
    sleeping = 4 //user may give a value greater than the increment of the previous value
}

Once defined, the type can be referred to by its name in the models, for example, in variable declarations. The values of an enumeration type are the literals it contains.

Example usage of enumeration type and its values:

variables
Mode m

init
m := Mode::working // The value is formed by prefixing the literal with the type name

Vector Types

Vector types are constructed by giving a base type and a number of dimensions. For each dimension, an optional size can be given. The type constructed this way can be used inline in a declaration or can be given a name.

Examples of named vector types (given in types or signature model):

vector Image = Pixel [ 10 ] [ 20 ]
vector Requests = Command [] // vector without an explicit size
vector Matrix = int[2][2]

Example use of vector types in declarations:

variables

Image img // vector type referred to by name
string[][3] quarters // vector type constructed and used inline

Literal values of vector types have the syntax: <VectorType>[element1, element2, …​]. For example:

variables
int[] numbers
Matrix m
string[][3] quarters

init
numbers := <int[]>[] // example of empty vector of integers
numbers := <int[]>[1, 2] // vector with two elements

m := <Matrix>[<int[2]>[1, 2], <int[2]>[3, 4]]

quarters := <string[][3]>[<string[3]>["Jan", "Feb", "Mar"]]

Record Types

An example definition of record type:

record Status {
    Image image1
    Pixel [10 ] [ 20 ] image2
    Time time
}

It is also possible for one record type to extend another:

record Person {
    string name
    string address
}

record Student extends Person{
    string university
}

Instances of record types have the syntax: TypeName{field1 = value1, field2 = value2, …​}. For example:

Person p
...
p := Person{name = "John", age = 25}

Map Types

Map types are constructed by giving the types of the keys and values of the map. The key type must be a basic type or enumeration.

MapInt2Int = map<int, int>

Map types can also be used inline (without giving a name).

Values of map types have the syntax: <type>{key1 → value1, key2 → value2, …​}. For example:

MapInt2Int m1 // map type referred by name
map<int, int> m2 // map type constructed inline
...

m1 := <MapInt2Int>{} // example of an empty map
m2 := <map<int, int>>{1 -> 0, 2 -> 0}

Limitations for maps:

  • Currently, maps cannot be used as parameter and return types of events in signatures.

Default Values

Every type has a default value. It is usually used to automatically initialize variables that are not explicitly given a value. Below are the default values for each type.

Default values:

  • int: 0

  • real: 0.0

  • bool: true

  • string: ""

  • enums: the first enumeration literal

  • records: a record with the default values for the field types

  • vector: an empty vector

  • map: an empty map