Skip to main content

shape_value/
heap_variants.rs

1//! Single source of truth for HeapValue variants.
2//!
3//! `define_heap_types!` generates:
4//! - `HeapValue` enum
5//! - `HeapKind` enum (discriminant)
6//! - `HeapValue::kind()` method
7//! - `HeapValue::is_truthy()` method
8//! - `HeapValue::type_name()` method
9//!
10//! `equals()`, `structural_eq()`, and `Display` remain hand-written because
11//! they have complex per-variant logic (e.g. cross-type numeric comparison).
12
13/// All HeapValue variant data lives here as a single source of truth.
14///
15/// Because Rust macro hygiene makes it impossible to use identifiers across
16/// macro boundaries (the `_v` in a pattern introduced by one macro cannot be
17/// referenced by tokens captured from a different call site), we define both
18/// the variant table AND the dispatch expressions in the SAME macro.
19///
20/// `define_heap_types!` takes no arguments — the variant table is embedded.
21/// The public types and `impl` blocks are generated inside the expansion.
22///
23/// Callers import this via `crate::define_heap_types!()`.
24#[macro_export]
25macro_rules! define_heap_types {
26    () => {
27        /// Discriminator for HeapValue variants, usable without full pattern match.
28        ///
29        /// The discriminant order is ABI-stable (checked by tests in tags.rs).
30        /// New variants MUST be appended at the end.
31        #[derive(Debug, Clone, Copy, PartialEq, Eq)]
32        #[repr(u8)]
33        pub enum HeapKind {
34            String,             // 0
35            Array,              // 1
36            TypedObject,        // 2
37            Closure,            // 3
38            Decimal,            // 4
39            BigInt,             // 5
40            HostClosure,        // 6
41            DataTable,          // 7
42            TypedTable,         // 8
43            RowView,            // 9
44            ColumnRef,          // 10
45            IndexedTable,       // 11
46            Range,              // 12
47            Enum,               // 13
48            Some,               // 14
49            Ok,                 // 15
50            Err,                // 16
51            Future,             // 17
52            TaskGroup,          // 18
53            TraitObject,        // 19
54            ExprProxy,          // 20
55            FilterExpr,         // 21
56            Time,               // 22
57            Duration,           // 23
58            TimeSpan,           // 24
59            Timeframe,          // 25
60            TimeReference,      // 26
61            DateTimeExpr,       // 27
62            DataDateTimeRef,    // 28
63            TypeAnnotation,     // 29
64            TypeAnnotatedValue, // 30
65            PrintResult,        // 31
66            SimulationCall,     // 32
67            FunctionRef,        // 33
68            DataReference,      // 34
69            Number,             // 35
70            Bool,               // 36
71            None,               // 37
72            Unit,               // 38
73            Function,           // 39
74            ModuleFunction,     // 40
75            HashMap,            // 41
76            Content,            // 42
77            Instant,            // 43
78            IoHandle,           // 44
79            SharedCell,         // 45
80            NativeScalar,       // 46
81            NativeView,         // 47
82            IntArray,           // 48
83            FloatArray,         // 49
84            BoolArray,          // 50
85            Matrix,             // 51
86            Iterator,           // 52
87            Generator,          // 53
88            Mutex,              // 54
89            Atomic,             // 55
90            Lazy,               // 56
91            I8Array,            // 57
92            I16Array,           // 58
93            I32Array,           // 59
94            U8Array,            // 60
95            U16Array,           // 61
96            U32Array,           // 62
97            U64Array,           // 63
98            F32Array,           // 64
99            Set,                // 65
100            Deque,              // 66
101            PriorityQueue,      // 67
102            Channel,            // 68
103            Char,               // 69
104            ProjectedRef,       // 70
105            FloatArraySlice,    // 71
106        }
107
108        /// Compact heap-allocated value for ValueWord TAG_HEAP.
109        ///
110        /// Every type that cannot be inlined in ValueWord has a dedicated variant here.
111        /// Inline ValueWord types (f64, i48, bool, None, Unit, Function, ModuleFunction)
112        /// are never stored in HeapValue.
113        #[derive(Debug, Clone)]
114        pub enum HeapValue {
115            // ===== Tuple variants =====
116            String(std::sync::Arc<String>),
117            Array($crate::value::VMArray),
118            Decimal(rust_decimal::Decimal),
119            BigInt(i64),
120            HostClosure($crate::value::HostCallable),
121            DataTable(std::sync::Arc<$crate::datatable::DataTable>),
122            HashMap(Box<$crate::heap_value::HashMapData>),
123            Set(Box<$crate::heap_value::SetData>),
124            Deque(Box<$crate::heap_value::DequeData>),
125            PriorityQueue(Box<$crate::heap_value::PriorityQueueData>),
126            Content(Box<$crate::content::ContentNode>),
127            Instant(Box<std::time::Instant>),
128            IoHandle(Box<$crate::heap_value::IoHandleData>),
129            Enum(Box<$crate::enums::EnumValue>),
130            Some(Box<$crate::value_word::ValueWord>),
131            Ok(Box<$crate::value_word::ValueWord>),
132            Err(Box<$crate::value_word::ValueWord>),
133            Future(u64),
134            ExprProxy(std::sync::Arc<String>),
135            FilterExpr(std::sync::Arc<$crate::value::FilterNode>),
136            Time(chrono::DateTime<chrono::FixedOffset>),
137            Duration(shape_ast::ast::Duration),
138            TimeSpan(chrono::Duration),
139            Timeframe(shape_ast::data::Timeframe),
140            // NOTE: Number(f64), Bool(bool), Function(u16), ModuleFunction(usize) — REMOVED.
141            // These were shadow variants duplicating inline ValueWord tags.
142            // HeapKind ordinals 35-40 are reserved (ABI stability).
143            TimeReference(Box<shape_ast::ast::TimeReference>),
144            DateTimeExpr(Box<shape_ast::ast::DateTimeExpr>),
145            DataDateTimeRef(Box<shape_ast::ast::DataDateTimeRef>),
146            TypeAnnotation(Box<shape_ast::ast::TypeAnnotation>),
147            PrintResult(Box<$crate::value::PrintResult>),
148            SimulationCall(Box<$crate::heap_value::SimulationCallData>),
149            DataReference(Box<$crate::heap_value::DataReferenceData>),
150            NativeScalar($crate::heap_value::NativeScalar),
151            NativeView(Box<$crate::heap_value::NativeViewData>),
152            // ===== Typed collection variants =====
153            IntArray(std::sync::Arc<$crate::typed_buffer::TypedBuffer<i64>>),
154            FloatArray(std::sync::Arc<$crate::typed_buffer::AlignedTypedBuffer>),
155            BoolArray(std::sync::Arc<$crate::typed_buffer::TypedBuffer<u8>>),
156            Matrix(std::sync::Arc<$crate::heap_value::MatrixData>),
157            // ===== Width-specific typed arrays =====
158            I8Array(std::sync::Arc<$crate::typed_buffer::TypedBuffer<i8>>),
159            I16Array(std::sync::Arc<$crate::typed_buffer::TypedBuffer<i16>>),
160            I32Array(std::sync::Arc<$crate::typed_buffer::TypedBuffer<i32>>),
161            U8Array(std::sync::Arc<$crate::typed_buffer::TypedBuffer<u8>>),
162            U16Array(std::sync::Arc<$crate::typed_buffer::TypedBuffer<u16>>),
163            U32Array(std::sync::Arc<$crate::typed_buffer::TypedBuffer<u32>>),
164            U64Array(std::sync::Arc<$crate::typed_buffer::TypedBuffer<u64>>),
165            F32Array(std::sync::Arc<$crate::typed_buffer::TypedBuffer<f32>>),
166            Iterator(Box<$crate::heap_value::IteratorState>),
167            Generator(Box<$crate::heap_value::GeneratorState>),
168            // ===== Concurrency primitives =====
169            Mutex(Box<$crate::heap_value::MutexData>),
170            Atomic(Box<$crate::heap_value::AtomicData>),
171            Lazy(Box<$crate::heap_value::LazyData>),
172            Channel(Box<$crate::heap_value::ChannelData>),
173            Char(char),
174            ProjectedRef(Box<$crate::heap_value::ProjectedRefData>),
175            /// Zero-copy read-only slice into a parent matrix row.
176            FloatArraySlice {
177                parent: std::sync::Arc<$crate::heap_value::MatrixData>,
178                offset: u32,
179                len: u32,
180            },
181            // ===== Struct variants =====
182            TypedObject {
183                schema_id: u64,
184                slots: Box<[$crate::slot::ValueSlot]>,
185                heap_mask: u64,
186            },
187            Closure {
188                function_id: u16,
189                upvalues: Vec<$crate::value::Upvalue>,
190            },
191            TypedTable {
192                schema_id: u64,
193                table: std::sync::Arc<$crate::datatable::DataTable>,
194            },
195            RowView {
196                schema_id: u64,
197                table: std::sync::Arc<$crate::datatable::DataTable>,
198                row_idx: usize,
199            },
200            ColumnRef {
201                schema_id: u64,
202                table: std::sync::Arc<$crate::datatable::DataTable>,
203                col_id: u32,
204            },
205            IndexedTable {
206                schema_id: u64,
207                table: std::sync::Arc<$crate::datatable::DataTable>,
208                index_col: u32,
209            },
210            Range {
211                start: Option<Box<$crate::value_word::ValueWord>>,
212                end: Option<Box<$crate::value_word::ValueWord>>,
213                inclusive: bool,
214            },
215            TaskGroup {
216                kind: u8,
217                task_ids: Vec<u64>,
218            },
219            TraitObject {
220                value: Box<$crate::value_word::ValueWord>,
221                vtable: std::sync::Arc<$crate::value::VTable>,
222            },
223            TypeAnnotatedValue {
224                type_name: String,
225                value: Box<$crate::value_word::ValueWord>,
226            },
227            FunctionRef {
228                name: String,
229                closure: Option<Box<$crate::value_word::ValueWord>>,
230            },
231            // ===== Shared mutable cell for closure capture =====
232            SharedCell(std::sync::Arc<std::sync::RwLock<$crate::value_word::ValueWord>>),
233            // NOTE: None and Unit unit variants — REMOVED.
234            // These were shadow variants duplicating inline ValueWord tags.
235            // HeapKind ordinals 37-38 are reserved (ABI stability).
236        }
237
238        impl HeapValue {
239            /// Get the kind discriminator for fast dispatch without full pattern matching.
240            #[inline]
241            pub fn kind(&self) -> HeapKind {
242                match self {
243                    // Tuple
244                    HeapValue::String(..) => HeapKind::String,
245                    HeapValue::Array(..) => HeapKind::Array,
246                    HeapValue::Decimal(..) => HeapKind::Decimal,
247                    HeapValue::BigInt(..) => HeapKind::BigInt,
248                    HeapValue::HostClosure(..) => HeapKind::HostClosure,
249                    HeapValue::DataTable(..) => HeapKind::DataTable,
250                    HeapValue::HashMap(..) => HeapKind::HashMap,
251                    HeapValue::Set(..) => HeapKind::Set,
252                    HeapValue::Deque(..) => HeapKind::Deque,
253                    HeapValue::PriorityQueue(..) => HeapKind::PriorityQueue,
254                    HeapValue::Content(..) => HeapKind::Content,
255                    HeapValue::Instant(..) => HeapKind::Instant,
256                    HeapValue::IoHandle(..) => HeapKind::IoHandle,
257                    HeapValue::NativeScalar(..) => HeapKind::NativeScalar,
258                    HeapValue::NativeView(..) => HeapKind::NativeView,
259                    HeapValue::IntArray(..) => HeapKind::IntArray,
260                    HeapValue::FloatArray(..) => HeapKind::FloatArray,
261                    HeapValue::BoolArray(..) => HeapKind::BoolArray,
262                    HeapValue::Matrix(..) => HeapKind::Matrix,
263                    HeapValue::Iterator(..) => HeapKind::Iterator,
264                    HeapValue::Generator(..) => HeapKind::Generator,
265                    HeapValue::Mutex(..) => HeapKind::Mutex,
266                    HeapValue::Atomic(..) => HeapKind::Atomic,
267                    HeapValue::Lazy(..) => HeapKind::Lazy,
268                    HeapValue::Channel(..) => HeapKind::Channel,
269                    HeapValue::Char(..) => HeapKind::Char,
270                    HeapValue::ProjectedRef(..) => HeapKind::ProjectedRef,
271                    HeapValue::FloatArraySlice { .. } => HeapKind::FloatArraySlice,
272                    HeapValue::I8Array(..) => HeapKind::I8Array,
273                    HeapValue::I16Array(..) => HeapKind::I16Array,
274                    HeapValue::I32Array(..) => HeapKind::I32Array,
275                    HeapValue::U8Array(..) => HeapKind::U8Array,
276                    HeapValue::U16Array(..) => HeapKind::U16Array,
277                    HeapValue::U32Array(..) => HeapKind::U32Array,
278                    HeapValue::U64Array(..) => HeapKind::U64Array,
279                    HeapValue::F32Array(..) => HeapKind::F32Array,
280                    HeapValue::Enum(..) => HeapKind::Enum,
281                    HeapValue::Some(..) => HeapKind::Some,
282                    HeapValue::Ok(..) => HeapKind::Ok,
283                    HeapValue::Err(..) => HeapKind::Err,
284                    HeapValue::Future(..) => HeapKind::Future,
285                    HeapValue::ExprProxy(..) => HeapKind::ExprProxy,
286                    HeapValue::FilterExpr(..) => HeapKind::FilterExpr,
287                    HeapValue::Time(..) => HeapKind::Time,
288                    HeapValue::Duration(..) => HeapKind::Duration,
289                    HeapValue::TimeSpan(..) => HeapKind::TimeSpan,
290                    HeapValue::Timeframe(..) => HeapKind::Timeframe,
291                    HeapValue::TimeReference(..) => HeapKind::TimeReference,
292                    HeapValue::DateTimeExpr(..) => HeapKind::DateTimeExpr,
293                    HeapValue::DataDateTimeRef(..) => HeapKind::DataDateTimeRef,
294                    HeapValue::TypeAnnotation(..) => HeapKind::TypeAnnotation,
295                    HeapValue::PrintResult(..) => HeapKind::PrintResult,
296                    HeapValue::SimulationCall(..) => HeapKind::SimulationCall,
297                    HeapValue::DataReference(..) => HeapKind::DataReference,
298                    // Struct
299                    HeapValue::TypedObject { .. } => HeapKind::TypedObject,
300                    HeapValue::Closure { .. } => HeapKind::Closure,
301                    HeapValue::TypedTable { .. } => HeapKind::TypedTable,
302                    HeapValue::RowView { .. } => HeapKind::RowView,
303                    HeapValue::ColumnRef { .. } => HeapKind::ColumnRef,
304                    HeapValue::IndexedTable { .. } => HeapKind::IndexedTable,
305                    HeapValue::Range { .. } => HeapKind::Range,
306                    HeapValue::TaskGroup { .. } => HeapKind::TaskGroup,
307                    HeapValue::TraitObject { .. } => HeapKind::TraitObject,
308                    HeapValue::TypeAnnotatedValue { .. } => HeapKind::TypeAnnotatedValue,
309                    HeapValue::FunctionRef { .. } => HeapKind::FunctionRef,
310                    // SharedCell
311                    HeapValue::SharedCell(..) => HeapKind::SharedCell,
312                }
313            }
314
315            /// Check if this heap value is truthy.
316            #[inline]
317            pub fn is_truthy(&self) -> bool {
318                match self {
319                    HeapValue::String(_v) => !_v.is_empty(),
320                    HeapValue::Array(_v) => !_v.is_empty(),
321                    HeapValue::Decimal(_v) => !_v.is_zero(),
322                    HeapValue::BigInt(_v) => *_v != 0,
323                    HeapValue::HostClosure(_) => true,
324                    HeapValue::DataTable(_v) => _v.row_count() > 0,
325                    HeapValue::HashMap(_v) => !_v.keys.is_empty(),
326                    HeapValue::Set(_v) => !_v.items.is_empty(),
327                    HeapValue::Deque(_v) => !_v.items.is_empty(),
328                    HeapValue::PriorityQueue(_v) => !_v.items.is_empty(),
329                    HeapValue::Content(_) => true,
330                    HeapValue::Instant(_) => true,
331                    HeapValue::IoHandle(_v) => _v.is_open(),
332                    HeapValue::NativeScalar(_v) => _v.is_truthy(),
333                    HeapValue::NativeView(_v) => _v.ptr != 0,
334                    HeapValue::IntArray(_v) => !_v.is_empty(),
335                    HeapValue::FloatArray(_v) => !_v.is_empty(),
336                    HeapValue::BoolArray(_v) => !_v.is_empty(),
337                    HeapValue::I8Array(_v) => !_v.is_empty(),
338                    HeapValue::I16Array(_v) => !_v.is_empty(),
339                    HeapValue::I32Array(_v) => !_v.is_empty(),
340                    HeapValue::U8Array(_v) => !_v.is_empty(),
341                    HeapValue::U16Array(_v) => !_v.is_empty(),
342                    HeapValue::U32Array(_v) => !_v.is_empty(),
343                    HeapValue::U64Array(_v) => !_v.is_empty(),
344                    HeapValue::F32Array(_v) => !_v.is_empty(),
345                    HeapValue::Matrix(_v) => _v.data.len() > 0,
346                    HeapValue::Iterator(_v) => !_v.done,
347                    HeapValue::Generator(_v) => _v.state != u16::MAX,
348                    HeapValue::Mutex(_) => true,
349                    HeapValue::Atomic(_v) => {
350                        _v.inner.load(std::sync::atomic::Ordering::Relaxed) != 0
351                    }
352                    HeapValue::Lazy(_v) => _v.is_initialized(),
353                    HeapValue::Channel(_v) => !_v.is_closed(),
354                    HeapValue::Char(_) => true,
355                    HeapValue::ProjectedRef(_) => true,
356                    HeapValue::FloatArraySlice { len, .. } => *len > 0,
357                    HeapValue::Enum(_) => true,
358                    HeapValue::Some(_) => true,
359                    HeapValue::Ok(_) => true,
360                    HeapValue::Err(_) => false,
361                    HeapValue::Future(_) => true,
362                    HeapValue::ExprProxy(_) => true,
363                    HeapValue::FilterExpr(_) => true,
364                    HeapValue::Time(_) => true,
365                    HeapValue::Duration(_) => true,
366                    HeapValue::TimeSpan(_) => true,
367                    HeapValue::Timeframe(_) => true,
368                    HeapValue::TimeReference(_) => true,
369                    HeapValue::DateTimeExpr(_) => true,
370                    HeapValue::DataDateTimeRef(_) => true,
371                    HeapValue::TypeAnnotation(_) => true,
372                    HeapValue::PrintResult(_) => true,
373                    HeapValue::SimulationCall(_) => true,
374                    HeapValue::DataReference(_) => true,
375                    // Struct
376                    HeapValue::TypedObject { slots, .. } => !slots.is_empty(),
377                    HeapValue::Closure { .. } => true,
378                    HeapValue::TypedTable { table, .. } => table.row_count() > 0,
379                    HeapValue::RowView { .. } => true,
380                    HeapValue::ColumnRef { .. } => true,
381                    HeapValue::IndexedTable { table, .. } => table.row_count() > 0,
382                    HeapValue::Range { .. } => true,
383                    HeapValue::TaskGroup { .. } => true,
384                    HeapValue::TraitObject { value, .. } => value.is_truthy(),
385                    HeapValue::TypeAnnotatedValue { value, .. } => value.is_truthy(),
386                    HeapValue::FunctionRef { .. } => true,
387                    // SharedCell
388                    HeapValue::SharedCell(arc) => arc.read().unwrap().is_truthy(),
389                }
390            }
391
392            /// Get the type name for this heap value.
393            #[inline]
394            pub fn type_name(&self) -> &'static str {
395                match self {
396                    HeapValue::String(_) => "string",
397                    HeapValue::Array(_) => "array",
398                    HeapValue::Decimal(_) => "decimal",
399                    HeapValue::BigInt(_) => "int",
400                    HeapValue::HostClosure(_) => "host_closure",
401                    HeapValue::DataTable(_) => "datatable",
402                    HeapValue::HashMap(_) => "hashmap",
403                    HeapValue::Set(_) => "set",
404                    HeapValue::Deque(_) => "deque",
405                    HeapValue::PriorityQueue(_) => "priority_queue",
406                    HeapValue::Content(_) => "content",
407                    HeapValue::Instant(_) => "instant",
408                    HeapValue::IoHandle(_) => "io_handle",
409                    HeapValue::NativeScalar(v) => v.type_name(),
410                    HeapValue::NativeView(v) => {
411                        if v.mutable {
412                            "cmut"
413                        } else {
414                            "cview"
415                        }
416                    }
417                    HeapValue::IntArray(_) => "Vec<int>",
418                    HeapValue::FloatArray(_) => "Vec<number>",
419                    HeapValue::BoolArray(_) => "Vec<bool>",
420                    HeapValue::I8Array(_) => "Vec<i8>",
421                    HeapValue::I16Array(_) => "Vec<i16>",
422                    HeapValue::I32Array(_) => "Vec<i32>",
423                    HeapValue::U8Array(_) => "Vec<u8>",
424                    HeapValue::U16Array(_) => "Vec<u16>",
425                    HeapValue::U32Array(_) => "Vec<u32>",
426                    HeapValue::U64Array(_) => "Vec<u64>",
427                    HeapValue::F32Array(_) => "Vec<f32>",
428                    HeapValue::Matrix(_) => "Mat<number>",
429                    HeapValue::Iterator(_) => "iterator",
430                    HeapValue::Generator(_) => "generator",
431                    HeapValue::Mutex(_) => "mutex",
432                    HeapValue::Atomic(_) => "atomic",
433                    HeapValue::Lazy(_) => "lazy",
434                    HeapValue::Channel(_) => "channel",
435                    HeapValue::Char(_) => "char",
436                    HeapValue::ProjectedRef(_) => "reference",
437                    HeapValue::FloatArraySlice { .. } => "Vec<number>",
438                    HeapValue::Enum(_) => "enum",
439                    HeapValue::Some(_) => "option",
440                    HeapValue::Ok(_) => "result",
441                    HeapValue::Err(_) => "result",
442                    HeapValue::Future(_) => "future",
443                    HeapValue::ExprProxy(_) => "expr_proxy",
444                    HeapValue::FilterExpr(_) => "filter_expr",
445                    HeapValue::Time(_) => "time",
446                    HeapValue::Duration(_) => "duration",
447                    HeapValue::TimeSpan(_) => "timespan",
448                    HeapValue::Timeframe(_) => "timeframe",
449                    HeapValue::TimeReference(_) => "time_reference",
450                    HeapValue::DateTimeExpr(_) => "datetime_expr",
451                    HeapValue::DataDateTimeRef(_) => "data_datetime_ref",
452                    HeapValue::TypeAnnotation(_) => "type_annotation",
453                    HeapValue::PrintResult(_) => "print_result",
454                    HeapValue::SimulationCall(_) => "simulation_call",
455                    HeapValue::DataReference(_) => "data_reference",
456                    // Struct
457                    HeapValue::TypedObject { .. } => "object",
458                    HeapValue::Closure { .. } => "closure",
459                    HeapValue::TypedTable { .. } => "typed_table",
460                    HeapValue::RowView { .. } => "row",
461                    HeapValue::ColumnRef { .. } => "column",
462                    HeapValue::IndexedTable { .. } => "indexed_table",
463                    HeapValue::Range { .. } => "range",
464                    HeapValue::TaskGroup { .. } => "task_group",
465                    HeapValue::TraitObject { .. } => "trait_object",
466                    HeapValue::TypeAnnotatedValue { value, .. } => value.type_name(),
467                    HeapValue::FunctionRef { .. } => "function",
468                    // SharedCell
469                    HeapValue::SharedCell(_) => "shared_cell",
470                }
471            }
472        }
473    };
474}