shape_jit/ffi/object/
conversion.rs1use std::sync::Arc;
16
17use super::super::super::context::JITDuration;
18use super::super::super::jit_array::JitArray;
19use super::super::super::nan_boxing::*;
20
21#[derive(Clone)]
23pub struct JitTaskGroup {
24 pub kind: u8,
25 pub task_ids: Vec<u64>,
26}
27
28pub fn jit_bits_to_nanboxed(bits: u64) -> shape_value::ValueWord {
34 use shape_value::ValueWord;
35
36 if is_number(bits) {
37 return ValueWord::from_f64(unbox_number(bits));
38 }
39 if bits == TAG_NULL {
40 return ValueWord::none();
41 }
42 if bits == TAG_BOOL_TRUE {
43 return ValueWord::from_bool(true);
44 }
45 if bits == TAG_BOOL_FALSE {
46 return ValueWord::from_bool(false);
47 }
48 if bits == TAG_UNIT {
49 return ValueWord::unit();
50 }
51 if is_inline_function(bits) {
52 let func_id = unbox_function_id(bits);
53 return ValueWord::from_function_ref(format!("__func_{}", func_id), None);
54 }
55 if is_ok_tag(bits) {
56 let inner_bits = unsafe { unbox_result_inner(bits) };
57 let inner = jit_bits_to_nanboxed(inner_bits);
58 return ValueWord::from_ok(inner);
59 }
60 if is_err_tag(bits) {
61 let inner_bits = unsafe { unbox_result_inner(bits) };
62 let inner = jit_bits_to_nanboxed(inner_bits);
63 return ValueWord::from_err(inner);
64 }
65 if is_some_tag(bits) {
66 let inner_bits = unsafe { unbox_some_inner(bits) };
67 let inner = jit_bits_to_nanboxed(inner_bits);
68 return ValueWord::from_some(inner);
69 }
70
71 match heap_kind(bits) {
72 Some(HK_STRING) => {
73 let s = unsafe { jit_unbox::<String>(bits) };
74 ValueWord::from_string(Arc::new(s.clone()))
75 }
76 Some(HK_ARRAY) => {
77 let arr = unsafe { jit_unbox::<JitArray>(bits) };
78 let values: Vec<ValueWord> = arr.iter().map(|&b| jit_bits_to_nanboxed(b)).collect();
79 ValueWord::from_array(Arc::new(values))
80 }
81 Some(HK_CLOSURE) => {
82 let closure = unsafe { jit_unbox::<super::super::super::context::JITClosure>(bits) };
83 ValueWord::from_function_ref(format!("__func_{}", closure.function_id), None)
84 }
85 Some(HK_TASK_GROUP) => {
86 let tg = unsafe { jit_unbox::<JitTaskGroup>(bits) };
87 ValueWord::from_task_group(tg.kind, tg.task_ids.clone())
88 }
89 Some(HK_FUTURE) => {
90 let id = unsafe { jit_unbox::<u64>(bits) };
91 ValueWord::from_future(*id)
92 }
93 _ => ValueWord::none(),
94 }
95}
96
97pub fn jit_bits_to_nanboxed_with_ctx(
99 bits: u64,
100 ctx: *const super::super::super::context::JITContext,
101) -> shape_value::ValueWord {
102 use shape_value::ValueWord;
103
104 if is_number(bits) {
105 return ValueWord::from_f64(unbox_number(bits));
106 }
107
108 if is_inline_function(bits) {
110 let func_id = unbox_function_id(bits);
111 let name = lookup_function_name(ctx, func_id);
112 return ValueWord::from_function_ref(name, None);
113 }
114
115 if is_heap_kind(bits, HK_CLOSURE) {
116 let closure = unsafe { jit_unbox::<super::super::super::context::JITClosure>(bits) };
117 let name = lookup_function_name(ctx, closure.function_id);
118 return ValueWord::from_function_ref(name, None);
119 }
120
121 if is_heap_kind(bits, HK_ARRAY) {
122 let arr = unsafe { jit_unbox::<JitArray>(bits) };
123 let values: Vec<ValueWord> = arr
124 .iter()
125 .map(|&b| jit_bits_to_nanboxed_with_ctx(b, ctx))
126 .collect();
127 return ValueWord::from_array(Arc::new(values));
128 }
129
130 jit_bits_to_nanboxed(bits)
132}
133
134fn lookup_function_name(
136 ctx: *const super::super::super::context::JITContext,
137 func_id: u16,
138) -> String {
139 if !ctx.is_null() {
140 unsafe {
141 let ctx_ref = &*ctx;
142 if !ctx_ref.function_names_ptr.is_null()
143 && (func_id as usize) < ctx_ref.function_names_len
144 {
145 return (*ctx_ref.function_names_ptr.add(func_id as usize)).clone();
146 }
147 }
148 }
149 format!("__func_{}", func_id)
150}
151
152pub fn jit_bits_to_typed_scalar(
162 bits: u64,
163 hint: Option<shape_vm::SlotKind>,
164) -> shape_value::TypedScalar {
165 use shape_value::{ScalarKind, TypedScalar};
166 use shape_vm::SlotKind;
167
168 if is_number(bits) {
169 let f = unbox_number(bits);
170 if let Some(h) = hint {
172 match h {
173 SlotKind::Int8 | SlotKind::NullableInt8 => {
174 return TypedScalar::i8(f as i8);
175 }
176 SlotKind::UInt8 | SlotKind::NullableUInt8 => {
177 return TypedScalar::u8(f as u8);
178 }
179 SlotKind::Int16 | SlotKind::NullableInt16 => {
180 return TypedScalar::i16(f as i16);
181 }
182 SlotKind::UInt16 | SlotKind::NullableUInt16 => {
183 return TypedScalar::u16(f as u16);
184 }
185 SlotKind::Int32 | SlotKind::NullableInt32 => {
186 return TypedScalar::i32(f as i32);
187 }
188 SlotKind::UInt32 | SlotKind::NullableUInt32 => {
189 return TypedScalar::u32(f as u32);
190 }
191 SlotKind::Int64 | SlotKind::NullableInt64 => {
192 return TypedScalar::i64(f as i64);
193 }
194 SlotKind::UInt64 | SlotKind::NullableUInt64 => {
195 return TypedScalar::u64(f as u64);
196 }
197 SlotKind::Float64 | SlotKind::NullableFloat64 => {
198 return TypedScalar::f64_from_bits(bits);
199 }
200 _ => {
201 }
203 }
204 }
205 return TypedScalar::f64_from_bits(bits);
207 }
208
209 if bits == TAG_BOOL_TRUE {
210 return TypedScalar::bool(true);
211 }
212 if bits == TAG_BOOL_FALSE {
213 return TypedScalar::bool(false);
214 }
215 if bits == TAG_NULL || bits == TAG_NONE {
216 return TypedScalar::none();
217 }
218 if bits == TAG_UNIT {
219 return TypedScalar::unit();
220 }
221
222 TypedScalar::none()
224}
225
226pub fn typed_scalar_to_jit_bits(ts: &shape_value::TypedScalar) -> u64 {
231 use shape_value::ScalarKind;
232
233 match ts.kind {
234 ScalarKind::I8 | ScalarKind::I16 | ScalarKind::I32 | ScalarKind::I64 => {
235 box_number(ts.payload_lo as i64 as f64)
236 }
237 ScalarKind::U8 | ScalarKind::U16 | ScalarKind::U32 | ScalarKind::U64 => {
238 box_number(ts.payload_lo as f64)
239 }
240 ScalarKind::I128 | ScalarKind::U128 => box_number(ts.payload_lo as i64 as f64),
241 ScalarKind::F64 | ScalarKind::F32 => ts.payload_lo, ScalarKind::Bool => {
243 if ts.payload_lo != 0 {
244 TAG_BOOL_TRUE
245 } else {
246 TAG_BOOL_FALSE
247 }
248 }
249 ScalarKind::None => TAG_NULL,
250 ScalarKind::Unit => TAG_UNIT,
251 }
252}
253
254pub fn nanboxed_to_jit_bits(nb: &shape_value::ValueWord) -> u64 {
256 use shape_value::NanTag;
257 use shape_value::heap_value::HeapValue;
258
259 match nb.tag() {
260 NanTag::F64 => box_number(unsafe { nb.as_f64_unchecked() }),
261 NanTag::I48 => box_number(unsafe { nb.as_i64_unchecked() } as f64),
262 NanTag::Bool => {
263 if unsafe { nb.as_bool_unchecked() } {
264 TAG_BOOL_TRUE
265 } else {
266 TAG_BOOL_FALSE
267 }
268 }
269 NanTag::None => TAG_NULL,
270 NanTag::Unit => TAG_UNIT,
271 NanTag::Function => {
272 let func_id = unsafe { nb.as_function_unchecked() };
273 box_function(func_id)
274 }
275 NanTag::ModuleFunction => TAG_NULL,
276 NanTag::Ref => TAG_NULL,
277 NanTag::Heap => match nb.as_heap_ref() {
278 Some(HeapValue::String(s)) => jit_box(HK_STRING, s.clone()),
279 Some(HeapValue::Array(arr)) => {
280 let boxed_arr: Vec<u64> = arr.iter().map(|v| nanboxed_to_jit_bits(v)).collect();
286 jit_box(HK_ARRAY, JitArray::from_vec(boxed_arr))
287 }
288 Some(HeapValue::Time(dt)) => jit_box(HK_TIME, dt.timestamp()),
289 Some(HeapValue::Duration(dur)) => {
290 let unit_code = match dur.unit {
291 crate::ast::DurationUnit::Seconds => 0,
292 crate::ast::DurationUnit::Minutes => 1,
293 crate::ast::DurationUnit::Hours => 2,
294 crate::ast::DurationUnit::Days => 3,
295 crate::ast::DurationUnit::Weeks => 4,
296 crate::ast::DurationUnit::Months => 5,
297 crate::ast::DurationUnit::Years => 6,
298 crate::ast::DurationUnit::Samples => 7,
299 };
300 jit_box(
301 HK_DURATION,
302 JITDuration {
303 value: dur.value,
304 unit: unit_code,
305 },
306 )
307 }
308 Some(HeapValue::Timeframe(tf)) => {
309 let internal_tf = crate::ast::data::Timeframe::new(
310 tf.value,
311 match tf.unit {
312 crate::ast::TimeframeUnit::Second => {
313 crate::ast::data::TimeframeUnit::Second
314 }
315 crate::ast::TimeframeUnit::Minute => {
316 crate::ast::data::TimeframeUnit::Minute
317 }
318 crate::ast::TimeframeUnit::Hour => crate::ast::data::TimeframeUnit::Hour,
319 crate::ast::TimeframeUnit::Day => crate::ast::data::TimeframeUnit::Day,
320 crate::ast::TimeframeUnit::Week => crate::ast::data::TimeframeUnit::Week,
321 crate::ast::TimeframeUnit::Month => crate::ast::data::TimeframeUnit::Month,
322 crate::ast::TimeframeUnit::Year => crate::ast::data::TimeframeUnit::Year,
323 },
324 );
325 jit_box(HK_TIMEFRAME, internal_tf)
326 }
327 Some(HeapValue::Ok(inner)) => {
328 let inner_bits = nanboxed_to_jit_bits(inner);
329 box_ok(inner_bits)
330 }
331 Some(HeapValue::Err(inner)) => {
332 let inner_bits = nanboxed_to_jit_bits(inner);
333 box_err(inner_bits)
334 }
335 Some(HeapValue::Some(inner)) => {
336 let inner_bits = nanboxed_to_jit_bits(inner);
337 box_some(inner_bits)
338 }
339 Some(HeapValue::BigInt(i)) => box_number(*i as f64),
341 Some(HeapValue::TaskGroup { kind, task_ids }) => jit_box(
342 HK_TASK_GROUP,
343 JitTaskGroup {
344 kind: *kind,
345 task_ids: task_ids.clone(),
346 },
347 ),
348 Some(HeapValue::Future(id)) => jit_box(HK_FUTURE, *id),
349 _ => TAG_NULL,
350 },
351 }
352}