Skip to main content

dynamic/
types.rs

1use crate::{Dynamic, DynamicErr};
2use smol_str::SmolStr;
3
4use anyhow::{Result, anyhow};
5use parking_lot::RwLock;
6use std::rc::Rc;
7
8#[derive(Debug, Clone, Copy, Eq, PartialEq)]
9pub enum ConstIntOp {
10    Add,
11    Sub,
12    Mul,
13    Div,
14    Mod,
15}
16
17#[derive(Debug, Default, Clone, Eq)]
18pub enum Type {
19    #[default]
20    Any, //这个是任何类型 none 动态类型 可以是任何类型
21    Void, //整个是空类型  void()
22    Bool,
23    U8,
24    I8,
25    U16,
26    I16,
27    U32,
28    I32,
29    U64,
30    I64,
31    F16,
32    F32,
33    F64,
34    Str,
35    Map,
36    List(Rc<Type>),
37    Iter,
38    Ident {
39        name: SmolStr,
40        params: Vec<Type>,
41    },
42    ConstInt(i64),
43    ConstBinary {
44        op: ConstIntOp,
45        left: Rc<Type>,
46        right: Rc<Type>,
47    },
48    Tuple(Vec<Type>),
49    Struct {
50        params: Vec<Type>,
51        fields: Vec<(SmolStr, Type)>,
52    },
53    Vec(Rc<Type>, u32),   //spirv 特有 表示向量 一般在四个元素以下
54    Array(Rc<Type>, u32), //这是通常意义上的 类型数组,没有大小的限制
55    ArrayParam(Rc<Type>, Rc<Type>),
56    Fn {
57        tys: Vec<Type>,
58        ret: Rc<Type>,
59    }, //调用参数 和返回参数的类型 注意
60    Symbol {
61        id: u32,
62        params: Vec<Type>,
63    }, //自定义的类型 仅在有符号表的情况下有意义 可能是结构 有可能是函数 支持泛型参数
64}
65
66unsafe impl Send for Type {}
67unsafe impl Sync for Type {}
68
69/// 两个类型相加得到的"公共类型",也是 VM 里混合宽度算术结果类型的推断规则。
70///
71/// 优先级(从高到低):
72/// 1. 完全相同的类型 → 自身;
73/// 2. 任一为字符串 → `Str`(支持 `任意 + 字符串` 拼接);
74/// 3. 任一为 `Any` → `Any`(动态值参与即退化为动态);
75/// 4. 任一为浮点 → 取较宽的浮点(有 f64 则 f64,否则 f32);
76/// 5. 任一为有符号整数 → 取双方较大宽度的有符号整数(有符号优先于无符号);
77/// 6. 任一为无符号整数 → 取双方较大宽度的无符号整数;
78/// 7. 其它 → `Any`。
79///
80/// 注意:有符号在第 5 步先于无符号被处理,因此 `i32 + u32` 结果是 `i32`(按宽度,
81/// 不做无符号回绕检查)。宽度按 `Type::width` 计算。
82impl std::ops::Add for Type {
83    type Output = Self;
84    fn add(self, rhs: Self) -> Self::Output {
85        if self == rhs {
86            self
87        } else if self.is_str() || rhs.is_str() {
88            Type::Str
89        } else if self.is_any() || rhs.is_any() {
90            Type::Any
91        } else if self.is_float() || rhs.is_float() {
92            if self.is_f64() || rhs.is_f64() { Type::F64 } else { Type::F32 }
93        } else if self.is_int() || rhs.is_int() {
94            // 混合有符号/无符号时按有符号提升,与运行时 ops.rs(checked_i64 路径)一致。
95            // 注意:这会让 u32+i32 -> i32(丢无符号),但运行时本来也走有符号路径,
96            // 保持类型推断与运行时行为一致比保留无符号性更重要。
97            match self.width().max(rhs.width()) {
98                1 => Type::I8,
99                2 => Type::I16,
100                4 => Type::I32,
101                _ => Type::I64,
102            }
103        } else if self.is_uint() || rhs.is_uint() {
104            match self.width().max(rhs.width()) {
105                1 => Type::U8,
106                2 => Type::U16,
107                4 => Type::U32,
108                _ => Type::U64,
109            }
110        } else {
111            Type::Any
112        }
113    }
114}
115
116impl PartialEq for Type {
117    fn eq(&self, other: &Self) -> bool {
118        match (self, other) {
119            (Type::Any, Type::Any) => true,
120            (Type::Void, Type::Void)
121            | (Type::Bool, Type::Bool)
122            | (Type::U8, Type::U8)
123            | (Type::I8, Type::I8)
124            | (Type::U16, Type::U16)
125            | (Type::I16, Type::I16)
126            | (Type::U32, Type::U32)
127            | (Type::I32, Type::I32)
128            | (Type::U64, Type::U64)
129            | (Type::I64, Type::I64)
130            | (Type::F16, Type::F16)
131            | (Type::F32, Type::F32)
132            | (Type::F64, Type::F64)
133            | (Type::Str, Type::Str)
134            | (Type::Map, Type::Map) => true,
135            (Type::List(left), Type::List(right)) => left == right,
136            (Type::Tuple(left), Type::Tuple(right)) => left == right,
137            (Type::Ident { name: name1, params: params1 }, Type::Ident { name: name2, params: params2 }) => name1 == name2 && params1 == params2,
138            (Type::ConstInt(left), Type::ConstInt(right)) => left == right,
139            (Type::ConstBinary { op: op1, left: left1, right: right1 }, Type::ConstBinary { op: op2, left: left2, right: right2 }) => op1 == op2 && left1 == left2 && right1 == right2,
140            (Type::Symbol { id: id1, params: p1 }, Type::Symbol { id: id2, params: p2 }) => id1 == id2 && p1 == p2,
141            (Type::Struct { params: p1, fields: f1 }, Type::Struct { params: p2, fields: f2 }) => {
142                p1.len() == p2.len() && f1.len() == f2.len() && p1.iter().zip(p2.iter()).position(|(t1, t2)| t1 != t2).is_none() && f1.iter().zip(f2.iter()).position(|(item1, item2)| item1 != item2).is_none()
143            }
144            (Type::Vec(elem_type1, len1), Type::Vec(elem_type2, len2)) => elem_type1 == elem_type2 && len1 == len2,
145            (Type::Array(elem_type1, len1), Type::Array(elem_type2, len2)) => elem_type1 == elem_type2 && len1 == len2,
146            (Type::ArrayParam(elem_type1, len1), Type::ArrayParam(elem_type2, len2)) => elem_type1 == elem_type2 && len1 == len2,
147            (Type::Fn { tys: t1, ret: r1 }, Type::Fn { tys: t2, ret: r2 }) => t1 == t2 && r1 == r2,
148            _ => false,
149        }
150    }
151}
152
153impl Type {
154    pub fn list_any() -> Self {
155        Self::List(Rc::new(Self::Any))
156    }
157
158    fn align_up(value: u32, align: u32) -> u32 {
159        if align <= 1 { value } else { (value + align - 1) & !(align - 1) }
160    }
161
162    pub fn align(&self) -> u32 {
163        self.storage_width().min(8).max(1)
164    }
165
166    pub fn storage_width(&self) -> u32 {
167        match self {
168            Self::Void => 0,
169            Self::Bool => 1,
170            Self::U8 | Self::I8 => 1,
171            Self::U16 | Self::I16 | Self::F16 => 2,
172            Self::U32 | Self::I32 | Self::F32 => 4,
173            Self::U64 | Self::I64 | Self::F64 => 8,
174            Self::Struct { params: _, fields } => Self::struct_layout(fields).0,
175            Self::Vec(ty, num) => num * ty.storage_width(),
176            Self::Array(ty, num) => num * ty.storage_width(),
177            Self::ArrayParam(ty, len) => {
178                if let Self::ConstInt(num) = len.as_ref() {
179                    if *num >= 0 { *num as u32 * ty.storage_width() } else { 8 }
180                } else {
181                    8
182                }
183            }
184            Self::ConstBinary { .. } => 8,
185            _ => 8,
186        }
187    }
188
189    pub fn struct_layout(fields: &[(SmolStr, Type)]) -> (u32, Vec<u32>) {
190        let mut offset = 0;
191        let mut offsets = Vec::with_capacity(fields.len());
192        let mut struct_align = 8;
193        for (_, ty) in fields {
194            let align = ty.align().min(8);
195            struct_align = struct_align.max(align);
196            offset = Self::align_up(offset, align);
197            offsets.push(offset);
198            offset += ty.storage_width();
199        }
200        (Self::align_up(offset, struct_align), offsets)
201    }
202
203    pub fn field_offset(&self, idx: usize) -> Option<u32> {
204        if let Self::Struct { params: _, fields } = self { Self::struct_layout(fields).1.get(idx).cloned() } else { None }
205    }
206
207    pub fn len(&self) -> usize {
208        match self {
209            Self::Struct { params: _, fields } => fields.len(),
210            Self::Tuple(items) => items.len(),
211            Self::Vec(_, num) | Self::Array(_, num) => *num as usize,
212            Self::ArrayParam(_, len) => {
213                if let Self::ConstInt(num) = len.as_ref() {
214                    if *num >= 0 { *num as usize } else { 0 }
215                } else {
216                    0
217                }
218            }
219            Self::ConstBinary { .. } => 0,
220            _ => 0,
221        }
222    }
223
224    pub fn compare_args(left: &[Type], right: &[Type]) -> Option<Vec<Type>> {
225        if left.len() != right.len() {
226            return None;
227        }
228        let mut tys = Vec::new();
229        for (left, right) in left.iter().zip(right.iter()) {
230            if left == right || right.is_any() {
231                tys.push(left.clone());
232            } else if left.is_any() {
233                tys.push(right.clone());
234            } else {
235                return None;
236            }
237        }
238        Some(tys)
239    }
240
241    pub fn force(&self, src: Dynamic) -> Result<Dynamic, DynamicErr> {
242        match self {
243            Self::Bool => src.try_into().map(Dynamic::Bool),
244            Self::I8 => src.try_into().map(Dynamic::I8),
245            Self::I16 => src.try_into().map(Dynamic::I16),
246            Self::I32 => src.try_into().map(Dynamic::I32),
247            Self::I64 => src.try_into().map(Dynamic::I64),
248            Self::U8 => src.try_into().map(Dynamic::U8),
249            Self::U16 => src.try_into().map(Dynamic::U16),
250            Self::U32 => src.try_into().map(Dynamic::U32),
251            Self::U64 => src.try_into().map(Dynamic::U64),
252            Self::F16 => {
253                let f: f64 = src.try_into()?;
254                Ok(Dynamic::F16(crate::f64_to_f16(f)))
255            }
256            Self::F32 => src.try_into().map(Dynamic::F32),
257            Self::F64 => src.try_into().map(Dynamic::F64),
258            Self::Str => Ok(Dynamic::from(src.to_string())),
259            _ => Ok(src),
260        }
261    }
262
263    pub fn width(&self) -> u32 {
264        //所占字节数
265        self.storage_width()
266    }
267
268    pub fn is_void(&self) -> bool {
269        if let Self::Void = self { true } else { false }
270    }
271
272    pub fn is_bool(&self) -> bool {
273        if let Self::Bool = self { true } else { false }
274    }
275
276    pub fn is_str(&self) -> bool {
277        if let Self::Str = self { true } else { false }
278    }
279
280    pub fn is_native(&self) -> bool {
281        match self {
282            Self::F16 | Self::F32 | Self::F64 | Self::U8 | Self::I8 | Self::U16 | Self::I16 | Self::U32 | Self::I32 | Self::U64 | Self::I64 => true,
283            _ => false,
284        }
285    }
286
287    pub fn is_any(&self) -> bool {
288        match self {
289            Self::Any => true,
290            Self::Fn { tys: _, ret } => ret.is_any(),
291            _ => false,
292        }
293    }
294
295    pub fn is_ident(&self) -> bool {
296        if let Self::Ident { name: _, params: _ } = self { true } else { false }
297    }
298
299    pub fn is_struct(&self) -> bool {
300        if let Self::Struct { .. } = self { true } else { false }
301    }
302
303    pub fn get_field(&self, name: &str) -> Result<(usize, &Type)> {
304        if let Self::Struct { params: _, fields } = self {
305            fields.iter().enumerate().find(|(_, (field_name, _))| field_name == name).map(|(index, (_, ty))| (index, ty)).ok_or(anyhow!("{:?} 未发现属性 {}", self, name))
306        } else {
307            Err(anyhow!("不是结构体"))
308        }
309    }
310
311    pub fn add_field(&mut self, name: SmolStr, ty: Type) -> Result<u32> {
312        if let Self::Struct { params: _, fields } = self {
313            fields.push((name, ty));
314            Ok(fields.len() as u32 - 1)
315        } else {
316            Err(anyhow!("不是结构体"))
317        }
318    }
319
320    pub fn is_vec(&self) -> bool {
321        if let Self::Vec(_, _) = self { true } else { false }
322    }
323
324    pub fn is_array(&self) -> bool {
325        if let Self::Array(_, _) = self { true } else { false }
326    }
327
328    pub fn is_int(&self) -> bool {
329        match self {
330            Self::I8 | Self::I16 | Self::I32 | Self::I64 => true,
331            _ => false,
332        }
333    }
334
335    pub fn is_uint(&self) -> bool {
336        match self {
337            Self::U8 | Self::U16 | Self::U32 | Self::U64 => true,
338            _ => false,
339        }
340    }
341
342    pub fn sign(self) -> Self {
343        match self {
344            Self::U8 => Self::I8,
345            Self::U16 => Self::I16,
346            Self::U32 => Self::I32,
347            Self::U64 => Self::I64,
348            _ => self,
349        }
350    }
351
352    pub fn is_float(&self) -> bool {
353        match self {
354            Self::F16 | Self::F32 | Self::F64 => true,
355            _ => false,
356        }
357    }
358
359    pub fn is_f64(&self) -> bool {
360        match self {
361            Self::F64 => true,
362            _ => false,
363        }
364    }
365
366    pub fn is_f32(&self) -> bool {
367        match self {
368            Self::F32 => true,
369            _ => false,
370        }
371    }
372
373    pub fn is_fn(&self) -> bool {
374        if let Self::Fn { .. } = self { true } else { false }
375    }
376
377    pub fn from_args(args: Vec<(SmolStr, Type)>) -> (Self, Vec<SmolStr>) {
378        let (args, tys) = args.into_iter().fold((Vec::new(), Vec::new()), |mut v, a| {
379            v.0.push(a.0);
380            v.1.push(a.1);
381            v
382        });
383        (Self::Fn { tys, ret: Rc::new(Type::Any) }, args)
384    }
385}
386
387impl Dynamic {
388    pub fn get_type(&self) -> Type {
389        let len = self.len() as u32;
390        match self {
391            Self::Bool(_) => Type::Bool,
392            Self::I8(_) => Type::I8,
393            Self::I16(_) => Type::I16,
394            Self::I32(_) => Type::I32,
395            Self::I64(_) => Type::I64,
396            Self::U8(_) => Type::U8,
397            Self::U16(_) => Type::U16,
398            Self::U32(_) => Type::U32,
399            Self::U64(_) => Type::U64,
400            Self::F16(_) => Type::F16,
401            Self::F32(_) => Type::F32,
402            Self::F64(_) => Type::F64,
403            Self::Bytes(_) => Type::Vec(Rc::new(Type::U8), len),
404            Self::VecI8(_) => Type::Vec(Rc::new(Type::I8), len),
405            Self::VecI16(_) => Type::Vec(Rc::new(Type::I16), len),
406            Self::VecI32(_) => Type::Vec(Rc::new(Type::I32), len),
407            Self::VecI64(_) => Type::Vec(Rc::new(Type::I64), len),
408            Self::VecU16(_) => Type::Vec(Rc::new(Type::U16), len),
409            Self::VecU32(_) => Type::Vec(Rc::new(Type::U32), len),
410            Self::VecU64(_) => Type::Vec(Rc::new(Type::U64), len),
411            Self::VecF32(_) => Type::Vec(Rc::new(Type::F32), len),
412            Self::VecF64(_) => Type::Vec(Rc::new(Type::F64), len),
413            Self::String(_) | Self::StringBuf(_) => Type::Str,
414            Self::Map(_) => Type::Map,
415            Self::StructView { ty, .. } | Self::StructOwned { ty, .. } => ty.as_ref().clone(),
416            Self::Custom(_) => Type::Any,
417            Self::Null => Type::Void,
418            Self::List(items) => {
419                let tys: Vec<Type> = items.read().iter().map(|v| v.get_type()).collect();
420                if let Some(first) = tys.first() {
421                    if tys.iter().all(|x| x == first) {
422                        return Type::Array(Rc::new(first.clone()), len);
423                    }
424                }
425                Type::list_any()
426            }
427            Self::Iter { idx: _, keys: _, value: _ } => Type::Iter,
428        }
429    }
430}
431
432type DynamicReturnHandler = unsafe fn(*const Dynamic) -> Box<Dynamic>;
433
434static DYNAMIC_RETURN_HANDLER: RwLock<Option<DynamicReturnHandler>> = RwLock::new(None);
435
436pub fn set_dynamic_return_handler(handler: DynamicReturnHandler) {
437    *DYNAMIC_RETURN_HANDLER.write() = Some(handler);
438}
439
440unsafe fn take_dynamic_return(ptr: *const Dynamic) -> Box<Dynamic> {
441    if let Some(handler) = *DYNAMIC_RETURN_HANDLER.read() {
442        unsafe { handler(ptr) }
443    } else if ptr.is_null() {
444        Box::new(Dynamic::Null)
445    } else {
446        unsafe { Box::from_raw(ptr as *mut Dynamic) }
447    }
448}
449
450pub fn call_fn(ptr: i64, ret_ty: Type, param: Box<Dynamic>) -> Result<Box<Dynamic>> {
451    let param = Box::into_raw(param);
452    match ret_ty {
453        Type::Any => {
454            let fn_ptr: extern "C" fn(*const Dynamic) -> *mut Dynamic = unsafe { std::mem::transmute(ptr) };
455            let r = fn_ptr(param);
456            unsafe {
457                drop(Box::from_raw(param));
458            }
459            Ok(unsafe { take_dynamic_return(r) })
460        }
461        Type::Bool => {
462            let fn_ptr: extern "C" fn(*const Dynamic) -> i8 = unsafe { std::mem::transmute(ptr) };
463            let r = fn_ptr(param);
464            unsafe {
465                drop(Box::from_raw(param));
466            }
467            Ok(Box::new(Dynamic::Bool(r != 0)))
468        }
469        Type::Void => {
470            let fn_ptr: extern "C" fn(*const Dynamic) = unsafe { std::mem::transmute(ptr) };
471            fn_ptr(param);
472            unsafe {
473                drop(Box::from_raw(param));
474            }
475            Ok(Box::new(Dynamic::Null))
476        }
477        Type::F32 => {
478            let fn_ptr: extern "C" fn(*const Dynamic) -> f32 = unsafe { std::mem::transmute(ptr) };
479            let r = fn_ptr(param);
480            unsafe {
481                drop(Box::from_raw(param));
482            }
483            Ok(Box::new(Dynamic::F32(r)))
484        }
485        Type::F64 => {
486            let fn_ptr: extern "C" fn(*const Dynamic) -> f64 = unsafe { std::mem::transmute(ptr) };
487            let r = fn_ptr(param);
488            unsafe {
489                drop(Box::from_raw(param));
490            }
491            Ok(Box::new(Dynamic::F64(r)))
492        }
493        _ => {
494            let fn_ptr: extern "C" fn(*const Dynamic) -> i64 = unsafe { std::mem::transmute(ptr) };
495            let r = fn_ptr(param);
496            unsafe {
497                drop(Box::from_raw(param));
498            }
499            Ok(Box::new(Dynamic::I64(r)))
500        }
501    }
502}