Types
Types are definitions created to serialize data into structured forms. Types are used for managing communication between components, components can only connect and communicate with each other only if their type matches. Each component receives data stream described as a specific type, then component decodes it, process it and sends out data stream.
Types are defined based on ANTLR g4 format.
Possible Types
-
Atomic types:
Int32
,Int64
,Bool
,String
,Bytes
,Float
,Double
,UInt32
,UInt64
.String
andBytes
are further categorized into variable size atomic and the rest are const size atomic. -
Lists: Denoted by
[]
, they represent an arbitrary, finite number of elements of the same type:[Int32]
-
Tuples: Represent an ordered collection of elements with static length and types. The syntax is similar to Python tuple:
(Bool, String, a)
,()
,(UInt64,)
, ... -
Records (aka Structs): Like tuples, but unordered and with named fields:
{name : String, age : UInt32, score : (UInt64, UInt64)}
-
Unions: Unordered collections of different types that represent elements that might be of any of the given types. E.g.
Int32 | Int64
;Bool | String
;Image.BGR | Image.BGRA | Image.GRAY | Image.RGB | Image.RGBA
-
Named types: Any type can be given a name starting with an uppercase letter. The on-wire representation of a named type is the same as that of its base type, but the two are not directly compatible, though they can be converted amongst each other. E.g
Person := {name : String, age : UInt32, score : (UInt64, UInt64)}
, this is the named typePerson
that has their age, name and score for a competition It is possible to introduce a named type without content, i.e. with a single possible value, e.g. typeNothing := ()
which represents an empty tuple.
Basic named type definition
// DetectedClass is a type with named field 'id' and 'confidence'
DetectedClass := {
id: UInt64,
confidence: Double
}
Named types can include other named types
// VideoFrame is image with timestamp given as Unix Epoch
VideoFrame := {
image: Image,
timestamp: UInt64
}
The language also supports type variables, similar to generics in Python or templates in C++. A type variable is an arbitrary name starting with lower case (to distinguish from types). They denote any single type and are scoped within a single component's definition. That is, the same variable refers to the same type everywhere within one component but not across two different components. E.g. a
, b
, myType
Named types can include generics
Point<t0> := {
x:t0,
y:t0
}
Some types include a namespace, the namespace indicates to which workspace the type belongs to.
Type with a namespace
pipelogic.BoundingBox := {
class: DetectedClass,
rectangle: Rectangle<Double>,
angle: Double
}
Empty named types can be used to represent an enum
// Creates types without content Image.BGR, Image.RGB, ...
Image.BGR := ()
Image.RGB := ()
Image.GRAY := ()
Image.RGBA := ()
Image.BGRA := ()
More complex named types definition
Image := {
width: UInt64,
height: UInt64,
// format can be BGR, BGRA, ...
format: Image.BGR | Image.BGRA | Image.GRAY | Image.RGB | Image.RGBA,
data: Bytes
}
Next Steps: