use std::collections::HashMap;
use super::super::super::context::{JITDataReference, JITDuration};
use crate::ffi::jit_kinds::*;
use crate::ffi::value_ffi::*;
#[inline(always)]
pub extern "C" fn jit_get_prop(obj_bits: u64, key_bits: u64) -> u64 {
unsafe {
let key_str: Option<&str> = if is_heap_kind(key_bits, HK_STRING) {
Some(unbox_string(key_bits))
} else {
None
};
if tracing::enabled!(target: "shape_jit", tracing::Level::DEBUG) {
tracing::debug!(
target: "shape_jit",
obj = obj_bits,
heap_kind = ?heap_kind(obj_bits),
key = ?key_str,
"jit-get-prop",
);
}
if let Some(kind) = heap_kind(obj_bits) {
match kind {
HK_ARRAY | HK_FLOAT_ARRAY | HK_INT_ARRAY | HK_FLOAT_ARRAY_SLICE
| HK_BOOL_ARRAY | HK_I8_ARRAY | HK_I16_ARRAY | HK_I32_ARRAY
| HK_U8_ARRAY | HK_U16_ARRAY | HK_U32_ARRAY | HK_U64_ARRAY
| HK_F32_ARRAY => {
let _ = key_str;
todo!(
"phase-2c §2.7.4 / W10 jit-playbook §5: \
JitArray rebuild — jit_get_prop array arm. \
Receiver decode + length/first/last/index \
all block on the kinded TypedArray<T> \
rebuild per ADR-006 §2.7.6/Q8."
)
}
HK_JIT_OBJECT => {
let obj = unified_unbox::<HashMap<String, u64>>(obj_bits);
match key_str {
Some(key) => obj.get(key).copied().unwrap_or(TAG_NULL),
None => TAG_NULL,
}
}
HK_STRING => {
let s = unbox_string(obj_bits);
match key_str {
Some("length") | Some("len") => box_number(s.chars().count() as f64),
_ => {
if is_number(key_bits) {
let idx_f64 = unbox_number(key_bits);
let char_count = s.chars().count();
let idx = if idx_f64 < 0.0 {
let len = char_count as i64;
let neg_idx = idx_f64 as i64;
let actual_idx = len + neg_idx;
if actual_idx < 0 {
return TAG_NULL;
}
actual_idx as usize
} else {
idx_f64 as usize
};
if let Some(c) = s.chars().nth(idx) {
box_string(c.to_string())
} else {
TAG_NULL
}
} else {
TAG_NULL
}
}
}
}
HK_DURATION => {
let dur = unified_unbox::<JITDuration>(obj_bits);
match key_str {
Some("value") => box_number(dur.value),
Some("unit") => box_number(dur.unit as f64),
_ => TAG_NULL,
}
}
HK_TIME => {
use chrono::{Datelike, TimeZone, Timelike, Utc};
let timestamp = *unified_unbox::<i64>(obj_bits);
match key_str {
Some("timestamp") | Some("unix") | Some("ts") => {
box_number(timestamp as f64)
}
Some("ms") | Some("timestamp_millis") => {
box_number((timestamp * 1000) as f64)
}
Some("year") | Some("month") | Some("day") | Some("hour")
| Some("minute") | Some("second") | Some("weekday") => {
if let chrono::LocalResult::Single(dt) = Utc.timestamp_opt(timestamp, 0)
{
match key_str {
Some("year") => box_number(dt.year() as f64),
Some("month") => box_number(dt.month() as f64),
Some("day") => box_number(dt.day() as f64),
Some("hour") => box_number(dt.hour() as f64),
Some("minute") => box_number(dt.minute() as f64),
Some("second") => box_number(dt.second() as f64),
Some("weekday") => {
box_number(dt.weekday().num_days_from_monday() as f64)
}
_ => TAG_NULL,
}
} else {
TAG_NULL
}
}
_ => TAG_NULL,
}
}
HK_DATA_REFERENCE => {
let data_ref = unified_unbox::<JITDataReference>(obj_bits);
match key_str {
Some("datetime") | Some("time") | Some("timestamp") => {
unified_box(HK_TIME, data_ref.timestamp)
}
Some("symbol") => {
if !data_ref.symbol.is_null() {
let symbol = (*data_ref.symbol).clone();
box_string(symbol)
} else {
TAG_NULL
}
}
Some("timeframe") => {
let tf_value = data_ref.timeframe_value;
let tf_unit = data_ref.timeframe_unit;
let unit = match tf_unit {
0 => crate::ast::TimeframeUnit::Second,
1 => crate::ast::TimeframeUnit::Minute,
2 => crate::ast::TimeframeUnit::Hour,
3 => crate::ast::TimeframeUnit::Day,
4 => crate::ast::TimeframeUnit::Week,
5 => crate::ast::TimeframeUnit::Month,
_ => crate::ast::TimeframeUnit::Minute,
};
let tf = crate::ast::Timeframe::new(tf_value, unit);
unified_box(HK_TIMEFRAME, tf)
}
Some("timezone") => {
if data_ref.has_timezone && !data_ref.timezone.is_null() {
let tz = (*data_ref.timezone).clone();
box_string(tz)
} else {
box_str("UTC")
}
}
_ => TAG_NULL,
}
}
HK_TYPED_OBJECT => {
let ptr =
unbox_typed_object(obj_bits) as *const super::super::typed_object::TypedObject;
if !ptr.is_null() {
if let Some(key) = key_str {
let schema_id = (*ptr).schema_id;
let mut field_idx = shape_runtime::type_schema::lookup_schema_by_id_public(schema_id)
.and_then(|s| s.field_names().position(|n| n == key));
if field_idx.is_none() {
field_idx = super::super::control::with_trampoline_vm(|vm| {
vm.program().type_schema_registry
.get_by_id(schema_id)
.and_then(|s| s.field_names().position(|n| n == key))
}).flatten();
}
if let Some(idx) = field_idx {
return (*ptr).get_field(idx * 8);
}
}
}
TAG_NULL
}
_ => TAG_NULL,
}
} else {
TAG_NULL
}
}
}
#[inline(always)]
pub extern "C" fn jit_hashmap_shape_id(_obj_bits: u64) -> u32 {
0
}
#[inline(always)]
pub extern "C" fn jit_hashmap_value_at(_obj_bits: u64, _slot_index: u64) -> u64 {
TAG_NULL
}
#[inline(always)]
pub extern "C" fn jit_length(value_bits: u64) -> u64 {
let len = match heap_kind(value_bits) {
Some(HK_ARRAY) | Some(HK_FLOAT_ARRAY) | Some(HK_INT_ARRAY)
| Some(HK_FLOAT_ARRAY_SLICE) | Some(HK_BOOL_ARRAY)
| Some(HK_I8_ARRAY) | Some(HK_I16_ARRAY) | Some(HK_I32_ARRAY)
| Some(HK_U8_ARRAY) | Some(HK_U16_ARRAY) | Some(HK_U32_ARRAY)
| Some(HK_U64_ARRAY) | Some(HK_F32_ARRAY) => {
todo!(
"phase-2c §2.7.4 / W10 jit-playbook §5: JitArray \
rebuild — jit_length array arm."
)
}
Some(HK_STRING) => {
let s = unsafe { unbox_string(value_bits) };
s.chars().count()
}
Some(HK_JIT_OBJECT) => {
let obj = unsafe { unified_unbox::<HashMap<String, u64>>(value_bits) };
obj.len()
}
Some(HK_COLUMN_REF) => 0,
_ => {
0
}
};
box_number(len as f64)
}