diff options
Diffstat (limited to 'vala')
60 files changed, 1156 insertions, 1845 deletions
diff --git a/vala/Makefile.am b/vala/Makefile.am index 7ce1baee1..fe04e51bf 100644 --- a/vala/Makefile.am +++ b/vala/Makefile.am @@ -127,12 +127,6 @@ libvalacore_la_SOURCES = \ valafield.c \ valafield.h \ valafield.vala \ - valaflags.c \ - valaflags.h \ - valaflags.vala \ - valaflagsvalue.c \ - valaflagsvalue.h \ - valaflagsvalue.vala \ valaforeachstatement.c \ valaforeachstatement.h \ valaforeachstatement.vala \ @@ -247,6 +241,9 @@ libvalacore_la_SOURCES = \ valareturnstatement.c \ valareturnstatement.h \ valareturnstatement.vala \ + valascope.c \ + valascope.h \ + valascope.vala \ valasemanticanalyzer.c \ valasemanticanalyzer.h \ valasemanticanalyzer.vala \ @@ -283,9 +280,6 @@ libvalacore_la_SOURCES = \ valaswitchstatement.c \ valaswitchstatement.h \ valaswitchstatement.vala \ - valasymbolbuilder.c \ - valasymbolbuilder.h \ - valasymbolbuilder.vala \ valasymbol.c \ valasymbol.h \ valasymbol.vala \ @@ -360,8 +354,6 @@ valainclude_HEADERS = \ valaexpression.h \ valaexpressionstatement.h \ valafield.h \ - valaflags.h \ - valaflagsvalue.h \ valaforeachstatement.h \ valaformalparameter.h \ valaforstatement.h \ @@ -400,6 +392,7 @@ valainclude_HEADERS = \ valareferencetransferexpression.h \ valareport.h \ valareturnstatement.h \ + valascope.h \ valasemanticanalyzer.h \ valasignal.h \ valasizeofexpression.h \ @@ -412,7 +405,6 @@ valainclude_HEADERS = \ valaswitchlabel.h \ valaswitchsection.h \ valaswitchstatement.h \ - valasymbolbuilder.h \ valasymbol.h \ valasymbolresolver.h \ valathrowstatement.h \ diff --git a/vala/parser.y b/vala/parser.y index 79042d6ea..58a6c5f43 100644 --- a/vala/parser.y +++ b/vala/parser.y @@ -36,12 +36,8 @@ #define src_com(l,c) (vala_source_reference_new_with_comment (current_source_file, l.first_line, l.first_column, l.last_line, l.last_column, c)) static ValaSourceFile *current_source_file; -static ValaNamespace *current_namespace; -static gboolean current_namespace_implicit; -static ValaClass *current_class; -static ValaStruct *current_struct; -static ValaInterface *current_interface; -static ValaEnum *current_enum; +static GList *symbol_stack; +static GList *scope_stack; typedef enum { VALA_MODIFIER_NONE, @@ -53,6 +49,12 @@ typedef enum { int yylex (YYSTYPE *yylval_param, YYLTYPE *yylloc_param, ValaParser *parser); static void yyerror (YYLTYPE *locp, ValaParser *parser, const char *msg); + +static void push_symbol (ValaSymbol *symbol); +static ValaSymbol *pop_symbol (void); + +static gboolean check_is_namespace (ValaSymbol *symbol, ValaSourceReference *src); +static gboolean check_is_class (ValaSymbol *symbol, ValaSourceReference *src); %} %defines @@ -69,15 +71,10 @@ static void yyerror (YYLTYPE *locp, ValaParser *parser, const char *msg); ValaTypeReference *type_reference; ValaExpression *expression; ValaStatement *statement; - ValaNamespace *namespace; - ValaClass *class; + ValaBlock *block; ValaStruct *struct_; ValaInterface *interface; - ValaEnum *enum_; ValaEnumValue *enum_value; - ValaFlags *flags; - ValaFlagsValue *flags_value; - ValaCallback *callback; ValaConstant *constant; ValaField *field; ValaMethod *method; @@ -167,7 +164,6 @@ static void yyerror (YYLTYPE *locp, ValaParser *parser, const char *msg); %token ENUM "enum" %token VALA_FALSE "false" %token FINALLY "finally" -%token FLAGS "flags" %token FOR "for" %token FOREACH "foreach" %token GET "get" @@ -269,8 +265,8 @@ static void yyerror (YYLTYPE *locp, ValaParser *parser, const char *msg); %type <expression> opt_expression %type <expression> expression %type <statement> statement -%type <statement> embedded_statement -%type <statement> block +%type <block> embedded_statement +%type <block> block %type <list> opt_statement_list %type <list> statement_list %type <statement> empty_statement @@ -307,13 +303,11 @@ static void yyerror (YYLTYPE *locp, ValaParser *parser, const char *msg); %type <catch_clause> specific_catch_clause %type <catch_clause> opt_general_catch_clause %type <catch_clause> general_catch_clause -%type <statement> opt_finally_clause -%type <statement> finally_clause +%type <block> opt_finally_clause +%type <block> finally_clause %type <statement> lock_statement -%type <namespace> namespace_declaration %type <str> opt_name_specifier %type <str> name_specifier -%type <class> class_declaration %type <num> opt_access_modifier %type <num> access_modifier %type <num> opt_modifiers @@ -326,16 +320,7 @@ static void yyerror (YYLTYPE *locp, ValaParser *parser, const char *msg); %type <property_accessor> get_accessor_declaration %type <property_accessor> opt_set_accessor_declaration %type <property_accessor> set_accessor_declaration -%type <struct_> struct_declaration %type <struct_> struct_header -%type <interface> interface_declaration -%type <enum_> enum_declaration -%type <flags> flags_declaration -%type <list> flags_body -%type <list> opt_flags_member_declarations -%type <list> flags_member_declarations -%type <flags_value> flags_member_declaration -%type <callback> callback_declaration %type <constant> constant_declaration %type <field> field_declaration %type <list> variable_declarators @@ -346,7 +331,7 @@ static void yyerror (YYLTYPE *locp, ValaParser *parser, const char *msg); %type <expression> variable_initializer %type <method> method_declaration %type <method> method_header -%type <statement> method_body +%type <block> method_body %type <list> opt_formal_parameter_list %type <list> formal_parameter_list %type <num> opt_construct @@ -1051,7 +1036,7 @@ shift_expression g_object_unref ($1); g_object_unref ($3); } - /* don't use two OP_GT due to resolve parse conflicts + /* don't use two OP_GT to resolve parse conflicts * stacked generics won't be that common in vala */ | shift_expression OP_SHIFT_RIGHT additive_expression { @@ -1350,6 +1335,9 @@ expression statement : declaration_statement | block + { + $$ = VALA_STATEMENT ($1); + } | empty_statement | expression_statement | selection_statement @@ -1364,56 +1352,56 @@ embedded_statement | empty_statement { ValaSourceReference *src = src(@1); - $$ = VALA_STATEMENT (vala_block_new (src)); - vala_block_add_statement (VALA_BLOCK ($$), $1); + $$ = vala_block_new (src); + vala_block_add_statement ($$, $1); g_object_unref ($1); g_object_unref (src); } | expression_statement { ValaSourceReference *src = src(@1); - $$ = VALA_STATEMENT (vala_block_new (src)); - vala_block_add_statement (VALA_BLOCK ($$), $1); + $$ = vala_block_new (src); + vala_block_add_statement ($$, $1); g_object_unref ($1); g_object_unref (src); } | selection_statement { ValaSourceReference *src = src(@1); - $$ = VALA_STATEMENT (vala_block_new (src)); - vala_block_add_statement (VALA_BLOCK ($$), $1); + $$ = vala_block_new (src); + vala_block_add_statement ($$, $1); g_object_unref ($1); g_object_unref (src); } | iteration_statement { ValaSourceReference *src = src(@1); - $$ = VALA_STATEMENT (vala_block_new (src)); - vala_block_add_statement (VALA_BLOCK ($$), $1); + $$ = vala_block_new (src); + vala_block_add_statement ($$, $1); g_object_unref ($1); g_object_unref (src); } | jump_statement { ValaSourceReference *src = src(@1); - $$ = VALA_STATEMENT (vala_block_new (src)); - vala_block_add_statement (VALA_BLOCK ($$), $1); + $$ = vala_block_new (src); + vala_block_add_statement ($$, $1); g_object_unref ($1); g_object_unref (src); } | try_statement { ValaSourceReference *src = src(@1); - $$ = VALA_STATEMENT (vala_block_new (src)); - vala_block_add_statement (VALA_BLOCK ($$), $1); + $$ = vala_block_new (src); + vala_block_add_statement ($$, $1); g_object_unref ($1); g_object_unref (src); } | lock_statement { ValaSourceReference *src = src(@1); - $$ = VALA_STATEMENT (vala_block_new (src)); - vala_block_add_statement (VALA_BLOCK ($$), $1); + $$ = vala_block_new (src); + vala_block_add_statement ($$, $1); g_object_unref ($1); g_object_unref (src); } @@ -1423,11 +1411,11 @@ block : OPEN_BRACE opt_statement_list CLOSE_BRACE { ValaSourceReference *src = src(@1); - $$ = VALA_STATEMENT (vala_block_new (src)); + $$ = vala_block_new (src); if ($2 != NULL) { GList *l; for (l = $2; l != NULL; l = l->next) { - vala_block_add_statement (VALA_BLOCK ($$), l->data); + vala_block_add_statement ($$, l->data); g_object_unref (l->data); } g_list_free ($2); @@ -1580,51 +1568,24 @@ selection_statement if_statement : comment IF open_parens expression CLOSE_PARENS embedded_statement { - ValaBlock *true_block; ValaSourceReference *src; - if (VALA_IS_BLOCK ($6)) { - true_block = VALA_BLOCK ($6); - } else { - true_block = vala_block_new (vala_code_node_get_source_reference (VALA_CODE_NODE ($6))); - vala_block_add_statement (true_block, $6); - g_object_unref ($6); - } - src = src_com(@4, $1); - $$ = VALA_STATEMENT (vala_if_statement_new ($4, true_block, NULL, src)); + $$ = VALA_STATEMENT (vala_if_statement_new ($4, $6, NULL, src)); g_object_unref (src); g_object_unref ($4); - g_object_unref (true_block); + g_object_unref ($6); } | comment IF open_parens expression CLOSE_PARENS embedded_statement ELSE embedded_statement { - ValaBlock *true_block; - ValaBlock *false_block; ValaSourceReference *src; - if (VALA_IS_BLOCK ($6)) { - true_block = VALA_BLOCK ($6); - } else { - true_block = vala_block_new (vala_code_node_get_source_reference (VALA_CODE_NODE ($6))); - vala_block_add_statement (true_block, $6); - g_object_unref ($6); - } - - if (VALA_IS_BLOCK ($8)) { - false_block = VALA_BLOCK ($8); - } else { - false_block = vala_block_new (vala_code_node_get_source_reference (VALA_CODE_NODE ($8))); - vala_block_add_statement (false_block, $8); - g_object_unref ($8); - } - src = src_com(@4, $1); - $$ = VALA_STATEMENT (vala_if_statement_new ($4, true_block, false_block, src)); + $$ = VALA_STATEMENT (vala_if_statement_new ($4, $6, $8, src)); g_object_unref (src); g_object_unref ($4); - g_object_unref (true_block); - g_object_unref (false_block); + g_object_unref ($6); + g_object_unref ($8); } ; @@ -1802,7 +1763,7 @@ for_statement if (init != NULL) { ValaSourceReference *decl_src = vala_code_node_get_source_reference (VALA_CODE_NODE (decl)); - ValaMemberAccess *lhs = vala_member_access_new (NULL, vala_variable_declarator_get_name (decl), decl_src); + ValaMemberAccess *lhs = vala_member_access_new (NULL, vala_symbol_get_name (VALA_SYMBOL (decl)), decl_src); ValaAssignment *assign = vala_assignment_new (VALA_EXPRESSION (lhs), init, VALA_ASSIGNMENT_OPERATOR_SIMPLE, decl_src); g_object_unref (lhs); vala_for_statement_add_initializer (for_statement, VALA_EXPRESSION (assign)); @@ -1919,7 +1880,7 @@ try_statement { GList *l; ValaSourceReference *src = src(@1); - $$ = VALA_STATEMENT (vala_try_statement_new (VALA_BLOCK ($2), VALA_BLOCK ($4), src)); + $$ = VALA_STATEMENT (vala_try_statement_new ($2, $4, src)); g_object_unref ($2); if ($4 != NULL) { g_object_unref ($4); @@ -1935,7 +1896,7 @@ try_statement | TRY block finally_clause { ValaSourceReference *src = src(@1); - $$ = VALA_STATEMENT (vala_try_statement_new (VALA_BLOCK ($2), VALA_BLOCK ($3), src)); + $$ = VALA_STATEMENT (vala_try_statement_new ($2, $3, src)); g_object_unref ($2); g_object_unref ($3); g_object_unref (src); @@ -2027,15 +1988,29 @@ namespace_declaration : comment opt_attributes NAMESPACE identifier { ValaSourceReference *src = src_com(@4, $1); - current_namespace = vala_namespace_new ($4, src); + ValaSymbol *current_symbol = vala_scope_lookup (scope_stack->data, $4); + if (current_symbol != NULL) { + if (check_is_namespace (current_symbol, src)) { + // merge namespace declarations + if (!vala_source_file_get_pkg (current_source_file)) { + vala_namespace_set_pkg (VALA_NAMESPACE (current_symbol), FALSE); + } + VALA_CODE_NODE (current_symbol)->attributes = $2; + } + } else { + current_symbol = VALA_SYMBOL (vala_namespace_new ($4, src)); + vala_namespace_set_pkg (VALA_NAMESPACE (current_symbol), vala_source_file_get_pkg (current_source_file)); + VALA_CODE_NODE (current_symbol)->attributes = g_list_concat (VALA_CODE_NODE (current_symbol)->attributes, $2); + vala_namespace_add_namespace (VALA_NAMESPACE (symbol_stack->data), VALA_NAMESPACE (current_symbol)); + } g_object_unref (src); - VALA_CODE_NODE(current_namespace)->attributes = $2; g_free ($4); + + push_symbol (current_symbol); } namespace_body { - $$ = current_namespace; - current_namespace = vala_code_context_get_global_namespace (vala_source_file_get_context (current_source_file)); + g_object_unref (pop_symbol ()); } ; @@ -2093,10 +2068,6 @@ outer_declarations outer_declaration : namespace_declaration - { - vala_code_context_add_namespace (vala_source_file_get_context (current_source_file), $1); - g_object_unref ($1); - } | namespace_member_declaration ; @@ -2112,100 +2083,15 @@ namespace_member_declarations namespace_member_declaration : class_declaration - { - /* skip declarations with errors */ - if ($1 != NULL) { - vala_namespace_add_class (current_namespace, $1); - vala_source_file_add_node (current_source_file, VALA_CODE_NODE ($1)); - g_object_unref ($1); - } - - if (current_namespace_implicit) { - /* current namespace has been declared implicitly */ - current_namespace = vala_code_context_get_global_namespace (vala_source_file_get_context (current_source_file)); - current_namespace_implicit = FALSE; - } - } | struct_declaration - { - /* skip declarations with errors */ - if ($1 != NULL) { - vala_namespace_add_struct (current_namespace, $1); - vala_source_file_add_node (current_source_file, VALA_CODE_NODE ($1)); - g_object_unref ($1); - } - - if (current_namespace_implicit) { - /* current namespace has been declared implicitly */ - current_namespace = vala_code_context_get_global_namespace (vala_source_file_get_context (current_source_file)); - current_namespace_implicit = FALSE; - } - } | interface_declaration - { - /* skip declarations with errors */ - if ($1 != NULL) { - vala_namespace_add_interface (current_namespace, $1); - vala_source_file_add_node (current_source_file, VALA_CODE_NODE ($1)); - g_object_unref ($1); - } - - if (current_namespace_implicit) { - /* current namespace has been declared implicitly */ - current_namespace = vala_code_context_get_global_namespace (vala_source_file_get_context (current_source_file)); - current_namespace_implicit = FALSE; - } - } | enum_declaration - { - /* skip declarations with errors */ - if ($1 != NULL) { - vala_namespace_add_enum (current_namespace, $1); - vala_source_file_add_node (current_source_file, VALA_CODE_NODE ($1)); - g_object_unref ($1); - } - - if (current_namespace_implicit) { - /* current namespace has been declared implicitly */ - current_namespace = vala_code_context_get_global_namespace (vala_source_file_get_context (current_source_file)); - current_namespace_implicit = FALSE; - } - } - | flags_declaration - { - /* skip declarations with errors */ - if ($1 != NULL) { - vala_namespace_add_flags (current_namespace, $1); - vala_source_file_add_node (current_source_file, VALA_CODE_NODE ($1)); - g_object_unref ($1); - } - - if (current_namespace_implicit) { - /* current namespace has been declared implicitly */ - current_namespace = vala_code_context_get_global_namespace (vala_source_file_get_context (current_source_file)); - current_namespace_implicit = FALSE; - } - } | callback_declaration - { - /* skip declarations with errors */ - if ($1 != NULL) { - vala_namespace_add_callback (current_namespace, $1); - vala_source_file_add_node (current_source_file, VALA_CODE_NODE ($1)); - g_object_unref ($1); - } - - if (current_namespace_implicit) { - /* current namespace has been declared implicitly */ - current_namespace = vala_code_context_get_global_namespace (vala_source_file_get_context (current_source_file)); - current_namespace_implicit = FALSE; - } - } | constant_declaration { /* skip declarations with errors */ if ($1 != NULL) { - vala_namespace_add_constant (current_namespace, $1); + vala_namespace_add_constant (VALA_NAMESPACE (symbol_stack->data), $1); vala_source_file_add_node (current_source_file, VALA_CODE_NODE ($1)); g_object_unref ($1); } @@ -2218,7 +2104,7 @@ namespace_member_declaration * to explicitly state it */ vala_field_set_instance ($1, FALSE); - vala_namespace_add_field (current_namespace, $1); + vala_namespace_add_field (VALA_NAMESPACE (symbol_stack->data), $1); vala_source_file_add_node (current_source_file, VALA_CODE_NODE ($1)); g_object_unref ($1); } @@ -2231,7 +2117,7 @@ namespace_member_declaration * to explicitly state it */ vala_method_set_instance ($1, FALSE); - vala_namespace_add_method (current_namespace, $1); + vala_namespace_add_method (VALA_NAMESPACE (symbol_stack->data), $1); vala_source_file_add_node (current_source_file, VALA_CODE_NODE ($1)); g_object_unref ($1); } @@ -2245,54 +2131,84 @@ class_declaration ValaSourceReference *src; char *name = $6; - + + ValaSymbol *parent_symbol = VALA_SYMBOL (g_object_ref (symbol_stack->data)); + ValaScope *parent_scope = VALA_SCOPE (scope_stack->data); + if ($7 != NULL) { ValaSourceReference *ns_src = src(@6); - current_namespace = vala_namespace_new ($6, ns_src); + parent_symbol = vala_scope_lookup (parent_scope, $6); + if (parent_symbol != NULL) { + if (check_is_namespace (parent_symbol, src)) { + if (!vala_source_file_get_pkg (current_source_file)) { + vala_namespace_set_pkg (VALA_NAMESPACE (parent_symbol), FALSE); + } + } + } else { + parent_symbol = VALA_SYMBOL (vala_namespace_new ($6, ns_src)); + vala_namespace_set_pkg (VALA_NAMESPACE (parent_symbol), vala_source_file_get_pkg (current_source_file)); + vala_namespace_add_namespace (VALA_NAMESPACE (symbol_stack->data), VALA_NAMESPACE (parent_symbol)); + } + parent_scope = vala_symbol_get_scope (parent_symbol); g_free ($6); g_object_unref (ns_src); - current_namespace_implicit = TRUE; - - vala_code_context_add_namespace (vala_source_file_get_context (current_source_file), current_namespace); - g_object_unref (current_namespace); name = $7; } - + src = src_com(@6, $1); - current_class = vala_class_new (name, src); - g_free (name); - g_object_unref (src); - - VALA_CODE_NODE(current_class)->attributes = $2; - if ($3 != 0) { - VALA_DATA_TYPE(current_class)->access = $3; - } - if (($4 & VALA_MODIFIER_ABSTRACT) == VALA_MODIFIER_ABSTRACT) { - vala_class_set_is_abstract (current_class, TRUE); - } - if (($4 & VALA_MODIFIER_STATIC) == VALA_MODIFIER_STATIC) { - vala_class_set_is_static (current_class, TRUE); - } - if ($8 != NULL) { - for (l = $8; l != NULL; l = l->next) { - vala_class_add_type_parameter (current_class, l->data); - g_object_unref (l->data); + ValaSymbol *current_symbol = vala_scope_lookup (parent_scope, name); + if (current_symbol != NULL) { + if (check_is_class (current_symbol, src)) { + // merge class declarations } - g_list_free ($8); - } - if ($9 != NULL) { - for (l = $9; l != NULL; l = l->next) { - vala_class_add_base_type (current_class, l->data); - g_object_unref (l->data); + } else { + current_symbol = VALA_SYMBOL (vala_class_new (name, src)); + g_free (name); + g_object_unref (src); + + if (VALA_IS_CLASS (parent_symbol)) { + vala_class_add_class (VALA_CLASS (parent_symbol), VALA_CLASS (current_symbol)); + } else if (VALA_IS_NAMESPACE (parent_symbol)) { + vala_namespace_add_class (VALA_NAMESPACE (parent_symbol), VALA_CLASS (current_symbol)); + vala_source_file_add_node (current_source_file, VALA_CODE_NODE (current_symbol)); + } else { + g_assert_not_reached (); + } + + VALA_CODE_NODE (current_symbol)->attributes = $2; + if ($3 != 0) { + VALA_DATA_TYPE (current_symbol)->access = $3; + } + if (($4 & VALA_MODIFIER_ABSTRACT) == VALA_MODIFIER_ABSTRACT) { + vala_class_set_is_abstract (VALA_CLASS (current_symbol), TRUE); + } + if (($4 & VALA_MODIFIER_STATIC) == VALA_MODIFIER_STATIC) { + vala_class_set_is_static (VALA_CLASS (current_symbol), TRUE); + } + if ($8 != NULL) { + for (l = $8; l != NULL; l = l->next) { + vala_class_add_type_parameter (VALA_CLASS (current_symbol), l->data); + g_object_unref (l->data); + } + g_list_free ($8); + } + if ($9 != NULL) { + for (l = $9; l != NULL; l = l->next) { + vala_class_add_base_type (VALA_CLASS (current_symbol), l->data); + g_object_unref (l->data); + } + g_list_free ($9); } - g_list_free ($9); } + + g_object_unref (parent_symbol); + + push_symbol (current_symbol); } class_body { - $$ = current_class; - current_class = NULL; + g_object_unref (pop_symbol ()); } ; @@ -2404,7 +2320,7 @@ class_member_declaration { /* skip declarations with errors */ if ($1 != NULL) { - vala_class_add_constant (current_class, $1); + vala_class_add_constant (VALA_CLASS (symbol_stack->data), $1); g_object_unref ($1); } } @@ -2412,7 +2328,7 @@ class_member_declaration { /* skip declarations with errors */ if ($1 != NULL) { - vala_class_add_field (current_class, $1); + vala_class_add_field (VALA_CLASS (symbol_stack->data), $1); g_object_unref ($1); } } @@ -2420,7 +2336,7 @@ class_member_declaration { /* skip declarations with errors */ if ($1 != NULL) { - vala_class_add_method (current_class, $1); + vala_class_add_method (VALA_CLASS (symbol_stack->data), $1); g_object_unref ($1); } } @@ -2428,7 +2344,7 @@ class_member_declaration { /* skip declarations with errors */ if ($1 != NULL) { - vala_class_add_property (current_class, $1, FALSE); + vala_class_add_property (VALA_CLASS (symbol_stack->data), $1, FALSE); g_object_unref ($1); } } @@ -2436,7 +2352,7 @@ class_member_declaration { /* skip declarations with errors */ if ($1 != NULL) { - vala_class_add_signal (current_class, $1); + vala_class_add_signal (VALA_CLASS (symbol_stack->data), $1); g_object_unref ($1); } } @@ -2444,7 +2360,7 @@ class_member_declaration { /* skip declarations with errors */ if ($1 != NULL) { - vala_class_set_constructor (current_class, $1); + vala_class_set_constructor (VALA_CLASS (symbol_stack->data), $1); g_object_unref ($1); } } @@ -2452,17 +2368,19 @@ class_member_declaration { /* skip declarations with errors */ if ($1 != NULL) { - vala_class_set_destructor (current_class, $1); + vala_class_set_destructor (VALA_CLASS (symbol_stack->data), $1); g_object_unref ($1); } } + | class_declaration + | struct_declaration ; constant_declaration : comment opt_attributes opt_access_modifier CONST type variable_declarator SEMICOLON { ValaSourceReference *src = src_com(@5, $1); - $$ = vala_constant_new (vala_variable_declarator_get_name ($6), $5, vala_variable_declarator_get_initializer ($6), src); + $$ = vala_constant_new (vala_symbol_get_name (VALA_SYMBOL ($6)), $5, vala_variable_declarator_get_initializer ($6), src); g_object_unref (src); g_object_unref ($5); g_object_unref ($6); @@ -2486,7 +2404,7 @@ field_declaration vala_type_reference_set_takes_ownership ($5, TRUE); } - $$ = vala_field_new (vala_variable_declarator_get_name ($6), $5, vala_variable_declarator_get_initializer ($6), src); + $$ = vala_field_new (vala_symbol_get_name (VALA_SYMBOL ($6)), $5, vala_variable_declarator_get_initializer ($6), src); g_object_unref (src); if ($3 != 0) { $$->access = $3; @@ -2581,7 +2499,7 @@ method_declaration : method_header method_body { $$ = $1; - vala_method_set_body ($$, VALA_BLOCK($2)); + vala_method_set_body ($$, $2); if ($2 != NULL) { g_object_unref ($2); } @@ -2944,12 +2862,11 @@ destructor_declaration struct_declaration : struct_header { - current_struct = $1; + push_symbol (VALA_SYMBOL ($1)); } struct_body { - $$ = current_struct; - current_struct = NULL; + g_object_unref (pop_symbol ()); } ; @@ -2961,15 +2878,26 @@ struct_header char *name = $5; + ValaSymbol *parent_symbol = VALA_SYMBOL (g_object_ref (symbol_stack->data)); + ValaScope *parent_scope = VALA_SCOPE (scope_stack->data); + if ($6 != NULL) { ValaSourceReference *ns_src = src(@5); - current_namespace = vala_namespace_new ($5, ns_src); + parent_symbol = vala_scope_lookup (parent_scope, $5); + if (parent_symbol != NULL) { + if (check_is_namespace (parent_symbol, src)) { + if (!vala_source_file_get_pkg (current_source_file)) { + vala_namespace_set_pkg (VALA_NAMESPACE (parent_symbol), FALSE); + } + } + } else { + parent_symbol = VALA_SYMBOL (vala_namespace_new ($5, ns_src)); + vala_namespace_set_pkg (VALA_NAMESPACE (parent_symbol), vala_source_file_get_pkg (current_source_file)); + vala_namespace_add_namespace (VALA_NAMESPACE (symbol_stack->data), VALA_NAMESPACE (parent_symbol)); + } + parent_scope = vala_symbol_get_scope (parent_symbol); g_free ($5); g_object_unref (ns_src); - current_namespace_implicit = TRUE; - - vala_code_context_add_namespace (vala_source_file_get_context (current_source_file), current_namespace); - g_object_unref (current_namespace); name = $6; } @@ -2978,6 +2906,16 @@ struct_header $$ = vala_struct_new (name, src); g_free (name); g_object_unref (src); + + if (VALA_IS_CLASS (parent_symbol)) { + vala_class_add_struct (VALA_CLASS (parent_symbol), $$); + } else if (VALA_IS_NAMESPACE (parent_symbol)) { + vala_namespace_add_struct (VALA_NAMESPACE (parent_symbol), $$); + vala_source_file_add_node (current_source_file, VALA_CODE_NODE ($$)); + } else { + g_assert_not_reached (); + } + for (l = $7; l != NULL; l = l->next) { vala_struct_add_type_parameter ($$, l->data); } @@ -3014,7 +2952,7 @@ struct_member_declaration { /* skip declarations with errors */ if ($1 != NULL) { - vala_struct_add_field (current_struct, $1); + vala_struct_add_field (VALA_STRUCT (symbol_stack->data), $1); g_object_unref ($1); } } @@ -3022,7 +2960,7 @@ struct_member_declaration { /* skip declarations with errors */ if ($1 != NULL) { - vala_struct_add_method (current_struct, $1); + vala_struct_add_method (VALA_STRUCT (symbol_stack->data), $1); g_object_unref ($1); } } @@ -3034,35 +2972,50 @@ interface_declaration ValaSourceReference *src; char *name = $6; + ValaSymbol *parent_symbol = VALA_SYMBOL (g_object_ref (symbol_stack->data)); + ValaScope *parent_scope = VALA_SCOPE (scope_stack->data); + if ($7 != NULL) { ValaSourceReference *ns_src = src(@6); - current_namespace = vala_namespace_new ($6, ns_src); + parent_symbol = vala_scope_lookup (parent_scope, $6); + if (parent_symbol != NULL) { + if (check_is_namespace (parent_symbol, src)) { + if (!vala_source_file_get_pkg (current_source_file)) { + vala_namespace_set_pkg (VALA_NAMESPACE (parent_symbol), FALSE); + } + } + } else { + parent_symbol = VALA_SYMBOL (vala_namespace_new ($6, ns_src)); + vala_namespace_set_pkg (VALA_NAMESPACE (parent_symbol), vala_source_file_get_pkg (current_source_file)); + vala_namespace_add_namespace (VALA_NAMESPACE (symbol_stack->data), VALA_NAMESPACE (parent_symbol)); + } + parent_scope = vala_symbol_get_scope (parent_symbol); g_free ($6); g_object_unref (ns_src); - current_namespace_implicit = TRUE; - - vala_code_context_add_namespace (vala_source_file_get_context (current_source_file), current_namespace); - g_object_unref (current_namespace); name = $7; } src = src_com(@6, $1); - current_interface = vala_interface_new (name, src); + ValaInterface *iface = vala_interface_new (name, src); g_free (name); g_object_unref (src); - VALA_CODE_NODE(current_interface)->attributes = $2; + vala_namespace_add_interface (VALA_NAMESPACE (parent_symbol), iface); + vala_source_file_add_node (current_source_file, VALA_CODE_NODE (iface)); + g_object_unref (parent_symbol); + + VALA_CODE_NODE (iface)->attributes = $2; if ($3 != 0) { - VALA_DATA_TYPE(current_interface)->access = $3; + VALA_DATA_TYPE (iface)->access = $3; } if (($4 & VALA_MODIFIER_STATIC) == VALA_MODIFIER_STATIC) { - vala_interface_set_is_static (current_interface, TRUE); + vala_interface_set_is_static (iface, TRUE); } if ($8 != NULL) { GList *l; for (l = $8; l != NULL; l = l->next) { - vala_interface_add_type_parameter (current_interface, l->data); + vala_interface_add_type_parameter (iface, l->data); g_object_unref (l->data); } g_list_free ($8); @@ -3070,15 +3023,17 @@ interface_declaration if ($9 != NULL) { GList *l; for (l = $9; l != NULL; l = l->next) { - vala_interface_add_prerequisite (current_interface, l->data); + vala_interface_add_prerequisite (iface, l->data); g_object_unref (l->data); } g_list_free ($9); } + + push_symbol (VALA_SYMBOL (iface)); } interface_body { - $$ = current_interface; + g_object_unref (pop_symbol ()); } ; @@ -3101,7 +3056,7 @@ interface_member_declaration { /* skip declarations with errors */ if ($1 != NULL) { - vala_interface_add_method (current_interface, $1); + vala_interface_add_method (VALA_INTERFACE (symbol_stack->data), $1); g_object_unref ($1); } } @@ -3109,7 +3064,7 @@ interface_member_declaration { /* skip declarations with errors */ if ($1 != NULL) { - vala_interface_add_property (current_interface, $1); + vala_interface_add_property (VALA_INTERFACE (symbol_stack->data), $1); g_object_unref ($1); } } @@ -3117,7 +3072,7 @@ interface_member_declaration { /* skip declarations with errors */ if ($1 != NULL) { - vala_interface_add_signal (current_interface, $1); + vala_interface_add_signal (VALA_INTERFACE (symbol_stack->data), $1); g_object_unref ($1); } } @@ -3130,34 +3085,50 @@ enum_declaration char *name = $5; + ValaSymbol *parent_symbol = VALA_SYMBOL (g_object_ref (symbol_stack->data)); + ValaScope *parent_scope = VALA_SCOPE (scope_stack->data); + if ($6 != NULL) { ValaSourceReference *ns_src = src(@5); - current_namespace = vala_namespace_new ($5, ns_src); + parent_symbol = vala_scope_lookup (parent_scope, $5); + if (parent_symbol != NULL) { + if (check_is_namespace (parent_symbol, src)) { + if (!vala_source_file_get_pkg (current_source_file)) { + vala_namespace_set_pkg (VALA_NAMESPACE (parent_symbol), FALSE); + } + } + } else { + parent_symbol = VALA_SYMBOL (vala_namespace_new ($5, ns_src)); + vala_namespace_set_pkg (VALA_NAMESPACE (parent_symbol), vala_source_file_get_pkg (current_source_file)); + vala_namespace_add_namespace (VALA_NAMESPACE (symbol_stack->data), VALA_NAMESPACE (parent_symbol)); + } + parent_scope = vala_symbol_get_scope (parent_symbol); g_free ($5); g_object_unref (ns_src); - current_namespace_implicit = TRUE; - - vala_code_context_add_namespace (vala_source_file_get_context (current_source_file), current_namespace); - g_object_unref (current_namespace); name = $6; } src = src_com(@5, $1); - current_enum = vala_enum_new (name, src); + ValaEnum *en = vala_enum_new (name, src); g_free (name); g_object_unref (src); - VALA_CODE_NODE(current_enum)->attributes = $2; + vala_namespace_add_enum (VALA_NAMESPACE (parent_symbol), en); + vala_source_file_add_node (current_source_file, VALA_CODE_NODE (en)); + g_object_unref (parent_symbol); + + VALA_CODE_NODE (en)->attributes = $2; if ($3 != 0) { - VALA_DATA_TYPE(current_enum)->access = $3; + VALA_DATA_TYPE (en)->access = $3; } + + push_symbol (VALA_SYMBOL (en)); } enum_body { - $$ = current_enum; - current_enum = NULL; + g_object_unref (pop_symbol ()); } ; @@ -3180,7 +3151,7 @@ enum_member_declaration { ValaEnumValue *ev = vala_enum_value_new ($2); g_free ($2); - vala_enum_add_value (current_enum, ev); + vala_enum_add_value (VALA_ENUM (symbol_stack->data), ev); g_object_unref (ev); } | opt_attributes identifier ASSIGN expression @@ -3188,7 +3159,7 @@ enum_member_declaration ValaEnumValue *ev = vala_enum_value_new_with_value ($2, $4); g_free ($2); g_object_unref ($4); - vala_enum_add_value (current_enum, ev); + vala_enum_add_value (VALA_ENUM (symbol_stack->data), ev); g_object_unref (ev); } ; @@ -3208,90 +3179,12 @@ enum_method_declaration { /* skip declarations with errors */ if ($1 != NULL) { - vala_enum_add_method (current_enum, $1); + vala_enum_add_method (VALA_ENUM (symbol_stack->data), $1); g_object_unref ($1); } } ; -flags_declaration - : comment opt_attributes opt_access_modifier FLAGS identifier opt_name_specifier flags_body - { - GList *l; - ValaSourceReference *src; - - char *name = $5; - - if ($6 != NULL) { - ValaSourceReference *ns_src = src(@5); - current_namespace = vala_namespace_new ($5, ns_src); - g_free ($5); - g_object_unref (ns_src); - current_namespace_implicit = TRUE; - - vala_code_context_add_namespace (vala_source_file_get_context (current_source_file), current_namespace); - g_object_unref (current_namespace); - - name = $6; - } - - src = src_com(@5, $1); - $$ = vala_flags_new (name, src); - g_free (name); - g_object_unref (src); - - VALA_CODE_NODE($$)->attributes = $2; - - if ($3 != 0) { - VALA_DATA_TYPE($$)->access = $3; - } - for (l = $7; l != NULL; l = l->next) { - vala_flags_add_value ($$, l->data); - g_object_unref (l->data); - } - } - ; - -flags_body - : OPEN_BRACE opt_flags_member_declarations CLOSE_BRACE - { - $$ = $2; - } - ; - -opt_flags_member_declarations - : /* empty */ - { - $$ = NULL; - } - | flags_member_declarations opt_comma - ; - -flags_member_declarations - : flags_member_declaration - { - $$ = g_list_append (NULL, $1); - } - | flags_member_declarations COMMA flags_member_declaration - { - $$ = g_list_append ($1, $3); - } - ; - -flags_member_declaration - : opt_attributes identifier - { - $$ = vala_flags_value_new ($2); - g_free ($2); - } - | opt_attributes identifier ASSIGN expression - { - $$ = vala_flags_value_new_with_value ($2, $4); - g_free ($2); - g_object_unref ($4); - } - ; - callback_declaration : comment opt_attributes opt_access_modifier opt_modifiers DELEGATE type identifier opt_name_specifier opt_type_parameter_list OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS opt_throws_declaration SEMICOLON { @@ -3299,43 +3192,61 @@ callback_declaration GList *l; char *name = $7; + ValaSymbol *parent_symbol = VALA_SYMBOL (g_object_ref (symbol_stack->data)); + ValaScope *parent_scope = VALA_SCOPE (scope_stack->data); + if ($8 != NULL) { ValaSourceReference *ns_src = src(@7); - current_namespace = vala_namespace_new ($7, ns_src); + parent_symbol = vala_scope_lookup (parent_scope, $7); + if (parent_symbol != NULL) { + if (check_is_namespace (parent_symbol, src)) { + if (!vala_source_file_get_pkg (current_source_file)) { + vala_namespace_set_pkg (VALA_NAMESPACE (parent_symbol), FALSE); + } + } + } else { + parent_symbol = VALA_SYMBOL (vala_namespace_new ($7, ns_src)); + vala_namespace_set_pkg (VALA_NAMESPACE (parent_symbol), vala_source_file_get_pkg (current_source_file)); + vala_namespace_add_namespace (VALA_NAMESPACE (symbol_stack->data), VALA_NAMESPACE (parent_symbol)); + } + parent_scope = vala_symbol_get_scope (parent_symbol); g_free ($7); g_object_unref (ns_src); - current_namespace_implicit = TRUE; - - vala_code_context_add_namespace (vala_source_file_get_context (current_source_file), current_namespace); - g_object_unref (current_namespace); name = $8; } src = src_com(@7, $1); - $$ = vala_callback_new (name, $6, src); + ValaCallback *cb = vala_callback_new (name, $6, src); g_free (name); g_object_unref ($6); g_object_unref (src); + + vala_namespace_add_callback (VALA_NAMESPACE (parent_symbol), cb); + vala_source_file_add_node (current_source_file, VALA_CODE_NODE (cb)); + g_object_unref (parent_symbol); + if ($3 != 0) { - VALA_DATA_TYPE($$)->access = $3; + VALA_DATA_TYPE (cb)->access = $3; } - VALA_CODE_NODE($$)->attributes = $2; + VALA_CODE_NODE (cb)->attributes = $2; if ($9 != NULL) { for (l = $9; l != NULL; l = l->next) { - vala_callback_add_type_parameter ($$, l->data); + vala_callback_add_type_parameter (cb, l->data); g_object_unref (l->data); } g_list_free ($9); } if ($11 != NULL) { for (l = $11; l != NULL; l = l->next) { - vala_callback_add_parameter ($$, l->data); + vala_callback_add_parameter (cb, l->data); g_object_unref (l->data); } g_list_free ($11); } + + g_object_unref (cb); } ; @@ -3573,7 +3484,7 @@ void vala_parser_parse_file (ValaParser *parser, ValaSourceFile *source_file) { current_source_file = source_file; - current_namespace = vala_code_context_get_global_namespace (vala_source_file_get_context (current_source_file)); + push_symbol (VALA_SYMBOL (vala_code_context_get_root (vala_source_file_get_context (source_file)))); yyin = fopen (vala_source_file_get_filename (current_source_file), "r"); if (yyin == NULL) { printf ("Couldn't open source file: %s.\n", vala_source_file_get_filename (current_source_file)); @@ -3587,3 +3498,40 @@ vala_parser_parse_file (ValaParser *parser, ValaSourceFile *source_file) fclose (yyin); yyin = NULL; } + +static void push_symbol (ValaSymbol *symbol) { + symbol_stack = g_list_prepend (symbol_stack, symbol); + scope_stack = g_list_prepend (scope_stack, vala_symbol_get_scope (symbol)); +} + +static ValaSymbol *pop_symbol (void) { + ValaSymbol *sym = VALA_SYMBOL (symbol_stack->data); + symbol_stack = g_list_delete_link (symbol_stack, symbol_stack); + scope_stack = g_list_delete_link (scope_stack, scope_stack); + return sym; +} + +static gboolean check_is_namespace (ValaSymbol *symbol, ValaSourceReference *src) { + if (!VALA_IS_NAMESPACE (symbol)) { + char *sym_name = vala_symbol_get_full_name (symbol); + char *error_msg = g_strdup_printf ("`%s` already exists but is not a namespace", sym_name); + g_free (sym_name); + vala_report_error (src, error_msg); + g_free (error_msg); + return FALSE; + } + return TRUE; +} + +static gboolean check_is_class (ValaSymbol *symbol, ValaSourceReference *src) { + if (!VALA_IS_CLASS (symbol)) { + char *sym_name = vala_symbol_get_full_name (symbol); + char *error_msg = g_strdup_printf ("`%s` already exists but is not a class", sym_name); + g_free (sym_name); + vala_report_error (src, error_msg); + g_free (error_msg); + return FALSE; + } + return TRUE; +} + diff --git a/vala/scanner.l b/vala/scanner.l index a7c608c97..a85de62b0 100644 --- a/vala/scanner.l +++ b/vala/scanner.l @@ -143,7 +143,6 @@ literal ({integer_literal}|{real_literal}|{character_literal}|{string_literal "enum" { uploc; return ENUM; } "false" { uploc; return VALA_FALSE; } "finally" { uploc; return FINALLY; } -"flags" { uploc; return FLAGS; } "for" { uploc; return FOR; } "foreach" { uploc; return FOREACH; } "get" { uploc; return GET; } diff --git a/vala/vala.h b/vala/vala.h index ab5830e0f..bc016b899 100644 --- a/vala/vala.h +++ b/vala/vala.h @@ -28,8 +28,6 @@ #include <vala/valaexpression.h> #include <vala/valaexpressionstatement.h> #include <vala/valafield.h> -#include <vala/valaflags.h> -#include <vala/valaflagsvalue.h> #include <vala/valaforeachstatement.h> #include <vala/valaformalparameter.h> #include <vala/valaforstatement.h> @@ -60,6 +58,7 @@ #include <vala/valareferencetransferexpression.h> #include <vala/valareport.h> #include <vala/valareturnstatement.h> +#include <vala/valascope.h> #include <vala/valasignal.h> #include <vala/valasizeofexpression.h> #include <vala/valasourcefile.h> diff --git a/vala/valaarray.vala b/vala/valaarray.vala index 100e7a6b5..5cf51ed97 100644 --- a/vala/valaarray.vala +++ b/vala/valaarray.vala @@ -90,10 +90,8 @@ public class Vala.Array : DataType { name = "%s]".printf (name); length_field = new ArrayLengthField (source_reference); - length_field.symbol = new Symbol (length_field); resize_method = new ArrayResizeMethod (source_reference); - resize_method.symbol = new Symbol (resize_method); } /** diff --git a/vala/valaarraylengthfield.vala b/vala/valaarraylengthfield.vala index 8cbf17139..9dc6ee278 100644 --- a/vala/valaarraylengthfield.vala +++ b/vala/valaarraylengthfield.vala @@ -30,7 +30,7 @@ public class Vala.ArrayLengthField : Field { access = MemberAccessibility.PUBLIC; var root_symbol = source_reference.file.context.root; - type_reference.data_type = (DataType) root_symbol.lookup ("int").node; + type_reference.data_type = (DataType) root_symbol.scope.lookup ("int"); } /** diff --git a/vala/valaarrayresizemethod.vala b/vala/valaarrayresizemethod.vala index e8b1eac1a..7a1b0c627 100644 --- a/vala/valaarrayresizemethod.vala +++ b/vala/valaarrayresizemethod.vala @@ -33,7 +33,7 @@ public class Vala.ArrayResizeMethod : Method { var root_symbol = source_reference.file.context.root; var int_type = new TypeReference (); - int_type.data_type = (DataType) root_symbol.lookup ("int").node; + int_type.data_type = (DataType) root_symbol.scope.lookup ("int"); add_parameter (new FormalParameter ("length", int_type)); diff --git a/vala/valaattributeprocessor.vala b/vala/valaattributeprocessor.vala index e78b5e321..525ff2855 100644 --- a/vala/valaattributeprocessor.vala +++ b/vala/valaattributeprocessor.vala @@ -42,6 +42,10 @@ public class Vala.AttributeProcessor : CodeVisitor { public override void visit_namespace (Namespace! ns) { ns.process_attributes (); + + foreach (Namespace ns in ns.get_namespaces ()) { + ns.accept (this); + } } public override void visit_class (Class! cl) { @@ -66,10 +70,6 @@ public class Vala.AttributeProcessor : CodeVisitor { en.process_attributes (); } - public override void visit_flags (Flags! fl) { - fl.process_attributes (); - } - public override void visit_method (Method! m) { m.process_attributes (); } diff --git a/vala/valablock.vala b/vala/valablock.vala index 3f73c4b60..94830a608 100644 --- a/vala/valablock.vala +++ b/vala/valablock.vala @@ -25,7 +25,7 @@ using GLib; /** * Represents a source code block. */ -public class Vala.Block : Statement { +public class Vala.Block : Symbol, Statement { /** * Specifies whether this block contains a jump statement. This * information can be used to remove unreachable block cleanup code. @@ -40,8 +40,7 @@ public class Vala.Block : Statement { * * @param source reference to source code */ - public Block (SourceReference source = null) { - source_reference = source; + public Block (construct SourceReference source_reference = null) { } /** diff --git a/vala/valabreakstatement.vala b/vala/valabreakstatement.vala index 25f91b837..3180fd5a4 100644 --- a/vala/valabreakstatement.vala +++ b/vala/valabreakstatement.vala @@ -1,6 +1,6 @@ /* valabreakstatement.vala * - * Copyright (C) 2006 Jürg Billeter + * Copyright (C) 2006-2007 Jürg Billeter * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -25,7 +25,7 @@ using GLib; /** * Represents a break statement in the source code. */ -public class Vala.BreakStatement : Statement { +public class Vala.BreakStatement : CodeNode, Statement { /** * Creates a new break statement. * diff --git a/vala/valacallback.vala b/vala/valacallback.vala index c1ad58874..a959fb198 100644 --- a/vala/valacallback.vala +++ b/vala/valacallback.vala @@ -51,10 +51,7 @@ public class Vala.Callback : DataType { * @param source reference to source code * @return newly created callback */ - public Callback (string _name, TypeReference _return_type, SourceReference source = null) { - name = _name; - return_type = _return_type; - source_reference = source; + public Callback (construct string name, construct TypeReference return_type, construct SourceReference source_reference = null) { } /** @@ -65,6 +62,7 @@ public class Vala.Callback : DataType { public void add_type_parameter (TypeParameter! p) { type_parameters.append (p); p.type = this; + scope.add (p.name, p); } /** @@ -74,6 +72,7 @@ public class Vala.Callback : DataType { */ public void add_parameter (FormalParameter! param) { parameters.append (param); + scope.add (param.name, param); } /** @@ -149,7 +148,7 @@ public class Vala.Callback : DataType { public override string get_cname (bool const_type = false) { if (cname == null) { - cname = "%s%s".printf (@namespace.get_cprefix (), name); + cname = "%s%s".printf (parent_symbol.get_cprefix (), name); } return cname; } diff --git a/vala/valaclass.vala b/vala/valaclass.vala index 66389cb9f..2786aba86 100644 --- a/vala/valaclass.vala +++ b/vala/valaclass.vala @@ -67,6 +67,10 @@ public class Vala.Class : DataType { private List<Method> methods; private List<Property> properties; private List<Signal> signals; + + // inner types + private List<Class> classes; + private List<Struct> structs; /** * Specifies the default construction method. @@ -122,6 +126,7 @@ public class Vala.Class : DataType { public void add_type_parameter (TypeParameter! p) { type_parameters.append (p); p.type = this; + scope.add (p.name, p); } /** @@ -140,6 +145,7 @@ public class Vala.Class : DataType { */ public void add_constant (Constant! c) { constants.append (c); + scope.add (c.name, c); } /** @@ -154,6 +160,7 @@ public class Vala.Class : DataType { if (f.access == MemberAccessibility.PRIVATE && f.instance) { _has_private_fields = true; } + scope.add (f.name, f); } /** @@ -171,7 +178,17 @@ public class Vala.Class : DataType { * @param m a method */ public void add_method (Method! m) { + if (m.instance) { + m.this_parameter = new FormalParameter ("this", new TypeReference ()); + m.this_parameter.type_reference.data_type = this; + m.scope.add (m.this_parameter.name, m.this_parameter); + } + if (m is CreationMethod && m.name == null) { + default_construction_method = m; + } + methods.append (m); + scope.add (m.name, m); } /** @@ -190,6 +207,11 @@ public class Vala.Class : DataType { */ public void add_property (Property! prop, bool no_field = false) { properties.append (prop); + scope.add (prop.name, prop); + + prop.this_parameter = new FormalParameter ("this", new TypeReference ()); + prop.this_parameter.type_reference.data_type = this; + prop.scope.add (prop.this_parameter.name, prop.this_parameter); if (!no_field && prop.set_accessor != null && prop.set_accessor.body == null && source_reference != null && !source_reference.file.pkg) { @@ -219,6 +241,7 @@ public class Vala.Class : DataType { */ public void add_signal (Signal! sig) { signals.append (sig); + scope.add (sig.name, sig); } /** @@ -230,6 +253,26 @@ public class Vala.Class : DataType { return signals.copy (); } + /** + * Adds the specified class as an inner class. + * + * @param cl a class + */ + public void add_class (Class! cl) { + classes.append (cl); + scope.add (cl.name, cl); + } + + /** + * Adds the specified struct as an inner struct. + * + * @param st a struct + */ + public void add_struct (Struct! st) { + structs.append (st); + scope.add (st.name, st); + } + public override void accept (CodeVisitor! visitor) { visitor.visit_class (this); } @@ -270,11 +313,23 @@ public class Vala.Class : DataType { if (destructor != null) { destructor.accept (visitor); } + + foreach (Class cl in classes) { + cl.accept (visitor); + } + + foreach (Struct st in structs) { + st.accept (visitor); + } + } + + public override string! get_cprefix () { + return get_cname (); } public override string get_cname (bool const_type = false) { if (cname == null) { - cname = "%s%s".printf (@namespace.get_cprefix (), name); + cname = "%s%s".printf (parent_symbol.get_cprefix (), name); } return cname; } @@ -290,7 +345,7 @@ public class Vala.Class : DataType { private string get_lower_case_csuffix () { if (lower_case_csuffix == null) { - lower_case_csuffix = Namespace.camel_case_to_lower_case (name); + lower_case_csuffix = camel_case_to_lower_case (name); } return lower_case_csuffix; } @@ -299,10 +354,10 @@ public class Vala.Class : DataType { if (infix == null) { infix = ""; } - return "%s%s%s".printf (@namespace.get_lower_case_cprefix (), infix, get_lower_case_csuffix ()); + return "%s%s%s".printf (parent_symbol.get_lower_case_cprefix (), infix, get_lower_case_csuffix ()); } - public override string get_lower_case_cprefix () { + public override string! get_lower_case_cprefix () { return "%s_".printf (get_lower_case_cname (null)); } diff --git a/vala/valacodecontext.vala b/vala/valacodecontext.vala index 118fb67d8..4ae5d3f26 100644 --- a/vala/valacodecontext.vala +++ b/vala/valacodecontext.vala @@ -85,49 +85,19 @@ public class Vala.CodeContext { public Method module_init_method { get; set; } List<SourceFile> source_files; - private Symbol! _root = new Symbol (); - - private Namespace global_namespace = new Namespace (null); - private List<Namespace> namespaces; + private Namespace! _root = new Namespace (null); List<SourceFileCycle> cycles; private List<string> packages; /** - * The root symbol of the code tree. - * - * @return root symbol - */ - public Symbol! root { - get { return _root; } - } - - /** - * Adds the specified namespace. - * - * @param ns a namespace - */ - public void add_namespace (Namespace! ns) { - namespaces.append (ns); - } - - /** - * Returns the implicitly declared root namespace. + * The root namespace of the symbol tree. * * @return root namespace */ - public Namespace! get_global_namespace () { - return global_namespace; - } - - /** - * Returns a copy of the list of namespaces. - * - * @return namespace list - */ - public List<weak Namespace> get_namespaces () { - return namespaces.copy (); + public Namespace! root { + get { return _root; } } /** @@ -182,11 +152,7 @@ public class Vala.CodeContext { * @param visitor the visitor to be called when traversing */ public void accept (CodeVisitor! visitor) { - global_namespace.accept (visitor); - - foreach (Namespace ns in namespaces) { - ns.accept (visitor); - } + root.accept (visitor); foreach (SourceFile file in source_files) { file.accept (visitor); diff --git a/vala/valacodenode.vala b/vala/valacodenode.vala index 696ad1453..5fc2bcb19 100644 --- a/vala/valacodenode.vala +++ b/vala/valacodenode.vala @@ -33,12 +33,7 @@ public abstract class Vala.CodeNode { * Parent of this code node. */ public CodeNode parent_node { get; set; } - - /** - * Symbol that corresponds to this code node. - */ - public Symbol symbol { get; set; } - + /** * References the location in the source file where this code node has * been written. diff --git a/vala/valacodevisitor.vala b/vala/valacodevisitor.vala index b4b702e44..9a92c4d45 100644 --- a/vala/valacodevisitor.vala +++ b/vala/valacodevisitor.vala @@ -84,22 +84,6 @@ public abstract class Vala.CodeVisitor { } /** - * Visit operation called for flags. - * - * @param fl a flags - */ - public virtual void visit_flags (Flags! fl) { - } - - /** - * Visit operation called for flags values. - * - * @param fv an flags value - */ - public virtual void visit_flags_value (FlagsValue! fv) { - } - - /** * Visit operation called for callbacks. * * @param cb a callback diff --git a/vala/valaconstant.vala b/vala/valaconstant.vala index 13ebe0fff..16b30ca7b 100644 --- a/vala/valaconstant.vala +++ b/vala/valaconstant.vala @@ -27,11 +27,6 @@ using GLib; */ public class Vala.Constant : Member, Lockable { /** - * The symbol name of this constant. - */ - public string! name { get; set construct; } - - /** * The data type of this constant. */ public TypeReference! type_reference { get; set construct; } @@ -90,17 +85,11 @@ public class Vala.Constant : Member, Lockable { */ public string! get_cname () { if (cname == null) { - if (symbol.parent_symbol.node is DataType) { - var t = (DataType) symbol.parent_symbol.node; - cname = "%s%s".printf (t.get_lower_case_cprefix ().up (), name); + if (parent_symbol == null) { + // global constant + cname = name; } else { - var ns = (Namespace) symbol.parent_symbol.node; - if (ns == null) { - // global constant - cname = name; - } else { - cname = "%s%s".printf (ns.get_lower_case_cprefix ().up (), name); - } + cname = "%s%s".printf (parent_symbol.get_lower_case_cprefix ().up (), name); } } return cname; diff --git a/vala/valaconstructor.vala b/vala/valaconstructor.vala index 28b72e96f..0aea35128 100644 --- a/vala/valaconstructor.vala +++ b/vala/valaconstructor.vala @@ -25,11 +25,16 @@ using GLib; /** * Represents a class or instance constructor. */ -public class Vala.Constructor : CodeNode { +public class Vala.Constructor : Symbol { /** * The body of this constructor. */ - public Statement body { get; set; } + public Block body { get; set; } + + /** + * Specifies the generated `this' parameter for instance methods. + */ + public FormalParameter this_parameter { get; set; } private bool _instance = true; diff --git a/vala/valacontinuestatement.vala b/vala/valacontinuestatement.vala index da0f0d502..509f4e6d9 100644 --- a/vala/valacontinuestatement.vala +++ b/vala/valacontinuestatement.vala @@ -1,6 +1,6 @@ /* valacontinuestatement.vala * - * Copyright (C) 2006 Jürg Billeter + * Copyright (C) 2006-2007 Jürg Billeter * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -25,7 +25,7 @@ using GLib; /** * Represents a continue statement in the source code. */ -public class Vala.ContinueStatement : Statement { +public class Vala.ContinueStatement : CodeNode, Statement { /** * Creates a new continue statement. * diff --git a/vala/valacreationmethod.vala b/vala/valacreationmethod.vala index 85e1075c3..dd86699a3 100644 --- a/vala/valacreationmethod.vala +++ b/vala/valacreationmethod.vala @@ -56,7 +56,7 @@ public class Vala.CreationMethod : Method { } public override string! get_default_cname () { - var parent = symbol.parent_symbol.node; + var parent = parent_symbol; assert (parent is DataType); if (name == null) { return "%snew".printf (((DataType) parent).get_lower_case_cprefix ()); diff --git a/vala/valadatatype.vala b/vala/valadatatype.vala index cd55bceea..85299666a 100644 --- a/vala/valadatatype.vala +++ b/vala/valadatatype.vala @@ -27,12 +27,7 @@ using GLib; * Represents a runtime data type. This data type may be defined in Vala source * code or imported from an external library with a Vala API file. */ -public abstract class Vala.DataType : CodeNode { - /** - * The symbol name of this data type. - */ - public string name { get; set; } - +public abstract class Vala.DataType : Symbol { /** * Specifies the accessibility of the class. Public accessibility * doesn't limit access. Default accessibility limits access to this @@ -41,11 +36,6 @@ public abstract class Vala.DataType : CodeNode { */ public MemberAccessibility access; - /** - * The namespace containing this data type. - */ - public weak Namespace @namespace; - private List<string> cheader_filenames; private Pointer pointer_type; @@ -178,29 +168,6 @@ public abstract class Vala.DataType : CodeNode { public virtual string get_upper_case_cname (string infix = null) { return null; } - - /** - * Returns the C name of this data type in lower case. Words are - * separated by underscores. The lower case C name of the namespace is - * prefix of the result. - * - * @param infix a string to be placed between namespace and data type - * name or null - * @return the lower case name to be used in C code - */ - public virtual string get_lower_case_cname (string infix = null) { - return null; - } - - /** - * Returns the string to be prefixed to members of this data type in - * lower case when used in C code. - * - * @return the lower case prefix to be used in C code - */ - public virtual string get_lower_case_cprefix () { - return null; - } /** * Returns the default value for the given type. Returning null means @@ -221,7 +188,7 @@ public abstract class Vala.DataType : CodeNode { public virtual List<weak string> get_cheader_filenames () { if (cheader_filenames == null) { /* default to header filenames of the namespace */ - foreach (string filename in @namespace.get_cheader_filenames ()) { + foreach (string filename in parent_symbol.get_cheader_filenames ()) { add_cheader_filename (filename); } @@ -252,11 +219,10 @@ public abstract class Vala.DataType : CodeNode { if (pointer_type == null) { pointer_type = new Pointer (this, source_reference); /* create a new Symbol */ - pointer_type.symbol = new Symbol (pointer_type); - this.symbol.parent_symbol.add (pointer_type.name, pointer_type.symbol); + parent_symbol.scope.add (pointer_type.name, pointer_type); /* link the namespace */ - pointer_type.@namespace = this.@namespace; + pointer_type.owner = parent_symbol.scope; } return pointer_type; @@ -273,19 +239,15 @@ public abstract class Vala.DataType : CodeNode { if (array_type == null) { var new_array_type = new Array (this, rank, source_reference); - /* create a new Symbol */ - new_array_type.symbol = new Symbol (new_array_type); - this.symbol.parent_symbol.add (new_array_type.name, new_array_type.symbol); + parent_symbol.scope.add (new_array_type.name, new_array_type); /* add internal length field */ - new_array_type.symbol.add (new_array_type.get_length_field ().name, new_array_type.get_length_field ().symbol); + new_array_type.scope.add (new_array_type.get_length_field ().name, new_array_type.get_length_field ()); /* add internal resize method */ - new_array_type.symbol.add (new_array_type.get_resize_method ().name, new_array_type.get_resize_method ().symbol); + new_array_type.scope.add (new_array_type.get_resize_method ().name, new_array_type.get_resize_method ()); /* link the array type to the same source as the container type */ new_array_type.source_reference = this.source_reference; - /* link the namespace */ - new_array_type.@namespace = this.@namespace; array_types.insert (rank.to_string (), new_array_type); diff --git a/vala/valadeclarationstatement.vala b/vala/valadeclarationstatement.vala index 44b5172d6..f045b9eb8 100644 --- a/vala/valadeclarationstatement.vala +++ b/vala/valadeclarationstatement.vala @@ -1,6 +1,6 @@ /* valadeclarationstatement.vala * - * Copyright (C) 2006 Jürg Billeter + * Copyright (C) 2006-2007 Jürg Billeter * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -25,7 +25,7 @@ using GLib; /** * Represents a local variable declaration statement in the source code. */ -public class Vala.DeclarationStatement : Statement { +public class Vala.DeclarationStatement : CodeNode, Statement { /** * The local variable declaration. */ diff --git a/vala/valadestructor.vala b/vala/valadestructor.vala index a169e1b79..85ea47a40 100644 --- a/vala/valadestructor.vala +++ b/vala/valadestructor.vala @@ -25,11 +25,11 @@ using GLib; /** * Represents a class or instance destructor. */ -public class Vala.Destructor : CodeNode { +public class Vala.Destructor : Symbol { /** * The body of this constructor. */ - public Statement body { get; set; } + public Block body { get; set; } private bool _instance = true; @@ -37,22 +37,17 @@ public class Vala.Destructor : CodeNode { * Specifies whether this is an instance or a class destructor. */ public bool instance { - get { - return _instance; - } - set { - _instance = value; - } + get { return _instance; } + set { _instance = value; } } /** * Creates a new destructor. * - * @param source reference to source code - * @return newly created destructor + * @param source_reference reference to source code + * @return newly created destructor */ - public Destructor (SourceReference source) { - source_reference = source; + public Destructor (construct SourceReference source_reference = null) { } public override void accept (CodeVisitor! visitor) { diff --git a/vala/valadostatement.vala b/vala/valadostatement.vala index 92ea9e99b..f54a9167e 100644 --- a/vala/valadostatement.vala +++ b/vala/valadostatement.vala @@ -1,6 +1,6 @@ /* valadostatement.vala * - * Copyright (C) 2006 Jürg Billeter + * Copyright (C) 2006-2007 Jürg Billeter * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -25,11 +25,11 @@ using GLib; /** * Represents a do iteration statement in the source code. */ -public class Vala.DoStatement : Statement { +public class Vala.DoStatement : CodeNode, Statement { /** * Specifies the loop body. */ - public Statement body { get; set; } + public Block body { get; set; } /** * Specifies the loop condition. @@ -54,10 +54,7 @@ public class Vala.DoStatement : Statement { * @param source reference to source code * @return newly created do statement */ - public DoStatement (Statement! _body, Expression! cond, SourceReference source) { - body = _body; - condition = cond; - source_reference = source; + public DoStatement (construct Block! body, construct Expression! condition, construct SourceReference source_reference = null) { } public override void accept (CodeVisitor! visitor) { diff --git a/vala/valaemptystatement.vala b/vala/valaemptystatement.vala index 9dd75fe1b..6ca047db8 100644 --- a/vala/valaemptystatement.vala +++ b/vala/valaemptystatement.vala @@ -1,6 +1,6 @@ /* valaemptystatement.vala * - * Copyright (C) 2006 Jürg Billeter + * Copyright (C) 2006-2007 Jürg Billeter * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -25,7 +25,7 @@ using GLib; /** * An empty statement. */ -public class Vala.EmptyStatement : Statement { +public class Vala.EmptyStatement : CodeNode, Statement { /** * Creates a new empty statement. * diff --git a/vala/valaenum.vala b/vala/valaenum.vala index 2f9e4f01b..fd7c520f2 100644 --- a/vala/valaenum.vala +++ b/vala/valaenum.vala @@ -55,6 +55,7 @@ public class Vala.Enum : DataType { */ public void add_value (EnumValue! value) { values.append (value); + scope.add (value.name, value); } /** @@ -63,7 +64,20 @@ public class Vala.Enum : DataType { * @param m a method */ public void add_method (Method! m) { + if (m is CreationMethod) { + Report.error (m.source_reference, "construction methods may only be declared within classes and structs"); + + m.error = true; + return; + } + if (m.instance) { + m.this_parameter = new FormalParameter ("this", new TypeReference ()); + m.this_parameter.type_reference.data_type = this; + m.scope.add (m.this_parameter.name, m.this_parameter); + } + methods.append (m); + scope.add (m.name, m); } /** @@ -91,12 +105,12 @@ public class Vala.Enum : DataType { public override string get_cname (bool const_type = false) { if (cname == null) { - cname = "%s%s".printf (@namespace.get_cprefix (), name); + cname = "%s%s".printf (parent_symbol.get_cprefix (), name); } return cname; } - public override string get_lower_case_cprefix () { + public override string! get_lower_case_cprefix () { if (lower_case_cprefix == null) { lower_case_cprefix = "%s_".printf (get_lower_case_cname (null)); } @@ -105,7 +119,7 @@ public class Vala.Enum : DataType { private string get_lower_case_csuffix () { if (lower_case_csuffix == null) { - lower_case_csuffix = Namespace.camel_case_to_lower_case (name); + lower_case_csuffix = camel_case_to_lower_case (name); } return lower_case_csuffix; } @@ -114,11 +128,11 @@ public class Vala.Enum : DataType { if (infix == null) { infix = ""; } - return "%s%s%s".printf (@namespace.get_lower_case_cprefix (), infix, get_lower_case_csuffix ()); + return "%s%s%s".printf (parent_symbol.get_lower_case_cprefix (), infix, get_lower_case_csuffix ()); } public override string get_upper_case_cname (string infix) { - return "%s%s".printf (@namespace.get_lower_case_cprefix (), Namespace.camel_case_to_lower_case (name)).up (); + return "%s%s".printf (parent_symbol.get_lower_case_cprefix (), camel_case_to_lower_case (name)).up (); } public override bool is_reference_type () { diff --git a/vala/valaenumvalue.vala b/vala/valaenumvalue.vala index 740983ef2..a95a29c2d 100644 --- a/vala/valaenumvalue.vala +++ b/vala/valaenumvalue.vala @@ -25,12 +25,7 @@ using GLib; /** * Represents an enum member in the source code. */ -public class Vala.EnumValue : CodeNode { - /** - * The symbol name of this enum value. - */ - public string! name { get; set construct; } - +public class Vala.EnumValue : Symbol { /** * Specifies the numerical representation of this enum value. */ @@ -44,8 +39,7 @@ public class Vala.EnumValue : CodeNode { * @param name enum value name * @return newly created enum value */ - public EnumValue (string! _name) { - name = _name; + public EnumValue (construct string! name) { } /** @@ -55,9 +49,7 @@ public class Vala.EnumValue : CodeNode { * @param value numerical representation * @return newly created enum value */ - public EnumValue.with_value (string! _name, Expression _value) { - name = _name; - value = _value; + public EnumValue.with_value (construct string! name, construct Expression value) { } public override void accept (CodeVisitor! visitor) { @@ -71,7 +63,7 @@ public class Vala.EnumValue : CodeNode { */ public string! get_cname () { if (cname == null) { - var en = (Enum) symbol.parent_symbol.node; + var en = (Enum) parent_symbol; cname = "%s%s".printf (en.get_cprefix (), name); } return cname; diff --git a/vala/valaexpressionstatement.vala b/vala/valaexpressionstatement.vala index 472ec195f..58925b6d9 100644 --- a/vala/valaexpressionstatement.vala +++ b/vala/valaexpressionstatement.vala @@ -1,6 +1,6 @@ /* valaexpressionstatement.vala * - * Copyright (C) 2006 Jürg Billeter + * Copyright (C) 2006-2007 Jürg Billeter * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -26,7 +26,7 @@ using GLib; * A code statement that evaluates a given expression. The value computed by the * expression, if any, is discarded. */ -public class Vala.ExpressionStatement : Statement { +public class Vala.ExpressionStatement : CodeNode, Statement { /** * Specifies the expression to evaluate. */ @@ -49,9 +49,7 @@ public class Vala.ExpressionStatement : Statement { * @param source reference to source code * @return newly created expression statement */ - public ExpressionStatement (Expression! expr, SourceReference source = null) { - expression = expr; - source_reference = source; + public ExpressionStatement (construct Expression! expression, construct SourceReference source_reference = null) { } public override void accept (CodeVisitor! visitor) { @@ -66,20 +64,20 @@ public class Vala.ExpressionStatement : Statement { } } - public override int get_number_of_set_construction_parameters () { + /** + * Returns whether this statement sets a property. + * + * @return true if this statement sets a property, false otherwise + */ + public bool sets_property () { if (expression is Assignment) { var assign = (Assignment) expression; if (assign.left is MemberAccess) { var ma = (MemberAccess) assign.left; - if (ma.symbol_reference != null) { - if (ma.symbol_reference.node is Property) { - var prop = (Property) ma.symbol_reference.node; - return 1; - } - } + return (ma.symbol_reference is Property); } } - return -1; + return false; } } diff --git a/vala/valafield.vala b/vala/valafield.vala index 3ccd10c8a..576ea8c0e 100644 --- a/vala/valafield.vala +++ b/vala/valafield.vala @@ -27,11 +27,6 @@ using GLib; */ public class Vala.Field : Member, Invokable, Lockable { /** - * The symbol name of this field. - */ - public string! name { get; set construct; } - - /** * The data type of this field. */ public TypeReference! type_reference { get; set construct; } @@ -54,12 +49,8 @@ public class Vala.Field : Member, Invokable, Lockable { * the contained type. */ public bool instance { - get { - return _instance; - } - set { - _instance = value; - } + get { return _instance; } + set { _instance = value; } } /** @@ -82,11 +73,7 @@ public class Vala.Field : Member, Invokable, Lockable { * @param source reference to source code * @return newly created field */ - public Field (string! _name, TypeReference! type, Expression init, SourceReference source) { - name = _name; - type_reference = type; - initializer = init; - source_reference = source; + public Field (construct string! name, construct TypeReference! type_reference, construct Expression initializer, construct SourceReference source_reference = null) { } public override void accept (CodeVisitor! visitor) { @@ -110,9 +97,8 @@ public class Vala.Field : Member, Invokable, Lockable { */ public string! get_cname () { if (cname == null) { - if (!instance && symbol.parent_symbol.node is DataType) { - var t = (DataType) symbol.parent_symbol.node; - cname = "%s_%s".printf (t.get_lower_case_cname (null), name); + if (!instance) { + cname = "%s_%s".printf (parent_symbol.get_lower_case_cname (null), name); } else { cname = name; } diff --git a/vala/valaflags.vala b/vala/valaflags.vala deleted file mode 100644 index fb5f2b598..000000000 --- a/vala/valaflags.vala +++ /dev/null @@ -1,150 +0,0 @@ -/* valaflags.vala - * - * Copyright (C) 2006-2007 Jürg Billeter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Author: - * Jürg Billeter <j@bitron.ch> - */ - -using GLib; - -/** - * Represents a flags declaration in the source code. - */ -public class Vala.Flags : DataType { - private List<FlagsValue> values; - private string cname; - private string cprefix; - - /** - * Creates a new flags. - * - * @param name type name - * @param source reference to source code - * @return newly created flags - */ - public Flags (construct string! name, construct SourceReference source_reference = null) { - } - - /** - * Appends the specified flags value to the list of values. - * - * @param value a flags value - */ - public void add_value (FlagsValue! value) { - values.append (value); - } - - public override void accept (CodeVisitor! visitor) { - visitor.visit_flags (this); - } - - public override void accept_children (CodeVisitor! visitor) { - foreach (FlagsValue value in values) { - value.accept (visitor); - } - } - - public override string get_cname (bool const_type = false) { - if (cname == null) { - cname = "%s%s".printf (@namespace.get_cprefix (), name); - } - return cname; - } - - public override string get_upper_case_cname (string infix) { - return "%s%s".printf (@namespace.get_lower_case_cprefix (), Namespace.camel_case_to_lower_case (name)).up (); - } - - public override bool is_reference_type () { - return false; - } - - private void set_cname (string! cname) { - this.cname = cname; - } - - /** - * Returns the string to be prepended to the name of members of this - * enum when used in C code. - * - * @return the prefix to be used in C code - */ - public string! get_cprefix () { - if (cprefix == null) { - cprefix = "%s_".printf (get_upper_case_cname (null)); - } - return cprefix; - } - - /** - * Sets the string to be prepended to the name of members of this enum - * when used in C code. - * - * @param cprefix the prefix to be used in C code - */ - public void set_cprefix (string! cprefix) { - this.cprefix = cprefix; - } - - private void process_ccode_attribute (Attribute! a) { - if (a.has_argument ("cname")) { - set_cname (a.get_string ("cname")); - } - if (a.has_argument ("cprefix")) { - set_cprefix (a.get_string ("cprefix")); - } - if (a.has_argument ("cheader_filename")) { - var val = a.get_string ("cheader_filename"); - foreach (string filename in val.split (",")) { - add_cheader_filename (filename); - } - } - } - - /** - * Process all associated attributes. - */ - public void process_attributes () { - foreach (Attribute a in attributes) { - if (a.name == "CCode") { - process_ccode_attribute (a); - } - } - } - - public override string get_type_id () { - // FIXME: use GType-registered flags - return "G_TYPE_INT"; - } - - public override string get_marshaller_type_name () { - return "FLAGS"; - } - - public override string get_get_value_function () { - return "g_value_get_flags"; - } - - public override string get_set_value_function () { - return "g_value_set_flags"; - } - - public override string get_default_value () { - return "0"; - } -} diff --git a/vala/valaflagsvalue.vala b/vala/valaflagsvalue.vala deleted file mode 100644 index 232bc322d..000000000 --- a/vala/valaflagsvalue.vala +++ /dev/null @@ -1,80 +0,0 @@ -/* valaflagsvalue.vala - * - * Copyright (C) 2006 Jürg Billeter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Author: - * Jürg Billeter <j@bitron.ch> - */ - -using GLib; - -/** - * Represents a flags member in the source code. - */ -public class Vala.FlagsValue : CodeNode { - /** - * The symbol name of this flags value. - */ - public string! name { get; set construct; } - - /** - * Specifies the numerical representation of this flags value. - */ - public Expression value { get; set; } - - private string cname; - - /** - * Creates a new flags value. - * - * @param name flags value name - * @return newly created flags value - */ - public FlagsValue (string! _name) { - name = _name; - } - - /** - * Creates a new flags value with the specified numerical - * representation. - * - * @param name flags value name - * @param value numerical representation - * @return newly created flags value - */ - public FlagsValue.with_value (string! _name, Expression _value) { - name = _name; - value = _value; - } - - public override void accept (CodeVisitor! visitor) { - visitor.visit_flags_value (this); - } - - /** - * Returns the name of this flags value as it is used in C code. - * - * @return the name to be used in C code - */ - public string! get_cname () { - if (cname == null) { - var fl = (Flags) symbol.parent_symbol.node; - cname = "%s_%s".printf (fl.get_upper_case_cname (null), name); - } - return cname; - } -} diff --git a/vala/valaforeachstatement.vala b/vala/valaforeachstatement.vala index 7c0055b77..c97302430 100644 --- a/vala/valaforeachstatement.vala +++ b/vala/valaforeachstatement.vala @@ -26,7 +26,7 @@ using GLib; * Represents a foreach statement in the source code. Foreach statements iterate * over the elements of a collection. */ -public class Vala.ForeachStatement : Statement { +public class Vala.ForeachStatement : CodeNode, Statement { /** * Specifies the element type. */ @@ -53,7 +53,7 @@ public class Vala.ForeachStatement : Statement { /** * Specifies the loop body. */ - public Statement body { get; set; } + public Block body { get; set; } /** * Specifies the declarator for the generated element variable. @@ -71,12 +71,7 @@ public class Vala.ForeachStatement : Statement { * @param source reference to source code * @return newly created foreach statement */ - public ForeachStatement (TypeReference! type, string! id, Expression! col, Statement _body, SourceReference source) { - type_reference = type; - variable_name = id; - collection = col; - body = _body; - source_reference = source; + public ForeachStatement (construct TypeReference! type_reference, construct string! variable_name, construct Expression! collection, construct Block body, construct SourceReference source_reference) { } public override void accept (CodeVisitor! visitor) { diff --git a/vala/valaformalparameter.vala b/vala/valaformalparameter.vala index 1ee8d38af..363e26ac7 100644 --- a/vala/valaformalparameter.vala +++ b/vala/valaformalparameter.vala @@ -26,12 +26,7 @@ using GLib; /** * Represents a formal parameter in method and callback signatures. */ -public class Vala.FormalParameter : CodeNode, Invokable { - /** - * The parameter name. - */ - public string! name { get; set construct; } - +public class Vala.FormalParameter : Symbol, Invokable { /** * The parameter type. */ diff --git a/vala/valaforstatement.vala b/vala/valaforstatement.vala index 6017482be..37bbd62bb 100644 --- a/vala/valaforstatement.vala +++ b/vala/valaforstatement.vala @@ -25,7 +25,7 @@ using GLib; /** * Represents a for iteration statement in the source code. */ -public class Vala.ForStatement : Statement { +public class Vala.ForStatement : CodeNode, Statement { /** * Specifies the loop condition. */ @@ -42,7 +42,7 @@ public class Vala.ForStatement : Statement { /** * Specifies the loop body. */ - public Statement body { get; set; } + public Block body { get; set; } private List<Expression> initializer; private List<Expression> iterator; @@ -57,10 +57,7 @@ public class Vala.ForStatement : Statement { * @param source reference to source code * @return newly created for statement */ - public ForStatement (Expression cond, Statement _body, SourceReference source) { - condition = cond; - body = _body; - source_reference = source; + public ForStatement (construct Expression condition, construct Block body, construct SourceReference source_reference = null) { } /** diff --git a/vala/valaifstatement.vala b/vala/valaifstatement.vala index 2912db849..5af3ca5a6 100644 --- a/vala/valaifstatement.vala +++ b/vala/valaifstatement.vala @@ -1,6 +1,6 @@ /* valaifstatement.vala * - * Copyright (C) 2006 Jürg Billeter + * Copyright (C) 2006-2007 Jürg Billeter * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -25,7 +25,7 @@ using GLib; /** * Represents an if selection statement in the source code. */ -public class Vala.IfStatement : Statement { +public class Vala.IfStatement : CodeNode, Statement { /** * The boolean condition to evaluate. */ diff --git a/vala/valainterface.vala b/vala/valainterface.vala index 5534bbe74..4655f364a 100644 --- a/vala/valainterface.vala +++ b/vala/valainterface.vala @@ -52,9 +52,7 @@ public class Vala.Interface : DataType { * @param source reference to source code * @return newly created interface */ - public Interface (string! _name, SourceReference source = null) { - name = _name; - source_reference = source; + public Interface (construct string! name, construct SourceReference source_reference = null) { } /** @@ -65,6 +63,7 @@ public class Vala.Interface : DataType { public void add_type_parameter (TypeParameter! p) { type_parameters.append (p); p.type = this; + scope.add (p.name, p); } /** @@ -92,7 +91,20 @@ public class Vala.Interface : DataType { * @param m a method */ public void add_method (Method! m) { + if (m is CreationMethod) { + Report.error (m.source_reference, "construction methods may only be declared within classes and structs"); + + m.error = true; + return; + } + if (m.instance) { + m.this_parameter = new FormalParameter ("this", new TypeReference ()); + m.this_parameter.type_reference.data_type = this; + m.scope.add (m.this_parameter.name, m.this_parameter); + } + methods.append (m); + scope.add (m.name, m); } /** @@ -111,6 +123,7 @@ public class Vala.Interface : DataType { */ public void add_property (Property! prop) { properties.append (prop); + scope.add (prop.name, prop); } /** @@ -129,6 +142,7 @@ public class Vala.Interface : DataType { */ public void add_signal (Signal! sig) { signals.append (sig); + scope.add (sig.name, sig); } /** @@ -142,7 +156,7 @@ public class Vala.Interface : DataType { public override string get_cname (bool const_type = false) { if (cname == null) { - cname = "%s%s".printf (@namespace.get_cprefix (), name); + cname = "%s%s".printf (parent_symbol.get_cprefix (), name); } return cname; } @@ -155,7 +169,7 @@ public class Vala.Interface : DataType { */ public string! get_lower_case_csuffix () { if (lower_case_csuffix == null) { - lower_case_csuffix = Namespace.camel_case_to_lower_case (name); + lower_case_csuffix = camel_case_to_lower_case (name); } return lower_case_csuffix; } @@ -174,10 +188,10 @@ public class Vala.Interface : DataType { if (infix == null) { infix = ""; } - return "%s%s%s".printf (@namespace.get_lower_case_cprefix (), infix, get_lower_case_csuffix ()); + return "%s%s%s".printf (parent_symbol.get_lower_case_cprefix (), infix, get_lower_case_csuffix ()); } - public override string get_lower_case_cprefix () { + public override string! get_lower_case_cprefix () { return "%s_".printf (get_lower_case_cname (null)); } diff --git a/vala/valainterfacewriter.vala b/vala/valainterfacewriter.vala index 58d0af279..a011a42f1 100644 --- a/vala/valainterfacewriter.vala +++ b/vala/valainterfacewriter.vala @@ -55,7 +55,7 @@ public class Vala.InterfaceWriter : CodeVisitor { } public override void visit_namespace (Namespace! ns) { - if (ns.source_reference != null && ns.source_reference.file.pkg) { + if (ns.pkg) { return; } @@ -64,10 +64,8 @@ public class Vala.InterfaceWriter : CodeVisitor { return; } - current_cheader_filename = ns.get_cheader_filename (); - write_indent (); - write_string ("[CCode (cprefix = \"%s\", lower_case_cprefix = \"%s\", cheader_filename = \"%s\")]".printf (ns.get_cprefix (), ns.get_lower_case_cprefix (), current_cheader_filename)); + write_string ("[CCode (cprefix = \"%s\", lower_case_cprefix = \"%s\")]".printf (ns.get_cprefix (), ns.get_lower_case_cprefix ())); write_newline (); write_indent (); @@ -124,7 +122,7 @@ public class Vala.InterfaceWriter : CodeVisitor { } else { first = false; } - write_string (base_type.data_type.symbol.get_full_name ()); + write_string (base_type.data_type.get_full_name ()); } } write_begin_block (); @@ -150,6 +148,21 @@ public class Vala.InterfaceWriter : CodeVisitor { } write_indent (); + + var first = true; + string cheaders; + foreach (string cheader in st.get_cheader_filenames ()) { + if (first) { + cheaders = cheader; + first = false; + } else { + cheaders = "%s, %s".printf (cheaders, cheader); + } + } + write_string ("[CCode (cheader_filename = \"%s\")]".printf (cheaders)); + write_newline (); + + write_indent (); write_string ("public struct "); write_identifier (st.name); write_begin_block (); @@ -207,7 +220,18 @@ public class Vala.InterfaceWriter : CodeVisitor { } write_indent (); - write_string ("[CCode (cprefix = \"%s\")]".printf (en.get_cprefix ())); + + var first = true; + string cheaders; + foreach (string cheader in en.get_cheader_filenames ()) { + if (first) { + cheaders = cheader; + first = false; + } else { + cheaders = "%s, %s".printf (cheaders, cheader); + } + } + write_string ("[CCode (cprefix = \"%s\", cheader_filename = \"%s\")]".printf (en.get_cprefix (), cheaders)); write_indent (); write_string ("public enum "); @@ -227,36 +251,6 @@ public class Vala.InterfaceWriter : CodeVisitor { write_newline (); } - public override void visit_flags (Flags! fl) { - if (fl.source_reference != null && fl.source_reference.file.pkg) { - return; - } - - if (fl.access == MemberAccessibility.PRIVATE) { - return; - } - - write_indent (); - write_string ("[CCode (cprefix = \"%s\")]".printf (fl.get_cprefix ())); - - write_indent (); - write_string ("public flags "); - write_identifier (fl.name); - write_begin_block (); - - fl.accept_children (this); - - write_end_block (); - write_newline (); - } - - public override void visit_flags_value (FlagsValue! fv) { - write_indent (); - write_identifier (fv.name); - write_string (","); - write_newline (); - } - public override void visit_constant (Constant! c) { if (c.source_reference != null && c.source_reference.file.pkg) { return; @@ -264,7 +258,7 @@ public class Vala.InterfaceWriter : CodeVisitor { write_indent (); write_string ("public const "); - write_string (c.type_reference.data_type.symbol.get_full_name ()); + write_string (c.type_reference.data_type.get_full_name ()); write_string (" "); write_identifier (c.name); @@ -288,7 +282,7 @@ public class Vala.InterfaceWriter : CodeVisitor { !f.type_reference.takes_ownership) { write_string ("weak "); } - write_string (f.type_reference.data_type.symbol.get_full_name ()); + write_string (f.type_reference.data_type.get_full_name ()); var type_args = f.type_reference.get_type_arguments (); if (!(f.type_reference.data_type is Array) && type_args != null) { @@ -297,7 +291,7 @@ public class Vala.InterfaceWriter : CodeVisitor { if (!type_arg.takes_ownership) { write_string ("weak "); } - write_string (type_arg.data_type.symbol.get_full_name ()); + write_string (type_arg.data_type.get_full_name ()); } write_string (">"); } @@ -329,7 +323,7 @@ public class Vala.InterfaceWriter : CodeVisitor { } else if (param.type_reference.is_out) { write_string ("out "); } - write_string (param.type_reference.data_type.symbol.get_full_name ()); + write_string (param.type_reference.data_type.get_full_name ()); var type_args = param.type_reference.get_type_arguments (); if (!(param.type_reference.data_type is Array) && type_args != null) { @@ -338,7 +332,7 @@ public class Vala.InterfaceWriter : CodeVisitor { if (!type_arg.takes_ownership) { write_string ("weak "); } - write_string (type_arg.data_type.symbol.get_full_name ()); + write_string (type_arg.data_type.get_full_name ()); } write_string (">"); } @@ -382,7 +376,7 @@ public class Vala.InterfaceWriter : CodeVisitor { if (cb.return_type.transfers_ownership) { write_string ("ref "); } - write_string (cb.return_type.data_type.symbol.get_full_name ()); + write_string (cb.return_type.data_type.get_full_name ()); } write_string (" "); @@ -398,6 +392,10 @@ public class Vala.InterfaceWriter : CodeVisitor { } public override void visit_method (Method! m) { + if (m.source_reference != null && m.source_reference.file.pkg) { + return; + } + if (m.access == MemberAccessibility.PRIVATE || m.overrides) { return; } @@ -433,7 +431,7 @@ public class Vala.InterfaceWriter : CodeVisitor { if (m is CreationMethod) { write_string (" "); - var datatype = (DataType) m.symbol.parent_symbol.node; + var datatype = (DataType) m.parent_symbol; write_identifier (datatype.name); if (m.name != null) { @@ -459,7 +457,7 @@ public class Vala.InterfaceWriter : CodeVisitor { } else if ((m.return_type.data_type != null && m.return_type.data_type.is_reference_type ()) || m.return_type.type_parameter != null) { write_string ("weak "); } - write_string (m.return_type.data_type.symbol.get_full_name ()); + write_string (m.return_type.data_type.get_full_name ()); if (m.return_type.non_null) { write_string ("!"); } @@ -493,7 +491,7 @@ public class Vala.InterfaceWriter : CodeVisitor { if (!prop.type_reference.takes_ownership) { write_string ("weak "); } - write_string (prop.type_reference.data_type.symbol.get_full_name ()); + write_string (prop.type_reference.data_type.get_full_name ()); var type_args = prop.type_reference.get_type_arguments (); if (!(prop.type_reference.data_type is Array) && type_args != null) { @@ -502,7 +500,7 @@ public class Vala.InterfaceWriter : CodeVisitor { if (!type_arg.takes_ownership) { write_string ("weak "); } - write_string (type_arg.data_type.symbol.get_full_name ()); + write_string (type_arg.data_type.get_full_name ()); } write_string (">"); } @@ -546,7 +544,7 @@ public class Vala.InterfaceWriter : CodeVisitor { if (sig.return_type.transfers_ownership) { write_string ("ref "); } - write_string (sig.return_type.data_type.symbol.get_full_name ()); + write_string (sig.return_type.data_type.get_full_name ()); if (sig.return_type.non_null) { write_string ("!"); } @@ -579,8 +577,8 @@ public class Vala.InterfaceWriter : CodeVisitor { } private void write_identifier (string! s) { - if (s == "base" || s == "callback" || s == "class" || - s == "construct" || s == "flags" || s == "foreach" || + if (s == "base" || s == "class" || + s == "construct" || s == "delegate" || s == "foreach" || s == "in" || s == "interface" || s == "lock" || s == "namespace" || s == "out" || s == "ref") { stream.putc ('@'); diff --git a/vala/valalockstatement.vala b/vala/valalockstatement.vala index 775725e08..9243c9a6b 100644 --- a/vala/valalockstatement.vala +++ b/vala/valalockstatement.vala @@ -1,6 +1,6 @@ /* valalockstatement.vala * - * Copyright (C) 2006 Raffaele Sandrini + * Copyright (C) 2006-2007 Raffaele Sandrini, Jürg Billeter * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -25,7 +25,7 @@ using GLib; /** * Represents a lock statement e.g. "lock (a) { f(a) }". */ -public class Vala.LockStatement : Statement { +public class Vala.LockStatement : CodeNode, Statement { /** * Expression representing the resource to be locked. */ @@ -34,12 +34,9 @@ public class Vala.LockStatement : Statement { /** * The statement during its execution the resource is locked. */ - public Statement! body { get; set construct; } + public Block! body { get; set construct; } - public LockStatement (Expression _resource, Statement _body, SourceReference source) { - resource = _resource; - body = _body; - source_reference = source; + public LockStatement (construct Expression resource, construct Block body, construct SourceReference source_reference = null) { } public override void accept (CodeVisitor! visitor) { diff --git a/vala/valamember.vala b/vala/valamember.vala index 651a98b1e..de4014df9 100644 --- a/vala/valamember.vala +++ b/vala/valamember.vala @@ -1,6 +1,6 @@ /* valamember.vala * - * Copyright (C) 2006 Raffaele Sandrini + * Copyright (C) 2006-2007 Raffaele Sandrini, Jürg Billeter * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -23,7 +23,7 @@ /** * Represents a general class member. */ -public class Vala.Member : CodeNode { +public class Vala.Member : Symbol { public override void accept (CodeVisitor! visitor) { visitor.visit_member (this); } diff --git a/vala/valamemorymanager.vala b/vala/valamemorymanager.vala index 28e4b5e65..b580ce2b9 100644 --- a/vala/valamemorymanager.vala +++ b/vala/valamemorymanager.vala @@ -88,7 +88,7 @@ public class Vala.MemoryManager : CodeVisitor { } public override void visit_method (Method! m) { - current_symbol = m.symbol; + current_symbol = m; m.accept_children (this); } @@ -98,7 +98,7 @@ public class Vala.MemoryManager : CodeVisitor { } public override void visit_property (Property! prop) { - current_symbol = prop.symbol; + current_symbol = prop; prop.accept_children (this); } @@ -135,8 +135,8 @@ public class Vala.MemoryManager : CodeVisitor { public override void visit_end_return_statement (ReturnStatement! stmt) { if (stmt.return_expression != null) { - if (current_symbol.node is Method) { - var m = (Method) current_symbol.node; + if (current_symbol is Method) { + var m = (Method) current_symbol; if (m.return_type.transfers_ownership) { visit_possibly_missing_copy_expression (stmt.return_expression); @@ -172,23 +172,23 @@ public class Vala.MemoryManager : CodeVisitor { List<weak FormalParameter> params; var msym = expr.call.symbol_reference; - if (msym.node is VariableDeclarator) { - var decl = (VariableDeclarator) msym.node; + if (msym is VariableDeclarator) { + var decl = (VariableDeclarator) msym; var cb = (Callback) decl.type_reference.data_type; params = cb.get_parameters (); - } else if (msym.node is FormalParameter) { - var param = (FormalParameter) msym.node; + } else if (msym is FormalParameter) { + var param = (FormalParameter) msym; var cb = (Callback) param.type_reference.data_type; params = cb.get_parameters (); - } else if (msym.node is Field) { - var f = (Field) msym.node; + } else if (msym is Field) { + var f = (Field) msym; var cb = (Callback) f.type_reference.data_type; params = cb.get_parameters (); - } else if (msym.node is Method) { - var m = (Method) msym.node; + } else if (msym is Method) { + var m = (Method) msym; params = m.get_parameters (); - } else if (msym.node is Signal) { - var sig = (Signal) msym.node; + } else if (msym is Signal) { + var sig = (Signal) msym; params = sig.get_parameters (); } weak List<weak FormalParameter> params_it = params; @@ -206,7 +206,7 @@ public class Vala.MemoryManager : CodeVisitor { var ma = (MemberAccess) expr.call; TypeReference instance_type = ma.inner.static_type; // trace type arguments back to the datatype where the method has been declared - while (instance_type.data_type != msym.parent_symbol.node) { + while (instance_type.data_type != msym.parent_symbol) { List<weak TypeReference> base_types = null; if (instance_type.data_type is Class) { var cl = (Class) instance_type.data_type; @@ -220,7 +220,7 @@ public class Vala.MemoryManager : CodeVisitor { return; } foreach (TypeReference base_type in base_types) { - if (SemanticAnalyzer.symbol_lookup_inherited (base_type.data_type.symbol, msym.name) != null) { + if (SemanticAnalyzer.symbol_lookup_inherited (base_type.data_type, msym.name) != null) { // construct a new type reference for the base type with correctly linked type arguments var instance_base_type = new TypeReference (); instance_base_type.data_type = base_type.data_type; @@ -241,7 +241,7 @@ public class Vala.MemoryManager : CodeVisitor { } } } - if (instance_type.data_type != msym.parent_symbol.node) { + if (instance_type.data_type != msym.parent_symbol) { Report.error (expr.source_reference, "internal error: generic type parameter tracing not supported yet"); expr.error = true; return; @@ -284,7 +284,7 @@ public class Vala.MemoryManager : CodeVisitor { } public override void visit_end_assignment (Assignment! a) { - if (a.left is PointerIndirection || (a.left.symbol_reference != null && a.left.symbol_reference.node is Signal)) { + if (a.left is PointerIndirection || a.left.symbol_reference is Signal) { } else { if (a.left.static_type.takes_ownership) { visit_possibly_missing_copy_expression (a.right); diff --git a/vala/valamethod.vala b/vala/valamethod.vala index c6c85abcd..16ad70637 100644 --- a/vala/valamethod.vala +++ b/vala/valamethod.vala @@ -28,11 +28,6 @@ using GLib; */ public class Vala.Method : Member, Invokable { /** - * The symbol name of this method. - */ - public string name { get; set; } - - /** * The return type of this method. */ public TypeReference return_type { get; set; } @@ -150,10 +145,7 @@ public class Vala.Method : Member, Invokable { * @param source reference to source code * @return newly created method */ - public Method (string _name, TypeReference _return_type, SourceReference source = null) { - name = _name; - return_type = _return_type; - source_reference = source; + public Method (construct string name, construct TypeReference return_type, construct SourceReference source_reference = null) { } /** @@ -167,6 +159,9 @@ public class Vala.Method : Member, Invokable { } parameters.append (param); + if (!param.ellipsis) { + scope.add (param.name, param); + } } public List<weak FormalParameter> get_parameters () { @@ -222,17 +217,10 @@ public class Vala.Method : Member, Invokable { * @return the name to be used in C code by default */ public virtual string! get_default_cname () { - var parent = symbol.parent_symbol.node; - if (parent is DataType) { - if (name.has_prefix ("_")) { - return "_%s%s".printf (((DataType) parent).get_lower_case_cprefix (), name.offset (1)); - } else { - return "%s%s".printf (((DataType) parent).get_lower_case_cprefix (), name); - } - } else if (parent is Namespace) { - return "%s%s".printf (((Namespace) parent).get_lower_case_cprefix (), name); + if (name.has_prefix ("_")) { + return "_%s%s".printf (parent_symbol.get_lower_case_cprefix (), name.offset (1)); } else { - return name; + return "%s%s".printf (parent_symbol.get_lower_case_cprefix (), name); } } @@ -244,8 +232,7 @@ public class Vala.Method : Member, Invokable { */ public string! get_real_cname () { if (base_method != null || base_interface_method != null) { - var parent = (Class) symbol.parent_symbol.node; - return "%s_real_%s".printf (parent.get_lower_case_cname (null), name); + return "%s_real_%s".printf (parent_symbol.get_lower_case_cname (null), name); } else { return get_cname (); } diff --git a/vala/valanamespace.vala b/vala/valanamespace.vala index b76d52d66..25c235047 100644 --- a/vala/valanamespace.vala +++ b/vala/valanamespace.vala @@ -25,17 +25,16 @@ using GLib; /** * Represents a namespace declaration in the source code. */ -public class Vala.Namespace : CodeNode { +public class Vala.Namespace : Symbol { /** - * The name of this namespace. + * Specifies whether this namespace is only used in a VAPI package file. */ - public string name { get; set; } + public bool pkg { get; set; } private List<Class> classes; private List<Interface> interfaces; private List<Struct> structs; private List<Enum> enums; - private List<Flags> flags_; private List<Callback> callbacks; private List<Constant> constants; private List<Field> fields; @@ -45,7 +44,9 @@ public class Vala.Namespace : CodeNode { private string lower_case_cprefix; private List<string> cheader_filenames; - + + private List<Namespace> namespaces; + /** * Creates a new namespace. * @@ -53,29 +54,36 @@ public class Vala.Namespace : CodeNode { * @param source reference to source code * @return newly created namespace */ - public Namespace (string _name, SourceReference source = null) { - name = _name; - source_reference = source; + public Namespace (construct string name, construct SourceReference source_reference = null) { } /** - * Adds the specified class to this namespace. + * Adds the specified namespace to this source file. * - * @param cl a class + * @param ns a namespace */ - public void add_class (Class! cl) { - classes.append (cl); - cl.@namespace = this; + public void add_namespace (Namespace! ns) { + namespaces.append (ns); + scope.add (ns.name, ns); } - + /** - * Removes the specified class from this namespace. + * Returns a copy of the list of namespaces. + * + * @return namespace list + */ + public List<weak Namespace> get_namespaces () { + return namespaces.copy (); + } + + /** + * Adds the specified class to this namespace. * * @param cl a class */ - public void remove_class (Class! cl) { - cl.@namespace = null; - classes.remove (cl); + public void add_class (Class! cl) { + classes.append (cl); + scope.add (cl.name, cl); } /** @@ -85,7 +93,7 @@ public class Vala.Namespace : CodeNode { */ public void add_interface (Interface! iface) { interfaces.append (iface); - iface.@namespace = this; + scope.add (iface.name, iface); } /** @@ -95,7 +103,7 @@ public class Vala.Namespace : CodeNode { */ public void add_struct (Struct! st) { structs.append (st); - st.@namespace = this; + scope.add (st.name, st); } /** @@ -105,27 +113,17 @@ public class Vala.Namespace : CodeNode { */ public void add_enum (Enum! en) { enums.append (en); - en.@namespace = this; + scope.add (en.name, en); } /** - * Adds the specified flags to this namespace. - * - * @param fl a flags - */ - public void add_flags (Flags! fl) { - flags_.append (fl); - fl.@namespace = this; - } - - /** * Adds the specified callback to this namespace. * * @param cb a callback */ public void add_callback (Callback! cb) { callbacks.append (cb); - cb.@namespace = this; + scope.add (cb.name, cb); } /** @@ -162,6 +160,7 @@ public class Vala.Namespace : CodeNode { */ public void add_constant (Constant! constant) { constants.append (constant); + scope.add (constant.name, constant); } /** @@ -171,6 +170,7 @@ public class Vala.Namespace : CodeNode { */ public void add_field (Field! f) { fields.append (f); + scope.add (f.name, f); } /** @@ -179,7 +179,21 @@ public class Vala.Namespace : CodeNode { * @param m a method */ public void add_method (Method! m) { + if (m is CreationMethod) { + Report.error (m.source_reference, "construction methods may only be declared within classes and structs"); + + m.error = true; + return; + } + if (m.instance) { + Report.error (m.source_reference, "instance methods not allowed outside of data types"); + + m.error = true; + return; + } + methods.append (m); + scope.add (m.name, m); } public override void accept (CodeVisitor! visitor) { @@ -187,13 +201,13 @@ public class Vala.Namespace : CodeNode { } public override void accept_children (CodeVisitor! visitor) { - /* process enums and flags first to avoid order problems in C code */ - foreach (Enum en in enums) { - en.accept (visitor); + foreach (Namespace ns in namespaces) { + ns.accept (visitor); } - foreach (Flags fl in flags_) { - fl.accept (visitor); + /* process enums first to avoid order problems in C code */ + foreach (Enum en in enums) { + en.accept (visitor); } foreach (Class cl in classes) { @@ -224,55 +238,8 @@ public class Vala.Namespace : CodeNode { m.accept (visitor); } } - - /** - * Converts a string from CamelCase to lower_case. - * - * @param camel_case a string in camel case - * @return the specified string converted to lower case - */ - public static string! camel_case_to_lower_case (string! camel_case) { - String result = new String (""); - - weak string i = camel_case; - - bool first = true; - while (i.len () > 0) { - unichar c = i.get_char (); - if (c.isupper () && !first) { - /* current character is upper case and - * we're not at the beginning */ - weak string t = i.prev_char (); - bool prev_upper = t.get_char ().isupper (); - t = i.next_char (); - bool next_upper = t.get_char ().isupper (); - if (!prev_upper || (i.len () >= 2 && !next_upper)) { - /* previous character wasn't upper case or - * next character isn't upper case*/ - int len = result.str.len (); - if (len != 1 && result.str.offset (len - 2).get_char () != '_') { - /* we're not creating 1 character words */ - result.append_c ('_'); - } - } - } - - result.append_unichar (c.tolower ()); - - first = false; - i = i.next_char (); - } - - return result.str; - } - /** - * Returns the camel case string to be prepended to the name of members - * of this namespace when used in C code. - * - * @return the camel case prefix to be used in C code - */ - public string! get_cprefix () { + public override string! get_cprefix () { if (cprefix == null) { if (name == null) { cprefix = ""; @@ -299,7 +266,7 @@ public class Vala.Namespace : CodeNode { * * @return the lower case prefix to be used in C code */ - public string! get_lower_case_cprefix () { + public override string! get_lower_case_cprefix () { if (lower_case_cprefix == null) { if (name == null) { lower_case_cprefix = ""; @@ -320,19 +287,7 @@ public class Vala.Namespace : CodeNode { this.lower_case_cprefix = cprefix; } - /** - * Returns a list of C header filenames users of this namespace must - * include. - * - * @return list of C header filenames for this namespace - */ - public List<weak string> get_cheader_filenames () { - if (cheader_filenames == null) { - if (source_reference != null && !source_reference.file.pkg) { - // don't add default include directives for VAPI files - cheader_filenames.append (source_reference.file.get_cinclude_filename ()); - } - } + public override List<weak string> get_cheader_filenames () { return cheader_filenames.copy (); } diff --git a/vala/valaproperty.vala b/vala/valaproperty.vala index 0de75331f..3009ad90d 100644 --- a/vala/valaproperty.vala +++ b/vala/valaproperty.vala @@ -27,11 +27,6 @@ using GLib; */ public class Vala.Property : Member, Lockable { /** - * The property name. - */ - public string! name { get; set construct; } - - /** * The property type. */ public TypeReference! type_reference { get; set construct; } @@ -147,7 +142,7 @@ public class Vala.Property : Member, Lockable { * @return the upper case name to be used in C code */ public string! get_upper_case_cname () { - return "%s_%s".printf (((DataType) symbol.parent_symbol.node).get_lower_case_cname (null), Namespace.camel_case_to_lower_case (name)).up (); + return "%s_%s".printf (parent_symbol.get_lower_case_cname (null), camel_case_to_lower_case (name)).up (); } /** diff --git a/vala/valapropertyaccessor.vala b/vala/valapropertyaccessor.vala index 1dd0ab8c9..7bd3a15d9 100644 --- a/vala/valapropertyaccessor.vala +++ b/vala/valapropertyaccessor.vala @@ -27,6 +27,11 @@ using GLib; */ public class Vala.PropertyAccessor : CodeNode { /** + * The corresponding property. + */ + public weak Property prop { get; set; } + + /** * Specifies whether this accessor may be used to get the property. */ public bool readable { get; set; } @@ -45,7 +50,7 @@ public class Vala.PropertyAccessor : CodeNode { /** * The accessor body. */ - public Statement body { get; set; } + public Block body { get; set; } /** * Represents the generated value parameter in a set accessor. @@ -62,12 +67,7 @@ public class Vala.PropertyAccessor : CodeNode { * @param source reference to source code * @return newly created property accessor */ - public PropertyAccessor (bool _readable, bool _writable, bool _construction, Statement _body, SourceReference source) { - readable = _readable; - writable = _writable; - construction = _construction; - body = _body; - source_reference = source; + public PropertyAccessor (construct bool readable, construct bool writable, construct bool construction, construct Block body, construct SourceReference source_reference) { } public override void accept (CodeVisitor! visitor) { diff --git a/vala/valareturnstatement.vala b/vala/valareturnstatement.vala index 52e7b0841..3ec1ab720 100644 --- a/vala/valareturnstatement.vala +++ b/vala/valareturnstatement.vala @@ -1,6 +1,6 @@ /* valareturnstatement.vala * - * Copyright (C) 2006 Jürg Billeter + * Copyright (C) 2006-2007 Jürg Billeter * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -25,7 +25,7 @@ using GLib; /** * Represents a return statement in the source code. */ -public class Vala.ReturnStatement : Statement { +public class Vala.ReturnStatement : CodeNode, Statement { /** * The optional expression to return. */ diff --git a/vala/valascope.vala b/vala/valascope.vala new file mode 100644 index 000000000..745c8e58a --- /dev/null +++ b/vala/valascope.vala @@ -0,0 +1,89 @@ +/* valascope.vala + * + * Copyright (C) 2006-2007 Jürg Billeter + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Author: + * Jürg Billeter <j@bitron.ch> + */ + +using GLib; + +/** + * Represents a part of the symbol tree. + */ +public class Vala.Scope { + /** + * The symbol that owns this scope. + */ + public weak Symbol owner { get; set; } + + /** + * The parent of this scope. + */ + public weak Scope parent_scope { get; set; } + + private HashTable<string,Symbol> symbol_table; + + /** + * Creates a new scope. + * + * @return newly created scope + */ + public Scope (construct Symbol owner = null) { + } + + /** + * Adds the specified symbol with the specified name to the symbol table + * of this scope. + * + * @param name name for the specified symbol + * @param sym a symbol + */ + public void add (string name, Symbol! sym) { + if (name != null) { + if (symbol_table == null) { + symbol_table = new HashTable.full (str_hash, str_equal, g_free, g_object_unref); + } else if (lookup (name) != null) { + owner.error = true; + Report.error (owner.source_reference, "`%s' already contains a definition for `%s'".printf (owner.get_full_name (), name)); + return; + } + + symbol_table.insert (name, sym); + } + sym.owner = this; + } + + /** + * Returns the symbol stored in the symbol table with the specified + * name. + * + * @param name name of the symbol to be returned + * @return found symbol or null + */ + public Symbol lookup (string! name) { + if (symbol_table == null) { + return null; + } + Symbol sym = symbol_table.lookup (name); + if (sym != null && !sym.active) { + sym = null; + } + return sym; + } +} + diff --git a/vala/valasemanticanalyzer.vala b/vala/valasemanticanalyzer.vala index 2309f35c2..f11f3bba8 100644 --- a/vala/valasemanticanalyzer.vala +++ b/vala/valasemanticanalyzer.vala @@ -69,37 +69,37 @@ public class Vala.SemanticAnalyzer : CodeVisitor { root_symbol = context.root; bool_type = new TypeReference (); - bool_type.data_type = (DataType) root_symbol.lookup ("bool").node; + bool_type.data_type = (DataType) root_symbol.scope.lookup ("bool"); string_type = new TypeReference (); - string_type.data_type = (DataType) root_symbol.lookup ("string").node; + string_type.data_type = (DataType) root_symbol.scope.lookup ("string"); - pointer_type = (DataType) root_symbol.lookup ("pointer").node; + pointer_type = (DataType) root_symbol.scope.lookup ("pointer"); int_type = new TypeReference (); - int_type.data_type = (DataType) root_symbol.lookup ("int").node; + int_type.data_type = (DataType) root_symbol.scope.lookup ("int"); uint_type = new TypeReference (); - uint_type.data_type = (DataType) root_symbol.lookup ("uint").node; + uint_type.data_type = (DataType) root_symbol.scope.lookup ("uint"); ulong_type = new TypeReference (); - ulong_type.data_type = (DataType) root_symbol.lookup ("ulong").node; + ulong_type.data_type = (DataType) root_symbol.scope.lookup ("ulong"); unichar_type = new TypeReference (); - unichar_type.data_type = (DataType) root_symbol.lookup ("unichar").node; + unichar_type.data_type = (DataType) root_symbol.scope.lookup ("unichar"); // TODO: don't require GLib namespace in semantic analyzer - var glib_ns = root_symbol.lookup ("GLib"); + var glib_ns = root_symbol.scope.lookup ("GLib"); if (glib_ns != null) { - initially_unowned_type = (DataType) glib_ns.lookup ("InitiallyUnowned").node; + initially_unowned_type = (DataType) glib_ns.scope.lookup ("InitiallyUnowned"); type_type = new TypeReference (); - type_type.data_type = (DataType) glib_ns.lookup ("Type").node; + type_type.data_type = (DataType) glib_ns.scope.lookup ("Type"); - glist_type = (DataType) glib_ns.lookup ("List").node; - gslist_type = (DataType) glib_ns.lookup ("SList").node; + glist_type = (DataType) glib_ns.scope.lookup ("List"); + gslist_type = (DataType) glib_ns.scope.lookup ("SList"); - gerror_type = (DataType) glib_ns.lookup ("Error").node; + gerror_type = (DataType) glib_ns.scope.lookup ("Error"); } current_symbol = root_symbol; @@ -118,15 +118,15 @@ public class Vala.SemanticAnalyzer : CodeVisitor { } public override void visit_class (Class! cl) { - current_symbol = cl.symbol; + current_symbol = cl; current_class = cl; if (cl.base_class != null) { - current_source_file.add_symbol_dependency (cl.base_class.symbol, SourceFileDependencyType.HEADER_FULL); + current_source_file.add_symbol_dependency (cl.base_class, SourceFileDependencyType.HEADER_FULL); } foreach (TypeReference base_type_reference in cl.get_base_types ()) { - current_source_file.add_symbol_dependency (base_type_reference.data_type.symbol, SourceFileDependencyType.HEADER_FULL); + current_source_file.add_symbol_dependency (base_type_reference.data_type, SourceFileDependencyType.HEADER_FULL); } cl.accept_children (this); @@ -142,14 +142,14 @@ public class Vala.SemanticAnalyzer : CodeVisitor { List<string> missing_prereqs = null; foreach (DataType prereq in prerequisites) { if (!class_is_a (cl, prereq)) { - missing_prereqs.prepend (prereq.symbol.get_full_name ()); + missing_prereqs.prepend (prereq.get_full_name ()); } } /* report any missing prerequisites */ if (missing_prereqs != null) { cl.error = true; - string error_string = "%s: some prerequisites (".printf (cl.symbol.get_full_name ()); + string error_string = "%s: some prerequisites (".printf (cl.get_full_name ()); bool first = true; foreach (string s in missing_prereqs) { if (first) { @@ -175,10 +175,10 @@ public class Vala.SemanticAnalyzer : CodeVisitor { /* check methods */ foreach (Method m in iface.get_methods ()) { if (m.is_abstract) { - var sym = cl.symbol.lookup (m.name); - if (sym == null || !(sym.node is Method) || ((Method) sym.node).base_interface_method != m) { + var sym = cl.scope.lookup (m.name); + if (sym == null || !(sym is Method) || ((Method) sym).base_interface_method != m) { cl.error = true; - Report.error (cl.source_reference, "`%s' does not implement interface method `%s'".printf (cl.symbol.get_full_name (), m.symbol.get_full_name ())); + Report.error (cl.source_reference, "`%s' does not implement interface method `%s'".printf (cl.get_full_name (), m.get_full_name ())); } } } @@ -193,10 +193,10 @@ public class Vala.SemanticAnalyzer : CodeVisitor { while (base_class != null && base_class.is_abstract) { foreach (Method m in base_class.get_methods ()) { if (m.is_abstract) { - var sym = cl.symbol.lookup (m.name); - if (sym == null || !(sym.node is Method) || ((Method) sym.node).base_method != m) { + var sym = cl.scope.lookup (m.name); + if (sym == null || !(sym is Method) || ((Method) sym).base_method != m) { cl.error = true; - Report.error (cl.source_reference, "`%s' does not implement abstract method `%s'".printf (cl.symbol.get_full_name (), m.symbol.get_full_name ())); + Report.error (cl.source_reference, "`%s' does not implement abstract method `%s'".printf (cl.get_full_name (), m.get_full_name ())); } } } @@ -248,7 +248,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor { } public override void visit_struct (Struct! st) { - current_symbol = st.symbol; + current_symbol = st; current_struct = st; st.accept_children (this); @@ -258,10 +258,10 @@ public class Vala.SemanticAnalyzer : CodeVisitor { } public override void visit_interface (Interface! iface) { - current_symbol = iface.symbol; + current_symbol = iface; foreach (TypeReference prerequisite_reference in iface.get_prerequisites ()) { - current_source_file.add_symbol_dependency (prerequisite_reference.data_type.symbol, SourceFileDependencyType.HEADER_FULL); + current_source_file.add_symbol_dependency (prerequisite_reference.data_type, SourceFileDependencyType.HEADER_FULL); } iface.accept_children (this); @@ -279,7 +279,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor { if (class_or_interface is Class) { if (prereq_class != null) { iface.error = true; - Report.error (iface.source_reference, "%s: Interfaces cannot have multiple instantiable prerequisites (`%s' and `%s')".printf (iface.symbol.get_full_name (), class_or_interface.symbol.get_full_name (), prereq_class.symbol.get_full_name ())); + Report.error (iface.source_reference, "%s: Interfaces cannot have multiple instantiable prerequisites (`%s' and `%s')".printf (iface.get_full_name (), class_or_interface.get_full_name (), prereq_class.get_full_name ())); return; } @@ -311,18 +311,18 @@ public class Vala.SemanticAnalyzer : CodeVisitor { if (f.access != MemberAccessibility.PRIVATE) { if (f.type_reference.data_type != null) { /* is null if it references a type parameter */ - current_source_file.add_symbol_dependency (f.type_reference.data_type.symbol, SourceFileDependencyType.HEADER_SHALLOW); + current_source_file.add_symbol_dependency (f.type_reference.data_type, SourceFileDependencyType.HEADER_SHALLOW); } } else { if (f.type_reference.data_type != null) { /* is null if it references a type parameter */ - current_source_file.add_symbol_dependency (f.type_reference.data_type.symbol, SourceFileDependencyType.SOURCE); + current_source_file.add_symbol_dependency (f.type_reference.data_type, SourceFileDependencyType.SOURCE); } } } public override void visit_method (Method! m) { - current_symbol = m.symbol; + current_symbol = m; current_return_type = m.return_type; var init_attr = m.get_attribute ("ModuleInit"); @@ -332,7 +332,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor { if (m.return_type.data_type != null) { /* is null if it is void or a reference to a type parameter */ - current_source_file.add_symbol_dependency (m.return_type.data_type.symbol, SourceFileDependencyType.HEADER_SHALLOW); + current_source_file.add_symbol_dependency (m.return_type.data_type, SourceFileDependencyType.HEADER_SHALLOW); } m.accept_children (this); @@ -340,39 +340,38 @@ public class Vala.SemanticAnalyzer : CodeVisitor { current_symbol = current_symbol.parent_symbol; current_return_type = null; - if (current_symbol.parent_symbol != null && - current_symbol.parent_symbol.node is Method) { + if (current_symbol.parent_symbol is Method) { /* lambda expressions produce nested methods */ - var up_method = (Method) current_symbol.parent_symbol.node; + var up_method = (Method) current_symbol.parent_symbol; current_return_type = up_method.return_type; } - if (current_symbol.node is Class) { + if (current_symbol is Class) { if (!(m is CreationMethod)) { - find_base_interface_method (m, (Class) current_symbol.node); + find_base_interface_method (m, (Class) current_symbol); if (m.is_virtual || m.overrides) { - find_base_class_method (m, (Class) current_symbol.node); + find_base_class_method (m, (Class) current_symbol); if (m.base_method == null) { - Report.error (m.source_reference, "%s: no suitable method found to override".printf (m.symbol.get_full_name ())); + Report.error (m.source_reference, "%s: no suitable method found to override".printf (m.get_full_name ())); } } } - } else if (current_symbol.node is Struct) { + } else if (current_symbol is Struct) { if (m.is_abstract || m.is_virtual || m.overrides) { - Report.error (m.source_reference, "A struct member `%s' cannot be marked as override, virtual, or abstract".printf (m.symbol.get_full_name ())); + Report.error (m.source_reference, "A struct member `%s' cannot be marked as override, virtual, or abstract".printf (m.get_full_name ())); return; } } } private void find_base_class_method (Method! m, Class! cl) { - var sym = cl.symbol.lookup (m.name); - if (sym != null && sym.node is Method) { - var base_method = (Method) sym.node; + var sym = cl.scope.lookup (m.name); + if (sym is Method) { + var base_method = (Method) sym; if (base_method.is_abstract || base_method.is_virtual) { if (!m.equals (base_method)) { m.error = true; - Report.error (m.source_reference, "Return type and/or parameters of overriding method `%s' do not match overridden method `%s'.".printf (m.symbol.get_full_name (), base_method.symbol.get_full_name ())); + Report.error (m.source_reference, "Return type and/or parameters of overriding method `%s' do not match overridden method `%s'.".printf (m.get_full_name (), base_method.get_full_name ())); return; } @@ -390,13 +389,13 @@ public class Vala.SemanticAnalyzer : CodeVisitor { // FIXME report error if multiple possible base methods are found foreach (TypeReference type in cl.get_base_types ()) { if (type.data_type is Interface) { - var sym = type.data_type.symbol.lookup (m.name); - if (sym != null && sym.node is Method) { - var base_method = (Method) sym.node; + var sym = type.data_type.scope.lookup (m.name); + if (sym is Method) { + var base_method = (Method) sym; if (base_method.is_abstract) { if (!m.equals (base_method)) { m.error = true; - Report.error (m.source_reference, "Return type and/or parameters of overriding method `%s' do not match overridden method `%s'.".printf (m.symbol.get_full_name (), base_method.symbol.get_full_name ())); + Report.error (m.source_reference, "Return type and/or parameters of overriding method `%s' do not match overridden method `%s'.".printf (m.get_full_name (), base_method.get_full_name ())); return; } @@ -410,12 +409,12 @@ public class Vala.SemanticAnalyzer : CodeVisitor { public override void visit_creation_method (CreationMethod! m) { m.return_type = new TypeReference (); - m.return_type.data_type = (DataType) current_symbol.node; + m.return_type.data_type = (DataType) m.parent_symbol; m.return_type.transfers_ownership = true; - if (current_symbol.node is Class) { + if (current_symbol is Class) { // check for floating reference - var cl = (Class) current_symbol.node; + var cl = (Class) current_symbol; while (cl != null) { if (cl == initially_unowned_type) { m.return_type.floating_reference = true; @@ -426,7 +425,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor { } } - current_symbol = m.symbol; + current_symbol = m; current_return_type = m.return_type; m.accept_children (this); @@ -434,26 +433,25 @@ public class Vala.SemanticAnalyzer : CodeVisitor { current_symbol = current_symbol.parent_symbol; current_return_type = null; - if (current_symbol.parent_symbol != null && - current_symbol.parent_symbol.node is Method) { + if (current_symbol.parent_symbol is Method) { /* lambda expressions produce nested methods */ - var up_method = (Method) current_symbol.parent_symbol.node; + var up_method = (Method) current_symbol.parent_symbol; current_return_type = up_method.return_type; } - if (current_symbol.node is Class) { + if (current_symbol is Class) { if (!(m is CreationMethod)) { - find_base_interface_method (m, (Class) current_symbol.node); + find_base_interface_method (m, (Class) current_symbol); if (m.is_virtual || m.overrides) { - find_base_class_method (m, (Class) current_symbol.node); + find_base_class_method (m, (Class) current_symbol); if (m.base_method == null) { - Report.error (m.source_reference, "%s: no suitable method found to override".printf (m.symbol.get_full_name ())); + Report.error (m.source_reference, "%s: no suitable method found to override".printf (m.get_full_name ())); } } } - } else if (current_symbol.node is Struct) { + } else if (current_symbol is Struct) { if (m.is_abstract || m.is_virtual || m.overrides) { - Report.error (m.source_reference, "A struct member `%s' cannot be marked as override, virtual, or abstract".printf (m.symbol.get_full_name ())); + Report.error (m.source_reference, "A struct member `%s' cannot be marked as override, virtual, or abstract".printf (m.get_full_name ())); return; } } @@ -461,13 +459,12 @@ public class Vala.SemanticAnalyzer : CodeVisitor { if (m.body != null && current_class != null) { int n_params = 0; foreach (Statement stmt in m.body.get_statements ()) { - int params = stmt.get_number_of_set_construction_parameters (); - if (params == -1) { + if (!(stmt is ExpressionStatement) || !((ExpressionStatement) stmt).sets_property ()) { m.error = true; Report.error (stmt.source_reference, "class creation methods only allow property assignment statements"); return; } - n_params += params; + n_params++; } m.n_construction_params = n_params; } @@ -479,46 +476,46 @@ public class Vala.SemanticAnalyzer : CodeVisitor { if (!p.ellipsis) { if (p.type_reference.data_type != null) { /* is null if it references a type parameter */ - current_source_file.add_symbol_dependency (p.type_reference.data_type.symbol, SourceFileDependencyType.HEADER_SHALLOW); - current_source_file.add_symbol_dependency (p.type_reference.data_type.symbol, SourceFileDependencyType.SOURCE); + current_source_file.add_symbol_dependency (p.type_reference.data_type, SourceFileDependencyType.HEADER_SHALLOW); + current_source_file.add_symbol_dependency (p.type_reference.data_type, SourceFileDependencyType.SOURCE); } } /* special treatment for construct formal parameters used in creation methods */ if (p.construct_parameter) { - if (!(p.symbol.parent_symbol.node is CreationMethod)) { + if (!(p.parent_symbol is CreationMethod)) { p.error = true; Report.error (p.source_reference, "construct parameters are only allowed in type creation methods"); return; } - var method_body = ((CreationMethod)p.symbol.parent_symbol.node).body; + var method_body = ((CreationMethod) p.parent_symbol).body; var left = new MemberAccess.simple (p.name); var right = new MemberAccess.simple (p.name); /* try to lookup the requested property */ - var prop_sym = symbol_lookup_inherited (current_class.symbol, p.name); - if (!(prop_sym.node is Property)) { + var prop_sym = symbol_lookup_inherited (current_class, p.name); + if (!(prop_sym is Property)) { p.error = true; - Report.error (p.source_reference, "class `%s' does not contain a property named `%s'".printf (current_class.symbol.get_full_name (), p.name)); + Report.error (p.source_reference, "class `%s' does not contain a property named `%s'".printf (current_class.get_full_name (), p.name)); return; } left.symbol_reference = prop_sym; - right.symbol_reference = p.symbol; + right.symbol_reference = p; method_body.add_statement (new ExpressionStatement (new Assignment (left, right))); } } 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; + var sym = cl.scope.lookup (prop.name); + if (sym is Property) { + var base_property = (Property) sym; 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 ())); + Report.error (prop.source_reference, "Type and/or accessors of overriding property `%s' do not match overridden property `%s'.".printf (prop.get_full_name (), base_property.get_full_name ())); return; } @@ -536,13 +533,13 @@ public class Vala.SemanticAnalyzer : CodeVisitor { // 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; + var sym = type.data_type.scope.lookup (prop.name); + if (sym is Property) { + var base_property = (Property) sym; 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 ())); + Report.error (prop.source_reference, "Type and/or accessors of overriding property `%s' do not match overridden property `%s'.".printf (prop.get_full_name (), base_property.get_full_name ())); return; } @@ -555,37 +552,59 @@ public class Vala.SemanticAnalyzer : CodeVisitor { } public override void visit_property (Property! prop) { + current_symbol = prop; + prop.accept_children (this); + current_symbol = current_symbol.parent_symbol; + 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); + current_source_file.add_symbol_dependency (prop.type_reference.data_type, SourceFileDependencyType.HEADER_SHALLOW); + current_source_file.add_symbol_dependency (prop.type_reference.data_type, SourceFileDependencyType.SOURCE); } - if (prop.symbol.parent_symbol.node is Class) { - var cl = (Class) prop.symbol.parent_symbol.node; + if (prop.parent_symbol is Class) { + var cl = (Class) prop.parent_symbol; 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 ())); + Report.error (prop.source_reference, "%s: no suitable property found to override".printf (prop.get_full_name ())); } } } } public override void visit_property_accessor (PropertyAccessor! acc) { - var prop = (Property) acc.symbol.parent_symbol.node; + acc.prop = (Property) current_symbol; if (acc.readable) { - current_return_type = prop.type_reference; + current_return_type = acc.prop.type_reference; } else { // void current_return_type = new TypeReference (); } + if (!acc.source_reference.file.pkg) { + if (acc.body == null && !acc.prop.interface_only && !acc.prop.is_abstract) { + /* no accessor body specified, insert default body */ + + acc.body = new Block (); + if (acc.readable) { + acc.body.add_statement (new ReturnStatement (new MemberAccess.simple ("_%s".printf (acc.prop.name)))); + } else { + acc.body.add_statement (new ExpressionStatement (new Assignment (new MemberAccess.simple ("_%s".printf (acc.prop.name)), new MemberAccess.simple ("value")))); + } + } + + if (acc.writable || acc.construction) { + acc.value_parameter = new FormalParameter ("value", acc.prop.type_reference); + acc.body.scope.add (acc.value_parameter.name, acc.value_parameter); + } + } + acc.accept_children (this); current_return_type = null; @@ -596,7 +615,12 @@ public class Vala.SemanticAnalyzer : CodeVisitor { } public override void visit_constructor (Constructor! c) { - current_symbol = c.symbol; + c.this_parameter = new FormalParameter ("this", new TypeReference ()); + c.this_parameter.type_reference.data_type = (DataType) current_symbol; + c.scope.add (c.this_parameter.name, c.this_parameter); + + c.owner = current_symbol.scope; + current_symbol = c; c.accept_children (this); @@ -604,7 +628,8 @@ public class Vala.SemanticAnalyzer : CodeVisitor { } public override void visit_destructor (Destructor! d) { - current_symbol = d.symbol; + d.owner = current_symbol.scope; + current_symbol = d; d.accept_children (this); @@ -615,12 +640,13 @@ public class Vala.SemanticAnalyzer : CodeVisitor { } public override void visit_begin_block (Block! b) { - current_symbol = b.symbol; + b.owner = current_symbol.scope; + current_symbol = b; } public override void visit_end_block (Block! b) { foreach (VariableDeclarator decl in b.get_local_variables ()) { - decl.symbol.active = false; + decl.active = false; } current_symbol = current_symbol.parent_symbol; @@ -654,15 +680,15 @@ public class Vala.SemanticAnalyzer : CodeVisitor { return; } - if (decl.initializer.symbol_reference.node is Method && + if (decl.initializer.symbol_reference is Method && decl.type_reference.data_type is Callback) { - var m = (Method) decl.initializer.symbol_reference.node; + var m = (Method) decl.initializer.symbol_reference; var cb = (Callback) decl.type_reference.data_type; /* check whether method matches callback type */ if (!cb.matches_method (m)) { decl.error = true; - Report.error (decl.source_reference, "declaration of method `%s' doesn't match declaration of callback `%s'".printf (m.symbol.get_full_name (), cb.symbol.get_full_name ())); + Report.error (decl.source_reference, "declaration of method `%s' doesn't match declaration of callback `%s'".printf (m.get_full_name (), cb.get_full_name ())); return; } @@ -688,16 +714,15 @@ public class Vala.SemanticAnalyzer : CodeVisitor { } if (decl.type_reference.data_type != null) { - current_source_file.add_symbol_dependency (decl.type_reference.data_type.symbol, SourceFileDependencyType.SOURCE); + current_source_file.add_symbol_dependency (decl.type_reference.data_type, SourceFileDependencyType.SOURCE); } - decl.symbol = new Symbol (decl); - current_symbol.add (decl.name, decl.symbol); + current_symbol.scope.add (decl.name, decl); - var block = (Block) current_symbol.node; + var block = (Block) current_symbol; block.add_local_variable (decl); - decl.symbol.active = true; + decl.active = true; } /** @@ -820,14 +845,13 @@ public class Vala.SemanticAnalyzer : CodeVisitor { public override void visit_begin_foreach_statement (ForeachStatement! stmt) { if (stmt.type_reference.data_type != null) { - current_source_file.add_symbol_dependency (stmt.type_reference.data_type.symbol, SourceFileDependencyType.SOURCE); + current_source_file.add_symbol_dependency (stmt.type_reference.data_type, SourceFileDependencyType.SOURCE); } stmt.variable_declarator = new VariableDeclarator (stmt.variable_name); stmt.variable_declarator.type_reference = stmt.type_reference; - stmt.variable_declarator.symbol = new Symbol (stmt.variable_declarator); - stmt.body.symbol.add (stmt.variable_name, stmt.variable_declarator.symbol); + stmt.body.scope.add (stmt.variable_name, stmt.variable_declarator); } public override void visit_end_foreach_statement (ForeachStatement! stmt) { @@ -874,8 +898,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor { } if (stmt.return_expression != null && - stmt.return_expression.symbol_reference != null && - stmt.return_expression.symbol_reference.node is VariableDeclarator && + stmt.return_expression.symbol_reference is VariableDeclarator && stmt.return_expression.static_type.takes_ownership && !current_return_type.transfers_ownership) { Report.warning (stmt.source_reference, "Local variable with strong reference used as return value and method return type hasn't been declared to transfer ownership"); @@ -892,15 +915,14 @@ public class Vala.SemanticAnalyzer : CodeVisitor { public override void visit_catch_clause (CatchClause! clause) { if (clause.type_reference.data_type != null) { - current_source_file.add_symbol_dependency (clause.type_reference.data_type.symbol, SourceFileDependencyType.SOURCE); + current_source_file.add_symbol_dependency (clause.type_reference.data_type, SourceFileDependencyType.SOURCE); } clause.variable_declarator = new VariableDeclarator (clause.variable_name); clause.variable_declarator.type_reference = new TypeReference (); clause.variable_declarator.type_reference.data_type = gerror_type; - clause.variable_declarator.symbol = new Symbol (clause.variable_declarator); - clause.body.symbol.add (clause.variable_name, clause.variable_declarator.symbol); + clause.body.scope.add (clause.variable_name, clause.variable_declarator); clause.accept_children (this); } @@ -912,7 +934,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor { */ public override void visit_lock_statement (LockStatement! stmt) { /* resource must be a member access and denote a Lockable */ - if (!(stmt.resource is MemberAccess && stmt.resource.symbol_reference.node is Lockable)) { + if (!(stmt.resource is MemberAccess && stmt.resource.symbol_reference is Lockable)) { stmt.error = true; stmt.resource.error = true; Report.error (stmt.resource.source_reference, "Expression is either not a member access or does not denote a lockable member"); @@ -920,13 +942,13 @@ public class Vala.SemanticAnalyzer : CodeVisitor { } /* parent symbol must be the current class */ - if (stmt.resource.symbol_reference.parent_symbol.node != current_class) { + if (stmt.resource.symbol_reference.parent_symbol != current_class) { stmt.error = true; stmt.resource.error = true; Report.error (stmt.resource.source_reference, "Only members of the current class are lockable"); } - ((Lockable)stmt.resource.symbol_reference.node).set_lock_used (true); + ((Lockable) stmt.resource.symbol_reference).set_lock_used (true); } public override void visit_begin_array_creation_expression (ArrayCreationExpression! expr) { @@ -993,17 +1015,17 @@ public class Vala.SemanticAnalyzer : CodeVisitor { public override void visit_character_literal (CharacterLiteral! expr) { expr.static_type = new TypeReference (); - expr.static_type.data_type = (DataType) root_symbol.lookup ("char").node; + expr.static_type.data_type = (DataType) root_symbol.scope.lookup ("char"); } public override void visit_integer_literal (IntegerLiteral! expr) { expr.static_type = new TypeReference (); - expr.static_type.data_type = (DataType) root_symbol.lookup (expr.get_type_name ()).node; + expr.static_type.data_type = (DataType) root_symbol.scope.lookup (expr.get_type_name ()); } public override void visit_real_literal (RealLiteral! expr) { expr.static_type = new TypeReference (); - expr.static_type.data_type = (DataType) root_symbol.lookup (expr.get_type_name ()).node; + expr.static_type.data_type = (DataType) root_symbol.scope.lookup (expr.get_type_name ()); } public override void visit_string_literal (StringLiteral! expr) { @@ -1021,60 +1043,60 @@ public class Vala.SemanticAnalyzer : CodeVisitor { expr.static_type = expr.literal.static_type; } - private TypeReference get_static_type_for_node (CodeNode! node) { - if (node is Field) { - var f = (Field) node; + private TypeReference get_static_type_for_symbol (Symbol! sym) { + if (sym is Field) { + var f = (Field) sym; return f.type_reference; - } else if (node is Constant) { - var c = (Constant) node; + } else if (sym is Constant) { + var c = (Constant) sym; return c.type_reference; - } else if (node is Property) { - var prop = (Property) node; + } else if (sym is Property) { + var prop = (Property) sym; var type = prop.type_reference.copy (); type.takes_ownership = false; return type; - } else if (node is FormalParameter) { - var p = (FormalParameter) node; + } else if (sym is FormalParameter) { + var p = (FormalParameter) sym; return p.type_reference; - } else if (node is TypeReference) { - return (TypeReference) node; - } else if (node is VariableDeclarator) { - var decl = (VariableDeclarator) node; + } else if (sym is TypeReference) { + return (TypeReference) sym; + } else if (sym is VariableDeclarator) { + var decl = (VariableDeclarator) sym; return decl.type_reference; - } else if (node is EnumValue || node is FlagsValue) { + } else if (sym is EnumValue) { var type = new TypeReference (); - type.data_type = (DataType) node.symbol.parent_symbol.node; + type.data_type = (DataType) sym.parent_symbol; return type; } return null; } public static Symbol symbol_lookup_inherited (Symbol! sym, string! name) { - var result = sym.lookup (name); + var result = sym.scope.lookup (name); if (result != null) { return result; } - if (sym.node is Class) { - var cl = (Class) sym.node; + if (sym is Class) { + var cl = (Class) sym; foreach (TypeReference base_type in cl.get_base_types ()) { - result = symbol_lookup_inherited (base_type.data_type.symbol, name); + result = symbol_lookup_inherited (base_type.data_type, name); if (result != null) { return result; } } - } else if (sym.node is Struct) { - var st = (Struct) sym.node; + } else if (sym is Struct) { + var st = (Struct) sym; foreach (TypeReference base_type in st.get_base_types ()) { - result = symbol_lookup_inherited (base_type.data_type.symbol, name); + result = symbol_lookup_inherited (base_type.data_type, name); if (result != null) { return result; } } - } else if (sym.node is Interface) { - var iface = (Interface) sym.node; + } else if (sym is Interface) { + var iface = (Interface) sym; foreach (TypeReference prerequisite in iface.get_prerequisites ()) { - result = symbol_lookup_inherited (prerequisite.data_type.symbol, name); + result = symbol_lookup_inherited (prerequisite.data_type, name); if (result != null) { return result; } @@ -1092,8 +1114,8 @@ public class Vala.SemanticAnalyzer : CodeVisitor { private DataType find_parent_type (Symbol sym) { while (sym != null) { - if (sym.node is DataType) { - return (DataType) sym.node; + if (sym is DataType) { + return (DataType) sym; } sym = sym.parent_symbol; } @@ -1114,7 +1136,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor { if (expr.symbol_reference == null) { foreach (NamespaceReference ns in current_using_directives) { - var local_sym = ns.namespace_symbol.lookup (expr.member_name); + var local_sym = ns.namespace_symbol.scope.lookup (expr.member_name); if (local_sym != null) { if (expr.symbol_reference != null) { expr.error = true; @@ -1134,14 +1156,13 @@ public class Vala.SemanticAnalyzer : CodeVisitor { if (expr.inner is MemberAccess || expr.inner is BaseAccess) { base_symbol = expr.inner.symbol_reference; - if (base_symbol.node is Namespace || - base_symbol.node is DataType) { - expr.symbol_reference = base_symbol.lookup (expr.member_name); + if (base_symbol is Namespace || base_symbol is DataType) { + expr.symbol_reference = base_symbol.scope.lookup (expr.member_name); } } if (expr.symbol_reference == null && expr.inner.static_type != null) { - base_symbol = expr.inner.static_type.data_type.symbol; + base_symbol = expr.inner.static_type.data_type; expr.symbol_reference = symbol_lookup_inherited (base_symbol, expr.member_name); } } @@ -1152,7 +1173,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor { return; } - var member = expr.symbol_reference.node; + var member = expr.symbol_reference; MemberAccessibility access = MemberAccessibility.PUBLIC; if (member is Field) { access = ((Field) member).access; @@ -1161,19 +1182,19 @@ public class Vala.SemanticAnalyzer : CodeVisitor { } if (access == MemberAccessibility.PRIVATE) { - var target_type = (DataType) member.symbol.parent_symbol.node; + var target_type = (DataType) member.parent_symbol; var this_type = find_parent_type (current_symbol); if (target_type != this_type) { expr.error = true; - Report.error (expr.source_reference, "Access to private member `%s' denied".printf (member.symbol.get_full_name ())); + Report.error (expr.source_reference, "Access to private member `%s' denied".printf (member.get_full_name ())); return; } } current_source_file.add_symbol_dependency (expr.symbol_reference, SourceFileDependencyType.SOURCE); - expr.static_type = get_static_type_for_node (expr.symbol_reference.node); + expr.static_type = get_static_type_for_symbol (expr.symbol_reference); } private bool is_type_compatible (TypeReference! expression_type, TypeReference! expected_type) { @@ -1266,8 +1287,8 @@ public class Vala.SemanticAnalyzer : CodeVisitor { List<weak FormalParameter> params; - if (msym.node is Invokable) { - var m = (Invokable) msym.node; + if (msym is Invokable) { + var m = (Invokable) msym; if (m.is_invokable ()) { params = m.get_parameters (); } else { @@ -1303,7 +1324,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor { weak List<weak Expression> prev_arg_it = null; weak List<weak Expression> arg_it = args; - bool diag = (msym.node.get_attribute ("Diagnostics") != null); + bool diag = (msym.get_attribute ("Diagnostics") != null); bool ellipsis = false; int i = 0; @@ -1315,7 +1336,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor { /* header file necessary if we need to cast argument */ if (param.type_reference.data_type != null) { - current_source_file.add_symbol_dependency (param.type_reference.data_type.symbol, SourceFileDependencyType.SOURCE); + current_source_file.add_symbol_dependency (param.type_reference.data_type, SourceFileDependencyType.SOURCE); } if (arg_it == null) { @@ -1373,8 +1394,8 @@ public class Vala.SemanticAnalyzer : CodeVisitor { TypeReference ret_type; List<weak FormalParameter> params; - if (msym.node is Invokable) { - var m = (Invokable) msym.node; + if (msym is Invokable) { + var m = (Invokable) msym; ret_type = m.get_return_type (); params = m.get_parameters (); @@ -1403,7 +1424,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor { } else { TypeReference instance_type = ma.inner.static_type; // trace type arguments back to the datatype where the method has been declared - while (instance_type.data_type != msym.parent_symbol.node) { + while (instance_type.data_type != msym.parent_symbol) { List<weak TypeReference> base_types = null; if (instance_type.data_type is Class) { var cl = (Class) instance_type.data_type; @@ -1417,7 +1438,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor { return; } foreach (TypeReference base_type in base_types) { - if (symbol_lookup_inherited (base_type.data_type.symbol, msym.name) != null) { + if (symbol_lookup_inherited (base_type.data_type, msym.name) != null) { // construct a new type reference for the base type with correctly linked type arguments var instance_base_type = new TypeReference (); instance_base_type.data_type = base_type.data_type; @@ -1438,7 +1459,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor { } } } - if (instance_type.data_type != msym.parent_symbol.node) { + if (instance_type.data_type != msym.parent_symbol) { Report.error (expr.source_reference, "internal error: generic type parameter tracing not supported yet"); expr.error = true; return; @@ -1459,8 +1480,8 @@ public class Vala.SemanticAnalyzer : CodeVisitor { } } - if (msym.node is Method) { - var m = (Method) msym.node; + if (msym is Method) { + var m = (Method) msym; expr.tree_can_fail = expr.can_fail = (m.get_error_domains ().length () > 0); } @@ -1532,7 +1553,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor { expr.static_type.data_type = current_class.base_class; } - expr.symbol_reference = expr.static_type.data_type.symbol; + expr.symbol_reference = expr.static_type.data_type; } public override void visit_postfix_expression (PostfixExpression! expr) { @@ -1554,37 +1575,37 @@ public class Vala.SemanticAnalyzer : CodeVisitor { return; } - var constructor_node = expr.member_name.symbol_reference.node; - var type_node = expr.member_name.symbol_reference.node; + var constructor_sym = expr.member_name.symbol_reference; + var type_sym = expr.member_name.symbol_reference; var type_args = expr.member_name.get_type_arguments (); - if (constructor_node is Method) { - type_node = constructor_node.symbol.parent_symbol.node; + if (constructor_sym is Method) { + type_sym = constructor_sym.parent_symbol; - var constructor = (Method) constructor_node; - if (!(constructor_node is CreationMethod)) { + var constructor = (Method) constructor_sym; + if (!(constructor_sym is CreationMethod)) { expr.error = true; - Report.error (expr.source_reference, "`%s' is not a creation method".printf (constructor.symbol.get_full_name ())); + Report.error (expr.source_reference, "`%s' is not a creation method".printf (constructor.get_full_name ())); return; } - expr.symbol_reference = constructor.symbol; + expr.symbol_reference = constructor; type_args = ((MemberAccess) expr.member_name.inner).get_type_arguments (); - } else if (constructor_node is EnumValue) { - type_node = constructor_node.symbol.parent_symbol.node; + } else if (constructor_sym is EnumValue) { + type_sym = constructor_sym.parent_symbol; - expr.symbol_reference = constructor_node.symbol; + expr.symbol_reference = constructor_sym; } - if (type_node is Class || type_node is Struct) { - type = (DataType) type_node; - } else if (type_node is Enum && ((Enum) type_node).error_domain) { - type = (DataType) type_node; + if (type_sym is Class || type_sym is Struct) { + type = (DataType) type_sym; + } else if (type_sym is Enum && ((Enum) type_sym).error_domain) { + type = (DataType) type_sym; } else { expr.error = true; - Report.error (expr.source_reference, "`%s' is not a class, struct, or error domain".printf (type_node.symbol.get_full_name ())); + Report.error (expr.source_reference, "`%s' is not a class, struct, or error domain".printf (type_sym.get_full_name ())); return; } @@ -1603,7 +1624,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor { return; } - current_source_file.add_symbol_dependency (type.symbol, SourceFileDependencyType.SOURCE); + current_source_file.add_symbol_dependency (type, SourceFileDependencyType.SOURCE); expr.static_type = expr.type_reference.copy (); expr.static_type.transfers_ownership = true; @@ -1614,12 +1635,12 @@ public class Vala.SemanticAnalyzer : CodeVisitor { if (cl.is_abstract) { expr.static_type = null; expr.error = true; - Report.error (expr.source_reference, "Can't create instance of abstract class `%s'".printf (cl.symbol.get_full_name ())); + Report.error (expr.source_reference, "Can't create instance of abstract class `%s'".printf (cl.get_full_name ())); return; } - if (expr.symbol_reference == null && cl.default_construction_method != null) { - expr.symbol_reference = cl.default_construction_method.symbol; + if (expr.symbol_reference == null) { + expr.symbol_reference = cl.default_construction_method; } while (cl != null) { @@ -1633,21 +1654,21 @@ public class Vala.SemanticAnalyzer : CodeVisitor { } else if (type is Struct) { var st = (Struct) type; - if (expr.symbol_reference == null && st.default_construction_method != null) { - expr.symbol_reference = st.default_construction_method.symbol; + if (expr.symbol_reference == null) { + expr.symbol_reference = st.default_construction_method; } } if (expr.symbol_reference == null && expr.get_argument_list ().length () != 0) { expr.static_type = null; expr.error = true; - Report.error (expr.source_reference, "No arguments allowed when constructing type `%s'".printf (type.symbol.get_full_name ())); + Report.error (expr.source_reference, "No arguments allowed when constructing type `%s'".printf (type.get_full_name ())); return; } - if (expr.symbol_reference != null && expr.symbol_reference.node is Method) { - var m = (Method) expr.symbol_reference.node; - check_arguments (expr, m.symbol, m.get_parameters (), expr.get_argument_list ()); + if (expr.symbol_reference is Method) { + var m = (Method) expr.symbol_reference; + check_arguments (expr, m, m.get_parameters (), expr.get_argument_list ()); expr.tree_can_fail = expr.can_fail = (m.get_error_domains ().length () > 0); } else if (type is Enum) { @@ -1784,7 +1805,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor { // FIXME: check whether cast is allowed if (expr.type_reference.data_type != null) { - current_source_file.add_symbol_dependency (expr.type_reference.data_type.symbol, SourceFileDependencyType.SOURCE); + current_source_file.add_symbol_dependency (expr.type_reference.data_type, SourceFileDependencyType.SOURCE); } expr.static_type = expr.type_reference; @@ -2009,7 +2030,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor { return; } - current_source_file.add_symbol_dependency (expr.type_reference.data_type.symbol, SourceFileDependencyType.SOURCE); + current_source_file.add_symbol_dependency (expr.type_reference.data_type, SourceFileDependencyType.SOURCE); expr.static_type = bool_type; } @@ -2151,8 +2172,8 @@ public class Vala.SemanticAnalyzer : CodeVisitor { private Method find_current_method () { var sym = current_symbol; while (sym != null) { - if (sym.node is Method) { - return (Method) sym.node; + if (sym is Method) { + return (Method) sym; } sym = sym.parent_symbol; } @@ -2162,7 +2183,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor { private bool is_in_constructor () { var sym = current_symbol; while (sym != null) { - if (sym.node is Constructor) { + if (sym is Constructor) { return true; } sym = sym.parent_symbol; @@ -2188,8 +2209,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor { var cb = (Callback) l.expected_type.data_type; l.method = new Method (get_lambda_name (), cb.return_type); l.method.instance = cb.instance && in_instance_method; - l.method.symbol = new Symbol (l.method); - l.method.symbol.parent_symbol = current_symbol; + l.method.owner = current_symbol.scope; var lambda_params = l.get_parameters (); weak List<weak FormalParameter> lambda_param_it = lambda_params; @@ -2202,8 +2222,6 @@ public class Vala.SemanticAnalyzer : CodeVisitor { var lambda_param = (string) lambda_param_it.data; var param = new FormalParameter (lambda_param, cb_param.type_reference); - param.symbol = new Symbol (param); - l.method.symbol.add (param.name, param.symbol); l.method.add_parameter (param); @@ -2219,8 +2237,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor { if (l.expression_body != null) { var block = new Block (); - block.symbol = new Symbol (block); - block.symbol.parent_symbol = l.method.symbol; + block.scope.parent_scope = l.method.scope; if (l.method.return_type.data_type != null) { block.add_statement (new ReturnStatement (l.expression_body)); @@ -2231,11 +2248,11 @@ public class Vala.SemanticAnalyzer : CodeVisitor { l.method.body = block; } else { l.method.body = l.statement_body; - l.method.body.symbol.parent_symbol = l.method.symbol; } + l.method.body.owner = l.method.scope; /* lambda expressions should be usable like MemberAccess of a method */ - l.symbol_reference = l.method.symbol; + l.symbol_reference = l.method; } public override void visit_begin_assignment (Assignment! a) { @@ -2248,8 +2265,8 @@ public class Vala.SemanticAnalyzer : CodeVisitor { return; } - if (ma.symbol_reference.node is Signal) { - var sig = (Signal) ma.symbol_reference.node; + if (ma.symbol_reference is Signal) { + var sig = (Signal) ma.symbol_reference; a.right.expected_type = new TypeReference (); a.right.expected_type.data_type = sig.get_callback (); @@ -2277,7 +2294,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor { var ma = (MemberAccess) a.left; - if (!(ma.symbol_reference.node is Signal)) { + if (!(ma.symbol_reference is Signal)) { var old_value = new MemberAccess (ma.inner, ma.member_name); var bin = new BinaryExpression (BinaryOperator.PLUS, old_value, new ParenthesizedExpression (a.right, a.right.source_reference)); @@ -2314,8 +2331,8 @@ public class Vala.SemanticAnalyzer : CodeVisitor { if (a.left is MemberAccess) { var ma = (MemberAccess) a.left; - if (ma.symbol_reference.node is Signal) { - var sig = (Signal) ma.symbol_reference.node; + if (ma.symbol_reference is Signal) { + var sig = (Signal) ma.symbol_reference; if (a.right.symbol_reference == null) { a.error = true; @@ -2323,7 +2340,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor { return; } - var m = (Method) a.right.symbol_reference.node; + var m = (Method) a.right.symbol_reference; if (m.instance && m.access != MemberAccessibility.PRIVATE) { /* TODO: generate wrapper function */ @@ -2342,27 +2359,27 @@ public class Vala.SemanticAnalyzer : CodeVisitor { */ m.instance_last = true; } - } else if (ma.symbol_reference.node is Property) { - var prop = (Property) ma.symbol_reference.node; + } else if (ma.symbol_reference is Property) { + var prop = (Property) ma.symbol_reference; if (prop.set_accessor == null) { ma.error = true; - Report.error (ma.source_reference, "Property `%s' is read-only".printf (prop.symbol.get_full_name ())); + Report.error (ma.source_reference, "Property `%s' is read-only".printf (prop.get_full_name ())); return; } - } else if (ma.symbol_reference.node is VariableDeclarator && a.right.static_type == null) { - var decl = (VariableDeclarator) ma.symbol_reference.node; + } else if (ma.symbol_reference is VariableDeclarator && a.right.static_type == null) { + var decl = (VariableDeclarator) ma.symbol_reference; var right_ma = (MemberAccess) a.right; - if (right_ma.symbol_reference.node is Method && + if (right_ma.symbol_reference is Method && decl.type_reference.data_type is Callback) { - var m = (Method) right_ma.symbol_reference.node; + var m = (Method) right_ma.symbol_reference; var cb = (Callback) decl.type_reference.data_type; /* check whether method matches callback type */ if (!cb.matches_method (m)) { decl.error = true; - Report.error (a.source_reference, "declaration of method `%s' doesn't match declaration of callback `%s'".printf (m.symbol.get_full_name (), cb.symbol.get_full_name ())); + Report.error (a.source_reference, "declaration of method `%s' doesn't match declaration of callback `%s'".printf (m.get_full_name (), cb.get_full_name ())); return; } @@ -2372,19 +2389,19 @@ public class Vala.SemanticAnalyzer : CodeVisitor { Report.error (a.source_reference, "Assignment: Invalid callback assignment attempt"); return; } - } else if (ma.symbol_reference.node is Field && a.right.static_type == null) { - var f = (Field) ma.symbol_reference.node; + } else if (ma.symbol_reference is Field && a.right.static_type == null) { + var f = (Field) ma.symbol_reference; var right_ma = (MemberAccess) a.right; - if (right_ma.symbol_reference.node is Method && + if (right_ma.symbol_reference is Method && f.type_reference.data_type is Callback) { - var m = (Method) right_ma.symbol_reference.node; + var m = (Method) right_ma.symbol_reference; var cb = (Callback) f.type_reference.data_type; /* check whether method matches callback type */ if (!cb.matches_method (m)) { f.error = true; - Report.error (a.source_reference, "declaration of method `%s' doesn't match declaration of callback `%s'".printf (m.symbol.get_full_name (), cb.symbol.get_full_name ())); + Report.error (a.source_reference, "declaration of method `%s' doesn't match declaration of callback `%s'".printf (m.get_full_name (), cb.get_full_name ())); return; } diff --git a/vala/valasignal.vala b/vala/valasignal.vala index 88ea75333..5e1b89ac8 100644 --- a/vala/valasignal.vala +++ b/vala/valasignal.vala @@ -27,11 +27,6 @@ using GLib; */ public class Vala.Signal : Member, Invokable, Lockable { /** - * The symbol name of this signal. - */ - public string! name { get; set construct; } - - /** * The return type of handlers of this signal. */ public TypeReference! return_type { get; set construct; } @@ -62,10 +57,7 @@ public class Vala.Signal : Member, Invokable, Lockable { * @param source reference to source code * @return newly created signal */ - public Signal (string! _name, TypeReference! _return_type, SourceReference source) { - name = _name; - return_type = _return_type; - source_reference = source; + public Signal (construct string! name, construct TypeReference! return_type, construct SourceReference source_reference = null) { } /** @@ -75,6 +67,7 @@ public class Vala.Signal : Member, Invokable, Lockable { */ public void add_parameter (FormalParameter! param) { parameters.append (param); + scope.add (param.name, param); } public List<weak FormalParameter> get_parameters () { @@ -100,7 +93,7 @@ public class Vala.Signal : Member, Invokable, Lockable { generated_callback.instance = true; var sender_type = new TypeReference (); - sender_type.data_type = (DataType) symbol.parent_symbol.node; + sender_type.data_type = (DataType) parent_symbol; var sender_param = new FormalParameter ("sender", sender_type); generated_callback.add_parameter (sender_param); diff --git a/vala/valasourcefile.vala b/vala/valasourcefile.vala index d04ecde01..a1b40eedc 100644 --- a/vala/valasourcefile.vala +++ b/vala/valasourcefile.vala @@ -67,7 +67,7 @@ public class Vala.SourceFile { * The context this source file belongs to. */ public weak CodeContext context { get; set; } - + private List<NamespaceReference> using_directives; private List<CodeNode> nodes; @@ -91,10 +91,7 @@ public class Vala.SourceFile { * @param pkg true if this is a VAPI package file * @return newly created source file */ - public SourceFile (CodeContext! _context, string! _filename, bool _pkg = false) { - context = _context; - filename = _filename; - pkg = _pkg; + public SourceFile (construct CodeContext! context, construct string! filename, construct bool pkg = false) { } /** @@ -210,28 +207,28 @@ public class Vala.SourceFile { public void add_symbol_dependency (Symbol! sym, SourceFileDependencyType dep_type) { DataType t; - if (sym.node is DataType) { - t = (DataType) sym.node; - } else if (sym.node is Method || sym.node is Field) { - if (sym.parent_symbol.node is DataType) { - t = (DataType) sym.parent_symbol.node; + if (sym is DataType) { + t = (DataType) sym; + } else if (sym is Method || sym is Field) { + if (sym.parent_symbol is DataType) { + t = (DataType) sym.parent_symbol; } else { return; } - } else if (sym.node is Property) { - t = (DataType) sym.parent_symbol.node; - } else if (sym.node is Constant) { - if (sym.parent_symbol.node is DataType) { - t = (DataType) sym.parent_symbol.node; - } else if (sym.parent_symbol.node is Namespace) { - var ns = (Namespace) sym.parent_symbol.node; + } else if (sym is Property) { + t = (DataType) sym.parent_symbol; + } else if (sym is Constant) { + if (sym.parent_symbol is DataType) { + t = (DataType) sym.parent_symbol; + } else if (sym.parent_symbol is Namespace) { + var ns = (Namespace) sym.parent_symbol; source_internal_includes.concat (ns.get_cheader_filenames ()); return; } else { return; } - } else if (sym.node is FormalParameter) { - var fp = (FormalParameter) sym.node; + } else if (sym is FormalParameter) { + var fp = (FormalParameter) sym; t = fp.type_reference.data_type; if (t == null) { /* generic type parameter */ diff --git a/vala/valastatement.vala b/vala/valastatement.vala index 75cc69af5..b38a69380 100644 --- a/vala/valastatement.vala +++ b/vala/valastatement.vala @@ -23,17 +23,7 @@ using GLib; /** - * Base class for all statement types. + * Interface for all statement types. */ -public abstract class Vala.Statement : CodeNode { - /** - * Returns the number of construction parameters this statement sets in - * maximum or -1 if this statement may not be used in the construction - * part of a construction method. - * - * @return number of construction parameters set or -1 - */ - public virtual int get_number_of_set_construction_parameters () { - return -1; - } +public interface Vala.Statement : CodeNode { } diff --git a/vala/valastruct.vala b/vala/valastruct.vala index ac34755ed..f5841948b 100644 --- a/vala/valastruct.vala +++ b/vala/valastruct.vala @@ -74,6 +74,7 @@ public class Vala.Struct : DataType { public void add_type_parameter (TypeParameter! p) { type_parameters.append (p); p.type = this; + scope.add (p.name, p); } /** @@ -83,6 +84,7 @@ public class Vala.Struct : DataType { */ public void add_constant (Constant! c) { constants.append (c); + scope.add (c.name, c); } /** @@ -92,6 +94,7 @@ public class Vala.Struct : DataType { */ public void add_field (Field! f) { fields.append (f); + scope.add (f.name, f); } /** @@ -111,7 +114,17 @@ public class Vala.Struct : DataType { public void add_method (Method! m) { return_if_fail (m != null); + if (m.instance) { + m.this_parameter = new FormalParameter ("this", new TypeReference ()); + m.this_parameter.type_reference.data_type = this; + m.scope.add (m.this_parameter.name, m.this_parameter); + } + if (m is CreationMethod && m.name == null) { + default_construction_method = m; + } + methods.append (m); + scope.add (m.name, m); } /** @@ -151,7 +164,7 @@ public class Vala.Struct : DataType { } if (cname == null) { - cname = "%s%s".printf (@namespace.get_cprefix (), name); + cname = "%s%s".printf (parent_symbol.get_cprefix (), name); } return cname; } @@ -164,7 +177,7 @@ public class Vala.Struct : DataType { this.const_cname = cname; } - public override string get_lower_case_cprefix () { + public override string! get_lower_case_cprefix () { if (lower_case_cprefix == null) { lower_case_cprefix = "%s_".printf (get_lower_case_cname (null)); } @@ -173,7 +186,7 @@ public class Vala.Struct : DataType { private string get_lower_case_csuffix () { if (lower_case_csuffix == null) { - lower_case_csuffix = Namespace.camel_case_to_lower_case (name); + lower_case_csuffix = camel_case_to_lower_case (name); } return lower_case_csuffix; } @@ -182,7 +195,7 @@ public class Vala.Struct : DataType { if (infix == null) { infix = ""; } - return "%s%s%s".printf (@namespace.get_lower_case_cprefix (), infix, get_lower_case_csuffix ()); + return "%s%s%s".printf (parent_symbol.get_lower_case_cprefix (), infix, get_lower_case_csuffix ()); } public override string get_upper_case_cname (string infix) { @@ -309,7 +322,7 @@ public class Vala.Struct : DataType { public override string get_dup_function () { if (dup_function == null) { - Report.error (source_reference, "The type `%s` doesn't contain a copy function".printf (symbol.get_full_name ())); + Report.error (source_reference, "The type `%s` doesn't contain a copy function".printf (get_full_name ())); } return dup_function; } @@ -320,7 +333,7 @@ public class Vala.Struct : DataType { public override string get_free_function () { if (free_function == null) { - Report.error (source_reference, "The type `%s` doesn't contain a free function".printf (symbol.get_full_name ())); + Report.error (source_reference, "The type `%s` doesn't contain a free function".printf (get_full_name ())); } return free_function; } @@ -334,7 +347,7 @@ public class Vala.Struct : DataType { if (is_reference_type ()) { type_id = "G_TYPE_POINTER"; } else { - Report.error (source_reference, "The type `%s` doesn't declare a type id".printf (symbol.get_full_name ())); + Report.error (source_reference, "The type `%s` doesn't declare a type id".printf (get_full_name ())); } } return type_id; @@ -349,7 +362,7 @@ public class Vala.Struct : DataType { if (is_reference_type ()) { marshaller_type_name = "POINTER"; } else { - Report.error (source_reference, "The type `%s` doesn't declare a marshaller type name".printf (symbol.get_full_name ())); + Report.error (source_reference, "The type `%s` doesn't declare a marshaller type name".printf (get_full_name ())); } } return marshaller_type_name; @@ -364,7 +377,7 @@ public class Vala.Struct : DataType { if (is_reference_type ()) { return "g_value_get_pointer"; } else { - Report.error (source_reference, "The value type `%s` doesn't declare a GValue get function".printf (symbol.get_full_name ())); + Report.error (source_reference, "The value type `%s` doesn't declare a GValue get function".printf (get_full_name ())); return null; } } else { @@ -377,7 +390,7 @@ public class Vala.Struct : DataType { if (is_reference_type ()) { return "g_value_set_pointer"; } else { - Report.error (source_reference, "The value type `%s` doesn't declare a GValue set function".printf (symbol.get_full_name ())); + Report.error (source_reference, "The value type `%s` doesn't declare a GValue set function".printf (get_full_name ())); return null; } } else { diff --git a/vala/valaswitchstatement.vala b/vala/valaswitchstatement.vala index b7c5a23d1..1d0ae011f 100644 --- a/vala/valaswitchstatement.vala +++ b/vala/valaswitchstatement.vala @@ -25,7 +25,7 @@ using GLib; /** * Represents a switch selection statement in the source code. */ -public class Vala.SwitchStatement : Statement { +public class Vala.SwitchStatement : CodeNode, Statement { /** * Specifies the switch expression. */ diff --git a/vala/valasymbol.vala b/vala/valasymbol.vala index e5c5941f5..0ff6f9af4 100644 --- a/vala/valasymbol.vala +++ b/vala/valasymbol.vala @@ -25,16 +25,32 @@ using GLib; /** * Represents a node in the symbol tree. */ -public class Vala.Symbol { +public abstract class Vala.Symbol : CodeNode { /** - * The code node that created this symbol, if applicable. + * The parent of this symbol. */ - public weak CodeNode node { get; set; } - + public weak Symbol parent_symbol { + get { + if (owner == null) { + return null; + } else { + return owner.owner; + } + } + } + /** - * The parent of this symbol. + * The scope this symbol opens. */ - public weak Symbol parent_symbol { get; set; } + public weak Scope owner { + get { + return _owner; + } + set { + _owner = value; + _scope.parent_scope = value; + } + } /** * The symbol name. @@ -50,20 +66,16 @@ public class Vala.Symbol { * jump statements. */ public bool active { get; set; } - - private HashTable<string,Symbol> symbol_table = new HashTable.full (str_hash, str_equal, g_free, g_object_unref); - - /** - * Creates a new symbol. - * - * @param node the corresponding code node - * @return newly created symbol - */ - public Symbol (CodeNode _node = null) { - node = _node; + + public Scope scope { + get { return _scope; } } - + + private Scope _owner; + private Scope _scope; + construct { + _scope = new Scope (this); active = true; } @@ -88,32 +100,92 @@ public class Vala.Symbol { return "%s.%s".printf (parent_symbol.get_full_name (), name); } - + /** - * Adds the specified symbol with the specified name to the symbol table - * of this symbol. + * Returns the camel case string to be prepended to the name of members + * of this symbol when used in C code. * - * @param name name for the specified symbol - * @param sym a symbol + * @return the camel case prefix to be used in C code */ - public void add (string! name, Symbol! sym) { - symbol_table.insert (name, sym); - sym.parent_symbol = this; - sym.name = name; + public virtual string! get_cprefix () { + if (name == null) { + return ""; + } else { + return name; + } } /** - * Returns the symbol stored in the symbol table with the specified - * name. + * Returns the C name of this symbol in lower case. Words are + * separated by underscores. The lower case C name of the parent symbol + * is prefix of the result, if there is one. + * + * @param infix a string to be placed between namespace and data type + * name or null + * @return the lower case name to be used in C code + */ + public virtual string get_lower_case_cname (string infix = null) { + return null; + } + + /** + * Returns the string to be prefixed to members of this symbol in + * lower case when used in C code. + * + * @return the lower case prefix to be used in C code + */ + public virtual string! get_lower_case_cprefix () { + return ""; + } + + /** + * Returns a list of C header filenames users of this symbol must + * include. + * + * @return list of C header filenames for this symbol + */ + public virtual List<weak string> get_cheader_filenames () { + return null; + } + + /** + * Converts a string from CamelCase to lower_case. * - * @param name name of the symbol to be returned - * @return found symbol or null + * @param camel_case a string in camel case + * @return the specified string converted to lower case */ - public Symbol lookup (string! name) { - Symbol sym = symbol_table.lookup (name); - if (sym != null && !sym.active) { - sym = null; + public static string! camel_case_to_lower_case (string! camel_case) { + String result = new String (""); + + weak string i = camel_case; + + bool first = true; + while (i.len () > 0) { + unichar c = i.get_char (); + if (c.isupper () && !first) { + /* current character is upper case and + * we're not at the beginning */ + weak string t = i.prev_char (); + bool prev_upper = t.get_char ().isupper (); + t = i.next_char (); + bool next_upper = t.get_char ().isupper (); + if (!prev_upper || (i.len () >= 2 && !next_upper)) { + /* previous character wasn't upper case or + * next character isn't upper case*/ + int len = result.str.len (); + if (len != 1 && result.str.offset (len - 2).get_char () != '_') { + /* we're not creating 1 character words */ + result.append_c ('_'); + } + } + } + + result.append_unichar (c.tolower ()); + + first = false; + i = i.next_char (); } - return sym; + + return result.str; } } diff --git a/vala/valasymbolbuilder.vala b/vala/valasymbolbuilder.vala deleted file mode 100644 index 31be7f90d..000000000 --- a/vala/valasymbolbuilder.vala +++ /dev/null @@ -1,427 +0,0 @@ -/* valasymbolbuilder.vala - * - * Copyright (C) 2006-2007 Jürg Billeter, Raffaele Sandrini - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Author: - * Jürg Billeter <j@bitron.ch> - * Raffaele Sandrini <rasa@gmx.ch> - */ - -using GLib; - -/** - * Code visitor building the symbol tree. - */ -public class Vala.SymbolBuilder : CodeVisitor { - Symbol root; - Symbol current_type; - Symbol current_symbol; - - /** - * Build the symbol tree for the specified code context. - * - * @param context a code context - */ - public void build (CodeContext! context) { - root = context.root; - context.accept (this); - } - - public override void visit_namespace (Namespace! ns) { - if (ns.name == null) { - ns.symbol = root; - } - - if (ns.symbol == null) { - ns.symbol = root.lookup (ns.name); - } - if (ns.symbol == null) { - ns.symbol = new Symbol (ns); - root.add (ns.name, ns.symbol); - } - - current_symbol = ns.symbol; - - ns.accept_children (this); - - current_symbol = current_symbol.parent_symbol; - } - - private weak Symbol add_symbol (string name, CodeNode! node) { - if (name != null) { - if (current_symbol.lookup (name) != null) { - node.error = true; - Report.error (node.source_reference, "`%s' already contains a definition for `%s'".printf (current_symbol.get_full_name (), name)); - return null; - } - } - node.symbol = new Symbol (node); - if (name != null) { - current_symbol.add (name, node.symbol); - } else { - node.symbol.parent_symbol = current_symbol; - } - - return node.symbol; - } - - public override void visit_class (Class! cl) { - if (cl.error) { - /* skip classes with errors */ - return; - } - - var class_symbol = current_symbol.lookup (cl.name); - if (class_symbol == null || !(class_symbol.node is Class)) { - class_symbol = add_symbol (cl.name, cl); - } else { - /* merge this class declaration with existing class symbol */ - var main_class = (Class) class_symbol.node; - foreach (TypeReference base_type in cl.get_base_types ()) { - main_class.add_base_type (base_type); - } - foreach (Field f in cl.get_fields ()) { - main_class.add_field (f); - } - foreach (Method m in cl.get_methods ()) { - main_class.add_method (m); - } - foreach (Property prop in cl.get_properties ()) { - main_class.add_property (prop, true); - } - foreach (Signal sig in cl.get_signals ()) { - main_class.add_signal (sig); - } - if (cl.constructor != null) { - if (main_class.constructor != null) { - cl.error = true; - Report.error (cl.constructor.source_reference, "`%s' already contains a constructor".printf (current_symbol.get_full_name ())); - return; - } - main_class.constructor = cl.constructor; - } - if (cl.destructor != null) { - if (main_class.destructor != null) { - cl.error = true; - Report.error (cl.destructor.source_reference, "`%s' already contains a destructor".printf (current_symbol.get_full_name ())); - return; - } - main_class.destructor = cl.destructor; - } - } - - current_symbol = class_symbol; - - cl.accept_children (this); - - current_symbol = current_symbol.parent_symbol; - - if (cl.symbol == null) { - /* remove merged class */ - cl.@namespace.remove_class (cl); - if (cl.source_reference != null) { - cl.source_reference.file.remove_node (cl); - } - } - } - - public override void visit_struct (Struct! st) { - if (st.error) { - /* skip structs with errors */ - return; - } - - if (add_symbol (st.name, st) == null) { - return; - } - - current_symbol = st.symbol; - - st.accept_children (this); - - current_symbol = current_symbol.parent_symbol; - } - - public override void visit_interface (Interface! iface) { - if (iface.error) { - /* skip interfaces with errors */ - return; - } - - if (add_symbol (iface.name, iface) == null) { - return; - } - - current_symbol = iface.symbol; - - iface.accept_children (this); - - current_symbol = current_symbol.parent_symbol; - } - - public override void visit_enum (Enum! en) { - if (en.error) { - /* skip enums with errors */ - return; - } - - if (add_symbol (en.name, en) == null) { - return; - } - - current_symbol = en.symbol; - - en.accept_children (this); - - current_symbol = current_symbol.parent_symbol; - } - - public override void visit_enum_value (EnumValue! ev) { - ev.symbol = new Symbol (ev); - current_symbol.add (ev.name, ev.symbol); - } - - public override void visit_flags (Flags! fl) { - if (fl.error) { - /* skip flags with errors */ - return; - } - - if (add_symbol (fl.name, fl) == null) { - return; - } - - current_symbol = fl.symbol; - - fl.accept_children (this); - - current_symbol = current_symbol.parent_symbol; - } - - public override void visit_flags_value (FlagsValue! fv) { - fv.symbol = new Symbol (fv); - current_symbol.add (fv.name, fv.symbol); - } - - public override void visit_callback (Callback! cb) { - if (cb.error) { - /* skip enums with errors */ - return; - } - - if (add_symbol (cb.name, cb) == null) { - return; - } - - current_symbol = cb.symbol; - - cb.accept_children (this); - - current_symbol = current_symbol.parent_symbol; - } - - public override void visit_constant (Constant! c) { - add_symbol (c.name, c); - } - - public override void visit_field (Field! f) { - add_symbol (f.name, f); - } - - public override void visit_method (Method! m) { - if (add_symbol (m.name, m) == null) { - return; - } - - if (m.instance) { - if (!(m.symbol.parent_symbol.node is DataType)) { - Report.error (m.source_reference, "instance methods not allowed outside of data types"); - - m.error = true; - return; - } - - m.this_parameter = new FormalParameter ("this", new TypeReference ()); - m.this_parameter.type_reference.data_type = (DataType) m.symbol.parent_symbol.node; - m.this_parameter.symbol = new Symbol (m.this_parameter); - current_symbol.add (m.this_parameter.name, m.this_parameter.symbol); - } - - current_symbol = m.symbol; - - m.accept_children (this); - - current_symbol = current_symbol.parent_symbol; - } - - public override void visit_creation_method (CreationMethod! m) { - if (add_symbol (m.name, m) == null) { - return; - } - - var type_node = m.symbol.parent_symbol.node; - if (!(type_node is Class || type_node is Struct)) { - Report.error (m.source_reference, "construction methods may only be declared within classes and structs"); - - m.error = true; - return; - } - - if (m.name == null) { - if (type_node is Class) { - ((Class) type_node).default_construction_method = m; - } else if (type_node is Struct) { - ((Struct) type_node).default_construction_method = m; - } - } - - current_symbol = m.symbol; - - m.accept_children (this); - - current_symbol = current_symbol.parent_symbol; - } - - public override void visit_formal_parameter (FormalParameter! p) { - if (!p.ellipsis) { - add_symbol (p.name, p); - } - } - - public override void visit_property (Property! prop) { - if (prop.error) { - /* skip properties with errors */ - return; - } - - if (add_symbol (prop.name, prop) == null) { - return; - } - - current_symbol = prop.symbol; - - prop.this_parameter = new FormalParameter ("this", new TypeReference ()); - prop.this_parameter.type_reference.data_type = (DataType) prop.symbol.parent_symbol.node; - prop.this_parameter.symbol = new Symbol (prop.this_parameter); - current_symbol.add (prop.this_parameter.name, prop.this_parameter.symbol); - - prop.accept_children (this); - - current_symbol = current_symbol.parent_symbol; - } - - public override void visit_property_accessor (PropertyAccessor! acc) { - acc.symbol = new Symbol (acc); - acc.symbol.parent_symbol = current_symbol; - - if (acc.source_reference.file.pkg) { - return; - } - - current_symbol = acc.symbol; - - if (acc.writable || acc.construction) { - acc.value_parameter = new FormalParameter ("value", ((Property) current_symbol.parent_symbol.node).type_reference); - acc.value_parameter.symbol = new Symbol (acc.value_parameter); - - current_symbol.add (acc.value_parameter.name, acc.value_parameter.symbol); - } - - if (acc.body == null) { - /* no accessor body specified, insert default body */ - - var prop = (Property) acc.symbol.parent_symbol.node; - - if (prop.interface_only || prop.is_abstract) { - current_symbol = current_symbol.parent_symbol; - return; - } - - var block = new Block (); - if (acc.readable) { - block.add_statement (new ReturnStatement (new MemberAccess.simple ("_%s".printf (prop.name)))); - } else { - block.add_statement (new ExpressionStatement (new Assignment (new MemberAccess.simple ("_%s".printf (prop.name)), new MemberAccess.simple ("value")))); - } - acc.body = block; - } - - acc.accept_children (this); - - current_symbol = current_symbol.parent_symbol; - } - - public override void visit_signal (Signal! sig) { - if (sig.error) { - /* skip signals with errors */ - return; - } - - if (add_symbol (sig.name, sig) == null) { - return; - } - - current_symbol = sig.symbol; - - sig.accept_children (this); - - current_symbol = current_symbol.parent_symbol; - } - - public override void visit_constructor (Constructor! c) { - c.symbol = new Symbol (c); - c.symbol.parent_symbol = current_symbol; - current_symbol = c.symbol; - - c.accept_children (this); - - current_symbol = current_symbol.parent_symbol; - } - - public override void visit_destructor (Destructor! d) { - d.symbol = new Symbol (d); - d.symbol.parent_symbol = current_symbol; - current_symbol = d.symbol; - - d.accept_children (this); - - current_symbol = current_symbol.parent_symbol; - } - - public override void visit_try_statement (TryStatement! stmt) { - stmt.accept_children (this); - } - - public override void visit_catch_clause (CatchClause! clause) { - clause.accept_children (this); - } - - public override void visit_begin_block (Block! b) { - b.symbol = new Symbol (b); - b.symbol.parent_symbol = current_symbol; - current_symbol = b.symbol; - } - - public override void visit_end_block (Block! b) { - current_symbol = current_symbol.parent_symbol; - } - - public override void visit_type_parameter (TypeParameter! p) { - add_symbol (p.name, p); - } -} - diff --git a/vala/valasymbolresolver.vala b/vala/valasymbolresolver.vala index 2b90d628d..379ebeb84 100644 --- a/vala/valasymbolresolver.vala +++ b/vala/valasymbolresolver.vala @@ -27,7 +27,7 @@ using GLib; */ public class Vala.SymbolResolver : CodeVisitor { Symbol root_symbol; - Symbol current_scope; + Scope current_scope; List<weak NamespaceReference> current_using_directives; Class object_class; @@ -39,12 +39,12 @@ public class Vala.SymbolResolver : CodeVisitor { */ public void resolve (CodeContext! context) { root_symbol = context.root; - current_scope = root_symbol; + current_scope = root_symbol.scope; // TODO: don't require GLib namespace in symbol resolver - var glib_ns = root_symbol.lookup ("GLib"); + var glib_ns = root_symbol.scope.lookup ("GLib"); if (glib_ns != null) { - object_class = (Class) glib_ns.lookup ("Object").node; + object_class = (Class) glib_ns.scope.lookup ("Object"); } context.accept (this); @@ -52,7 +52,7 @@ public class Vala.SymbolResolver : CodeVisitor { public override void visit_source_file (SourceFile! file) { current_using_directives = file.get_using_directives (); - current_scope = root_symbol; + current_scope = root_symbol.scope; file.accept_children (this); @@ -60,14 +60,14 @@ public class Vala.SymbolResolver : CodeVisitor { } public override void visit_class (Class! cl) { - current_scope = cl.symbol; + current_scope = cl.scope; cl.accept_children (this); foreach (TypeReference type in cl.get_base_types ()) { if (type.data_type is Class) { if (cl.base_class != null) { - Report.error (type.source_reference, "%s: Classes cannot have multiple base classes (`%s' and `%s')".printf (cl.symbol.get_full_name (), cl.base_class.symbol.get_full_name (), type.data_type.symbol.get_full_name ())); + Report.error (type.source_reference, "%s: Classes cannot have multiple base classes (`%s' and `%s')".printf (cl.get_full_name (), cl.base_class.get_full_name (), type.data_type.get_full_name ())); return; } cl.base_class = (Class) type.data_type; @@ -80,51 +80,61 @@ public class Vala.SymbolResolver : CodeVisitor { cl.base_class = object_class; } - current_scope = current_scope.parent_symbol; + current_scope = current_scope.parent_scope; } public override void visit_struct (Struct! st) { - current_scope = st.symbol; + current_scope = st.scope; st.accept_children (this); - current_scope = current_scope.parent_symbol; + current_scope = current_scope.parent_scope; } public override void visit_interface (Interface! iface) { - current_scope = iface.symbol; + current_scope = iface.scope; iface.accept_children (this); - current_scope = current_scope.parent_symbol; + current_scope = current_scope.parent_scope; } public override void visit_enum (Enum! en) { - current_scope = en.symbol; + current_scope = en.scope; en.accept_children (this); - current_scope = current_scope.parent_symbol; + current_scope = current_scope.parent_scope; } public override void visit_callback (Callback! cb) { - current_scope = cb.symbol; + current_scope = cb.scope; cb.accept_children (this); - current_scope = current_scope.parent_symbol; + current_scope = current_scope.parent_scope; } public override void visit_constant (Constant! c) { + current_scope = c.scope; + c.accept_children (this); } public override void visit_field (Field! f) { + current_scope = f.scope; + f.accept_children (this); + + current_scope = current_scope.parent_scope; } public override void visit_method (Method! m) { + current_scope = m.scope; + m.accept_children (this); + + current_scope = current_scope.parent_scope; } public override void visit_creation_method (CreationMethod! m) { @@ -173,11 +183,11 @@ public class Vala.SymbolResolver : CodeVisitor { if (type.namespace_name == null) { Symbol sym = null; - Symbol scope = current_scope; + Scope scope = current_scope; while (sym == null && scope != null) { sym = scope.lookup (type.type_name); - scope = scope.parent_symbol; - if (sym != null && !(sym.node is DataType) && !(sym.node is TypeParameter)) { + scope = scope.parent_scope; + if (sym != null && !(sym is DataType) && !(sym is TypeParameter)) { // ignore non-type symbols sym = null; } @@ -188,7 +198,7 @@ public class Vala.SymbolResolver : CodeVisitor { continue; } - var local_sym = ns.namespace_symbol.lookup (type.type_name); + var local_sym = ns.namespace_symbol.scope.lookup (type.type_name); if (local_sym != null) { if (sym != null) { Report.error (type.source_reference, "`%s' is an ambiguous reference between `%s' and `%s'".printf (type.type_name, sym.get_full_name (), local_sym.get_full_name ())); @@ -202,25 +212,25 @@ public class Vala.SymbolResolver : CodeVisitor { Report.error (type.source_reference, "The type name `%s' could not be found".printf (type.type_name)); return; } - if (sym.node is TypeParameter) { - type.type_parameter = (TypeParameter) sym.node; + if (sym is TypeParameter) { + type.type_parameter = (TypeParameter) sym; } else { - type.data_type = (DataType) sym.node; + type.data_type = (DataType) sym; } } else { - var ns_symbol = root_symbol.lookup (type.namespace_name); + var ns_symbol = root_symbol.scope.lookup (type.namespace_name); if (ns_symbol == null) { type.error = true; Report.error (type.source_reference, "The namespace name `%s' could not be found".printf (type.namespace_name)); return; } - var sym = ns_symbol.lookup (type.type_name); + var sym = ns_symbol.scope.lookup (type.type_name); if (sym == null) { Report.error (type.source_reference, "The type name `%s' does not exist in the namespace `%s'".printf (type.type_name, type.namespace_name)); return; } - type.data_type = (DataType) sym.node; + type.data_type = (DataType) sym; } if (type.pointer_level > 0) { diff --git a/vala/valathrowstatement.vala b/vala/valathrowstatement.vala index f89854e67..079550162 100644 --- a/vala/valathrowstatement.vala +++ b/vala/valathrowstatement.vala @@ -25,7 +25,7 @@ using GLib; /** * Represents a throw statement in the source code. */ -public class Vala.ThrowStatement : Statement { +public class Vala.ThrowStatement : CodeNode, Statement { /** * The error expression to throw. */ diff --git a/vala/valatrystatement.vala b/vala/valatrystatement.vala index 3e25a4911..dca02eca2 100644 --- a/vala/valatrystatement.vala +++ b/vala/valatrystatement.vala @@ -25,7 +25,7 @@ using GLib; /** * Represents a try statement in the source code. */ -public class Vala.TryStatement : Statement { +public class Vala.TryStatement : CodeNode, Statement { /** * Specifies the body of the try statement. */ diff --git a/vala/valatypeparameter.vala b/vala/valatypeparameter.vala index 46d1f35aa..bf73bb484 100644 --- a/vala/valatypeparameter.vala +++ b/vala/valatypeparameter.vala @@ -25,12 +25,7 @@ using GLib; /** * Represents a generic type parameter in the source code. */ -public class Vala.TypeParameter : CodeNode { - /** - * The parameter name. - */ - public string! name { get; set construct; } - +public class Vala.TypeParameter : Symbol { /** * The generic type declaring this parameter. */ @@ -67,14 +62,12 @@ public class Vala.TypeParameter : CodeNode { if (array_type == null) { var new_array_type = new Array.with_type_parameter (this, rank, source_reference); - /* create a new Symbol */ - new_array_type.symbol = new Symbol (new_array_type); - this.symbol.parent_symbol.add (new_array_type.name, new_array_type.symbol); + parent_symbol.scope.add (new_array_type.name, new_array_type); /* add internal length field */ - new_array_type.symbol.add (new_array_type.get_length_field ().name, new_array_type.get_length_field ().symbol); + new_array_type.scope.add (new_array_type.get_length_field ().name, new_array_type.get_length_field ()); /* add internal resize method */ - new_array_type.symbol.add (new_array_type.get_resize_method ().name, new_array_type.get_resize_method ().symbol); + new_array_type.scope.add (new_array_type.get_resize_method ().name, new_array_type.get_resize_method ()); /* link the array type to the same source as the container type */ new_array_type.source_reference = this.source_reference; diff --git a/vala/valatypereference.vala b/vala/valatypereference.vala index 52371f5da..482a8493a 100644 --- a/vala/valatypereference.vala +++ b/vala/valatypereference.vala @@ -259,7 +259,7 @@ public class Vala.TypeReference : CodeNode { */ public string! to_string () { if (data_type != null) { - return data_type.symbol.get_full_name (); + return data_type.get_full_name (); } else if (type_parameter != null) { return type_parameter.name; } else { diff --git a/vala/valavariabledeclarator.vala b/vala/valavariabledeclarator.vala index 4a3ae8197..743a4348b 100644 --- a/vala/valavariabledeclarator.vala +++ b/vala/valavariabledeclarator.vala @@ -25,12 +25,7 @@ using GLib; /** * Represents a variable declarator in the source code. */ -public class Vala.VariableDeclarator : CodeNode, Invokable { - /** - * The variable name. - */ - public string! name { get; set construct; } - +public class Vala.VariableDeclarator : Symbol, Invokable { /** * The optional initializer expression. */ @@ -61,10 +56,7 @@ public class Vala.VariableDeclarator : CodeNode, Invokable { * @param source reference to source code * @return newly created variable declarator */ - public VariableDeclarator (string! _name, Expression init = null, SourceReference source = null) { - name = _name; - initializer = init; - source_reference = source; + public VariableDeclarator (construct string! name, construct Expression initializer = null, construct SourceReference source_reference = null) { } public override void accept (CodeVisitor! visitor) { diff --git a/vala/valawhilestatement.vala b/vala/valawhilestatement.vala index ea22ea8db..496038aa4 100644 --- a/vala/valawhilestatement.vala +++ b/vala/valawhilestatement.vala @@ -1,6 +1,6 @@ /* valawhilestatement.vala * - * Copyright (C) 2006 Jürg Billeter + * Copyright (C) 2006-2007 Jürg Billeter * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -25,7 +25,7 @@ using GLib; /** * Represents a while iteration statement in the source code. */ -public class Vala.WhileStatement : Statement { +public class Vala.WhileStatement : CodeNode, Statement { /** * Specifies the loop condition. */ @@ -42,7 +42,7 @@ public class Vala.WhileStatement : Statement { /** * Specifies the loop body. */ - public Statement body { get; set; } + public Block body { get; set; } private Expression! _condition; @@ -54,10 +54,7 @@ public class Vala.WhileStatement : Statement { * @param source reference to source code * @return newly created while statement */ - public WhileStatement (Expression! cond, Statement! _body, SourceReference source) { - condition = cond; - body = _body; - source_reference = source; + public WhileStatement (construct Expression! condition, construct Block! body, construct SourceReference source_reference = null) { } public override void accept (CodeVisitor! visitor) { |