45 lines
2.0 KiB
Python
45 lines
2.0 KiB
Python
#!/usr/bin/env python3
|
|
"""Regress type_new_copy_slots C89 declarations and assignment timing."""
|
|
import re
|
|
from pathlib import Path
|
|
|
|
source = Path("cpython/Objects/typeobject.c").read_text()
|
|
match = re.search(
|
|
r"\nstatic PyObject\*\ntype_new_copy_slots\(type_new_ctx \*ctx, PyObject \*dict\)\n\{(.*?)\n\}",
|
|
source,
|
|
re.S,
|
|
)
|
|
assert match, "type_new_copy_slots definition missing"
|
|
body = re.sub(r"/\*.*?\*/|//[^\n]*", "", match.group(1), flags=re.S)
|
|
assert re.match(
|
|
r"\s*PyObject \*slots = ctx->slots;"
|
|
r"\s*Py_ssize_t nslot = ctx->nslot;"
|
|
r"\s*Py_ssize_t new_nslot = nslot - ctx->add_dict - ctx->add_weak;"
|
|
r"\s*PyObject \*new_slots = PyList_New\(new_nslot\);"
|
|
r"\s*Py_ssize_t j;\s*Py_ssize_t i;\s*PyObject \*tuple;\s*if\b",
|
|
body,
|
|
), "type_new_copy_slots: j, i, tuple must be in the opening declaration block (C89)"
|
|
assert re.search(
|
|
r"if \(new_slots == NULL\)\s*\{\s*return NULL;\s*\}"
|
|
r"\s*j = 0;\s*for \(i = 0; i < nslot; i\+\+\)\s*\{"
|
|
r"\s*PyObject \*slot = PyTuple_GET_ITEM\(slots, i\);\s*int r;\s*if\b",
|
|
body,
|
|
), "preserve allocation check, index initialization and loop; declare r before statements"
|
|
assert re.search(
|
|
r"slot =_Py_Mangle\(ctx->name, slot\);"
|
|
r"\s*if \(!slot\)\s*\{\s*goto error;\s*\}"
|
|
r"\s*PyList_SET_ITEM\(new_slots, j, slot\);"
|
|
r"\s*r = PyDict_Contains\(dict, slot\);\s*if \(r < 0\)",
|
|
body,
|
|
), "preserve mangling, ownership transfer, dict lookup and error-check order"
|
|
assert re.search(
|
|
r"j\+\+;\s*\}\s*assert\(j == new_nslot\);"
|
|
r"\s*if \(PyList_Sort\(new_slots\) == -1\)\s*\{\s*goto error;\s*\}"
|
|
r"\s*tuple = PyList_AsTuple\(new_slots\);\s*Py_DECREF\(new_slots\);"
|
|
r"\s*if \(tuple == NULL\)",
|
|
body,
|
|
), "preserve index increment, sorting, tuple conversion and cleanup order"
|
|
for declaration in (r"Py_ssize_t j\b", r"Py_ssize_t i\b", r"int r\b", r"PyObject \*tuple\b"):
|
|
assert len(re.findall(declaration, body)) == 1, "declare each moved local exactly once"
|
|
print("type_new_copy_slots C89 declarations and assignment timing: PASS")
|