Skip to main content

dynamic/
types.rs

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