Compute the vtable structure for a class.
(cls: ClassIR)
| 9 | |
| 10 | |
| 11 | def compute_vtable(cls: ClassIR) -> None: |
| 12 | """Compute the vtable structure for a class.""" |
| 13 | if cls.vtable is not None: |
| 14 | return |
| 15 | |
| 16 | if not cls.is_generated: |
| 17 | cls.has_dict = any(x.inherits_python for x in cls.mro) |
| 18 | |
| 19 | for t in cls.mro[1:]: |
| 20 | # Make sure all ancestors are processed first |
| 21 | compute_vtable(t) |
| 22 | # Merge attributes from traits into the class |
| 23 | if not t.is_trait: |
| 24 | continue |
| 25 | for name, typ in t.attributes.items(): |
| 26 | if not cls.is_trait and not any(name in b.attributes for b in cls.base_mro): |
| 27 | cls.attributes[name] = typ |
| 28 | |
| 29 | cls.vtable = {} |
| 30 | if cls.base: |
| 31 | assert cls.base.vtable is not None |
| 32 | cls.vtable.update(cls.base.vtable) |
| 33 | cls.vtable_entries = specialize_parent_vtable(cls, cls.base) |
| 34 | |
| 35 | # Include the vtable from the parent classes, but handle method overrides. |
| 36 | entries = cls.vtable_entries |
| 37 | |
| 38 | all_traits = [t for t in cls.mro if t.is_trait] |
| 39 | |
| 40 | for t in [cls] + [t for t in all_traits if t is not cls]: |
| 41 | for fn in itertools.chain(t.methods.values()): |
| 42 | # TODO: don't generate a new entry when we overload without changing the type |
| 43 | if fn == cls.get_method(fn.name, prefer_method=True): |
| 44 | cls.vtable[fn.name] = len(entries) |
| 45 | # If the class contains a glue method referring to itself, that is a |
| 46 | # shadow glue method to support interpreted subclasses. |
| 47 | shadow = cls.glue_methods.get((cls, fn.name)) |
| 48 | entries.append(VTableMethod(t, fn.name, fn, shadow)) |
| 49 | |
| 50 | # Compute vtables for all of the traits that the class implements |
| 51 | if not cls.is_trait: |
| 52 | for trait in all_traits: |
| 53 | compute_vtable(trait) |
| 54 | cls.trait_vtables[trait] = specialize_parent_vtable(cls, trait) |
| 55 | |
| 56 | |
| 57 | def specialize_parent_vtable(cls: ClassIR, parent: ClassIR) -> VTableEntries: |
searching dependent graphs…