Skip to main content

vm/
native.rs

1use super::FnVariant;
2use crate::JITRunTime;
3use anyhow::Result;
4use cranelift::prelude::AbiParam;
5use cranelift_module::{Linkage, Module};
6use dynamic::{Dynamic, Type};
7use parser::{BinaryOp, Expr, ExprKind, Span};
8use rand::RngExt;
9use std::sync::{Mutex, Weak};
10
11extern "C" fn any_clone(addr: *const Dynamic) -> *const Dynamic {
12    //在堆上分配内存 复制 addr 到内存中
13    unsafe {
14        let cloned_value = (*addr).deep_clone();
15        let ptr = Box::new(cloned_value);
16        Box::into_raw(ptr)
17    }
18}
19
20extern "C" fn any_null() -> *const Dynamic {
21    //在堆上分配内存 复制 addr 到内存中
22    let ptr = Box::new(Dynamic::Null);
23    Box::into_raw(ptr)
24}
25
26extern "C" fn print(addr: *const Dynamic) {
27    if !addr.is_null() {
28        unsafe {
29            println!("{}", (*addr).to_string());
30        }
31    }
32}
33
34extern "C" fn any_is_map(addr: *const Dynamic) -> bool {
35    !addr.is_null() && unsafe { (*addr).is_map() }
36}
37
38extern "C" fn any_is_list(addr: *const Dynamic) -> bool {
39    !addr.is_null() && unsafe { (*addr).is_list() }
40}
41
42extern "C" fn random(start: *const Dynamic, stop: *const Dynamic) -> *const Dynamic {
43    if !start.is_null() && !stop.is_null() {
44        let mut rng = rand::rng();
45        unsafe {
46            if (&*start).is_int() {
47                let start = (*start).as_int().unwrap_or(0);
48                let stop = (*stop).as_int().unwrap_or(100);
49                return Box::into_raw(Box::new(Dynamic::I64(rng.random_range(start..stop))));
50            } else if (&*start).is_f32() || (&*start).is_f64() {
51                let start = (*start).as_float().unwrap_or(0.0);
52                let stop = (*stop).as_float().unwrap_or(1.0);
53                return Box::into_raw(Box::new(Dynamic::F64(rng.random_range(start..stop))));
54            }
55        }
56    }
57    Box::into_raw(Box::new(Dynamic::Null))
58}
59
60extern "C" fn uuid() -> *const Dynamic {
61    Box::into_raw(Box::new(uuid::Uuid::new_v4().to_string().into()))
62}
63
64extern "C" fn struct_alloc(size: i64) -> *mut u8 {
65    let size = size.max(0) as usize;
66    let mut buf = vec![0u8; size].into_boxed_slice();
67    let ptr = buf.as_mut_ptr();
68    std::mem::forget(buf);
69    ptr
70}
71
72extern "C" fn struct_from_ptr(addr: i64, ty: i64) -> *const Dynamic {
73    let ty = unsafe { (&*(ty as *const Type)).clone() };
74    Box::into_raw(Box::new(Dynamic::Struct { addr: addr as usize, ty }))
75}
76
77pub(crate) extern "C" fn import_with_vm(context: *const Weak<Mutex<JITRunTime>>, addr: *const Dynamic, path: *const Dynamic) -> bool {
78    if addr.is_null() || path.is_null() {
79        return false;
80    }
81    super::with_vm_context(context, |vm| vm.import(unsafe { &*addr }.as_str(), unsafe { &*path }.as_str())).map_err(|e| println!("import {:?}", e)).is_ok()
82}
83
84extern "C" fn any_len(addr: *const Dynamic) -> i64 {
85    if addr.is_null() { 0 } else { unsafe { (&*addr).len() as i64 } }
86}
87
88extern "C" fn any_iter(addr: *const Dynamic) -> *const Dynamic {
89    if addr.is_null() {
90        &Dynamic::Null
91    } else {
92        let v = unsafe { Box::new((*addr).clone().into_iter()) };
93        Box::into_raw(v)
94    }
95}
96
97extern "C" fn any_next(addr: *mut Dynamic) -> *const Dynamic {
98    let v = unsafe { Box::new((*addr).next().unwrap_or(Dynamic::Null)) };
99    Box::into_raw(v)
100}
101
102extern "C" fn any_push(addr: *mut Dynamic, value: *mut Dynamic) {
103    if !addr.is_null() && !value.is_null() {
104        unsafe {
105            let value_box = Box::from_raw(value as *mut Dynamic);
106            (&mut *addr).push(*value_box);
107        }
108    }
109}
110
111extern "C" fn any_pop(addr: *mut Dynamic) -> *const Dynamic {
112    if addr.is_null() {
113        &Dynamic::Null
114    } else {
115        let v = unsafe { Box::new((*addr).pop().unwrap_or(Dynamic::Null)) };
116        Box::into_raw(v)
117    }
118}
119
120extern "C" fn get_key(addr: *const Dynamic, key: *const Dynamic) -> *const Dynamic {
121    if addr.is_null() || key.is_null() {
122        &Dynamic::Null
123    } else {
124        let key: &str = unsafe { &*key }.as_str();
125        let v = unsafe { Box::new((*addr).get_dynamic(key).unwrap_or(Dynamic::Null)) };
126        Box::into_raw(v)
127    }
128}
129
130extern "C" fn contains(addr: *const Dynamic, key: *const Dynamic) -> bool {
131    if addr.is_null() || key.is_null() {
132        false
133    } else {
134        let key: &str = unsafe { &*key }.as_str();
135        unsafe { (*addr).contains(key) }
136    }
137}
138
139extern "C" fn starts_with(addr: *const Dynamic, prefix: *const Dynamic) -> bool {
140    if addr.is_null() || prefix.is_null() {
141        false
142    } else {
143        let prefix: &str = unsafe { &*prefix }.as_str();
144        unsafe { (*addr).starts_with(prefix) }
145    }
146}
147
148extern "C" fn get_idx(addr: *const Dynamic, idx: i64) -> *const Dynamic {
149    if addr.is_null() {
150        &Dynamic::Null
151    } else {
152        let v = unsafe { Box::new((*addr).get_idx(idx as usize).unwrap_or(Dynamic::Null)) };
153        Box::into_raw(v)
154    }
155}
156
157extern "C" fn slice(addr: *const Dynamic, start: i64, stop: *const Dynamic, inclusive: bool) -> *const Dynamic {
158    if addr.is_null() {
159        return &Dynamic::Null;
160    }
161
162    let value = unsafe { &*addr };
163    let len = value.len() as i64;
164    let start = start.clamp(0, len) as usize;
165    let mut stop = if stop.is_null() {
166        len
167    } else {
168        let raw = unsafe { &*stop };
169        if raw.is_null() { len } else { raw.as_int().unwrap_or(len) }
170    };
171    if inclusive && stop < len {
172        stop += 1;
173    }
174    let stop = stop.clamp(start as i64, len) as usize;
175
176    let sliced = match value {
177        Dynamic::String(text) => Dynamic::from(text.chars().skip(start).take(stop.saturating_sub(start)).collect::<String>()),
178        Dynamic::List(list) => Dynamic::list(list.read().unwrap()[start..stop].to_vec()),
179        _ => Dynamic::Null,
180    };
181    Box::into_raw(Box::new(sliced))
182}
183
184extern "C" fn set_key(addr: *mut Dynamic, key: *const Dynamic, value: *const Dynamic) {
185    if addr.is_null() || key.is_null() {
186        return;
187    }
188    let key: &str = unsafe { &*key }.as_str();
189    unsafe { (&mut *addr).set_dynamic(key.into(), (&*value).clone()) }
190}
191
192extern "C" fn set_idx(addr: *mut Dynamic, idx: i64, value: *const Dynamic) {
193    if addr.is_null() {
194        return;
195    }
196    unsafe { (&mut *addr).set_idx(idx as usize, (&*value).clone()) }
197}
198
199extern "C" fn any_from_i64(v: i64) -> *const Dynamic {
200    let value = Box::new(Dynamic::I64(v));
201    Box::into_raw(value)
202}
203
204extern "C" fn any_from_bool(v: bool) -> *const Dynamic {
205    let value = Box::new(Dynamic::Bool(v));
206    Box::into_raw(value)
207}
208
209extern "C" fn any_to_i64(addr: *const Dynamic) -> i64 {
210    if addr.is_null() {
211        return 0;
212    }
213    unsafe { (&*addr).as_int().unwrap_or(0) }
214}
215
216extern "C" fn any_to_bool(addr: *const Dynamic) -> bool {
217    if addr.is_null() {
218        return false;
219    }
220    unsafe {
221        let value = &*addr;
222        if let Some(v) = value.as_bool() {
223            v
224        } else if let Some(v) = value.as_int() {
225            v != 0
226        } else if let Some(v) = value.as_float() {
227            v != 0.0
228        } else {
229            !value.is_null()
230        }
231    }
232}
233
234extern "C" fn any_from_f64(v: f64) -> *const Dynamic {
235    let value = Box::new(Dynamic::F64(v));
236    Box::into_raw(value)
237}
238
239extern "C" fn any_split(addr: *mut Dynamic, s: *const Dynamic) -> *const Dynamic {
240    if addr.is_null() || s.is_null() {
241        return &Dynamic::Null;
242    }
243    let s: &str = unsafe { &*s }.as_str();
244    Box::into_raw(Box::new(unsafe { (&*addr).clone() }.split(s)))
245}
246
247extern "C" fn any_to_f64(addr: *const Dynamic) -> f64 {
248    if addr.is_null() {
249        return 0.0;
250    }
251    unsafe { (&*addr).as_float().unwrap_or(0.0) }
252}
253
254extern "C" fn any_to_string(addr: *const Dynamic) -> *const Dynamic {
255    if addr.is_null() {
256        return Box::into_raw(Box::new(Dynamic::from("")));
257    }
258    Box::into_raw(Box::new(Dynamic::from(unsafe { &*addr }.to_string())))
259}
260
261extern "C" fn any_binary(left: *const Dynamic, op: i32, right: *const Dynamic) -> *const Dynamic {
262    if left.is_null() {
263        return right;
264    }
265    if right.is_null() {
266        return left;
267    }
268    let op = BinaryOp::try_from(op).unwrap();
269    unsafe {
270        let expr = Expr::new(
271            ExprKind::Binary { left: Box::new(Expr::new(ExprKind::Value((&*left).clone()), Span::default())), op, right: Box::new(Expr::new(ExprKind::Value((&*right).clone()), Span::default())) },
272            Span::default(),
273        );
274        let r = Box::new(expr.compact().unwrap_or(Dynamic::Null));
275        Box::into_raw(r)
276    }
277}
278
279extern "C" fn any_logic(left: *const Dynamic, op: i32, right: *const Dynamic) -> i32 {
280    let op = BinaryOp::try_from(op).unwrap();
281    unsafe {
282        let expr = Expr::new(
283            ExprKind::Binary { left: Box::new(Expr::new(ExprKind::Value((&*left).clone()), Span::default())), op, right: Box::new(Expr::new(ExprKind::Value((&*right).clone()), Span::default())) },
284            Span::default(),
285        );
286        if expr.compact().and_then(|r| r.as_bool()).unwrap_or(false) { 1 } else { 0 }
287    }
288}
289
290pub const STD: [(&str, &[Type], Type, *const u8); 5] = [
291    ("print", &[Type::Any], Type::Void, print as *const u8),
292    ("uuid", &[], Type::Any, uuid as *const u8),
293    ("rand", &[Type::Any, Type::Any], Type::Any, random as *const u8),
294    ("__struct_alloc", &[Type::I64], Type::Any, struct_alloc as *const u8),
295    ("__struct_from_ptr", &[Type::I64, Type::I64], Type::Any, struct_from_ptr as *const u8),
296];
297
298pub const ANY: [(&str, &[Type], Type, *const u8); 26] = [
299    ("Any::null", &[], Type::Any, any_null as *const u8),
300    ("Any::is_map", &[Type::Any], Type::Bool, any_is_map as *const u8),
301    ("Any::is_list", &[Type::Any], Type::Bool, any_is_list as *const u8),
302    ("Any::clone", &[Type::Any], Type::Any, any_clone as *const u8),
303    ("Any::len", &[Type::Any], Type::I32, any_len as *const u8),
304    ("Any::split", &[Type::Any, Type::Any], Type::Any, any_split as *const u8),
305    ("Any::push", &[Type::Any, Type::Any], Type::Void, any_push as *const u8),
306    ("Any::pop", &[Type::Any], Type::Any, any_pop as *const u8),
307    ("Any::get_idx", &[Type::Any, Type::I64], Type::Any, get_idx as *const u8),
308    ("Any::slice", &[Type::Any, Type::I64, Type::Any, Type::Bool], Type::Any, slice as *const u8),
309    ("Any::contains", &[Type::Any, Type::Any], Type::Bool, contains as *const u8),
310    ("Any::starts_with", &[Type::Any, Type::Any], Type::Bool, starts_with as *const u8),
311    ("Any::get_key", &[Type::Any, Type::Any], Type::Any, get_key as *const u8),
312    ("Any::set_idx", &[Type::Any, Type::I64, Type::Any], Type::Void, set_idx as *const u8),
313    ("Any::set_key", &[Type::Any, Type::Any, Type::Any], Type::Void, set_key as *const u8),
314    ("Any::from_i64", &[Type::I64], Type::Any, any_from_i64 as *const u8),
315    ("Any::from_bool", &[Type::Bool], Type::Any, any_from_bool as *const u8),
316    ("Any::to_i64", &[Type::Any], Type::I64, any_to_i64 as *const u8),
317    ("Any::to_bool", &[Type::Any], Type::Bool, any_to_bool as *const u8),
318    ("Any::from_f64", &[Type::F64], Type::Any, any_from_f64 as *const u8),
319    ("Any::to_f64", &[Type::Any], Type::F64, any_to_f64 as *const u8),
320    ("Any::to_string", &[Type::Any], Type::Str, any_to_string as *const u8),
321    ("Any::binary", &[Type::Any, Type::I32, Type::Any], Type::Any, any_binary as *const u8),
322    ("Any::logic", &[Type::Any, Type::I32, Type::Any], Type::Bool, any_logic as *const u8),
323    ("Any::iter", &[Type::Any], Type::Any, any_iter as *const u8),
324    ("Any::next", &[Type::Any], Type::Any, any_next as *const u8),
325];
326
327use std::rc::Rc;
328impl JITRunTime {
329    pub fn add_native_ptr(&mut self, full_name: &str, name: &str, arg_tys: &[Type], ret_ty: Type, fn_ptr: *const u8) -> Result<u32> {
330        self.native_symbols.write().unwrap().insert(full_name.to_string(), fn_ptr as usize);
331        self.add_native(full_name, name, arg_tys, ret_ty)
332    }
333
334    pub(crate) fn add_context_native_ptr(&mut self, full_name: &str, name: &str, arg_tys: &[Type], ret_ty: Type, fn_ptr: *const u8) -> Result<u32> {
335        self.native_symbols.write().unwrap().insert(full_name.to_string(), fn_ptr as usize);
336        self.add_context_native(full_name, name, arg_tys, ret_ty)
337    }
338
339    pub fn add_native(&mut self, full_name: &str, name: &str, arg_tys: &[Type], ret_ty: Type) -> Result<u32> {
340        let fn_ty = Type::Fn { tys: arg_tys.to_vec(), ret: Rc::new(ret_ty.clone()) };
341        let id = self.compiler.add_symbol(name, compiler::Symbol::Native(fn_ty.clone()));
342        let sig = self.get_sig(arg_tys, ret_ty)?;
343        let fn_id = self.module.declare_function(full_name, Linkage::Import, &sig)?;
344        self.fns.insert(id, FnVariant::Native { ty: fn_ty, fn_id, context: None });
345        Ok(id)
346    }
347
348    pub(crate) fn add_context_native(&mut self, full_name: &str, name: &str, arg_tys: &[Type], ret_ty: Type) -> Result<u32> {
349        let fn_ty = Type::Fn { tys: arg_tys.to_vec(), ret: Rc::new(ret_ty.clone()) };
350        let id = self.compiler.add_symbol(name, compiler::Symbol::Native(fn_ty.clone()));
351        let mut sig = self.module.make_signature();
352        sig.params.push(AbiParam::new(crate::ptr_type()));
353        for arg in arg_tys.iter() {
354            sig.params.push(AbiParam::new(crate::get_type(arg)?));
355        }
356        if !ret_ty.is_void() {
357            sig.returns.push(AbiParam::new(crate::get_type(&ret_ty)?));
358        }
359        let fn_id = self.module.declare_function(full_name, Linkage::Import, &sig)?;
360        self.fns.insert(id, FnVariant::Native { ty: fn_ty, fn_id, context: Some(self.owner_context_ptr()) });
361        Ok(id)
362    }
363}