1use std::sync::OnceLock;
2
3pub const TAG_UNIT: u64 = 0x7F00_0000_0000_0000;
15pub const TAG_FALSE: u64 = 0x7F01_0000_0000_0000;
16pub const TAG_TRUE: u64 = 0x7F02_0000_0000_0000;
17pub const TAG_MASK: u64 = 0xFFFF_0000_0000_0000;
18pub const TAG_PATTERN: u64 = 0x7F00_0000_0000_0000;
19pub const PTR_MASK: u64 = 0x0000_FFFF_FFFF_FFFF;
20
21pub const TAG_KIND_UNIT: u64 = 0x0000_0000_0000_0000;
24pub const TAG_KIND_BOOL_FALSE: u64 = 0x0001_0000_0000_0000;
25pub const TAG_KIND_BOOL_TRUE: u64 = 0x0002_0000_0000_0000;
26pub const TAG_KIND_STRING: u64 = 0x0003_0000_0000_0000;
28pub const TAG_KIND_LIST: u64 = 0x0004_0000_0000_0000;
29pub const TAG_KIND_STRUCT: u64 = 0x0005_0000_0000_0000;
30pub const TAG_KIND_VARIANT: u64 = 0x0006_0000_0000_0000;
31pub const TAG_KIND_CLOSURE: u64 = 0x0007_0000_0000_0000;
32pub const TAG_KIND_OK: u64 = 0x0008_0000_0000_0000;
33pub const TAG_KIND_ERR: u64 = 0x0009_0000_0000_0000;
34
35pub type BuiltinDispatch = unsafe extern "C" fn(
40 name_ptr: *const u8,
41 name_len: usize,
42 args_ptr: *const u64,
43 args_len: usize,
44) -> u64;
45
46static BUILTIN_DISPATCH: OnceLock<BuiltinDispatch> = OnceLock::new();
47
48pub fn register_builtin_dispatch(f: BuiltinDispatch) {
49 BUILTIN_DISPATCH.set(f).ok();
50}
51
52#[inline]
54pub unsafe fn call_builtin(name: &str, args: &[u64]) -> u64 {
55 let dispatch = BUILTIN_DISPATCH
56 .get()
57 .expect("BUILTIN_DISPATCH not registered");
58 dispatch(name.as_ptr(), name.len(), args.as_ptr(), args.len())
59}
60
61#[inline]
64pub fn encode_f64(val: f64) -> u64 {
65 val.to_bits()
66}
67
68#[inline]
69pub fn decode_f64(val: u64) -> f64 {
70 f64::from_bits(val)
71}
72
73#[inline]
74pub fn is_number(val: u64) -> bool {
75 (val >> 56) != 0x7F
76}
77
78#[inline]
79pub fn is_tagged(val: u64) -> bool {
80 (val >> 56) == 0x7F
81}
82
83#[inline]
84pub fn encode_bool(val: bool) -> u64 {
85 if val {
86 TAG_TRUE
87 } else {
88 TAG_FALSE
89 }
90}
91
92#[inline]
93pub fn decode_bool(val: u64) -> bool {
94 val == TAG_TRUE
95}
96
97#[inline]
98pub const fn encode_unit() -> u64 {
99 TAG_UNIT
100}
101
102#[inline]
106pub fn encode_heap(tag: u64, ptr: *const u8) -> u64 {
107 TAG_PATTERN | tag | (ptr as u64 & PTR_MASK)
108}
109
110#[inline]
112pub fn decode_ptr(val: u64) -> *const u8 {
113 (val & PTR_MASK) as *const u8
114}
115
116#[inline]
118pub fn tag_kind(val: u64) -> u64 {
119 val & 0x00FF_0000_0000_0000
120}
121
122pub static SYMBOL_MAP: &[(&str, &[u8])] = &[
132 ("__ling_alloc", b"ling_alloc\0"),
134 ("__ling_free", b"ling_free\0"),
135 ("__ling_panic", b"ling_panic\0"),
136 ("__ling_add", b"ling_add\0"),
138 ("__ling_sub", b"ling_sub\0"),
139 ("__ling_mul", b"ling_mul\0"),
140 ("__ling_div", b"ling_div\0"),
141 ("__ling_rem", b"ling_rem\0"),
142 ("__ling_neg", b"ling_neg\0"),
143 ("__ling_eq", b"ling_eq\0"),
145 ("__ling_ne", b"ling_ne\0"),
146 ("__ling_lt", b"ling_lt\0"),
147 ("__ling_le", b"ling_le\0"),
148 ("__ling_gt", b"ling_gt\0"),
149 ("__ling_ge", b"ling_ge\0"),
150 ("__ling_and", b"ling_and\0"),
152 ("__ling_or", b"ling_or\0"),
153 ("__ling_not", b"ling_not\0"),
154 ("__ling_builtin", b"ling_builtin\0"),
156 ("__ling_str_new", b"ling_str_new\0"),
158 ("__ling_str_len", b"ling_str_len\0"),
159 ("__ling_str_concat", b"ling_str_concat\0"),
160 ("__ling_str_eq", b"ling_str_eq\0"),
161 ("__ling_list_new", b"ling_list_new\0"),
163 ("__ling_list_push", b"ling_list_push\0"),
164 ("__ling_list_get", b"ling_list_get\0"),
165 ("__ling_list_len", b"ling_list_len\0"),
166 ("__ling_struct_new", b"ling_struct_new\0"),
168 ("__ling_struct_get", b"ling_struct_get\0"),
169 ("__ling_print", b"ling_print\0"),
171 ("__ling_print_val", b"ling_print_val\0"),
172 ("__ling_print_newline", b"ling_print_newline\0"),
173 ("__ling_time_now", b"ling_time_now\0"),
174 ("__ling_f64_add", b"ling_f64_add\0"),
176 ("__ling_f64_sub", b"ling_f64_sub\0"),
177 ("__ling_f64_mul", b"ling_f64_mul\0"),
178 ("__ling_f64_div", b"ling_f64_div\0"),
179 ("__ling_f64_rem", b"ling_f64_rem\0"),
180 ("__ling_f64_neg", b"ling_f64_neg\0"),
181 ("__ling_f64_eq", b"ling_f64_eq\0"),
182 ("__ling_f64_lt", b"ling_f64_lt\0"),
183 ("__ling_f64_gt", b"ling_f64_gt\0"),
184 ("__ling_f64_le", b"ling_f64_le\0"),
185 ("__ling_f64_ge", b"ling_f64_ge\0"),
186 ("__ling_sin", b"ling_sin\0"),
187 ("__ling_cos", b"ling_cos\0"),
188 ("__ling_sqrt", b"ling_sqrt\0"),
189 ("__ling_abs", b"ling_abs\0"),
190 ("__ling_floor", b"ling_floor\0"),
191 ("__ling_ceil", b"ling_ceil\0"),
192 ("__ling_round", b"ling_round\0"),
193 ("__ling_bool_to_u64", b"ling_bool_to_u64\0"),
195];
196
197extern "C" {
206 pub fn ling_f64_add(a: f64, b: f64) -> f64;
207 pub fn ling_f64_sub(a: f64, b: f64) -> f64;
208 pub fn ling_f64_mul(a: f64, b: f64) -> f64;
209 pub fn ling_f64_div(a: f64, b: f64) -> f64;
210 pub fn ling_f64_rem(a: f64, b: f64) -> f64;
211 pub fn ling_f64_neg(a: f64) -> f64;
212 pub fn ling_f64_eq(a: f64, b: f64) -> u64;
213 pub fn ling_f64_lt(a: f64, b: f64) -> u64;
214 pub fn ling_f64_gt(a: f64, b: f64) -> u64;
215 pub fn ling_f64_le(a: f64, b: f64) -> u64;
216 pub fn ling_f64_ge(a: f64, b: f64) -> u64;
217 pub fn ling_sin(a: f64) -> f64;
218 pub fn ling_cos(a: f64) -> f64;
219 pub fn ling_sqrt(a: f64) -> f64;
220 pub fn ling_abs(a: f64) -> f64;
221 pub fn ling_floor(a: f64) -> f64;
222 pub fn ling_ceil(a: f64) -> f64;
223 pub fn ling_round(a: f64) -> f64;
224 pub fn ling_bool_to_u64(b: u64) -> u64;
225
226 pub fn ling_add(a: u64, b: u64) -> u64;
227 pub fn ling_sub(a: u64, b: u64) -> u64;
228 pub fn ling_mul(a: u64, b: u64) -> u64;
229 pub fn ling_div(a: u64, b: u64) -> u64;
230 pub fn ling_rem(a: u64, b: u64) -> u64;
231 pub fn ling_neg(a: u64) -> u64;
232 pub fn ling_eq(a: u64, b: u64) -> u64;
233 pub fn ling_ne(a: u64, b: u64) -> u64;
234 pub fn ling_lt(a: u64, b: u64) -> u64;
235 pub fn ling_le(a: u64, b: u64) -> u64;
236 pub fn ling_gt(a: u64, b: u64) -> u64;
237 pub fn ling_ge(a: u64, b: u64) -> u64;
238 pub fn ling_and(a: u64, b: u64) -> u64;
239 pub fn ling_or(a: u64, b: u64) -> u64;
240 pub fn ling_not(a: u64) -> u64;
241
242 pub fn ling_alloc(size: u64) -> u64;
243 pub fn ling_free(ptr: u64) -> u64;
244 pub fn ling_panic(msg: u64);
245
246 pub fn ling_str_new(ptr: *const u8, len: usize) -> u64;
247 pub fn ling_str_len(val: u64) -> u64;
248 pub fn ling_str_concat(a: u64, b: u64) -> u64;
249 pub fn ling_str_eq(a: u64, b: u64) -> u64;
250
251 pub fn ling_list_new() -> u64;
252 pub fn ling_list_push(list: u64, val: u64) -> u64;
253 pub fn ling_list_get(list: u64, idx: u64) -> u64;
254 pub fn ling_list_len(list: u64) -> u64;
255
256 pub fn ling_struct_new(
257 name_ptr: *const u8,
258 name_len: usize,
259 args_ptr: *const u64,
260 args_len: usize,
261 ) -> u64;
262 pub fn ling_struct_get(val: u64, field_ptr: *const u8, field_len: usize) -> u64;
263
264 pub fn ling_print(cstr: *const u8);
265 pub fn ling_print_val(val: u64);
266
267 pub fn ling_builtin(
269 name_ptr: *const u8,
270 name_len: usize,
271 args_ptr: *const u64,
272 args_len: usize,
273 ) -> u64;
274}