1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
// WASM Value layout: typed ABI.
//
// Native scalar types map directly to WASM types:
// Int → i64 (plain value)
// Float → f64 (plain value)
// Bool → i32 (0 = false, 1 = true)
// Unit → i32 (0)
//
// Heap-allocated types are i32 pointers:
// String → i32 (pointer to string object)
// Result/Option → i32 (pointer to wrapper object)
// List → i32 (pointer to cons cell, 0 = empty)
// Record → i32 (pointer to record object)
// Tuple → i32 (pointer to tuple object)
//
// Heap objects have an 8-byte i64 header followed by 8-byte fields.
// ---------------------------------------------------------------------------
// Heap object kinds
// ---------------------------------------------------------------------------
pub const OBJ_STRING: u64 = 0;
pub const OBJ_RECORD: u64 = 1;
pub const OBJ_VARIANT: u64 = 2;
pub const OBJ_WRAPPER: u64 = 3; // inner field is i64
pub const OBJ_LIST_CONS: u64 = 4; // head is i64, tail is i32 (stored as i64)
pub const OBJ_TUPLE: u64 = 5;
// 6 reserved
pub const OBJ_WRAPPER_F64: u64 = 7; // inner field is f64
pub const OBJ_WRAPPER_I32: u64 = 8; // inner field is i32 (stored as i64)
pub const OBJ_LIST_CONS_F64: u64 = 9; // head is f64, tail is i32 (stored as i64)
pub const OBJ_VECTOR: u64 = 10; // flat array of i64 elements
// kind=11 was OBJ_MAP_ENTRY (assoc-list cons), retired in 0.14 alongside HAMT.
pub const OBJ_MAP: u64 = 12; // flat hashtable (count + cap + entries)
pub const OBJ_BUFFER: u64 = 13; // mutable string buffer for deforestation (`__buf_*`)
// kinds 14, 15 are unused (formerly HAMT_LEAF / HAMT_COLLISION, retired in 0.14).
// ---------------------------------------------------------------------------
// Wrapper tags (Ok/Err/Some)
// ---------------------------------------------------------------------------
pub const WRAP_OK: u64 = 0;
pub const WRAP_ERR: u64 = 1;
pub const WRAP_SOME: u64 = 2;
// ---------------------------------------------------------------------------
// Sentinels (i32 values for non-heap constants)
// ---------------------------------------------------------------------------
/// Empty list sentinel (i32 pointer = 0, null).
pub const EMPTY_LIST: i32 = 0;
/// Option.None sentinel (i32 = -1, distinguishable from null pointer).
pub const NONE_SENTINEL: i32 = -1;
// ---------------------------------------------------------------------------
// Heap object header layout
// ---------------------------------------------------------------------------
// [63:56] = object kind (8 bits)
// [55:48] = variant/wrapper tag (8 bits)
// [47:32] = metadata / pointer mask (16 bits)
// [31:0] = field_count / length (32 bits)
pub const HDR_KIND_SHIFT: u32 = 56;
pub const HDR_TAG_SHIFT: u32 = 48;
pub const HDR_TYPE_SHIFT: u32 = 32;
pub const HDR_META_SHIFT: u32 = HDR_TYPE_SHIFT;
pub const HDR_META_MASK: u64 = 0xFFFF;
pub const OBJ_FORWARD: u64 = 0xFF;
/// Build a heap object header.
///
/// The third field is now runtime metadata:
/// - fixed-size objects use it as a pointer-field bitmask
/// - wrappers/vectors/lists use low bits as per-kind flags