Data Types
Ola is a statically typed language, and variable types must be known at compile time to avoid most runtime exceptions. Three basic types and multiple complex types are supported.
Basic Types
Ola supports multiple basic types, including integer
,field
, boolean
, address
,hash
.
Integer Type
There are two types of integer types: u32
and u256
, All types are built on the basis of the field
type. Ola provides the above-mentioned basic libs of various integer types based on the field implementation, which is convenient for developers to write complex logic. Note: The literal quantity of a number is composed of three parts: base character prefix, corresponding number, and type suffix. The default is a decimal field type literal.
Field Elements Type
Ola supports the field
type for elements of the base field of the elliptic curve. These are unsigned integers less than the modulus of the base field. The following are the smallest and largest field elements.
The filed
type is a goldilocks field number, with a maximum value of 2^64 - 2^32 + 1
.
The filed
type has limited operations because it is based on elliptic curves in a finite field. It can only support basic +
and -
operations, as well as accept some special function return values.
Boolean
Bool indicates that the value of field
is 0
or 1
, which is declared using the keyword bool
.
Address
The address type is an array composed of 4 fields. The address is calculated by Poseidon hash on certain inputs, and the first 4 fields of the hash return value are used as the address.
Hash
Hash and address types are similar, both are arrays of 4 field elements.
Complex Types
Ola supports a variety of complex types such as Arrays
, String
, Fields
,Slice
, Tuples
,Structs
,Enumerations
,Mapping
。
Arrays
Ola supports fixed length and dynamic length array.
Array elements are numbered from zero and are accessed using[index]
for addressing.
Arrays are passed by reference. If you modify the array in another function, those changes will be reflected in the current function. For example:
Fiexed Length Array
Arrays can be declared by adding [length] to the type name, where length is a constant expression. Any type can be made into an array, including arrays themselves (also known as arrays of arrays). For example:
For example:
Any array subscript which is out of bounds (either an negative array index, or an index past the last element) will cause a runtime exception. In this example, calling primenumber(10)
will fail; the first prime number is indexed by 0, and the last by 9.
Dynamatic Array
Dynamic length arrays are useful for when you do not know in advance how long your arrays will need to be. They are declared by adding []
to your type. How they can be used depends on whether they are contract storage variables or stored in memory.
Memory dynamic arrays must be allocated with new
before they can be used. The new
expression requires a single unsigned integer argument. The length can be read using length
member variable.
Storage dynamic memory arrays do not have to be allocated. By default, they have a length of zero and elements can be added and removed using the push()
and pop()
methods.
Calling the method pop()
on an empty array is an error and contract execution will abort, just like when accessing an element beyond the end of an array.
Depending on the array element, pop()
can be costly. It has to first copy the element to memory, and then clear storage.
Array Slicing
Similar to rust, arrays can be created by slicing an array to copy the generated array,[from_index..to_index]
。
Memory dynamic arrays must be allocated with new
before they can be used. The new
expression requires a single unsigned integer argument. The length can be read using length
member variable.
String
String
can be initialized with a string literal Strings can be concatenated and compared equal, no other operations are allowed on strings. string types can be converted to fields types and vice versa.
Fields
Fields is a dynamic array representation of the filed type. fields can be concatenated using the system library provided by the ola language.
Fields types can be converted to string types and vice versa.
If the fields
variable is a storage variable, there is a push()
and pop()
method available to add and remove bytes from the array. Array elements in a memory fields
can be modified, but no elements can be removed or added, in other words, push()
and pop()
are not available when fields
is stored in memory.
Structs
A combination of multiple data types to form a new custom combination type. Struct members are accessed via.
(struct_name.struct_field
).
A struct has one or more fields, each with a unique name. Structs can be function arguments and return values. Structs can contain other structs. There is a struct literal syntax to create a struct with all the fields set.
Enumerations
The enumeration type is defined by the keyword enum
. enums types need to have a definition which lists the possible values it can hold. An enum has a type name, and a list of unique values. Enum types can used in functions, but the value is represented as a u32
in the ABI. Enum are limited to u32 values.
If enum is declared in another contract, the type can be referred to with contractname.typename. The individual enum values are contractname.typename.value
.
Mapping
Mappings are a dictionary type, or associative arrays. Mappings have a number of limitations:
They only work as storage variables
They are not iterable
The key cannot be a
struct
,array
, or another mapping.
Mappings are declared with mapping(keytype => valuetype)
, for example:
If you access a non-existing field on a mapping, all the fields will read as zero. It is common practise to have a boolean field called exists
. Since mappings are not iterable, it is not possible to delete
an entire mapping itself, but individual mapping entries can be deleted.
Last updated