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, Void, 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), Array(Rc<Type>, u32), ArrayParam(Rc<Type>, Rc<Type>),
56 Fn {
57 tys: Vec<Type>,
58 ret: Rc<Type>,
59 }, Symbol {
61 id: u32,
62 params: Vec<Type>,
63 }, }
65
66unsafe impl Send for Type {}
67unsafe impl Sync for Type {}
68
69impl 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()) {
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 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}