From 93bcbdd43e388304c115d32dc1f3c76000471329 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=BCrg=20Billeter?= Date: Sat, 10 Mar 2007 22:08:11 +0000 Subject: [PATCH] support abstract, virtual, and override modifiers for properties support MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 2007-03-10 Jürg Billeter * vala/parser.y, vala/valasymbolbuilder.vala, vala/valasemanticanalyzer.vala, vala/valaproperty.vala: support abstract, virtual, and override modifiers for properties * vala/parser.y: support get and set as identifiers svn path=/trunk/; revision=231 --- vala/ChangeLog | 7 +++ vala/vala/parser.y | 98 +++++++++++++++++++++++-------------- vala/vala/valaproperty.vala | 66 +++++++++++++++++++++++++ vala/vala/valasemanticanalyzer.vala | 55 +++++++++++++++++++++ vala/vala/valasymbolbuilder.vala | 2 +- 5 files changed, 190 insertions(+), 38 deletions(-) diff --git a/vala/ChangeLog b/vala/ChangeLog index fdfd7ba..15f6839 100644 --- a/vala/ChangeLog +++ b/vala/ChangeLog @@ -1,5 +1,12 @@ 2007-03-10 Jürg Billeter + * vala/parser.y, vala/valasymbolbuilder.vala, + vala/valasemanticanalyzer.vala, vala/valaproperty.vala: support + abstract, virtual, and override modifiers for properties + * vala/parser.y: support get and set as identifiers + +2007-03-10 Jürg Billeter + * vala/valatypereference.vala: correct cname of generic type parameters 2007-03-10 Jürg Billeter diff --git a/vala/vala/parser.y b/vala/vala/parser.y index 7ba0211..3991046 100644 --- a/vala/vala/parser.y +++ b/vala/vala/parser.y @@ -208,6 +208,7 @@ static void yyerror (YYLTYPE *locp, ValaParser *parser, const char *msg); %token STRING_LITERAL "string" %type comment +%type identifier %type literal %type boolean_literal %type type_name @@ -379,6 +380,19 @@ opt_comma | COMMA ; +/* identifiers never conflict with context-specific keywords get or set */ +identifier + : IDENTIFIER + | GET + { + $$ = g_strdup ("get"); + } + | SET + { + $$ = g_strdup ("set"); + } + ; + literal : boolean_literal | INTEGER_LITERAL @@ -437,7 +451,7 @@ compilation_unit ; type_name - : IDENTIFIER opt_type_argument_list + : identifier opt_type_argument_list { GList *l; ValaSourceReference *src = src(@1); @@ -450,7 +464,7 @@ type_name } g_list_free ($2); } - | IDENTIFIER DOT IDENTIFIER opt_type_argument_list + | identifier DOT identifier opt_type_argument_list { GList *l; ValaSourceReference *src = src(@1); @@ -644,7 +658,7 @@ primary_no_array_creation_expression ; simple_name - : IDENTIFIER opt_type_argument_list + : identifier opt_type_argument_list { ValaSourceReference *src = src(@1); $$ = VALA_EXPRESSION (vala_member_access_new (NULL, $1, src)); @@ -673,7 +687,7 @@ parenthesized_expression ; member_access - : primary_expression DOT IDENTIFIER opt_type_argument_list + : primary_expression DOT identifier opt_type_argument_list { ValaSourceReference *src = src(@3); $$ = VALA_EXPRESSION (vala_member_access_new ($1, $3, src)); @@ -1109,7 +1123,7 @@ lambda_expression g_object_unref ($5); g_object_unref (src); } - | IDENTIFIER LAMBDA expression + | identifier LAMBDA expression { ValaSourceReference *src = src(@2); $$ = VALA_EXPRESSION (vala_lambda_expression_new ($3, src)); @@ -1133,7 +1147,7 @@ lambda_expression g_object_unref ($5); g_object_unref (src); } - | IDENTIFIER LAMBDA block + | identifier LAMBDA block { ValaSourceReference *src = src(@2); $$ = VALA_EXPRESSION (vala_lambda_expression_new_with_statement_body (VALA_BLOCK ($3), src)); @@ -1153,12 +1167,12 @@ opt_lambda_parameter_list ; lambda_parameter_list - : IDENTIFIER COMMA IDENTIFIER + : identifier COMMA identifier { $$ = g_list_append (NULL, $1); $$ = g_list_append ($$, $3); } - | lambda_parameter_list COMMA IDENTIFIER + | lambda_parameter_list COMMA identifier { $$ = g_list_append ($1, $3); } @@ -1726,7 +1740,7 @@ statement_expression_list ; foreach_statement - : FOREACH OPEN_PARENS type IDENTIFIER IN expression CLOSE_PARENS embedded_statement + : FOREACH OPEN_PARENS type identifier IN expression CLOSE_PARENS embedded_statement { ValaSourceReference *src = src(@3); $$ = VALA_STATEMENT (vala_foreach_statement_new ($3, $4, $6, $8, src)); @@ -1842,7 +1856,7 @@ specific_catch_clauses ; specific_catch_clause - : CATCH OPEN_PARENS type IDENTIFIER CLOSE_PARENS block + : CATCH OPEN_PARENS type identifier CLOSE_PARENS block { ValaSourceReference *src = src(@1); $$ = vala_catch_clause_new ($3, $4, VALA_BLOCK ($6), src); @@ -1897,7 +1911,7 @@ lock_statement } namespace_declaration - : comment opt_attributes NAMESPACE IDENTIFIER + : comment opt_attributes NAMESPACE identifier { ValaSourceReference *src = src_com(@4, $1); current_namespace = vala_namespace_new ($4, src); @@ -1926,7 +1940,7 @@ opt_name_specifier ; name_specifier - : DOT IDENTIFIER + : DOT identifier { $$ = $2; } @@ -1943,7 +1957,7 @@ using_directives ; using_directive - : USING IDENTIFIER SEMICOLON + : USING identifier SEMICOLON { ValaSourceReference *src = src(@2); ValaNamespaceReference *ns_ref = vala_namespace_reference_new ($2, src); @@ -2103,7 +2117,7 @@ namespace_member_declaration ; class_declaration - : comment opt_attributes opt_access_modifier opt_modifiers CLASS IDENTIFIER opt_name_specifier opt_type_parameter_list opt_class_base + : comment opt_attributes opt_access_modifier opt_modifiers CLASS identifier opt_name_specifier opt_type_parameter_list opt_class_base { char *name = $6; @@ -2371,14 +2385,14 @@ variable_declarators ; variable_declarator - : IDENTIFIER + : identifier { ValaSourceReference *src = src(@1); $$ = vala_variable_declarator_new ($1, NULL, src); g_object_unref (src); g_free ($1); } - | IDENTIFIER ASSIGN variable_initializer + | identifier ASSIGN variable_initializer { ValaSourceReference *src = src(@1); $$ = vala_variable_declarator_new ($1, $3, src); @@ -2445,7 +2459,7 @@ method_declaration ; method_header - : comment opt_attributes opt_access_modifier opt_modifiers type IDENTIFIER OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS opt_throws_declaration + : comment opt_attributes opt_access_modifier opt_modifiers type identifier OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS opt_throws_declaration { GList *l; @@ -2484,7 +2498,7 @@ method_header g_object_unref ($5); g_free ($6); } - | comment opt_attributes opt_access_modifier opt_modifiers IDENTIFIER opt_name_specifier OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS + | comment opt_attributes opt_access_modifier opt_modifiers identifier opt_name_specifier OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS { GList *l; @@ -2564,7 +2578,7 @@ opt_construct ; fixed_parameter - : opt_attributes opt_construct type IDENTIFIER + : opt_attributes opt_construct type identifier { if (vala_type_reference_get_is_ref ($3) && vala_type_reference_get_is_out ($3)) { vala_type_reference_set_takes_ownership ($3, TRUE); @@ -2578,7 +2592,7 @@ fixed_parameter g_object_unref ($3); g_free ($4); } - | opt_attributes opt_construct type IDENTIFIER ASSIGN expression + | opt_attributes opt_construct type identifier ASSIGN expression { if (vala_type_reference_get_is_ref ($3) && vala_type_reference_get_is_out ($3)) { vala_type_reference_set_takes_ownership ($3, TRUE); @@ -2612,7 +2626,7 @@ throws_declaration ; property_declaration - : comment opt_attributes opt_access_modifier opt_modifiers type IDENTIFIER OPEN_BRACE get_accessor_declaration opt_set_accessor_declaration CLOSE_BRACE + : comment opt_attributes opt_access_modifier opt_modifiers type identifier OPEN_BRACE get_accessor_declaration opt_set_accessor_declaration CLOSE_BRACE { if (!vala_type_reference_get_is_weak ($5)) { vala_type_reference_set_takes_ownership ($5, TRUE); @@ -2630,8 +2644,18 @@ property_declaration if ($9 != NULL) { g_object_unref ($9); } + + if (($4 & VALA_MODIFIER_ABSTRACT) == VALA_MODIFIER_ABSTRACT) { + vala_property_set_is_abstract ($$, TRUE); + } + if (($4 & VALA_MODIFIER_VIRTUAL) == VALA_MODIFIER_VIRTUAL) { + vala_property_set_is_virtual ($$, TRUE); + } + if (($4 & VALA_MODIFIER_OVERRIDE) == VALA_MODIFIER_OVERRIDE) { + vala_property_set_overrides ($$, TRUE); + } } - | comment opt_attributes opt_access_modifier opt_modifiers type IDENTIFIER OPEN_BRACE set_accessor_declaration CLOSE_BRACE + | comment opt_attributes opt_access_modifier opt_modifiers type identifier OPEN_BRACE set_accessor_declaration CLOSE_BRACE { if (!vala_type_reference_get_is_weak ($5)) { vala_type_reference_set_takes_ownership ($5, TRUE); @@ -2701,7 +2725,7 @@ set_accessor_declaration ; signal_declaration - : comment opt_attributes opt_access_modifier SIGNAL type IDENTIFIER OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS SEMICOLON + : comment opt_attributes opt_access_modifier SIGNAL type identifier OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS SEMICOLON { GList *l; @@ -2738,7 +2762,7 @@ constructor_declaration ; destructor_declaration - : comment opt_attributes opt_access_modifier opt_modifiers TILDE IDENTIFIER OPEN_PARENS CLOSE_PARENS block + : comment opt_attributes opt_access_modifier opt_modifiers TILDE identifier OPEN_PARENS CLOSE_PARENS block { ValaSourceReference *src = src_com(@6, $1); $$ = vala_destructor_new (src); @@ -2763,7 +2787,7 @@ struct_declaration ; struct_header - : comment opt_attributes opt_access_modifier STRUCT IDENTIFIER opt_name_specifier opt_type_parameter_list opt_class_base + : comment opt_attributes opt_access_modifier STRUCT identifier opt_name_specifier opt_type_parameter_list opt_class_base { char *name = $5; @@ -2836,7 +2860,7 @@ struct_member_declaration ; interface_declaration - : comment opt_attributes opt_access_modifier INTERFACE IDENTIFIER opt_name_specifier opt_type_parameter_list opt_class_base + : comment opt_attributes opt_access_modifier INTERFACE identifier opt_name_specifier opt_type_parameter_list opt_class_base { char *name = $5; @@ -2927,7 +2951,7 @@ interface_member_declaration ; enum_declaration - : comment opt_attributes opt_access_modifier ENUM IDENTIFIER opt_name_specifier enum_body + : comment opt_attributes opt_access_modifier ENUM identifier opt_name_specifier enum_body { char *name = $5; @@ -2989,12 +3013,12 @@ enum_member_declarations ; enum_member_declaration - : opt_attributes IDENTIFIER + : opt_attributes identifier { $$ = vala_enum_value_new ($2); g_free ($2); } - | opt_attributes IDENTIFIER ASSIGN expression + | opt_attributes identifier ASSIGN expression { $$ = vala_enum_value_new_with_value ($2, $4); g_free ($2); @@ -3003,7 +3027,7 @@ enum_member_declaration ; flags_declaration - : comment opt_attributes opt_access_modifier FLAGS IDENTIFIER opt_name_specifier flags_body + : comment opt_attributes opt_access_modifier FLAGS identifier opt_name_specifier flags_body { char *name = $5; @@ -3042,11 +3066,11 @@ flags_member_declarations ; flags_member_declaration - : opt_attributes IDENTIFIER + : opt_attributes identifier ; callback_declaration - : comment opt_attributes opt_access_modifier CALLBACK type IDENTIFIER opt_name_specifier opt_type_parameter_list OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS SEMICOLON + : comment opt_attributes opt_access_modifier CALLBACK type identifier opt_name_specifier opt_type_parameter_list OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS SEMICOLON { GList *l; char *name = $6; @@ -3155,7 +3179,7 @@ attribute ; attribute_name - : IDENTIFIER + : identifier ; opt_named_argument_list @@ -3178,7 +3202,7 @@ named_argument_list ; named_argument - : IDENTIFIER ASSIGN expression + : identifier ASSIGN expression { ValaSourceReference *src = src(@1); $$ = vala_named_argument_new ($1, $3, src); @@ -3216,7 +3240,7 @@ type_parameters ; type_parameter - : IDENTIFIER + : identifier { ValaSourceReference *src = src(@1); $$ = vala_type_parameter_new ($1, src); @@ -3267,7 +3291,7 @@ open_parens ; member_name - : IDENTIFIER opt_type_argument_list + : identifier opt_type_argument_list { ValaSourceReference *src = src(@1); $$ = VALA_EXPRESSION (vala_member_access_new (NULL, $1, src)); @@ -3283,7 +3307,7 @@ member_name g_list_free ($2); } } - | member_name DOT IDENTIFIER opt_type_argument_list + | member_name DOT identifier opt_type_argument_list { ValaSourceReference *src = src(@1); $$ = VALA_EXPRESSION (vala_member_access_new ($1, $3, src)); diff --git a/vala/vala/valaproperty.vala b/vala/vala/valaproperty.vala index 2b0e48f..15d2fa7 100644 --- a/vala/vala/valaproperty.vala +++ b/vala/vala/valaproperty.vala @@ -71,6 +71,37 @@ public class Vala.Property : Member, Lockable { */ public bool interface_only { get; set; } + /** + * Specifies whether this property is abstract. Abstract properties have + * no accessor bodies, may only be specified within abstract classes and + * interfaces, and must be overriden by derived non-abstract classes. + */ + public bool is_abstract { get; set; } + + /** + * Specifies whether this property is virtual. Virtual properties may be + * overridden by derived classes. + */ + public bool is_virtual { get; set; } + + /** + * Specifies whether this property overrides a virtual or abstract + * property of a base type. + */ + public bool overrides { get; set; } + + /** + * Specifies the virtual or abstract property this property overrides. + * Reference must be weak as virtual properties set base_property to + * themselves. + */ + public weak Property base_property { get; set; } + + /** + * Specifies the abstract interface property this property implements. + */ + public Property base_interface_property { get; set; } + private bool lock_used = false; /** @@ -162,4 +193,39 @@ public class Vala.Property : Member, Lockable { public void set_lock_used (bool used) { lock_used = used; } + + /** + * Checks whether the accessors and type of the specified property + * matches this property. + * + * @param prop a property + * @return true if the specified property is compatible to this + * property + */ + public bool equals (Property! prop2) { + if (!prop2.type_reference.equals (type_reference)) { + return false; + } + + if ((get_accessor == null && prop2.get_accessor != null) || + (get_accessor != null && prop2.get_accessor == null)) { + return false; + } + + if ((set_accessor == null && prop2.set_accessor != null) || + (set_accessor != null && prop2.set_accessor == null)) { + return false; + } + + if (set_accessor != null) { + if (set_accessor.writable != prop2.set_accessor.writable) { + return false; + } + if (set_accessor.construction != prop2.set_accessor.construction) { + return false; + } + } + + return true; + } } diff --git a/vala/vala/valasemanticanalyzer.vala b/vala/vala/valasemanticanalyzer.vala index 344046a..8bacce8 100644 --- a/vala/vala/valasemanticanalyzer.vala +++ b/vala/vala/valasemanticanalyzer.vala @@ -452,12 +452,67 @@ public class Vala.SemanticAnalyzer : CodeVisitor { } } + private void find_base_class_property (Property! prop, Class! cl) { + var sym = cl.symbol.lookup (prop.name); + if (sym != null && sym.node is Property) { + var base_property = (Property) sym.node; + if (base_property.is_abstract || base_property.is_virtual) { + if (!prop.equals (base_property)) { + prop.error = true; + Report.error (prop.source_reference, "Type and/or accessors of overriding property `%s' do not match overridden property `%s'.".printf (prop.symbol.get_full_name (), base_property.symbol.get_full_name ())); + return; + } + + prop.base_property = base_property; + return; + } + } + + if (cl.base_class != null) { + find_base_class_property (prop, cl.base_class); + } + } + + private void find_base_interface_property (Property! prop, Class! cl) { + // FIXME report error if multiple possible base properties are found + foreach (TypeReference type in cl.get_base_types ()) { + if (type.data_type is Interface) { + var sym = type.data_type.symbol.lookup (prop.name); + if (sym != null && sym.node is Property) { + var base_property = (Property) sym.node; + if (base_property.is_abstract) { + if (!prop.equals (base_property)) { + prop.error = true; + Report.error (prop.source_reference, "Type and/or accessors of overriding property `%s' do not match overridden property `%s'.".printf (prop.symbol.get_full_name (), base_property.symbol.get_full_name ())); + return; + } + + prop.base_interface_property = base_property; + return; + } + } + } + } + } + public override void visit_end_property (Property! prop) { if (prop.type_reference.data_type != null) { /* is null if it references a type parameter */ current_source_file.add_symbol_dependency (prop.type_reference.data_type.symbol, SourceFileDependencyType.HEADER_SHALLOW); current_source_file.add_symbol_dependency (prop.type_reference.data_type.symbol, SourceFileDependencyType.SOURCE); } + + if (prop.symbol.parent_symbol.node is Class) { + var cl = (Class) prop.symbol.parent_symbol.node; + find_base_interface_property (prop, cl); + if (prop.is_virtual || prop.overrides) { + find_base_class_property (prop, cl); + if (prop.base_property == null) { + prop.error = true; + Report.error (prop.source_reference, "%s: no suitable property found to override".printf (prop.symbol.get_full_name ())); + } + } + } } public override void visit_begin_property_accessor (PropertyAccessor! acc) { diff --git a/vala/vala/valasymbolbuilder.vala b/vala/vala/valasymbolbuilder.vala index 01ba4d9..0828f58 100644 --- a/vala/vala/valasymbolbuilder.vala +++ b/vala/vala/valasymbolbuilder.vala @@ -295,7 +295,7 @@ public class Vala.SymbolBuilder : CodeVisitor { var prop = (Property) acc.symbol.parent_symbol.node; - if (prop.interface_only) { + if (prop.interface_only || prop.symbol.parent_symbol.node is Interface) { return; } -- 2.7.4