1extern crate self as go_engine;
6use crate::ffi::*;
7use go_vm::types::*;
8use std::any::Any;
9use std::cell::RefCell;
10use std::mem;
11use std::rc::Rc;
12
13macro_rules! err_wrong_type {
14 () => {
15 Err("reflect: wrong type".to_owned().into())
16 };
17}
18
19macro_rules! err_index_oor {
20 () => {
21 Err("reflect: index out of range".to_owned().into())
22 };
23}
24
25macro_rules! err_set_val_type {
26 () => {
27 Err(RuntimeError::new(
28 "reflect: set value with wrong type".to_owned(),
29 ))
30 };
31}
32
33#[inline]
34fn wrap_std_val(v: GosValue, m: Option<Meta>) -> GosValue {
35 FfiCtx::new_unsafe_ptr(Rc::new(StdValue::new(v, m)))
36}
37
38#[inline]
39fn wrap_ptr_std_val(p: Box<PointerObj>, m: Option<Meta>) -> GosValue {
40 FfiCtx::new_unsafe_ptr(Rc::new(StdValue::Pointer(p, m, None)))
41}
42
43#[inline]
44fn val_to_std_val(val: &GosValue) -> RuntimeResult<&StdValue> {
45 val.as_non_nil_unsafe_ptr()?.downcast_ref::<StdValue>()
46}
47
48#[inline]
49fn val_to_map_iter(val: &GosValue) -> RuntimeResult<&StdMapIter> {
50 val.as_non_nil_unsafe_ptr()?.downcast_ref::<StdMapIter>()
51}
52
53#[inline]
54fn meta_objs(p: *const MetadataObjs) -> &'static MetadataObjs {
55 unsafe { &*p }
56}
57
58enum GosKind {
59 Invalid = 0,
60 Bool,
61 Int,
62 Int8,
63 Int16,
64 Int32,
65 Int64,
66 Uint,
67 Uint8,
68 Uint16,
69 Uint32,
70 Uint64,
71 UintPtr,
72 Float32,
73 Float64,
74 Complex64,
75 Complex128,
76 Array,
77 Chan,
78 Func,
79 Interface,
80 Map,
81 Ptr,
82 Slice,
83 String,
84 Struct,
85 UnsafePtr,
86}
87
88#[derive(Ffi)]
89pub struct ReflectFfi;
90
91#[ffi_impl]
92impl ReflectFfi {
93 fn ffi_value_of(iface: GosValue) -> RuntimeResult<GosValue> {
94 StdValue::value_from_iface(&iface)
95 }
96
97 fn ffi_type_of(ctx: &FfiCtx, p: GosValue) -> RuntimeResult<(GosValue, usize)> {
98 let v = val_to_std_val(&p)?;
99 Ok(StdType::type_of(v, ctx))
100 }
101
102 fn ffi_bool_val(ctx: &FfiCtx, p: GosValue) -> RuntimeResult<bool> {
103 val_to_std_val(&p)?.bool_val(ctx)
104 }
105
106 fn ffi_int_val(ctx: &FfiCtx, p: GosValue) -> RuntimeResult<i64> {
107 val_to_std_val(&p)?.int_val(ctx)
108 }
109
110 fn ffi_uint_val(ctx: &FfiCtx, p: GosValue) -> RuntimeResult<u64> {
111 val_to_std_val(&p)?.uint_val(ctx)
112 }
113
114 fn ffi_float_val(ctx: &FfiCtx, p: GosValue) -> RuntimeResult<f64> {
115 val_to_std_val(&p)?.float_val(ctx)
116 }
117
118 fn ffi_bytes_val(ctx: &FfiCtx, p: GosValue) -> RuntimeResult<GosValue> {
119 val_to_std_val(&p)?.bytes_val(ctx)
120 }
121
122 fn ffi_elem(ctx: &FfiCtx, p: GosValue) -> RuntimeResult<GosValue> {
123 val_to_std_val(&p)?.elem(ctx)
124 }
125
126 fn ffi_num_field(ctx: &FfiCtx, p: GosValue) -> RuntimeResult<GosValue> {
127 val_to_std_val(&p)?.num_field(ctx)
128 }
129
130 fn ffi_field(ctx: &FfiCtx, p: GosValue, i: isize) -> RuntimeResult<GosValue> {
131 val_to_std_val(&p)?.field(ctx, i)
132 }
133
134 fn ffi_index(ctx: &FfiCtx, p: GosValue, i: isize) -> RuntimeResult<GosValue> {
135 val_to_std_val(&p)?.index(ctx, i)
136 }
137
138 fn ffi_is_nil(ctx: &FfiCtx, p: GosValue) -> RuntimeResult<bool> {
139 Ok(val_to_std_val(&p)?.val(ctx)?.is_nil())
140 }
141
142 fn ffi_len(ctx: &FfiCtx, p: GosValue) -> RuntimeResult<isize> {
143 val_to_std_val(&p)?.len(ctx)
144 }
145
146 fn ffi_map_range_init(ctx: &FfiCtx, p: GosValue) -> RuntimeResult<GosValue> {
147 StdMapIter::map_range(ctx, val_to_std_val(&p)?)
148 }
149
150 fn ffi_map_range_next(p: GosValue) -> RuntimeResult<GosValue> {
151 Ok(val_to_map_iter(&p)?.next())
152 }
153
154 fn ffi_map_range_key(p: GosValue) -> RuntimeResult<GosValue> {
155 val_to_map_iter(&p)?.key()
156 }
157
158 fn ffi_map_range_value(p: GosValue) -> RuntimeResult<GosValue> {
159 val_to_map_iter(&p)?.value()
160 }
161
162 fn ffi_can_addr(p: GosValue) -> RuntimeResult<bool> {
163 Ok(val_to_std_val(&p)?.can_addr())
164 }
165
166 fn ffi_can_set(p: GosValue) -> RuntimeResult<bool> {
167 Ok(val_to_std_val(&p)?.can_set())
168 }
169
170 fn ffi_set(ctx: &mut FfiCtx, p: GosValue, val: GosValue) -> RuntimeResult<()> {
171 val_to_std_val(&p)?.set(ctx, val_to_std_val(&val)?.val(ctx)?)
172 }
173
174 fn ffi_set_bool(ctx: &mut FfiCtx, p: GosValue, val: bool) -> RuntimeResult<()> {
175 val_to_std_val(&p)?.set_bool(ctx, val)
176 }
177
178 fn ffi_set_string(ctx: &mut FfiCtx, p: GosValue, val: GosValue) -> RuntimeResult<()> {
179 val_to_std_val(&p)?.set_string(ctx, val)
180 }
181
182 fn ffi_set_int(ctx: &mut FfiCtx, p: GosValue, val: i64) -> RuntimeResult<()> {
183 val_to_std_val(&p)?.set_int(ctx, val)
184 }
185
186 fn ffi_set_uint(ctx: &mut FfiCtx, p: GosValue, val: u64) -> RuntimeResult<()> {
187 val_to_std_val(&p)?.set_uint(ctx, val)
188 }
189
190 fn ffi_set_float(ctx: &mut FfiCtx, p: GosValue, val: f64) -> RuntimeResult<()> {
191 val_to_std_val(&p)?.set_float(ctx, val)
192 }
193
194 fn ffi_set_complex(ctx: &mut FfiCtx, p: GosValue, val: GosValue) -> RuntimeResult<()> {
195 val_to_std_val(&p)?.set_complex(ctx, val)
196 }
197
198 fn ffi_set_bytes(ctx: &mut FfiCtx, p: GosValue, val: GosValue) -> RuntimeResult<()> {
199 val_to_std_val(&p)?.set_bytes(ctx, val)
200 }
201
202 fn ffi_set_pointer(ctx: &mut FfiCtx, p: GosValue, val: GosValue) -> RuntimeResult<()> {
203 val_to_std_val(&p)?.set_pointer(ctx, val)
204 }
205
206 fn ffi_swap(iface: GosValue, i: isize, j: isize) -> RuntimeResult<()> {
207 let iface = iface.as_interface().unwrap();
208 match iface.underlying_value() {
209 Some(obj) => {
210 if obj.typ() == ValueType::Slice {
211 obj.slice_swap(i as usize, j as usize)
212 } else {
213 Err("reflect swap: not a slice".to_owned().into())
214 }
215 }
216 None => Err("reflect swap: nil value".to_owned().into()),
217 }
218 }
219}
220
221#[derive(Clone, Debug, UnsafePtr)]
222enum StdValue {
223 Value(GosValue, Option<Meta>),
224 Pointer(Box<PointerObj>, Option<Meta>, Option<bool>),
225}
226
227impl StdValue {
228 fn new(v: GosValue, meta: Option<Meta>) -> StdValue {
229 StdValue::Value(v, meta)
230 }
231
232 fn value_from_iface(v: &GosValue) -> RuntimeResult<GosValue> {
233 if v.typ() != ValueType::Interface {
234 return Err("reflect: not an interface".to_owned().into());
235 }
236 let iface = v.as_interface().unwrap();
237 match &iface as &InterfaceObj {
238 InterfaceObj::Gos(v, m) => Ok(wrap_std_val(v.clone(), m.as_ref().map(|x| x.0))),
239 InterfaceObj::Ffi(_) => Err("reflect: ffi objects are not supported".to_owned().into()),
241 }
242 }
243
244 fn val(&self, ctx: &FfiCtx) -> RuntimeResult<GosValue> {
245 match self {
246 Self::Value(v, _) => Ok(v.clone()),
247 Self::Pointer(p, _, _) => p.deref(&ctx.stack, &ctx.vm_objs.packages),
248 }
249 }
250
251 fn meta(&self) -> &Option<Meta> {
252 match self {
253 Self::Value(_, m) | Self::Pointer(_, m, _) => m,
254 }
255 }
256
257 fn settable_meta(&self) -> RuntimeResult<&Meta> {
258 match self {
259 Self::Pointer(_, m, _) => m
260 .as_ref()
261 .ok_or("reflect: type info missing".to_owned().into()),
262 Self::Value(_, _) => Err("reflect: value not settable".to_owned().into()),
263 }
264 }
265
266 fn bool_val(&self, ctx: &FfiCtx) -> RuntimeResult<bool> {
267 let val = self.val(ctx)?;
268 match val.typ() {
269 ValueType::Bool => Ok(val.as_()),
270 _ => err_wrong_type!(),
271 }
272 }
273
274 fn int_val(&self, ctx: &FfiCtx) -> RuntimeResult<i64> {
275 let val = self.val(ctx)?;
276 match val.typ() {
277 ValueType::Int => Ok(*val.as_int() as i64),
278 ValueType::Int8 => Ok(*val.as_int8() as i64),
279 ValueType::Int16 => Ok(*val.as_int16() as i64),
280 ValueType::Int32 => Ok(*val.as_int32() as i64),
281 ValueType::Int64 => Ok(*val.as_int64()),
282 _ => err_wrong_type!(),
283 }
284 }
285
286 fn uint_val(&self, ctx: &FfiCtx) -> RuntimeResult<u64> {
287 let val = self.val(ctx)?;
288 match val.typ() {
289 ValueType::Uint => Ok(*val.as_uint() as u64),
290 ValueType::Uint8 => Ok(*val.as_uint8() as u64),
291 ValueType::Uint16 => Ok(*val.as_uint16() as u64),
292 ValueType::Uint32 => Ok(*val.as_uint32() as u64),
293 ValueType::Uint64 => Ok(*val.as_uint64()),
294 _ => err_wrong_type!(),
295 }
296 }
297
298 fn float_val(&self, ctx: &FfiCtx) -> RuntimeResult<f64> {
299 let val = self.val(ctx)?;
300 match val.typ() {
301 ValueType::Float32 => Ok((Into::<f32>::into(*val.as_float32()) as f64).into()),
302 ValueType::Float64 => Ok(*val.as_float64()),
303 _ => err_wrong_type!(),
304 }
305 .map(|x| x.into_inner())
306 }
307
308 fn bytes_val(&self, ctx: &FfiCtx) -> RuntimeResult<GosValue> {
309 let val = self.val(ctx)?;
310 if val.typ() != ValueType::Slice || val.t_elem() != ValueType::Uint8 {
311 return err_wrong_type!();
312 }
313 Ok(val)
314 }
315
316 fn elem(&self, ctx: &FfiCtx) -> RuntimeResult<GosValue> {
317 let val = self.val(ctx)?;
318 match val.typ() {
319 ValueType::Interface => StdValue::value_from_iface(&val),
320 ValueType::Pointer => {
321 let p = val.as_non_nil_pointer()?;
322 let meta = self.meta().map(|x| x.unptr_to());
323 Ok(wrap_ptr_std_val(Box::new(p.clone()), meta))
324 }
325 _ => err_wrong_type!(),
326 }
327 }
328
329 fn num_field(&self, ctx: &FfiCtx) -> RuntimeResult<GosValue> {
330 let val = self.val(ctx)?;
331 if val.typ() != ValueType::Struct {
332 err_wrong_type!()
333 } else {
334 Ok((val.as_struct().0.borrow_fields().len() as isize).into())
335 }
336 }
337
338 fn field(&self, ctx: &FfiCtx, ival: isize) -> RuntimeResult<GosValue> {
339 let i = ival as usize;
340 let val = self.val(ctx)?;
341 match val.typ() {
342 ValueType::Struct => {
343 let fields = &val.as_struct().0.borrow_fields();
344 if fields.len() <= i {
345 err_index_oor!()
346 } else {
347 let p = Box::new(PointerObj::StructField(val.clone(), i as i32));
348 let metas = &ctx.vm_objs.metas;
349 let fields = &metas[self.meta().unwrap().underlying(metas).key]
350 .as_struct()
351 .infos();
352 Ok(FfiCtx::new_unsafe_ptr(Rc::new(StdValue::Pointer(
353 p,
354 Some(fields[i].meta),
355 Some(fields[i].exported()),
356 ))))
357 }
358 }
359 _ => err_wrong_type!(),
360 }
361 }
362
363 fn index(&self, ctx: &FfiCtx, ival: isize) -> RuntimeResult<GosValue> {
364 let i = ival as i32;
365 let iusize = i as usize;
366 let container = self.val(ctx)?;
367 let t = container.typ();
368 match t {
369 ValueType::Array | ValueType::Slice => {
370 let metas = &ctx.vm_objs.metas;
371 let elem_meta = match &metas[self.meta().unwrap().underlying(metas).key] {
372 MetadataType::Array(m, _) | MetadataType::Slice(m) => m,
373 _ => unreachable!(),
374 };
375 let p = Box::new(PointerObj::new_slice_member(
376 container,
377 i,
378 t,
379 elem_meta.value_type(metas),
380 )?);
381 Ok(wrap_ptr_std_val(p, Some(elem_meta.clone())))
382 }
383 ValueType::String => match container.as_string().len() > iusize {
385 true => Ok(wrap_std_val(
386 container.as_string().index_elem_u8(iusize).into(),
387 Some(ctx.vm_objs.prim_meta.mint8),
388 )),
389 false => err_index_oor!(),
390 },
391 _ => err_wrong_type!(),
392 }
393 }
394
395 fn len(&self, ctx: &FfiCtx) -> RuntimeResult<isize> {
396 let val = self.val(ctx)?;
397 Ok(val.len() as isize)
398 }
399
400 fn can_addr(&self) -> bool {
401 match self {
402 Self::Value(_, _) => false,
403 Self::Pointer(_, _, _) => true,
404 }
405 }
406
407 fn can_set(&self) -> bool {
408 match self {
409 Self::Value(_, _) => false,
410 Self::Pointer(p, _, exported) => match p as &PointerObj {
411 PointerObj::SliceMember(_, _) => true,
412 PointerObj::StructField(_, _) => exported.unwrap(),
413 PointerObj::UpVal(_) => true,
414 _ => false,
415 },
416 }
417 }
418
419 fn set(&self, ctx: &mut FfiCtx, val: GosValue) -> RuntimeResult<()> {
420 if !self.can_set() {
421 return Err("reflect: value is not settable".to_owned().into());
422 }
423 match self {
424 Self::Pointer(p, _, _) => {
425 p.set_pointee(&val, ctx.stack, &ctx.vm_objs.packages, &ctx.gcc)
426 }
427 _ => unreachable!(),
428 }
429 }
430
431 fn set_bool(&self, ctx: &mut FfiCtx, val: bool) -> RuntimeResult<()> {
432 match self.settable_meta()?.value_type(&ctx.vm_objs.metas) {
433 ValueType::Bool => self.set(ctx, val.into()),
434 _ => err_set_val_type!(),
435 }
436 }
437
438 fn set_string(&self, ctx: &mut FfiCtx, val: GosValue) -> RuntimeResult<()> {
439 match self.settable_meta()?.value_type(&ctx.vm_objs.metas) {
440 ValueType::String => self.set(ctx, val),
441 _ => err_set_val_type!(),
442 }
443 }
444
445 fn set_int(&self, ctx: &mut FfiCtx, ival: i64) -> RuntimeResult<()> {
446 let val = match self.settable_meta()?.value_type(&ctx.vm_objs.metas) {
447 ValueType::Int => Ok((ival as isize).into()),
448 ValueType::Int8 => Ok((ival as i8).into()),
449 ValueType::Int16 => Ok((ival as i16).into()),
450 ValueType::Int32 => Ok((ival as i32).into()),
451 ValueType::Int64 => Ok((ival as i64).into()),
452 _ => err_set_val_type!(),
453 }?;
454 self.set(ctx, val)
455 }
456
457 fn set_uint(&self, ctx: &mut FfiCtx, ival: u64) -> RuntimeResult<()> {
458 let val = match self.settable_meta()?.value_type(&ctx.vm_objs.metas) {
459 ValueType::Uint => Ok((ival as usize).into()),
460 ValueType::Uint8 => Ok((ival as u8).into()),
461 ValueType::Uint16 => Ok((ival as u16).into()),
462 ValueType::Uint32 => Ok((ival as u32).into()),
463 ValueType::Uint64 => Ok((ival as u64).into()),
464 _ => err_set_val_type!(),
465 }?;
466 self.set(ctx, val)
467 }
468
469 fn set_float(&self, ctx: &mut FfiCtx, fval: f64) -> RuntimeResult<()> {
470 let val = match self.settable_meta()?.value_type(&ctx.vm_objs.metas) {
471 ValueType::Float32 => Ok((fval as f32).into()),
472 ValueType::Float64 => Ok(fval.into()),
473 _ => err_set_val_type!(),
474 }?;
475 self.set(ctx, val)
476 }
477
478 fn set_complex(&self, ctx: &mut FfiCtx, val: GosValue) -> RuntimeResult<()> {
479 let c = val.as_complex128();
480 let val = match self.settable_meta()?.value_type(&ctx.vm_objs.metas) {
481 ValueType::Complex64 => Ok(FfiCtx::new_complex64(
482 c.r.into_inner() as f32,
483 c.i.into_inner() as f32,
484 )),
485 ValueType::Complex128 => Ok(FfiCtx::new_complex128(c.r.into_inner(), c.i.into_inner())),
486 _ => err_set_val_type!(),
487 }?;
488 self.set(ctx, val)
489 }
490
491 fn set_bytes(&self, ctx: &mut FfiCtx, val: GosValue) -> RuntimeResult<()> {
492 let metas = &ctx.vm_objs.metas;
493 let meta = self.settable_meta()?;
494 if meta.value_type(metas) != ValueType::Slice {
495 err_wrong_type!()
496 } else {
497 let elem_meta = metas[meta.key].as_slice();
498 if elem_meta.value_type(metas) != ValueType::Uint8 {
499 err_wrong_type!()
500 } else {
501 self.set(ctx, val)
502 }
503 }
504 }
505
506 fn set_pointer(&self, ctx: &mut FfiCtx, val: GosValue) -> RuntimeResult<()> {
507 if self.settable_meta()? != &ctx.vm_objs.prim_meta.unsafe_ptr {
508 err_wrong_type!()
509 } else {
510 self.set(ctx, val)
511 }
512 }
513}
514
515#[derive(Clone, Debug)]
516struct StdType {
517 meta: Meta,
518 mobjs: *const MetadataObjs,
519}
520
521impl UnsafePtr for StdType {
522 fn as_any(&self) -> &dyn Any {
523 self
524 }
525
526 fn eq(&self, other: &dyn UnsafePtr) -> bool {
527 match other.as_any().downcast_ref::<StdType>() {
528 Some(other_type) => {
529 let objs = meta_objs(self.mobjs);
530 self.meta.identical(&other_type.meta, objs)
531 }
532 None => false,
533 }
534 }
535}
536
537impl StdType {
538 fn new(m: Meta, objs: &MetadataObjs) -> StdType {
539 StdType {
540 meta: m,
541 mobjs: objs,
542 }
543 }
544
545 fn type_of(val: &StdValue, ctx: &FfiCtx) -> (GosValue, usize) {
546 let m = val.meta().unwrap().clone();
547 let typ = StdType::new(m, &ctx.vm_objs.metas);
548 let kind = match m
549 .underlying(&ctx.vm_objs.metas)
550 .value_type(&ctx.vm_objs.metas)
551 {
552 ValueType::Bool => GosKind::Bool,
553 ValueType::Int => GosKind::Int,
554 ValueType::Int8 => GosKind::Int8,
555 ValueType::Int16 => GosKind::Int16,
556 ValueType::Int32 => GosKind::Int32,
557 ValueType::Int64 => GosKind::Int64,
558 ValueType::Uint => GosKind::Uint,
559 ValueType::UintPtr => GosKind::UintPtr,
560 ValueType::Uint8 => GosKind::Uint8,
561 ValueType::Uint16 => GosKind::Uint16,
562 ValueType::Uint32 => GosKind::Uint32,
563 ValueType::Uint64 => GosKind::Uint64,
564 ValueType::Float32 => GosKind::Float32,
565 ValueType::Float64 => GosKind::Float64,
566 ValueType::Complex64 => GosKind::Complex64,
567 ValueType::Complex128 => GosKind::Complex128,
568 ValueType::Array => GosKind::Array,
569 ValueType::Channel => GosKind::Chan,
570 ValueType::Closure => GosKind::Func,
571 ValueType::Interface => GosKind::Interface,
572 ValueType::Map => GosKind::Map,
573 ValueType::Pointer => GosKind::Ptr,
574 ValueType::UnsafePtr => GosKind::UnsafePtr,
575 ValueType::Slice => GosKind::Slice,
576 ValueType::String => GosKind::String,
577 ValueType::Struct => GosKind::Struct,
578 _ => GosKind::Invalid,
579 };
580 (FfiCtx::new_unsafe_ptr(Rc::new(typ)), (kind as usize))
581 }
582}
583
584#[derive(Clone, Debug)]
585struct StdMapIterInner {
586 iter: GosMapIter<'static>,
587 item: Option<(GosValue, GosValue)>,
588}
589
590#[derive(Clone, Debug)]
591struct StdMapIter {
592 inner: RefCell<StdMapIterInner>,
593 key_meta: Meta,
594 }
596
597impl UnsafePtr for StdMapIter {
598 fn as_any(&self) -> &dyn Any {
599 self
600 }
601}
602
603impl StdMapIter {
604 fn map_range(ctx: &FfiCtx, v: &StdValue) -> RuntimeResult<GosValue> {
605 let val = v.val(ctx)?;
606 let mref = val.as_map().unwrap().0.borrow_data();
607 let iter: GosMapIter<'static> = unsafe { mem::transmute(mref.iter()) };
608 let metas = &ctx.vm_objs.metas;
609 let map_meta = metas[v.meta().unwrap().underlying(metas).key].as_map();
610 let (key_meta, _) = (map_meta.0.clone(), map_meta.1.clone());
611 let smi = StdMapIter {
612 inner: RefCell::new(StdMapIterInner { iter, item: None }),
613 key_meta,
614 };
615 Ok(FfiCtx::new_unsafe_ptr(Rc::new(smi)))
616 }
617
618 fn next(&self) -> GosValue {
619 let mut inner = self.inner.borrow_mut();
620 inner.item = inner.iter.next().map(|x| (x.0.clone(), x.1.clone()));
621 inner.item.is_some().into()
622 }
623
624 fn key(&self) -> RuntimeResult<GosValue> {
625 match &self.inner.borrow().item {
626 Some(kv) => Ok(kv.0.clone()),
627 None => Err("reflect.MapIter: Next not called or iter exhausted"
628 .to_owned()
629 .into()),
630 }
631 .map(|x| wrap_std_val(x, Some(self.key_meta)))
632 }
633
634 fn value(&self) -> RuntimeResult<GosValue> {
635 match &self.inner.borrow().item {
636 Some(kv) => Ok(kv.1.clone()),
637 None => Err("reflect.MapIter: Next not called or iter exhausted"
638 .to_owned()
639 .into()),
640 }
641 .map(|x| wrap_std_val(x, Some(self.key_meta)))
642 }
643}