goscript_vm/
metadata.rs

1use super::gc::GcoVec;
2use super::instruction::{OpIndex, ValueType};
3use super::objects::{FunctionKey, MetadataKey, MetadataObjs, StructObj, VMObjects};
4use super::value::GosValue;
5use std::cell::RefCell;
6use std::collections::HashMap;
7use std::rc::Rc;
8
9#[macro_export]
10macro_rules! zero_val {
11    ($meta:ident, $objs:expr, $gcv:expr) => {
12        $meta.zero_val(&$objs.metas, $gcv)
13    };
14}
15
16#[derive(PartialEq, Eq, Clone, Debug)]
17pub enum ChannelType {
18    Send,
19    Recv,
20    SendRecv,
21}
22
23#[derive(Debug)]
24pub struct Metadata {
25    pub mbool: GosMetadata,
26    pub mint: GosMetadata,
27    pub mint8: GosMetadata,
28    pub mint16: GosMetadata,
29    pub mint32: GosMetadata,
30    pub mint64: GosMetadata,
31    pub muint: GosMetadata,
32    pub muint8: GosMetadata,
33    pub muint16: GosMetadata,
34    pub muint32: GosMetadata,
35    pub muint64: GosMetadata,
36    pub mfloat32: GosMetadata,
37    pub mfloat64: GosMetadata,
38    pub mcomplex64: GosMetadata,
39    pub mcomplex128: GosMetadata,
40    pub mstr: GosMetadata,
41    pub default_sig: GosMetadata,
42    pub empty_iface: GosMetadata,
43}
44
45impl Metadata {
46    pub fn new(objs: &mut MetadataObjs) -> Metadata {
47        Metadata {
48            mbool: GosMetadata::NonPtr(objs.insert(MetadataType::Bool), MetaCategory::Default),
49            mint: GosMetadata::NonPtr(objs.insert(MetadataType::Int), MetaCategory::Default),
50            mint8: GosMetadata::NonPtr(objs.insert(MetadataType::Int8), MetaCategory::Default),
51            mint16: GosMetadata::NonPtr(objs.insert(MetadataType::Int16), MetaCategory::Default),
52            mint32: GosMetadata::NonPtr(objs.insert(MetadataType::Int32), MetaCategory::Default),
53            mint64: GosMetadata::NonPtr(objs.insert(MetadataType::Int64), MetaCategory::Default),
54            muint: GosMetadata::NonPtr(objs.insert(MetadataType::Uint), MetaCategory::Default),
55            muint8: GosMetadata::NonPtr(objs.insert(MetadataType::Uint8), MetaCategory::Default),
56            muint16: GosMetadata::NonPtr(objs.insert(MetadataType::Uint16), MetaCategory::Default),
57            muint32: GosMetadata::NonPtr(objs.insert(MetadataType::Uint32), MetaCategory::Default),
58            muint64: GosMetadata::NonPtr(objs.insert(MetadataType::Uint64), MetaCategory::Default),
59            mfloat32: GosMetadata::NonPtr(
60                objs.insert(MetadataType::Float32),
61                MetaCategory::Default,
62            ),
63            mfloat64: GosMetadata::NonPtr(
64                objs.insert(MetadataType::Float64),
65                MetaCategory::Default,
66            ),
67            mcomplex64: GosMetadata::NonPtr(
68                objs.insert(MetadataType::Complex64),
69                MetaCategory::Default,
70            ),
71            mcomplex128: GosMetadata::NonPtr(
72                objs.insert(MetadataType::Complex128),
73                MetaCategory::Default,
74            ),
75            mstr: GosMetadata::NonPtr(
76                objs.insert(MetadataType::Str(GosValue::new_str("".to_string()))),
77                MetaCategory::Default,
78            ),
79            default_sig: GosMetadata::NonPtr(
80                objs.insert(MetadataType::Signature(SigMetadata::default())),
81                MetaCategory::Default,
82            ),
83            empty_iface: GosMetadata::NonPtr(
84                objs.insert(MetadataType::Interface(Fields::new(vec![], HashMap::new()))),
85                MetaCategory::Default,
86            ),
87        }
88    }
89}
90
91#[derive(Debug, Clone, Copy, PartialEq)]
92pub enum MetaCategory {
93    Default,
94    Array,
95    Type,
96    ArrayType,
97}
98
99#[derive(Debug, Clone, Copy, PartialEq)]
100pub enum GosMetadata {
101    Untyped,
102    NonPtr(MetadataKey, MetaCategory),
103    Ptr1(MetadataKey, MetaCategory),
104    Ptr2(MetadataKey, MetaCategory),
105    Ptr3(MetadataKey, MetaCategory),
106    Ptr4(MetadataKey, MetaCategory),
107    Ptr5(MetadataKey, MetaCategory),
108    Ptr6(MetadataKey, MetaCategory),
109    Ptr7(MetadataKey, MetaCategory),
110}
111
112impl GosMetadata {
113    #[inline]
114    pub fn new(v: MetadataType, metas: &mut MetadataObjs) -> GosMetadata {
115        GosMetadata::NonPtr(metas.insert(v), MetaCategory::Default)
116    }
117
118    #[inline]
119    pub fn new_array(elem_meta: GosMetadata, size: usize, metas: &mut MetadataObjs) -> GosMetadata {
120        let t = MetadataType::SliceOrArray(elem_meta, size);
121        GosMetadata::NonPtr(metas.insert(t), MetaCategory::Array)
122    }
123
124    #[inline]
125    pub fn new_slice(val_meta: GosMetadata, metas: &mut MetadataObjs) -> GosMetadata {
126        GosMetadata::new(MetadataType::SliceOrArray(val_meta, 0), metas)
127    }
128
129    #[inline]
130    pub fn new_map(
131        kmeta: GosMetadata,
132        vmeta: GosMetadata,
133        metas: &mut MetadataObjs,
134    ) -> GosMetadata {
135        GosMetadata::new(MetadataType::Map(kmeta, vmeta), metas)
136    }
137
138    #[inline]
139    pub fn new_interface(fields: Fields, metas: &mut MetadataObjs) -> GosMetadata {
140        GosMetadata::new(MetadataType::Interface(fields), metas)
141    }
142
143    #[inline]
144    pub fn new_channel(
145        typ: ChannelType,
146        val_meta: GosMetadata,
147        metas: &mut MetadataObjs,
148    ) -> GosMetadata {
149        GosMetadata::new(MetadataType::Channel(typ, val_meta), metas)
150    }
151
152    #[inline]
153    pub fn new_struct(f: Fields, objs: &mut VMObjects, gcv: &mut GcoVec) -> GosMetadata {
154        let field_zeros: Vec<GosValue> = f.fields.iter().map(|x| zero_val!(x, objs, gcv)).collect();
155        let struct_val = StructObj {
156            meta: GosMetadata::Untyped, // placeholder, will be set below
157            fields: field_zeros,
158        };
159        let gos_struct = GosValue::new_struct(struct_val, gcv);
160        let key = objs.metas.insert(MetadataType::Struct(f, gos_struct));
161        let gosm = GosMetadata::NonPtr(key, MetaCategory::Default);
162        match &mut objs.metas[key] {
163            MetadataType::Struct(_, v) => match v {
164                GosValue::Struct(s) => s.0.borrow_mut().meta = gosm,
165                _ => unreachable!(),
166            },
167            _ => unreachable!(),
168        }
169        gosm
170    }
171
172    pub fn new_sig(
173        recv: Option<GosMetadata>,
174        params: Vec<GosMetadata>,
175        results: Vec<GosMetadata>,
176        variadic: Option<(GosMetadata, GosMetadata)>,
177        metas: &mut MetadataObjs,
178    ) -> GosMetadata {
179        let ptypes = params.iter().map(|x| x.get_value_type(metas)).collect();
180        let t = MetadataType::Signature(SigMetadata {
181            recv: recv,
182            params: params,
183            results: results,
184            variadic: variadic,
185            params_type: ptypes,
186        });
187        GosMetadata::new(t, metas)
188    }
189
190    pub fn new_named(underlying: GosMetadata, metas: &mut MetadataObjs) -> GosMetadata {
191        debug_assert!(underlying.get_value_type(metas) != ValueType::Named);
192        GosMetadata::new(MetadataType::Named(Methods::new(), underlying), metas)
193    }
194
195    pub fn new_slice_from_array(array: GosMetadata) -> GosMetadata {
196        GosMetadata::NonPtr(array.as_non_ptr(), MetaCategory::Default)
197    }
198
199    #[inline]
200    pub fn ptr_to(&self) -> GosMetadata {
201        match self {
202            GosMetadata::Untyped => {
203                unreachable!() /* todo: panic */
204            }
205            GosMetadata::NonPtr(k, t) => GosMetadata::Ptr1(*k, *t),
206            GosMetadata::Ptr1(k, t) => GosMetadata::Ptr2(*k, *t),
207            GosMetadata::Ptr2(k, t) => GosMetadata::Ptr3(*k, *t),
208            GosMetadata::Ptr3(k, t) => GosMetadata::Ptr4(*k, *t),
209            GosMetadata::Ptr4(k, t) => GosMetadata::Ptr5(*k, *t),
210            GosMetadata::Ptr5(k, t) => GosMetadata::Ptr6(*k, *t),
211            GosMetadata::Ptr6(k, t) => GosMetadata::Ptr7(*k, *t),
212            GosMetadata::Ptr7(_, _) => {
213                unreachable!() /* todo: panic */
214            }
215        }
216    }
217
218    #[inline]
219    pub fn unptr_to(&self) -> GosMetadata {
220        match self {
221            GosMetadata::Untyped => {
222                unreachable!() /* todo: panic */
223            }
224            GosMetadata::NonPtr(_, _) => {
225                unreachable!() /* todo: panic */
226            }
227            GosMetadata::Ptr1(k, t) => GosMetadata::NonPtr(*k, *t),
228            GosMetadata::Ptr2(k, t) => GosMetadata::Ptr1(*k, *t),
229            GosMetadata::Ptr3(k, t) => GosMetadata::Ptr2(*k, *t),
230            GosMetadata::Ptr4(k, t) => GosMetadata::Ptr3(*k, *t),
231            GosMetadata::Ptr5(k, t) => GosMetadata::Ptr4(*k, *t),
232            GosMetadata::Ptr6(k, t) => GosMetadata::Ptr5(*k, *t),
233            GosMetadata::Ptr7(k, t) => GosMetadata::Ptr6(*k, *t),
234        }
235    }
236
237    // todo: change name
238    #[inline]
239    pub fn as_non_ptr(&self) -> MetadataKey {
240        match self {
241            GosMetadata::NonPtr(k, _) => *k,
242            _ => unreachable!(),
243        }
244    }
245
246    // todo: change name
247    #[inline]
248    pub fn unwrap_non_ptr(&self) -> (MetadataKey, MetaCategory) {
249        match self {
250            GosMetadata::NonPtr(k, mc) => (*k, *mc),
251            _ => unreachable!(),
252        }
253    }
254
255    #[inline]
256    pub fn into_type_category(self) -> GosMetadata {
257        let convert = |c| match c {
258            MetaCategory::Default => MetaCategory::Type,
259            MetaCategory::Array => MetaCategory::ArrayType,
260            _ => c,
261        };
262        match self {
263            GosMetadata::NonPtr(k, c) => GosMetadata::NonPtr(k, convert(c)),
264            GosMetadata::Ptr1(k, c) => GosMetadata::Ptr1(k, convert(c)),
265            GosMetadata::Ptr2(k, c) => GosMetadata::Ptr2(k, convert(c)),
266            GosMetadata::Ptr3(k, c) => GosMetadata::Ptr3(k, convert(c)),
267            GosMetadata::Ptr4(k, c) => GosMetadata::Ptr4(k, convert(c)),
268            GosMetadata::Ptr5(k, c) => GosMetadata::Ptr5(k, convert(c)),
269            GosMetadata::Ptr6(k, c) => GosMetadata::Ptr6(k, convert(c)),
270            GosMetadata::Ptr7(k, c) => GosMetadata::Ptr7(k, convert(c)),
271            GosMetadata::Untyped => {
272                unreachable!() /* todo: panic */
273            }
274        }
275    }
276
277    #[inline]
278    pub fn get_value_type(&self, metas: &MetadataObjs) -> ValueType {
279        match self {
280            GosMetadata::NonPtr(k, mc) => match mc {
281                MetaCategory::Default => match &metas[*k] {
282                    MetadataType::Bool => ValueType::Bool,
283                    MetadataType::Int => ValueType::Int,
284                    MetadataType::Int8 => ValueType::Int8,
285                    MetadataType::Int16 => ValueType::Int16,
286                    MetadataType::Int32 => ValueType::Int32,
287                    MetadataType::Int64 => ValueType::Int64,
288                    MetadataType::Uint => ValueType::Uint,
289                    MetadataType::Uint8 => ValueType::Uint8,
290                    MetadataType::Uint16 => ValueType::Uint16,
291                    MetadataType::Uint32 => ValueType::Uint32,
292                    MetadataType::Uint64 => ValueType::Uint64,
293                    MetadataType::Float32 => ValueType::Float32,
294                    MetadataType::Float64 => ValueType::Float64,
295                    MetadataType::Complex64 => ValueType::Complex64,
296                    MetadataType::Complex128 => ValueType::Complex128,
297                    MetadataType::Str(_) => ValueType::Str,
298                    MetadataType::Struct(_, _) => ValueType::Struct,
299                    MetadataType::Signature(_) => ValueType::Closure,
300                    MetadataType::SliceOrArray(_, _) => ValueType::Slice,
301                    MetadataType::Map(_, _) => ValueType::Map,
302                    MetadataType::Interface(_) => ValueType::Interface,
303                    MetadataType::Channel(_, _) => ValueType::Channel,
304                    MetadataType::Named(_, _) => ValueType::Named,
305                },
306                MetaCategory::Type | MetaCategory::ArrayType => ValueType::Metadata,
307                MetaCategory::Array => ValueType::Array,
308            },
309            GosMetadata::Untyped => {
310                unreachable!() /* todo: panic */
311            }
312            _ => ValueType::Pointer,
313        }
314    }
315
316    #[inline]
317    pub fn zero_val(&self, mobjs: &MetadataObjs, gcos: &GcoVec) -> GosValue {
318        self.zero_val_impl(mobjs, gcos)
319    }
320
321    #[inline]
322    fn zero_val_impl(&self, mobjs: &MetadataObjs, gcos: &GcoVec) -> GosValue {
323        match &self {
324            GosMetadata::Untyped => GosValue::Nil(*self),
325            GosMetadata::NonPtr(k, mc) => match &mobjs[*k] {
326                MetadataType::Bool => GosValue::Bool(false),
327                MetadataType::Int => GosValue::Int(0),
328                MetadataType::Int8 => GosValue::Int8(0),
329                MetadataType::Int16 => GosValue::Int16(0),
330                MetadataType::Int32 => GosValue::Int32(0),
331                MetadataType::Int64 => GosValue::Int64(0),
332                MetadataType::Uint => GosValue::Uint(0),
333                MetadataType::Uint8 => GosValue::Uint8(0),
334                MetadataType::Uint16 => GosValue::Uint16(0),
335                MetadataType::Uint32 => GosValue::Uint32(0),
336                MetadataType::Uint64 => GosValue::Uint64(0),
337                MetadataType::Float32 => GosValue::Float32(0.0.into()),
338                MetadataType::Float64 => GosValue::Float64(0.0.into()),
339                MetadataType::Complex64 => GosValue::Complex64(0.0.into(), 0.0.into()),
340                MetadataType::Complex128 => {
341                    GosValue::Complex128(Box::new((0.0.into(), 0.0.into())))
342                }
343                MetadataType::Str(s) => s.clone(),
344                MetadataType::SliceOrArray(m, size) => match mc {
345                    MetaCategory::Array => {
346                        let val = m.default_val(mobjs, gcos);
347                        GosValue::array_with_size(*size, &val, *self, gcos)
348                    }
349                    MetaCategory::Default => GosValue::new_slice_nil(*self, gcos),
350                    _ => unreachable!(),
351                },
352                MetadataType::Struct(_, s) => s.copy_semantic(gcos),
353                MetadataType::Signature(_) => GosValue::Nil(*self),
354                MetadataType::Map(_, v) => {
355                    GosValue::new_map_nil(*self, v.default_val(mobjs, gcos), gcos)
356                }
357                MetadataType::Interface(_) => GosValue::Nil(*self),
358                MetadataType::Channel(_, _) => GosValue::Nil(*self),
359                MetadataType::Named(_, gm) => {
360                    let val = gm.default_val(mobjs, gcos);
361                    GosValue::Named(Box::new((val, *gm)))
362                }
363            },
364            _ => GosValue::Nil(*self),
365        }
366    }
367
368    #[inline]
369    pub fn default_val(&self, mobjs: &MetadataObjs, gcos: &GcoVec) -> GosValue {
370        match &self {
371            GosMetadata::NonPtr(k, mc) => match &mobjs[*k] {
372                MetadataType::Bool => GosValue::Bool(false),
373                MetadataType::Int => GosValue::Int(0),
374                MetadataType::Int8 => GosValue::Int8(0),
375                MetadataType::Int16 => GosValue::Int16(0),
376                MetadataType::Int32 => GosValue::Int32(0),
377                MetadataType::Int64 => GosValue::Int64(0),
378                MetadataType::Uint => GosValue::Uint(0),
379                MetadataType::Uint8 => GosValue::Uint8(0),
380                MetadataType::Uint16 => GosValue::Uint16(0),
381                MetadataType::Uint32 => GosValue::Uint32(0),
382                MetadataType::Uint64 => GosValue::Uint64(0),
383                MetadataType::Float32 => GosValue::Float32(0.0.into()),
384                MetadataType::Float64 => GosValue::Float64(0.0.into()),
385                MetadataType::Complex64 => GosValue::Complex64(0.0.into(), 0.0.into()),
386                MetadataType::Complex128 => {
387                    GosValue::Complex128(Box::new((0.0.into(), 0.0.into())))
388                }
389                MetadataType::Str(s) => s.clone(),
390                MetadataType::SliceOrArray(m, size) => match mc {
391                    MetaCategory::Array => {
392                        let val = m.default_val(mobjs, gcos);
393                        GosValue::array_with_size(*size, &val, *self, gcos)
394                    }
395                    MetaCategory::Default => GosValue::new_slice(0, 0, *self, None, gcos),
396                    _ => unreachable!(),
397                },
398                MetadataType::Struct(_, s) => s.copy_semantic(gcos),
399                MetadataType::Signature(_) => GosValue::Nil(*self),
400                MetadataType::Map(_, v) => {
401                    GosValue::new_map(*self, v.default_val(mobjs, gcos), gcos)
402                }
403                MetadataType::Interface(_) => GosValue::Nil(*self),
404                MetadataType::Channel(_, _) => GosValue::Nil(*self),
405                MetadataType::Named(_, gm) => {
406                    let val = gm.default_val(mobjs, gcos);
407                    GosValue::Named(Box::new((val, *gm)))
408                }
409            },
410            _ => unreachable!(),
411        }
412    }
413
414    #[inline]
415    pub fn field_index(&self, name: &str, metas: &MetadataObjs) -> OpIndex {
416        let key = self.recv_meta_key();
417        match &metas[GosMetadata::NonPtr(key, MetaCategory::Default)
418            .get_underlying(metas)
419            .as_non_ptr()]
420        {
421            MetadataType::Struct(m, _) => m.mapping[name] as OpIndex,
422            _ => unreachable!(),
423        }
424    }
425
426    #[inline]
427    pub fn get_underlying(&self, metas: &MetadataObjs) -> GosMetadata {
428        match self {
429            GosMetadata::NonPtr(k, _) => match &metas[*k] {
430                MetadataType::Named(_, u) => *u,
431                _ => *self,
432            },
433            _ => *self,
434        }
435    }
436
437    #[inline]
438    pub fn recv_meta_key(&self) -> MetadataKey {
439        match self {
440            GosMetadata::NonPtr(k, _) => *k,
441            GosMetadata::Ptr1(k, _) => *k,
442            _ => unreachable!(),
443        }
444    }
445
446    pub fn add_method(&self, name: String, pointer_recv: bool, metas: &mut MetadataObjs) {
447        let k = self.recv_meta_key();
448        match &mut metas[k] {
449            MetadataType::Named(m, _) => {
450                m.members.push(Rc::new(RefCell::new(MethodDesc {
451                    pointer_recv: pointer_recv,
452                    func: None,
453                })));
454                m.mapping.insert(name, m.members.len() as OpIndex - 1);
455            }
456            _ => unreachable!(),
457        }
458    }
459
460    pub fn set_method_code(&self, name: &String, func: FunctionKey, metas: &mut MetadataObjs) {
461        let k = self.recv_meta_key();
462        match &mut metas[k] {
463            MetadataType::Named(m, _) => {
464                let index = m.mapping[name] as usize;
465                m.members[index].borrow_mut().func = Some(func);
466            }
467            _ => unreachable!(),
468        }
469    }
470
471    #[inline]
472    pub fn get_named_metadate<'a>(
473        &self,
474        metas: &'a MetadataObjs,
475    ) -> (&'a Methods, &'a GosMetadata) {
476        let k = self.recv_meta_key();
477        match &metas[k] {
478            MetadataType::Named(methods, md) => (methods, md),
479            _ => unreachable!(),
480        }
481    }
482
483    #[inline]
484    pub fn get_method(&self, index: OpIndex, metas: &MetadataObjs) -> Rc<RefCell<MethodDesc>> {
485        let (m, _) = self.get_named_metadate(metas);
486        m.members[index as usize].clone()
487    }
488
489    /// method_index returns the index of the method of a non-interface
490    #[inline]
491    pub fn method_index(&self, name: &str, metas: &MetadataObjs) -> OpIndex {
492        let (m, _) = self.get_named_metadate(metas);
493        m.mapping[name] as OpIndex
494    }
495
496    /// iface_method_index returns the index of the method of an interface
497    #[inline]
498    pub fn iface_method_index(&self, name: &str, metas: &MetadataObjs) -> OpIndex {
499        let (_, under) = self.get_named_metadate(metas);
500        if let MetadataType::Interface(m) = &metas[under.as_non_ptr()] {
501            m.mapping[name] as OpIndex
502        } else {
503            unreachable!()
504        }
505    }
506
507    pub fn semantic_eq(&self, other: &Self, metas: &MetadataObjs) -> bool {
508        match (self, other) {
509            (Self::NonPtr(ak, ac), Self::NonPtr(bk, bc)) => {
510                Self::semantic_eq_impl(ak, ac, bk, bc, metas)
511            }
512            (Self::Ptr1(ak, ac), Self::Ptr1(bk, bc)) => {
513                Self::semantic_eq_impl(ak, ac, bk, bc, metas)
514            }
515            (Self::Ptr2(ak, ac), Self::Ptr2(bk, bc)) => {
516                Self::semantic_eq_impl(ak, ac, bk, bc, metas)
517            }
518            (Self::Ptr3(ak, ac), Self::Ptr3(bk, bc)) => {
519                Self::semantic_eq_impl(ak, ac, bk, bc, metas)
520            }
521            (Self::Ptr4(ak, ac), Self::Ptr4(bk, bc)) => {
522                Self::semantic_eq_impl(ak, ac, bk, bc, metas)
523            }
524            (Self::Ptr5(ak, ac), Self::Ptr5(bk, bc)) => {
525                Self::semantic_eq_impl(ak, ac, bk, bc, metas)
526            }
527            (Self::Ptr6(ak, ac), Self::Ptr6(bk, bc)) => {
528                Self::semantic_eq_impl(ak, ac, bk, bc, metas)
529            }
530            (Self::Ptr7(ak, ac), Self::Ptr7(bk, bc)) => {
531                Self::semantic_eq_impl(ak, ac, bk, bc, metas)
532            }
533            (Self::Untyped, Self::Untyped) => true,
534            _ => false,
535        }
536    }
537
538    #[inline]
539    fn semantic_eq_impl(
540        ak: &MetadataKey,
541        ac: &MetaCategory,
542        bk: &MetadataKey,
543        bc: &MetaCategory,
544        metas: &MetadataObjs,
545    ) -> bool {
546        (ac == bc) && ((ak == bk) || metas[*ak].semantic_eq(&metas[*bk], *ac, metas))
547    }
548}
549
550#[derive(Debug, Clone)]
551pub struct Fields {
552    pub fields: Vec<GosMetadata>,
553    pub mapping: HashMap<String, OpIndex>,
554}
555
556impl Fields {
557    #[inline]
558    pub fn new(fields: Vec<GosMetadata>, mapping: HashMap<String, OpIndex>) -> Fields {
559        Fields {
560            fields: fields,
561            mapping: mapping,
562        }
563    }
564
565    #[inline]
566    pub fn iface_named_mapping(&self, named_obj: &Methods) -> Vec<Rc<RefCell<MethodDesc>>> {
567        let default = Rc::new(RefCell::new(MethodDesc {
568            pointer_recv: false,
569            func: None,
570        }));
571        let mut result = vec![default; self.fields.len()];
572        for (n, i) in self.mapping.iter() {
573            let f = &named_obj.members[named_obj.mapping[n] as usize];
574            result[*i as usize] = f.clone();
575        }
576        result
577    }
578
579    pub fn iface_ffi_info(&self) -> Vec<(String, GosMetadata)> {
580        let mut ret = vec![];
581        for f in self.fields.iter() {
582            ret.push((String::new(), *f));
583        }
584        for (name, index) in self.mapping.iter() {
585            ret[*index as usize].0 = name.clone();
586        }
587        ret
588    }
589
590    pub fn semantic_eq(&self, other: &Self, metas: &MetadataObjs) -> bool {
591        if self.fields.len() != other.fields.len() {
592            return false;
593        }
594        for (i, f) in self.fields.iter().enumerate() {
595            if !f.semantic_eq(&other.fields[i], metas) {
596                return false;
597            }
598        }
599        true
600    }
601}
602
603#[derive(Debug, Clone)]
604pub struct MethodDesc {
605    pub pointer_recv: bool,
606    pub func: Option<FunctionKey>,
607}
608
609#[derive(Debug, Clone)]
610pub struct Methods {
611    pub members: Vec<Rc<RefCell<MethodDesc>>>,
612    pub mapping: HashMap<String, OpIndex>,
613}
614
615impl Methods {
616    pub fn new() -> Methods {
617        Methods {
618            members: vec![],
619            mapping: HashMap::new(),
620        }
621    }
622}
623
624#[derive(Debug, Clone)]
625pub struct SigMetadata {
626    pub recv: Option<GosMetadata>,
627    pub params: Vec<GosMetadata>,
628    pub results: Vec<GosMetadata>,
629    pub variadic: Option<(GosMetadata, GosMetadata)>,
630    pub params_type: Vec<ValueType>, // for calling FFI
631}
632
633impl Default for SigMetadata {
634    fn default() -> SigMetadata {
635        Self {
636            recv: None,
637            params: vec![],
638            results: vec![],
639            variadic: None,
640            params_type: vec![],
641        }
642    }
643}
644
645impl SigMetadata {
646    pub fn pointer_recv(&self) -> bool {
647        if let Some(r) = &self.recv {
648            match r {
649                GosMetadata::NonPtr(_, _) => false,
650                _ => true,
651            }
652        } else {
653            false
654        }
655    }
656
657    pub fn semantic_eq(&self, other: &Self, metas: &MetadataObjs) -> bool {
658        if !match (&self.recv, &other.recv) {
659            (None, None) => true,
660            (Some(a), Some(b)) => a.semantic_eq(b, metas),
661            _ => false,
662        } {
663            return false;
664        }
665
666        if self.params.len() != other.params.len() {
667            return false;
668        }
669        for (i, p) in self.params.iter().enumerate() {
670            if !p.semantic_eq(&other.params[i], metas) {
671                return false;
672            }
673        }
674
675        if self.results.len() != other.params.len() {
676            return false;
677        }
678        for (i, r) in self.results.iter().enumerate() {
679            if !r.semantic_eq(&other.results[i], metas) {
680                return false;
681            }
682        }
683        if !match (&self.variadic, &other.variadic) {
684            (None, None) => true,
685            (Some((a, _)), Some((b, _))) => a.semantic_eq(b, metas),
686            _ => false,
687        } {
688            return false;
689        }
690        true
691    }
692}
693
694#[derive(Debug, Clone)]
695pub enum MetadataType {
696    Bool,
697    Int,
698    Int8,
699    Int16,
700    Int32,
701    Int64,
702    Uint,
703    Uint8,
704    Uint16,
705    Uint32,
706    Uint64,
707    Float32,
708    Float64,
709    Complex64,
710    Complex128,
711    Str(GosValue),
712    SliceOrArray(GosMetadata, usize),
713    Struct(Fields, GosValue),
714    Signature(SigMetadata),
715    Map(GosMetadata, GosMetadata),
716    Interface(Fields),
717    Channel(ChannelType, GosMetadata),
718    Named(Methods, GosMetadata),
719}
720
721impl MetadataType {
722    #[inline]
723    pub fn as_signature(&self) -> &SigMetadata {
724        match self {
725            Self::Signature(s) => s,
726            _ => unreachable!(),
727        }
728    }
729
730    #[inline]
731    pub fn as_interface(&self) -> &Fields {
732        match self {
733            Self::Interface(fields) => fields,
734            _ => unreachable!(),
735        }
736    }
737
738    #[inline]
739    pub fn as_channel(&self) -> (&ChannelType, &GosMetadata) {
740        match self {
741            Self::Channel(t, m) => (t, m),
742            _ => unreachable!(),
743        }
744    }
745
746    pub fn semantic_eq(&self, other: &Self, mc: MetaCategory, metas: &MetadataObjs) -> bool {
747        match (self, other) {
748            (Self::Bool, Self::Bool) => true,
749            (Self::Int, Self::Int) => true,
750            (Self::Int8, Self::Int8) => true,
751            (Self::Int16, Self::Int16) => true,
752            (Self::Int32, Self::Int32) => true,
753            (Self::Int64, Self::Int64) => true,
754            (Self::Uint8, Self::Uint8) => true,
755            (Self::Uint16, Self::Uint16) => true,
756            (Self::Uint32, Self::Uint32) => true,
757            (Self::Uint64, Self::Uint64) => true,
758            (Self::Float32, Self::Float32) => true,
759            (Self::Float64, Self::Float64) => true,
760            (Self::Complex64, Self::Complex64) => true,
761            (Self::Complex128, Self::Complex128) => true,
762            (Self::Str(_), Self::Str(_)) => true,
763            (Self::Struct(a, _), Self::Struct(b, _)) => a.semantic_eq(b, metas),
764            (Self::Signature(a), Self::Signature(b)) => a.semantic_eq(b, metas),
765            (Self::SliceOrArray(a, size_a), Self::SliceOrArray(b, size_b)) => {
766                match mc {
767                    MetaCategory::Array | MetaCategory::ArrayType => {
768                        if size_a != size_b {
769                            return false;
770                        }
771                    }
772                    _ => {}
773                }
774                a.semantic_eq(b, metas)
775            }
776            (Self::Map(ak, av), Self::Map(bk, bv)) => {
777                ak.semantic_eq(bk, metas) && av.semantic_eq(bv, metas)
778            }
779            (Self::Interface(a), Self::Interface(b)) => a.semantic_eq(b, metas),
780            (Self::Channel(at, avt), Self::Channel(bt, bvt)) => {
781                at == bt && avt.semantic_eq(bvt, metas)
782            }
783            (Self::Named(_, a), Self::Named(_, b)) => a.semantic_eq(b, metas),
784            _ => false,
785        }
786    }
787}