1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
|
from __future__ import annotations
import sys
import sysconfig
from typing import Any, 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
TYPE_VAR_PREFIX: Final = "CPyTypeVar_" # Type variables when using new-style Python 3.12 syntax
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",
"pythonsupport.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_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}"
|