137 lines
4.1 KiB
Python
137 lines
4.1 KiB
Python
|
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_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}"
|