mirror of https://github.com/python/cpython
gh-122943: Move code generation for var-positional parameter to converters (GH-126575)
This commit is contained in:
parent
403410fa1b
commit
ee0746af7d
|
@ -1232,7 +1232,18 @@ class self_converter(CConverter):
|
||||||
|
|
||||||
# Converters for var-positional parameter.
|
# Converters for var-positional parameter.
|
||||||
|
|
||||||
class varpos_tuple_converter(CConverter):
|
class VarPosCConverter(CConverter):
|
||||||
|
format_unit = ''
|
||||||
|
|
||||||
|
def parse_arg(self, argname: str, displayname: str, *, limited_capi: bool) -> str | None:
|
||||||
|
raise AssertionError('should never be called')
|
||||||
|
|
||||||
|
def parse_vararg(self, *, pos_only: int, min_pos: int, max_pos: int,
|
||||||
|
fastcall: bool, limited_capi: bool) -> str:
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|
||||||
|
class varpos_tuple_converter(VarPosCConverter):
|
||||||
type = 'PyObject *'
|
type = 'PyObject *'
|
||||||
format_unit = ''
|
format_unit = ''
|
||||||
c_default = 'NULL'
|
c_default = 'NULL'
|
||||||
|
@ -1240,14 +1251,76 @@ class varpos_tuple_converter(CConverter):
|
||||||
def cleanup(self) -> str:
|
def cleanup(self) -> str:
|
||||||
return f"""Py_XDECREF({self.parser_name});\n"""
|
return f"""Py_XDECREF({self.parser_name});\n"""
|
||||||
|
|
||||||
def parse_arg(self, argname: str, displayname: str, *, limited_capi: bool) -> str | None:
|
def parse_vararg(self, *, pos_only: int, min_pos: int, max_pos: int,
|
||||||
raise AssertionError('should never be called')
|
fastcall: bool, limited_capi: bool) -> str:
|
||||||
|
paramname = self.parser_name
|
||||||
|
if fastcall:
|
||||||
|
if limited_capi:
|
||||||
|
if min(pos_only, min_pos) < max_pos:
|
||||||
|
size = f'Py_MAX(nargs - {max_pos}, 0)'
|
||||||
|
else:
|
||||||
|
size = f'nargs - {max_pos}' if max_pos else 'nargs'
|
||||||
|
return f"""
|
||||||
|
{paramname} = PyTuple_New({size});
|
||||||
|
if (!{paramname}) {{{{
|
||||||
|
goto exit;
|
||||||
|
}}}}
|
||||||
|
for (Py_ssize_t i = {max_pos}; i < nargs; ++i) {{{{
|
||||||
|
PyTuple_SET_ITEM({paramname}, i - {max_pos}, Py_NewRef(args[i]));
|
||||||
|
}}}}
|
||||||
|
"""
|
||||||
|
else:
|
||||||
|
self.add_include('pycore_tuple.h', '_PyTuple_FromArray()')
|
||||||
|
start = f'args + {max_pos}' if max_pos else 'args'
|
||||||
|
size = f'nargs - {max_pos}' if max_pos else 'nargs'
|
||||||
|
if min(pos_only, min_pos) < max_pos:
|
||||||
|
return f"""
|
||||||
|
{paramname} = nargs > {max_pos}
|
||||||
|
? _PyTuple_FromArray({start}, {size})
|
||||||
|
: PyTuple_New(0);
|
||||||
|
if ({paramname} == NULL) {{{{
|
||||||
|
goto exit;
|
||||||
|
}}}}
|
||||||
|
"""
|
||||||
|
else:
|
||||||
|
return f"""
|
||||||
|
{paramname} = _PyTuple_FromArray({start}, {size});
|
||||||
|
if ({paramname} == NULL) {{{{
|
||||||
|
goto exit;
|
||||||
|
}}}}
|
||||||
|
"""
|
||||||
|
else:
|
||||||
|
if max_pos:
|
||||||
|
return f"""
|
||||||
|
{paramname} = PyTuple_GetSlice(args, {max_pos}, PY_SSIZE_T_MAX);
|
||||||
|
if (!{paramname}) {{{{
|
||||||
|
goto exit;
|
||||||
|
}}}}
|
||||||
|
"""
|
||||||
|
else:
|
||||||
|
return f"{paramname} = Py_NewRef(args);\n"
|
||||||
|
|
||||||
class varpos_array_converter(CConverter):
|
|
||||||
|
class varpos_array_converter(VarPosCConverter):
|
||||||
type = 'PyObject * const *'
|
type = 'PyObject * const *'
|
||||||
format_unit = ''
|
|
||||||
length = True
|
length = True
|
||||||
c_ignored_default = ''
|
c_ignored_default = ''
|
||||||
|
|
||||||
def parse_arg(self, argname: str, displayname: str, *, limited_capi: bool) -> str | None:
|
def parse_vararg(self, *, pos_only: int, min_pos: int, max_pos: int,
|
||||||
raise AssertionError('should never be called')
|
fastcall: bool, limited_capi: bool) -> str:
|
||||||
|
paramname = self.parser_name
|
||||||
|
if not fastcall:
|
||||||
|
self.add_include('pycore_tuple.h', '_PyTuple_ITEMS()')
|
||||||
|
start = 'args' if fastcall else '_PyTuple_ITEMS(args)'
|
||||||
|
size = 'nargs' if fastcall else 'PyTuple_GET_SIZE(args)'
|
||||||
|
if max_pos:
|
||||||
|
if min(pos_only, min_pos) < max_pos:
|
||||||
|
start = f'{size} > {max_pos} ? {start} + {max_pos} : {start}'
|
||||||
|
size = f'Py_MAX(0, {size} - {max_pos})'
|
||||||
|
else:
|
||||||
|
start = f'{start} + {max_pos}'
|
||||||
|
size = f'{size} - {max_pos}'
|
||||||
|
return f"""
|
||||||
|
{paramname} = {start};
|
||||||
|
{self.length_name} = {size};
|
||||||
|
"""
|
||||||
|
|
|
@ -452,71 +452,13 @@ class ParseArgsCodeGen:
|
||||||
|
|
||||||
def _parse_vararg(self) -> str:
|
def _parse_vararg(self) -> str:
|
||||||
assert self.varpos is not None
|
assert self.varpos is not None
|
||||||
paramname = self.varpos.converter.parser_name
|
c = self.varpos.converter
|
||||||
if self.varpos.converter.length:
|
assert isinstance(c, libclinic.converters.VarPosCConverter)
|
||||||
if not self.fastcall:
|
return c.parse_vararg(pos_only=self.pos_only,
|
||||||
self.codegen.add_include('pycore_tuple.h',
|
min_pos=self.min_pos,
|
||||||
'_PyTuple_ITEMS()')
|
max_pos=self.max_pos,
|
||||||
start = 'args' if self.fastcall else '_PyTuple_ITEMS(args)'
|
fastcall=self.fastcall,
|
||||||
size = 'nargs' if self.fastcall else 'PyTuple_GET_SIZE(args)'
|
limited_capi=self.limited_capi)
|
||||||
if self.max_pos:
|
|
||||||
if min(self.pos_only, self.min_pos) < self.max_pos:
|
|
||||||
start = f'{size} > {self.max_pos} ? {start} + {self.max_pos} : {start}'
|
|
||||||
size = f'Py_MAX(0, {size} - {self.max_pos})'
|
|
||||||
else:
|
|
||||||
start = f'{start} + {self.max_pos}'
|
|
||||||
size = f'{size} - {self.max_pos}'
|
|
||||||
return f"""
|
|
||||||
{paramname} = {start};
|
|
||||||
{self.varpos.converter.length_name} = {size};
|
|
||||||
"""
|
|
||||||
|
|
||||||
if self.fastcall:
|
|
||||||
if self.limited_capi:
|
|
||||||
if min(self.pos_only, self.min_pos) < self.max_pos:
|
|
||||||
size = f'Py_MAX(nargs - {self.max_pos}, 0)'
|
|
||||||
else:
|
|
||||||
size = f'nargs - {self.max_pos}' if self.max_pos else 'nargs'
|
|
||||||
return f"""
|
|
||||||
{paramname} = PyTuple_New({size});
|
|
||||||
if (!{paramname}) {{{{
|
|
||||||
goto exit;
|
|
||||||
}}}}
|
|
||||||
for (Py_ssize_t i = {self.max_pos}; i < nargs; ++i) {{{{
|
|
||||||
PyTuple_SET_ITEM({paramname}, i - {self.max_pos}, Py_NewRef(args[i]));
|
|
||||||
}}}}
|
|
||||||
"""
|
|
||||||
else:
|
|
||||||
self.codegen.add_include('pycore_tuple.h',
|
|
||||||
'_PyTuple_FromArray()')
|
|
||||||
if min(self.pos_only, self.min_pos) < self.max_pos:
|
|
||||||
return f"""
|
|
||||||
{paramname} = nargs > {self.max_pos}
|
|
||||||
? _PyTuple_FromArray(args + {self.max_pos}, nargs - {self.max_pos})
|
|
||||||
: PyTuple_New(0);
|
|
||||||
if ({paramname} == NULL) {{{{
|
|
||||||
goto exit;
|
|
||||||
}}}}
|
|
||||||
"""
|
|
||||||
else:
|
|
||||||
start = f'args + {self.max_pos}' if self.max_pos else 'args'
|
|
||||||
size = f'nargs - {self.max_pos}' if self.max_pos else 'nargs'
|
|
||||||
return f"""
|
|
||||||
{paramname} = _PyTuple_FromArray({start}, {size});
|
|
||||||
if ({paramname} == NULL) {{{{
|
|
||||||
goto exit;
|
|
||||||
}}}}
|
|
||||||
"""
|
|
||||||
else:
|
|
||||||
if self.max_pos:
|
|
||||||
return f"""
|
|
||||||
{paramname} = PyTuple_GetSlice(args, {self.max_pos}, PY_SSIZE_T_MAX);
|
|
||||||
if (!{paramname}) {{{{
|
|
||||||
goto exit;
|
|
||||||
}}}}
|
|
||||||
"""
|
|
||||||
else:
|
|
||||||
return f"{paramname} = Py_NewRef(args);\n"
|
|
||||||
|
|
||||||
def parse_pos_only(self) -> None:
|
def parse_pos_only(self) -> None:
|
||||||
if self.fastcall:
|
if self.fastcall:
|
||||||
|
@ -839,7 +781,10 @@ class ParseArgsCodeGen:
|
||||||
def copy_includes(self) -> None:
|
def copy_includes(self) -> None:
|
||||||
# Copy includes from parameters to Clinic after parse_arg()
|
# Copy includes from parameters to Clinic after parse_arg()
|
||||||
# has been called above.
|
# has been called above.
|
||||||
for converter in self.converters:
|
converters = self.converters
|
||||||
|
if self.varpos:
|
||||||
|
converters = converters + [self.varpos.converter]
|
||||||
|
for converter in converters:
|
||||||
for include in converter.get_includes():
|
for include in converter.get_includes():
|
||||||
self.codegen.add_include(
|
self.codegen.add_include(
|
||||||
include.filename,
|
include.filename,
|
||||||
|
|
Loading…
Reference in New Issue