61 lines
1.9 KiB
Python
61 lines
1.9 KiB
Python
#!/usr/bin/env python3
|
|
"""Guard slice_richcompare C89 locals and allocation/refcount order."""
|
|
import re
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
source = Path(sys.argv[1] if len(sys.argv) > 1 else "cpython/Objects/sliceobject.c")
|
|
match = re.search(
|
|
r"\nslice_richcompare\(PyObject \*v, PyObject \*w, int op\)\s*\{(.*?)\n\}",
|
|
source.read_text(),
|
|
re.S,
|
|
)
|
|
assert match, "slice_richcompare definition not found"
|
|
body = re.sub(r"/\*.*?\*/", "", match.group(1), flags=re.S)
|
|
declarations = re.match(
|
|
r"\s*PyObject \*t1;\s*PyObject \*t2;\s*PyObject \*res;", body
|
|
)
|
|
assert declarations, "slice_richcompare must declare t1, t2, res without initializers at function entry"
|
|
|
|
expected_statements = """
|
|
if (!PySlice_Check(v) || !PySlice_Check(w))
|
|
Py_RETURN_NOTIMPLEMENTED;
|
|
if (v == w) {
|
|
switch (op) {
|
|
case Py_EQ:
|
|
case Py_LE:
|
|
case Py_GE:
|
|
res = Py_True;
|
|
break;
|
|
default:
|
|
res = Py_False;
|
|
break;
|
|
}
|
|
Py_INCREF(res);
|
|
return res;
|
|
}
|
|
t1 = PyTuple_Pack(3,
|
|
((PySliceObject *)v)->start,
|
|
((PySliceObject *)v)->stop,
|
|
((PySliceObject *)v)->step);
|
|
if (t1 == NULL) {
|
|
return NULL;
|
|
}
|
|
t2 = PyTuple_Pack(3,
|
|
((PySliceObject *)w)->start,
|
|
((PySliceObject *)w)->stop,
|
|
((PySliceObject *)w)->step);
|
|
if (t2 == NULL) {
|
|
Py_DECREF(t1);
|
|
return NULL;
|
|
}
|
|
res = PyObject_RichCompare(t1, t2, op);
|
|
Py_DECREF(t1);
|
|
Py_DECREF(t2);
|
|
return res;
|
|
"""
|
|
assert body[declarations.end():].split() == expected_statements.split(), (
|
|
"slice_richcompare must preserve shortcut/allocation/failure/comparison/refcount order without late declarations"
|
|
)
|
|
print("slice_richcompare C89 declarations and allocation/refcount order: PASS")
|