Type System¶
The Type System is the foundation of Viper’s metadata-driven architecture. Every value knows its type, and type metadata enables automatic serialization, validation, and cross-language interoperability.
TypeCode: Fast Polymorphic Dispatch¶
TypeCode is an enum of 33 codes that enables fast polymorphic dispatch without C++ RTTI:
enum class TypeCode : std::uint8_t {
Void = 0,
Bool,
UInt8, UInt16, UInt32, UInt64,
Int8, Int16, Int32, Int64,
Float, Double,
BlobId, CommitId, UUId,
String, Blob,
Vec, Mat,
Tuple,
Optional, Vector, Set, Map, XArray,
Any, Variant,
Enumeration, Structure,
Key,
Concept, Club, AnyConcept,
};
Benefits of TypeCode¶
Benefit |
Explanation |
|---|---|
Fast dispatch |
switch/case compiles to jump table |
No RTTI |
Works with |
Exhaustive |
Compiler warns on missing cases |
Cross-language |
TypeCode transmitted via RPC |
Type Hierarchy¶
Primitives¶
Atomic types with no internal structure:
TypeCode |
C++ Type |
Description |
|---|---|---|
Bool |
bool |
Boolean |
Int8-64 |
int8-64_t |
Signed integers |
UInt8-64 |
uint8-64_t |
Unsigned integers |
Float |
float |
32-bit floating point |
Double |
double |
64-bit floating point |
String |
std::string |
UTF-8 string |
Void |
void |
No value |
BlobId |
BlobId |
Content hash (SHA-1) |
CommitId |
CommitId |
Commit hash (SHA-1) |
UUId |
UUId |
128-bit unique ID |
Containers¶
Typed collections of values:
TypeCode |
Description |
Element Types |
|---|---|---|
Optional |
Nullable value ( |
Any |
Vector |
Dynamic array ( |
Any |
Set |
Ordered set ( |
Any |
Map |
Dictionary ( |
Any |
Tuple |
Fixed heterogeneous ( |
Any combination |
Vec |
Fixed math vector ( |
Numeric |
Mat |
Fixed math matrix ( |
Numeric |
XArray |
CRDT array with UUID positions |
Any |
User-Defined Types¶
Types created via Definitions:
TypeCode |
Description |
Factory |
|---|---|---|
Structure |
Named fields with types |
|
Enumeration |
Named cases |
|
Concept |
Abstract entity with hierarchy |
|
Club |
Collection of Concepts |
|
Attachments¶
Attachments define key-document associations accessed via abstract interfaces
(AttachmentGetting, AttachmentMutating). Unlike types above, Attachment is not
a TypeCode but a first-class entity in Definitions:
Component |
Description |
|---|---|
|
TypeConcept, TypeClub, or TypeAnyConcept |
|
Type of the document (often Structure) |
|
UUID for cross-language compatibility |
|
Derived: |
auto attachment = defs->createAttachment(
nameSpace,
"CameraAttachment", // name
cameraConceptType, // keyType
cameraDocumentType, // documentType
"Camera storage" // documentation
);
RuntimeId: Cross-Language Compatibility¶
RuntimeId (stored as runtimeId in the Type class) is a UUID computed by
deterministic hash (MD5) of the type structure. It guarantees that the same type
definition produces the same identifier in C++ and Python.
The runtimeId is a public const member of Type:
auto type = TypeVector::make(TypeDouble::Instance());
type->runtimeId; // UUID computed from type structure
Why RuntimeId Matters¶
Use Case |
Explanation |
|---|---|
RPC |
Verify type compatibility across network |
Database |
Match stored types with runtime types |
Python binding |
Ensure C++ and Python see same types |
Code generation |
Detect type changes requiring regeneration |
Type-Value Duality¶
For each TypeX exists a corresponding ValueX:
Type |
Value |
Example |
|---|---|---|
TypeDouble |
ValueDouble |
|
TypeString |
ValueString |
|
TypeVector |
ValueVector |
|
TypeMap |
ValueMap |
|
TypeStructure |
ValueStructure |
|
TypeEnumeration |
ValueEnumeration |
|
TypeConcept |
ValueKey |
|
Every Value Knows Its Type¶
auto value = ValueDouble::make(3.14);
value->type(); // -> TypeDouble::Instance()
value->type()->typeCode; // -> TypeCode::Double (public member)
value->type()->runtimeId; // -> consistent UUID (public member)
value->representation(); // -> "3.14"
Type Interface¶
All types inherit from the Type base class:
class Type {
public:
TypeCode const typeCode; // Public const member
UUId const runtimeId; // Public const member
explicit Type(TypeCode code, UUId const & runtimeId);
virtual std::string representation() const = 0;
virtual std::string description() const = 0;
template<typename T>
bool equal(std::shared_ptr<T> const & other);
template<typename T>
Ordered compare(std::shared_ptr<T> const & other);
};
Self-Description¶
Every type can describe itself:
auto type = TypeVector::make(TypeDouble::Instance());
type->representation(); // "vector<double>"
type->description(); // "Vector of Double values"
TypeChecker: Validation¶
TypeChecker validates type compatibility before operations:
// Validate expected type
TypeChecker::check(value, expectedType); // throws if mismatch
// Safe downcast pattern
auto doubleType = TypeDouble::cast(type); // nullptr if not Double
Error Messages¶
Type errors provide clear context:
[process@host]:Type:Unexpected:Type mismatch: expected Double, got String
Definitions: Type Registry¶
Definitions is the central registry for user-defined types. It is the exclusive factory
for:
TypeStructure- named fieldsTypeEnumeration- named casesTypeConcept- abstract entitiesTypeClub- concept collectionsAttachment- key-document associations
auto defs = Definitions::make();
// Create a structure (via descriptor)
auto structDesc = TypeStructureDescriptor::make("Person");
structDesc->addField("name", TypeString::Instance());
structDesc->addField("age", TypeInt32::Instance());
auto personType = defs->createStructure(nameSpace, structDesc);
// Create a concept
auto cameraType = defs->createConcept(nameSpace, "Camera");
// Create an attachment (key-document association)
auto attachment = defs->createAttachment(
nameSpace,
"CameraAttachment",
cameraType, // keyType: TypeConcept (not TypeKey)
cameraDocumentType, // documentType
"Camera storage" // documentation
);
See Also¶
Philosophy - Metadata Everywhere principle
Value System - Type-Value duality in action
Architecture - Type System in layer model
Glossary - Type terminology