P DataTypes
P Supports the following data types:
P Types | Description |
---|---|
Primitive | int , bool , float , string , enum , machine , and event . |
Record | tuple and named tuple |
Collection | map , seq , and set |
Foreign | These are types that are not defined in P but in an external language (e.g., C# or Java) and can be used in the P program. |
User Defined | These are user defined types that are constructed using any of the P types listed above |
Universal Supertypes | any and data |
P Types Grammar
Data types in P:
type :
| bool # PrimitiveType
| int # PrimitiveType
| float # PrimitiveType
| string # PrimitiveType
| event # PrimitiveType
| machine # PrimitiveType
| (type (, type)*) # TupleType
| (iden: type (, iden: type)*) # NamedTupleType
| seq[type] # SeqType
| set[type] # SetType
| map[type, type] # MapType
| data # UniversalType
| any # UniversalType
| iden # UserDefinedType
;
Declaring user defined types and foreign types:
typeDecl :
| type iden ; # ForeignTypeDeclaration
| type iden = type ; # UserDefinedTypeDeclaration
;
Declaring enum types:
enumTypeDecl :
| enum iden { enumElemList }
| enum iden { numberedEnumElemList }
;
enumElemList : enumElem (, enumElem)* ;
enumElem : iden ;
numberedEnumElemList : numberedEnumElem (, numberedEnumElem)* ;
numberedEnumElem : iden = IntLiteral ;
Operations on P data types
Details for the operations that can be performed on P datatypes are described in the expressions and statements.
Primitive
P supports the common primitive datatypes like int
, bool
, float
, and string
. Two
additional primitive data types that are specific to the P language are event
and
machine
. event
type represents the set of all P events. Similarly, machine
type
represents the set of all machine references.
...
event eRequest: bool;
...
// some function body in the P program
{
var i: int;
var j: float;
var k: string;
var l: bool;
var ev: event;
var client: machine;
ev = eRequest;
client = new Client();
i = 10; j = 10.0; k = "Failure!!";
l = (i == (j to int));
assert l, k;
send client, ev, l;
}
Enum
P supports enums, enum values in P are considered as global constants and must have unique
name. Enums by default are given integer values starting from 0 (if no values are assigned
to the elements). Enums in P can be coerced to int
. Please refer to the grammar above for the syntax for declaring enums.
enum tResponseStatus { ERROR, SUCCESS, TIMEOUT }
// usage of enums
var status: tResponseStatus;
status = ERROR;
// you can coerce an enum to int
assert (ERROR to int) == 0;
enum tResponseStatus { ERROR = 500, SUCCESS = 200,
TIMEOUT = 400; }
// usage of enums
var status: tResponseStatus;
status = ERROR;
// you can coerce an enum to int
assert (ERROR to int) == 500;
Record
P supports two types of records: tuples and named tuples. The fields of a tuple can be
accessed by using the .
operation followed by the field index.
// tuple with three fields
var tupleEx: (int, bool, int);
// constructing a value of tuple type.
tupleEx = (20, false, 21);
// accessing the first and third element of the tupleEx
tupleEx.0 = tupleEx.0 + tupleEx.2;
Named tuples are similar to tuples with each field having an associated name. The fields
of a named tuple can be accessed by using the .
operation followed by the field name.
// named tuple with three fields
var namedTupleEx: (x1: int, x2: bool, x3: int);
// constructing a value of named tuple type.
namedTupleEx = (x1 = 20, x2 = false, x3 = 21);
// accessing the first and third element of the namedTupleEx
namedTupleEx.x1 = namedTupleEx.x1 + namedTupleEx.x3;
Note
Tuple and Named tuple types are disjoint, i.e., a tuple of type (int,
bool, int)
cannot be assigned to a variable of tuple (x1: int, x2: bool, x3: int)
though the elements of the tuple have same types (and vice versa). And similarly, a named
tuple of type (x1: int, x2: bool, x3: int)
cannot be assigned to a variable of tuple
(y1: int, y2: bool, y3: int)
they are two distinct types.
Collection
P supports three collection types: map, sequence (lists), and set. The operations to mutate the collection types like insert, update, and remove elements are described in the statements section. One can use the while
loop to iterate over these collection types. Other operations like sizeof
, in
(to check containment), choose
(pick a value nondeterministically), keys
, and values
on these collection types are defined in the expressions section.
Syntax:
map[K, V]
represents amap
type with keys of typeK
and values of typeV
.seq[T]
represents a sequence type with elements of typeT
.set[T]
represents a set type with elements of typeT
.
Foreign
P allows programmers to define (or implement) types in the external languages. We refer to these types as foreign types, they are declared in P but are implemented in an external language. They can be used inside P programs just like any other types.
Syntax:: type tName;
tName
is the name of the foreign type.
Note that foreign types are disjoint from all other types in P. They are subtype of the any
type.
Details about how to define/implement foreign types in P is described here.
User Defined
P supports assigning names to type i.e., creating typedef
. Note that these typedefs are simply assigning names to P types and does not effect the sub-typing relation.
Syntax:: type iden = type ;
// defining a type tLookUpRequest
type tLookUpRequest = (client: machine, requestId: int, key: string);
// defining a type tLookUpRequestX
type tLookUpRequestX = (client: machine, requestId: int, key: string);
tLookUpRequest
as a short hand for referring to the type (client: machine, requestId: int, key: string)
Note that the types tLookUpRequest
and tLookUpRequestX
are same, the compiler does not distinguish between the two types.
Universal Supertypes
P supports two universal supertypes (any
and data
), type that are supertypes of all
types in the language.
any
type in P is the supertype of all types. Also, note that in P,seq[any]
is a super type ofseq[int]
and similarly for other collection types.data
type in P is the supertype of all types in P that do not have amachine
type embedded in it. This type is mainly used to represent values in P that do not have a machine reference embedded in them i.e., the value is purely "data" and has no machine "references" in it. For example,data
is a supertype of(key: string, value: int)
but not(key: string, client: machine)
.
Default values for P data types
The default
feature in P (checkout details in expressions) can be used
to obtain the default value of any P type. P variables on declaration are automatically
initialized to their default values.
default
values of P types
P variables on declaration are automatically initialized to their default values. For example:
var s : set[int];
// by default a set type is initialized to an empty set
assert sizeof(s) == 0;
s += (100);
assert sizeof(s) == 1;
// reset the variable to an empty set
s = default(set[int]);
Similarly,
type tRequest = (client: machine, requestId: int);
type tResponse = (values: map[int, int]);
...
// initializes x to (client = null, requestId = 0);
x = default(tRequest);
// initializes y to (values = {}), empty map.
y = default(tResponse);
assert x.client == default(machine);
assert sizeof(y.values) == 0;
P Types | Default Value |
---|---|
int | 0 |
float | 0.0 |
bool | false |
string | "" |
event | null |
machine | null |
enum | Element of the enum with lowest (int) value |
Record (tuple or named tuple) | Each field in the record type is initialized to its default value. |
Collection (set, seq, and map) | Empty collection |
Foreign | null |
any and data |
null |