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            match self.width().max(rhs.width()) {
95                1 => Type::I8,
96                2 => Type::I16,
97                4 => Type::I32,
98                _ => Type::I64,
99            }
100        } else if self.is_uint() || rhs.is_uint() {
101            match self.width().max(rhs.width()) {
102                1 => Type::U8,
103                2 => Type::U16,
104                4 => Type::U32,
105                _ => Type::U64,
106            }
107        } else {
108            Type::Any
109        }
110    }
111}
112
113impl PartialEq for Type {
114    fn eq(&self, other: &Self) -> bool {
115        match (self, other) {
116            (Type::Any, Type::Any) => true,
117            (Type::Void, Type::Void)
118            | (Type::Bool, Type::Bool)
119            | (Type::U8, Type::U8)
120            | (Type::I8, Type::I8)
121            | (Type::U16, Type::U16)
122            | (Type::I16, Type::I16)
123            | (Type::U32, Type::U32)
124            | (Type::I32, Type::I32)
125            | (Type::U64, Type::U64)
126            | (Type::I64, Type::I64)
127            | (Type::F16, Type::F16)
128            | (Type::F32, Type::F32)
129            | (Type::F64, Type::F64)
130            | (Type::Str, Type::Str)
131            | (Type::Map, Type::Map) => true,
132            (Type::List(left), Type::List(right)) => left == right,
133            (Type::Ident { name: name1, params: params1 }, Type::Ident { name: name2, params: params2 }) => name1 == name2 && params1 == params2,
134            (Type::ConstInt(left), Type::ConstInt(right)) => left == right,
135            (Type::ConstBinary { op: op1, left: left1, right: right1 }, Type::ConstBinary { op: op2, left: left2, right: right2 }) => op1 == op2 && left1 == left2 && right1 == right2,
136            (Type::Symbol { id: id1, params: p1 }, Type::Symbol { id: id2, params: p2 }) => id1 == id2 && p1 == p2,
137            (Type::Struct { params: p1, fields: f1 }, Type::Struct { params: p2, fields: f2 }) => {
138                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()
139            }
140            (Type::Vec(elem_type1, len1), Type::Vec(elem_type2, len2)) => elem_type1 == elem_type2 && len1 == len2,
141            (Type::Array(elem_type1, len1), Type::Array(elem_type2, len2)) => elem_type1 == elem_type2 && len1 == len2,
142            (Type::ArrayParam(elem_type1, len1), Type::ArrayParam(elem_type2, len2)) => elem_type1 == elem_type2 && len1 == len2,
143            (Type::Fn { tys: t1, ret: r1 }, Type::Fn { tys: t2, ret: r2 }) => t1 == t2 && r1 == r2,
144            _ => false,
145        }
146    }
147}
148
149impl Type {
150    pub fn list_any() -> Self {
151        Self::List(Rc::new(Self::Any))
152    }
153
154    fn align_up(value: u32, align: u32) -> u32 {
155        if align <= 1 { value } else { (value + align - 1) & !(align - 1) }
156    }
157
158    pub fn align(&self) -> u32 {
159        self.storage_width().min(8).max(1)
160    }
161
162    pub fn storage_width(&self) -> u32 {
163        match self {
164            Self::Void => 0,
165            Self::Bool => 1,
166            Self::U8 | Self::I8 => 1,
167            Self::U16 | Self::I16 | Self::F16 => 2,
168            Self::U32 | Self::I32 | Self::F32 => 4,
169            Self::U64 | Self::I64 | Self::F64 => 8,
170            Self::Struct { params: _, fields } => Self::struct_layout(fields).0,
171            Self::Vec(ty, num) => num * ty.storage_width(),
172            Self::Array(ty, num) => num * ty.storage_width(),
173            Self::ArrayParam(ty, len) => {
174                if let Self::ConstInt(num) = len.as_ref() {
175                    if *num >= 0 { *num as u32 * ty.storage_width() } else { 8 }
176                } else {
177                    8
178                }
179            }
180            Self::ConstBinary { .. } => 8,
181            _ => 8,
182        }
183    }
184
185    pub fn struct_layout(fields: &[(SmolStr, Type)]) -> (u32, Vec<u32>) {
186        let mut offset = 0;
187        let mut offsets = Vec::with_capacity(fields.len());
188        let mut struct_align = 8;
189        for (_, ty) in fields {
190            let align = ty.align().min(8);
191            struct_align = struct_align.max(align);
192            offset = Self::align_up(offset, align);
193            offsets.push(offset);
194            offset += ty.storage_width();
195        }
196        (Self::align_up(offset, struct_align), offsets)
197    }
198
199    pub fn field_offset(&self, idx: usize) -> Option<u32> {
200        if let Self::Struct { params: _, fields } = self { Self::struct_layout(fields).1.get(idx).cloned() } else { None }
201    }
202
203    pub fn len(&self) -> usize {
204        match self {
205            Self::Struct { params: _, fields } => fields.len(),
206            Self::Tuple(items) => items.len(),
207            Self::Vec(_, num) | Self::Array(_, num) => *num as usize,
208            Self::ArrayParam(_, len) => {
209                if let Self::ConstInt(num) = len.as_ref() {
210                    if *num >= 0 { *num as usize } else { 0 }
211                } else {
212                    0
213                }
214            }
215            Self::ConstBinary { .. } => 0,
216            _ => 0,
217        }
218    }
219
220    pub fn compare_args(left: &[Type], right: &[Type]) -> Option<Vec<Type>> {
221        let mut tys = Vec::new();
222        for (left, right) in left.iter().zip(right.iter()) {
223            if left == right || right.is_any() {
224                tys.push(left.clone());
225            } else if left.is_any() {
226                tys.push(right.clone());
227            } else {
228                return None;
229            }
230        }
231        Some(tys)
232    }
233
234    pub fn force(&self, src: Dynamic) -> Result<Dynamic, DynamicErr> {
235        match self {
236            Self::Bool => src.try_into().map(Dynamic::Bool),
237            Self::I8 => src.try_into().map(Dynamic::I8),
238            Self::I16 => src.try_into().map(Dynamic::I16),
239            Self::I32 => src.try_into().map(Dynamic::I32),
240            Self::I64 => src.try_into().map(Dynamic::I64),
241            Self::U8 => src.try_into().map(Dynamic::U8),
242            Self::U16 => src.try_into().map(Dynamic::U16),
243            Self::U32 => src.try_into().map(Dynamic::U32),
244            Self::U64 => src.try_into().map(Dynamic::U64),
245            Self::F16 => {
246                let f: f64 = src.try_into()?;
247                Ok(Dynamic::F16(crate::f64_to_f16(f)))
248            }
249            Self::F32 => src.try_into().map(Dynamic::F32),
250            Self::F64 => src.try_into().map(Dynamic::F64),
251            Self::Str => Ok(Dynamic::from(src.to_string())),
252            _ => Ok(src),
253        }
254    }
255
256    pub fn width(&self) -> u32 {
257        //所占字节数
258        self.storage_width()
259    }
260
261    pub fn is_void(&self) -> bool {
262        if let Self::Void = self { true } else { false }
263    }
264
265    pub fn is_bool(&self) -> bool {
266        if let Self::Bool = self { true } else { false }
267    }
268
269    pub fn is_str(&self) -> bool {
270        if let Self::Str = self { true } else { false }
271    }
272
273    pub fn is_native(&self) -> bool {
274        match self {
275            Self::F16 | Self::F32 | Self::F64 | Self::U8 | Self::I8 | Self::U16 | Self::I16 | Self::U32 | Self::I32 | Self::U64 | Self::I64 => true,
276            _ => false,
277        }
278    }
279
280    pub fn is_any(&self) -> bool {
281        match self {
282            Self::Any => true,
283            Self::Fn { tys: _, ret } => ret.is_any(),
284            _ => false,
285        }
286    }
287
288    pub fn is_ident(&self) -> bool {
289        if let Self::Ident { name: _, params: _ } = self { true } else { false }
290    }
291
292    pub fn is_struct(&self) -> bool {
293        if let Self::Struct { .. } = self { true } else { false }
294    }
295
296    pub fn get_field(&self, name: &str) -> Result<(usize, &Type)> {
297        if let Self::Struct { params: _, fields } = self {
298            fields.iter().enumerate().find(|(_, (field_name, _))| field_name == name).map(|(index, (_, ty))| (index, ty)).ok_or(anyhow!("{:?} 未发现属性 {}", self, name))
299        } else {
300            Err(anyhow!("不是结构体"))
301        }
302    }
303
304    pub fn add_field(&mut self, name: SmolStr, ty: Type) -> Result<u32> {
305        if let Self::Struct { params: _, fields } = self {
306            fields.push((name, ty));
307            Ok(fields.len() as u32 - 1)
308        } else {
309            Err(anyhow!("不是结构体"))
310        }
311    }
312
313    pub fn is_vec(&self) -> bool {
314        if let Self::Vec(_, _) = self { true } else { false }
315    }
316
317    pub fn is_array(&self) -> bool {
318        if let Self::Array(_, _) = self { true } else { false }
319    }
320
321    pub fn is_int(&self) -> bool {
322        match self {
323            Self::I8 | Self::I16 | Self::I32 | Self::I64 => true,
324            _ => false,
325        }
326    }
327
328    pub fn is_uint(&self) -> bool {
329        match self {
330            Self::U8 | Self::U16 | Self::U32 | Self::U64 => true,
331            _ => false,
332        }
333    }
334
335    pub fn sign(self) -> Self {
336        match self {
337            Self::U8 => Self::I8,
338            Self::U16 => Self::I16,
339            Self::U32 => Self::I32,
340            Self::U64 => Self::I64,
341            _ => self,
342        }
343    }
344
345    pub fn is_float(&self) -> bool {
346        match self {
347            Self::F16 | Self::F32 | Self::F64 => true,
348            _ => false,
349        }
350    }
351
352    pub fn is_f64(&self) -> bool {
353        match self {
354            Self::F64 => true,
355            _ => false,
356        }
357    }
358
359    pub fn is_f32(&self) -> bool {
360        match self {
361            Self::F32 => true,
362            _ => false,
363        }
364    }
365
366    pub fn is_fn(&self) -> bool {
367        if let Self::Fn { .. } = self { true } else { false }
368    }
369
370    pub fn from_args(args: Vec<(SmolStr, Type)>) -> (Self, Vec<SmolStr>) {
371        let (args, tys) = args.into_iter().fold((Vec::new(), Vec::new()), |mut v, a| {
372            v.0.push(a.0);
373            v.1.push(a.1);
374            v
375        });
376        (Self::Fn { tys, ret: Rc::new(Type::Any) }, args)
377    }
378}
379
380impl Dynamic {
381    pub fn get_type(&self) -> Type {
382        let len = self.len() as u32;
383        match self {
384            Self::Bool(_) => Type::Bool,
385            Self::I8(_) => Type::I8,
386            Self::I16(_) => Type::I16,
387            Self::I32(_) => Type::I32,
388            Self::I64(_) => Type::I64,
389            Self::U8(_) => Type::U8,
390            Self::U16(_) => Type::U16,
391            Self::U32(_) => Type::U32,
392            Self::U64(_) => Type::U64,
393            Self::F16(_) => Type::F16,
394            Self::F32(_) => Type::F32,
395            Self::F64(_) => Type::F64,
396            Self::Bytes(_) => Type::Vec(Rc::new(Type::U8), len),
397            Self::VecI8(_) => Type::Vec(Rc::new(Type::I8), len),
398            Self::VecI16(_) => Type::Vec(Rc::new(Type::I16), len),
399            Self::VecI32(_) => Type::Vec(Rc::new(Type::I32), len),
400            Self::VecI64(_) => Type::Vec(Rc::new(Type::I64), len),
401            Self::VecU16(_) => Type::Vec(Rc::new(Type::U16), len),
402            Self::VecU32(_) => Type::Vec(Rc::new(Type::U32), len),
403            Self::VecU64(_) => Type::Vec(Rc::new(Type::U64), len),
404            Self::VecF32(_) => Type::Vec(Rc::new(Type::F32), len),
405            Self::VecF64(_) => Type::Vec(Rc::new(Type::F64), len),
406            Self::String(_) | Self::StringBuf(_) => Type::Str,
407            Self::Map(_) => Type::Map,
408            Self::Struct { ty, .. } => ty.clone(),
409            Self::Custom(_) => Type::Any,
410            Self::Null => Type::Void,
411            Self::List(items) => {
412                let tys: Vec<Type> = items.read().iter().map(|v| v.get_type()).collect();
413                if let Some(first) = tys.first() {
414                    if tys.iter().all(|x| x == first) {
415                        return Type::Array(Rc::new(first.clone()), len);
416                    }
417                }
418                Type::list_any()
419            }
420            Self::Iter { idx: _, keys: _, value: _ } => Type::Iter,
421        }
422    }
423}
424
425type DynamicReturnHandler = unsafe fn(*const Dynamic) -> Box<Dynamic>;
426
427static DYNAMIC_RETURN_HANDLER: RwLock<Option<DynamicReturnHandler>> = RwLock::new(None);
428
429pub fn set_dynamic_return_handler(handler: DynamicReturnHandler) {
430    *DYNAMIC_RETURN_HANDLER.write() = Some(handler);
431}
432
433unsafe fn take_dynamic_return(ptr: *const Dynamic) -> Box<Dynamic> {
434    if let Some(handler) = *DYNAMIC_RETURN_HANDLER.read() {
435        unsafe { handler(ptr) }
436    } else if ptr.is_null() {
437        Box::new(Dynamic::Null)
438    } else {
439        unsafe { Box::from_raw(ptr as *mut Dynamic) }
440    }
441}
442
443pub fn call_fn(ptr: i64, ret_ty: Type, param: Box<Dynamic>) -> Result<Box<Dynamic>> {
444    let param = Box::into_raw(param);
445    match ret_ty {
446        Type::Any => {
447            let fn_ptr: extern "C" fn(*const Dynamic) -> *mut Dynamic = unsafe { std::mem::transmute(ptr) };
448            let r = fn_ptr(param);
449            unsafe {
450                drop(Box::from_raw(param));
451            }
452            Ok(unsafe { take_dynamic_return(r) })
453        }
454        Type::Bool => {
455            let fn_ptr: extern "C" fn(*const Dynamic) -> i8 = unsafe { std::mem::transmute(ptr) };
456            let r = fn_ptr(param);
457            unsafe {
458                drop(Box::from_raw(param));
459            }
460            Ok(Box::new(Dynamic::Bool(r != 0)))
461        }
462        Type::Void => {
463            let fn_ptr: extern "C" fn(*const Dynamic) = unsafe { std::mem::transmute(ptr) };
464            fn_ptr(param);
465            unsafe {
466                drop(Box::from_raw(param));
467            }
468            Ok(Box::new(Dynamic::Null))
469        }
470        Type::F32 => {
471            let fn_ptr: extern "C" fn(*const Dynamic) -> f32 = unsafe { std::mem::transmute(ptr) };
472            let r = fn_ptr(param);
473            unsafe {
474                drop(Box::from_raw(param));
475            }
476            Ok(Box::new(Dynamic::F32(r)))
477        }
478        Type::F64 => {
479            let fn_ptr: extern "C" fn(*const Dynamic) -> f64 = unsafe { std::mem::transmute(ptr) };
480            let r = fn_ptr(param);
481            unsafe {
482                drop(Box::from_raw(param));
483            }
484            Ok(Box::new(Dynamic::F64(r)))
485        }
486        _ => {
487            let fn_ptr: extern "C" fn(*const Dynamic) -> i64 = unsafe { std::mem::transmute(ptr) };
488            let r = fn_ptr(param);
489            unsafe {
490                drop(Box::from_raw(param));
491            }
492            Ok(Box::new(Dynamic::I64(r)))
493        }
494    }
495}