1use crate::bytecode::*;
6use crate::dispatcher::ArrCaller;
7use crate::gc::GcContainer;
8use crate::stack::Stack;
9use crate::value::*;
10use crate::value::{GosValue, RuntimeResult};
11#[cfg(feature = "async")]
12use futures_lite::future::Future;
13use go_parser::Map;
14use std::cell::Ref;
15#[cfg(feature = "async")]
16use std::pin::Pin;
17use std::rc::Rc;
18
19pub struct FfiCtx<'a> {
20 pub func_name: &'a str,
21 pub vm_objs: &'a VMObjects,
22 pub user_data: Option<usize>,
23 pub stack: &'a mut Stack,
24 pub gcc: &'a GcContainer,
25 pub(crate) array_slice_caller: &'a ArrCaller,
26}
27
28impl<'a> FfiCtx<'a> {
29 #[inline]
30 pub fn new_nil(t: ValueType) -> GosValue {
31 GosValue::new_nil(t)
32 }
33
34 #[inline]
35 pub fn new_nil_slice(t_elem: ValueType) -> GosValue {
36 GosValue::new_nil_slice(t_elem)
37 }
38
39 #[inline]
40 pub fn new_uint_ptr(u: usize) -> GosValue {
41 GosValue::new_uint_ptr(u)
42 }
43
44 #[inline]
45 pub fn new_complex64(r: f32, i: f32) -> GosValue {
46 GosValue::new_complex64(r.into(), i.into())
47 }
48
49 #[inline]
50 pub fn new_function(f: FunctionKey) -> GosValue {
51 GosValue::new_function(f)
52 }
53
54 #[inline]
55 pub fn new_package(p: PackageKey) -> GosValue {
56 GosValue::new_package(p)
57 }
58
59 #[inline]
60 pub fn new_metadata(m: Meta) -> GosValue {
61 GosValue::new_metadata(m)
62 }
63
64 #[inline]
65 pub fn new_complex128(r: f64, i: f64) -> GosValue {
66 GosValue::new_complex128(r.into(), i.into())
67 }
68
69 #[inline]
70 pub fn new_string(s: &str) -> GosValue {
71 GosValue::with_str(s)
72 }
73
74 #[inline]
75 pub fn new_unsafe_ptr(p: Rc<dyn UnsafePtr>) -> GosValue {
76 GosValue::new_unsafe_ptr(p)
77 }
78
79 #[inline]
80 pub fn new_struct(&self, fields: Vec<GosValue>) -> GosValue {
81 GosValue::new_struct(StructObj::new(fields), self.gcc)
82 }
83
84 #[inline]
85 pub fn new_array(&self, member: Vec<GosValue>, t_elem: ValueType) -> GosValue {
86 GosValue::array_with_data(member, self.array_slice_caller.get(t_elem), self.gcc)
87 }
88
89 #[inline]
90 pub fn new_primitive_array<T>(&self, member: Vec<T>, t_elem: ValueType) -> GosValue
91 where
92 T: CellData,
93 {
94 let buf: Vec<CellElem<T>> = unsafe { std::mem::transmute(member) };
95 GosValue::new_non_gc_array(ArrayObj::with_raw_data(buf), t_elem)
96 }
97
98 #[inline]
99 pub fn new_map(&self, m: Map<GosValue, GosValue>) -> GosValue {
100 GosValue::map_with_data(m, self.gcc)
101 }
102
103 #[inline]
104 pub fn new_pointer(pointee: GosValue) -> GosValue {
105 let pobj = PointerObj::UpVal(UpValue::new_closed(pointee));
106 GosValue::new_pointer(pobj)
107 }
108
109 #[inline]
121 pub fn new_interface(&self, underlying: GosValue, metas: Option<(&Meta, Meta)>) -> GosValue {
122 GosValue::new_interface(InterfaceObj::with_value(
123 underlying,
124 metas.map(|(iface, value_meta)| {
125 let (m, b) = iface.bind_with_iface(value_meta, &self.vm_objs.metas);
126 (m, b.into_iter().map(|x| x.into()).collect())
127 }),
128 ))
129 }
130
131 #[inline]
132 pub fn new_empty_interface(&self, underlying: GosValue, meta: Meta) -> GosValue {
133 GosValue::new_interface(InterfaceObj::with_value(underlying, Some((meta, vec![]))))
134 }
135
136 #[inline]
137 pub fn deref_pointer(&self, ptr: &GosValue) -> RuntimeResult<GosValue> {
138 ptr.as_non_nil_pointer()?
139 .deref(&self.stack, &self.vm_objs.packages)
140 }
141
142 #[inline]
143 pub fn zero_val(&self, m: &Meta) -> GosValue {
144 m.zero(&self.vm_objs.metas, self.gcc)
145 }
146
147 #[inline]
148 pub fn slice_as_rust_slice<T>(val: &GosValue) -> RuntimeResult<Ref<[T]>>
149 where
150 T: Element,
151 {
152 Ok(val.as_non_nil_slice::<T>()?.0.as_rust_slice())
153 }
154
155 #[inline]
156 pub fn slice_as_primitive_slice<'b, C, D>(val: &'b GosValue) -> RuntimeResult<Ref<[D]>>
157 where
158 C: CellData + 'b,
159 D: Copy,
160 {
161 Ok(val.as_non_nil_slice::<CellElem<C>>()?.0.as_raw_slice::<D>())
162 }
163
164 #[inline]
165 pub fn array_as_rust_slice<T>(val: &GosValue) -> Ref<[T]>
166 where
167 T: Element,
168 {
169 val.as_array::<T>().0.as_rust_slice()
170 }
171
172 #[inline]
173 pub fn array_as_primitive_slice<'b, C, D>(val: &'b GosValue) -> Ref<[D]>
174 where
175 C: CellData + 'b,
176 D: Copy,
177 {
178 val.as_array::<CellElem<C>>().0.as_raw_slice::<D>()
179 }
180}
181
182pub trait Ffi {
184 fn call(&self, ctx: &mut FfiCtx, params: Vec<GosValue>) -> RuntimeResult<Vec<GosValue>>;
185
186 #[cfg(feature = "async")]
187 fn async_call(
188 &self,
189 ctx: &mut FfiCtx,
190 params: Vec<GosValue>,
191 ) -> Pin<Box<dyn Future<Output = RuntimeResult<Vec<GosValue>>> + '_>>;
192}
193
194impl std::fmt::Debug for dyn Ffi {
195 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
196 write!(f, "{}", "ffi")
197 }
198}
199
200pub struct FfiFactory {
201 registry: Map<&'static str, Rc<dyn Ffi>>,
202 user_data: Option<usize>,
205}
206
207impl FfiFactory {
208 pub fn new() -> FfiFactory {
209 FfiFactory {
210 registry: Map::new(),
211 user_data: None,
212 }
213 }
214
215 pub fn with_user_data(ptr: usize) -> FfiFactory {
216 FfiFactory {
217 registry: Map::new(),
218 user_data: Some(ptr),
219 }
220 }
221
222 pub fn register(&mut self, name: &'static str, proto: Rc<dyn Ffi>) {
223 assert!(self.registry.insert(name, proto).is_none());
224 }
225
226 pub(crate) fn user_data(&self) -> Option<usize> {
227 self.user_data
228 }
229
230 pub(crate) fn create(&self, name: &str) -> RuntimeResult<Rc<dyn Ffi>> {
231 match self.registry.get(name) {
232 Some(proto) => Ok(proto.clone()),
233 None => Err(format!("FFI named {} not found", name).into()),
234 }
235 }
236}
237
238impl std::fmt::Debug for FfiFactory {
239 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
240 write!(f, "FfiFactory")
241 }
242}
243
244pub struct CodeGenVMCtx {
246 vm_objs: VMObjects,
247 dummy_func_name: &'static str,
248 dummy_stack: Stack,
249 dummy_gcc: GcContainer,
250 caller: ArrCaller,
251}
252
253impl CodeGenVMCtx {
254 pub fn new(vm_objs: VMObjects) -> CodeGenVMCtx {
255 CodeGenVMCtx {
256 vm_objs,
257 dummy_func_name: "dummy_name",
258 dummy_stack: Stack::new(),
259 dummy_gcc: GcContainer::new(),
260 caller: ArrCaller::new(),
261 }
262 }
263
264 pub fn ffi_ctx(&mut self) -> FfiCtx {
265 FfiCtx {
266 func_name: self.dummy_func_name,
267 vm_objs: &self.vm_objs,
268 user_data: None,
269 stack: &mut self.dummy_stack,
270 gcc: &&self.dummy_gcc,
271 array_slice_caller: &self.caller,
272 }
273 }
274
275 pub fn objects(&self) -> &VMObjects {
276 &self.vm_objs
277 }
278
279 pub fn objects_mut(&mut self) -> &mut VMObjects {
280 &mut self.vm_objs
281 }
282
283 pub fn metas(&self) -> &MetadataObjs {
284 &self.vm_objs.metas
285 }
286
287 pub fn metas_mut(&mut self) -> &mut MetadataObjs {
288 &mut self.vm_objs.metas
289 }
290
291 pub fn functions(&self) -> &FunctionObjs {
292 &self.vm_objs.functions
293 }
294
295 pub fn functions_mut(&mut self) -> &mut FunctionObjs {
296 &mut self.vm_objs.functions
297 }
298
299 pub fn packages(&self) -> &PackageObjs {
300 &self.vm_objs.packages
301 }
302
303 pub fn packages_mut(&mut self) -> &mut PackageObjs {
304 &mut self.vm_objs.packages
305 }
306
307 pub fn prim_meta(&self) -> &PrimitiveMeta {
308 &self.vm_objs.prim_meta
309 }
310
311 pub fn gc_container(&self) -> &GcContainer {
312 &self.dummy_gcc
313 }
314
315 pub fn into_vmo(self) -> VMObjects {
316 self.vm_objs
317 }
318
319 pub fn function_with_meta(
320 &mut self,
321 package: Option<PackageKey>,
322 meta: Meta,
323 flag: FuncFlag,
324 ) -> GosValue {
325 let package = package.unwrap_or_else(|| PackageKey::null());
326 let val = FunctionObj::new(package, meta, &self.vm_objs.metas, &self.dummy_gcc, flag);
327 GosValue::new_function(self.vm_objs.functions.insert(val))
328 }
329
330 pub fn new_struct_meta(&mut self, fields: Fields) -> Meta {
331 Meta::new_struct(fields, &mut self.vm_objs)
332 }
333
334 #[inline]
335 pub fn new_closure_static(
336 func: FunctionKey,
337 up_ptrs: Option<&Vec<ValueDesc>>,
338 meta: Meta,
339 ) -> GosValue {
340 GosValue::new_closure_static(func, up_ptrs, meta)
341 }
342}