go_codegen/
types.rs

1// Copyright 2022 The Goscript Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5use go_parser::ast::{Expr, Node, NodeId};
6use go_parser::{IdentKey, Map};
7use go_types::{
8    check::TypeInfo, typ::BasicType, typ::ChanDir, typ::Type, ConstValue, EntityType,
9    ObjKey as TCObjKey, OperandMode, PackageKey as TCPackageKey, SelectionKind as TCSelectionKind,
10    TCObjects, TypeKey as TCTypeKey,
11};
12use go_vm::types::*;
13use go_vm::*;
14use std::vec;
15
16pub type TypeCache = Map<TCTypeKey, Meta>;
17
18#[derive(PartialEq)]
19pub enum SelectionType {
20    NonMethod,
21    MethodNonPtrRecv,
22    MethodPtrRecv,
23}
24
25pub(crate) struct TypeLookup<'a> {
26    tc_objs: &'a TCObjects,
27    ti: &'a TypeInfo,
28    types_cache: &'a mut TypeCache,
29}
30
31impl<'a> TypeLookup<'a> {
32    pub fn new(
33        tc_objs: &'a TCObjects,
34        ti: &'a TypeInfo,
35        types_cache: &'a mut TypeCache,
36    ) -> TypeLookup<'a> {
37        TypeLookup {
38            tc_objs,
39            ti,
40            types_cache,
41        }
42    }
43
44    #[inline]
45    pub fn type_info(&self) -> &TypeInfo {
46        self.ti
47    }
48
49    #[inline]
50    pub fn try_tc_const_value(&self, id: NodeId) -> Option<&ConstValue> {
51        let typ_val = self.ti.types.get(&id).unwrap();
52        typ_val.get_const_val()
53    }
54
55    #[inline]
56    pub fn const_type_value(&self, id: NodeId) -> (TCTypeKey, GosValue) {
57        let typ_val = self.ti.types.get(&id).unwrap();
58        let const_val = typ_val.get_const_val().unwrap();
59        (typ_val.typ, self.const_value(typ_val.typ, const_val))
60    }
61
62    #[inline]
63    pub fn ident_const_value(&self, id: &IdentKey) -> GosValue {
64        let lobj_key = self.ti.defs[id].unwrap();
65        let lobj = &self.tc_objs.lobjs[lobj_key];
66        let tkey = lobj.typ().unwrap();
67        self.const_value(tkey, lobj.const_val())
68    }
69
70    #[inline]
71    pub fn expr_tc_type(&self, e: &Expr) -> TCTypeKey {
72        self.node_tc_type(e.id())
73    }
74
75    #[inline]
76    pub fn node_tc_type(&self, id: NodeId) -> TCTypeKey {
77        self.ti.types.get(&id).unwrap().typ
78    }
79
80    #[inline]
81    pub fn try_expr_mode(&self, e: &Expr) -> Option<&OperandMode> {
82        self.ti.types.get(&e.id()).map(|x| &x.mode)
83    }
84
85    #[inline]
86    pub fn expr_mode(&self, e: &Expr) -> &OperandMode {
87        &self.ti.types.get(&e.id()).unwrap().mode
88    }
89
90    // some of the built in funcs are not recorded
91    pub fn try_expr_tc_type(&self, e: &Expr) -> Option<TCTypeKey> {
92        self.ti
93            .types
94            .get(&e.id())
95            .map(|x| {
96                let typ = x.typ;
97                if self.tc_objs.types[typ].is_invalid(self.tc_objs) {
98                    None
99                } else {
100                    Some(typ)
101                }
102            })
103            .flatten()
104    }
105
106    pub fn try_pkg_key(&self, e: &Expr) -> Option<TCPackageKey> {
107        if let Expr::Ident(ikey) = e {
108            self.ti
109                .uses
110                .get(ikey)
111                .map(|x| {
112                    if let EntityType::PkgName(pkg, _) = self.tc_objs.lobjs[*x].entity_type() {
113                        Some(*pkg)
114                    } else {
115                        None
116                    }
117                })
118                .flatten()
119        } else {
120            None
121        }
122    }
123
124    pub fn expr_value_type(&self, e: &Expr) -> ValueType {
125        let tv = self.ti.types.get(&e.id()).unwrap();
126        if tv.mode == OperandMode::TypeExpr {
127            ValueType::Metadata
128        } else {
129            let t = self.expr_tc_type(e);
130            self.tc_type_to_value_type(t)
131        }
132    }
133
134    pub fn sliceable_expr_value_types(
135        &mut self,
136        e: &Expr,
137        vmctx: &mut CodeGenVMCtx,
138    ) -> (ValueType, TCTypeKey) {
139        let tc_type = self.expr_tc_type(&e);
140        let typ = self.tc_objs.types[tc_type].underlying().unwrap_or(tc_type);
141        let meta = self.tc_type_to_meta(typ, vmctx);
142        let metas = &vmctx.metas();
143        match &metas[meta.key] {
144            MetadataType::Array(_, _) => (
145                ValueType::Array,
146                self.tc_objs.types[typ].try_as_array().unwrap().elem(),
147            ),
148            MetadataType::Slice(_) => (
149                ValueType::Slice,
150                self.tc_objs.types[typ].try_as_slice().unwrap().elem(),
151            ),
152            MetadataType::Str => (
153                ValueType::String,
154                self.tc_objs.universe().types()[&BasicType::Uint8],
155            ),
156            _ => unreachable!(),
157        }
158    }
159
160    pub fn node_meta(&mut self, id: NodeId, vmctx: &mut CodeGenVMCtx) -> Meta {
161        let tv = self.ti.types.get(&id).unwrap();
162        let md = self.tc_type_to_meta(tv.typ, vmctx);
163        if tv.mode == OperandMode::TypeExpr {
164            md.into_type_category()
165        } else {
166            md
167        }
168    }
169
170    #[inline]
171    pub fn object_use(&self, ikey: IdentKey) -> TCObjKey {
172        self.ti.uses[&ikey]
173    }
174
175    #[inline]
176    pub fn object_def(&self, ikey: IdentKey) -> TCObjKey {
177        self.ti.defs[&ikey].unwrap()
178    }
179
180    #[inline]
181    pub fn object_implicit(&self, id: &NodeId) -> TCObjKey {
182        self.ti.implicits[id]
183    }
184
185    #[inline]
186    pub fn obj_use_tc_type(&self, ikey: IdentKey) -> TCTypeKey {
187        self.obj_tc_type(self.object_use(ikey))
188    }
189
190    #[inline]
191    pub fn obj_use_value_type(&self, ikey: IdentKey) -> ValueType {
192        self.tc_type_to_value_type(self.obj_use_tc_type(ikey))
193    }
194
195    #[inline]
196    pub fn obj_def_tc_type(&self, ikey: IdentKey) -> TCTypeKey {
197        self.obj_tc_type(self.object_def(ikey))
198    }
199
200    #[inline]
201    pub fn obj_tc_type(&self, okey: TCObjKey) -> TCTypeKey {
202        let obj = &self.tc_objs.lobjs[okey];
203        obj.typ().unwrap()
204    }
205
206    #[inline]
207    pub fn ident_is_def(&self, ikey: &IdentKey) -> bool {
208        self.ti.defs.contains_key(ikey)
209    }
210
211    #[inline]
212    pub fn obj_def_meta(&mut self, ikey: IdentKey, vmctx: &mut CodeGenVMCtx) -> Meta {
213        self.tc_type_to_meta(self.obj_def_tc_type(ikey), vmctx)
214    }
215
216    #[inline]
217    pub fn expr_range_tc_types(&self, e: &Expr) -> [TCTypeKey; 3] {
218        let typ = self.ti.types.get(&e.id()).unwrap().typ;
219        self.range_tc_types(typ)
220    }
221
222    #[inline]
223    pub fn expr_tuple_tc_types(&self, e: &Expr) -> Vec<TCTypeKey> {
224        let typ = self.ti.types.get(&e.id()).unwrap().typ;
225        self.tuple_tc_types(typ)
226    }
227
228    pub fn selection_vtypes_indices_sel_typ(
229        &self,
230        id: NodeId,
231    ) -> (TCTypeKey, TCTypeKey, &Vec<usize>, SelectionType) {
232        let sel = &self.ti.selections[&id];
233        let recv_type = sel.recv().unwrap();
234        let obj = &self.tc_objs.lobjs[sel.obj()];
235        let expr_type = obj.typ().unwrap();
236        let sel_typ = if self.tc_objs.types[expr_type].try_as_signature().is_some() {
237            match obj.entity_type() {
238                EntityType::Func(ptr_recv) => match ptr_recv {
239                    true => SelectionType::MethodPtrRecv,
240                    false => SelectionType::MethodNonPtrRecv,
241                },
242                _ => SelectionType::NonMethod,
243            }
244        } else {
245            SelectionType::NonMethod
246        };
247        (recv_type, expr_type, &sel.indices(), sel_typ)
248    }
249
250    pub fn need_cast_container_index(&self, container: &Expr, index: &Expr) -> Option<TCTypeKey> {
251        let index_key = self.node_tc_type(index.id());
252        if self.tc_type_to_value_type(index_key) == ValueType::Interface {
253            return None;
254        }
255        let container_key = self.node_tc_type(container.id());
256        match &self.tc_objs.types[container_key] {
257            Type::Map(detail) => (self.tc_type_to_value_type(detail.key()) == ValueType::Interface)
258                .then_some(detail.key()),
259            _ => None,
260        }
261    }
262
263    pub fn tc_type_to_meta(&mut self, typ: TCTypeKey, vmctx: &mut CodeGenVMCtx) -> Meta {
264        if !self.types_cache.contains_key(&typ) {
265            let val = self.tc_type_to_meta_impl(typ, vmctx);
266            self.types_cache.insert(typ, val);
267        }
268        self.types_cache.get(&typ).unwrap().clone()
269    }
270
271    pub fn sig_params_tc_types(&self, func: TCTypeKey) -> (Vec<TCTypeKey>, Option<TCTypeKey>) {
272        let typ = &self.tc_objs.types[func].underlying_val(self.tc_objs);
273        let sig = typ.try_as_signature().unwrap();
274        let params: Vec<TCTypeKey> = self.tc_objs.types[sig.params()]
275            .try_as_tuple()
276            .unwrap()
277            .vars()
278            .iter()
279            .map(|&x| self.tc_objs.lobjs[x].typ().unwrap())
280            .collect();
281        let variadic = if sig.variadic() {
282            let slice_key = *params.last().unwrap();
283            match &self.tc_objs.types[slice_key] {
284                Type::Slice(s) => Some(s.elem()),
285                // spec: "As a special case, append also accepts a first argument assignable
286                // to type []byte with a second argument of string type followed by ... .
287                // This form appends the bytes of the string.
288                Type::Basic(_) => Some(*self.tc_objs.universe().byte()),
289                _ => unreachable!(),
290            }
291        } else {
292            None
293        };
294        (params, variadic)
295    }
296
297    pub fn sig_returns_tc_types(&self, func: TCTypeKey) -> Vec<TCTypeKey> {
298        let typ = &self.tc_objs.types[func].underlying_val(self.tc_objs);
299        let sig = typ.try_as_signature().unwrap();
300        self.tuple_tc_types(sig.results())
301    }
302
303    pub fn is_method(&self, expr: &Expr) -> bool {
304        match expr {
305            Expr::Selector(sel_expr) => match self.ti.selections.get(&sel_expr.id()) {
306                Some(sel) => match sel.kind() {
307                    TCSelectionKind::MethodVal => true,
308                    _ => false,
309                },
310                None => false,
311            },
312            _ => false,
313        }
314    }
315
316    // returns vm_type(metadata) for the tc_type
317    pub fn basic_type_meta(&self, tkey: TCTypeKey, prim_meta: &PrimitiveMeta) -> Option<Meta> {
318        self.tc_objs.types[tkey].try_as_basic().map(|x| {
319            let typ = x.typ();
320            match typ {
321                BasicType::Bool | BasicType::UntypedBool => prim_meta.mbool,
322                BasicType::Int | BasicType::UntypedInt => prim_meta.mint,
323                BasicType::Int8 => prim_meta.mint8,
324                BasicType::Int16 => prim_meta.mint16,
325                BasicType::Int32 | BasicType::Rune | BasicType::UntypedRune => prim_meta.mint32,
326                BasicType::Int64 => prim_meta.mint64,
327                BasicType::Uint | BasicType::Uintptr => prim_meta.muint,
328                BasicType::Uint8 | BasicType::Byte => prim_meta.muint8,
329                BasicType::Uint16 => prim_meta.muint16,
330                BasicType::Uint32 => prim_meta.muint32,
331                BasicType::Uint64 => prim_meta.muint64,
332                BasicType::Float32 => prim_meta.mfloat32,
333                BasicType::Float64 | BasicType::UntypedFloat => prim_meta.mfloat64,
334                BasicType::Complex64 => prim_meta.mcomplex64,
335                BasicType::Complex128 => prim_meta.mcomplex128,
336                BasicType::Str | BasicType::UntypedString => prim_meta.mstr,
337                BasicType::UnsafePointer => prim_meta.unsafe_ptr,
338                BasicType::UntypedNil => prim_meta.none,
339                _ => {
340                    dbg!(typ);
341                    unreachable!()
342                }
343            }
344        })
345    }
346
347    // get GosValue from type checker's Obj
348    fn const_value(&self, tkey: TCTypeKey, val: &ConstValue) -> GosValue {
349        let underlying_type = self.tc_objs.types[tkey].underlying().unwrap_or(tkey);
350        let typ = self.tc_type_to_value_type(underlying_type);
351        match typ {
352            ValueType::Bool => val.bool_as_bool().into(),
353            ValueType::Int => (val.to_int().int_as_i64().0 as isize).into(),
354            ValueType::Int8 => (val.to_int().int_as_i64().0 as i8).into(),
355            ValueType::Int16 => (val.to_int().int_as_i64().0 as i16).into(),
356            ValueType::Int32 => (val.to_int().int_as_i64().0 as i32).into(),
357            ValueType::Int64 => val.to_int().int_as_i64().0.into(),
358            ValueType::Uint => (val.to_int().int_as_u64().0 as usize).into(),
359            ValueType::UintPtr => FfiCtx::new_uint_ptr(val.to_int().int_as_u64().0 as usize),
360            ValueType::Uint8 => (val.to_int().int_as_u64().0 as u8).into(),
361            ValueType::Uint16 => (val.to_int().int_as_u64().0 as u16).into(),
362            ValueType::Uint32 => (val.to_int().int_as_u64().0 as u32).into(),
363            ValueType::Uint64 => val.to_int().int_as_u64().0.into(),
364            ValueType::Float32 => val.num_as_f32().0.into_inner().into(),
365            ValueType::Float64 => val.num_as_f64().0.into_inner().into(),
366            ValueType::Complex64 => {
367                let (cr, ci, _) = val.to_complex().complex_as_complex64();
368                FfiCtx::new_complex64(cr.0, ci.0)
369            }
370            ValueType::Complex128 => {
371                let (cr, ci, _) = val.to_complex().complex_as_complex128();
372                FfiCtx::new_complex128(cr.0, ci.0)
373            }
374            ValueType::String => FfiCtx::new_string(&val.str_as_string()),
375            ValueType::UnsafePtr => FfiCtx::new_nil(ValueType::UnsafePtr),
376            _ => {
377                dbg!(typ);
378                unreachable!();
379            }
380        }
381    }
382
383    // get vm_type from tc_type
384    fn tc_type_to_meta_impl(&mut self, typ: TCTypeKey, vmctx: &mut CodeGenVMCtx) -> Meta {
385        match &self.tc_objs.types[typ] {
386            Type::Basic(_) => self.basic_type_meta(typ, vmctx.prim_meta()).unwrap(),
387            Type::Array(detail) => {
388                let elem = self.tc_type_to_meta_impl(detail.elem(), vmctx);
389                Meta::new_array(elem, detail.len().unwrap() as usize, vmctx.metas_mut())
390            }
391            Type::Slice(detail) => {
392                let el_type = self.tc_type_to_meta(detail.elem(), vmctx);
393                Meta::new_slice(el_type, vmctx.metas_mut())
394            }
395            Type::Map(detail) => {
396                let ktype = self.tc_type_to_meta(detail.key(), vmctx);
397                let vtype = self.tc_type_to_meta(detail.elem(), vmctx);
398                Meta::new_map(ktype, vtype, vmctx.metas_mut())
399            }
400            Type::Struct(detail) => {
401                let fields = self.build_fields(detail.fields(), detail.tags(), vmctx);
402                vmctx.new_struct_meta(fields)
403            }
404            Type::Interface(detail) => {
405                let methods = detail.all_methods();
406                let fields = self.build_fields(methods.as_ref().unwrap(), &None, vmctx);
407                Meta::new_interface(fields, vmctx.metas_mut())
408            }
409            Type::Chan(detail) => {
410                let typ = match detail.dir() {
411                    ChanDir::RecvOnly => ChannelType::Recv,
412                    ChanDir::SendOnly => ChannelType::Send,
413                    ChanDir::SendRecv => ChannelType::SendRecv,
414                };
415                let vmeta = self.tc_type_to_meta(detail.elem(), vmctx);
416                Meta::new_channel(typ, vmeta, vmctx.metas_mut())
417            }
418            Type::Signature(detail) => {
419                let mut convert = |tuple_key| -> Vec<Meta> {
420                    self.tc_objs.types[tuple_key]
421                        .try_as_tuple()
422                        .unwrap()
423                        .vars()
424                        .iter()
425                        .map(|&x| self.tc_type_to_meta(self.tc_objs.lobjs[x].typ().unwrap(), vmctx))
426                        .collect()
427                };
428                let params = convert(detail.params());
429                let results = convert(detail.results());
430                let mut recv = None;
431                if let Some(r) = detail.recv() {
432                    let recv_tc_type = self.tc_objs.lobjs[*r].typ().unwrap();
433                    // to avoid infinite recursion
434                    if !self.tc_objs.types[recv_tc_type].is_interface(self.tc_objs) {
435                        recv = Some(self.tc_type_to_meta(recv_tc_type, vmctx));
436                    }
437                }
438                let variadic = if detail.variadic() {
439                    let slice = params.last().unwrap();
440                    match &vmctx.metas()[slice.key] {
441                        MetadataType::Slice(elem) => Some((*slice, elem.clone())),
442                        _ => unreachable!(),
443                    }
444                } else {
445                    None
446                };
447                Meta::new_sig(recv, params, results, variadic, vmctx.metas_mut())
448            }
449            Type::Pointer(detail) => {
450                let inner = self.tc_type_to_meta(detail.base(), vmctx);
451                inner.ptr_to()
452            }
453            Type::Named(detail) => {
454                // generate a Named with dummy underlying to avoid recursion
455                let md = Meta::new_named(vmctx.prim_meta().mint, vmctx.metas_mut());
456                for key in detail.methods().iter() {
457                    let mobj = &self.tc_objs.lobjs[*key];
458                    md.add_method(
459                        mobj.name().clone(),
460                        mobj.entity_type().func_has_ptr_recv(),
461                        vmctx.metas_mut(),
462                    )
463                }
464                self.types_cache.insert(typ, md);
465                let underlying = self.tc_type_to_meta(detail.underlying(), vmctx);
466                let (_, underlying_mut) = vmctx.metas_mut()[md.key].as_named_mut();
467                *underlying_mut = underlying;
468                md
469            }
470            _ => {
471                dbg!(&self.tc_objs.types[typ]);
472                unimplemented!()
473            }
474        }
475    }
476
477    pub fn underlying_tc(&self, typ: TCTypeKey) -> TCTypeKey {
478        match &self.tc_objs.types[typ] {
479            Type::Named(n) => n.underlying(),
480            _ => typ,
481        }
482    }
483
484    pub fn obj_underlying_value_type(&self, typ: TCTypeKey) -> ValueType {
485        self.tc_type_to_value_type(self.underlying_tc(typ))
486    }
487
488    pub fn tc_type_to_value_type(&self, typ: TCTypeKey) -> ValueType {
489        match &self.tc_objs.types[typ] {
490            Type::Basic(detail) => match detail.typ() {
491                BasicType::Bool | BasicType::UntypedBool => ValueType::Bool,
492                BasicType::Int | BasicType::UntypedInt => ValueType::Int,
493                BasicType::Int8 => ValueType::Int8,
494                BasicType::Int16 => ValueType::Int16,
495                BasicType::Int32 | BasicType::Rune | BasicType::UntypedRune => ValueType::Int32,
496                BasicType::Int64 => ValueType::Int64,
497                BasicType::Uint => ValueType::Uint,
498                BasicType::Uintptr => ValueType::UintPtr,
499                BasicType::Uint8 | BasicType::Byte => ValueType::Uint8,
500                BasicType::Uint16 => ValueType::Uint16,
501                BasicType::Uint32 => ValueType::Uint32,
502                BasicType::Uint64 => ValueType::Uint64,
503                BasicType::Float32 => ValueType::Float32,
504                BasicType::Float64 | BasicType::UntypedFloat => ValueType::Float64,
505                BasicType::Complex64 => ValueType::Complex64,
506                BasicType::Complex128 => ValueType::Complex128,
507                BasicType::Str | BasicType::UntypedString => ValueType::String,
508                BasicType::UnsafePointer => ValueType::UnsafePtr,
509                BasicType::UntypedNil => ValueType::Void,
510                _ => {
511                    dbg!(detail.typ());
512                    unreachable!()
513                }
514            },
515            Type::Array(_) => ValueType::Array,
516            Type::Slice(_) => ValueType::Slice,
517            Type::Map(_) => ValueType::Map,
518            Type::Struct(_) => ValueType::Struct,
519            Type::Interface(_) => ValueType::Interface,
520            Type::Chan(_) => ValueType::Channel,
521            Type::Signature(_) => ValueType::Closure,
522            Type::Pointer(_) => ValueType::Pointer,
523            Type::Named(n) => self.tc_type_to_value_type(n.underlying()),
524            _ => {
525                dbg!(&self.tc_objs.types[typ]);
526                unimplemented!()
527            }
528        }
529    }
530
531    pub fn slice_elem_type(&self, typ: TCTypeKey) -> ValueType {
532        match &self.tc_objs.types[typ] {
533            Type::Slice(s) => self.tc_type_to_value_type(s.elem()),
534            _ => unreachable!(),
535        }
536    }
537
538    pub fn bool_tc_type(&self) -> TCTypeKey {
539        self.tc_objs.universe().types()[&BasicType::Bool]
540    }
541
542    pub fn should_cast_to_iface(&self, lhs: TCTypeKey, rhs: TCTypeKey) -> bool {
543        let vt1 = self.obj_underlying_value_type(rhs);
544        self.obj_underlying_value_type(lhs) == ValueType::Interface
545            && vt1 != ValueType::Interface
546            && vt1 != ValueType::Void
547    }
548
549    fn range_tc_types(&self, typ: TCTypeKey) -> [TCTypeKey; 3] {
550        let t_int = self.tc_objs.universe().types()[&BasicType::Int];
551        let typ = self.tc_objs.types[typ].underlying().unwrap_or(typ);
552        match &self.tc_objs.types[typ] {
553            Type::Basic(detail) => match detail.typ() {
554                BasicType::Str | BasicType::UntypedString => [typ, t_int, t_int],
555                _ => unreachable!(),
556            },
557            Type::Slice(detail) => [typ, t_int, detail.elem()],
558            Type::Array(detail) => [typ, t_int, detail.elem()],
559            Type::Map(detail) => [typ, detail.key(), detail.elem()],
560            _ => {
561                dbg!(&self.tc_objs.types[typ]);
562                unreachable!()
563            }
564        }
565    }
566
567    fn tuple_tc_types(&self, typ: TCTypeKey) -> Vec<TCTypeKey> {
568        match &self.tc_objs.types[typ] {
569            Type::Tuple(detail) => detail
570                .vars()
571                .iter()
572                .map(|x| self.tc_objs.lobjs[*x].typ().unwrap())
573                .collect(),
574            _ => unreachable!(),
575        }
576    }
577
578    pub fn iface_binding_info(
579        &mut self,
580        i_s: (TCTypeKey, TCTypeKey),
581        vmctx: &mut CodeGenVMCtx,
582    ) -> (Meta, Vec<IfaceBinding>) {
583        let iface = self.tc_type_to_meta(i_s.0, vmctx);
584        let named = self.tc_type_to_meta(i_s.1, vmctx);
585        let metas = vmctx.metas();
586        iface.bind_with_iface(named, metas)
587    }
588
589    fn build_fields(
590        &mut self,
591        fields: &Vec<TCObjKey>,
592        tags: &Option<Vec<Option<String>>>,
593        vmctx: &mut CodeGenVMCtx,
594    ) -> Fields {
595        let mut infos = Vec::new();
596        let mut embedded_fields = Vec::new();
597        for (i, f) in fields.iter().enumerate() {
598            let field = &self.tc_objs.lobjs[*f];
599            let tag = match tags {
600                Some(tags) => tags[i].clone(),
601                None => None,
602            };
603            let meta = self.tc_type_to_meta(field.typ().unwrap(), vmctx);
604            let embedded =
605                field.entity_type().is_var() && field.entity_type().var_property().embedded;
606            infos.push(FieldInfo {
607                meta,
608                name: field.name().clone(),
609                tag,
610                embedded_indices: None,
611            });
612            if embedded {
613                embedded_fields.push((meta, i));
614            }
615        }
616
617        for (meta, i) in embedded_fields {
618            match meta.mtype_unwraped(&vmctx.metas()) {
619                MetadataType::Struct(fields) => {
620                    for (j, f) in fields.infos().iter().enumerate() {
621                        let mut indices = vec![i];
622                        match f.embedded_indices.clone() {
623                            Some(mut ins) => indices.append(&mut ins),
624                            None => indices.push(j),
625                        };
626                        infos.push(FieldInfo {
627                            meta: f.meta,
628                            name: f.name.clone(),
629                            tag: f.tag.clone(),
630                            embedded_indices: Some(indices),
631                        });
632                    }
633                }
634                _ => {}
635            }
636        }
637
638        Fields::new(infos)
639    }
640}