Value System¶
The Value System provides runtime values with reference semantics and a Python-like API. Every value knows its type and can be serialized, compared, and hashed automatically.
Reference Semantics¶
Viper uses reference semantics (like Python) rather than value semantics (like C++ STL):
C++ STL (Value Semantics) |
Viper (Reference Semantics) |
|---|---|
|
|
Assignment copies data |
Assignment shares reference |
Explicit std::move for moves |
Explicit |
Explicit Copy When Needed¶
auto v1 = ValueVector::make(TypeInt32::Instance());
v1->append(ValueInt32::make(1));
auto v2 = Value::copy(v1); // v2 is a deep copy
v2->append(ValueInt32::make(2));
// v1 contains [1], v2 contains [1, 2]
Value Interface¶
All values inherit from the Value base class:
class Value {
public:
virtual TypeCode typeCode() const = 0;
virtual std::shared_ptr<Type> type() const = 0;
virtual std::string representation() const = 0;
virtual std::size_t hash() const = 0;
virtual bool equal(std::shared_ptr<Value const> const & other) const = 0;
virtual Ordered compare(std::shared_ptr<Value const> const & other) const = 0;
// Static helper for deep copy
static std::shared_ptr<Value> copy(std::shared_ptr<Value const> const & value);
};
Self-Description¶
Every value can describe itself:
auto v = ValueVector::make(TypeInt32::Instance());
v->append(ValueInt32::make(1));
v->append(ValueInt32::make(2));
v->representation(); // "[1, 2]"
v->type()->representation(); // "vector<int32>"
Primitives¶
Immutable atomic values:
Class |
Factory |
Constants |
|---|---|---|
ValueBool |
|
|
ValueInt8 |
|
|
ValueInt16 |
|
|
ValueInt32 |
|
|
ValueInt64 |
|
|
ValueUInt8 |
|
|
ValueUInt16 |
|
|
ValueUInt32 |
|
|
ValueUInt64 |
|
|
ValueFloat |
|
|
ValueDouble |
|
|
ValueString |
|
|
ValueUUId |
|
|
ValueBlobId |
|
|
ValueCommitId |
|
|
ValueVoid |
|
Singleton |
Static Factory Methods¶
Constants are exposed as class attributes (not method calls):
# Python usage
v = dsviper.ValueDouble.ZERO # Class attribute
v = dsviper.ValueDouble.ONE # Class attribute
Containers¶
Mutable collections with Python-like API:
ValueVector¶
Dynamic typed array:
auto v = ValueVector::make(TypeVector::make(TypeInt32::Instance()));
v->append(ValueInt32::make(1));
v->append(ValueInt32::make(2));
v->insert(1, ValueInt32::make(10)); // [1, 10, 2]
v->pop(0); // Remove at index 0, returns value
v->at(0); // -> 10
v->size(); // -> 2
Python equivalent:
v = dsviper.ValueVector.make(dsviper.TypeInt32.Instance())
v.append(1) # Native int accepted, converted via metadata
v[0] # -> ValueInt32(1)
len(v) # -> 1
ValueMap¶
Ordered dictionary:
auto m = ValueMap::make(TypeMap::make(TypeString::Instance(), TypeInt32::Instance()));
m->set(ValueString::make("a"), ValueInt32::make(1));
m->get(ValueString::make("a")); // -> ValueInt32(1) or nullptr
m->at(ValueString::make("a")); // -> ValueInt32(1), throws if missing
m->keys(); // -> ValueSet
m->values(); // -> ValueVector
m->items(); // -> ValueVector of tuples
Python equivalent:
m = dsviper.ValueMap.make(dsviper.TypeString.Instance(), dsviper.TypeInt32.Instance())
m["a"] = 1 # Native types accepted
m["a"] # -> ValueInt32(1)
list(m.keys()) # -> [ValueString("a")]
ValueSet¶
Ordered set:
auto s = ValueSet::make(TypeSet::make(TypeInt32::Instance()));
s->add(ValueInt32::make(1));
s->add(ValueInt32::make(2));
s->contains(ValueInt32::make(1)); // -> true
s->discard(ValueInt32::make(1)); // Remove without error if missing
s->size(); // -> 1
Compound Types¶
ValueStructure¶
Named fields with types:
// 1. Create descriptor
auto descriptor = TypeStructureDescriptor::make("Person");
descriptor->addField("name", TypeString::Instance());
descriptor->addField("age", TypeInt32::Instance());
// 2. Register type via Definitions
auto personType = defs->createStructure(nameSpace, descriptor);
// 3. Create value
auto person = ValueStructure::make(personType);
person->set("name", ValueString::make("Alice"));
person->set("age", ValueInt32::make(30));
person->at("name"); // -> ValueString("Alice")
ValueEnumeration¶
Enumerated case value:
// 1. Create descriptor
auto descriptor = TypeEnumerationDescriptor::make("Color");
descriptor->addCase("Red");
descriptor->addCase("Green");
descriptor->addCase("Blue");
// 2. Register type via Definitions
auto colorType = defs->createEnumeration(nameSpace, descriptor);
// 3. Create value
auto red = ValueEnumeration::make(colorType, "Red");
red->typeEnumerationCase->name; // -> "Red" (public const member)
ValueOptional¶
Nullable wrapper:
auto optType = TypeOptional::make(TypeDouble::Instance());
auto opt = ValueOptional::make(optType, ValueDouble::make(3.14));
opt->isNil(); // -> false
opt->unwrap(); // -> ValueDouble(3.14)
auto nil = ValueOptional::make(optType); // No value = nil
nil->isNil(); // -> true
ValueVariant¶
Union type:
auto variant = ValueVariant::make(variantType, ValueInt32::make(42));
variant->unwrap(); // -> ValueInt32(42)
Special Values¶
ValueKey¶
Typed reference to a concept instance:
auto typeKey = TypeKey::make(cameraType); // TypeKey wraps TypeConcept
auto key = ValueKey::make(typeKey, UUId::create());
key->instanceId; // -> UUId (public const member)
key->typeConcept; // -> TypeConcept (public const member)
ValueXArray¶
CRDT array with UUID positions for concurrent editing:
auto xaType = TypeXArray::make(TypeString::Instance());
auto xa = ValueXArray::make(xaType);
auto pos = xa->append(ValueString::make("hello")); // Returns new position UUID
xa->set(pos, ValueString::make("world")); // Update at position
xa->at(pos); // -> ValueString("world")
ValueAny¶
Dynamic container (type erasure):
auto any = ValueAny::make(ValueInt32::make(42));
any->isNil(); // -> false
any->unwrap(); // -> ValueInt32(42)
Seamless Python Integration¶
dsviper accepts Python natives as input since metadata drives conversion:
# Python natives are accepted
v = dsviper.ValueVector.make(dsviper.TypeInt32.Instance())
v.append(42) # Python int -> ValueInt32
v.extend([1, 2, 3]) # Python list -> multiple ValueInt32
m = dsviper.ValueMap.make(dsviper.TypeString.Instance(), dsviper.TypeDouble.Instance())
m["key"] = 3.14 # Python str/float -> ValueString/ValueDouble
However, dsviper is a strong-typed layer over Python: type mismatches raise exceptions immediately.
v = dsviper.ValueVector.make(dsviper.TypeInt32.Instance())
v.append("hello") # RAISES: expected Int32, got String
See Also¶
Type System - Type-Value duality
Philosophy - Reference semantics rationale
Patterns - Token Constructor pattern
Glossary - Value terminology