mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-29 00:06:44 -04:00
interrogate: Reimplement subscript assignment "operator"
This redoes the handling of `obj[n] = item` to occur in InterrogateBuilder instead so that it doesn't prevent the same remap from being used as getitem. This fixes the non-const variant of InstanceList[n].
This commit is contained in:
parent
5ef1b44455
commit
18e8918138
@ -419,6 +419,17 @@ get_call_str(const string &container, const vector_string &pexprs) const {
|
|||||||
call << ')';
|
call << ')';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} else if (_type == T_item_assignment_operator) {
|
||||||
|
call << "(";
|
||||||
|
_parameters[0]._remap->pass_parameter(call, container);
|
||||||
|
call << ")[";
|
||||||
|
|
||||||
|
size_t pn = _first_true_parameter;
|
||||||
|
_parameters[pn]._remap->pass_parameter(call, get_parameter_expr(pn, pexprs));
|
||||||
|
call << "] = ";
|
||||||
|
++pn;
|
||||||
|
_parameters[pn]._remap->pass_parameter(call, get_parameter_expr(pn, pexprs));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
const char *separator = "";
|
const char *separator = "";
|
||||||
|
|
||||||
@ -468,11 +479,6 @@ get_call_str(const string &container, const vector_string &pexprs) const {
|
|||||||
size_t pn = _first_true_parameter;
|
size_t pn = _first_true_parameter;
|
||||||
size_t num_parameters = pexprs.size();
|
size_t num_parameters = pexprs.size();
|
||||||
|
|
||||||
if (_type == T_item_assignment_operator) {
|
|
||||||
// The last parameter is the value to set.
|
|
||||||
--num_parameters;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (pn = _first_true_parameter;
|
for (pn = _first_true_parameter;
|
||||||
pn < num_parameters; ++pn) {
|
pn < num_parameters; ++pn) {
|
||||||
nassertd(pn < _parameters.size()) break;
|
nassertd(pn < _parameters.size()) break;
|
||||||
@ -481,11 +487,6 @@ get_call_str(const string &container, const vector_string &pexprs) const {
|
|||||||
separator = ", ";
|
separator = ", ";
|
||||||
}
|
}
|
||||||
call << ")";
|
call << ")";
|
||||||
|
|
||||||
if (_type == T_item_assignment_operator) {
|
|
||||||
call << " = ";
|
|
||||||
_parameters[pn]._remap->pass_parameter(call, get_parameter_expr(pn, pexprs));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return call.str();
|
return call.str();
|
||||||
@ -568,6 +569,9 @@ setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_mak
|
|||||||
|
|
||||||
} else if ((ifunc._flags & InterrogateFunction::F_setter) != 0) {
|
} else if ((ifunc._flags & InterrogateFunction::F_setter) != 0) {
|
||||||
_type = T_setter;
|
_type = T_setter;
|
||||||
|
|
||||||
|
} else if ((ifunc._flags & InterrogateFunction::F_item_assignment) != 0) {
|
||||||
|
_type = T_item_assignment_operator;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((_cppfunc->_storage_class & CPPInstance::SC_blocking) != 0) {
|
if ((_cppfunc->_storage_class & CPPInstance::SC_blocking) != 0) {
|
||||||
@ -623,14 +627,6 @@ setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_mak
|
|||||||
fname == "operator <<=" ||
|
fname == "operator <<=" ||
|
||||||
fname == "operator >>=") {
|
fname == "operator >>=") {
|
||||||
_type = T_assignment_method;
|
_type = T_assignment_method;
|
||||||
|
|
||||||
} else if (fname == "operator []" && !_const_method && rtype != nullptr) {
|
|
||||||
// Check if this is an item-assignment operator.
|
|
||||||
CPPReferenceType *reftype = rtype->as_reference_type();
|
|
||||||
if (reftype != nullptr && reftype->_pointing_at->as_const_type() == nullptr) {
|
|
||||||
// It returns a mutable reference.
|
|
||||||
_type = T_item_assignment_operator;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -707,37 +703,6 @@ setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_mak
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (_type == T_item_assignment_operator) {
|
|
||||||
// An item-assignment method isn't really a thing in C++, but it is in
|
|
||||||
// scripting languages, so we use this to denote item-access operators
|
|
||||||
// that return a non-const reference.
|
|
||||||
|
|
||||||
if (_cpptype == nullptr) {
|
|
||||||
nout << "Method " << *_cppfunc << " has no struct type\n";
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
// Synthesize a const reference parameter for the assignment.
|
|
||||||
CPPType *bare_type = TypeManager::unwrap_reference(rtype);
|
|
||||||
CPPType *const_type = CPPType::new_type(new CPPConstType(bare_type));
|
|
||||||
CPPType *ref_type = CPPType::new_type(new CPPReferenceType(const_type));
|
|
||||||
|
|
||||||
Parameter param;
|
|
||||||
param._has_name = true;
|
|
||||||
param._name = "assign_val";
|
|
||||||
param._remap = interface_maker->remap_parameter(_cpptype, ref_type);
|
|
||||||
|
|
||||||
if (param._remap == nullptr || !param._remap->is_valid()) {
|
|
||||||
nout << "Invalid remap for assignment type of method " << *_cppfunc << "\n";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
_parameters.push_back(param);
|
|
||||||
|
|
||||||
// Pretend we don't return anything at all.
|
|
||||||
CPPType *void_type = TypeManager::get_void_type();
|
|
||||||
_return_type = interface_maker->remap_parameter(_cpptype, void_type);
|
|
||||||
_void_return = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (fname == "operator <=>") {
|
} else if (fname == "operator <=>") {
|
||||||
// This returns an opaque object that we must leave unchanged.
|
// This returns an opaque object that we must leave unchanged.
|
||||||
_return_type = new ParameterRemapUnchanged(rtype);
|
_return_type = new ParameterRemapUnchanged(rtype);
|
||||||
|
@ -74,6 +74,7 @@ RenameSet methodRenameDictionary[] = {
|
|||||||
{ "operator =" , "assign", 0 },
|
{ "operator =" , "assign", 0 },
|
||||||
{ "operator ()" , "__call__", 0 },
|
{ "operator ()" , "__call__", 0 },
|
||||||
{ "operator []" , "__getitem__", 0 },
|
{ "operator []" , "__getitem__", 0 },
|
||||||
|
{ "operator [] =" , "__setitem__", 0 },
|
||||||
{ "operator ++unary", "increment", 0 },
|
{ "operator ++unary", "increment", 0 },
|
||||||
{ "operator ++" , "increment", 0 },
|
{ "operator ++" , "increment", 0 },
|
||||||
{ "operator --unary", "decrement", 0 },
|
{ "operator --unary", "decrement", 0 },
|
||||||
|
@ -3012,6 +3012,38 @@ define_method(CPPInstance *function, InterrogateType &itype,
|
|||||||
index) == itype._methods.end()) {
|
index) == itype._methods.end()) {
|
||||||
itype._methods.push_back(index);
|
itype._methods.push_back(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For an operator [] returning a non-const reference, we synthesize an
|
||||||
|
// "item-assignment" operator, which does not exist in C++ but does in
|
||||||
|
// scripting languages. This allows `obj[n] = ...`
|
||||||
|
if (ftype->_return_type != nullptr &&
|
||||||
|
ftype->_return_type->is_reference() &&
|
||||||
|
!ftype->_return_type->remove_reference()->is_const() &&
|
||||||
|
(ftype->_flags & CPPFunctionType::F_const_method) == 0 &&
|
||||||
|
function->get_simple_name() == "operator []") {
|
||||||
|
|
||||||
|
// Make up a CPPFunctionType with extra parameter.
|
||||||
|
CPPType *assign_type = TypeManager::wrap_const_reference(ftype->_return_type->remove_reference());
|
||||||
|
CPPParameterList *params = new CPPParameterList(*(ftype->_parameters));
|
||||||
|
CPPInstance *param1 = new CPPInstance(assign_type, "assign_val");
|
||||||
|
params->_parameters.push_back(param1);
|
||||||
|
CPPType *void_type = TypeManager::get_void_type();
|
||||||
|
CPPFunctionType *ftype = new CPPFunctionType(void_type, params, 0);
|
||||||
|
|
||||||
|
// Now make up an instance for the function.
|
||||||
|
CPPInstance *function = new CPPInstance(ftype, "operator [] =");
|
||||||
|
function->_ident->_native_scope = scope;
|
||||||
|
|
||||||
|
FunctionIndex index = get_function(function, "",
|
||||||
|
struct_type, scope,
|
||||||
|
InterrogateFunction::F_item_assignment);
|
||||||
|
if (index != 0) {
|
||||||
|
if (find(itype._methods.begin(), itype._methods.end(),
|
||||||
|
index) == itype._methods.end()) {
|
||||||
|
itype._methods.push_back(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -70,6 +70,7 @@ private:
|
|||||||
F_setter = 0x0020,
|
F_setter = 0x0020,
|
||||||
F_unary_op = 0x0040,
|
F_unary_op = 0x0040,
|
||||||
F_operator_typecast = 0x0080,
|
F_operator_typecast = 0x0080,
|
||||||
|
F_item_assignment = 0x0100,
|
||||||
};
|
};
|
||||||
|
|
||||||
int _flags;
|
int _flags;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user