1pub const TAG_BASE: u64 = 0xFFF8_0000_0000_0000;
28
29pub const PAYLOAD_MASK: u64 = 0x0000_FFFF_FFFF_FFFF;
31
32pub const TAG_MASK: u64 = 0x0007_0000_0000_0000;
34
35pub const TAG_SHIFT: u32 = 48;
37
38pub const CANONICAL_NAN: u64 = 0x7FF8_0000_0000_0000;
42
43pub const I48_MAX: i64 = (1_i64 << 47) - 1;
45
46pub const I48_MIN: i64 = -(1_i64 << 47);
48
49pub const TAG_HEAP: u64 = 0b000;
53
54pub const TAG_INT: u64 = 0b001;
56
57pub const TAG_BOOL: u64 = 0b010;
59
60pub const TAG_NONE: u64 = 0b011;
62
63pub const TAG_UNIT: u64 = 0b100;
65
66pub const TAG_FUNCTION: u64 = 0b101;
68
69pub const TAG_MODULE_FN: u64 = 0b110;
71
72pub const TAG_REF: u64 = 0b111;
74
75#[inline(always)]
79pub fn make_tagged(tag: u64, payload: u64) -> u64 {
80 debug_assert!(tag <= 0b111);
81 debug_assert!(payload & !PAYLOAD_MASK == 0, "payload exceeds 48 bits");
82 TAG_BASE | (tag << TAG_SHIFT) | payload
83}
84
85#[inline(always)]
87pub fn is_tagged(bits: u64) -> bool {
88 (bits & TAG_BASE) == TAG_BASE
89}
90
91#[inline(always)]
93pub fn is_number(bits: u64) -> bool {
94 !is_tagged(bits)
95}
96
97#[inline(always)]
99pub fn get_tag(bits: u64) -> u64 {
100 (bits & TAG_MASK) >> TAG_SHIFT
101}
102
103#[inline(always)]
105pub fn get_payload(bits: u64) -> u64 {
106 bits & PAYLOAD_MASK
107}
108
109#[inline(always)]
111pub fn sign_extend_i48(bits: u64) -> i64 {
112 let shifted = (bits as i64) << 16;
113 shifted >> 16
114}
115
116pub const HEAP_KIND_STRING: u8 = 0;
122pub const HEAP_KIND_ARRAY: u8 = 1;
123pub const HEAP_KIND_TYPED_OBJECT: u8 = 2;
124pub const HEAP_KIND_CLOSURE: u8 = 3;
125pub const HEAP_KIND_DECIMAL: u8 = 4;
126pub const HEAP_KIND_BIG_INT: u8 = 5;
127pub const HEAP_KIND_HOST_CLOSURE: u8 = 6;
128pub const HEAP_KIND_DATATABLE: u8 = 7;
129pub const HEAP_KIND_TYPED_TABLE: u8 = 8;
130pub const HEAP_KIND_ROW_VIEW: u8 = 9;
131pub const HEAP_KIND_COLUMN_REF: u8 = 10;
132pub const HEAP_KIND_INDEXED_TABLE: u8 = 11;
133pub const HEAP_KIND_RANGE: u8 = 12;
134pub const HEAP_KIND_ENUM: u8 = 13;
135pub const HEAP_KIND_SOME: u8 = 14;
136pub const HEAP_KIND_OK: u8 = 15;
137pub const HEAP_KIND_ERR: u8 = 16;
138pub const HEAP_KIND_FUTURE: u8 = 17;
139pub const HEAP_KIND_TASK_GROUP: u8 = 18;
140pub const HEAP_KIND_TRAIT_OBJECT: u8 = 19;
141pub const HEAP_KIND_EXPR_PROXY: u8 = 20;
142pub const HEAP_KIND_FILTER_EXPR: u8 = 21;
143pub const HEAP_KIND_TIME: u8 = 22;
144pub const HEAP_KIND_DURATION: u8 = 23;
145pub const HEAP_KIND_TIMESPAN: u8 = 24;
146pub const HEAP_KIND_TIMEFRAME: u8 = 25;
147pub const HEAP_KIND_TIME_REFERENCE: u8 = 26;
148pub const HEAP_KIND_DATETIME_EXPR: u8 = 27;
149pub const HEAP_KIND_DATA_DATETIME_REF: u8 = 28;
150pub const HEAP_KIND_TYPE_ANNOTATION: u8 = 29;
151pub const HEAP_KIND_TYPE_ANNOTATED_VALUE: u8 = 30;
152pub const HEAP_KIND_PRINT_RESULT: u8 = 31;
153pub const HEAP_KIND_SIMULATION_CALL: u8 = 32;
154pub const HEAP_KIND_FUNCTION_REF: u8 = 33;
155pub const HEAP_KIND_DATA_REFERENCE: u8 = 34;
156pub const HEAP_KIND_NUMBER: u8 = 35;
157pub const HEAP_KIND_BOOL: u8 = 36;
158pub const HEAP_KIND_NONE: u8 = 37;
159pub const HEAP_KIND_UNIT: u8 = 38;
160pub const HEAP_KIND_FUNCTION: u8 = 39;
161pub const HEAP_KIND_MODULE_FUNCTION: u8 = 40;
162pub const HEAP_KIND_HASHMAP: u8 = 41;
163pub const HEAP_KIND_CONTENT: u8 = 42;
164pub const HEAP_KIND_INSTANT: u8 = 43;
165pub const HEAP_KIND_IO_HANDLE: u8 = 44;
166pub const HEAP_KIND_SHARED_CELL: u8 = 45;
167pub const HEAP_KIND_NATIVE_SCALAR: u8 = 46;
168pub const HEAP_KIND_NATIVE_VIEW: u8 = 47;
169pub const HEAP_KIND_INT_ARRAY: u8 = 48;
170pub const HEAP_KIND_FLOAT_ARRAY: u8 = 49;
171pub const HEAP_KIND_BOOL_ARRAY: u8 = 50;
172pub const HEAP_KIND_MATRIX: u8 = 51;
173pub const HEAP_KIND_ITERATOR: u8 = 52;
174pub const HEAP_KIND_GENERATOR: u8 = 53;
175pub const HEAP_KIND_MUTEX: u8 = 54;
176pub const HEAP_KIND_ATOMIC: u8 = 55;
177pub const HEAP_KIND_LAZY: u8 = 56;
178pub const HEAP_KIND_I8_ARRAY: u8 = 57;
179pub const HEAP_KIND_I16_ARRAY: u8 = 58;
180pub const HEAP_KIND_I32_ARRAY: u8 = 59;
181pub const HEAP_KIND_U8_ARRAY: u8 = 60;
182pub const HEAP_KIND_U16_ARRAY: u8 = 61;
183pub const HEAP_KIND_U32_ARRAY: u8 = 62;
184pub const HEAP_KIND_U64_ARRAY: u8 = 63;
185pub const HEAP_KIND_F32_ARRAY: u8 = 64;
186pub const HEAP_KIND_SET: u8 = 65;
187pub const HEAP_KIND_DEQUE: u8 = 66;
188pub const HEAP_KIND_PRIORITY_QUEUE: u8 = 67;
189pub const HEAP_KIND_CHANNEL: u8 = 68;
190pub const HEAP_KIND_CHAR: u8 = 69;
191pub const HEAP_KIND_PROJECTED_REF: u8 = 70;
192pub const HEAP_KIND_FLOAT_ARRAY_SLICE: u8 = 71;
193
194#[cfg(test)]
195mod tests {
196 use super::*;
197
198 #[test]
199 fn test_tag_round_trip() {
200 for tag in 0..=7u64 {
201 let payload = 0x1234_5678_ABCDu64;
202 let bits = make_tagged(tag, payload);
203 assert!(is_tagged(bits));
204 assert!(!is_number(bits));
205 assert_eq!(get_tag(bits), tag);
206 assert_eq!(get_payload(bits), payload);
207 }
208 }
209
210 #[test]
211 fn test_f64_not_tagged() {
212 let f = 3.14f64;
213 assert!(!is_tagged(f.to_bits()));
214 assert!(is_number(f.to_bits()));
215 }
216
217 #[test]
218 fn test_canonical_nan_not_tagged() {
219 assert!(!is_tagged(CANONICAL_NAN));
220 }
221
222 #[test]
223 fn test_sign_extend_positive() {
224 assert_eq!(sign_extend_i48(42), 42);
225 }
226
227 #[test]
228 fn test_sign_extend_negative() {
229 let neg1_48 = PAYLOAD_MASK; assert_eq!(sign_extend_i48(neg1_48), -1);
232 }
233
234 #[test]
235 fn test_sign_extend_boundary() {
236 let max_48 = I48_MAX as u64;
238 assert_eq!(sign_extend_i48(max_48), I48_MAX);
239
240 let min_48 = (I48_MIN as u64) & PAYLOAD_MASK;
242 assert_eq!(sign_extend_i48(min_48), I48_MIN);
243 }
244
245 #[test]
246 fn test_heap_kind_constants_match_enum_order() {
247 use crate::heap_value::HeapKind;
249 assert_eq!(HEAP_KIND_STRING, HeapKind::String as u8);
250 assert_eq!(HEAP_KIND_ARRAY, HeapKind::Array as u8);
251 assert_eq!(HEAP_KIND_TYPED_OBJECT, HeapKind::TypedObject as u8);
252 assert_eq!(HEAP_KIND_CLOSURE, HeapKind::Closure as u8);
253 assert_eq!(HEAP_KIND_DECIMAL, HeapKind::Decimal as u8);
254 assert_eq!(HEAP_KIND_BIG_INT, HeapKind::BigInt as u8);
255 assert_eq!(HEAP_KIND_HOST_CLOSURE, HeapKind::HostClosure as u8);
256 assert_eq!(HEAP_KIND_DATATABLE, HeapKind::DataTable as u8);
257 assert_eq!(HEAP_KIND_TYPED_TABLE, HeapKind::TypedTable as u8);
258 assert_eq!(HEAP_KIND_ROW_VIEW, HeapKind::RowView as u8);
259 assert_eq!(HEAP_KIND_COLUMN_REF, HeapKind::ColumnRef as u8);
260 assert_eq!(HEAP_KIND_INDEXED_TABLE, HeapKind::IndexedTable as u8);
261 assert_eq!(HEAP_KIND_RANGE, HeapKind::Range as u8);
262 assert_eq!(HEAP_KIND_ENUM, HeapKind::Enum as u8);
263 assert_eq!(HEAP_KIND_SOME, HeapKind::Some as u8);
264 assert_eq!(HEAP_KIND_OK, HeapKind::Ok as u8);
265 assert_eq!(HEAP_KIND_ERR, HeapKind::Err as u8);
266 assert_eq!(HEAP_KIND_FUTURE, HeapKind::Future as u8);
267 assert_eq!(HEAP_KIND_TASK_GROUP, HeapKind::TaskGroup as u8);
268 assert_eq!(HEAP_KIND_TRAIT_OBJECT, HeapKind::TraitObject as u8);
269 assert_eq!(HEAP_KIND_EXPR_PROXY, HeapKind::ExprProxy as u8);
270 assert_eq!(HEAP_KIND_FILTER_EXPR, HeapKind::FilterExpr as u8);
271 assert_eq!(HEAP_KIND_TIME, HeapKind::Time as u8);
272 assert_eq!(HEAP_KIND_DURATION, HeapKind::Duration as u8);
273 assert_eq!(HEAP_KIND_TIMESPAN, HeapKind::TimeSpan as u8);
274 assert_eq!(HEAP_KIND_TIMEFRAME, HeapKind::Timeframe as u8);
275 assert_eq!(HEAP_KIND_TIME_REFERENCE, HeapKind::TimeReference as u8);
276 assert_eq!(HEAP_KIND_DATETIME_EXPR, HeapKind::DateTimeExpr as u8);
277 assert_eq!(HEAP_KIND_DATA_DATETIME_REF, HeapKind::DataDateTimeRef as u8);
278 assert_eq!(HEAP_KIND_TYPE_ANNOTATION, HeapKind::TypeAnnotation as u8);
279 assert_eq!(
280 HEAP_KIND_TYPE_ANNOTATED_VALUE,
281 HeapKind::TypeAnnotatedValue as u8
282 );
283 assert_eq!(HEAP_KIND_PRINT_RESULT, HeapKind::PrintResult as u8);
284 assert_eq!(HEAP_KIND_SIMULATION_CALL, HeapKind::SimulationCall as u8);
285 assert_eq!(HEAP_KIND_FUNCTION_REF, HeapKind::FunctionRef as u8);
286 assert_eq!(HEAP_KIND_DATA_REFERENCE, HeapKind::DataReference as u8);
287 assert_eq!(HEAP_KIND_NUMBER, HeapKind::Number as u8);
288 assert_eq!(HEAP_KIND_BOOL, HeapKind::Bool as u8);
289 assert_eq!(HEAP_KIND_NONE, HeapKind::None as u8);
290 assert_eq!(HEAP_KIND_UNIT, HeapKind::Unit as u8);
291 assert_eq!(HEAP_KIND_FUNCTION, HeapKind::Function as u8);
292 assert_eq!(HEAP_KIND_MODULE_FUNCTION, HeapKind::ModuleFunction as u8);
293 assert_eq!(HEAP_KIND_HASHMAP, HeapKind::HashMap as u8);
294 assert_eq!(HEAP_KIND_CONTENT, HeapKind::Content as u8);
295 assert_eq!(HEAP_KIND_INSTANT, HeapKind::Instant as u8);
296 assert_eq!(HEAP_KIND_IO_HANDLE, HeapKind::IoHandle as u8);
297 assert_eq!(HEAP_KIND_SHARED_CELL, HeapKind::SharedCell as u8);
298 assert_eq!(HEAP_KIND_NATIVE_SCALAR, HeapKind::NativeScalar as u8);
299 assert_eq!(HEAP_KIND_NATIVE_VIEW, HeapKind::NativeView as u8);
300 assert_eq!(HEAP_KIND_INT_ARRAY, HeapKind::IntArray as u8);
301 assert_eq!(HEAP_KIND_FLOAT_ARRAY, HeapKind::FloatArray as u8);
302 assert_eq!(HEAP_KIND_BOOL_ARRAY, HeapKind::BoolArray as u8);
303 assert_eq!(HEAP_KIND_MATRIX, HeapKind::Matrix as u8);
304 assert_eq!(HEAP_KIND_ITERATOR, HeapKind::Iterator as u8);
305 assert_eq!(HEAP_KIND_GENERATOR, HeapKind::Generator as u8);
306 assert_eq!(HEAP_KIND_MUTEX, HeapKind::Mutex as u8);
307 assert_eq!(HEAP_KIND_ATOMIC, HeapKind::Atomic as u8);
308 assert_eq!(HEAP_KIND_LAZY, HeapKind::Lazy as u8);
309 assert_eq!(HEAP_KIND_I8_ARRAY, HeapKind::I8Array as u8);
310 assert_eq!(HEAP_KIND_I16_ARRAY, HeapKind::I16Array as u8);
311 assert_eq!(HEAP_KIND_I32_ARRAY, HeapKind::I32Array as u8);
312 assert_eq!(HEAP_KIND_U8_ARRAY, HeapKind::U8Array as u8);
313 assert_eq!(HEAP_KIND_U16_ARRAY, HeapKind::U16Array as u8);
314 assert_eq!(HEAP_KIND_U32_ARRAY, HeapKind::U32Array as u8);
315 assert_eq!(HEAP_KIND_U64_ARRAY, HeapKind::U64Array as u8);
316 assert_eq!(HEAP_KIND_F32_ARRAY, HeapKind::F32Array as u8);
317 assert_eq!(HEAP_KIND_SET, HeapKind::Set as u8);
318 assert_eq!(HEAP_KIND_DEQUE, HeapKind::Deque as u8);
319 assert_eq!(HEAP_KIND_PRIORITY_QUEUE, HeapKind::PriorityQueue as u8);
320 assert_eq!(HEAP_KIND_CHANNEL, HeapKind::Channel as u8);
321 assert_eq!(HEAP_KIND_CHAR, HeapKind::Char as u8);
322 assert_eq!(HEAP_KIND_PROJECTED_REF, HeapKind::ProjectedRef as u8);
323 assert_eq!(
324 HEAP_KIND_FLOAT_ARRAY_SLICE,
325 HeapKind::FloatArraySlice as u8
326 );
327 }
328}