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        }
104
105        /// Compact heap-allocated value for ValueWord TAG_HEAP.
106        ///
107        /// Every type that cannot be inlined in ValueWord has a dedicated variant here.
108        /// Inline ValueWord types (f64, i48, bool, None, Unit, Function, ModuleFunction)
109        /// are never stored in HeapValue.
110        #[derive(Debug, Clone)]
111        pub enum HeapValue {
112            // ===== Tuple variants =====
113            String(std::sync::Arc<String>),
114            Array($crate::value::VMArray),
115            Decimal(rust_decimal::Decimal),
116            BigInt(i64),
117            HostClosure($crate::value::HostCallable),
118            DataTable(std::sync::Arc<$crate::datatable::DataTable>),
119            HashMap(Box<$crate::heap_value::HashMapData>),
120            Set(Box<$crate::heap_value::SetData>),
121            Deque(Box<$crate::heap_value::DequeData>),
122            PriorityQueue(Box<$crate::heap_value::PriorityQueueData>),
123            Content(Box<$crate::content::ContentNode>),
124            Instant(Box<std::time::Instant>),
125            IoHandle(Box<$crate::heap_value::IoHandleData>),
126            Enum(Box<$crate::enums::EnumValue>),
127            Some(Box<$crate::value_word::ValueWord>),
128            Ok(Box<$crate::value_word::ValueWord>),
129            Err(Box<$crate::value_word::ValueWord>),
130            Future(u64),
131            ExprProxy(std::sync::Arc<String>),
132            FilterExpr(std::sync::Arc<$crate::value::FilterNode>),
133            Time(chrono::DateTime<chrono::FixedOffset>),
134            Duration(shape_ast::ast::Duration),
135            TimeSpan(chrono::Duration),
136            Timeframe(shape_ast::data::Timeframe),
137            // NOTE: Number(f64), Bool(bool), Function(u16), ModuleFunction(usize) — REMOVED.
138            // These were shadow variants duplicating inline ValueWord tags.
139            // HeapKind ordinals 35-40 are reserved (ABI stability).
140            TimeReference(Box<shape_ast::ast::TimeReference>),
141            DateTimeExpr(Box<shape_ast::ast::DateTimeExpr>),
142            DataDateTimeRef(Box<shape_ast::ast::DataDateTimeRef>),
143            TypeAnnotation(Box<shape_ast::ast::TypeAnnotation>),
144            PrintResult(Box<$crate::value::PrintResult>),
145            SimulationCall(Box<$crate::heap_value::SimulationCallData>),
146            DataReference(Box<$crate::heap_value::DataReferenceData>),
147            NativeScalar($crate::heap_value::NativeScalar),
148            NativeView(Box<$crate::heap_value::NativeViewData>),
149            // ===== Typed collection variants =====
150            IntArray(std::sync::Arc<$crate::typed_buffer::TypedBuffer<i64>>),
151            FloatArray(std::sync::Arc<$crate::typed_buffer::AlignedTypedBuffer>),
152            BoolArray(std::sync::Arc<$crate::typed_buffer::TypedBuffer<u8>>),
153            Matrix(Box<$crate::heap_value::MatrixData>),
154            // ===== Width-specific typed arrays =====
155            I8Array(std::sync::Arc<$crate::typed_buffer::TypedBuffer<i8>>),
156            I16Array(std::sync::Arc<$crate::typed_buffer::TypedBuffer<i16>>),
157            I32Array(std::sync::Arc<$crate::typed_buffer::TypedBuffer<i32>>),
158            U8Array(std::sync::Arc<$crate::typed_buffer::TypedBuffer<u8>>),
159            U16Array(std::sync::Arc<$crate::typed_buffer::TypedBuffer<u16>>),
160            U32Array(std::sync::Arc<$crate::typed_buffer::TypedBuffer<u32>>),
161            U64Array(std::sync::Arc<$crate::typed_buffer::TypedBuffer<u64>>),
162            F32Array(std::sync::Arc<$crate::typed_buffer::TypedBuffer<f32>>),
163            Iterator(Box<$crate::heap_value::IteratorState>),
164            Generator(Box<$crate::heap_value::GeneratorState>),
165            // ===== Concurrency primitives =====
166            Mutex(Box<$crate::heap_value::MutexData>),
167            Atomic(Box<$crate::heap_value::AtomicData>),
168            Lazy(Box<$crate::heap_value::LazyData>),
169            Channel(Box<$crate::heap_value::ChannelData>),
170            // ===== Struct variants =====
171            TypedObject {
172                schema_id: u64,
173                slots: Box<[$crate::slot::ValueSlot]>,
174                heap_mask: u64,
175            },
176            Closure {
177                function_id: u16,
178                upvalues: Vec<$crate::value::Upvalue>,
179            },
180            TypedTable {
181                schema_id: u64,
182                table: std::sync::Arc<$crate::datatable::DataTable>,
183            },
184            RowView {
185                schema_id: u64,
186                table: std::sync::Arc<$crate::datatable::DataTable>,
187                row_idx: usize,
188            },
189            ColumnRef {
190                schema_id: u64,
191                table: std::sync::Arc<$crate::datatable::DataTable>,
192                col_id: u32,
193            },
194            IndexedTable {
195                schema_id: u64,
196                table: std::sync::Arc<$crate::datatable::DataTable>,
197                index_col: u32,
198            },
199            Range {
200                start: Option<Box<$crate::value_word::ValueWord>>,
201                end: Option<Box<$crate::value_word::ValueWord>>,
202                inclusive: bool,
203            },
204            TaskGroup {
205                kind: u8,
206                task_ids: Vec<u64>,
207            },
208            TraitObject {
209                value: Box<$crate::value_word::ValueWord>,
210                vtable: std::sync::Arc<$crate::value::VTable>,
211            },
212            TypeAnnotatedValue {
213                type_name: String,
214                value: Box<$crate::value_word::ValueWord>,
215            },
216            FunctionRef {
217                name: String,
218                closure: Option<Box<$crate::value_word::ValueWord>>,
219            },
220            // ===== Shared mutable cell for closure capture =====
221            SharedCell(std::sync::Arc<std::sync::RwLock<$crate::value_word::ValueWord>>),
222            // NOTE: None and Unit unit variants — REMOVED.
223            // These were shadow variants duplicating inline ValueWord tags.
224            // HeapKind ordinals 37-38 are reserved (ABI stability).
225        }
226
227        impl HeapValue {
228            /// Get the kind discriminator for fast dispatch without full pattern matching.
229            #[inline]
230            pub fn kind(&self) -> HeapKind {
231                match self {
232                    // Tuple
233                    HeapValue::String(..) => HeapKind::String,
234                    HeapValue::Array(..) => HeapKind::Array,
235                    HeapValue::Decimal(..) => HeapKind::Decimal,
236                    HeapValue::BigInt(..) => HeapKind::BigInt,
237                    HeapValue::HostClosure(..) => HeapKind::HostClosure,
238                    HeapValue::DataTable(..) => HeapKind::DataTable,
239                    HeapValue::HashMap(..) => HeapKind::HashMap,
240                    HeapValue::Set(..) => HeapKind::Set,
241                    HeapValue::Deque(..) => HeapKind::Deque,
242                    HeapValue::PriorityQueue(..) => HeapKind::PriorityQueue,
243                    HeapValue::Content(..) => HeapKind::Content,
244                    HeapValue::Instant(..) => HeapKind::Instant,
245                    HeapValue::IoHandle(..) => HeapKind::IoHandle,
246                    HeapValue::NativeScalar(..) => HeapKind::NativeScalar,
247                    HeapValue::NativeView(..) => HeapKind::NativeView,
248                    HeapValue::IntArray(..) => HeapKind::IntArray,
249                    HeapValue::FloatArray(..) => HeapKind::FloatArray,
250                    HeapValue::BoolArray(..) => HeapKind::BoolArray,
251                    HeapValue::Matrix(..) => HeapKind::Matrix,
252                    HeapValue::Iterator(..) => HeapKind::Iterator,
253                    HeapValue::Generator(..) => HeapKind::Generator,
254                    HeapValue::Mutex(..) => HeapKind::Mutex,
255                    HeapValue::Atomic(..) => HeapKind::Atomic,
256                    HeapValue::Lazy(..) => HeapKind::Lazy,
257                    HeapValue::Channel(..) => HeapKind::Channel,
258                    HeapValue::I8Array(..) => HeapKind::I8Array,
259                    HeapValue::I16Array(..) => HeapKind::I16Array,
260                    HeapValue::I32Array(..) => HeapKind::I32Array,
261                    HeapValue::U8Array(..) => HeapKind::U8Array,
262                    HeapValue::U16Array(..) => HeapKind::U16Array,
263                    HeapValue::U32Array(..) => HeapKind::U32Array,
264                    HeapValue::U64Array(..) => HeapKind::U64Array,
265                    HeapValue::F32Array(..) => HeapKind::F32Array,
266                    HeapValue::Enum(..) => HeapKind::Enum,
267                    HeapValue::Some(..) => HeapKind::Some,
268                    HeapValue::Ok(..) => HeapKind::Ok,
269                    HeapValue::Err(..) => HeapKind::Err,
270                    HeapValue::Future(..) => HeapKind::Future,
271                    HeapValue::ExprProxy(..) => HeapKind::ExprProxy,
272                    HeapValue::FilterExpr(..) => HeapKind::FilterExpr,
273                    HeapValue::Time(..) => HeapKind::Time,
274                    HeapValue::Duration(..) => HeapKind::Duration,
275                    HeapValue::TimeSpan(..) => HeapKind::TimeSpan,
276                    HeapValue::Timeframe(..) => HeapKind::Timeframe,
277                    HeapValue::TimeReference(..) => HeapKind::TimeReference,
278                    HeapValue::DateTimeExpr(..) => HeapKind::DateTimeExpr,
279                    HeapValue::DataDateTimeRef(..) => HeapKind::DataDateTimeRef,
280                    HeapValue::TypeAnnotation(..) => HeapKind::TypeAnnotation,
281                    HeapValue::PrintResult(..) => HeapKind::PrintResult,
282                    HeapValue::SimulationCall(..) => HeapKind::SimulationCall,
283                    HeapValue::DataReference(..) => HeapKind::DataReference,
284                    // Struct
285                    HeapValue::TypedObject { .. } => HeapKind::TypedObject,
286                    HeapValue::Closure { .. } => HeapKind::Closure,
287                    HeapValue::TypedTable { .. } => HeapKind::TypedTable,
288                    HeapValue::RowView { .. } => HeapKind::RowView,
289                    HeapValue::ColumnRef { .. } => HeapKind::ColumnRef,
290                    HeapValue::IndexedTable { .. } => HeapKind::IndexedTable,
291                    HeapValue::Range { .. } => HeapKind::Range,
292                    HeapValue::TaskGroup { .. } => HeapKind::TaskGroup,
293                    HeapValue::TraitObject { .. } => HeapKind::TraitObject,
294                    HeapValue::TypeAnnotatedValue { .. } => HeapKind::TypeAnnotatedValue,
295                    HeapValue::FunctionRef { .. } => HeapKind::FunctionRef,
296                    // SharedCell
297                    HeapValue::SharedCell(..) => HeapKind::SharedCell,
298                }
299            }
300
301            /// Check if this heap value is truthy.
302            #[inline]
303            pub fn is_truthy(&self) -> bool {
304                match self {
305                    HeapValue::String(_v) => !_v.is_empty(),
306                    HeapValue::Array(_v) => !_v.is_empty(),
307                    HeapValue::Decimal(_v) => !_v.is_zero(),
308                    HeapValue::BigInt(_v) => *_v != 0,
309                    HeapValue::HostClosure(_) => true,
310                    HeapValue::DataTable(_v) => _v.row_count() > 0,
311                    HeapValue::HashMap(_v) => !_v.keys.is_empty(),
312                    HeapValue::Set(_v) => !_v.items.is_empty(),
313                    HeapValue::Deque(_v) => !_v.items.is_empty(),
314                    HeapValue::PriorityQueue(_v) => !_v.items.is_empty(),
315                    HeapValue::Content(_) => true,
316                    HeapValue::Instant(_) => true,
317                    HeapValue::IoHandle(_v) => _v.is_open(),
318                    HeapValue::NativeScalar(_v) => _v.is_truthy(),
319                    HeapValue::NativeView(_v) => _v.ptr != 0,
320                    HeapValue::IntArray(_v) => !_v.is_empty(),
321                    HeapValue::FloatArray(_v) => !_v.is_empty(),
322                    HeapValue::BoolArray(_v) => !_v.is_empty(),
323                    HeapValue::I8Array(_v) => !_v.is_empty(),
324                    HeapValue::I16Array(_v) => !_v.is_empty(),
325                    HeapValue::I32Array(_v) => !_v.is_empty(),
326                    HeapValue::U8Array(_v) => !_v.is_empty(),
327                    HeapValue::U16Array(_v) => !_v.is_empty(),
328                    HeapValue::U32Array(_v) => !_v.is_empty(),
329                    HeapValue::U64Array(_v) => !_v.is_empty(),
330                    HeapValue::F32Array(_v) => !_v.is_empty(),
331                    HeapValue::Matrix(_v) => _v.data.len() > 0,
332                    HeapValue::Iterator(_v) => !_v.done,
333                    HeapValue::Generator(_v) => _v.state != u16::MAX,
334                    HeapValue::Mutex(_) => true,
335                    HeapValue::Atomic(_v) => {
336                        _v.inner.load(std::sync::atomic::Ordering::Relaxed) != 0
337                    }
338                    HeapValue::Lazy(_v) => _v.is_initialized(),
339                    HeapValue::Channel(_v) => !_v.is_closed(),
340                    HeapValue::Enum(_) => true,
341                    HeapValue::Some(_) => true,
342                    HeapValue::Ok(_) => true,
343                    HeapValue::Err(_) => false,
344                    HeapValue::Future(_) => true,
345                    HeapValue::ExprProxy(_) => true,
346                    HeapValue::FilterExpr(_) => true,
347                    HeapValue::Time(_) => true,
348                    HeapValue::Duration(_) => true,
349                    HeapValue::TimeSpan(_) => true,
350                    HeapValue::Timeframe(_) => true,
351                    HeapValue::TimeReference(_) => true,
352                    HeapValue::DateTimeExpr(_) => true,
353                    HeapValue::DataDateTimeRef(_) => true,
354                    HeapValue::TypeAnnotation(_) => true,
355                    HeapValue::PrintResult(_) => true,
356                    HeapValue::SimulationCall(_) => true,
357                    HeapValue::DataReference(_) => true,
358                    // Struct
359                    HeapValue::TypedObject { slots, .. } => !slots.is_empty(),
360                    HeapValue::Closure { .. } => true,
361                    HeapValue::TypedTable { table, .. } => table.row_count() > 0,
362                    HeapValue::RowView { .. } => true,
363                    HeapValue::ColumnRef { .. } => true,
364                    HeapValue::IndexedTable { table, .. } => table.row_count() > 0,
365                    HeapValue::Range { .. } => true,
366                    HeapValue::TaskGroup { .. } => true,
367                    HeapValue::TraitObject { value, .. } => value.is_truthy(),
368                    HeapValue::TypeAnnotatedValue { value, .. } => value.is_truthy(),
369                    HeapValue::FunctionRef { .. } => true,
370                    // SharedCell
371                    HeapValue::SharedCell(arc) => arc.read().unwrap().is_truthy(),
372                }
373            }
374
375            /// Get the type name for this heap value.
376            #[inline]
377            pub fn type_name(&self) -> &'static str {
378                match self {
379                    HeapValue::String(_) => "string",
380                    HeapValue::Array(_) => "array",
381                    HeapValue::Decimal(_) => "decimal",
382                    HeapValue::BigInt(_) => "int",
383                    HeapValue::HostClosure(_) => "host_closure",
384                    HeapValue::DataTable(_) => "datatable",
385                    HeapValue::HashMap(_) => "hashmap",
386                    HeapValue::Set(_) => "set",
387                    HeapValue::Deque(_) => "deque",
388                    HeapValue::PriorityQueue(_) => "priority_queue",
389                    HeapValue::Content(_) => "content",
390                    HeapValue::Instant(_) => "instant",
391                    HeapValue::IoHandle(_) => "io_handle",
392                    HeapValue::NativeScalar(v) => v.type_name(),
393                    HeapValue::NativeView(v) => {
394                        if v.mutable {
395                            "cmut"
396                        } else {
397                            "cview"
398                        }
399                    }
400                    HeapValue::IntArray(_) => "Vec<int>",
401                    HeapValue::FloatArray(_) => "Vec<number>",
402                    HeapValue::BoolArray(_) => "Vec<bool>",
403                    HeapValue::I8Array(_) => "Vec<i8>",
404                    HeapValue::I16Array(_) => "Vec<i16>",
405                    HeapValue::I32Array(_) => "Vec<i32>",
406                    HeapValue::U8Array(_) => "Vec<u8>",
407                    HeapValue::U16Array(_) => "Vec<u16>",
408                    HeapValue::U32Array(_) => "Vec<u32>",
409                    HeapValue::U64Array(_) => "Vec<u64>",
410                    HeapValue::F32Array(_) => "Vec<f32>",
411                    HeapValue::Matrix(_) => "Mat<number>",
412                    HeapValue::Iterator(_) => "iterator",
413                    HeapValue::Generator(_) => "generator",
414                    HeapValue::Mutex(_) => "mutex",
415                    HeapValue::Atomic(_) => "atomic",
416                    HeapValue::Lazy(_) => "lazy",
417                    HeapValue::Channel(_) => "channel",
418                    HeapValue::Enum(_) => "enum",
419                    HeapValue::Some(_) => "option",
420                    HeapValue::Ok(_) => "result",
421                    HeapValue::Err(_) => "result",
422                    HeapValue::Future(_) => "future",
423                    HeapValue::ExprProxy(_) => "expr_proxy",
424                    HeapValue::FilterExpr(_) => "filter_expr",
425                    HeapValue::Time(_) => "time",
426                    HeapValue::Duration(_) => "duration",
427                    HeapValue::TimeSpan(_) => "timespan",
428                    HeapValue::Timeframe(_) => "timeframe",
429                    HeapValue::TimeReference(_) => "time_reference",
430                    HeapValue::DateTimeExpr(_) => "datetime_expr",
431                    HeapValue::DataDateTimeRef(_) => "data_datetime_ref",
432                    HeapValue::TypeAnnotation(_) => "type_annotation",
433                    HeapValue::PrintResult(_) => "print_result",
434                    HeapValue::SimulationCall(_) => "simulation_call",
435                    HeapValue::DataReference(_) => "data_reference",
436                    // Struct
437                    HeapValue::TypedObject { .. } => "object",
438                    HeapValue::Closure { .. } => "closure",
439                    HeapValue::TypedTable { .. } => "typed_table",
440                    HeapValue::RowView { .. } => "row",
441                    HeapValue::ColumnRef { .. } => "column",
442                    HeapValue::IndexedTable { .. } => "indexed_table",
443                    HeapValue::Range { .. } => "range",
444                    HeapValue::TaskGroup { .. } => "task_group",
445                    HeapValue::TraitObject { .. } => "trait_object",
446                    HeapValue::TypeAnnotatedValue { value, .. } => value.type_name(),
447                    HeapValue::FunctionRef { .. } => "function",
448                    // SharedCell
449                    HeapValue::SharedCell(_) => "shared_cell",
450                }
451            }
452        }
453    };
454}