Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

lib/var/var.x

Variant type for dynamic typing.

Primary API

FunctionSummary
x2c_var_custom_descriptorReturns a boxed custom object’s descriptor, or NULL for another value.
x2c_var_declareReturns the process-lifetime descriptor declared for custom tag, declaring it on first use.
x2c_var_descriptor_indexReturns value’s dense built-in descriptor row, or -1 when it has none.
x2c_var_tag_descriptor_indexReturns a built-in object or Symbol tag’s descriptor row, or -1.
Var.box_recordBoxes a copy of the size-byte record at record as custom tag.
Var.isReports whether value has the requested runtime tag.
Var.is_floatingReports whether v belongs to the floating runtime family.
Var.is_integerReports whether v belongs to the integer runtime family.
Var.is_nilReports whether v is the typed empty List.
Var.is_nullReports whether v is the all-zero Null value.
Var.is_objectReports whether v holds a registered boxed object.
Var.is_pointerReports whether v holds a native pointer.
Var.is_referenceReports whether v holds a pointer to a boxed handle.
Var.is_voidReports whether v is the absence sentinel void.
Var.newConstructs a Var with tag from its tag-directed variadic payload.
Var.nullReturns Null, the all-zero Var that stands for external nil.
Var.tag_bottomReturns the bottom encoding field of built-in tag.
Var.tag_topReturns the top encoding field of built-in tag.

Functions

x2c_var_custom_descriptor

VarDescriptor *x2c_var_custom_descriptor(Var value)

Returns a boxed custom object’s descriptor, or NULL for another value.

Source: lib/var/classes.x:80

x2c_var_declare

VarDescriptor *x2c_var_declare(Symbol tag)

Returns the process-lifetime descriptor declared for custom tag, declaring it on first use. The caller holds the descriptor lock and has checked that registration is open and tag is not built in.

Source: lib/var/classes.x:222

x2c_var_descriptor_index

int x2c_var_descriptor_index(Var value)

Returns value’s dense built-in descriptor row, or -1 when it has none. The row is the tag’s offset from <array> and includes the Symbol row. Numbers, pointers, references, custom tags, and invalid encodings have no built-in row.

Source: lib/var/encoding.x:273

x2c_var_tag_descriptor_index

int x2c_var_tag_descriptor_index(Symbol tag)

Returns a built-in object or Symbol tag’s descriptor row, or -1.

Source: lib/var/encoding.x:289

Var

Var.box_record

Var Var.box_record(Symbol tag, const void *record, size_t size)

Boxes a copy of the size-byte record at record as custom tag. The copy is allocated in the active Scope. Once the direct custom rows are taken, the copy carries its descriptor in front of it.

Raises: <bad-target> when tag names no declared class, or <alloc-fail> when the copy cannot be allocated.

Source: lib/var/classes.x:96

Var.is

int Var.is(Var var, Symbol tag)

Reports whether value has the requested runtime tag. This tests one family. A Var holding an unsigned char answers 0 for <i32> even though both are integers. When any integer will do, ask Var.is_integer, or compare Var.kind. As with Var.tag, validate externally constructed bits first: an invalid encoding uses the <f64> fallback.

Source: lib/var/encoding.x:165

Var.is_floating

meta native int Var.is_floating(Var v)

Reports whether v belongs to the floating runtime family. True for <f32>, <f64>, and <ldouble>, and for the discrete <nan>, <+inf>, and <-inf> values. Read the payload with Var.floating, or with Var.long_double_value when the tag is <ldouble> and the extra precision matters.

Source: lib/var/encoding.x:190

Var.is_integer

int Var.is_integer(Var v)

Reports whether v belongs to the integer runtime family. True for every signed and unsigned integer family from <u8> through <ullong>, including the scope-owned wide boxes. Symbols are a kind of their own and answer 0 here, even though Var.integer returns a Symbol’s numeric value.

Source: lib/var/encoding.x:198

Var.is_nil

meta native int Var.is_nil(Var v)

Reports whether v is the typed empty List. The empty List is a native null pointer carrying the <list> tag. Var.is_null answers 0 and Var.tag answers <list>. Every %() and every exhausted List.cdr yields this one value, so an identity test on the bits is a valid emptiness test.

Source: lib/var/encoding.x:258

Var.is_null

meta native int Var.is_null(Var v)

Reports whether v is the all-zero Null value. Null is a value: the null pointer and the external nil. It is legal collection data, iterating a List can return it, and it is false in a condition. Its tag decodes as <p48>, so there is no dedicated null family for Var.is to match.

Write Null as (Var) { .u64 = 0 }. An unresolved C NULL macro also converts to this value when its x2c target is Var.

Source: lib/var/encoding.x:245

Var.is_object

meta native int Var.is_object(Var v)

Reports whether v holds a registered boxed object. True for the builtin classes such as String, List, Array, Map, File, and Iter, and for any tag registered with Var.register_object_tag. A pointer to a handle, such as <string*>, is <reference> instead and answers 0 here.

Source: lib/var/encoding.x:212

Var.is_pointer

meta native int Var.is_pointer(Var v)

Reports whether v holds a native pointer.

Source: lib/var/encoding.x:201

Var.is_reference

meta native int Var.is_reference(Var v)

Reports whether v holds a pointer to a boxed handle.

Source: lib/var/encoding.x:204

Var.is_void

int Var.is_void(Var v)

Reports whether v is the absence sentinel void. An API returns void to say there is nothing here. It is excluded from every collection and iterator value domain: it cannot be pushed into an Array or stored in a Map. Equality and identity still inspect it. Two sentinels compare equal and identical, while one sentinel and one ordinary value compare unequal. Truthiness, hashing, ordering, conversion, and iteration on void raise to a matching catch or terminate.

Null is the all-zero Var: legal collection data and false in a condition. A void result may mean missing, exhausted, or invalid; each API documents its meaning.

Var raw = (Var) { .u64 = 0 };
printf("null: void=%d null=%d\n", raw is void, raw.is_null());
printf("void: void=%d null=%d\n", void is void, void.is_null());

This is the test that accepts a void argument.

Source: lib/var/encoding.x:234

Var.new

Var Var.new(Symbol tag, ...)

Constructs a Var with tag from its tag-directed variadic payload. The tag chooses how the argument is read, so pass exactly the C type the tag names: an int for <i32>, an unsigned long for <u48>, a double for <f64>, a long double for <ldouble>, a pointer for any pointer, reference, or object family, and a Symbol’s numeric value for <symbol>. <void> consumes no payload. Variadic arguments are not converted for you. Assignment, Var boxed = 42;, is the usual way to box a value. Use this constructor when the tag is computed at run time.

Immediate values are stored inline. Wide numeric tags allocate a box in the active Scope. Pointer, reference, and object tags borrow the address and encode only its low 48 bits; they do not take ownership, and the address must satisfy the alignment implied by the tag. A declared custom tag is accepted too and requires an 8-byte-aligned pointer. Once the direct custom rows are taken, a custom object boxes through a process-lifetime cell, one per class and address, so boxing one object twice gives identical bits.

Raises: <bad-target> when tag is neither known nor registered, <conv-range> when a scalar does not fit the tag’s payload width, <bad-arg> when an <array> or <map> pointer is null, <alloc-fail> when a wide box cannot be allocated, and <bad-enc> when a box address cannot be represented or a pointer does not satisfy its tag’s alignment.

Source: lib/var/construction.x:28

Var.null

meta native Var Var.null(void)

Returns Null, the all-zero Var that stands for external nil. Generated call adapters return it for a void target.

Source: lib/var/encoding.x:250

Var.tag_bottom

meta native unsigned long Var.tag_bottom(Symbol tag)

Returns the bottom encoding field of built-in tag.

Source: lib/var/encoding.x:70

Var.tag_top

meta native unsigned long Var.tag_top(Symbol tag)

Returns the top encoding field of built-in tag.

Source: lib/var/encoding.x:62

Advanced and interop API

FunctionSummary
Var.box_longBoxes a long into a scope-owned <long> value.
Var.box_long_doubleBoxes a long double into a scope-owned <ldouble> value.
Var.box_long_longBoxes a native signed long-long value without losing precision.
Var.box_ulongBoxes an unsigned long into a scope-owned <ulong> value.
Var.box_ulong_longBoxes a native unsigned long-long value without losing precision.
Var.encoding_validReports whether value has a valid structural Var encoding.
Var.floatingReturns v’s payload as a double when its tag is floating, or 0.0.
Var.integerReturns v’s payload as a long when its tag is integral, or 0.
Var.integer_compareOrders the integer payloads of a and b, returning -1, 0, or 1.
Var.integer_floating_compareOrders an integer-kinded integer against a floating floating.
Var.kindReturns the Symbol naming the coarse category of v’s payload.
Var.known_tagReports whether tag has a built-in encoding or declared custom class.
Var.long_double_valueReturns the payload of an <ldouble> box, or 0.0 if v has another tag.
Var.long_long_valueReturns an <llong> box’s signed payload, or 0 for another tag.
Var.long_valueReturns the payload of a <long> box, or 0 if v has a different tag.
Var.parseParses str as source text of kind kind and returns the boxed value.
Var.pointerReturns the raw address stored in v, or NULL if it holds no address.
Var.register_object_tagDeclares custom boxed-object tag and returns 0.
Var.tagReturns the Symbol naming the exact family of v’s payload.
Var.ulong_long_valueReturns a <ullong> box’s unsigned payload, or 0 for another tag.
Var.ulong_valueReturns the payload of a <ulong> box, or 0 if v has a different tag.
Var.wide_compareOrders two wide boxes carrying the same tag, returning -1, 0, or 1.
Var.wide_equalReports content equality for supported wide scalar boxes.
Var.wide_hashReturns a supported wide scalar box’s content hash, or 0 otherwise.

Var

Var.box_long

Var Var.box_long(long value)

Boxes a long into a scope-owned <long> value. A Var is eight bytes, and the tag consumes some of them. The five widest native families, long, unsigned long, long long, unsigned long long, and long double, cannot be stored inline. Boxing one allocates a small immutable box in the active scope, and the result lives for that scope’s lifetime like any other scope allocation.

Two boxes of the same number are equal and identical: == compares the values, and === compares the type and the value bits. Var.same compares the 64 Var bits, and therefore the box addresses.

Var five = Var.box_long(5L);
Var also = Var.box_long(5L);
printf("equal=%d identical=%d same=%d tag=%s\n", five == also,
       five === also, five.same(also), five.tag().str());

Raises: <alloc-fail> when the box cannot be allocated and <bad-enc> when its address cannot be represented in a Var. Before Error initialization, allocation failure uses the raw fatal floor.

Source: lib/var/numbers.x:66

Var.box_long_double

Var Var.box_long_double(long double value)

Boxes a long double into a scope-owned <ldouble> value. This is the only family that keeps a full long double payload. The tag names that C family; it does not promise a bit width. Var.floating narrows the value to double; Var.long_double_value preserves the extra precision.

Raises: <alloc-fail> when the box cannot be allocated and <bad-enc> when its address cannot be represented in a Var. Before Error initialization, allocation failure uses the raw fatal floor.

Source: lib/var/numbers.x:119

Var.box_long_long

Var Var.box_long_long(long long value)

Boxes a native signed long-long value without losing precision.

Raises: <alloc-fail> when the box cannot be allocated and <bad-enc> when its address cannot be represented in a Var. Before Error initialization, allocation failure uses the raw fatal floor.

Source: lib/var/numbers.x:93

Var.box_ulong

Var Var.box_ulong(unsigned long value)

Boxes an unsigned long into a scope-owned <ulong> value. <ulong> is a distinct family from <long>. A box made here is never Var.equal or identical to one made by Var.box_long, even when both hold the same bit pattern, because Var.wide_equal requires matching tags. == converts the two as C does. Read it back with Var.ulong_value, the one reader that returns the payload unsigned.

Raises: <alloc-fail> when the box cannot be allocated and <bad-enc> when its address cannot be represented in a Var. Before Error initialization, allocation failure uses the raw fatal floor.

Source: lib/var/numbers.x:82

Var.box_ulong_long

Var Var.box_ulong_long(unsigned long long value)

Boxes a native unsigned long-long value without losing precision.

Raises: <alloc-fail> when the box cannot be allocated and <bad-enc> when its address cannot be represented in a Var. Before Error initialization, allocation failure uses the raw fatal floor.

Source: lib/var/numbers.x:104

Var.encoding_valid

int Var.encoding_valid(Var value)

Reports whether value has a valid structural Var encoding. An address-bearing encoding must still refer to live storage of the right type; wide encodings in particular require a readable Scope-owned box.

Source: lib/var/encoding.x:264

Var.floating

meta native double Var.floating(Var v)

Returns v’s payload as a double when its tag is floating, or 0.0. Handles <f32>, <f64>, and <ldouble>, and reconstructs NaN, +Inf, and -Inf from their discrete tags. An <ldouble> payload is narrowed to double; call Var.long_double_value to keep the full precision.

Like the other raw payload readers this one is silent. An integer, a String, or void reads as 0.0, and nothing distinguishes that from a stored zero. When the tag is not already known, convert with Var.convert in lib/varconvert.x, which raises a conversion failure; the scalar-named readers such as Var.double do this for you.

An unhandled tag yields 0.0.

Source: lib/var/numbers.x:180

Var.integer

meta native long Var.integer(Var v)

Returns v’s payload as a long when its tag is integral, or 0. This reads the payload; it does not convert. It decodes every integer family, from <u8> through <ullong>, including the scope-owned boxes, and returns 0 for a tag it does not handle. A double reads as 0, and so does a String; nothing reports the mismatch. A <ullong> or <llong> payload is truncated to long, and a <ulong> above LONG_MAX comes back negative. Var.ulong_value preserves the unsigned payload. A Symbol reads as its numeric Symbol value.

When the tag might not be what you expect, convert instead of reading. Var.convert in lib/varconvert.x raises a conversion failure. Assigning a Var to an int or a long, and the scalar-named readers such as Var.int, go through Var.convert too.

Var text = "ada";
Var small = (unsigned char) 44;
printf("small=%ld text=%ld\n", small.integer(), text.integer());

An unhandled tag yields 0.

Source: lib/var/numbers.x:224

Var.integer_compare

int Var.integer_compare(Var a, Var b)

Orders the integer payloads of a and b, returning -1, 0, or 1. Each value is decomposed into a sign and an unsigned magnitude first, so the whole integer range orders correctly, including a <ullong> above LONG_MAX against a negative <long>. Subtracting in a fixed-width integer type could overflow.

Both arguments are assumed to be integer-kinded. Another value is decoded by Var.integer, which reads it as 0. Confirm with Var.is_integer when the kinds are not known.

Source: lib/var/ordering.x:19

Var.integer_floating_compare

int Var.integer_floating_compare(Var integer, Var floating)

Orders an integer-kinded integer against a floating floating. Returns -1, 0, or 1 for less, equal, and greater. The integer is never converted to floating point, so a large <ullong> and a nearby double order by their true values. A floating value with a fractional part is never equal to an integer.

+Inf is greater than every integer and -Inf is less than every integer. NaN is not ordered and reports -1. Test the tag for <nan> first if that distinction matters.

Source: lib/var/ordering.x:60

Var.kind

meta native Symbol Var.kind(Var v)

Returns the Symbol naming the coarse category of v’s payload. The categories are <integer>, <floating>, <symbol>, <object>, <pointer>, <reference>, and <void>, and every tag belongs to exactly one. Use kind when a group of families is treated alike. All twelve integer widths answer <integer>, and every builtin class handle such as String, List, Map, and File answers <object>.

<pointer> means a raw C pointer such as <u8*>, while <reference> means a pointer to an object handle such as <string*>. NaN and the infinities are <floating>. Only void is <void>.

Source: lib/var/encoding.x:178

Var.known_tag

int Var.known_tag(Symbol tag)

Reports whether tag has a built-in encoding or declared custom class.

Source: lib/var/var.x:62

Var.long_double_value

meta native long double Var.long_double_value(Var v)

Returns the payload of an <ldouble> box, or 0.0 if v has another tag. This is the only reader that preserves a long double. Every other floating tag, <f64> included, yields 0.0 here instead of being widened. Var.floating is the general floating reader.

A tag mismatch yields 0.0.

Source: lib/var/numbers.x:306

Var.long_long_value

meta native long long Var.long_long_value(Var v)

Returns an <llong> box’s signed payload, or 0 for another tag.

Source: lib/var/numbers.x:292

Var.long_value

meta native long Var.long_value(Var v)

Returns the payload of a <long> box, or 0 if v has a different tag. The test is on the tag, so a <ulong>, <llong>, or <i32> value reads as 0 with no complaint. Var.integer accepts any integer family; use this one when the tag is known and the payload must survive intact.

A tag mismatch yields 0.

Source: lib/var/numbers.x:276

Var.parse

meta native Var Var.parse(String str, Symbol kind)

Parses str as source text of kind kind and returns the boxed value. The kinds understood are <int>, <float>, <double>, <string>, <symbol>, and <char>. For <string>, matching %"..." or "..." delimiters are removed; unquoted input is also accepted, and either form is unescaped. <char> expects 'a' complete with its quotes and produces an <i32>. Both <float> and <double> produce an <f64>; there is no path here to <f32>.

Integer and floating kinds require the whole input to parse, apart from surrounding whitespace. Malformed input, trailing text, a value outside the native reader’s range, or an <int> outside int range returns void, so a parsed numeric zero remains distinguishable from failure.

<symbol> accepts the leading atom or <...> Symbol literal and ignores trailing text; no recognized leading Symbol produces the zero Symbol. A kind this function does not handle returns void, and a bad character literal gives <i32> -1.

Var count = Var.parse("42", <int>);
Var broken = Var.parse("abc", <int>);
Var refused = Var.parse("3", <u8>);
printf("%s=%s %s=%s refused=%d\n", count.tag().str(), count,
       broken.tag().str(), broken, refused is void);

Raises: <alloc-fail> while constructing String or quoted-Symbol output.

Source: lib/var/construction.x:205

Var.pointer

void *Var.pointer(Var v)

Returns the raw address stored in v, or NULL if it holds no address. Every pointer, reference, and object family shares one decoder: the payload is masked free of the subtype bits its family reserves, so the result is the stored low-48-bit address for a <u8*>, a <string> handle, and a registered custom object. The returned pointer is borrowed; this operation does not retain it or change its lifetime. A value that is not address-shaped, such as an integer, a double, a Symbol, a wide box, or void, reads as NULL, and nothing distinguishes that from a stored null pointer.

Nothing here proves that an accepted address is live or came from the right constructor; that remains the typed API’s precondition. This raw decoder also accepts some reserved pointer-shaped bit patterns. Validate external bits with Var.encoding_valid, then confirm the family with Var.tag or Var.is before trusting the result.

Source: lib/var/classes.x:181

Var.register_object_tag

int Var.register_object_tag(Symbol tag)

Declares custom boxed-object tag and returns 0. Declaring spends no Var row; the first box of a value assigns one. Declaring a tag again returns 0; NULL or a built-in tag returns -1 without changing the registry. Declaration must finish before the first successful Thread.start; afterward it raises <bad-state>. Native registry-mutex failure aborts.

Source: lib/var/classes.x:207

Var.tag

meta native Symbol Var.tag(Var v)

Returns the Symbol naming the exact family of v’s payload. The tag names one family: <i32>, <string>, <f64>, <symbol>, or a registered custom object tag. Built-in families have one row in the encoding table in this file. Use Var.kind for a group of families and Var.is to test one family.

Raw Null, the all-zero Var written (Var) { .u64 = 0 }, is a native null pointer. It decodes as <p48>; there is no dedicated null family. Test it with Var.is_null. An encoding matching no reserved row decodes as <f64>, since the shifted double range covers everything left over.

Var raw = (Var) { .u64 = 0 };
printf("%s %s\n", raw.tag().str(), void.tag().str());

Source: lib/var/encoding.x:151

Var.ulong_long_value

meta native unsigned long long Var.ulong_long_value(Var v)

Returns a <ullong> box’s unsigned payload, or 0 for another tag.

Source: lib/var/numbers.x:296

Var.ulong_value

meta native unsigned long Var.ulong_value(Var v)

Returns the payload of a <ulong> box, or 0 if v has a different tag. Prefer this to Var.integer for a <ulong>: the general reader casts the payload to long, which reinterprets anything above LONG_MAX as negative, while this reader returns the unsigned value. A tag that is not <ulong> yields 0 silently, so test with Var.is when the tag is in doubt.

A tag mismatch yields 0.

Source: lib/var/numbers.x:288

Var.wide_compare

int Var.wide_compare(Var a, Var b)

Orders two wide boxes carrying the same tag, returning -1, 0, or 1. Integer families delegate to Var.integer_compare. An <ldouble> pair compares as long double and falls back to a byte comparison when neither operand is less than the other, so distinct NaN representations still order deterministically.

0 means equal, and it is also the answer for mismatched tags and for an argument that is not a wide box. Check the tags first, or use Var.compare, the runtime’s full ordering.

Source: lib/var/numbers.x:377

Var.wide_equal

int Var.wide_equal(Var a, Var b)

Reports content equality for supported wide scalar boxes. Boxed <long>, <ulong>, <llong>, <ullong>, and <ldouble> values are separate allocations, so bit identity says nothing about their contents. This is the payload comparison that Var.equal and === use for those tags. An <ldouble> pair is compared byte for byte, so two NaNs sharing one representation compare equal here.

A 0 result means “not equal as wide boxes”. It also covers an argument that is not a wide box and a pair whose tags differ. For a general equality test use Var.equal, which covers every family, or ==, which compares two numbers as C does.

Source: lib/var/numbers.x:348

Var.wide_hash

unsigned Var.wide_hash(Var v)

Returns a supported wide scalar box’s content hash, or 0 otherwise.

Source: lib/var/numbers.x:316

Runtime-internal callables

These callables connect runtime translation units. They are documented for source readers but are not supported as user API.

FunctionSummary
Var.clone_wideClones the wide numeric value into a new box in the active Scope.
Var.custom_descriptor_indexReturns a boxed custom object’s row, or -1 for another value.
Var.move_wide_toMoves a wide numeric box into the destination Scope held by scope.
Var.wide_ownerReturns the Scope owning a live wide numeric box, or NULL otherwise.

Var

Var.clone_wide

meta native Var Var.clone_wide(Var value)

Clones the wide numeric value into a new box in the active Scope. The clone is == and === to value but has its own box, so Var.same tells the two apart. Returns void when value is not wide.

Raises: <alloc-fail> when the clone cannot be allocated, or <bad-enc> if its address cannot be represented in a Var.

Source: lib/var/numbers.x:131

Var.custom_descriptor_index

int Var.custom_descriptor_index(Var value)

Returns a boxed custom object’s row, or -1 for another value. Rows below 30 belong to one class each; row 30 holds every overflow heap class and row 31 every overflow record.

Source: lib/var/encoding.x:283

Var.move_wide_to

Self Var.move_wide_to(Self value, Scope *scope)

Moves a wide numeric box into the destination Scope held by scope. The box is not copied and value keeps its identity. If the destination slot is NULL, a new Scope is created there. Returns value unchanged for another family. For a wide value, raises <bad-arg> when scope is NULL, or <alloc-fail> when a new destination Scope cannot be allocated. Ownership is unchanged on failure.

Source: lib/var/numbers.x:155

Var.wide_owner

Scope Var.wide_owner(Var v)

Returns the Scope owning a live wide numeric box, or NULL otherwise.

Source: lib/var/numbers.x:162

Public types

TypeKindSummary
TagIdenumNames the built-in Var tags in var-tags.x ledger order, which is the order of x2c_var_taginfo; lib/var-ledger.x checks the two agree.
VarDecodeGroupstructResolves one encoding top: the selector is the middle field when by_middle is set and the bottom field under mask otherwise, and ids maps it to a TagId, or _invalid_ where no tag has it.
VarTagInfostructDescribes one built-in Var tag’s kind and encoding fields.

TagId

typedef enum TagId { _invalid_ = -1, _u8_, _i8_, _u16_, _i16_, _u32_, _i32_, _f32_, _u48_, _i48_, _p48_, _f64_, _long_, _ulong_, _llong_, _ullong_, _ldouble_, _u8_p_, _i8_p_, _u16_p_, _i16_p_, _u32_p_, _i32_p_, _f32_p_, _ulong_p_, _long_p_, _f64_p_, _ullong_p_, _llong_p_, _ldouble_p_, _p48_p_, _u8_pp_, _i8_pp_, _u16_pp_, _i16_pp_, _u32_pp_, _i32_pp_, _f32_pp_, _ulong_pp_, _long_pp_, _f64_pp_, _ullong_pp_, _llong_pp_, _ldouble_pp_, _array_, _block_, _buffer_, _bytes_, _context_, _error_, _file_, _func_, _iter_, _lambda_, _list_, _logger_, _map_, _mutex_, _pipe_, _proc_, _regexp_, _rope_, _scope_, _slice_, _socket_, _stream_, _string_, _symbol_, _tensor_, _thread_, _token_, _var_, _array_p_, _block_p_, _buffer_p_, _bytes_p_, _context_p_, _error_p_, _file_p_, _func_p_, _iter_p_, _lambda_p_, _list_p_, _logger_p_, _map_p_, _mutex_p_, _pipe_p_, _proc_p_, _regexp_p_, _rope_p_, _scope_p_, _slice_p_, _socket_p_, _stream_p_, _string_p_, _symbol_p_, _tensor_p_, _thread_p_, _token_p_, _var_p_, _nan_, _neginf_, _posinf_, _void_, _tag_count_ } TagId

Names the built-in Var tags in var-tags.x ledger order, which is the order of x2c_var_taginfo; lib/var-ledger.x checks the two agree.

Source: lib/var/var.x:28

VarDecodeGroup

typedef struct VarDecodeGroup { unsigned char mask, by_middle; signed char ids[8]; } VarDecodeGroup

Resolves one encoding top: the selector is the middle field when by_middle is set and the bottom field under mask otherwise, and ids maps it to a TagId, or _invalid_ where no tag has it.

Source: lib/var/var.x:56

VarTagInfo

typedef struct VarTagInfo { Symbol tag, kind; unsigned long top, middle, bottom; } VarTagInfo

Describes one built-in Var tag’s kind and encoding fields.

Source: lib/var/var.x:48

Design notes

Var owns the one-word encoding of dynamic values. Doubles keep their IEEE 754 bits, and the special-value ranges carry tagged payloads, native pointers, Symbols, and boxes for wide scalars and custom classes. A Var preserves its runtime kind, and void is excluded from value-bearing protocols.

Tests and examples

make verify (unittest/test-var.x) and make examples (type-conversion-matrix).