mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-29 16:20:11 -04:00
interrogate: refactor default argument handling
This commit is contained in:
parent
f29643dd14
commit
a9d6d3be46
@ -25,6 +25,7 @@
|
|||||||
#include "cppFunctionGroup.h"
|
#include "cppFunctionGroup.h"
|
||||||
#include "cppFunctionType.h"
|
#include "cppFunctionType.h"
|
||||||
#include "cppClosureType.h"
|
#include "cppClosureType.h"
|
||||||
|
#include "cppReferenceType.h"
|
||||||
#include "cppStructType.h"
|
#include "cppStructType.h"
|
||||||
#include "cppBison.h"
|
#include "cppBison.h"
|
||||||
#include "pdtoa.h"
|
#include "pdtoa.h"
|
||||||
@ -260,12 +261,12 @@ CPPExpression(CPPIdentifier *ident, CPPScope *current_scope,
|
|||||||
_u._variable = inst;
|
_u._variable = inst;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
CPPFunctionGroup *fgroup = decl->as_function_group();
|
/*CPPFunctionGroup *fgroup = decl->as_function_group();
|
||||||
if (fgroup != nullptr) {
|
if (fgroup != nullptr) {
|
||||||
_type = T_function;
|
_type = T_function;
|
||||||
_u._fgroup = fgroup;
|
_u._fgroup = fgroup;
|
||||||
return;
|
return;
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
_type = T_unknown_ident;
|
_type = T_unknown_ident;
|
||||||
@ -1232,6 +1233,61 @@ determine_type() const {
|
|||||||
return nullptr; // Compiler kludge; can't get here.
|
return nullptr; // Compiler kludge; can't get here.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if this is an lvalue expression.
|
||||||
|
*/
|
||||||
|
bool CPPExpression::
|
||||||
|
is_lvalue() const {
|
||||||
|
switch (_type) {
|
||||||
|
case T_variable:
|
||||||
|
case T_function:
|
||||||
|
case T_unknown_ident:
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case T_typecast:
|
||||||
|
case T_static_cast:
|
||||||
|
case T_dynamic_cast:
|
||||||
|
case T_const_cast:
|
||||||
|
case T_reinterpret_cast:
|
||||||
|
{
|
||||||
|
CPPReferenceType *ref_type = _u._typecast._to->as_reference_type();
|
||||||
|
return ref_type != nullptr && ref_type->_value_category == CPPReferenceType::VC_lvalue;
|
||||||
|
}
|
||||||
|
|
||||||
|
case T_unary_operation:
|
||||||
|
if (_u._op._operator == 'f') {
|
||||||
|
// A function returning an lvalue reference.
|
||||||
|
CPPType *return_type = determine_type();
|
||||||
|
if (return_type != nullptr) {
|
||||||
|
CPPReferenceType *ref_type = return_type->as_reference_type();
|
||||||
|
return ref_type != nullptr && ref_type->_value_category == CPPReferenceType::VC_lvalue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return _u._op._operator == PLUSPLUS
|
||||||
|
|| _u._op._operator == MINUSMINUS
|
||||||
|
|| _u._op._operator == '*';
|
||||||
|
|
||||||
|
case T_binary_operation:
|
||||||
|
if (_u._op._operator == ',') {
|
||||||
|
CPPReferenceType *ref_type = _u._op._op2->as_reference_type();
|
||||||
|
return ref_type != nullptr && ref_type->_value_category == CPPReferenceType::VC_lvalue;
|
||||||
|
}
|
||||||
|
return (_u._op._operator == POINTSAT || _u._op._operator == ',');
|
||||||
|
|
||||||
|
case T_trinary_operation:
|
||||||
|
return _u._op._op2->is_lvalue() && _u._op._op3->is_lvalue();
|
||||||
|
|
||||||
|
case T_literal:
|
||||||
|
case T_raw_literal:
|
||||||
|
return true;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if this declaration is an actual, factual declaration, or
|
* Returns true if this declaration is an actual, factual declaration, or
|
||||||
* false if some part of the declaration depends on a template parameter which
|
* false if some part of the declaration depends on a template parameter which
|
||||||
|
@ -133,6 +133,7 @@ public:
|
|||||||
|
|
||||||
Result evaluate() const;
|
Result evaluate() const;
|
||||||
CPPType *determine_type() const;
|
CPPType *determine_type() const;
|
||||||
|
bool is_lvalue() const;
|
||||||
bool is_tbd() const;
|
bool is_tbd() const;
|
||||||
|
|
||||||
virtual bool is_fully_specified() const;
|
virtual bool is_fully_specified() const;
|
||||||
|
@ -4078,13 +4078,9 @@ write_coerce_constructor(ostream &out, Object *obj, bool is_const) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Special case optimization: if the last map is a subset of the map before
|
* Special case optimization: if the last map is a subset of the map before
|
||||||
* it, and the last parameter is only a simple parameter type (that we have
|
* it, we can merge the cases. When this happens, we can make use of a
|
||||||
* special default argument handling for), we can merge the cases. When this
|
* special feature of PyArg_ParseTuple for handling of these last few default
|
||||||
* happens, we can make use of a special feature of PyArg_ParseTuple for
|
* arguments.
|
||||||
* handling of these last few default arguments. This doesn't work well for
|
|
||||||
* all types of default expressions, though, hence the need for this elaborate
|
|
||||||
* checking mechanism down here, which goes in parallel with the actual
|
|
||||||
* optional arg handling logic in write_function_instance.
|
|
||||||
*
|
*
|
||||||
* This isn't just to help reduce the amount of generated code; it also
|
* This isn't just to help reduce the amount of generated code; it also
|
||||||
* enables arbitrary selection of keyword arguments for many functions, ie.
|
* enables arbitrary selection of keyword arguments for many functions, ie.
|
||||||
@ -4095,14 +4091,6 @@ write_coerce_constructor(ostream &out, Object *obj, bool is_const) {
|
|||||||
* Thanks to this mechanism, we can call it like so:
|
* Thanks to this mechanism, we can call it like so:
|
||||||
*
|
*
|
||||||
* func(c=True, d=".")
|
* func(c=True, d=".")
|
||||||
*
|
|
||||||
* The return value is the minimum of the number of maximum arguments.
|
|
||||||
*
|
|
||||||
* Sorry, let me try that again: it returns the largest number of arguments
|
|
||||||
* for which the overloads will be separated out rather than handled via the
|
|
||||||
* special default handling mechanism. Or something.
|
|
||||||
*
|
|
||||||
* Please don't hate me.
|
|
||||||
*/
|
*/
|
||||||
int InterfaceMakerPythonNative::
|
int InterfaceMakerPythonNative::
|
||||||
collapse_default_remaps(std::map<int, std::set<FunctionRemap *> > &map_sets,
|
collapse_default_remaps(std::map<int, std::set<FunctionRemap *> > &map_sets,
|
||||||
@ -4118,70 +4106,8 @@ collapse_default_remaps(std::map<int, std::set<FunctionRemap *> > &map_sets,
|
|||||||
if (std::includes(rmi_next->second.begin(), rmi_next->second.end(),
|
if (std::includes(rmi_next->second.begin(), rmi_next->second.end(),
|
||||||
rmi->second.begin(), rmi->second.end())) {
|
rmi->second.begin(), rmi->second.end())) {
|
||||||
|
|
||||||
// Check if the nth argument is something we can easily create a default
|
|
||||||
// for.
|
|
||||||
std::set<FunctionRemap *>::iterator sii;
|
|
||||||
for (sii = rmi->second.begin(); sii != rmi->second.end(); ++sii) {
|
|
||||||
FunctionRemap *remap = (*sii);
|
|
||||||
size_t pn = (size_t)rmi->first;
|
|
||||||
if (!remap->_has_this || remap->_type == FunctionRemap::T_constructor) {
|
|
||||||
--pn;
|
|
||||||
}
|
|
||||||
nassertd(pn < remap->_parameters.size()) goto abort_iteration;
|
|
||||||
|
|
||||||
ParameterRemap *param = remap->_parameters[pn]._remap;
|
|
||||||
CPPType *type = param->get_new_type();
|
|
||||||
|
|
||||||
if (param->new_type_is_atomic_string()) {
|
|
||||||
CPPType *orig_type = param->get_orig_type();
|
|
||||||
if (TypeManager::is_char_pointer(orig_type)) {
|
|
||||||
} else if (TypeManager::is_wchar_pointer(orig_type)) {
|
|
||||||
goto abort_iteration;
|
|
||||||
} else if (TypeManager::is_wstring(orig_type)) {
|
|
||||||
goto abort_iteration;
|
|
||||||
} else if (TypeManager::is_const_ptr_to_basic_string_wchar(orig_type)) {
|
|
||||||
goto abort_iteration;
|
|
||||||
} else {
|
|
||||||
// Regular strings are OK if the default argument is a string
|
|
||||||
// literal or the default string constructor, since those are
|
|
||||||
// trivial to handle. This actually covers almost all of the
|
|
||||||
// cases of default string args.
|
|
||||||
CPPExpression::Type expr_type = param->get_default_value()->_type;
|
|
||||||
if (expr_type != CPPExpression::T_default_construct &&
|
|
||||||
expr_type != CPPExpression::T_string) {
|
|
||||||
goto abort_iteration;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (TypeManager::is_integer(type)) {
|
|
||||||
} else if (TypeManager::is_float(type)) {
|
|
||||||
} else if (TypeManager::is_const_char_pointer(type)) {
|
|
||||||
} else if (TypeManager::is_pointer_to_PyTypeObject(type)) {
|
|
||||||
} else if (TypeManager::is_pointer_to_PyStringObject(type)) {
|
|
||||||
} else if (TypeManager::is_pointer_to_PyUnicodeObject(type)) {
|
|
||||||
} else if (TypeManager::is_pointer_to_PyObject(type)) {
|
|
||||||
} else if (TypeManager::is_pointer_to_Py_buffer(type)) {
|
|
||||||
goto abort_iteration;
|
|
||||||
} else if (TypeManager::is_pointer_to_simple(type)) {
|
|
||||||
goto abort_iteration;
|
|
||||||
} else if (TypeManager::is_pointer(type)) {
|
|
||||||
// I'm allowing other pointer types, but only if the expression
|
|
||||||
// happens to evaluate to a numeric constant (which will likely only
|
|
||||||
// be NULL). There are too many issues to resolve right now with
|
|
||||||
// allowing more complex default expressions, including issues in
|
|
||||||
// the C++ parser (but the reader is welcome to give it a try!)
|
|
||||||
CPPExpression::Result res = param->get_default_value()->evaluate();
|
|
||||||
if (res._type != CPPExpression::RT_integer &&
|
|
||||||
res._type != CPPExpression::RT_pointer) {
|
|
||||||
goto abort_iteration;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
goto abort_iteration;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// rmi_next has a superset of the remaps in rmi, and we are going to
|
// rmi_next has a superset of the remaps in rmi, and we are going to
|
||||||
// erase rmi_next, so put all the remaps in rmi. rmi->second =
|
// erase rmi_next, so put all the remaps in rmi.
|
||||||
// rmi_next->second;
|
|
||||||
|
|
||||||
max_required_args = rmi_next->first;
|
max_required_args = rmi_next->first;
|
||||||
rmi = rmi_next;
|
rmi = rmi_next;
|
||||||
@ -4191,7 +4117,6 @@ collapse_default_remaps(std::map<int, std::set<FunctionRemap *> > &map_sets,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
abort_iteration:
|
|
||||||
// Now erase the other remap sets. Reverse iterators are weird, we first
|
// Now erase the other remap sets. Reverse iterators are weird, we first
|
||||||
// need to get forward iterators and decrement them by one.
|
// need to get forward iterators and decrement them by one.
|
||||||
std::map<int, std::set<FunctionRemap *> >::iterator erase_begin, erase_end;
|
std::map<int, std::set<FunctionRemap *> >::iterator erase_begin, erase_end;
|
||||||
@ -4738,6 +4663,7 @@ write_function_instance(ostream &out, FunctionRemap *remap,
|
|||||||
"(" + orig_type->get_local_name(&parser) + ")" + param_name;
|
"(" + orig_type->get_local_name(&parser) + ")" + param_name;
|
||||||
|
|
||||||
string default_expr;
|
string default_expr;
|
||||||
|
const char *null_assign = "";
|
||||||
|
|
||||||
if (is_optional) {
|
if (is_optional) {
|
||||||
// If this is an optional argument, PyArg_ParseTuple will leave the
|
// If this is an optional argument, PyArg_ParseTuple will leave the
|
||||||
@ -4747,6 +4673,7 @@ write_function_instance(ostream &out, FunctionRemap *remap,
|
|||||||
default_expr_str << " = ";
|
default_expr_str << " = ";
|
||||||
default_value->output(default_expr_str, 0, &parser, false);
|
default_value->output(default_expr_str, 0, &parser, false);
|
||||||
default_expr = default_expr_str.str();
|
default_expr = default_expr_str.str();
|
||||||
|
null_assign = " = nullptr";
|
||||||
|
|
||||||
// We should only ever have to consider optional arguments for functions
|
// We should only ever have to consider optional arguments for functions
|
||||||
// taking a variable number of arguments.
|
// taking a variable number of arguments.
|
||||||
@ -4776,23 +4703,40 @@ write_function_instance(ostream &out, FunctionRemap *remap,
|
|||||||
expected_params += "str";
|
expected_params += "str";
|
||||||
|
|
||||||
} else if (TypeManager::is_wchar_pointer(orig_type)) {
|
} else if (TypeManager::is_wchar_pointer(orig_type)) {
|
||||||
indent(out, indent_level) << "#if PY_VERSION_HEX >= 0x03020000\n";
|
out << "#if PY_VERSION_HEX >= 0x03020000\n";
|
||||||
indent(out, indent_level) << "PyObject *" << param_name << ";\n";
|
indent(out, indent_level) << "PyObject *" << param_name << null_assign << ";\n";
|
||||||
indent(out, indent_level) << "#else\n";
|
out << "#else\n";
|
||||||
indent(out, indent_level) << "PyUnicodeObject *" << param_name << ";\n";
|
indent(out, indent_level) << "PyUnicodeObject *" << param_name << null_assign << ";\n";
|
||||||
indent(out, indent_level) << "#endif\n";
|
out << "#endif\n";
|
||||||
format_specifiers += "U";
|
format_specifiers += "U";
|
||||||
parameter_list += ", &" + param_name;
|
parameter_list += ", &" + param_name;
|
||||||
|
|
||||||
extra_convert
|
if (is_optional) {
|
||||||
<< "#if PY_VERSION_HEX >= 0x03030000\n"
|
extra_convert
|
||||||
<< "wchar_t *" << param_name << "_str = PyUnicode_AsWideCharString(" << param_name << ", nullptr);\n"
|
<< "wchar_t *" << param_name << "_str;\n"
|
||||||
<< "#else"
|
<< "if (" << param_name << " != nullptr) {\n"
|
||||||
<< "Py_ssize_t " << param_name << "_len = PyUnicode_GET_SIZE(" << param_name << ");\n"
|
<< "#if PY_VERSION_HEX >= 0x03030000\n"
|
||||||
<< "wchar_t *" << param_name << "_str = (wchar_t *)alloca(sizeof(wchar_t) * (" + param_name + "_len + 1));\n"
|
<< " " << param_name << "_str = PyUnicode_AsWideCharString(" << param_name << ", nullptr);\n"
|
||||||
<< "PyUnicode_AsWideChar(" << param_name << ", " << param_name << "_str, " << param_name << "_len);\n"
|
<< "#else"
|
||||||
<< param_name << "_str[" << param_name << "_len] = 0;\n"
|
<< "Py_ssize_t " << param_name << "_len = PyUnicode_GET_SIZE(" << param_name << ");\n"
|
||||||
<< "#endif\n";
|
<< " " << param_name << "_str = (wchar_t *)alloca(sizeof(wchar_t) * (" + param_name + "_len + 1));\n"
|
||||||
|
<< "PyUnicode_AsWideChar(" << param_name << ", " << param_name << "_str, " << param_name << "_len);\n"
|
||||||
|
<< param_name << "_str[" << param_name << "_len] = 0;\n"
|
||||||
|
<< "#endif\n"
|
||||||
|
<< "} else {\n"
|
||||||
|
<< " " << param_name << "_str" << default_expr << ";\n"
|
||||||
|
<< "}\n";
|
||||||
|
} else {
|
||||||
|
extra_convert
|
||||||
|
<< "#if PY_VERSION_HEX >= 0x03030000\n"
|
||||||
|
<< "wchar_t *" << param_name << "_str = PyUnicode_AsWideCharString(" << param_name << ", nullptr);\n"
|
||||||
|
<< "#else"
|
||||||
|
<< "Py_ssize_t " << param_name << "_len = PyUnicode_GET_SIZE(" << param_name << ");\n"
|
||||||
|
<< "wchar_t *" << param_name << "_str = (wchar_t *)alloca(sizeof(wchar_t) * (" + param_name + "_len + 1));\n"
|
||||||
|
<< "PyUnicode_AsWideChar(" << param_name << ", " << param_name << "_str, " << param_name << "_len);\n"
|
||||||
|
<< param_name << "_str[" << param_name << "_len] = 0;\n"
|
||||||
|
<< "#endif\n";
|
||||||
|
}
|
||||||
|
|
||||||
pexpr_string = param_name + "_str";
|
pexpr_string = param_name + "_str";
|
||||||
|
|
||||||
@ -4803,56 +4747,48 @@ write_function_instance(ostream &out, FunctionRemap *remap,
|
|||||||
|
|
||||||
expected_params += "unicode";
|
expected_params += "unicode";
|
||||||
|
|
||||||
} else if (TypeManager::is_wstring(orig_type)) {
|
} else if (TypeManager::is_wstring(orig_type) ||
|
||||||
indent(out, indent_level) << "#if PY_VERSION_HEX >= 0x03020000\n";
|
TypeManager::is_const_ptr_to_basic_string_wchar(orig_type)) {
|
||||||
indent(out, indent_level) << "PyObject *" << param_name << ";\n";
|
out << "#if PY_VERSION_HEX >= 0x03020000\n";
|
||||||
indent(out, indent_level) << "#else\n";
|
indent(out, indent_level) << "PyObject *" << param_name << null_assign << ";\n";
|
||||||
indent(out, indent_level) << "PyUnicodeObject *" << param_name << ";\n";
|
out << "#else\n";
|
||||||
indent(out, indent_level) << "#endif\n";
|
indent(out, indent_level) << "PyUnicodeObject *" << param_name << null_assign << ";\n";
|
||||||
|
out << "#endif\n";
|
||||||
format_specifiers += "U";
|
format_specifiers += "U";
|
||||||
parameter_list += ", &" + param_name;
|
parameter_list += ", &" + param_name;
|
||||||
|
|
||||||
extra_convert
|
if (is_optional) {
|
||||||
<< "#if PY_VERSION_HEX >= 0x03030000\n"
|
extra_convert
|
||||||
<< "Py_ssize_t " << param_name << "_len;\n"
|
<< "Py_ssize_t " << param_name << "_len;\n"
|
||||||
<< "wchar_t *" << param_name << "_str = PyUnicode_AsWideCharString("
|
<< "wchar_t *" << param_name << "_str;\n"
|
||||||
<< param_name << ", &" << param_name << "_len);\n"
|
<< "std::wstring " << param_name << "_wstr;\n"
|
||||||
<< "#else\n"
|
<< "if (" << param_name << " != nullptr) {\n"
|
||||||
<< "Py_ssize_t " << param_name << "_len = PyUnicode_GET_SIZE(" << param_name << ");\n"
|
<< "#if PY_VERSION_HEX >= 0x03030000\n"
|
||||||
<< "wchar_t *" << param_name << "_str = (wchar_t *)alloca(sizeof(wchar_t) * (" + param_name + "_len + 1));\n"
|
<< " " << param_name << "_str = PyUnicode_AsWideCharString("
|
||||||
<< "PyUnicode_AsWideChar(" << param_name << ", " << param_name << "_str, " << param_name << "_len);\n"
|
<< param_name << ", &" << param_name << "_len);\n"
|
||||||
<< "#endif\n";
|
<< "#else\n"
|
||||||
|
<< " " << param_name << "_len = PyUnicode_GET_SIZE(" << param_name << ");\n"
|
||||||
pexpr_string = param_name + "_str, " + param_name + "_len";
|
<< " " << param_name << "_str = (wchar_t *)alloca(sizeof(wchar_t) * (" + param_name + "_len + 1));\n"
|
||||||
|
<< "PyUnicode_AsWideChar(" << param_name << ", " << param_name << "_str, " << param_name << "_len);\n"
|
||||||
extra_cleanup
|
<< "#endif\n"
|
||||||
<< "#if PY_VERSION_HEX >= 0x03030000\n"
|
<< " " << param_name << "_wstr.assign(" << param_name << "_str, " << param_name << "_len);\n"
|
||||||
<< "PyMem_Free(" << param_name << "_str);\n"
|
<< "} else {\n"
|
||||||
<< "#endif\n";
|
<< " " << param_name << "_wstr" << default_expr << ";\n"
|
||||||
|
<< "}\n";
|
||||||
expected_params += "unicode";
|
pexpr_string = "std::move(" + param_name + "_wstr)";
|
||||||
|
} else {
|
||||||
} else if (TypeManager::is_const_ptr_to_basic_string_wchar(orig_type)) {
|
extra_convert
|
||||||
indent(out, indent_level) << "#if PY_VERSION_HEX >= 0x03020000\n";
|
<< "#if PY_VERSION_HEX >= 0x03030000\n"
|
||||||
indent(out, indent_level) << "PyObject *" << param_name << ";\n";
|
<< "Py_ssize_t " << param_name << "_len;\n"
|
||||||
indent(out, indent_level) << "#else\n";
|
<< "wchar_t *" << param_name << "_str = PyUnicode_AsWideCharString("
|
||||||
indent(out, indent_level) << "PyUnicodeObject *" << param_name << ";\n";
|
<< param_name << ", &" << param_name << "_len);\n"
|
||||||
indent(out, indent_level) << "#endif\n";
|
<< "#else\n"
|
||||||
format_specifiers += "U";
|
<< "Py_ssize_t " << param_name << "_len = PyUnicode_GET_SIZE(" << param_name << ");\n"
|
||||||
parameter_list += ", &" + param_name;
|
<< "wchar_t *" << param_name << "_str = (wchar_t *)alloca(sizeof(wchar_t) * (" + param_name + "_len + 1));\n"
|
||||||
|
<< "PyUnicode_AsWideChar(" << param_name << ", " << param_name << "_str, " << param_name << "_len);\n"
|
||||||
extra_convert
|
<< "#endif\n";
|
||||||
<< "#if PY_VERSION_HEX >= 0x03030000\n"
|
pexpr_string = param_name + "_str, " + param_name + "_len";
|
||||||
<< "Py_ssize_t " << param_name << "_len;\n"
|
}
|
||||||
<< "wchar_t *" << param_name << "_str = PyUnicode_AsWideCharString("
|
|
||||||
<< param_name << ", &" << param_name << "_len);\n"
|
|
||||||
<< "#else\n"
|
|
||||||
<< "Py_ssize_t " << param_name << "_len = PyUnicode_GET_SIZE(" << param_name << ");\n"
|
|
||||||
<< "wchar_t *" << param_name << "_str = (wchar_t *)alloca(sizeof(wchar_t) * (" + param_name + "_len + 1));\n"
|
|
||||||
<< "PyUnicode_AsWideChar(" << param_name << ", " << param_name << "_str, " << param_name << "_len);\n"
|
|
||||||
<< "#endif\n";
|
|
||||||
|
|
||||||
pexpr_string = param_name + "_str, " + param_name + "_len";
|
|
||||||
|
|
||||||
extra_cleanup
|
extra_cleanup
|
||||||
<< "#if PY_VERSION_HEX >= 0x03030000\n"
|
<< "#if PY_VERSION_HEX >= 0x03030000\n"
|
||||||
@ -5019,11 +4955,11 @@ write_function_instance(ostream &out, FunctionRemap *remap,
|
|||||||
only_pyobjects = false;
|
only_pyobjects = false;
|
||||||
|
|
||||||
} else if (TypeManager::is_wchar(type)) {
|
} else if (TypeManager::is_wchar(type)) {
|
||||||
indent(out, indent_level) << "#if PY_VERSION_HEX >= 0x03020000\n";
|
out << "#if PY_VERSION_HEX >= 0x03020000\n";
|
||||||
indent(out, indent_level) << "PyObject *" << param_name << ";\n";
|
indent(out, indent_level) << "PyObject *" << param_name << ";\n";
|
||||||
indent(out, indent_level) << "#else\n";
|
out << "#else\n";
|
||||||
indent(out, indent_level) << "PyUnicodeObject *" << param_name << ";\n";
|
indent(out, indent_level) << "PyUnicodeObject *" << param_name << ";\n";
|
||||||
indent(out, indent_level) << "#endif\n";
|
out << "#endif\n";
|
||||||
format_specifiers += "U";
|
format_specifiers += "U";
|
||||||
parameter_list += ", &" + param_name;
|
parameter_list += ", &" + param_name;
|
||||||
|
|
||||||
@ -5348,17 +5284,36 @@ write_function_instance(ostream &out, FunctionRemap *remap,
|
|||||||
if (args_type == AT_single_arg) {
|
if (args_type == AT_single_arg) {
|
||||||
param_name = "arg";
|
param_name = "arg";
|
||||||
} else {
|
} else {
|
||||||
indent(out, indent_level) << "PyObject *" << param_name << ";\n";
|
indent(out, indent_level) << "PyObject *" << param_name << null_assign << ";\n";
|
||||||
format_specifiers += "O";
|
format_specifiers += "O";
|
||||||
parameter_list += ", &" + param_name;
|
parameter_list += ", &" + param_name;
|
||||||
}
|
}
|
||||||
indent(out, indent_level) << "Py_buffer " << param_name << "_view;\n";
|
indent(out, indent_level) << "Py_buffer " << param_name << "_view;\n";
|
||||||
|
|
||||||
extra_param_check << " && PyObject_GetBuffer("
|
if (is_optional) {
|
||||||
<< param_name << ", &"
|
indent(out, indent_level) << "Py_buffer *" << param_name << "_viewp;\n";
|
||||||
<< param_name << "_view, PyBUF_FULL) == 0";
|
|
||||||
pexpr_string = "&" + param_name + "_view";
|
extra_convert
|
||||||
extra_cleanup << "PyBuffer_Release(&" << param_name << "_view);\n";
|
<< "bool " << param_name << "_success;\n"
|
||||||
|
<< "if (" << param_name << " != nullptr) {\n"
|
||||||
|
<< " " << param_name << "_success = (PyObject_GetBuffer("
|
||||||
|
<< param_name << ", &" << param_name << "_view, PyBUF_FULL) == 0);\n"
|
||||||
|
<< " " << param_name << "_viewp = &" << param_name << "_view;\n"
|
||||||
|
<< "} else {\n"
|
||||||
|
<< " " << param_name << "_viewp" << default_expr << ";\n"
|
||||||
|
<< " " << param_name << "_success = true;\n"
|
||||||
|
<< "}\n";
|
||||||
|
|
||||||
|
extra_param_check << " && " << param_name << "_success";
|
||||||
|
pexpr_string = param_name + "_viewp";
|
||||||
|
extra_cleanup << "if (" << param_name << " != nullptr) PyBuffer_Release(&" << param_name << "_view);\n";
|
||||||
|
} else {
|
||||||
|
extra_param_check << " && PyObject_GetBuffer("
|
||||||
|
<< param_name << ", &"
|
||||||
|
<< param_name << "_view, PyBUF_FULL) == 0";
|
||||||
|
pexpr_string = "&" + param_name + "_view";
|
||||||
|
extra_cleanup << "PyBuffer_Release(&" << param_name << "_view);\n";
|
||||||
|
}
|
||||||
expected_params += "buffer";
|
expected_params += "buffer";
|
||||||
may_raise_typeerror = true;
|
may_raise_typeerror = true;
|
||||||
clear_error = true;
|
clear_error = true;
|
||||||
@ -5367,7 +5322,7 @@ write_function_instance(ostream &out, FunctionRemap *remap,
|
|||||||
if (args_type == AT_single_arg) {
|
if (args_type == AT_single_arg) {
|
||||||
param_name = "arg";
|
param_name = "arg";
|
||||||
} else {
|
} else {
|
||||||
indent(out, indent_level) << "PyObject *" << param_name << ";\n";
|
indent(out, indent_level) << "PyObject *" << param_name << null_assign << ";\n";
|
||||||
format_specifiers += "O";
|
format_specifiers += "O";
|
||||||
parameter_list += ", &" + param_name;
|
parameter_list += ", &" + param_name;
|
||||||
}
|
}
|
||||||
@ -5496,18 +5451,15 @@ write_function_instance(ostream &out, FunctionRemap *remap,
|
|||||||
if (args_type == AT_single_arg) {
|
if (args_type == AT_single_arg) {
|
||||||
param_name = "arg";
|
param_name = "arg";
|
||||||
} else {
|
} else {
|
||||||
indent(out, indent_level) << "PyObject *" << param_name;
|
indent(out, indent_level) << "PyObject *" << param_name << null_assign << ";\n";
|
||||||
if (is_optional) {
|
|
||||||
out << " = nullptr";
|
|
||||||
}
|
|
||||||
out << ";\n";
|
|
||||||
format_specifiers += "O";
|
format_specifiers += "O";
|
||||||
parameter_list += ", &" + param_name;
|
parameter_list += ", &" + param_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the default value is NULL, we also accept a None value.
|
// If the default value is NULL, we also accept a None value.
|
||||||
bool maybe_none = false;
|
bool maybe_none = false;
|
||||||
if (default_value != nullptr && (return_flags & RF_coerced) == 0) {
|
if (default_value != nullptr && (return_flags & RF_coerced) == 0 &&
|
||||||
|
TypeManager::is_pointer(orig_type)) {
|
||||||
CPPExpression::Result res = param->get_default_value()->evaluate();
|
CPPExpression::Result res = param->get_default_value()->evaluate();
|
||||||
if (res._type == CPPExpression::RT_integer ||
|
if (res._type == CPPExpression::RT_integer ||
|
||||||
res._type == CPPExpression::RT_pointer) {
|
res._type == CPPExpression::RT_pointer) {
|
||||||
@ -5576,8 +5528,11 @@ write_function_instance(ostream &out, FunctionRemap *remap,
|
|||||||
<< "if (" << param_name << " != nullptr && " << param_name << " != Py_None) {\n"
|
<< "if (" << param_name << " != nullptr && " << param_name << " != Py_None) {\n"
|
||||||
<< " " << param_name << "_this";
|
<< " " << param_name << "_this";
|
||||||
} else if (is_optional) {
|
} else if (is_optional) {
|
||||||
|
if (TypeManager::is_pointer(orig_type)) {
|
||||||
|
extra_convert << default_expr;
|
||||||
|
}
|
||||||
extra_convert
|
extra_convert
|
||||||
<< default_expr << ";\n"
|
<< ";\n"
|
||||||
<< "if (" << param_name << " != nullptr) {\n"
|
<< "if (" << param_name << " != nullptr) {\n"
|
||||||
<< " " << param_name << "_this";
|
<< " " << param_name << "_this";
|
||||||
} else if (maybe_none) {
|
} else if (maybe_none) {
|
||||||
@ -5590,7 +5545,13 @@ write_function_instance(ostream &out, FunctionRemap *remap,
|
|||||||
extra_convert << " = Dtool_Coerce_" + make_safe_name(class_name) +
|
extra_convert << " = Dtool_Coerce_" + make_safe_name(class_name) +
|
||||||
"(" + param_name + ", " + param_name + "_local);\n";
|
"(" + param_name + ", " + param_name + "_local);\n";
|
||||||
|
|
||||||
if (is_optional || maybe_none) {
|
if (is_optional && !TypeManager::is_pointer(orig_type)) {
|
||||||
|
extra_convert
|
||||||
|
<< "} else {\n"
|
||||||
|
<< " " << param_name << "_local" << default_expr << ";\n"
|
||||||
|
<< " " << param_name << "_this = &" << param_name << "_local;\n"
|
||||||
|
<< "}\n";
|
||||||
|
} else if (is_optional || maybe_none) {
|
||||||
extra_convert << "}\n";
|
extra_convert << "}\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5645,21 +5606,60 @@ write_function_instance(ostream &out, FunctionRemap *remap,
|
|||||||
} else { // The regular, non-coercion case.
|
} else { // The regular, non-coercion case.
|
||||||
type->output_instance(extra_convert, param_name + "_this", &parser);
|
type->output_instance(extra_convert, param_name + "_this", &parser);
|
||||||
if (is_optional && maybe_none) {
|
if (is_optional && maybe_none) {
|
||||||
|
// This parameter has a default value of nullptr, so we need to also
|
||||||
|
// allow passing in None.
|
||||||
extra_convert
|
extra_convert
|
||||||
<< default_expr << ";\n"
|
<< default_expr << ";\n"
|
||||||
<< "if (" << param_name << " != nullptr && " << param_name << " != Py_None) {\n"
|
<< "if (" << param_name << " != nullptr && " << param_name << " != Py_None) {\n"
|
||||||
<< " " << param_name << "_this";
|
<< " " << param_name << "_this";
|
||||||
} else if (is_optional) {
|
}
|
||||||
|
else if (is_optional && !TypeManager::is_pointer(orig_type) && !default_value->is_lvalue()) {
|
||||||
|
// Most annoying case, where we have to use an rvalue reference to
|
||||||
|
// extend the lifetime of the default argument. In this case, the
|
||||||
|
// default expression is invoked even if not used.
|
||||||
|
extra_convert << ";\n";
|
||||||
|
if (TypeManager::is_const_pointer_to_anything(type)) {
|
||||||
|
extra_convert << "const ";
|
||||||
|
obj_type->output_instance(extra_convert, "&" + param_name + "_ref", &parser);
|
||||||
|
} else {
|
||||||
|
obj_type->output_instance(extra_convert, "&&" + param_name + "_ref", &parser);
|
||||||
|
}
|
||||||
extra_convert
|
extra_convert
|
||||||
<< default_expr << ";\n"
|
<< default_expr << ";\n"
|
||||||
<< "if (" << param_name << " != nullptr) {\n"
|
<< "if (" << param_name << " == nullptr) {\n"
|
||||||
|
<< " " << param_name << "_this = &" << param_name << "_ref;\n"
|
||||||
|
<< "} else {\n"
|
||||||
<< " " << param_name << "_this";
|
<< " " << param_name << "_this";
|
||||||
} else if (maybe_none) {
|
}
|
||||||
|
else if (is_optional) {
|
||||||
|
// General case where the default argument is either an lvalue or a
|
||||||
|
// pointer.
|
||||||
|
extra_convert
|
||||||
|
<< ";\n"
|
||||||
|
<< "if (" << param_name << " == nullptr) {\n"
|
||||||
|
<< " " << param_name << "_this = ";
|
||||||
|
if (TypeManager::is_pointer(orig_type)) {
|
||||||
|
default_value->output(extra_convert, 0, &parser, false);
|
||||||
|
extra_convert << ";\n";
|
||||||
|
} else {
|
||||||
|
// The rvalue case was handled above, so this is an lvalue, which
|
||||||
|
// means we can safely take a reference to it.
|
||||||
|
extra_convert << "&(";
|
||||||
|
default_value->output(extra_convert, 0, &parser, false);
|
||||||
|
extra_convert << ");\n";
|
||||||
|
}
|
||||||
|
extra_convert
|
||||||
|
<< "} else {\n"
|
||||||
|
<< " " << param_name << "_this";
|
||||||
|
}
|
||||||
|
else if (maybe_none) {
|
||||||
|
// No default argument, but we still need to check for None.
|
||||||
extra_convert
|
extra_convert
|
||||||
<< " = nullptr;\n"
|
<< " = nullptr;\n"
|
||||||
<< "if (" << param_name << " != Py_None) {\n"
|
<< "if (" << param_name << " != Py_None) {\n"
|
||||||
<< " " << param_name << "_this";
|
<< " " << param_name << "_this";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (const_ok && !report_errors) {
|
if (const_ok && !report_errors) {
|
||||||
// This function does the same thing in this case and is slightly
|
// This function does the same thing in this case and is slightly
|
||||||
// simpler. But maybe we should just reorganize these functions
|
// simpler. But maybe we should just reorganize these functions
|
||||||
|
Loading…
x
Reference in New Issue
Block a user