public static VTable GetVTable(NameAnalyzer analyzer, TypeDefinition typeDef, Dictionary <TypeDefinition, VTable> tbls)
        {
            if (tbls.ContainsKey(typeDef))
            {
                return(tbls[typeDef]);
            }

            //Partition II 10.3, 12.2

            VTable ret = new VTable()
            {
                TypeDef = typeDef
            };

            TypeDefinition baseType = null;

            if (typeDef.BaseType != null)
            {
                baseType = typeDef.BaseType.Resolve();
                if (baseType != null)
                {
                    ret.Table = new List <VTableSlot>(GetVTable(analyzer, baseType, tbls).Table);
                    if (typeDef.BaseType is GenericInstanceType)
                    {
                        GenericInstanceType genInst = typeDef.BaseType as GenericInstanceType;
                        for (int i = 0; i < ret.Table.Count; i++)
                        {
                            ret.Table[i]             = ret.Table[i].Clone();
                            ret.Table[i].OpenCurrent = ret.Table[i].Current;
                            ret.Table[i].Current     = Resolve(ret.Table[i].OpenCurrent, genInst);
                            ret.Table[i].OpenRoot    = ret.Table[i].Root;
                            ret.Table[i].Root        = Resolve(ret.Table[i].OpenRoot, genInst);
                        }
                    }
                }
                else
                {
                    ret.Table = new List <VTableSlot>();
                }
            }
            else
            {
                ret.Table = new List <VTableSlot>();
            }

            if (typeDef.HasInterfaces)          //Interface methods
            {
                foreach (var i in typeDef.Interfaces)
                {
                    if (baseType != null && baseType.Interfaces.Contains(i))
                    {
                        continue;
                    }

                    TypeDefinition iface = i.Resolve();
                    if (iface == null)
                    {
                        continue;
                    }
                    GenericInstanceType genInst = i as GenericInstanceType;
                    foreach (var j in iface.Methods)
                    {
                        MethodReference ifaceMethod = j;
                        if (genInst != null)
                        {
                            ifaceMethod = Resolve(ifaceMethod, genInst);
                        }


                        VTableSlot slot = null;
                        for (int k = 0; k < ret.Table.Count; k++)
                        {
                            if (Match(ifaceMethod, ret.Table[k].Root))
                            {
                                slot = ret.Table[k];
                                break;
                            }
                        }
                        if (slot == null)
                        {
                            if (genInst != null)
                            {
                                ret.Table.Add(new VTableSlot()
                                {
                                    Root     = ifaceMethod,
                                    OpenRoot = j,
                                    Current  = null
                                });
                            }
                            else
                            {
                                ret.Table.Add(new VTableSlot()
                                {
                                    Root    = ifaceMethod,
                                    Current = null
                                });
                            }
                        }
                        else
                        {
                            slot.ReplaceRoot(analyzer, j);
                        }
                    }
                }
            }

            foreach (var i in typeDef.Methods)  //Interface virtual newslot
            {
                if (!i.IsVirtual || !i.IsNewSlot)
                {
                    continue;
                }
                for (int j = 0; j < ret.Table.Count; j++)
                {
                    if (ret.Table[j].Current == null && Match(i, ret.Table[j].Root))
                    {
                        ret.Table[j].ReplaceCurrent(analyzer, i);
                    }
                }
            }
            foreach (var i in typeDef.Methods)  //Interface virtual
            {
                if (!i.IsVirtual)
                {
                    continue;
                }
                for (int j = 0; j < ret.Table.Count; j++)
                {
                    if (ret.Table[j].Current == null && Match(i, ret.Table[j].Root))
                    {
                        ret.Table[j].ReplaceCurrent(analyzer, i);
                    }
                }
            }
            foreach (var i in typeDef.Methods)  //Base newslot
            {
                if (!i.IsVirtual || !i.IsNewSlot)
                {
                    continue;
                }
                for (int j = 0; j < ret.Table.Count; j++)
                {
                    if (Match(i, ret.Table[j].Current))
                    {
                        ret.Table[j].Root = i;
                        ret.Table[j].ReplaceCurrent(analyzer, i);
                    }
                }
            }
            foreach (var i in typeDef.Methods)  //Base virtual
            {
                if (!i.IsVirtual)
                {
                    continue;
                }
                for (int j = 0; j < ret.Table.Count; j++)
                {
                    if (i != ret.Table[j].Current && Match(i, ret.Table[j].Current))
                    {
                        ret.Table[j].ReplaceCurrent(analyzer, i);
                    }
                }
            }
            foreach (var i in typeDef.Methods)  //Remaining
            {
                if (!i.IsVirtual)
                {
                    continue;
                }
                bool matched = false;
                for (int j = 0; j < ret.Table.Count; j++)
                {
                    if (Match(i, ret.Table[j].Current))
                    {
                        matched = true;
                        break;
                    }
                }
                if (!matched)
                {
                    ret.Table.Add(new VTableSlot()
                    {
                        Root    = i,
                        Current = i
                    });
                }
            }

            tbls[typeDef] = ret;
            return(ret);
        }
        public static VTable GetVTable(NameAnalyzer analyzer, TypeDefinition typeDef, Dictionary<TypeDefinition, VTable> tbls)
        {
            if (tbls.ContainsKey(typeDef))
                return tbls[typeDef];

            //Partition II 10.3, 12.2

            VTable ret = new VTable() { TypeDef = typeDef };

            TypeDefinition baseType = null;
            if (typeDef.BaseType != null)
            {
                baseType = typeDef.BaseType.Resolve();
                if (baseType != null)
                {
                    ret.Table = new List<VTableSlot>(GetVTable(analyzer, baseType, tbls).Table);
                    if (typeDef.BaseType is GenericInstanceType)
                    {
                        GenericInstanceType genInst = typeDef.BaseType as GenericInstanceType;
                        for (int i = 0; i < ret.Table.Count; i++)
                        {
                            ret.Table[i] = ret.Table[i].Clone();
                            ret.Table[i].OpenCurrent = ret.Table[i].Current;
                            ret.Table[i].Current = Resolve(ret.Table[i].OpenCurrent, genInst);
                            ret.Table[i].OpenRoot = ret.Table[i].Root;
                            ret.Table[i].Root = Resolve(ret.Table[i].OpenRoot, genInst);
                        }
                    }
                }
                else
                    ret.Table = new List<VTableSlot>();
            }
            else
                ret.Table = new List<VTableSlot>();

            if (typeDef.HasInterfaces)          //Interface methods
            {
                foreach (var i in typeDef.Interfaces)
                {
                    if (baseType != null && baseType.Interfaces.Contains(i)) continue;

                    TypeDefinition iface = i.Resolve();
                    if (iface == null) continue;
                    GenericInstanceType genInst = i as GenericInstanceType;
                    foreach (var j in iface.Methods)
                    {
                        MethodReference ifaceMethod = j;
                        if (genInst != null)
                            ifaceMethod = Resolve(ifaceMethod, genInst);

                        VTableSlot slot = null;
                        for (int k = 0; k < ret.Table.Count; k++)
                            if (Match(ifaceMethod, ret.Table[k].Root))
                            {
                                slot = ret.Table[k];
                                break;
                            }
                        if (slot == null)
                        {
                            if (genInst != null)
                                ret.Table.Add(new VTableSlot()
                                {
                                    Root = ifaceMethod,
                                    OpenRoot = j,
                                    Current = null
                                });
                            else
                                ret.Table.Add(new VTableSlot()
                                {
                                    Root = ifaceMethod,
                                    Current = null
                                });
                        }
                        else
                        {
                            slot.ReplaceRoot(analyzer, j);
                        }
                    }
                }
            }

            foreach (var i in typeDef.Methods)  //Interface virtual newslot
            {
                if (!i.IsVirtual || !i.IsNewSlot) continue;
                for (int j = 0; j < ret.Table.Count; j++)
                    if (ret.Table[j].Current == null && Match(i, ret.Table[j].Root))
                        ret.Table[j].ReplaceCurrent(analyzer, i);
            }
            foreach (var i in typeDef.Methods)  //Interface virtual
            {
                if (!i.IsVirtual) continue;
                for (int j = 0; j < ret.Table.Count; j++)
                    if (ret.Table[j].Current == null && Match(i, ret.Table[j].Root))
                        ret.Table[j].ReplaceCurrent(analyzer, i);
            }
            foreach (var i in typeDef.Methods)  //Base newslot
            {
                if (!i.IsVirtual || !i.IsNewSlot) continue;
                for (int j = 0; j < ret.Table.Count; j++)
                    if (Match(i, ret.Table[j].Current))
                    {
                        ret.Table[j].Root = i;
                        ret.Table[j].ReplaceCurrent(analyzer, i);
                    }
            }
            foreach (var i in typeDef.Methods)  //Base virtual
            {
                if (!i.IsVirtual) continue;
                for (int j = 0; j < ret.Table.Count; j++)
                    if (i != ret.Table[j].Current && Match(i, ret.Table[j].Current))
                    {
                        ret.Table[j].ReplaceCurrent(analyzer, i);
                    }
            }
            foreach (var i in typeDef.Methods)  //Remaining
            {
                if (!i.IsVirtual) continue;
                bool matched = false;
                for (int j = 0; j < ret.Table.Count; j++)
                    if (Match(i, ret.Table[j].Current))
                    {
                        matched = true;
                        break;
                    }
                if (!matched)
                    ret.Table.Add(new VTableSlot()
                    {
                        Root = i,
                        Current = i
                    });
            }

            tbls[typeDef] = ret;
            return ret;
        }