Keep track of mappings from mypy concepts to IR concepts. For example, we keep track of how the mypy TypeInfos of compiled classes map to class IR objects. This state is shared across all modules being compiled in all compilation groups.
| 53 | |
| 54 | |
| 55 | class Mapper: |
| 56 | """Keep track of mappings from mypy concepts to IR concepts. |
| 57 | |
| 58 | For example, we keep track of how the mypy TypeInfos of compiled |
| 59 | classes map to class IR objects. |
| 60 | |
| 61 | This state is shared across all modules being compiled in all |
| 62 | compilation groups. |
| 63 | """ |
| 64 | |
| 65 | def __init__(self, group_map: dict[str, str | None]) -> None: |
| 66 | self.group_map = group_map |
| 67 | self.type_to_ir: dict[TypeInfo, ClassIR] = {} |
| 68 | self.func_to_decl: dict[SymbolNode, FuncDecl] = {} |
| 69 | self.symbol_fullnames: set[str] = set() |
| 70 | # The corresponding generator class that implements a generator/async function |
| 71 | self.fdef_to_generator: dict[FuncDef, ClassIR] = {} |
| 72 | |
| 73 | def type_to_rtype(self, typ: Type | None) -> RType: |
| 74 | if typ is None: |
| 75 | return object_rprimitive |
| 76 | |
| 77 | typ = get_proper_type(typ) |
| 78 | if isinstance(typ, Instance): |
| 79 | if typ.type.is_newtype: |
| 80 | # Unwrap NewType to its base type for rprimitive mapping |
| 81 | assert len(typ.type.bases) == 1, typ.type.bases |
| 82 | return self.type_to_rtype(typ.type.bases[0]) |
| 83 | if typ.type.fullname == "builtins.int": |
| 84 | return int_rprimitive |
| 85 | elif typ.type.fullname == "builtins.float": |
| 86 | return float_rprimitive |
| 87 | elif typ.type.fullname == "builtins.bool": |
| 88 | return bool_rprimitive |
| 89 | elif typ.type.fullname == "builtins.str": |
| 90 | return str_rprimitive |
| 91 | elif typ.type.fullname == "builtins.bytes": |
| 92 | return bytes_rprimitive |
| 93 | elif typ.type.fullname == "builtins.bytearray": |
| 94 | return bytearray_rprimitive |
| 95 | elif typ.type.fullname == "builtins.list": |
| 96 | return list_rprimitive |
| 97 | # Dict subclasses are at least somewhat common and we |
| 98 | # specifically support them, so make sure that dict operations |
| 99 | # get optimized on them. |
| 100 | elif any(cls.fullname == "builtins.dict" for cls in typ.type.mro): |
| 101 | return dict_rprimitive |
| 102 | elif typ.type.fullname == "builtins.set": |
| 103 | return set_rprimitive |
| 104 | elif typ.type.fullname == "builtins.frozenset": |
| 105 | return frozenset_rprimitive |
| 106 | elif typ.type.fullname == "builtins.tuple": |
| 107 | return tuple_rprimitive # Varying-length tuple |
| 108 | elif typ.type.fullname == "builtins.range": |
| 109 | return range_rprimitive |
| 110 | elif typ.type in self.type_to_ir: |
| 111 | inst = RInstance(self.type_to_ir[typ.type]) |
| 112 | # Treat protocols as Union[protocol, object], so that we can do fast |
no outgoing calls
searching dependent graphs…