Skip to main content

vm/
native.rs

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