mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-30 16:58:40 -04:00
interrogate: support MAKE_MAP_PROPERTY
This commit is contained in:
parent
0e2b14cf4c
commit
bf190f7306
File diff suppressed because it is too large
Load Diff
@ -397,6 +397,7 @@ pop_struct() {
|
|||||||
%type <u.type> class_derivation_name
|
%type <u.type> class_derivation_name
|
||||||
%type <u.type> enum_element_type
|
%type <u.type> enum_element_type
|
||||||
%type <u.type> maybe_trailing_return_type
|
%type <u.type> maybe_trailing_return_type
|
||||||
|
%type <u.identifier> maybe_comma_identifier
|
||||||
/*%type <u.type> typedefname*/
|
/*%type <u.type> typedefname*/
|
||||||
%type <u.identifier> name
|
%type <u.identifier> name
|
||||||
%type <u.identifier> name_no_final
|
%type <u.identifier> name_no_final
|
||||||
@ -548,202 +549,264 @@ declaration:
|
|||||||
{
|
{
|
||||||
current_scope->set_current_vis(V_private);
|
current_scope->set_current_vis(V_private);
|
||||||
}
|
}
|
||||||
| KW_MAKE_PROPERTY '(' name ',' IDENTIFIER ')' ';'
|
| KW_MAKE_PROPERTY '(' name ',' IDENTIFIER maybe_comma_identifier ')' ';'
|
||||||
{
|
|
||||||
|
|
||||||
CPPDeclaration *getter = $5->find_symbol(current_scope, global_scope, current_lexer);
|
|
||||||
if (getter == (CPPDeclaration *)NULL || getter->get_subtype() != CPPDeclaration::ST_function_group) {
|
|
||||||
yyerror("Reference to non-existent or invalid getter: " + $5->get_fully_scoped_name(), @5);
|
|
||||||
}
|
|
||||||
|
|
||||||
CPPMakeProperty *make_property = new CPPMakeProperty($3, getter->as_function_group(), NULL, current_scope, @1.file);
|
|
||||||
current_scope->add_declaration(make_property, global_scope, current_lexer, @1);
|
|
||||||
}
|
|
||||||
| KW_MAKE_PROPERTY '(' name ',' IDENTIFIER ',' IDENTIFIER ')' ';'
|
|
||||||
{
|
{
|
||||||
CPPDeclaration *getter = $5->find_symbol(current_scope, global_scope, current_lexer);
|
CPPDeclaration *getter = $5->find_symbol(current_scope, global_scope, current_lexer);
|
||||||
if (getter == (CPPDeclaration *)NULL || getter->get_subtype() != CPPDeclaration::ST_function_group) {
|
if (getter == nullptr || getter->get_subtype() != CPPDeclaration::ST_function_group) {
|
||||||
yyerror("Reference to non-existent or invalid getter: " + $5->get_fully_scoped_name(), @5);
|
yyerror("Reference to non-existent or invalid getter: " + $5->get_fully_scoped_name(), @5);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
CPPDeclaration *setter = $7->find_symbol(current_scope, global_scope, current_lexer);
|
CPPMakeProperty *make_property = new CPPMakeProperty($3, CPPMakeProperty::T_normal, current_scope, @1.file);
|
||||||
CPPFunctionGroup *setter_func = NULL;
|
make_property->_get_function = getter->as_function_group();
|
||||||
|
|
||||||
if (setter == (CPPDeclaration *)NULL || setter->get_subtype() != CPPDeclaration::ST_function_group) {
|
if ($6 != nullptr) {
|
||||||
yyerror("Reference to non-existent or invalid setter: " + $7->get_fully_scoped_name(), @7);
|
CPPDeclaration *setter = $6->find_symbol(current_scope, global_scope, current_lexer);
|
||||||
} else {
|
if (setter == nullptr || setter->get_subtype() != CPPDeclaration::ST_function_group) {
|
||||||
setter_func = setter->as_function_group();
|
yyerror("Reference to non-existent or invalid setter: " + $6->get_fully_scoped_name(), @6);
|
||||||
|
} else {
|
||||||
|
make_property->_set_function = setter->as_function_group();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CPPMakeProperty *make_property = new CPPMakeProperty($3, getter->as_function_group(),
|
|
||||||
setter_func, current_scope, @1.file);
|
|
||||||
current_scope->add_declaration(make_property, global_scope, current_lexer, @1);
|
current_scope->add_declaration(make_property, global_scope, current_lexer, @1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
| KW_MAKE_PROPERTY '(' name ',' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER ')' ';'
|
| KW_MAKE_PROPERTY '(' name ',' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER ')' ';'
|
||||||
{
|
{
|
||||||
CPPDeclaration *getter = $5->find_symbol(current_scope, global_scope, current_lexer);
|
CPPDeclaration *getter = $5->find_symbol(current_scope, global_scope, current_lexer);
|
||||||
if (getter == (CPPDeclaration *)NULL || getter->get_subtype() != CPPDeclaration::ST_function_group) {
|
if (getter == nullptr || getter->get_subtype() != CPPDeclaration::ST_function_group) {
|
||||||
yyerror("Reference to non-existent or invalid getter: " + $5->get_fully_scoped_name(), @5);
|
yyerror("Reference to non-existent or invalid getter: " + $5->get_fully_scoped_name(), @5);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
CPPDeclaration *setter = $7->find_symbol(current_scope, global_scope, current_lexer);
|
CPPMakeProperty *make_property = new CPPMakeProperty($3, CPPMakeProperty::T_normal, current_scope, @1.file);
|
||||||
CPPFunctionGroup *setter_func = NULL;
|
make_property->_get_function = getter->as_function_group();
|
||||||
|
|
||||||
if (setter == (CPPDeclaration *)NULL || setter->get_subtype() != CPPDeclaration::ST_function_group) {
|
CPPDeclaration *setter = $7->find_symbol(current_scope, global_scope, current_lexer);
|
||||||
|
if (setter == nullptr || setter->get_subtype() != CPPDeclaration::ST_function_group) {
|
||||||
yyerror("Reference to non-existent or invalid setter: " + $7->get_fully_scoped_name(), @7);
|
yyerror("Reference to non-existent or invalid setter: " + $7->get_fully_scoped_name(), @7);
|
||||||
} else {
|
} else {
|
||||||
setter_func = setter->as_function_group();
|
make_property->_set_function = setter->as_function_group();
|
||||||
}
|
}
|
||||||
|
|
||||||
CPPDeclaration *deleter = $9->find_symbol(current_scope, global_scope, current_lexer);
|
CPPDeclaration *deleter = $9->find_symbol(current_scope, global_scope, current_lexer);
|
||||||
if (deleter == (CPPDeclaration *)NULL || deleter->get_subtype() != CPPDeclaration::ST_function_group) {
|
if (deleter == nullptr || deleter->get_subtype() != CPPDeclaration::ST_function_group) {
|
||||||
yyerror("reference to non-existent or invalid delete method: " + $9->get_fully_scoped_name(), @9);
|
yyerror("reference to non-existent or invalid delete method: " + $9->get_fully_scoped_name(), @9);
|
||||||
deleter = NULL;
|
} else {
|
||||||
}
|
|
||||||
|
|
||||||
CPPMakeProperty *make_property = new CPPMakeProperty($3, getter->as_function_group(),
|
|
||||||
setter_func, current_scope, @1.file);
|
|
||||||
if (deleter) {
|
|
||||||
make_property->_del_function = deleter->as_function_group();
|
make_property->_del_function = deleter->as_function_group();
|
||||||
}
|
}
|
||||||
|
|
||||||
current_scope->add_declaration(make_property, global_scope, current_lexer, @1);
|
current_scope->add_declaration(make_property, global_scope, current_lexer, @1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
| KW_MAKE_SEQ_PROPERTY '(' name ',' IDENTIFIER ',' IDENTIFIER ')' ';'
|
| KW_MAKE_SEQ_PROPERTY '(' name ',' IDENTIFIER ',' IDENTIFIER ')' ';'
|
||||||
{
|
{
|
||||||
CPPDeclaration *length_getter = $5->find_symbol(current_scope, global_scope, current_lexer);
|
CPPDeclaration *length_getter = $5->find_symbol(current_scope, global_scope, current_lexer);
|
||||||
if (length_getter == (CPPDeclaration *)NULL || length_getter->get_subtype() != CPPDeclaration::ST_function_group) {
|
if (length_getter == nullptr || length_getter->get_subtype() != CPPDeclaration::ST_function_group) {
|
||||||
yyerror("reference to non-existent or invalid length method: " + $5->get_fully_scoped_name(), @5);
|
yyerror("reference to non-existent or invalid length method: " + $5->get_fully_scoped_name(), @5);
|
||||||
length_getter = NULL;
|
length_getter = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
CPPDeclaration *getter = $7->find_symbol(current_scope, global_scope, current_lexer);
|
CPPDeclaration *getter = $7->find_symbol(current_scope, global_scope, current_lexer);
|
||||||
if (getter == (CPPDeclaration *)NULL || getter->get_subtype() != CPPDeclaration::ST_function_group) {
|
if (getter == nullptr || getter->get_subtype() != CPPDeclaration::ST_function_group) {
|
||||||
yyerror("Reference to non-existent or invalid getter: " + $7->get_fully_scoped_name(), @7);
|
yyerror("Reference to non-existent or invalid getter: " + $7->get_fully_scoped_name(), @7);
|
||||||
|
getter = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
CPPMakeProperty *make_property = new CPPMakeProperty($3, getter->as_function_group(), NULL, current_scope, @1.file);
|
if (getter != nullptr && length_getter != nullptr) {
|
||||||
make_property->_length_function = length_getter->as_function_group();
|
CPPMakeProperty *make_property = new CPPMakeProperty($3, CPPMakeProperty::T_sequence, current_scope, @1.file);
|
||||||
current_scope->add_declaration(make_property, global_scope, current_lexer, @1);
|
make_property->_get_function = getter->as_function_group();
|
||||||
|
make_property->_length_function = length_getter->as_function_group();
|
||||||
|
current_scope->add_declaration(make_property, global_scope, current_lexer, @1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
| KW_MAKE_SEQ_PROPERTY '(' name ',' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER ')' ';'
|
| KW_MAKE_SEQ_PROPERTY '(' name ',' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER ')' ';'
|
||||||
{
|
{
|
||||||
CPPDeclaration *length_getter = $5->find_symbol(current_scope, global_scope, current_lexer);
|
CPPDeclaration *length_getter = $5->find_symbol(current_scope, global_scope, current_lexer);
|
||||||
if (length_getter == (CPPDeclaration *)NULL || length_getter->get_subtype() != CPPDeclaration::ST_function_group) {
|
if (length_getter == nullptr || length_getter->get_subtype() != CPPDeclaration::ST_function_group) {
|
||||||
yyerror("reference to non-existent or invalid length method: " + $5->get_fully_scoped_name(), @5);
|
yyerror("reference to non-existent or invalid length method: " + $5->get_fully_scoped_name(), @5);
|
||||||
length_getter = NULL;
|
length_getter = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
CPPDeclaration *getter = $7->find_symbol(current_scope, global_scope, current_lexer);
|
CPPDeclaration *getter = $7->find_symbol(current_scope, global_scope, current_lexer);
|
||||||
if (getter == (CPPDeclaration *)NULL || getter->get_subtype() != CPPDeclaration::ST_function_group) {
|
if (getter == nullptr || getter->get_subtype() != CPPDeclaration::ST_function_group) {
|
||||||
yyerror("Reference to non-existent or invalid getter: " + $7->get_fully_scoped_name(), @7);
|
yyerror("Reference to non-existent or invalid getter: " + $7->get_fully_scoped_name(), @7);
|
||||||
|
getter = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getter != nullptr && length_getter != nullptr) {
|
||||||
|
CPPMakeProperty *make_property = new CPPMakeProperty($3, CPPMakeProperty::T_sequence, current_scope, @1.file);
|
||||||
|
make_property->_get_function = getter->as_function_group();
|
||||||
|
make_property->_length_function = length_getter->as_function_group();
|
||||||
|
|
||||||
} else {
|
|
||||||
CPPDeclaration *setter = $9->find_symbol(current_scope, global_scope, current_lexer);
|
CPPDeclaration *setter = $9->find_symbol(current_scope, global_scope, current_lexer);
|
||||||
CPPFunctionGroup *setter_func = NULL;
|
if (setter == nullptr || setter->get_subtype() != CPPDeclaration::ST_function_group) {
|
||||||
|
|
||||||
if (setter == (CPPDeclaration *)NULL || setter->get_subtype() != CPPDeclaration::ST_function_group) {
|
|
||||||
yyerror("Reference to non-existent or invalid setter: " + $9->get_fully_scoped_name(), @9);
|
yyerror("Reference to non-existent or invalid setter: " + $9->get_fully_scoped_name(), @9);
|
||||||
} else {
|
} else {
|
||||||
setter_func = setter->as_function_group();
|
make_property->_set_function = setter->as_function_group();
|
||||||
}
|
}
|
||||||
|
|
||||||
CPPMakeProperty *make_property = new CPPMakeProperty($3, getter->as_function_group(),
|
|
||||||
setter_func, current_scope, @1.file);
|
|
||||||
make_property->_length_function = length_getter->as_function_group();
|
|
||||||
current_scope->add_declaration(make_property, global_scope, current_lexer, @1);
|
current_scope->add_declaration(make_property, global_scope, current_lexer, @1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
| KW_MAKE_SEQ_PROPERTY '(' name ',' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER ')' ';'
|
| KW_MAKE_SEQ_PROPERTY '(' name ',' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER ')' ';'
|
||||||
{
|
{
|
||||||
CPPDeclaration *length_getter = $5->find_symbol(current_scope, global_scope, current_lexer);
|
CPPDeclaration *length_getter = $5->find_symbol(current_scope, global_scope, current_lexer);
|
||||||
if (length_getter == (CPPDeclaration *)NULL || length_getter->get_subtype() != CPPDeclaration::ST_function_group) {
|
if (length_getter == nullptr || length_getter->get_subtype() != CPPDeclaration::ST_function_group) {
|
||||||
yyerror("reference to non-existent or invalid length method: " + $5->get_fully_scoped_name(), @5);
|
yyerror("reference to non-existent or invalid length method: " + $5->get_fully_scoped_name(), @5);
|
||||||
length_getter = NULL;
|
length_getter = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
CPPDeclaration *getter = $7->find_symbol(current_scope, global_scope, current_lexer);
|
CPPDeclaration *getter = $7->find_symbol(current_scope, global_scope, current_lexer);
|
||||||
if (getter == (CPPDeclaration *)NULL || getter->get_subtype() != CPPDeclaration::ST_function_group) {
|
if (getter == nullptr || getter->get_subtype() != CPPDeclaration::ST_function_group) {
|
||||||
yyerror("Reference to non-existent or invalid getter: " + $7->get_fully_scoped_name(), @7);
|
yyerror("Reference to non-existent or invalid getter: " + $7->get_fully_scoped_name(), @7);
|
||||||
|
getter = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getter != nullptr && length_getter != nullptr) {
|
||||||
|
CPPMakeProperty *make_property = new CPPMakeProperty($3, CPPMakeProperty::T_sequence, current_scope, @1.file);
|
||||||
|
make_property->_get_function = getter->as_function_group();
|
||||||
|
make_property->_length_function = length_getter->as_function_group();
|
||||||
|
|
||||||
} else {
|
|
||||||
CPPDeclaration *setter = $9->find_symbol(current_scope, global_scope, current_lexer);
|
CPPDeclaration *setter = $9->find_symbol(current_scope, global_scope, current_lexer);
|
||||||
CPPFunctionGroup *setter_func = NULL;
|
if (setter == nullptr || setter->get_subtype() != CPPDeclaration::ST_function_group) {
|
||||||
|
|
||||||
if (setter == (CPPDeclaration *)NULL || setter->get_subtype() != CPPDeclaration::ST_function_group) {
|
|
||||||
yyerror("Reference to non-existent or invalid setter: " + $9->get_fully_scoped_name(), @9);
|
yyerror("Reference to non-existent or invalid setter: " + $9->get_fully_scoped_name(), @9);
|
||||||
} else {
|
} else {
|
||||||
setter_func = setter->as_function_group();
|
make_property->_set_function = setter->as_function_group();
|
||||||
}
|
}
|
||||||
|
|
||||||
CPPDeclaration *deleter = $11->find_symbol(current_scope, global_scope, current_lexer);
|
CPPDeclaration *deleter = $11->find_symbol(current_scope, global_scope, current_lexer);
|
||||||
if (deleter == (CPPDeclaration *)NULL || deleter->get_subtype() != CPPDeclaration::ST_function_group) {
|
if (deleter == nullptr || deleter->get_subtype() != CPPDeclaration::ST_function_group) {
|
||||||
yyerror("reference to non-existent or invalid delete method: " + $11->get_fully_scoped_name(), @11);
|
yyerror("reference to non-existent or invalid delete method: " + $11->get_fully_scoped_name(), @11);
|
||||||
deleter = NULL;
|
} else {
|
||||||
}
|
|
||||||
|
|
||||||
CPPMakeProperty *make_property = new CPPMakeProperty($3, getter->as_function_group(),
|
|
||||||
setter_func, current_scope, @1.file);
|
|
||||||
make_property->_length_function = length_getter->as_function_group();
|
|
||||||
if (deleter) {
|
|
||||||
make_property->_del_function = deleter->as_function_group();
|
make_property->_del_function = deleter->as_function_group();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
current_scope->add_declaration(make_property, global_scope, current_lexer, @1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
| KW_MAKE_MAP_PROPERTY '(' name ',' IDENTIFIER ')' ';'
|
||||||
|
{
|
||||||
|
CPPDeclaration *getter = $5->find_symbol(current_scope, global_scope, current_lexer);
|
||||||
|
if (getter == nullptr || getter->get_subtype() != CPPDeclaration::ST_function_group) {
|
||||||
|
yyerror("reference to non-existent or invalid item getter method: " + $5->get_fully_scoped_name(), @5);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
CPPMakeProperty *make_property = new CPPMakeProperty($3, CPPMakeProperty::T_mapping, current_scope, @1.file);
|
||||||
|
make_property->_get_function = getter->as_function_group();
|
||||||
|
current_scope->add_declaration(make_property, global_scope, current_lexer, @1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
| KW_MAKE_MAP_PROPERTY '(' name ',' IDENTIFIER ',' IDENTIFIER ')' ';'
|
||||||
|
{
|
||||||
|
CPPDeclaration *getter = $7->find_symbol(current_scope, global_scope, current_lexer);
|
||||||
|
if (getter == nullptr || getter->get_subtype() != CPPDeclaration::ST_function_group) {
|
||||||
|
yyerror("Reference to non-existent or invalid getter: " + $7->get_fully_scoped_name(), @7);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
CPPMakeProperty *make_property;
|
||||||
|
make_property = new CPPMakeProperty($3, CPPMakeProperty::T_mapping, current_scope, @1.file);
|
||||||
|
make_property->_get_function = getter->as_function_group();
|
||||||
|
|
||||||
|
CPPDeclaration *hasser = $5->find_symbol(current_scope, global_scope, current_lexer);
|
||||||
|
if (hasser == nullptr || hasser->get_subtype() != CPPDeclaration::ST_function_group) {
|
||||||
|
yyerror("reference to non-existent or invalid has/find method: " + $5->get_fully_scoped_name(), @5);
|
||||||
|
} else {
|
||||||
|
make_property->_has_function = hasser->as_function_group();
|
||||||
|
}
|
||||||
|
|
||||||
|
current_scope->add_declaration(make_property, global_scope, current_lexer, @1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
| KW_MAKE_MAP_PROPERTY '(' name ',' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER maybe_comma_identifier ')' ';'
|
||||||
|
{
|
||||||
|
CPPDeclaration *getter = $7->find_symbol(current_scope, global_scope, current_lexer);
|
||||||
|
if (getter == nullptr || getter->get_subtype() != CPPDeclaration::ST_function_group) {
|
||||||
|
yyerror("Reference to non-existent or invalid getter: " + $7->get_fully_scoped_name(), @7);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
CPPMakeProperty *make_property = new CPPMakeProperty($3, CPPMakeProperty::T_mapping, current_scope, @1.file);
|
||||||
|
make_property->_get_function = getter->as_function_group();
|
||||||
|
|
||||||
|
CPPDeclaration *hasser = $5->find_symbol(current_scope, global_scope, current_lexer);
|
||||||
|
if (hasser == nullptr || hasser->get_subtype() != CPPDeclaration::ST_function_group) {
|
||||||
|
yyerror("reference to non-existent or invalid has/find method: " + $5->get_fully_scoped_name(), @5);
|
||||||
|
} else {
|
||||||
|
make_property->_has_function = hasser->as_function_group();
|
||||||
|
}
|
||||||
|
|
||||||
|
CPPDeclaration *setter = $9->find_symbol(current_scope, global_scope, current_lexer);
|
||||||
|
if (setter == nullptr || setter->get_subtype() != CPPDeclaration::ST_function_group) {
|
||||||
|
yyerror("Reference to non-existent or invalid setter: " + $9->get_fully_scoped_name(), @9);
|
||||||
|
} else {
|
||||||
|
make_property->_set_function = setter->as_function_group();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($10 != nullptr) {
|
||||||
|
CPPDeclaration *deleter = $10->find_symbol(current_scope, global_scope, current_lexer);
|
||||||
|
if (deleter == nullptr || deleter->get_subtype() != CPPDeclaration::ST_function_group) {
|
||||||
|
yyerror("reference to non-existent or invalid delete method: " + $10->get_fully_scoped_name(), @10);
|
||||||
|
} else {
|
||||||
|
make_property->_del_function = deleter->as_function_group();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
current_scope->add_declaration(make_property, global_scope, current_lexer, @1);
|
current_scope->add_declaration(make_property, global_scope, current_lexer, @1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
| KW_MAKE_PROPERTY2 '(' name ',' IDENTIFIER ',' IDENTIFIER ')' ';'
|
| KW_MAKE_PROPERTY2 '(' name ',' IDENTIFIER ',' IDENTIFIER ')' ';'
|
||||||
{
|
{
|
||||||
CPPDeclaration *hasser = $5->find_symbol(current_scope, global_scope, current_lexer);
|
|
||||||
if (hasser == (CPPDeclaration *)NULL || hasser->get_subtype() != CPPDeclaration::ST_function_group) {
|
|
||||||
yyerror("Reference to non-existent or invalid has-function: " + $5->get_fully_scoped_name(), @5);
|
|
||||||
}
|
|
||||||
|
|
||||||
CPPDeclaration *getter = $7->find_symbol(current_scope, global_scope, current_lexer);
|
CPPDeclaration *getter = $7->find_symbol(current_scope, global_scope, current_lexer);
|
||||||
if (getter == (CPPDeclaration *)NULL || getter->get_subtype() != CPPDeclaration::ST_function_group) {
|
if (getter == nullptr || getter->get_subtype() != CPPDeclaration::ST_function_group) {
|
||||||
yyerror("Reference to non-existent or invalid getter: " + $7->get_fully_scoped_name(), @7);
|
yyerror("Reference to non-existent or invalid getter: " + $7->get_fully_scoped_name(), @7);
|
||||||
}
|
|
||||||
|
|
||||||
if (hasser && getter) {
|
} else {
|
||||||
CPPMakeProperty *make_property;
|
CPPMakeProperty *make_property;
|
||||||
make_property = new CPPMakeProperty($3,
|
make_property = new CPPMakeProperty($3, CPPMakeProperty::T_normal,
|
||||||
hasser->as_function_group(),
|
|
||||||
getter->as_function_group(),
|
|
||||||
NULL, NULL,
|
|
||||||
current_scope, @1.file);
|
current_scope, @1.file);
|
||||||
|
make_property->_get_function = getter->as_function_group();
|
||||||
|
|
||||||
|
CPPDeclaration *hasser = $5->find_symbol(current_scope, global_scope, current_lexer);
|
||||||
|
if (hasser == nullptr || hasser->get_subtype() != CPPDeclaration::ST_function_group) {
|
||||||
|
yyerror("reference to non-existent or invalid has/find method: " + $5->get_fully_scoped_name(), @5);
|
||||||
|
} else {
|
||||||
|
make_property->_has_function = hasser->as_function_group();
|
||||||
|
}
|
||||||
|
|
||||||
current_scope->add_declaration(make_property, global_scope, current_lexer, @1);
|
current_scope->add_declaration(make_property, global_scope, current_lexer, @1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
| KW_MAKE_PROPERTY2 '(' name ',' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER ')' ';'
|
| KW_MAKE_PROPERTY2 '(' name ',' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER ')' ';'
|
||||||
{
|
{
|
||||||
CPPDeclaration *hasser = $5->find_symbol(current_scope, global_scope, current_lexer);
|
|
||||||
if (hasser == (CPPDeclaration *)NULL || hasser->get_subtype() != CPPDeclaration::ST_function_group) {
|
|
||||||
yyerror("Reference to non-existent or invalid has-function: " + $5->get_fully_scoped_name(), @5);
|
|
||||||
}
|
|
||||||
|
|
||||||
CPPDeclaration *getter = $7->find_symbol(current_scope, global_scope, current_lexer);
|
CPPDeclaration *getter = $7->find_symbol(current_scope, global_scope, current_lexer);
|
||||||
if (getter == (CPPDeclaration *)NULL || getter->get_subtype() != CPPDeclaration::ST_function_group) {
|
if (getter == nullptr || getter->get_subtype() != CPPDeclaration::ST_function_group) {
|
||||||
yyerror("Reference to non-existent or invalid getter: " + $7->get_fully_scoped_name(), @7);
|
yyerror("Reference to non-existent or invalid getter: " + $7->get_fully_scoped_name(), @7);
|
||||||
}
|
|
||||||
|
|
||||||
CPPDeclaration *setter = $9->find_symbol(current_scope, global_scope, current_lexer);
|
} else {
|
||||||
if (setter == (CPPDeclaration *)NULL || setter->get_subtype() != CPPDeclaration::ST_function_group) {
|
|
||||||
yyerror("Reference to non-existent or invalid setter: " + $9->get_fully_scoped_name(), @9);
|
|
||||||
}
|
|
||||||
|
|
||||||
CPPDeclaration *clearer = $11->find_symbol(current_scope, global_scope, current_lexer);
|
|
||||||
if (clearer == (CPPDeclaration *)NULL || clearer->get_subtype() != CPPDeclaration::ST_function_group) {
|
|
||||||
yyerror("Reference to non-existent or invalid clear-function: " + $11->get_fully_scoped_name(), @11);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasser && getter && setter && clearer) {
|
|
||||||
CPPMakeProperty *make_property;
|
CPPMakeProperty *make_property;
|
||||||
make_property = new CPPMakeProperty($3,
|
make_property = new CPPMakeProperty($3, CPPMakeProperty::T_normal,
|
||||||
hasser->as_function_group(),
|
|
||||||
getter->as_function_group(),
|
|
||||||
setter->as_function_group(),
|
|
||||||
clearer->as_function_group(),
|
|
||||||
current_scope, @1.file);
|
current_scope, @1.file);
|
||||||
|
make_property->_get_function = getter->as_function_group();
|
||||||
|
|
||||||
|
CPPDeclaration *hasser = $5->find_symbol(current_scope, global_scope, current_lexer);
|
||||||
|
if (hasser == nullptr || hasser->get_subtype() != CPPDeclaration::ST_function_group) {
|
||||||
|
yyerror("reference to non-existent or invalid has/find method: " + $5->get_fully_scoped_name(), @5);
|
||||||
|
} else {
|
||||||
|
make_property->_has_function = hasser->as_function_group();
|
||||||
|
}
|
||||||
|
|
||||||
|
CPPDeclaration *setter = $7->find_symbol(current_scope, global_scope, current_lexer);
|
||||||
|
if (setter == nullptr || setter->get_subtype() != CPPDeclaration::ST_function_group) {
|
||||||
|
yyerror("reference to non-existent or invalid setter: " + $7->get_fully_scoped_name(), @7);
|
||||||
|
} else {
|
||||||
|
make_property->_set_function = setter->as_function_group();
|
||||||
|
}
|
||||||
|
|
||||||
|
CPPDeclaration *clearer = $11->find_symbol(current_scope, global_scope, current_lexer);
|
||||||
|
if (clearer == nullptr || clearer->get_subtype() != CPPDeclaration::ST_function_group) {
|
||||||
|
yyerror("reference to non-existent or invalid clear method: " + $11->get_fully_scoped_name(), @11);
|
||||||
|
} else {
|
||||||
|
make_property->_clear_function = clearer->as_function_group();
|
||||||
|
}
|
||||||
|
|
||||||
current_scope->add_declaration(make_property, global_scope, current_lexer, @1);
|
current_scope->add_declaration(make_property, global_scope, current_lexer, @1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1723,6 +1786,18 @@ maybe_trailing_return_type:
|
|||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
|
maybe_comma_identifier:
|
||||||
|
empty
|
||||||
|
{
|
||||||
|
$$ = NULL;
|
||||||
|
}
|
||||||
|
| ',' IDENTIFIER
|
||||||
|
{
|
||||||
|
$$ = $2;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
function_parameter_list:
|
function_parameter_list:
|
||||||
empty
|
empty
|
||||||
{
|
{
|
||||||
|
@ -18,37 +18,17 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
CPPMakeProperty::
|
CPPMakeProperty::
|
||||||
CPPMakeProperty(CPPIdentifier *ident,
|
CPPMakeProperty(CPPIdentifier *ident, Type type,
|
||||||
CPPFunctionGroup *getter, CPPFunctionGroup *setter,
|
|
||||||
CPPScope *current_scope, const CPPFile &file) :
|
CPPScope *current_scope, const CPPFile &file) :
|
||||||
CPPDeclaration(file),
|
CPPDeclaration(file),
|
||||||
_ident(ident),
|
_ident(ident),
|
||||||
_length_function(NULL),
|
_type(type),
|
||||||
_has_function(NULL),
|
_length_function(nullptr),
|
||||||
_get_function(getter),
|
_has_function(nullptr),
|
||||||
_set_function(setter),
|
_get_function(nullptr),
|
||||||
_clear_function(NULL),
|
_set_function(nullptr),
|
||||||
_del_function(NULL)
|
_clear_function(nullptr),
|
||||||
{
|
_del_function(nullptr)
|
||||||
_ident->_native_scope = current_scope;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
CPPMakeProperty::
|
|
||||||
CPPMakeProperty(CPPIdentifier *ident,
|
|
||||||
CPPFunctionGroup *hasser, CPPFunctionGroup *getter,
|
|
||||||
CPPFunctionGroup *setter, CPPFunctionGroup *clearer,
|
|
||||||
CPPScope *current_scope, const CPPFile &file) :
|
|
||||||
CPPDeclaration(file),
|
|
||||||
_ident(ident),
|
|
||||||
_length_function(NULL),
|
|
||||||
_has_function(hasser),
|
|
||||||
_get_function(getter),
|
|
||||||
_set_function(setter),
|
|
||||||
_clear_function(clearer),
|
|
||||||
_del_function(NULL)
|
|
||||||
{
|
{
|
||||||
_ident->_native_scope = current_scope;
|
_ident->_native_scope = current_scope;
|
||||||
}
|
}
|
||||||
|
@ -23,16 +23,72 @@
|
|||||||
* This is a MAKE_PROPERTY() declaration appearing within a class body. It
|
* This is a MAKE_PROPERTY() declaration appearing within a class body. It
|
||||||
* means to generate a property within Python, replacing (for instance)
|
* means to generate a property within Python, replacing (for instance)
|
||||||
* get_something()/set_something() with a synthetic 'something' attribute.
|
* get_something()/set_something() with a synthetic 'something' attribute.
|
||||||
|
*
|
||||||
|
* This is an example of a simple property (MAKE_PROPERTY is defined as
|
||||||
|
* the built-in __make_property):
|
||||||
|
* @@code
|
||||||
|
* Thing get_thing() const;
|
||||||
|
* void set_thing(const Thing &);
|
||||||
|
*
|
||||||
|
* MAKE_PROPERTY(thing, get_thing, set_thing);
|
||||||
|
* @@endcode
|
||||||
|
* The setter may be omitted to make the property read-only.
|
||||||
|
*
|
||||||
|
* There is also a secondary macro that allows the property to be set to a
|
||||||
|
* cleared state using separate clear functions. In the scripting language,
|
||||||
|
* this would be represented by a "null" value, or an "optional" construct in
|
||||||
|
* languages that have no notion of a null value.
|
||||||
|
*
|
||||||
|
* @@code
|
||||||
|
* bool has_thing() const;
|
||||||
|
* Thing get_thing() const;
|
||||||
|
* void set_thing(const Thing &);
|
||||||
|
* void clear_thing();
|
||||||
|
* MAKE_PROPERTY2(thing, has_thing, get_thing, set_thing, clear_thing);
|
||||||
|
* @@endcode
|
||||||
|
* As with MAKE_PROPERTY, both the setter and clearer can be omitted to create
|
||||||
|
* a read-only property.
|
||||||
|
*
|
||||||
|
* Thirdly, there is a variant called MAKE_SEQ_PROPERTY. It takes a length
|
||||||
|
* function as argument and the getter and setter take an index as first
|
||||||
|
* argument:
|
||||||
|
* @@code
|
||||||
|
* size_t get_num_things() const;
|
||||||
|
* Thing &get_thing(size_t i) const;
|
||||||
|
* void set_thing(size_t i, Thing value) const;
|
||||||
|
* void remove_thing(size_t i) const;
|
||||||
|
*
|
||||||
|
* MAKE_SEQ_PROPERTY(get_num_things, get_thing, set_thing, remove_thing);
|
||||||
|
* @@endcode
|
||||||
|
*
|
||||||
|
* Lastly, there is the possibility to have properties with key/value
|
||||||
|
* associations, often called a "map" or "dictionary" in scripting languages:
|
||||||
|
* @@code
|
||||||
|
* bool has_thing(string key) const;
|
||||||
|
* Thing &get_thing(string key) const;
|
||||||
|
* void set_thing(string key, Thing value) const;
|
||||||
|
* void clear_thing(string key) const;
|
||||||
|
*
|
||||||
|
* MAKE_MAP_PROPERTY(things, has_thing, get_thing, set_thing, clear_thing);
|
||||||
|
* @@endcode
|
||||||
|
* You may also replace the "has" function with a "find" function that returns
|
||||||
|
* an index. If the returned index is negative (or in the case of an unsigned
|
||||||
|
* integer, the maximum value), the item is assumed not to be present in the
|
||||||
|
* mapping.
|
||||||
|
*
|
||||||
|
* It is also possible to use both MAKE_SEQ_PROPERTY and MAKE_MAP_PROPERTY on
|
||||||
|
* the same property name. This implies that this property has both a
|
||||||
|
* sequence and mapping interface.
|
||||||
*/
|
*/
|
||||||
class CPPMakeProperty : public CPPDeclaration {
|
class CPPMakeProperty : public CPPDeclaration {
|
||||||
public:
|
public:
|
||||||
CPPMakeProperty(CPPIdentifier *ident,
|
enum Type {
|
||||||
CPPFunctionGroup *getter, CPPFunctionGroup *setter,
|
T_normal = 0x0,
|
||||||
CPPScope *current_scope, const CPPFile &file);
|
T_sequence = 0x1,
|
||||||
|
T_mapping = 0x2,
|
||||||
|
};
|
||||||
|
|
||||||
CPPMakeProperty(CPPIdentifier *ident,
|
CPPMakeProperty(CPPIdentifier *ident, Type type,
|
||||||
CPPFunctionGroup *hasser, CPPFunctionGroup *getter,
|
|
||||||
CPPFunctionGroup *setter, CPPFunctionGroup *clearer,
|
|
||||||
CPPScope *current_scope, const CPPFile &file);
|
CPPScope *current_scope, const CPPFile &file);
|
||||||
|
|
||||||
virtual string get_simple_name() const;
|
virtual string get_simple_name() const;
|
||||||
@ -46,8 +102,7 @@ public:
|
|||||||
virtual CPPMakeProperty *as_make_property();
|
virtual CPPMakeProperty *as_make_property();
|
||||||
|
|
||||||
CPPIdentifier *_ident;
|
CPPIdentifier *_ident;
|
||||||
// If length_function is not NULL, this is actually a sequence property,
|
Type _type;
|
||||||
// and the other functions take an additional index argument.
|
|
||||||
CPPFunctionGroup *_length_function;
|
CPPFunctionGroup *_length_function;
|
||||||
CPPFunctionGroup *_has_function;
|
CPPFunctionGroup *_has_function;
|
||||||
CPPFunctionGroup *_get_function;
|
CPPFunctionGroup *_get_function;
|
||||||
|
@ -456,6 +456,7 @@ typedef struct _object PyObject;
|
|||||||
#define MAKE_PROPERTY2(property_name, ...) __make_property2(property_name, __VA_ARGS__)
|
#define MAKE_PROPERTY2(property_name, ...) __make_property2(property_name, __VA_ARGS__)
|
||||||
#define MAKE_SEQ(seq_name, num_name, element_name) __make_seq(seq_name, num_name, element_name)
|
#define MAKE_SEQ(seq_name, num_name, element_name) __make_seq(seq_name, num_name, element_name)
|
||||||
#define MAKE_SEQ_PROPERTY(property_name, ...) __make_seq_property(property_name, __VA_ARGS__)
|
#define MAKE_SEQ_PROPERTY(property_name, ...) __make_seq_property(property_name, __VA_ARGS__)
|
||||||
|
#define MAKE_MAP_PROPERTY(property_name, ...) __make_map_property(property_name, __VA_ARGS__)
|
||||||
#define EXTENSION(x) __extension x
|
#define EXTENSION(x) __extension x
|
||||||
#define EXTEND __extension
|
#define EXTEND __extension
|
||||||
#else
|
#else
|
||||||
@ -466,6 +467,7 @@ typedef struct _object PyObject;
|
|||||||
#define MAKE_PROPERTY2(property_name, ...)
|
#define MAKE_PROPERTY2(property_name, ...)
|
||||||
#define MAKE_SEQ(seq_name, num_name, element_name)
|
#define MAKE_SEQ(seq_name, num_name, element_name)
|
||||||
#define MAKE_SEQ_PROPERTY(property_name, ...)
|
#define MAKE_SEQ_PROPERTY(property_name, ...)
|
||||||
|
#define MAKE_MAP_PROPERTY(property_name, ...)
|
||||||
#define EXTENSION(x)
|
#define EXTENSION(x)
|
||||||
#define EXTEND
|
#define EXTEND
|
||||||
#endif
|
#endif
|
||||||
|
@ -51,6 +51,10 @@ PUBLISHED:
|
|||||||
|
|
||||||
static Filename get_cwd();
|
static Filename get_cwd();
|
||||||
|
|
||||||
|
PUBLISHED:
|
||||||
|
MAKE_MAP_PROPERTY(environment_variables, has_environment_variable,
|
||||||
|
get_environment_variable, set_environment_variable);
|
||||||
|
|
||||||
MAKE_SEQ_PROPERTY(args, get_num_args, get_arg);
|
MAKE_SEQ_PROPERTY(args, get_num_args, get_arg);
|
||||||
MAKE_PROPERTY(binary_name, get_binary_name, set_binary_name);
|
MAKE_PROPERTY(binary_name, get_binary_name, set_binary_name);
|
||||||
MAKE_PROPERTY(dtool_name, get_dtool_name, set_dtool_name);
|
MAKE_PROPERTY(dtool_name, get_dtool_name, set_dtool_name);
|
||||||
|
@ -75,8 +75,8 @@ InterfaceMaker::MakeSeq::
|
|||||||
MakeSeq(const string &name, const InterrogateMakeSeq &imake_seq) :
|
MakeSeq(const string &name, const InterrogateMakeSeq &imake_seq) :
|
||||||
_name(name),
|
_name(name),
|
||||||
_imake_seq(imake_seq),
|
_imake_seq(imake_seq),
|
||||||
_length_getter(NULL),
|
_length_getter(nullptr),
|
||||||
_element_getter(NULL)
|
_element_getter(nullptr)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,12 +86,10 @@ MakeSeq(const string &name, const InterrogateMakeSeq &imake_seq) :
|
|||||||
InterfaceMaker::Property::
|
InterfaceMaker::Property::
|
||||||
Property(const InterrogateElement &ielement) :
|
Property(const InterrogateElement &ielement) :
|
||||||
_ielement(ielement),
|
_ielement(ielement),
|
||||||
_length_function(NULL),
|
_length_function(nullptr),
|
||||||
_getter(NULL),
|
_has_function(nullptr),
|
||||||
_setter(NULL),
|
_clear_function(nullptr),
|
||||||
_has_function(NULL),
|
_deleter(nullptr),
|
||||||
_clear_function(NULL),
|
|
||||||
_deleter(NULL),
|
|
||||||
_has_this(false)
|
_has_this(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -126,9 +126,9 @@ public:
|
|||||||
Property(const InterrogateElement &ielement);
|
Property(const InterrogateElement &ielement);
|
||||||
|
|
||||||
const InterrogateElement &_ielement;
|
const InterrogateElement &_ielement;
|
||||||
|
vector<FunctionRemap *> _getter_remaps;
|
||||||
|
vector<FunctionRemap *> _setter_remaps;
|
||||||
Function *_length_function;
|
Function *_length_function;
|
||||||
Function *_getter;
|
|
||||||
Function *_setter;
|
|
||||||
Function *_has_function;
|
Function *_has_function;
|
||||||
Function *_clear_function;
|
Function *_clear_function;
|
||||||
Function *_deleter;
|
Function *_deleter;
|
||||||
|
@ -2640,8 +2640,7 @@ write_module_class(ostream &out, Object *obj) {
|
|||||||
for (pit = obj->_properties.begin(); pit != obj->_properties.end(); ++pit) {
|
for (pit = obj->_properties.begin(); pit != obj->_properties.end(); ++pit) {
|
||||||
Property *property = (*pit);
|
Property *property = (*pit);
|
||||||
const InterrogateElement &ielem = property->_ielement;
|
const InterrogateElement &ielem = property->_ielement;
|
||||||
if (!property->_has_this ||
|
if (!property->_has_this || property->_getter_remaps.empty()) {
|
||||||
property->_getter == NULL || !is_function_legal(property->_getter)) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2652,8 +2651,7 @@ write_module_class(ostream &out, Object *obj) {
|
|||||||
|
|
||||||
string getter = "&Dtool_" + ClassName + "_" + ielem.get_name() + "_Getter";
|
string getter = "&Dtool_" + ClassName + "_" + ielem.get_name() + "_Getter";
|
||||||
string setter = "NULL";
|
string setter = "NULL";
|
||||||
if (property->_length_function == NULL &&
|
if (!ielem.is_sequence() && !ielem.is_mapping() && !property->_setter_remaps.empty()) {
|
||||||
property->_setter != NULL && is_function_legal(property->_setter)) {
|
|
||||||
setter = "&Dtool_" + ClassName + "_" + ielem.get_name() + "_Setter";
|
setter = "&Dtool_" + ClassName + "_" + ielem.get_name() + "_Setter";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3190,8 +3188,7 @@ write_module_class(ostream &out, Object *obj) {
|
|||||||
for (pit = obj->_properties.begin(); pit != obj->_properties.end(); ++pit) {
|
for (pit = obj->_properties.begin(); pit != obj->_properties.end(); ++pit) {
|
||||||
Property *property = (*pit);
|
Property *property = (*pit);
|
||||||
const InterrogateElement &ielem = property->_ielement;
|
const InterrogateElement &ielem = property->_ielement;
|
||||||
if (property->_has_this ||
|
if (property->_has_this || property->_getter_remaps.empty()) {
|
||||||
property->_getter == NULL || !is_function_legal(property->_getter)) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3200,8 +3197,7 @@ write_module_class(ostream &out, Object *obj) {
|
|||||||
|
|
||||||
string getter = "&Dtool_" + ClassName + "_" + ielem.get_name() + "_Getter";
|
string getter = "&Dtool_" + ClassName + "_" + ielem.get_name() + "_Getter";
|
||||||
string setter = "NULL";
|
string setter = "NULL";
|
||||||
if (property->_length_function == NULL &&
|
if (!ielem.is_sequence() && !ielem.is_mapping() && !property->_setter_remaps.empty()) {
|
||||||
property->_setter != NULL && is_function_legal(property->_setter)) {
|
|
||||||
setter = "&Dtool_" + ClassName + "_" + ielem.get_name() + "_Setter";
|
setter = "&Dtool_" + ClassName + "_" + ielem.get_name() + "_Setter";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5997,7 +5993,7 @@ write_function_instance(ostream &out, FunctionRemap *remap,
|
|||||||
// this for coercion constructors since they are called by other wrapper
|
// this for coercion constructors since they are called by other wrapper
|
||||||
// functions which already check this on their own. Generated getters
|
// functions which already check this on their own. Generated getters
|
||||||
// obviously can't raise asserts.
|
// obviously can't raise asserts.
|
||||||
if (watch_asserts && (return_flags & RF_coerced) == 0 &&
|
if (watch_asserts && (return_flags & (RF_coerced | RF_raise_keyerror)) == 0 &&
|
||||||
remap->_type != FunctionRemap::T_getter &&
|
remap->_type != FunctionRemap::T_getter &&
|
||||||
remap->_type != FunctionRemap::T_setter) {
|
remap->_type != FunctionRemap::T_setter) {
|
||||||
out << "#ifndef NDEBUG\n";
|
out << "#ifndef NDEBUG\n";
|
||||||
@ -6126,6 +6122,27 @@ write_function_instance(ostream &out, FunctionRemap *remap,
|
|||||||
indent(out, indent_level) << "manage = true;\n";
|
indent(out, indent_level) << "manage = true;\n";
|
||||||
indent(out, indent_level) << "return true;\n";
|
indent(out, indent_level) << "return true;\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} else if (return_flags & RF_raise_keyerror) {
|
||||||
|
CPPType *orig_type = remap->_return_type->get_orig_type();
|
||||||
|
|
||||||
|
if (TypeManager::is_bool(orig_type) || TypeManager::is_pointer(orig_type)) {
|
||||||
|
indent(out, indent_level) << "if (!" << return_expr << ") {\n";
|
||||||
|
} else if (TypeManager::is_unsigned_integer(orig_type)) {
|
||||||
|
indent(out, indent_level) << "if ((int)" << return_expr << " == -1) {\n";
|
||||||
|
} else if (TypeManager::is_integer(orig_type)) {
|
||||||
|
indent(out, indent_level) << "if (" << return_expr << " < 0) {\n";
|
||||||
|
} else {
|
||||||
|
indent(out, indent_level) << "if (false) {\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args_type == AT_single_arg) {
|
||||||
|
indent(out, indent_level) << " PyErr_SetObject(PyExc_KeyError, arg);\n";
|
||||||
|
} else {
|
||||||
|
indent(out, indent_level) << " PyErr_SetObject(PyExc_KeyError, key);\n";
|
||||||
|
}
|
||||||
|
error_return(out, indent_level + 2, return_flags);
|
||||||
|
indent(out, indent_level) << "}\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close the extra braces opened earlier.
|
// Close the extra braces opened earlier.
|
||||||
@ -6398,19 +6415,21 @@ write_make_seq(ostream &out, Object *obj, const std::string &ClassName,
|
|||||||
*/
|
*/
|
||||||
void InterfaceMakerPythonNative::
|
void InterfaceMakerPythonNative::
|
||||||
write_getset(ostream &out, Object *obj, Property *property) {
|
write_getset(ostream &out, Object *obj, Property *property) {
|
||||||
|
// We keep around this empty vector for passing to get_call_str.
|
||||||
|
const vector_string pexprs;
|
||||||
|
|
||||||
string ClassName = make_safe_name(obj->_itype.get_scoped_name());
|
string ClassName = make_safe_name(obj->_itype.get_scoped_name());
|
||||||
std::string cClassName = obj->_itype.get_true_name();
|
std::string cClassName = obj->_itype.get_true_name();
|
||||||
|
|
||||||
const InterrogateElement &ielem = property->_ielement;
|
const InterrogateElement &ielem = property->_ielement;
|
||||||
|
|
||||||
if (property->_length_function != NULL) {
|
FunctionRemap *len_remap = nullptr;
|
||||||
|
if (property->_length_function != nullptr) {
|
||||||
// This is actually a sequence. Wrap this with a special class.
|
// This is actually a sequence. Wrap this with a special class.
|
||||||
FunctionRemap *len_remap = property->_length_function->_remaps.front();
|
len_remap = property->_length_function->_remaps.front();
|
||||||
vector_string pexprs;
|
|
||||||
|
|
||||||
out << "/**\n"
|
out << "/**\n"
|
||||||
" * sequence length function for property " << cClassName << "::" << ielem.get_name() << "\n"
|
" * sequence length function for property " << ielem.get_scoped_name() << "\n"
|
||||||
" */\n"
|
" */\n"
|
||||||
"static Py_ssize_t Dtool_" + ClassName + "_" + ielem.get_name() + "_Len(PyObject *self) {\n";
|
"static Py_ssize_t Dtool_" + ClassName + "_" + ielem.get_name() + "_Len(PyObject *self) {\n";
|
||||||
if (property->_length_function->_has_this) {
|
if (property->_length_function->_has_this) {
|
||||||
@ -6424,72 +6443,72 @@ write_getset(ostream &out, Object *obj, Property *property) {
|
|||||||
out << " return (Py_ssize_t)" << len_remap->get_call_str("", pexprs) << ";\n";
|
out << " return (Py_ssize_t)" << len_remap->get_call_str("", pexprs) << ";\n";
|
||||||
}
|
}
|
||||||
out << "}\n\n";
|
out << "}\n\n";
|
||||||
|
}
|
||||||
|
|
||||||
// Now write out the getitem helper function.
|
if (property->_getter_remaps.empty()) {
|
||||||
if (property->_getter != NULL) {
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ielem.is_sequence()) {
|
||||||
|
out <<
|
||||||
|
"/**\n"
|
||||||
|
" * sequence getter for property " << ielem.get_scoped_name() << "\n"
|
||||||
|
" */\n"
|
||||||
|
"static PyObject *Dtool_" + ClassName + "_" + ielem.get_name() + "_Sequence_Getitem(PyObject *self, Py_ssize_t index) {\n";
|
||||||
|
|
||||||
|
if (property->_has_this) {
|
||||||
out <<
|
out <<
|
||||||
"/**\n"
|
" " << cClassName << " *local_this = NULL;\n"
|
||||||
" * sequence getter for property " << cClassName << "::" << ielem.get_name() << "\n"
|
" if (!Dtool_Call_ExtractThisPointer(self, Dtool_" << ClassName << ", (void **)&local_this)) {\n"
|
||||||
" */\n"
|
" return NULL;\n"
|
||||||
"static PyObject *Dtool_" + ClassName + "_" + ielem.get_name() + "_Getitem(PyObject *self, Py_ssize_t index) {\n";
|
" }\n";
|
||||||
if (property->_getter->_has_this ||
|
|
||||||
(property->_has_function && property->_has_function->_has_this)) {
|
|
||||||
out <<
|
|
||||||
" " << cClassName << " *local_this = NULL;\n"
|
|
||||||
" if (!Dtool_Call_ExtractThisPointer(self, Dtool_" << ClassName << ", (void **)&local_this)) {\n"
|
|
||||||
" return NULL;\n"
|
|
||||||
" }\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is a getitem of a sequence type. This means we *need* to raise
|
|
||||||
// IndexError if we're out of bounds.
|
|
||||||
out << " if (index < 0 || index >= (Py_ssize_t)"
|
|
||||||
<< len_remap->get_call_str("local_this", pexprs) << ") {\n";
|
|
||||||
out << " PyErr_SetString(PyExc_IndexError, \"" << ClassName << "." << ielem.get_name() << "[] index out of range\");\n";
|
|
||||||
out << " return NULL;\n";
|
|
||||||
out << " }\n";
|
|
||||||
|
|
||||||
if (property->_has_function != NULL) {
|
|
||||||
if (property->_has_function->_has_this) {
|
|
||||||
out << " if (!local_this->" << property->_has_function->_ifunc.get_name() << "(index)) {\n";
|
|
||||||
} else {
|
|
||||||
out << " if (!" << cClassName << "::" << property->_has_function->_ifunc.get_name() << "(index)) {\n";
|
|
||||||
}
|
|
||||||
out << " Py_INCREF(Py_None);\n"
|
|
||||||
<< " return Py_None;\n"
|
|
||||||
<< " }\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
std::set<FunctionRemap*> remaps;
|
|
||||||
|
|
||||||
// Extract only the getters that take one argument.
|
|
||||||
Function::Remaps::iterator it;
|
|
||||||
for (it = property->_getter->_remaps.begin();
|
|
||||||
it != property->_getter->_remaps.end();
|
|
||||||
++it) {
|
|
||||||
FunctionRemap *remap = *it;
|
|
||||||
int min_num_args = remap->get_min_num_args();
|
|
||||||
int max_num_args = remap->get_max_num_args();
|
|
||||||
if (min_num_args <= 1 && max_num_args >= 1) {
|
|
||||||
remaps.insert(remap);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
string expected_params;
|
|
||||||
write_function_forset(out, remaps, 1, 1, expected_params, 2, true, true,
|
|
||||||
AT_no_args, RF_pyobject | RF_err_null, false, true, "index");
|
|
||||||
|
|
||||||
out << " if (!_PyErr_OCCURRED()) {\n";
|
|
||||||
out << " return Dtool_Raise_BadArgumentsError(\n";
|
|
||||||
output_quoted(out, 6, expected_params);
|
|
||||||
out << ");\n"
|
|
||||||
" }\n"
|
|
||||||
"}\n\n";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is a getitem of a sequence type. This means we *need* to raise
|
||||||
|
// IndexError if we're out of bounds.
|
||||||
|
out << " if (index < 0 || index >= (Py_ssize_t)"
|
||||||
|
<< len_remap->get_call_str("local_this", pexprs) << ") {\n";
|
||||||
|
out << " PyErr_SetString(PyExc_IndexError, \"" << ClassName << "." << ielem.get_name() << "[] index out of range\");\n";
|
||||||
|
out << " return NULL;\n";
|
||||||
|
out << " }\n";
|
||||||
|
|
||||||
|
/*if (property->_has_function != NULL) {
|
||||||
|
out << " if (!local_this->" << property->_has_function->_ifunc.get_name() << "(index)) {\n"
|
||||||
|
<< " Py_INCREF(Py_None);\n"
|
||||||
|
<< " return Py_None;\n"
|
||||||
|
<< " }\n";
|
||||||
|
}*/
|
||||||
|
|
||||||
|
std::set<FunctionRemap*> remaps;
|
||||||
|
|
||||||
|
// Extract only the getters that take one integral argument.
|
||||||
|
Function::Remaps::iterator it;
|
||||||
|
for (it = property->_getter_remaps.begin();
|
||||||
|
it != property->_getter_remaps.end();
|
||||||
|
++it) {
|
||||||
|
FunctionRemap *remap = *it;
|
||||||
|
int min_num_args = remap->get_min_num_args();
|
||||||
|
int max_num_args = remap->get_max_num_args();
|
||||||
|
if (min_num_args <= 1 && max_num_args >= 1 &&
|
||||||
|
TypeManager::is_integer(remap->_parameters[(size_t)remap->_has_this]._remap->get_new_type())) {
|
||||||
|
remaps.insert(remap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string expected_params;
|
||||||
|
write_function_forset(out, remaps, 1, 1, expected_params, 2, true, true,
|
||||||
|
AT_no_args, RF_pyobject | RF_err_null, false, true, "index");
|
||||||
|
|
||||||
|
out << " if (!_PyErr_OCCURRED()) {\n";
|
||||||
|
out << " return Dtool_Raise_BadArgumentsError(\n";
|
||||||
|
output_quoted(out, 6, expected_params);
|
||||||
|
out << ");\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n\n";
|
||||||
|
|
||||||
// Write out a setitem if this is not a read-only property.
|
// Write out a setitem if this is not a read-only property.
|
||||||
if (property->_setter != NULL) {
|
if (!property->_setter_remaps.empty()) {
|
||||||
out << "static int Dtool_" + ClassName + "_" + ielem.get_name() + "_Setitem(PyObject *self, Py_ssize_t index, PyObject *arg) {\n";
|
out << "static int Dtool_" + ClassName + "_" + ielem.get_name() + "_Sequence_Setitem(PyObject *self, Py_ssize_t index, PyObject *arg) {\n";
|
||||||
if (property->_has_this) {
|
if (property->_has_this) {
|
||||||
out << " " << cClassName << " *local_this = NULL;\n";
|
out << " " << cClassName << " *local_this = NULL;\n";
|
||||||
out << " if (!Dtool_Call_ExtractThisPointer_NonConst(self, Dtool_" << ClassName << ", (void **)&local_this, \""
|
out << " if (!Dtool_Call_ExtractThisPointer_NonConst(self, Dtool_" << ClassName << ", (void **)&local_this, \""
|
||||||
@ -6527,13 +6546,14 @@ write_getset(ostream &out, Object *obj, Property *property) {
|
|||||||
|
|
||||||
// Extract only the setters that take two arguments.
|
// Extract only the setters that take two arguments.
|
||||||
Function::Remaps::iterator it;
|
Function::Remaps::iterator it;
|
||||||
for (it = property->_setter->_remaps.begin();
|
for (it = property->_setter_remaps.begin();
|
||||||
it != property->_setter->_remaps.end();
|
it != property->_setter_remaps.end();
|
||||||
++it) {
|
++it) {
|
||||||
FunctionRemap *remap = *it;
|
FunctionRemap *remap = *it;
|
||||||
int min_num_args = remap->get_min_num_args();
|
int min_num_args = remap->get_min_num_args();
|
||||||
int max_num_args = remap->get_max_num_args();
|
int max_num_args = remap->get_max_num_args();
|
||||||
if (min_num_args <= 2 && max_num_args >= 2) {
|
if (min_num_args <= 2 && max_num_args >= 2 &&
|
||||||
|
TypeManager::is_integer(remap->_parameters[1]._remap->get_new_type())) {
|
||||||
remaps.insert(remap);
|
remaps.insert(remap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -6551,8 +6571,192 @@ write_getset(ostream &out, Object *obj, Property *property) {
|
|||||||
out << " return -1;\n";
|
out << " return -1;\n";
|
||||||
out << "}\n\n";
|
out << "}\n\n";
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Now write the getter, which returns a special wrapper object.
|
|
||||||
|
// Write the getitem functions.
|
||||||
|
if (ielem.is_mapping()) {
|
||||||
|
out <<
|
||||||
|
"/**\n"
|
||||||
|
" * mapping getitem for property " << ielem.get_scoped_name() << "\n"
|
||||||
|
" */\n"
|
||||||
|
"static PyObject *Dtool_" + ClassName + "_" + ielem.get_name() + "_Mapping_Getitem(PyObject *self, PyObject *arg) {\n";
|
||||||
|
|
||||||
|
// Before we do the has_function: if this is also a sequence, then we have
|
||||||
|
// to also handle the case here that we were passed an index.
|
||||||
|
if (ielem.is_sequence()) {
|
||||||
|
out <<
|
||||||
|
"#if PY_MAJOR_VERSION >= 3\n"
|
||||||
|
" if (PyLong_CheckExact(arg)) {\n"
|
||||||
|
"#else\n"
|
||||||
|
" if (PyLong_CheckExact(arg) || PyInt_CheckExact(arg)) {\n"
|
||||||
|
"#endif\n"
|
||||||
|
" return Dtool_" << ClassName << "_" << ielem.get_name() << "_Sequence_Getitem(self, PyLongOrInt_AsSize_t(arg));\n"
|
||||||
|
" }\n\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (property->_has_this) {
|
||||||
|
out <<
|
||||||
|
" " << cClassName << " *local_this = NULL;\n"
|
||||||
|
" if (!Dtool_Call_ExtractThisPointer(self, Dtool_" << ClassName << ", (void **)&local_this)) {\n"
|
||||||
|
" return NULL;\n"
|
||||||
|
" }\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (property->_has_function != NULL) {
|
||||||
|
std::set<FunctionRemap*> remaps;
|
||||||
|
remaps.insert(property->_has_function->_remaps.begin(),
|
||||||
|
property->_has_function->_remaps.end());
|
||||||
|
|
||||||
|
out << " {\n";
|
||||||
|
string expected_params;
|
||||||
|
write_function_forset(out, remaps, 1, 1, expected_params, 4, true, true,
|
||||||
|
AT_single_arg, RF_raise_keyerror | RF_err_null, false, true);
|
||||||
|
out << " }\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::set<FunctionRemap*> remaps;
|
||||||
|
// Extract only the getters that take one argument. Fish out the ones
|
||||||
|
// already taken by the sequence getter.
|
||||||
|
Function::Remaps::iterator it;
|
||||||
|
for (it = property->_getter_remaps.begin();
|
||||||
|
it != property->_getter_remaps.end();
|
||||||
|
++it) {
|
||||||
|
FunctionRemap *remap = *it;
|
||||||
|
int min_num_args = remap->get_min_num_args();
|
||||||
|
int max_num_args = remap->get_max_num_args();
|
||||||
|
if (min_num_args <= 1 && max_num_args >= 1 &&
|
||||||
|
(!ielem.is_sequence() || !TypeManager::is_integer(remap->_parameters[(size_t)remap->_has_this]._remap->get_new_type()))) {
|
||||||
|
remaps.insert(remap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string expected_params;
|
||||||
|
write_function_forset(out, remaps, 1, 1, expected_params, 2, true, true,
|
||||||
|
AT_single_arg, RF_pyobject | RF_err_null, false, true);
|
||||||
|
|
||||||
|
out << " if (!_PyErr_OCCURRED()) {\n";
|
||||||
|
out << " return Dtool_Raise_BadArgumentsError(\n";
|
||||||
|
output_quoted(out, 6, expected_params);
|
||||||
|
out << ");\n"
|
||||||
|
" }\n"
|
||||||
|
" return NULL;\n"
|
||||||
|
"}\n\n";
|
||||||
|
|
||||||
|
// Write out a setitem if this is not a read-only property.
|
||||||
|
if (!property->_setter_remaps.empty()) {
|
||||||
|
out <<
|
||||||
|
"/**\n"
|
||||||
|
" * mapping setitem for property " << ielem.get_scoped_name() << "\n"
|
||||||
|
" */\n"
|
||||||
|
"static int Dtool_" + ClassName + "_" + ielem.get_name() + "_Mapping_Setitem(PyObject *self, PyObject *key, PyObject *value) {\n";
|
||||||
|
|
||||||
|
if (property->_has_this) {
|
||||||
|
out <<
|
||||||
|
" " << cClassName << " *local_this = NULL;\n"
|
||||||
|
" if (!Dtool_Call_ExtractThisPointer_NonConst(self, Dtool_" << ClassName << ", (void **)&local_this, \""
|
||||||
|
<< classNameFromCppName(cClassName, false) << "." << ielem.get_name() << "\")) {\n"
|
||||||
|
" return -1;\n"
|
||||||
|
" }\n\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
out << " if (value == (PyObject *)NULL) {\n";
|
||||||
|
if (property->_deleter != NULL) {
|
||||||
|
out << " PyObject *arg = key;\n";
|
||||||
|
std::set<FunctionRemap*> remaps;
|
||||||
|
remaps.insert(property->_deleter->_remaps.begin(),
|
||||||
|
property->_deleter->_remaps.end());
|
||||||
|
|
||||||
|
string expected_params;
|
||||||
|
write_function_forset(out, remaps, 1, 1,
|
||||||
|
expected_params, 4, true, true, AT_single_arg,
|
||||||
|
RF_int, false, false);
|
||||||
|
out << " return -1;\n";
|
||||||
|
} else {
|
||||||
|
out << " Dtool_Raise_TypeError(\"can't delete " << ielem.get_name() << "[] attribute\");\n"
|
||||||
|
" return -1;\n";
|
||||||
|
}
|
||||||
|
out << " }\n";
|
||||||
|
|
||||||
|
if (property->_clear_function != NULL) {
|
||||||
|
out << " if (value == Py_None) {\n"
|
||||||
|
<< " local_this->" << property->_clear_function->_ifunc.get_name() << "(key);\n"
|
||||||
|
<< " return 0;\n"
|
||||||
|
<< " }\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::set<FunctionRemap*> remaps;
|
||||||
|
remaps.insert(property->_setter_remaps.begin(),
|
||||||
|
property->_setter_remaps.end());
|
||||||
|
|
||||||
|
// We have to create an args tuple only to unpack it alter, ugh.
|
||||||
|
out << " PyObject *args = PyTuple_New(2);\n"
|
||||||
|
<< " PyTuple_SET_ITEM(args, 0, key);\n"
|
||||||
|
<< " PyTuple_SET_ITEM(args, 1, value);\n"
|
||||||
|
<< " Py_INCREF(key);\n"
|
||||||
|
<< " Py_INCREF(value);\n";
|
||||||
|
|
||||||
|
string expected_params;
|
||||||
|
write_function_forset(out, remaps, 2, 2,
|
||||||
|
expected_params, 2, true, true, AT_varargs,
|
||||||
|
RF_int | RF_decref_args, false, false);
|
||||||
|
|
||||||
|
out << " if (!_PyErr_OCCURRED()) {\n";
|
||||||
|
out << " Dtool_Raise_BadArgumentsError(\n";
|
||||||
|
output_quoted(out, 6, expected_params);
|
||||||
|
out << ");\n";
|
||||||
|
out << " }\n";
|
||||||
|
out << " Py_DECREF(args);\n";
|
||||||
|
out << " return -1;\n";
|
||||||
|
out << "}\n\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now write the actual getter wrapper. It will be a different wrapper
|
||||||
|
// depending on whether it's a mapping, sequence, or both.
|
||||||
|
if (ielem.is_mapping() && ielem.is_sequence()) {
|
||||||
|
out << "static PyObject *Dtool_" + ClassName + "_" + ielem.get_name() + "_Getter(PyObject *self, void *) {\n";
|
||||||
|
if (property->_has_this) {
|
||||||
|
out << " nassertr(self != NULL, NULL);\n"
|
||||||
|
" Py_INCREF(self);\n";
|
||||||
|
} else {
|
||||||
|
out << " Py_XINCREF(self);\n";
|
||||||
|
}
|
||||||
|
out << " Dtool_SeqMapWrapper *wrap = PyObject_New(Dtool_SeqMapWrapper, &Dtool_SeqMapWrapper_Type);\n"
|
||||||
|
" wrap->_seq._base._self = self;\n"
|
||||||
|
" wrap->_seq._len_func = &Dtool_" << ClassName << "_" << ielem.get_name() << "_Len;\n"
|
||||||
|
" wrap->_seq._getitem_func = &Dtool_" << ClassName << "_" << ielem.get_name() << "_Sequence_Getitem;\n"
|
||||||
|
" wrap->_map_getitem_func = &Dtool_" << ClassName << "_" << ielem.get_name() << "_Mapping_Getitem;\n";
|
||||||
|
if (!property->_setter_remaps.empty()) {
|
||||||
|
out << " wrap->_seq._setitem_func = &Dtool_" << ClassName << "_" << ielem.get_name() << "_Sequence_Setitem;\n";
|
||||||
|
out << " wrap->_map_setitem_func = &Dtool_" << ClassName << "_" << ielem.get_name() << "_Mapping_Setitem;\n";
|
||||||
|
} else {
|
||||||
|
out << " wrap->_seq._setitem_func = NULL;\n";
|
||||||
|
out << " wrap->_map_setitem_func = NULL;\n";
|
||||||
|
}
|
||||||
|
out << " return (PyObject *)wrap;\n"
|
||||||
|
"}\n\n";
|
||||||
|
|
||||||
|
} else if (ielem.is_mapping()) {
|
||||||
|
out << "static PyObject *Dtool_" + ClassName + "_" + ielem.get_name() + "_Getter(PyObject *self, void *) {\n";
|
||||||
|
if (property->_has_this) {
|
||||||
|
out << " nassertr(self != NULL, NULL);\n"
|
||||||
|
" Py_INCREF(self);\n";
|
||||||
|
} else {
|
||||||
|
out << " Py_XINCREF(self);\n";
|
||||||
|
}
|
||||||
|
out << " Dtool_MappingWrapper *wrap = PyObject_New(Dtool_MappingWrapper, &Dtool_MappingWrapper_Type);\n"
|
||||||
|
" wrap->_base._self = self;\n"
|
||||||
|
" wrap->_getitem_func = &Dtool_" << ClassName << "_" << ielem.get_name() << "_Mapping_Getitem;\n";
|
||||||
|
if (!property->_setter_remaps.empty()) {
|
||||||
|
out << " wrap->_setitem_func = &Dtool_" << ClassName << "_" << ielem.get_name() << "_Mapping_Setitem;\n";
|
||||||
|
} else {
|
||||||
|
out << " wrap->_setitem_func = NULL;\n";
|
||||||
|
}
|
||||||
|
out << " return (PyObject *)wrap;\n"
|
||||||
|
"}\n\n";
|
||||||
|
|
||||||
|
} else if (ielem.is_sequence()) {
|
||||||
out << "static PyObject *Dtool_" + ClassName + "_" + ielem.get_name() + "_Getter(PyObject *self, void *) {\n";
|
out << "static PyObject *Dtool_" + ClassName + "_" + ielem.get_name() + "_Getter(PyObject *self, void *) {\n";
|
||||||
if (property->_has_this) {
|
if (property->_has_this) {
|
||||||
out << " nassertr(self != NULL, NULL);\n"
|
out << " nassertr(self != NULL, NULL);\n"
|
||||||
@ -6561,21 +6765,21 @@ write_getset(ostream &out, Object *obj, Property *property) {
|
|||||||
out << " Py_XINCREF(self);\n";
|
out << " Py_XINCREF(self);\n";
|
||||||
}
|
}
|
||||||
out << " Dtool_SequenceWrapper *wrap = PyObject_New(Dtool_SequenceWrapper, &Dtool_SequenceWrapper_Type);\n"
|
out << " Dtool_SequenceWrapper *wrap = PyObject_New(Dtool_SequenceWrapper, &Dtool_SequenceWrapper_Type);\n"
|
||||||
" wrap->_base = self;\n"
|
" wrap->_base._self = self;\n"
|
||||||
" wrap->_len_func = &Dtool_" << ClassName << "_" << ielem.get_name() << "_Len;\n"
|
" wrap->_len_func = &Dtool_" << ClassName << "_" << ielem.get_name() << "_Len;\n"
|
||||||
" wrap->_getitem_func = &Dtool_" << ClassName << "_" << ielem.get_name() << "_Getitem;\n";
|
" wrap->_getitem_func = &Dtool_" << ClassName << "_" << ielem.get_name() << "_Sequence_Getitem;\n";
|
||||||
if (property->_setter != NULL) {
|
if (!property->_setter_remaps.empty()) {
|
||||||
out << " wrap->_setitem_func = &Dtool_" << ClassName << "_" << ielem.get_name() << "_Setitem;\n";
|
out << " wrap->_setitem_func = &Dtool_" << ClassName << "_" << ielem.get_name() << "_Sequence_Setitem;\n";
|
||||||
} else {
|
} else {
|
||||||
out << " wrap->_setitem_func = NULL;\n";
|
out << " wrap->_setitem_func = NULL;\n";
|
||||||
}
|
}
|
||||||
out << " return (PyObject *)wrap;\n"
|
out << " return (PyObject *)wrap;\n"
|
||||||
"}\n\n";
|
"}\n\n";
|
||||||
|
|
||||||
} else if (property->_getter != NULL) {
|
} else {
|
||||||
// Write out a regular, unwrapped getter.
|
// Write out a regular, unwrapped getter.
|
||||||
out << "static PyObject *Dtool_" + ClassName + "_" + ielem.get_name() + "_Getter(PyObject *self, void *) {\n";
|
out << "static PyObject *Dtool_" + ClassName + "_" + ielem.get_name() + "_Getter(PyObject *self, void *) {\n";
|
||||||
FunctionRemap *remap = property->_getter->_remaps.front();
|
FunctionRemap *remap = property->_getter_remaps.front();
|
||||||
|
|
||||||
if (remap->_has_this) {
|
if (remap->_has_this) {
|
||||||
if (remap->_const_method) {
|
if (remap->_const_method) {
|
||||||
@ -6611,7 +6815,7 @@ write_getset(ostream &out, Object *obj, Property *property) {
|
|||||||
out << "}\n\n";
|
out << "}\n\n";
|
||||||
|
|
||||||
// Write out a setter if this is not a read-only property.
|
// Write out a setter if this is not a read-only property.
|
||||||
if (property->_setter != NULL) {
|
if (!property->_setter_remaps.empty()) {
|
||||||
out << "static int Dtool_" + ClassName + "_" + ielem.get_name() + "_Setter(PyObject *self, PyObject *arg, void *) {\n";
|
out << "static int Dtool_" + ClassName + "_" + ielem.get_name() + "_Setter(PyObject *self, PyObject *arg, void *) {\n";
|
||||||
if (remap->_has_this) {
|
if (remap->_has_this) {
|
||||||
out << " " << cClassName << " *local_this = NULL;\n";
|
out << " " << cClassName << " *local_this = NULL;\n";
|
||||||
@ -6630,7 +6834,7 @@ write_getset(ostream &out, Object *obj, Property *property) {
|
|||||||
<< " return 0;\n";
|
<< " return 0;\n";
|
||||||
} else {
|
} else {
|
||||||
out << " Dtool_Raise_TypeError(\"can't delete " << ielem.get_name() << " attribute\");\n"
|
out << " Dtool_Raise_TypeError(\"can't delete " << ielem.get_name() << " attribute\");\n"
|
||||||
" return -1;\n";
|
" return -1;\n";
|
||||||
}
|
}
|
||||||
out << " }\n";
|
out << " }\n";
|
||||||
|
|
||||||
@ -6649,9 +6853,9 @@ write_getset(ostream &out, Object *obj, Property *property) {
|
|||||||
|
|
||||||
// Extract only the setters that take one argument.
|
// Extract only the setters that take one argument.
|
||||||
Function::Remaps::iterator it;
|
Function::Remaps::iterator it;
|
||||||
for (it = property->_setter->_remaps.begin();
|
for (it = property->_setter_remaps.begin();
|
||||||
it != property->_setter->_remaps.end();
|
it != property->_setter_remaps.end();
|
||||||
++it) {
|
++it) {
|
||||||
FunctionRemap *remap = *it;
|
FunctionRemap *remap = *it;
|
||||||
int min_num_args = remap->get_min_num_args();
|
int min_num_args = remap->get_min_num_args();
|
||||||
int max_num_args = remap->get_max_num_args();
|
int max_num_args = remap->get_max_num_args();
|
||||||
@ -6763,62 +6967,8 @@ record_object(TypeIndex type_index) {
|
|||||||
ElementIndex element_index = itype.get_element(ei);
|
ElementIndex element_index = itype.get_element(ei);
|
||||||
const InterrogateElement &ielement = idb->get_element(element_index);
|
const InterrogateElement &ielement = idb->get_element(element_index);
|
||||||
|
|
||||||
Property *property = new Property(ielement);
|
Property *property = record_property(itype, itype.get_element(ei));
|
||||||
|
if (property != nullptr) {
|
||||||
if (ielement.has_setter()) {
|
|
||||||
FunctionIndex func_index = ielement.get_setter();
|
|
||||||
Function *setter = record_function(itype, func_index);
|
|
||||||
if (is_function_legal(setter)) {
|
|
||||||
property->_setter = setter;
|
|
||||||
property->_has_this |= setter->_has_this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ielement.has_getter()) {
|
|
||||||
FunctionIndex func_index = ielement.get_getter();
|
|
||||||
Function *getter = record_function(itype, func_index);
|
|
||||||
if (is_function_legal(getter)) {
|
|
||||||
property->_getter = getter;
|
|
||||||
property->_has_this |= getter->_has_this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ielement.has_has_function()) {
|
|
||||||
FunctionIndex func_index = ielement.get_has_function();
|
|
||||||
Function *has_function = record_function(itype, func_index);
|
|
||||||
if (is_function_legal(has_function)) {
|
|
||||||
property->_has_function = has_function;
|
|
||||||
property->_has_this |= has_function->_has_this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ielement.has_clear_function()) {
|
|
||||||
FunctionIndex func_index = ielement.get_clear_function();
|
|
||||||
Function *clear_function = record_function(itype, func_index);
|
|
||||||
if (is_function_legal(clear_function)) {
|
|
||||||
property->_clear_function = clear_function;
|
|
||||||
property->_has_this |= clear_function->_has_this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ielement.has_del_function()) {
|
|
||||||
FunctionIndex func_index = ielement.get_del_function();
|
|
||||||
Function *del_function = record_function(itype, func_index);
|
|
||||||
if (is_function_legal(del_function)) {
|
|
||||||
property->_deleter = del_function;
|
|
||||||
property->_has_this |= del_function->_has_this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ielement.is_sequence()) {
|
|
||||||
FunctionIndex func_index = ielement.get_length_function();
|
|
||||||
property->_length_function = record_function(itype, func_index);
|
|
||||||
if (property->_length_function != nullptr) {
|
|
||||||
property->_has_this |= property->_length_function->_has_this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (property->_getter != NULL) {
|
|
||||||
object->_properties.push_back(property);
|
object->_properties.push_back(property);
|
||||||
} else {
|
} else {
|
||||||
// No use exporting a property without a getter.
|
// No use exporting a property without a getter.
|
||||||
@ -6850,6 +7000,96 @@ record_object(TypeIndex type_index) {
|
|||||||
}
|
}
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
InterfaceMaker::Property *InterfaceMakerPythonNative::
|
||||||
|
record_property(const InterrogateType &itype, ElementIndex element_index) {
|
||||||
|
InterrogateDatabase *idb = InterrogateDatabase::get_ptr();
|
||||||
|
const InterrogateElement &ielement = idb->get_element(element_index);
|
||||||
|
if (!ielement.has_getter()) {
|
||||||
|
// A property needs at the very least a getter.
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Property *property;
|
||||||
|
{
|
||||||
|
FunctionIndex func_index = ielement.get_getter();
|
||||||
|
if (func_index != 0) {
|
||||||
|
const InterrogateFunction &ifunc = idb->get_function(func_index);
|
||||||
|
property = new Property(ielement);
|
||||||
|
|
||||||
|
InterrogateFunction::Instances::const_iterator ii;
|
||||||
|
for (ii = ifunc._instances->begin(); ii != ifunc._instances->end(); ++ii) {
|
||||||
|
CPPInstance *cppfunc = (*ii).second;
|
||||||
|
FunctionRemap *remap =
|
||||||
|
make_function_remap(itype, ifunc, cppfunc, 0);
|
||||||
|
|
||||||
|
if (remap != nullptr && is_remap_legal(remap)) {
|
||||||
|
property->_getter_remaps.push_back(remap);
|
||||||
|
property->_has_this |= remap->_has_this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ielement.has_setter()) {
|
||||||
|
FunctionIndex func_index = ielement.get_setter();
|
||||||
|
if (func_index != 0) {
|
||||||
|
const InterrogateFunction &ifunc = idb->get_function(func_index);
|
||||||
|
|
||||||
|
InterrogateFunction::Instances::const_iterator ii;
|
||||||
|
for (ii = ifunc._instances->begin(); ii != ifunc._instances->end(); ++ii) {
|
||||||
|
CPPInstance *cppfunc = (*ii).second;
|
||||||
|
FunctionRemap *remap =
|
||||||
|
make_function_remap(itype, ifunc, cppfunc, 0);
|
||||||
|
|
||||||
|
if (remap != nullptr && is_remap_legal(remap)) {
|
||||||
|
property->_setter_remaps.push_back(remap);
|
||||||
|
property->_has_this |= remap->_has_this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ielement.has_has_function()) {
|
||||||
|
FunctionIndex func_index = ielement.get_has_function();
|
||||||
|
Function *has_function = record_function(itype, func_index);
|
||||||
|
if (is_function_legal(has_function)) {
|
||||||
|
property->_has_function = has_function;
|
||||||
|
property->_has_this |= has_function->_has_this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ielement.has_clear_function()) {
|
||||||
|
FunctionIndex func_index = ielement.get_clear_function();
|
||||||
|
Function *clear_function = record_function(itype, func_index);
|
||||||
|
if (is_function_legal(clear_function)) {
|
||||||
|
property->_clear_function = clear_function;
|
||||||
|
property->_has_this |= clear_function->_has_this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ielement.has_del_function()) {
|
||||||
|
FunctionIndex func_index = ielement.get_del_function();
|
||||||
|
Function *del_function = record_function(itype, func_index);
|
||||||
|
if (is_function_legal(del_function)) {
|
||||||
|
property->_deleter = del_function;
|
||||||
|
property->_has_this |= del_function->_has_this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ielement.is_sequence()) {
|
||||||
|
FunctionIndex func_index = ielement.get_length_function();
|
||||||
|
property->_length_function = record_function(itype, func_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
return property;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Walks through the set of functions in the database and generates wrappers
|
* Walks through the set of functions in the database and generates wrappers
|
||||||
* for each function, storing these in the database. No actual code should be
|
* for each function, storing these in the database. No actual code should be
|
||||||
|
@ -47,6 +47,7 @@ public:
|
|||||||
virtual bool separate_overloading();
|
virtual bool separate_overloading();
|
||||||
|
|
||||||
virtual Object *record_object(TypeIndex type_index);
|
virtual Object *record_object(TypeIndex type_index);
|
||||||
|
Property *record_property(const InterrogateType &itype, ElementIndex element_index);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual string get_wrapper_prefix();
|
virtual string get_wrapper_prefix();
|
||||||
@ -111,6 +112,9 @@ private:
|
|||||||
|
|
||||||
// Decref temporary args object before returning.
|
// Decref temporary args object before returning.
|
||||||
RF_decref_args = 0x1000,
|
RF_decref_args = 0x1000,
|
||||||
|
|
||||||
|
// This raises a KeyError on falsey (or -1) return value.
|
||||||
|
RF_raise_keyerror = 0x4000,
|
||||||
};
|
};
|
||||||
|
|
||||||
class SlottedFunctionDef {
|
class SlottedFunctionDef {
|
||||||
|
@ -1798,34 +1798,46 @@ get_make_property(CPPMakeProperty *make_property, CPPStructType *struct_type, CP
|
|||||||
}
|
}
|
||||||
|
|
||||||
string property_name = make_property->get_local_name(&parser);
|
string property_name = make_property->get_local_name(&parser);
|
||||||
|
InterrogateDatabase *idb = InterrogateDatabase::get_ptr();
|
||||||
|
|
||||||
// First, check to see if it's already there.
|
// First, check to see if it's already there.
|
||||||
|
ElementIndex index = 0;
|
||||||
PropertiesByName::const_iterator tni =
|
PropertiesByName::const_iterator tni =
|
||||||
_properties_by_name.find(property_name);
|
_properties_by_name.find(property_name);
|
||||||
if (tni != _properties_by_name.end()) {
|
if (tni != _properties_by_name.end()) {
|
||||||
ElementIndex index = (*tni).second;
|
index = (*tni).second;
|
||||||
return index;
|
const InterrogateElement &ielem = idb->get_element(index);
|
||||||
|
if (ielem._make_property == make_property) {
|
||||||
|
// This is the same property.
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
// It is possible to have property definitions with the same name, but
|
||||||
|
// they cannot define conflicting interfaces.
|
||||||
|
if ((ielem.is_sequence() || ielem.is_mapping()) !=
|
||||||
|
(make_property->_type != CPPMakeProperty::T_normal)) {
|
||||||
|
cerr << "Conflicting property definitions for " << property_name << "!\n";
|
||||||
|
return index;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we have a length function (ie. this is a sequence property), we should
|
// If we have a length function (ie. this is a sequence property), we should
|
||||||
// find the function that will give us the length.
|
// find the function that will give us the length.
|
||||||
FunctionIndex length_function = 0;
|
FunctionIndex length_function = 0;
|
||||||
bool is_seq = false;
|
if (make_property->_type & CPPMakeProperty::T_sequence) {
|
||||||
|
CPPFunctionGroup::Instances::const_iterator fi;
|
||||||
CPPFunctionGroup::Instances::const_iterator fi;
|
CPPFunctionGroup *fgroup = make_property->_length_function;
|
||||||
CPPFunctionGroup *fgroup = make_property->_length_function;
|
if (fgroup != NULL) {
|
||||||
if (fgroup != NULL) {
|
for (fi = fgroup->_instances.begin(); fi != fgroup->_instances.end(); ++fi) {
|
||||||
is_seq = true;
|
CPPInstance *function = (*fi);
|
||||||
|
CPPFunctionType *ftype =
|
||||||
for (fi = fgroup->_instances.begin(); fi != fgroup->_instances.end(); ++fi) {
|
function->_type->as_function_type();
|
||||||
CPPInstance *function = (*fi);
|
if (ftype != NULL) {
|
||||||
CPPFunctionType *ftype =
|
length_function = get_function(function, "", struct_type,
|
||||||
function->_type->as_function_type();
|
struct_type->get_scope(), 0);
|
||||||
if (ftype != NULL) {
|
if (length_function != 0) {
|
||||||
length_function = get_function(function, "", struct_type,
|
break;
|
||||||
struct_type->get_scope(), 0);
|
}
|
||||||
if (length_function != 0) {
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1840,7 +1852,10 @@ get_make_property(CPPMakeProperty *make_property, CPPStructType *struct_type, CP
|
|||||||
CPPInstance *getter = NULL;
|
CPPInstance *getter = NULL;
|
||||||
CPPType *return_type = NULL;
|
CPPType *return_type = NULL;
|
||||||
|
|
||||||
fgroup = make_property->_get_function;
|
// How many arguments we expect the getter to have.
|
||||||
|
size_t num_args = (size_t)(make_property->_type != CPPMakeProperty::T_normal);
|
||||||
|
|
||||||
|
CPPFunctionGroup *fgroup = make_property->_get_function;
|
||||||
if (fgroup != NULL) {
|
if (fgroup != NULL) {
|
||||||
CPPFunctionGroup::Instances::const_iterator fi;
|
CPPFunctionGroup::Instances::const_iterator fi;
|
||||||
for (fi = fgroup->_instances.begin(); fi != fgroup->_instances.end(); ++fi) {
|
for (fi = fgroup->_instances.begin(); fi != fgroup->_instances.end(); ++fi) {
|
||||||
@ -1852,9 +1867,13 @@ get_make_property(CPPMakeProperty *make_property, CPPStructType *struct_type, CP
|
|||||||
|
|
||||||
const CPPParameterList::Parameters ¶ms = ftype->_parameters->_parameters;
|
const CPPParameterList::Parameters ¶ms = ftype->_parameters->_parameters;
|
||||||
|
|
||||||
size_t expected_num_args = (size_t)is_seq;
|
size_t expected_num_args = 0;
|
||||||
size_t index_arg = 0;
|
size_t index_arg = 0;
|
||||||
|
|
||||||
|
if (make_property->_type != CPPMakeProperty::T_normal) {
|
||||||
|
++expected_num_args;
|
||||||
|
}
|
||||||
|
|
||||||
if (!params.empty() && params[0]->get_simple_name() == "self" &&
|
if (!params.empty() && params[0]->get_simple_name() == "self" &&
|
||||||
TypeManager::is_pointer_to_PyObject(params[0]->_type)) {
|
TypeManager::is_pointer_to_PyObject(params[0]->_type)) {
|
||||||
// Taking a PyObject *self argument.
|
// Taking a PyObject *self argument.
|
||||||
@ -1867,7 +1886,8 @@ get_make_property(CPPMakeProperty *make_property, CPPStructType *struct_type, CP
|
|||||||
(params.size() > expected_num_args &&
|
(params.size() > expected_num_args &&
|
||||||
params[expected_num_args]->_initializer != NULL)) {
|
params[expected_num_args]->_initializer != NULL)) {
|
||||||
// If this is a sequence getter, it must take an index argument.
|
// If this is a sequence getter, it must take an index argument.
|
||||||
if (is_seq && !TypeManager::is_integer(params[index_arg]->_type)) {
|
if (make_property->_type == CPPMakeProperty::T_sequence &&
|
||||||
|
!TypeManager::is_integer(params[index_arg]->_type)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1899,13 +1919,14 @@ get_make_property(CPPMakeProperty *make_property, CPPStructType *struct_type, CP
|
|||||||
CPPInstance *function = (*fi);
|
CPPInstance *function = (*fi);
|
||||||
CPPFunctionType *ftype =
|
CPPFunctionType *ftype =
|
||||||
function->_type->as_function_type();
|
function->_type->as_function_type();
|
||||||
if (ftype != NULL && TypeManager::is_bool(ftype->_return_type)) {
|
if (ftype != nullptr && (TypeManager::is_integer(ftype->_return_type) ||
|
||||||
|
TypeManager::is_pointer(ftype->_return_type))) {
|
||||||
hasser = function;
|
hasser = function;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasser == NULL || return_type == NULL) {
|
if (hasser == nullptr) {
|
||||||
cerr << "No instance of has-function '"
|
cerr << "No instance of has-function '"
|
||||||
<< fgroup->_name << "' is suitable!\n";
|
<< fgroup->_name << "' is suitable!\n";
|
||||||
return 0;
|
return 0;
|
||||||
@ -1921,44 +1942,77 @@ get_make_property(CPPMakeProperty *make_property, CPPStructType *struct_type, CP
|
|||||||
for (fi = fgroup->_instances.begin(); fi != fgroup->_instances.end(); ++fi) {
|
for (fi = fgroup->_instances.begin(); fi != fgroup->_instances.end(); ++fi) {
|
||||||
CPPInstance *function = (*fi);
|
CPPInstance *function = (*fi);
|
||||||
CPPFunctionType *ftype = function->_type->as_function_type();
|
CPPFunctionType *ftype = function->_type->as_function_type();
|
||||||
if (ftype != NULL && ftype->_parameters->_parameters.size() == (size_t)is_seq) {
|
if (ftype != NULL && ftype->_parameters->_parameters.size() == num_args) {
|
||||||
deleter = function;
|
deleter = function;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (deleter == NULL || return_type == NULL) {
|
if (deleter == nullptr) {
|
||||||
cerr << "No instance of delete-function '"
|
cerr << "No instance of delete-function '"
|
||||||
<< fgroup->_name << "' is suitable!\n";
|
<< fgroup->_name << "' is suitable!\n";
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
InterrogateDatabase *idb = InterrogateDatabase::get_ptr();
|
if (index == 0) {
|
||||||
// It isn't here, so we'll have to define it.
|
// It isn't here, so we'll have to define it.
|
||||||
ElementIndex index = idb->get_next_index();
|
index = idb->get_next_index();
|
||||||
_properties_by_name[property_name] = index;
|
_properties_by_name[property_name] = index;
|
||||||
|
|
||||||
InterrogateElement iproperty;
|
InterrogateElement iproperty;
|
||||||
iproperty._name = make_property->get_simple_name();
|
iproperty._name = make_property->get_simple_name();
|
||||||
iproperty._scoped_name = descope(make_property->get_local_name(&parser));
|
iproperty._scoped_name = descope(make_property->get_local_name(&parser));
|
||||||
|
idb->add_element(index, iproperty);
|
||||||
|
}
|
||||||
|
|
||||||
|
InterrogateElement &iproperty = idb->update_element(index);
|
||||||
|
|
||||||
if (return_type != NULL) {
|
if (return_type != NULL) {
|
||||||
iproperty._type = get_type(TypeManager::unwrap_reference(return_type), false);
|
TypeIndex return_index = get_type(TypeManager::unwrap_reference(return_type), false);
|
||||||
|
if (iproperty._type != 0 && iproperty._type != return_index) {
|
||||||
|
cerr << "Property " << property_name << " has inconsistent element type!\n";
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
iproperty._type = 0;
|
iproperty._type = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (length_function != 0) {
|
if (make_property->_type & CPPMakeProperty::T_sequence) {
|
||||||
iproperty._flags |= InterrogateElement::F_sequence;
|
iproperty._flags |= InterrogateElement::F_sequence;
|
||||||
iproperty._length_function = length_function;
|
iproperty._length_function = length_function;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getter != NULL) {
|
if (make_property->_type & CPPMakeProperty::T_mapping) {
|
||||||
iproperty._flags |= InterrogateElement::F_has_getter;
|
iproperty._flags |= InterrogateElement::F_mapping;
|
||||||
iproperty._getter = get_function(getter, "", struct_type,
|
}
|
||||||
struct_type->get_scope(), 0);
|
|
||||||
nassertr(iproperty._getter, 0);
|
if (make_property->_type == CPPMakeProperty::T_normal) {
|
||||||
|
if (getter != NULL) {
|
||||||
|
iproperty._flags |= InterrogateElement::F_has_getter;
|
||||||
|
iproperty._getter = get_function(getter, "", struct_type,
|
||||||
|
struct_type->get_scope(), 0);
|
||||||
|
nassertr(iproperty._getter, 0);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// We could have a mixed sequence/mapping property, so synthesize a
|
||||||
|
// getitem function. We don't really care what's in here; we just use
|
||||||
|
// this to store the remaps.
|
||||||
|
if (!iproperty.has_getter()) {
|
||||||
|
iproperty._flags |= InterrogateElement::F_has_getter;
|
||||||
|
iproperty._getter = InterrogateDatabase::get_ptr()->get_next_index();
|
||||||
|
InterrogateFunction *ifunction = new InterrogateFunction;
|
||||||
|
ifunction->_instances = new InterrogateFunction::Instances;
|
||||||
|
InterrogateDatabase::get_ptr()->add_function(iproperty._getter, ifunction);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add our getter to the generated getitem function.
|
||||||
|
string signature = TypeManager::get_function_signature(getter);
|
||||||
|
InterrogateFunction &ifunction =
|
||||||
|
InterrogateDatabase::get_ptr()->update_function(iproperty._getter);
|
||||||
|
if (ifunction._instances == nullptr) {
|
||||||
|
ifunction._instances = new InterrogateFunction::Instances;
|
||||||
|
}
|
||||||
|
ifunction._instances->insert(InterrogateFunction::Instances::value_type(signature, getter));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasser != NULL) {
|
if (hasser != NULL) {
|
||||||
@ -2011,7 +2065,6 @@ get_make_property(CPPMakeProperty *make_property, CPPStructType *struct_type, CP
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
idb->add_element(index, iproperty);
|
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2621,7 +2674,9 @@ define_struct_type(InterrogateType &itype, CPPStructType *cpptype,
|
|||||||
|
|
||||||
} else if ((*di)->get_subtype() == CPPDeclaration::ST_make_property) {
|
} else if ((*di)->get_subtype() == CPPDeclaration::ST_make_property) {
|
||||||
ElementIndex element_index = get_make_property((*di)->as_make_property(), cpptype, scope);
|
ElementIndex element_index = get_make_property((*di)->as_make_property(), cpptype, scope);
|
||||||
itype._elements.push_back(element_index);
|
if (find(itype._elements.begin(), itype._elements.end(), element_index) == itype._elements.end()) {
|
||||||
|
itype._elements.push_back(element_index);
|
||||||
|
}
|
||||||
|
|
||||||
} else if ((*di)->get_subtype() == CPPDeclaration::ST_make_seq) {
|
} else if ((*di)->get_subtype() == CPPDeclaration::ST_make_seq) {
|
||||||
MakeSeqIndex make_seq_index = get_make_seq((*di)->as_make_seq(), cpptype);
|
MakeSeqIndex make_seq_index = get_make_seq((*di)->as_make_seq(), cpptype);
|
||||||
|
@ -26,6 +26,7 @@ InterrogateElement(InterrogateModuleDef *def) :
|
|||||||
_clear_function = 0;
|
_clear_function = 0;
|
||||||
_del_function = 0;
|
_del_function = 0;
|
||||||
_length_function = 0;
|
_length_function = 0;
|
||||||
|
_make_property = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -52,6 +53,7 @@ operator = (const InterrogateElement ©) {
|
|||||||
_clear_function = copy._clear_function;
|
_clear_function = copy._clear_function;
|
||||||
_del_function = copy._del_function;
|
_del_function = copy._del_function;
|
||||||
_length_function = copy._length_function;
|
_length_function = copy._length_function;
|
||||||
|
_make_property = copy._make_property;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -199,6 +201,14 @@ get_length_function() const {
|
|||||||
return _length_function;
|
return _length_function;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
INLINE bool InterrogateElement::
|
||||||
|
is_mapping() const {
|
||||||
|
return (_flags & F_mapping) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
INLINE ostream &
|
INLINE ostream &
|
||||||
operator << (ostream &out, const InterrogateElement &element) {
|
operator << (ostream &out, const InterrogateElement &element) {
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include "interrogateComponent.h"
|
#include "interrogateComponent.h"
|
||||||
|
|
||||||
class IndexRemapper;
|
class IndexRemapper;
|
||||||
|
class CPPMakeProperty;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An internal representation of a data element, like a data member or a
|
* An internal representation of a data element, like a data member or a
|
||||||
@ -51,6 +52,7 @@ public:
|
|||||||
INLINE FunctionIndex get_del_function() const;
|
INLINE FunctionIndex get_del_function() const;
|
||||||
INLINE bool is_sequence() const;
|
INLINE bool is_sequence() const;
|
||||||
INLINE FunctionIndex get_length_function() const;
|
INLINE FunctionIndex get_length_function() const;
|
||||||
|
INLINE bool is_mapping() const;
|
||||||
|
|
||||||
void output(ostream &out) const;
|
void output(ostream &out) const;
|
||||||
void input(istream &in);
|
void input(istream &in);
|
||||||
@ -80,6 +82,8 @@ private:
|
|||||||
FunctionIndex _clear_function;
|
FunctionIndex _clear_function;
|
||||||
FunctionIndex _del_function;
|
FunctionIndex _del_function;
|
||||||
|
|
||||||
|
CPPMakeProperty *_make_property;
|
||||||
|
|
||||||
friend class InterrogateBuilder;
|
friend class InterrogateBuilder;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -614,6 +614,14 @@ PyObject *Dtool_PyModuleInitHelper(LibraryDef *defs[], const char *modulename) {
|
|||||||
return Dtool_Raise_TypeError("PyType_Ready(Dtool_SequenceWrapper)");
|
return Dtool_Raise_TypeError("PyType_Ready(Dtool_SequenceWrapper)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (PyType_Ready(&Dtool_MappingWrapper_Type) < 0) {
|
||||||
|
return Dtool_Raise_TypeError("PyType_Ready(Dtool_MappingWrapper)");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PyType_Ready(&Dtool_SeqMapWrapper_Type) < 0) {
|
||||||
|
return Dtool_Raise_TypeError("PyType_Ready(Dtool_SeqMapWrapper)");
|
||||||
|
}
|
||||||
|
|
||||||
if (PyType_Ready(&Dtool_StaticProperty_Type) < 0) {
|
if (PyType_Ready(&Dtool_StaticProperty_Type) < 0) {
|
||||||
return Dtool_Raise_TypeError("PyType_Ready(Dtool_StaticProperty_Type)");
|
return Dtool_Raise_TypeError("PyType_Ready(Dtool_StaticProperty_Type)");
|
||||||
}
|
}
|
||||||
@ -1028,34 +1036,79 @@ bool Dtool_ExtractOptionalArg(PyObject **result, PyObject *args, PyObject *kwds)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class is returned from properties that require a settable interface,
|
* These classes are returned from properties that require a subscript
|
||||||
* ie. something.children[i] = 3.
|
* interface, ie. something.children[i] = 3.
|
||||||
*/
|
*/
|
||||||
static void Dtool_SequenceWrapper_dealloc(PyObject *self) {
|
static void Dtool_WrapperBase_dealloc(PyObject *self) {
|
||||||
Dtool_SequenceWrapper *wrap = (Dtool_SequenceWrapper *)self;
|
Dtool_WrapperBase *wrap = (Dtool_WrapperBase *)self;
|
||||||
nassertv(wrap);
|
nassertv(wrap);
|
||||||
Py_XDECREF(wrap->_base);
|
Py_XDECREF(wrap->_self);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Py_ssize_t Dtool_SequenceWrapper_length(PyObject *self) {
|
static Py_ssize_t Dtool_SequenceWrapper_length(PyObject *self) {
|
||||||
Dtool_SequenceWrapper *wrap = (Dtool_SequenceWrapper *)self;
|
Dtool_SequenceWrapper *wrap = (Dtool_SequenceWrapper *)self;
|
||||||
nassertr(wrap, -1);
|
nassertr(wrap, -1);
|
||||||
nassertr(wrap->_len_func, -1);
|
if (wrap->_len_func != nullptr) {
|
||||||
return wrap->_len_func(wrap->_base);
|
nassertr(wrap->_len_func, -1);
|
||||||
|
return wrap->_len_func(wrap->_base._self);
|
||||||
|
} else {
|
||||||
|
Dtool_Raise_TypeError("property does not support len()");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *Dtool_SequenceWrapper_getitem(PyObject *self, Py_ssize_t index) {
|
static PyObject *Dtool_SequenceWrapper_getitem(PyObject *self, Py_ssize_t index) {
|
||||||
Dtool_SequenceWrapper *wrap = (Dtool_SequenceWrapper *)self;
|
Dtool_SequenceWrapper *wrap = (Dtool_SequenceWrapper *)self;
|
||||||
nassertr(wrap, NULL);
|
nassertr(wrap, nullptr);
|
||||||
nassertr(wrap->_getitem_func, NULL);
|
nassertr(wrap->_getitem_func, nullptr);
|
||||||
return wrap->_getitem_func(wrap->_base, index);
|
return wrap->_getitem_func(wrap->_base._self, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int Dtool_SequenceWrapper_setitem(PyObject *self, Py_ssize_t index, PyObject *value) {
|
static int Dtool_SequenceWrapper_setitem(PyObject *self, Py_ssize_t index, PyObject *value) {
|
||||||
Dtool_SequenceWrapper *wrap = (Dtool_SequenceWrapper *)self;
|
Dtool_SequenceWrapper *wrap = (Dtool_SequenceWrapper *)self;
|
||||||
nassertr(wrap, -1);
|
nassertr(wrap, -1);
|
||||||
nassertr(wrap->_setitem_func, -1);
|
if (wrap->_setitem_func != nullptr) {
|
||||||
return wrap->_setitem_func(wrap->_base, index, value);
|
return wrap->_setitem_func(wrap->_base._self, index, value);
|
||||||
|
} else {
|
||||||
|
Dtool_Raise_TypeError("property does not support item assignment");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *Dtool_MappingWrapper_getitem(PyObject *self, PyObject *key) {
|
||||||
|
Dtool_MappingWrapper *wrap = (Dtool_MappingWrapper *)self;
|
||||||
|
nassertr(wrap, nullptr);
|
||||||
|
nassertr(wrap->_getitem_func, nullptr);
|
||||||
|
return wrap->_getitem_func(wrap->_base._self, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int Dtool_MappingWrapper_setitem(PyObject *self, PyObject *key, PyObject *value) {
|
||||||
|
Dtool_MappingWrapper *wrap = (Dtool_MappingWrapper *)self;
|
||||||
|
nassertr(wrap, -1);
|
||||||
|
if (wrap->_setitem_func != nullptr) {
|
||||||
|
return wrap->_setitem_func(wrap->_base._self, key, value);
|
||||||
|
} else {
|
||||||
|
Dtool_Raise_TypeError("property does not support item assignment");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *Dtool_SeqMapWrapper_getitem(PyObject *self, PyObject *key) {
|
||||||
|
Dtool_SeqMapWrapper *wrap = (Dtool_SeqMapWrapper *)self;
|
||||||
|
nassertr(wrap, nullptr);
|
||||||
|
nassertr(wrap->_map_getitem_func, nullptr);
|
||||||
|
return wrap->_map_getitem_func(wrap->_seq._base._self, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int Dtool_SeqMapWrapper_setitem(PyObject *self, PyObject *key, PyObject *value) {
|
||||||
|
Dtool_SeqMapWrapper *wrap = (Dtool_SeqMapWrapper *)self;
|
||||||
|
nassertr(wrap, -1);
|
||||||
|
if (wrap->_map_setitem_func != nullptr) {
|
||||||
|
return wrap->_map_setitem_func(wrap->_seq._base._self, key, value);
|
||||||
|
} else {
|
||||||
|
Dtool_Raise_TypeError("property does not support item assignment");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static PySequenceMethods Dtool_SequenceWrapper_SequenceMethods = {
|
static PySequenceMethods Dtool_SequenceWrapper_SequenceMethods = {
|
||||||
@ -1071,12 +1124,27 @@ static PySequenceMethods Dtool_SequenceWrapper_SequenceMethods = {
|
|||||||
0, // sq_inplace_repeat
|
0, // sq_inplace_repeat
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static PyMappingMethods Dtool_MappingWrapper_MappingMethods = {
|
||||||
|
0, // mp_length
|
||||||
|
Dtool_MappingWrapper_getitem,
|
||||||
|
Dtool_MappingWrapper_setitem,
|
||||||
|
};
|
||||||
|
|
||||||
|
static PyMappingMethods Dtool_SeqMapWrapper_MappingMethods = {
|
||||||
|
Dtool_SequenceWrapper_length,
|
||||||
|
Dtool_SeqMapWrapper_getitem,
|
||||||
|
Dtool_SeqMapWrapper_setitem,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This variant defines only a sequence interface.
|
||||||
|
*/
|
||||||
PyTypeObject Dtool_SequenceWrapper_Type = {
|
PyTypeObject Dtool_SequenceWrapper_Type = {
|
||||||
PyVarObject_HEAD_INIT(NULL, 0)
|
PyVarObject_HEAD_INIT(NULL, 0)
|
||||||
"sequence wrapper",
|
"sequence wrapper",
|
||||||
sizeof(Dtool_SequenceWrapper),
|
sizeof(Dtool_SequenceWrapper),
|
||||||
0, // tp_itemsize
|
0, // tp_itemsize
|
||||||
Dtool_SequenceWrapper_dealloc,
|
Dtool_WrapperBase_dealloc,
|
||||||
0, // tp_print
|
0, // tp_print
|
||||||
0, // tp_getattr
|
0, // tp_getattr
|
||||||
0, // tp_setattr
|
0, // tp_setattr
|
||||||
@ -1262,4 +1330,128 @@ PyTypeObject Dtool_StaticProperty_Type = {
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This variant defines only a mapping interface.
|
||||||
|
*/
|
||||||
|
PyTypeObject Dtool_MappingWrapper_Type = {
|
||||||
|
PyVarObject_HEAD_INIT(NULL, 0)
|
||||||
|
"mapping wrapper",
|
||||||
|
sizeof(Dtool_MappingWrapper),
|
||||||
|
0, // tp_itemsize
|
||||||
|
Dtool_WrapperBase_dealloc,
|
||||||
|
0, // tp_print
|
||||||
|
0, // tp_getattr
|
||||||
|
0, // tp_setattr
|
||||||
|
#if PY_MAJOR_VERSION >= 3
|
||||||
|
0, // tp_reserved
|
||||||
|
#else
|
||||||
|
0, // tp_compare
|
||||||
|
#endif
|
||||||
|
0, // tp_repr
|
||||||
|
0, // tp_as_number
|
||||||
|
0, // tp_as_sequence
|
||||||
|
&Dtool_MappingWrapper_MappingMethods,
|
||||||
|
0, // tp_hash
|
||||||
|
0, // tp_call
|
||||||
|
0, // tp_str
|
||||||
|
PyObject_GenericGetAttr,
|
||||||
|
PyObject_GenericSetAttr,
|
||||||
|
0, // tp_as_buffer
|
||||||
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES,
|
||||||
|
0, // tp_doc
|
||||||
|
0, // tp_traverse
|
||||||
|
0, // tp_clear
|
||||||
|
0, // tp_richcompare
|
||||||
|
0, // tp_weaklistoffset
|
||||||
|
0, // tp_iter
|
||||||
|
0, // tp_iternext
|
||||||
|
0, // tp_methods
|
||||||
|
0, // tp_members
|
||||||
|
0, // tp_getset
|
||||||
|
0, // tp_base
|
||||||
|
0, // tp_dict
|
||||||
|
0, // tp_descr_get
|
||||||
|
0, // tp_descr_set
|
||||||
|
0, // tp_dictoffset
|
||||||
|
0, // tp_init
|
||||||
|
PyType_GenericAlloc,
|
||||||
|
0, // tp_new
|
||||||
|
PyObject_Del,
|
||||||
|
0, // tp_is_gc
|
||||||
|
0, // tp_bases
|
||||||
|
0, // tp_mro
|
||||||
|
0, // tp_cache
|
||||||
|
0, // tp_subclasses
|
||||||
|
0, // tp_weaklist
|
||||||
|
0, // tp_del
|
||||||
|
#if PY_VERSION_HEX >= 0x02060000
|
||||||
|
0, // tp_version_tag
|
||||||
|
#endif
|
||||||
|
#if PY_VERSION_HEX >= 0x03040000
|
||||||
|
0, // tp_finalize
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This variant defines both a sequence and mapping interface.
|
||||||
|
*/
|
||||||
|
PyTypeObject Dtool_SeqMapWrapper_Type = {
|
||||||
|
PyVarObject_HEAD_INIT(NULL, 0)
|
||||||
|
"sequence/mapping wrapper",
|
||||||
|
sizeof(Dtool_SeqMapWrapper),
|
||||||
|
0, // tp_itemsize
|
||||||
|
Dtool_WrapperBase_dealloc,
|
||||||
|
0, // tp_print
|
||||||
|
0, // tp_getattr
|
||||||
|
0, // tp_setattr
|
||||||
|
#if PY_MAJOR_VERSION >= 3
|
||||||
|
0, // tp_reserved
|
||||||
|
#else
|
||||||
|
0, // tp_compare
|
||||||
|
#endif
|
||||||
|
0, // tp_repr
|
||||||
|
0, // tp_as_number
|
||||||
|
&Dtool_SequenceWrapper_SequenceMethods,
|
||||||
|
&Dtool_SeqMapWrapper_MappingMethods,
|
||||||
|
0, // tp_hash
|
||||||
|
0, // tp_call
|
||||||
|
0, // tp_str
|
||||||
|
PyObject_GenericGetAttr,
|
||||||
|
PyObject_GenericSetAttr,
|
||||||
|
0, // tp_as_buffer
|
||||||
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES,
|
||||||
|
0, // tp_doc
|
||||||
|
0, // tp_traverse
|
||||||
|
0, // tp_clear
|
||||||
|
0, // tp_richcompare
|
||||||
|
0, // tp_weaklistoffset
|
||||||
|
0, // tp_iter
|
||||||
|
0, // tp_iternext
|
||||||
|
0, // tp_methods
|
||||||
|
0, // tp_members
|
||||||
|
0, // tp_getset
|
||||||
|
0, // tp_base
|
||||||
|
0, // tp_dict
|
||||||
|
0, // tp_descr_get
|
||||||
|
0, // tp_descr_set
|
||||||
|
0, // tp_dictoffset
|
||||||
|
0, // tp_init
|
||||||
|
PyType_GenericAlloc,
|
||||||
|
0, // tp_new
|
||||||
|
PyObject_Del,
|
||||||
|
0, // tp_is_gc
|
||||||
|
0, // tp_bases
|
||||||
|
0, // tp_mro
|
||||||
|
0, // tp_cache
|
||||||
|
0, // tp_subclasses
|
||||||
|
0, // tp_weaklist
|
||||||
|
0, // tp_del
|
||||||
|
#if PY_VERSION_HEX >= 0x02060000
|
||||||
|
0, // tp_version_tag
|
||||||
|
#endif
|
||||||
|
#if PY_VERSION_HEX >= 0x03040000
|
||||||
|
0, // tp_finalize
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
#endif // HAVE_PYTHON
|
#endif // HAVE_PYTHON
|
||||||
|
@ -339,6 +339,9 @@ EXPCL_INTERROGATEDB PyObject *_Dtool_Raise_BadArgumentsError();
|
|||||||
#define Dtool_Raise_BadArgumentsError(x) Dtool_Raise_TypeError("Arguments must match:\n" x)
|
#define Dtool_Raise_BadArgumentsError(x) Dtool_Raise_TypeError("Arguments must match:\n" x)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// These functions are similar to Dtool_WrapValue, except that they also
|
||||||
|
// contain code for checking assertions and exceptions when compiling with
|
||||||
|
// NDEBUG mode on.
|
||||||
EXPCL_INTERROGATEDB PyObject *_Dtool_Return_None();
|
EXPCL_INTERROGATEDB PyObject *_Dtool_Return_None();
|
||||||
EXPCL_INTERROGATEDB PyObject *Dtool_Return_Bool(bool value);
|
EXPCL_INTERROGATEDB PyObject *Dtool_Return_Bool(bool value);
|
||||||
EXPCL_INTERROGATEDB PyObject *_Dtool_Return(PyObject *value);
|
EXPCL_INTERROGATEDB PyObject *_Dtool_Return(PyObject *value);
|
||||||
@ -465,18 +468,36 @@ EXPCL_INTERROGATEDB PyObject *
|
|||||||
map_deepcopy_to_copy(PyObject *self, PyObject *args);
|
map_deepcopy_to_copy(PyObject *self, PyObject *args);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class is returned from properties that require a settable interface,
|
* These classes are returned from properties that require a subscript
|
||||||
* ie. something.children[i] = 3.
|
* interface, ie. something.children[i] = 3.
|
||||||
*/
|
*/
|
||||||
|
struct Dtool_WrapperBase {
|
||||||
|
PyObject_HEAD;
|
||||||
|
PyObject *_self;
|
||||||
|
};
|
||||||
|
|
||||||
struct Dtool_SequenceWrapper {
|
struct Dtool_SequenceWrapper {
|
||||||
PyObject_HEAD
|
Dtool_WrapperBase _base;
|
||||||
PyObject *_base;
|
|
||||||
lenfunc _len_func;
|
lenfunc _len_func;
|
||||||
ssizeargfunc _getitem_func;
|
ssizeargfunc _getitem_func;
|
||||||
ssizeobjargproc _setitem_func;
|
ssizeobjargproc _setitem_func;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Dtool_MappingWrapper {
|
||||||
|
Dtool_WrapperBase _base;
|
||||||
|
binaryfunc _getitem_func;
|
||||||
|
objobjargproc _setitem_func;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Dtool_SeqMapWrapper {
|
||||||
|
Dtool_SequenceWrapper _seq;
|
||||||
|
binaryfunc _map_getitem_func;
|
||||||
|
objobjargproc _map_setitem_func;
|
||||||
|
};
|
||||||
|
|
||||||
EXPCL_INTERROGATEDB extern PyTypeObject Dtool_SequenceWrapper_Type;
|
EXPCL_INTERROGATEDB extern PyTypeObject Dtool_SequenceWrapper_Type;
|
||||||
|
EXPCL_INTERROGATEDB extern PyTypeObject Dtool_MappingWrapper_Type;
|
||||||
|
EXPCL_INTERROGATEDB extern PyTypeObject Dtool_SeqMapWrapper_Type;
|
||||||
EXPCL_INTERROGATEDB extern PyTypeObject Dtool_StaticProperty_Type;
|
EXPCL_INTERROGATEDB extern PyTypeObject Dtool_StaticProperty_Type;
|
||||||
|
|
||||||
EXPCL_INTERROGATEDB PyObject *Dtool_NewStaticProperty(PyTypeObject *obj, const PyGetSetDef *getset);
|
EXPCL_INTERROGATEDB PyObject *Dtool_NewStaticProperty(PyTypeObject *obj, const PyGetSetDef *getset);
|
||||||
|
@ -44,12 +44,13 @@ PUBLISHED:
|
|||||||
AnimGroup *get_child(int n) const;
|
AnimGroup *get_child(int n) const;
|
||||||
MAKE_SEQ(get_children, get_num_children, get_child);
|
MAKE_SEQ(get_children, get_num_children, get_child);
|
||||||
|
|
||||||
MAKE_SEQ_PROPERTY(children, get_num_children, get_child);
|
|
||||||
|
|
||||||
AnimGroup *get_child_named(const string &name) const;
|
AnimGroup *get_child_named(const string &name) const;
|
||||||
AnimGroup *find_child(const string &name) const;
|
AnimGroup *find_child(const string &name) const;
|
||||||
void sort_descendants();
|
void sort_descendants();
|
||||||
|
|
||||||
|
MAKE_SEQ_PROPERTY(children, get_num_children, get_child);
|
||||||
|
MAKE_MAP_PROPERTY(children, get_child_named, get_child_named);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual TypeHandle get_value_type() const;
|
virtual TypeHandle get_value_type() const;
|
||||||
|
|
||||||
|
@ -70,12 +70,14 @@ PUBLISHED:
|
|||||||
int get_num_children() const;
|
int get_num_children() const;
|
||||||
PartGroup *get_child(int n) const;
|
PartGroup *get_child(int n) const;
|
||||||
MAKE_SEQ(get_children, get_num_children, get_child);
|
MAKE_SEQ(get_children, get_num_children, get_child);
|
||||||
MAKE_SEQ_PROPERTY(children, get_num_children, get_child);
|
|
||||||
|
|
||||||
PartGroup *get_child_named(const string &name) const;
|
PartGroup *get_child_named(const string &name) const;
|
||||||
PartGroup *find_child(const string &name) const;
|
PartGroup *find_child(const string &name) const;
|
||||||
void sort_descendants();
|
void sort_descendants();
|
||||||
|
|
||||||
|
MAKE_SEQ_PROPERTY(children, get_num_children, get_child);
|
||||||
|
MAKE_MAP_PROPERTY(children, get_child_named, get_child_named);
|
||||||
|
|
||||||
bool apply_freeze(const TransformState *transform);
|
bool apply_freeze(const TransformState *transform);
|
||||||
virtual bool apply_freeze_matrix(const LVecBase3 &pos, const LVecBase3 &hpr, const LVecBase3 &scale);
|
virtual bool apply_freeze_matrix(const LVecBase3 &pos, const LVecBase3 &hpr, const LVecBase3 &scale);
|
||||||
virtual bool apply_freeze_scalar(PN_stdfloat value);
|
virtual bool apply_freeze_scalar(PN_stdfloat value);
|
||||||
|
@ -125,6 +125,9 @@ PUBLISHED:
|
|||||||
MAKE_SEQ_PROPERTY(points, get_num_points, get_point);
|
MAKE_SEQ_PROPERTY(points, get_num_points, get_point);
|
||||||
MAKE_SEQ_PROPERTY(vectors, get_num_vectors, get_vector);
|
MAKE_SEQ_PROPERTY(vectors, get_num_vectors, get_vector);
|
||||||
|
|
||||||
|
// We also define this as a mapping interface, for lookups by name.
|
||||||
|
MAKE_MAP_PROPERTY(columns, has_column, get_column);
|
||||||
|
|
||||||
void output(ostream &out) const;
|
void output(ostream &out) const;
|
||||||
void write(ostream &out, int indent_level = 0) const;
|
void write(ostream &out, int indent_level = 0) const;
|
||||||
void write_with_data(ostream &out, int indent_level,
|
void write_with_data(ostream &out, int indent_level,
|
||||||
|
@ -539,6 +539,8 @@ PUBLISHED:
|
|||||||
void set_aux_data(const string &key, TypedReferenceCount *aux_data);
|
void set_aux_data(const string &key, TypedReferenceCount *aux_data);
|
||||||
void clear_aux_data(const string &key);
|
void clear_aux_data(const string &key);
|
||||||
TypedReferenceCount *get_aux_data(const string &key) const;
|
TypedReferenceCount *get_aux_data(const string &key) const;
|
||||||
|
MAKE_MAP_PROPERTY(aux_data, get_aux_data, get_aux_data,
|
||||||
|
set_aux_data, clear_aux_data);
|
||||||
|
|
||||||
INLINE static void set_textures_power_2(AutoTextureScale scale);
|
INLINE static void set_textures_power_2(AutoTextureScale scale);
|
||||||
INLINE static AutoTextureScale get_textures_power_2();
|
INLINE static AutoTextureScale get_textures_power_2();
|
||||||
|
@ -142,6 +142,17 @@ get_weight(size_t n) const {
|
|||||||
return _entries[n]._weight;
|
return _entries[n]._weight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the nth transform stored in the blend object.
|
||||||
|
*/
|
||||||
|
INLINE void TransformBlend::
|
||||||
|
remove_transform(size_t n) {
|
||||||
|
nassertv(n < _entries.size());
|
||||||
|
_entries.erase(_entries.begin() + n);
|
||||||
|
Thread *current_thread = Thread::get_current_thread();
|
||||||
|
clear_result(current_thread);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Replaces the nth transform stored in the blend object.
|
* Replaces the nth transform stored in the blend object.
|
||||||
*/
|
*/
|
||||||
|
@ -62,9 +62,15 @@ PUBLISHED:
|
|||||||
INLINE const VertexTransform *get_transform(size_t n) const;
|
INLINE const VertexTransform *get_transform(size_t n) const;
|
||||||
MAKE_SEQ(get_transforms, get_num_transforms, get_transform);
|
MAKE_SEQ(get_transforms, get_num_transforms, get_transform);
|
||||||
INLINE PN_stdfloat get_weight(size_t n) const;
|
INLINE PN_stdfloat get_weight(size_t n) const;
|
||||||
|
INLINE void remove_transform(size_t n);
|
||||||
INLINE void set_transform(size_t n, const VertexTransform *transform);
|
INLINE void set_transform(size_t n, const VertexTransform *transform);
|
||||||
INLINE void set_weight(size_t n, PN_stdfloat weight);
|
INLINE void set_weight(size_t n, PN_stdfloat weight);
|
||||||
|
|
||||||
|
MAKE_SEQ_PROPERTY(transforms, get_num_transforms, get_transform,
|
||||||
|
set_transform, remove_transform);
|
||||||
|
MAKE_SEQ_PROPERTY(weights, get_num_transforms, get_weight, set_weight);
|
||||||
|
MAKE_MAP_PROPERTY(weights, has_transform, get_weight);
|
||||||
|
|
||||||
INLINE void update_blend(Thread *current_thread) const;
|
INLINE void update_blend(Thread *current_thread) const;
|
||||||
|
|
||||||
INLINE void get_blend(LMatrix4 &result, Thread *current_thread) const;
|
INLINE void get_blend(LMatrix4 &result, Thread *current_thread) const;
|
||||||
|
@ -91,12 +91,16 @@ PUBLISHED:
|
|||||||
void clear_tag_states();
|
void clear_tag_states();
|
||||||
bool has_tag_state(const string &tag_state) const;
|
bool has_tag_state(const string &tag_state) const;
|
||||||
CPT(RenderState) get_tag_state(const string &tag_state) const;
|
CPT(RenderState) get_tag_state(const string &tag_state) const;
|
||||||
|
MAKE_MAP_PROPERTY(tag_states, has_tag_state, get_tag_state,
|
||||||
|
set_tag_state, clear_tag_state);
|
||||||
|
|
||||||
void set_aux_scene_data(const NodePath &node_path, AuxSceneData *data);
|
void set_aux_scene_data(const NodePath &node_path, AuxSceneData *data);
|
||||||
bool clear_aux_scene_data(const NodePath &node_path);
|
bool clear_aux_scene_data(const NodePath &node_path);
|
||||||
AuxSceneData *get_aux_scene_data(const NodePath &node_path) const;
|
AuxSceneData *get_aux_scene_data(const NodePath &node_path) const;
|
||||||
void list_aux_scene_data(ostream &out) const;
|
void list_aux_scene_data(ostream &out) const;
|
||||||
int cleanup_aux_scene_data(Thread *current_thread = Thread::get_current_thread());
|
int cleanup_aux_scene_data(Thread *current_thread = Thread::get_current_thread());
|
||||||
|
MAKE_MAP_PROPERTY(aux_scene_data, get_aux_scene_data, get_aux_scene_data,
|
||||||
|
set_aux_scene_data, clear_aux_scene_data);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void add_display_region(DisplayRegion *display_region);
|
void add_display_region(DisplayRegion *display_region);
|
||||||
|
@ -913,6 +913,9 @@ PUBLISHED:
|
|||||||
INLINE bool has_net_tag(const string &key) const;
|
INLINE bool has_net_tag(const string &key) const;
|
||||||
NodePath find_net_tag(const string &key) const;
|
NodePath find_net_tag(const string &key) const;
|
||||||
|
|
||||||
|
MAKE_MAP_PROPERTY(tags, has_tag, get_tag, set_tag, clear_tag);
|
||||||
|
MAKE_MAP_PROPERTY(net_tags, has_net_tag, get_net_tag);
|
||||||
|
|
||||||
EXTENSION(INLINE PyObject *get_tag_keys() const);
|
EXTENSION(INLINE PyObject *get_tag_keys() const);
|
||||||
|
|
||||||
EXTENSION(PyObject *get_python_tags());
|
EXTENSION(PyObject *get_python_tags());
|
||||||
|
@ -109,6 +109,8 @@ PUBLISHED:
|
|||||||
INLINE int get_override(TypeHandle type) const;
|
INLINE int get_override(TypeHandle type) const;
|
||||||
INLINE int get_override(int slot) const;
|
INLINE int get_override(int slot) const;
|
||||||
|
|
||||||
|
MAKE_MAP_PROPERTY(attribs, has_attrib, get_attrib);
|
||||||
|
|
||||||
INLINE CPT(RenderState) get_unique() const;
|
INLINE CPT(RenderState) get_unique() const;
|
||||||
|
|
||||||
virtual bool unref() const;
|
virtual bool unref() const;
|
||||||
|
@ -417,6 +417,14 @@ ShaderInput(CPT_InternalName name, const LVecBase2i &vec, int priority) :
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
INLINE ShaderInput::
|
||||||
|
operator bool () const {
|
||||||
|
return _type != M_invalid;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
@ -104,6 +104,7 @@ PUBLISHED:
|
|||||||
M_buffer,
|
M_buffer,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
INLINE operator bool() const;
|
||||||
INLINE bool operator == (const ShaderInput &other) const;
|
INLINE bool operator == (const ShaderInput &other) const;
|
||||||
INLINE bool operator != (const ShaderInput &other) const;
|
INLINE bool operator != (const ShaderInput &other) const;
|
||||||
INLINE bool operator < (const ShaderInput &other) const;
|
INLINE bool operator < (const ShaderInput &other) const;
|
||||||
|
@ -64,12 +64,18 @@ PUBLISHED:
|
|||||||
|
|
||||||
int find_on_stage(const TextureStage *stage) const;
|
int find_on_stage(const TextureStage *stage) const;
|
||||||
|
|
||||||
|
MAKE_SEQ_PROPERTY(on_stages, get_num_on_stages, get_on_stage);
|
||||||
|
MAKE_MAP_PROPERTY(on_stages, find_on_stage, get_on_stage);
|
||||||
|
|
||||||
INLINE int get_num_off_stages() const;
|
INLINE int get_num_off_stages() const;
|
||||||
INLINE TextureStage *get_off_stage(int n) const;
|
INLINE TextureStage *get_off_stage(int n) const;
|
||||||
MAKE_SEQ(get_off_stages, get_num_off_stages, get_off_stage);
|
MAKE_SEQ(get_off_stages, get_num_off_stages, get_off_stage);
|
||||||
INLINE bool has_off_stage(TextureStage *stage) const;
|
INLINE bool has_off_stage(TextureStage *stage) const;
|
||||||
INLINE bool has_all_off() const;
|
INLINE bool has_all_off() const;
|
||||||
|
|
||||||
|
MAKE_SEQ_PROPERTY(off_stages, get_num_off_stages, get_off_stage);
|
||||||
|
MAKE_MAP_PROPERTY(off_stages, has_off_stage, get_off_stage);
|
||||||
|
|
||||||
INLINE bool is_identity() const;
|
INLINE bool is_identity() const;
|
||||||
|
|
||||||
CPT(RenderAttrib) add_on_stage(TextureStage *stage, Texture *tex, int override = 0) const;
|
CPT(RenderAttrib) add_on_stage(TextureStage *stage, Texture *tex, int override = 0) const;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user