| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141 |
- from __future__ import annotations
- import sys
- import sysconfig
- from typing import Any, Dict, Final
- from mypy.util import unnamed_function
- PREFIX: Final = "CPyPy_" # Python wrappers
- NATIVE_PREFIX: Final = "CPyDef_" # Native functions etc.
- DUNDER_PREFIX: Final = "CPyDunder_" # Wrappers for exposing dunder methods to the API
- REG_PREFIX: Final = "cpy_r_" # Registers
- STATIC_PREFIX: Final = "CPyStatic_" # Static variables (for literals etc.)
- TYPE_PREFIX: Final = "CPyType_" # Type object struct
- MODULE_PREFIX: Final = "CPyModule_" # Cached modules
- ATTR_PREFIX: Final = "_" # Attributes
- ENV_ATTR_NAME: Final = "__mypyc_env__"
- NEXT_LABEL_ATTR_NAME: Final = "__mypyc_next_label__"
- TEMP_ATTR_NAME: Final = "__mypyc_temp__"
- LAMBDA_NAME: Final = "__mypyc_lambda__"
- PROPSET_PREFIX: Final = "__mypyc_setter__"
- SELF_NAME: Final = "__mypyc_self__"
- # Max short int we accept as a literal is based on 32-bit platforms,
- # so that we can just always emit the same code.
- TOP_LEVEL_NAME: Final = "__top_level__" # Special function representing module top level
- # Maximal number of subclasses for a class to trigger fast path in isinstance() checks.
- FAST_ISINSTANCE_MAX_SUBCLASSES: Final = 2
- # Size of size_t, if configured.
- SIZEOF_SIZE_T_SYSCONFIG: Final = sysconfig.get_config_var("SIZEOF_SIZE_T")
- SIZEOF_SIZE_T: Final = (
- int(SIZEOF_SIZE_T_SYSCONFIG)
- if SIZEOF_SIZE_T_SYSCONFIG is not None
- else (sys.maxsize + 1).bit_length() // 8
- )
- IS_32_BIT_PLATFORM: Final = int(SIZEOF_SIZE_T) == 4
- PLATFORM_SIZE = 4 if IS_32_BIT_PLATFORM else 8
- # Maximum value for a short tagged integer.
- MAX_SHORT_INT: Final = 2 ** (8 * int(SIZEOF_SIZE_T) - 2) - 1
- # Minimum value for a short tagged integer.
- MIN_SHORT_INT: Final = -(MAX_SHORT_INT) - 1
- # Maximum value for a short tagged integer represented as a C integer literal.
- #
- # Note: Assume that the compiled code uses the same bit width as mypyc
- MAX_LITERAL_SHORT_INT: Final = MAX_SHORT_INT
- MIN_LITERAL_SHORT_INT: Final = -MAX_LITERAL_SHORT_INT - 1
- # Description of the C type used to track the definedness of attributes and
- # the presence of argument default values that have types with overlapping
- # error values. Each tracked attribute/argument has a dedicated bit in the
- # relevant bitmap.
- BITMAP_TYPE: Final = "uint32_t"
- BITMAP_BITS: Final = 32
- # Runtime C library files
- RUNTIME_C_FILES: Final = [
- "init.c",
- "getargs.c",
- "getargsfast.c",
- "int_ops.c",
- "float_ops.c",
- "str_ops.c",
- "bytes_ops.c",
- "list_ops.c",
- "dict_ops.c",
- "set_ops.c",
- "tuple_ops.c",
- "exc_ops.c",
- "misc_ops.c",
- "generic_ops.c",
- ]
- JsonDict = Dict[str, Any]
- def shared_lib_name(group_name: str) -> str:
- """Given a group name, return the actual name of its extension module.
- (This just adds a suffix to the final component.)
- """
- return f"{group_name}__mypyc"
- def short_name(name: str) -> str:
- if name.startswith("builtins."):
- return name[9:]
- return name
- def use_fastcall(capi_version: tuple[int, int]) -> bool:
- # We can use METH_FASTCALL for faster wrapper functions on Python 3.7+.
- return capi_version >= (3, 7)
- def use_vectorcall(capi_version: tuple[int, int]) -> bool:
- # We can use vectorcalls to make calls on Python 3.8+ (PEP 590).
- return capi_version >= (3, 8)
- def use_method_vectorcall(capi_version: tuple[int, int]) -> bool:
- # We can use a dedicated vectorcall API to call methods on Python 3.9+.
- return capi_version >= (3, 9)
- def get_id_from_name(name: str, fullname: str, line: int) -> str:
- """Create a unique id for a function.
- This creates an id that is unique for any given function definition, so that it can be used as
- a dictionary key. This is usually the fullname of the function, but this is different in that
- it handles the case where the function is named '_', in which case multiple different functions
- could have the same name."""
- if unnamed_function(name):
- return f"{fullname}.{line}"
- else:
- return fullname
- def short_id_from_name(func_name: str, shortname: str, line: int | None) -> str:
- if unnamed_function(func_name):
- assert line is not None
- partial_name = f"{shortname}.{line}"
- else:
- partial_name = shortname
- return partial_name
- def bitmap_name(index: int) -> str:
- if index == 0:
- return "__bitmap"
- return f"__bitmap{index + 1}"
|