From: Jürg Billeter Date: Sun, 21 May 2006 11:51:46 +0000 (+0000) Subject: support file comments, BREAK, CONTINUE support break and continue, add X-Git-Tag: VALA_0_0_1~48 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=405b0c4f10090cd147f09d31e37b96a5b14a8106;p=platform%2Fupstream%2Fvala.git support file comments, BREAK, CONTINUE support break and continue, add 2006-05-21 Jürg Billeter * vala/scanner.l: support file comments, BREAK, CONTINUE * vala/parser.y: support break and continue, add more comments * vala/valacodecontext.vala: find cyclic header dependencies * vala/valasourcefile.vala: add get_namespaces method, add dependency information, add add_symbol_dependency method, add SourceFileDependencyType enum * vala/valasourcefilecycle.vala * vala/valacodevisitor.vala: support break and continue statements * vala/valaparser.vala: support file comments * vala/valasemanticanalyzer.vala: record dependency information * vala/valacodegenerator.vala: add include directives, type forward declarations, once section, enum values, method return types, and more comments * vala/valablock.vala, vala/valadeclarationstatement.vala, vala/valaemptystatement.vala, vala/valaexpressionstatement.vala, vala/valaforeachstatement.vala, vala/valaforstatement.vala, vala/valaifstatement.vala, vala/valareturnstatement.vala, vala/valastatement.vala, vala/valawhilestatement.vala: move source_reference property to Statement class * vala/valaclass.vala, vala/valaenum.vala, vala/valastruct.vala, vala/valatype.vala: move name, source_reference, namespace, and get_cheader_filenames to Type class * vala/valabreakstatement.vala * vala/valacontinuestatement.vala * vala/valaenum.vala: fix cname, add get_upper_case_cname method * vala/valaenumvalue.vala: add get_cname method * vala/valafield.vala: add access field * vala/valanamespace.vala: add get_structs, get_classes, and get_cheader_filenames methods, support cheader_filename attribute * vala/valastruct.vala: support cheader_filename attribute * vala/valatypereference.vala: support void cname * vala/vala.h: update * ccode/valaccodeblock.vala: support comments before statements * ccode/valaccodeenum.vala: optionally use typedef * ccode/valaccodefunction.vala: add copy method * ccode/valaccodenewline.vala * ccode/valaccodeoncesection.vala * ccode/valaccodewriter.vala: use whole line for comments * bindings/glib-2.0.vala: add cheader_filename attributes, extend string types * valac/generator.c: fix private field access, include string.h svn path=/trunk/; revision=31 --- diff --git a/vala/ChangeLog b/vala/ChangeLog index 423f5fc..7f9dccd 100644 --- a/vala/ChangeLog +++ b/vala/ChangeLog @@ -1,3 +1,47 @@ +2006-05-21 Jürg Billeter + + * vala/scanner.l: support file comments, BREAK, CONTINUE + * vala/parser.y: support break and continue, add more comments + * vala/valacodecontext.vala: find cyclic header dependencies + * vala/valasourcefile.vala: add get_namespaces method, add dependency + information, add add_symbol_dependency method, add + SourceFileDependencyType enum + * vala/valasourcefilecycle.vala + * vala/valacodevisitor.vala: support break and continue statements + * vala/valaparser.vala: support file comments + * vala/valasemanticanalyzer.vala: record dependency information + * vala/valacodegenerator.vala: add include directives, type forward + declarations, once section, enum values, method return types, and more + comments + * vala/valablock.vala, vala/valadeclarationstatement.vala, + vala/valaemptystatement.vala, vala/valaexpressionstatement.vala, + vala/valaforeachstatement.vala, vala/valaforstatement.vala, + vala/valaifstatement.vala, vala/valareturnstatement.vala, + vala/valastatement.vala, vala/valawhilestatement.vala: move + source_reference property to Statement class + * vala/valaclass.vala, vala/valaenum.vala, vala/valastruct.vala, + vala/valatype.vala: move name, source_reference, namespace, and + get_cheader_filenames to Type class + * vala/valabreakstatement.vala + * vala/valacontinuestatement.vala + * vala/valaenum.vala: fix cname, add get_upper_case_cname method + * vala/valaenumvalue.vala: add get_cname method + * vala/valafield.vala: add access field + * vala/valanamespace.vala: add get_structs, get_classes, and + get_cheader_filenames methods, support cheader_filename attribute + * vala/valastruct.vala: support cheader_filename attribute + * vala/valatypereference.vala: support void cname + * vala/vala.h: update + * ccode/valaccodeblock.vala: support comments before statements + * ccode/valaccodeenum.vala: optionally use typedef + * ccode/valaccodefunction.vala: add copy method + * ccode/valaccodenewline.vala + * ccode/valaccodeoncesection.vala + * ccode/valaccodewriter.vala: use whole line for comments + * bindings/glib-2.0.vala: add cheader_filename attributes, extend string + types + * valac/generator.c: fix private field access, include string.h + 2006-05-19 Jürg Billeter * vala/valacodegenerator.vala: include header file in corresponding diff --git a/vala/bindings/glib-2.0.vala b/vala/bindings/glib-2.0.vala index f06c771..2ec8d53 100644 --- a/vala/bindings/glib-2.0.vala +++ b/vala/bindings/glib-2.0.vala @@ -20,85 +20,93 @@ * Jürg Billeter */ -[CCode (cname = "gboolean")] +[CCode (cname = "gboolean", cheader_filename = "glib.h")] public struct bool { } -[CCode (cname = "gpointer")] +[CCode (cname = "gpointer", cheader_filename = "glib.h")] public struct pointer { } +[CCode (cheader_filename = "glib.h")] public struct char { } -[CCode (cname = "unsigned char")] +[CCode (cname = "unsigned char", cheader_filename = "glib.h")] public struct uchar { } +[CCode (cheader_filename = "glib.h")] public struct int { } -[CCode (cname = "unsigned int")] +[CCode (cname = "unsigned int", cheader_filename = "glib.h")] public struct uint { } +[CCode (cheader_filename = "glib.h")] public struct short { } -[CCode (cname = "unsigned short")] +[CCode (cname = "unsigned short", cheader_filename = "glib.h")] public struct ushort { } +[CCode (cheader_filename = "glib.h")] public struct long { } -[CCode (cname = "unsigned long")] +[CCode (cname = "unsigned long", cheader_filename = "glib.h")] public struct ulong { } -[CCode (cname = "gint8")] +[CCode (cname = "gint8", cheader_filename = "glib.h")] public struct int8 { } -[CCode (cname = "guint8")] +[CCode (cname = "guint8", cheader_filename = "glib.h")] public struct uint8 { } -[CCode (cname = "gint16")] +[CCode (cname = "gint16", cheader_filename = "glib.h")] public struct int16 { } -[CCode (cname = "guint16")] +[CCode (cname = "guint16", cheader_filename = "glib.h")] public struct uint16 { } -[CCode (cname = "gint32")] +[CCode (cname = "gint32", cheader_filename = "glib.h")] public struct int32 { } -[CCode (cname = "guint32")] +[CCode (cname = "guint32", cheader_filename = "glib.h")] public struct uint32 { } -[CCode (cname = "gint64")] +[CCode (cname = "gint64", cheader_filename = "glib.h")] public struct int64 { } -[CCode (cname = "guint64")] +[CCode (cname = "guint64", cheader_filename = "glib.h")] public struct uint64 { } -[CCode (cname = "gunichar")] +[CCode (cname = "gunichar", cheader_filename = "glib.h")] public struct unichar { + [CCode (cname = "g_unichar_isalnum")] + public bool isalnum (); [CCode (cname = "g_unichar_isupper")] public bool isupper (); + [CCode (cname = "g_unichar_toupper")] + public unichar toupper (); [CCode (cname = "g_unichar_tolower")] public unichar tolower (); } [ReferenceType ()] [AllowPointerArithmetic ()] -[CCode (cname = "char")] +[CCode (cname = "char", cheader_filename = "string.h,glib.h")] public struct astring { [CCode (cname = "g_str_has_suffix")] public bool has_suffix (string suffix); @@ -123,7 +131,7 @@ public struct astring { } [ReferenceType ()] -[CCode (cname = "char")] +[CCode (cname = "char", cheader_filename = "string.h,glib.h")] public struct string { [CCode (cname = "g_str_has_suffix")] public bool has_suffix (string suffix); @@ -135,6 +143,9 @@ public struct string { public ref string ndup (int n); [CCode (cname = "g_strcompress")] public ref string compress (); + [CCode (cname = "g_strsplit")] + public ref string[] split (string delimiter, int max_tokens /* = 0 */); + [CCode (cname = "g_utf8_next_char")] public string next_char (); [CCode (cname = "g_utf8_get_char")] @@ -142,10 +153,14 @@ public struct string { [CCode (cname = "g_utf8_offset_to_pointer")] [PlusOperator ()] public string offset (long offset); + [CCode (cname = "g_utf8_pointer_to_offset")] + public long pointer_to_offset (string pos); [CCode (cname = "g_utf8_prev_char")] public string prev_char (); [CCode (cname = "g_utf8_strlen")] public long len (long max /*= -1*/); + [CCode (cname = "g_utf8_strchr")] + public string chr (long len, unichar c); [CCode (cname = "g_utf8_strup")] public ref string up (long len /*= -1*/); @@ -154,7 +169,7 @@ public struct string { } [Import ()] -[CCode (cprefix = "G", lower_case_cprefix = "g_", include_filename = "glib.h")] +[CCode (cprefix = "G", lower_case_cprefix = "g_", cheader_filename = "glib.h")] namespace GLib { public struct Path { public static ref string get_basename (string file_name); @@ -168,7 +183,8 @@ namespace GLib { public struct ObjectConstructParam { } - public class Object { + [CCode (cheader_filename = "glib-object.h")] + public abstract class Object { public virtual Object constructor (Type type, uint n_construct_properties, ObjectConstructParam[] construct_properties); } @@ -176,8 +192,10 @@ namespace GLib { public struct Error { } + public static void return_if_fail (bool expr); + [ReferenceType ()] - [CCode (cname = "FILE")] + [CCode (cname = "FILE", cheader_filename = "stdio.h")] public struct File { [CCode (cname = "fopen")] public static ref File open (string path, string mode); @@ -193,7 +211,7 @@ namespace GLib { public void close (); } - [CCode (cname = "stderr")] + [CCode (cname = "stderr", cheader_filename = "stdio.h")] public static GLib.File stderr; [Unknown (reference_type = true)] @@ -268,6 +286,8 @@ namespace GLib { public pointer nth_data (uint n); public List nth_prev (uint n); + public List find_custom (G data, CompareFunc func); + public List find (G data); public int position (List llink); public int index (G data); @@ -277,6 +297,12 @@ namespace GLib { public List prev; } + public struct CompareFunc { + } + + [CCode (cname = "strcmp")] + public static GLib.CompareFunc strcmp; + [ReferenceType ()] public struct HashTable { public static ref HashTable new (HashFunc hash_func, EqualFunc key_equal_func); @@ -298,8 +324,10 @@ namespace GLib { [ReferenceType ()] public struct String { public static ref String new (string init); - public void append_c (char c); - public void append_unichar (unichar wc); + public String append (string val); + public String append_c (char c); + public String append_unichar (unichar wc); + public String erase (long pos, long len); public string str; public long len; diff --git a/vala/ccode/valaccodeblock.vala b/vala/ccode/valaccodeblock.vala index ae79a7d..b82260e 100644 --- a/vala/ccode/valaccodeblock.vala +++ b/vala/ccode/valaccodeblock.vala @@ -24,15 +24,16 @@ using GLib; namespace Vala { public class CCodeBlock : CCodeStatement { - ref List statements; + List statements; - public void add_statement (string statement) { + public void add_statement (CCodeNode statement) { + /* allow generic nodes to include comments */ statements.append (statement); } public override void write (CCodeWriter writer) { writer.write_begin_block (); - foreach (CCodeStatement statement in statements) { + foreach (CCodeNode statement in statements) { if (statement != null) { statement.write (writer); } diff --git a/vala/ccode/valaccodeenum.vala b/vala/ccode/valaccodeenum.vala index 8fca688..6ccd1ea 100644 --- a/vala/ccode/valaccodeenum.vala +++ b/vala/ccode/valaccodeenum.vala @@ -28,20 +28,32 @@ namespace Vala { List values; public void add_value (string name, string value) { - values.append ("%s = %s".printf (name, value)); + if (value == null) { + values.append (name); + } else { + values.append ("%s = %s".printf (name, value)); + } } public override void write (CCodeWriter writer) { + if (name != null) { + writer.write_string ("typedef "); + } writer.write_string ("enum "); - writer.write_string (name); writer.write_begin_block (); foreach (string value in values) { writer.write_indent (); writer.write_string (value); - writer.write_string (",\n"); + writer.write_string (","); + writer.write_newline (); } writer.write_end_block (); - writer.write_string (";\n"); + if (name != null) { + writer.write_string (" "); + writer.write_string (name); + } + writer.write_string (";"); + writer.write_newline (); } } } diff --git a/vala/ccode/valaccodefunction.vala b/vala/ccode/valaccodefunction.vala index afe5e88..3f2e104 100644 --- a/vala/ccode/valaccodefunction.vala +++ b/vala/ccode/valaccodefunction.vala @@ -34,8 +34,16 @@ namespace Vala { parameters.append (param); } + public ref CCodeFunction copy () { + var func = new CCodeFunction (name = name, return_type = return_type); + func.modifiers = modifiers; + func.parameters = parameters.copy (); + func.block = block; + return func; + } + public override void write (CCodeWriter writer) { - writer.write_newline (); + writer.write_indent (); if ((modifiers & CCodeModifiers.STATIC) == CCodeModifiers.STATIC) { writer.write_string ("static "); } @@ -60,6 +68,7 @@ namespace Vala { } else { writer.write_newline (); block.write (writer); + writer.write_newline (); } writer.write_newline (); } diff --git a/vala/ccode/valaccodenewline.vala b/vala/ccode/valaccodenewline.vala new file mode 100644 index 0000000..235d78b --- /dev/null +++ b/vala/ccode/valaccodenewline.vala @@ -0,0 +1,31 @@ +/* valaccodenewline.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 + */ + +using GLib; + +namespace Vala { + public class CCodeNewline : CCodeNode { + public override void write (CCodeWriter writer) { + writer.write_newline (); + } + } +} diff --git a/vala/ccode/valaccodeoncesection.vala b/vala/ccode/valaccodeoncesection.vala new file mode 100644 index 0000000..5280d4d --- /dev/null +++ b/vala/ccode/valaccodeoncesection.vala @@ -0,0 +1,45 @@ +/* valaccodeoncesection.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 + */ + +using GLib; + +namespace Vala { + public class CCodeOnceSection : CCodeFragment { + public string define { get; construct; } + + public override void write (CCodeWriter writer) { + writer.write_indent (); + writer.write_string ("#ifndef "); + writer.write_string (define); + writer.write_newline (); + writer.write_string ("#define "); + writer.write_string (define); + writer.write_newline (); + foreach (CCodeNode node in children) { + node.write (writer); + } + writer.write_indent (); + writer.write_string ("#endif"); + writer.write_newline (); + } + } +} diff --git a/vala/ccode/valaccodewriter.vala b/vala/ccode/valaccodewriter.vala index 9467ea3..cac8c52 100644 --- a/vala/ccode/valaccodewriter.vala +++ b/vala/ccode/valaccodewriter.vala @@ -74,7 +74,9 @@ namespace Vala { } public void write_comment (string text) { + write_indent (); stream.printf ("/*%s*/", text); + write_newline (); } } } diff --git a/vala/vala/parser.y b/vala/vala/parser.y index 8a59629..33ffbd0 100644 --- a/vala/vala/parser.y +++ b/vala/vala/parser.y @@ -137,9 +137,11 @@ static void yyerror (YYLTYPE *locp, ValaParser *parser, const char *msg); %token PERCENT "%" %token ABSTRACT "abstract" +%token BREAK "break" %token CLASS "class" %token CONST "const" %token CONSTRUCT "construct" +%token CONTINUE "continue" %token ELSE "else" %token ENUM "enum" %token VALA_FALSE "false" @@ -229,6 +231,8 @@ static void yyerror (YYLTYPE *locp, ValaParser *parser, const char *msg); %type statement_expression_list %type foreach_statement %type jump_statement +%type break_statement +%type continue_statement %type return_statement %type namespace_declaration %type class_declaration @@ -323,10 +327,7 @@ boolean_literal ; compilation_unit - : comment opt_using_directives opt_outer_declarations - { - current_source_file->comment = $1; - } + : opt_using_directives opt_outer_declarations ; type_name @@ -659,6 +660,7 @@ opt_expression expression : conditional_expression + | assignment ; statement @@ -709,9 +711,9 @@ empty_statement ; declaration_statement - : local_variable_declaration + : comment local_variable_declaration { - $$ = VALA_STATEMENT (vala_declaration_statement_new ($1, src(@1))); + $$ = VALA_STATEMENT (vala_declaration_statement_new ($2, src_com(@2, $1))); } ; @@ -749,9 +751,9 @@ local_variable_type ; expression_statement - : statement_expression SEMICOLON + : comment statement_expression SEMICOLON { - $$ = VALA_STATEMENT (vala_expression_statement_new ($1, src(@1))); + $$ = VALA_STATEMENT (vala_expression_statement_new ($2, src_com(@2, $1))); } ; @@ -825,7 +827,23 @@ foreach_statement ; jump_statement - : return_statement + : break_statement + | continue_statement + | return_statement + ; + +break_statement + : BREAK SEMICOLON + { + $$ = VALA_STATEMENT (vala_break_statement_new (src(@1))); + } + ; + +continue_statement + : CONTINUE SEMICOLON + { + $$ = VALA_STATEMENT (vala_continue_statement_new (src(@1))); + } ; return_statement @@ -929,6 +947,7 @@ class_declaration { GList *l; current_struct = VALA_STRUCT (vala_class_new ($6, src_com (@6, $1))); + VALA_CODE_NODE(current_struct)->attributes = $2; for (l = $7; l != NULL; l = l->next) { vala_struct_add_type_parameter (current_struct, l->data); } @@ -938,7 +957,7 @@ class_declaration } class_body { - $$ = current_struct; + $$ = VALA_CLASS (current_struct); current_struct = NULL; } ; @@ -1077,6 +1096,9 @@ field_declaration : comment opt_attributes opt_access_modifier opt_modifiers opt_ref type variable_declarator SEMICOLON { $$ = vala_field_new (vala_variable_declarator_get_name ($7), $6, vala_variable_declarator_get_initializer ($7), src_com (@6, $1)); + if ($3 != 0) { + $$->access = $3; + } } ; diff --git a/vala/vala/scanner.l b/vala/vala/scanner.l index 0eeaf6b..396f822 100644 --- a/vala/vala/scanner.l +++ b/vala/vala/scanner.l @@ -28,6 +28,8 @@ #define YY_DECL int yylex (YYSTYPE *yylval_param, YYLTYPE *yylloc_param, ValaParser *parser) #define uploc { yylloc->first_column = yylloc->last_column + 1; yylloc->last_column += strlen (yytext); } + +static gboolean file_comment = FALSE; %} %option yylineno @@ -47,13 +49,13 @@ literal ({literal_integer}|{literal_character}|{literal_string}) %% -"/*" { uploc; BEGIN (IN_COMMENT); } -[^*\n]* { uploc; yymore (); } -"*"+[^*/\n]* { uploc; yymore (); } +"/*" { uploc; file_comment = (yylineno == 1); BEGIN (IN_COMMENT); } +"*/" { uploc; BEGIN (INITIAL); yytext[strlen (yytext) - 2] = '\0'; vala_parser_push_comment (parser, g_strdup (yytext), file_comment); } +[^*\n]+ { uploc; yymore (); } +"*" { uploc; yymore (); } \n { yylloc->first_line = yylloc->last_line = yylineno; yylloc->first_column = 1; yylloc->last_column = 0; yymore (); } -"*/" { uploc; BEGIN (INITIAL); yytext[strlen (yytext) - 2] = '\0'; vala_parser_push_comment (parser, g_strdup (yytext)); } -"//".* { uploc; vala_parser_push_comment (parser, g_strdup (yytext + 2)); } +"//".* { uploc; vala_parser_push_comment (parser, g_strdup (yytext + 2), FALSE); } "{" { uploc; return OPEN_BRACE; } "}" { uploc; return CLOSE_BRACE; } @@ -108,9 +110,11 @@ literal ({literal_integer}|{literal_character}|{literal_string}) "@"[[:alnum:]_]+ { uploc; yylval->str = strdup (yytext + 1); return IDENTIFIER; } "abstract" { uploc; return ABSTRACT; } +"break" { uploc; return BREAK; } "class" { uploc; return CLASS; } "const" { uploc; return CONST; } "construct" { uploc; return CONSTRUCT; } +"continue" { uploc; return CONTINUE; } "else" { uploc; return ELSE; } "enum" { uploc; return ENUM; } "false" { uploc; return VALA_FALSE; } diff --git a/vala/vala/vala.h b/vala/vala/vala.h index a459120..4655928 100644 --- a/vala/vala/vala.h +++ b/vala/vala/vala.h @@ -3,12 +3,14 @@ #include #include #include +#include #include #include #include #include #include #include +#include #include #include #include diff --git a/vala/vala/valablock.vala b/vala/vala/valablock.vala index dcc057f..3866688 100644 --- a/vala/vala/valablock.vala +++ b/vala/vala/valablock.vala @@ -25,7 +25,6 @@ using GLib; namespace Vala { public class Block : Statement { public List statement_list { get; construct; } - public SourceReference source_reference { get; construct; } public static ref Block new (List statement_list, SourceReference source) { return (new Block (statement_list = statement_list, source_reference = source)); diff --git a/vala/vala/valabreakstatement.vala b/vala/vala/valabreakstatement.vala new file mode 100644 index 0000000..6aff3be --- /dev/null +++ b/vala/vala/valabreakstatement.vala @@ -0,0 +1,35 @@ +/* valabreakstatement.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 + */ + +using GLib; + +namespace Vala { + public class BreakStatement : Statement { + public static ref BreakStatement new (SourceReference source) { + return (new BreakStatement (source_reference = source)); + } + + public override void accept (CodeVisitor visitor) { + visitor.visit_break_statement (this); + } + } +} diff --git a/vala/vala/valaclass.vala b/vala/vala/valaclass.vala index 77a8a46..f45e170 100644 --- a/vala/vala/valaclass.vala +++ b/vala/vala/valaclass.vala @@ -24,7 +24,6 @@ using GLib; namespace Vala { public class Class : Struct { - public SourceReference source_reference { get; construct; } public List base_types; public Class base_class; diff --git a/vala/vala/valacodecontext.vala b/vala/vala/valacodecontext.vala index 8d625e1..55a322a 100644 --- a/vala/vala/valacodecontext.vala +++ b/vala/vala/valacodecontext.vala @@ -27,6 +27,8 @@ namespace Vala { List source_files; public Symbol root = new Symbol (); + List cycles; + public ref List get_source_files () { return source_files.copy (); } @@ -40,5 +42,117 @@ namespace Vala { file.accept (visitor); } } + + public void find_header_cycles () { + /* find cycles in dependencies between source files */ + foreach (SourceFile file in source_files) { + /* we're only interested in internal source files */ + if (!file.pkg) { + if (file.mark == 0) { + visit (file, null); + } + } + } + + /* find one head for each cycle, it must not have any + * hard dependencies on other files in the cycle + */ + foreach (SourceFileCycle cycle in cycles) { + cycle.head = find_cycle_head ((SourceFile) cycle.files.data); + cycle.head.is_cycle_head = true; + } + + /* connect the source files in a non-cyclic way + * cycle members connect to the head of their cycle + */ + foreach (SourceFile file2 in source_files) { + /* we're only interested in internal source files */ + if (!file2.pkg) { + foreach (SourceFile dep in file2.header_internal_dependencies) { + if (file2.cycle != null && dep.cycle == file2.cycle) { + /* in the same cycle */ + if (!file2.is_cycle_head) { + /* include header of cycle head */ + file2.header_internal_includes.append (file2.cycle.head.get_cheader_filename ()); + } + } else { + /* we can just include the headers if they are not in a cycle or not in the same cycle as the current file */ + file2.header_internal_includes.append (dep.get_cheader_filename ()); + } + } + } + } + + } + + private SourceFile find_cycle_head (SourceFile file) { + foreach (SourceFile dep in file.header_internal_full_dependencies) { + foreach (SourceFile cycle_file in file.cycle.files) { + if (dep == cycle_file) { + return find_cycle_head (dep); + } + } + } + /* no hard dependencies on members of the same cycle found + * source file suitable as cycle head + */ + return file; + } + + private void visit (SourceFile file, List chain) { + var l = chain.copy (); + l.append (file); + + /* mark file as currently being visited */ + file.mark = 1; + + foreach (SourceFile dep in file.header_internal_dependencies) { + if (file != dep) { + if (dep.mark == 1) { + /* found cycle */ + + var cycle = new SourceFileCycle (); + cycles.append (cycle); + + bool cycle_start_found = false; + foreach (SourceFile cycle_file in l) { + if (!cycle_start_found) { + if (cycle_file == dep) { + cycle_start_found = true; + } + } + if (cycle_start_found) { + if (cycle_file.cycle != null) { + /* file already in a cycle */ + if (cycle_file.cycle != cycle) { + /* file is in an other cycle, merge the two cycles */ + + cycles.remove (cycle_file.cycle); + + foreach (SourceFile inner_cycle_file in cycle_file.cycle.files) { + if (inner_cycle_file.cycle != cycle) { + /* file in inner cycle not yet added to outer cycle */ + cycle.files.append (inner_cycle_file); + inner_cycle_file.cycle = cycle; + } + } + } + } else { + cycle.files.append (cycle_file); + cycle_file.cycle = cycle; + } + } + } + } else if (dep.mark == 0) { + /* found not yet visited file */ + + visit (dep, l); + } + } + } + + /* mark file as successfully visited */ + file.mark = 2; + } } } diff --git a/vala/vala/valacodegenerator.vala b/vala/vala/valacodegenerator.vala index 26af22a..d73d581 100644 --- a/vala/vala/valacodegenerator.vala +++ b/vala/vala/valacodegenerator.vala @@ -35,13 +35,17 @@ namespace Vala { CCodeStruct instance_struct; CCodeStruct class_struct; + CCodeEnum cenum; CCodeFunction function; CCodeBlock block; TypeReference reference; // dummy for dependency resolution Symbol dummy_symbol; // dummy for dependency resolution + SourceFileCycle dummy_cycle; // dummy for dependency resolution public void emit (CodeContext context) { + context.find_header_cycles (); + /* we're only interested in non-pkg source files */ foreach (SourceFile file in context.get_source_files ()) { if (!file.pkg) { @@ -60,26 +64,108 @@ namespace Vala { source_type_member_declaration = new CCodeFragment (); source_type_member_definition = new CCodeFragment (); - if (source_file.comment != null) { - header_begin.append (new CCodeComment (text = source_file.comment)); + source_include_directives.append (new CCodeIncludeDirective (filename = source_file.get_cheader_filename ())); + + List used_includes = null; + used_includes.append (source_file.get_cheader_filename ()); + + foreach (string filename1 in source_file.header_external_includes) { + if (used_includes.find_custom (filename1, strcmp) == null) { + header_begin.append (new CCodeIncludeDirective (filename = filename1)); + used_includes.append (filename1); + } } + foreach (string filename2 in source_file.header_internal_includes) { + if (used_includes.find_custom (filename2, strcmp) == null) { + header_begin.append (new CCodeIncludeDirective (filename = filename2)); + used_includes.append (filename2); + } + } + foreach (string filename3 in source_file.source_includes) { + if (used_includes.find_custom (filename3, strcmp) == null) { + source_include_directives.append (new CCodeIncludeDirective (filename = filename3)); + used_includes.append (filename3); + } + } + if (source_file.is_cycle_head) { + foreach (SourceFile cycle_file in source_file.cycle.files) { + foreach (Namespace ns in cycle_file.get_namespaces ()) { + foreach (Struct st in ns.get_structs ()) { + header_type_declaration.append (new CCodeTypeDefinition (type_name = "struct _%s".printf (st.get_cname ()), typedef_name = st.get_cname ())); + } + foreach (Class cl in ns.get_classes ()) { + header_type_declaration.append (new CCodeTypeDefinition (type_name = "struct _%s".printf (cl.get_cname ()), typedef_name = cl.get_cname ())); + header_type_declaration.append (new CCodeTypeDefinition (type_name = "struct _%sClass".printf (cl.get_cname ()), typedef_name = "%sClass".printf (cl.get_cname ()))); + } + } + } + } + } + + private static ref string get_define_for_filename (string filename) { + var define = String.new ("__"); - source_include_directives.append (new CCodeIncludeDirective (filename = source_file.get_cheader_filename ())); + var i = filename; + while (i.len (-1) > 0) { + var c = i.get_char (); + if (c.isalnum () && c < 128) { + define.append_unichar (c.toupper ()); + } else { + define.append_c ('_'); + } + + i = i.next_char (); + } + + define.append ("__"); + + return define.str; } public override void visit_end_source_file (SourceFile source_file) { + var header_define = get_define_for_filename (source_file.get_cheader_filename ()); + + CCodeComment comment = null; + if (source_file.comment != null) { + comment = new CCodeComment (text = source_file.comment); + } + var writer = new CCodeWriter (stream = File.open (source_file.get_cheader_filename (), "w")); - header_begin.write (writer); - header_type_declaration.write (writer); - header_type_definition.write (writer); - header_type_member_declaration.write (writer); + if (comment != null) { + comment.write (writer); + } + writer.write_newline (); + var once = new CCodeOnceSection (define = header_define); + once.append (new CCodeNewline ()); + once.append (header_begin); + once.append (new CCodeNewline ()); + once.append (new CCodeIdentifier (name = "G_BEGIN_DECLS")); + once.append (new CCodeNewline ()); + once.append (new CCodeNewline ()); + once.append (header_type_declaration); + once.append (new CCodeNewline ()); + once.append (header_type_definition); + once.append (new CCodeNewline ()); + once.append (header_type_member_declaration); + once.append (new CCodeNewline ()); + once.append (new CCodeIdentifier (name = "G_END_DECLS")); + once.append (new CCodeNewline ()); + once.append (new CCodeNewline ()); + once.write (writer); writer.close (); writer = new CCodeWriter (stream = File.open (source_file.get_csource_filename (), "w")); + if (comment != null) { + comment.write (writer); + } source_begin.write (writer); + writer.write_newline (); source_include_directives.write (writer); + writer.write_newline (); source_type_member_declaration.write (writer); + writer.write_newline (); source_type_member_definition.write (writer); + writer.write_newline (); writer.close (); header_begin = null; @@ -97,6 +183,7 @@ namespace Vala { class_struct = new CCodeStruct (name = "_%sClass".printf (cl.get_cname ())); + header_type_declaration.append (new CCodeNewline ()); var macro = "(%s_get_type ())".printf (cl.get_lower_case_cname (null)); header_type_declaration.append (new CCodeMacroReplacement (name = cl.get_upper_case_cname ("TYPE_"), replacement = macro)); @@ -114,10 +201,13 @@ namespace Vala { macro = "(G_TYPE_INSTANCE_GET_CLASS ((obj), %s, %sClass))".printf (cl.get_upper_case_cname ("TYPE_"), cl.get_cname ()); header_type_declaration.append (new CCodeMacroReplacement (name = "%s_GET_CLASS(obj)".printf (cl.get_upper_case_cname (null)), replacement = macro)); + header_type_declaration.append (new CCodeNewline ()); - - header_type_declaration.append (new CCodeTypeDefinition (type_name = "struct %s".printf (instance_struct.name), typedef_name = cl.get_cname ())); - header_type_declaration.append (new CCodeTypeDefinition (type_name = "struct %s".printf (class_struct.name), typedef_name = "%sClass".printf (cl.get_cname ()))); + + if (cl.source_reference.file.cycle == null) { + header_type_declaration.append (new CCodeTypeDefinition (type_name = "struct %s".printf (instance_struct.name), typedef_name = cl.get_cname ())); + header_type_declaration.append (new CCodeTypeDefinition (type_name = "struct %s".printf (class_struct.name), typedef_name = "%sClass".printf (cl.get_cname ()))); + } instance_struct.add_field (cl.base_class.get_cname (), "parent"); class_struct.add_field ("%sClass".printf (cl.base_class.get_cname ()), "parent"); @@ -139,43 +229,45 @@ namespace Vala { } public override void visit_begin_enum (Enum en) { - instance_struct = new CCodeEnum (name = "_%s".printf (en.name)); + cenum = new CCodeEnum (name = en.get_cname ()); if (en.source_reference.comment != null) { header_type_definition.append (new CCodeComment (text = en.source_reference.comment)); } - header_type_definition.append (instance_struct); + header_type_definition.append (cenum); + } + + public override void visit_enum_value (EnumValue ev) { + cenum.add_value (ev.get_cname (), null); } public override void visit_field (Field f) { - instance_struct.add_field (f.type_reference.get_cname (), f.name); + if (f.access == MemberAccessibility.PUBLIC) { + instance_struct.add_field (f.type_reference.get_cname (), f.name); + } } public override void visit_end_method (Method m) { - var cmethod_decl = new CCodeFunction (name = m.get_cname (), return_type = "void"); - function = new CCodeFunction (name = m.get_cname (), return_type = "void"); - - if (m.access == MemberAccessibility.PUBLIC) { - header_type_member_declaration.append (cmethod_decl); - } else { - cmethod_decl.modifiers |= CCodeModifiers.STATIC; - function.modifiers |= CCodeModifiers.STATIC; - source_type_member_declaration.append (cmethod_decl); - } + function = new CCodeFunction (name = m.get_cname (), return_type = m.return_type.get_cname ()); if (m.instance) { var st = (Struct) m.symbol.parent_symbol.node; var this_type = new TypeReference (); this_type.type = st; var cparam = new CCodeFormalParameter (type_name = this_type.get_cname (), name = "self"); - cmethod_decl.add_parameter (cparam); function.add_parameter (cparam); } foreach (FormalParameter param in m.get_parameters ()) { - cmethod_decl.add_parameter ((CCodeFormalParameter) param.ccodenode); function.add_parameter ((CCodeFormalParameter) param.ccodenode); } + + if (m.access == MemberAccessibility.PUBLIC) { + header_type_member_declaration.append (function.copy ()); + } else { + function.modifiers |= CCodeModifiers.STATIC; + source_type_member_declaration.append (function.copy ()); + } if (m.body != null) { function.block = m.body.ccodenode; @@ -195,6 +287,11 @@ namespace Vala { var cblock = new CCodeBlock (); foreach (Statement stmt in b.statement_list) { + var src = stmt.source_reference; + if (src != null && src.comment != null) { + cblock.add_statement (new CCodeComment (text = src.comment)); + } + if (stmt.ccodenode is CCodeFragment) { foreach (CCodeStatement cstmt in ((CCodeFragment) stmt.ccodenode).children) { cblock.add_statement (cstmt); diff --git a/vala/vala/valacodevisitor.vala b/vala/vala/valacodevisitor.vala index e3b695a..e2ded90 100644 --- a/vala/vala/valacodevisitor.vala +++ b/vala/vala/valacodevisitor.vala @@ -132,6 +132,12 @@ namespace Vala { public virtual void visit_end_foreach_statement (ForeachStatement stmt) { } + public virtual void visit_break_statement (BreakStatement stmt) { + } + + public virtual void visit_continue_statement (ContinueStatement stmt) { + } + public virtual void visit_return_statement (ReturnStatement stmt) { } diff --git a/vala/vala/valacontinuestatement.vala b/vala/vala/valacontinuestatement.vala new file mode 100644 index 0000000..fa7c845 --- /dev/null +++ b/vala/vala/valacontinuestatement.vala @@ -0,0 +1,35 @@ +/* valacontinuestatement.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 + */ + +using GLib; + +namespace Vala { + public class ContinueStatement : Statement { + public static ref ContinueStatement new (SourceReference source) { + return (new ContinueStatement (source_reference = source)); + } + + public override void accept (CodeVisitor visitor) { + visitor.visit_continue_statement (this); + } + } +} diff --git a/vala/vala/valadeclarationstatement.vala b/vala/vala/valadeclarationstatement.vala index ea2c82c..1339e57 100644 --- a/vala/vala/valadeclarationstatement.vala +++ b/vala/vala/valadeclarationstatement.vala @@ -25,7 +25,6 @@ using GLib; namespace Vala { public class DeclarationStatement : Statement { public LocalVariableDeclaration declaration { get; construct; } - public SourceReference source_reference { get; construct; } public static ref DeclarationStatement new (LocalVariableDeclaration decl, SourceReference source) { return (new DeclarationStatement (declaration = decl, source_reference = source)); diff --git a/vala/vala/valaemptystatement.vala b/vala/vala/valaemptystatement.vala index bc2e0c4..633d70b 100644 --- a/vala/vala/valaemptystatement.vala +++ b/vala/vala/valaemptystatement.vala @@ -24,8 +24,6 @@ using GLib; namespace Vala { public class EmptyStatement : Statement { - public SourceReference source_reference { get; construct; } - public static ref EmptyStatement new (SourceReference source) { return (new EmptyStatement (source_reference = source)); } diff --git a/vala/vala/valaenum.vala b/vala/vala/valaenum.vala index b5491b9..fd34dd4 100644 --- a/vala/vala/valaenum.vala +++ b/vala/vala/valaenum.vala @@ -24,9 +24,6 @@ using GLib; namespace Vala { public class Enum : Type_ { - public string name { get; construct; } - public SourceReference source_reference { get; construct; } - public Namespace @namespace; List values; public static ref Enum new (string name, SourceReference source) { @@ -46,9 +43,17 @@ namespace Vala { visitor.visit_end_enum (this); } - + + string cname; public override string get_cname () { - return name; + if (cname == null) { + cname = "%s%s".printf (@namespace.get_cprefix (), name); + } + return cname; + } + + public string get_upper_case_cname () { + return "%s%s".printf (@namespace.get_lower_case_cprefix (), Namespace.camel_case_to_lower_case (name)).up (-1); } public override bool is_reference_type () { diff --git a/vala/vala/valaenumvalue.vala b/vala/vala/valaenumvalue.vala index 4148548..7136f8d 100644 --- a/vala/vala/valaenumvalue.vala +++ b/vala/vala/valaenumvalue.vala @@ -27,6 +27,8 @@ namespace Vala { public string name { get; construct; } public IntegerLiteral value { get; construct; } public SourceReference source_reference { get; construct; } + + Symbol dummy_symbol; // dummy symbol for broken dependency handling public static ref EnumValue new (string name) { return (new EnumValue (name = name)); @@ -39,5 +41,14 @@ namespace Vala { public override void accept (CodeVisitor visitor) { visitor.visit_enum_value (this); } + + string cname; + public string get_cname () { + if (cname == null) { + var en = (Enum) symbol.parent_symbol.node; + cname = "%s_%s".printf (en.get_upper_case_cname (), name); + } + return cname; + } } } diff --git a/vala/vala/valaexpressionstatement.vala b/vala/vala/valaexpressionstatement.vala index 37cf482..8ccb9b8 100644 --- a/vala/vala/valaexpressionstatement.vala +++ b/vala/vala/valaexpressionstatement.vala @@ -25,7 +25,6 @@ using GLib; namespace Vala { public class ExpressionStatement : Statement { public Expression expression { get; construct; } - public SourceReference source_reference { get; construct; } public static ref ExpressionStatement new (Expression expr, SourceReference source) { return (new ExpressionStatement (expression = expr, source_reference = source)); diff --git a/vala/vala/valafield.vala b/vala/vala/valafield.vala index 83e9079..9b544d5 100644 --- a/vala/vala/valafield.vala +++ b/vala/vala/valafield.vala @@ -27,6 +27,7 @@ namespace Vala { public string name { get; construct; } public TypeReference type_reference { get; construct; } public Expression initializer { get; construct; } + public MemberAccessibility access; public SourceReference source_reference { get; construct; } public static ref Field new (string name, TypeReference type, Expression init, SourceReference source) { diff --git a/vala/vala/valaforeachstatement.vala b/vala/vala/valaforeachstatement.vala index bf86a4a..1b19758 100644 --- a/vala/vala/valaforeachstatement.vala +++ b/vala/vala/valaforeachstatement.vala @@ -28,7 +28,6 @@ namespace Vala { public string variable_name { get; construct; } public Expression collection { get; construct; } public Statement body { get; construct; } - public SourceReference source_reference { get; construct; } public static ref ForeachStatement new (TypeReference type, string id, Expression col, Statement body, SourceReference source) { return (new ForeachStatement (type_reference = type, variable_name = id, collection = col, body = body, source_reference = source)); diff --git a/vala/vala/valaforstatement.vala b/vala/vala/valaforstatement.vala index f032b76..5fd32cb 100644 --- a/vala/vala/valaforstatement.vala +++ b/vala/vala/valaforstatement.vala @@ -28,7 +28,6 @@ namespace Vala { public Expression condition { get; construct; } public List iterator { get; construct; } public Statement body { get; construct; } - public SourceReference source_reference { get; construct; } public static ref ForStatement new (List init, Expression cond, List iter, Statement body, SourceReference source) { return (new ForStatement (initializer = init, condition = cond, iterator = iter, body = body, source_reference = source)); diff --git a/vala/vala/valaifstatement.vala b/vala/vala/valaifstatement.vala index 2c550d7..3e731f6 100644 --- a/vala/vala/valaifstatement.vala +++ b/vala/vala/valaifstatement.vala @@ -27,7 +27,6 @@ namespace Vala { public Expression condition { get; construct; } public Statement true_statement { get; construct; } public Statement false_statement { get; construct; } - public SourceReference source_reference { get; construct; } public static ref IfStatement new (Expression cond, Statement true_stmt, Statement false_stmt, SourceReference source) { return (new IfStatement (condition = cond, true_statement = true_stmt, false_statement = false_stmt, source_reference = source)); diff --git a/vala/vala/valanamespace.vala b/vala/vala/valanamespace.vala index 3cd627b..6704b33 100644 --- a/vala/vala/valanamespace.vala +++ b/vala/vala/valanamespace.vala @@ -65,6 +65,10 @@ namespace Vala { en.@namespace = this; } + public ref List get_structs () { + return structs.copy (); + } + public ref List get_classes () { return classes.copy (); } @@ -168,6 +172,15 @@ namespace Vala { this.lower_case_cprefix = cprefix; } + List cheader_filenames; + + public ref List get_cheader_filenames () { + if (cheader_filenames == null) { + cheader_filenames.append (source_reference.file.get_cheader_filename ()); + } + return cheader_filenames.copy (); + } + void process_ccode_attribute (Attribute a) { foreach (NamedArgument arg in a.args) { if (arg.name.collate ("cprefix") == 0) { @@ -186,6 +199,17 @@ namespace Vala { set_lower_case_cprefix (((StringLiteral) lit).eval ()); } } + } else if (arg.name.collate ("cheader_filename") == 0) { + /* this will already be checked during semantic analysis */ + if (arg.argument is LiteralExpression) { + var lit = ((LiteralExpression) arg.argument).literal; + if (lit is StringLiteral) { + var val = ((StringLiteral) lit).eval (); + foreach (string filename in val.split (",", 0)) { + cheader_filenames.append (filename); + } + } + } } } } diff --git a/vala/vala/valaparser.vala b/vala/vala/valaparser.vala index c18ea8c..6138965 100644 --- a/vala/vala/valaparser.vala +++ b/vala/vala/valaparser.vala @@ -25,6 +25,7 @@ using GLib; namespace Vala { public class Parser : CodeVisitor { string comment; + string _file_comment; public void parse (CodeContext context) { context.accept (this); @@ -32,20 +33,35 @@ namespace Vala { public override void visit_begin_source_file (SourceFile source_file) { parse_file (source_file); + source_file.comment = _file_comment; } - public void push_comment (string comment_item) { + public void push_comment (string comment_item, bool file_comment) { if (comment == null) { comment = comment_item; } else { comment = "%s\n%s".printf (comment, comment_item); } + if (file_comment) { + _file_comment = comment; + comment = null; + } } public ref string pop_comment () { - ref string result = comment; + if (comment == null) { + return null; + } + + String result = String.new (comment); comment = null; - return result; + + string index; + while ((index = result.str.chr (-1, '\t')) != null) { + result.erase (result.str.pointer_to_offset (index), 1); + } + + return result.str; } [Import ()] diff --git a/vala/vala/valareturnstatement.vala b/vala/vala/valareturnstatement.vala index eae7e0a..b129393 100644 --- a/vala/vala/valareturnstatement.vala +++ b/vala/vala/valareturnstatement.vala @@ -25,7 +25,6 @@ using GLib; namespace Vala { public class ReturnStatement : Statement { public Expression return_expression { get; construct; } - public SourceReference source_reference { get; construct; } public static ref ReturnStatement new (Expression result, SourceReference source) { return (new ReturnStatement (return_expression = result, source_reference = source)); diff --git a/vala/vala/valasemanticanalyzer.vala b/vala/vala/valasemanticanalyzer.vala index 7cdd42f..2e7f045 100644 --- a/vala/vala/valasemanticanalyzer.vala +++ b/vala/vala/valasemanticanalyzer.vala @@ -26,6 +26,7 @@ namespace Vala { public class SemanticAnalyzer : CodeVisitor { Symbol root_symbol; Symbol current_symbol; + SourceFile current_source_file; List current_using_directives; TypeReference dummy; // required for broken dependency handlind @@ -37,6 +38,7 @@ namespace Vala { } public override void visit_begin_source_file (SourceFile file) { + current_source_file = file; current_using_directives = file.get_using_directives (); } @@ -54,6 +56,10 @@ namespace Vala { public override void visit_begin_class (Class cl) { current_symbol = cl.symbol; + + if (cl.base_class != null) { + current_source_file.add_symbol_dependency (cl.base_class.symbol, SourceFileDependencyType.HEADER_FULL); + } } public override void visit_end_class (Class cl) { @@ -68,14 +74,40 @@ namespace Vala { current_symbol = current_symbol.parent_symbol; } + public override void visit_field (Field f) { + if (f.access == MemberAccessibility.PUBLIC) { + if (f.type_reference.type != null) { + /* is null if it references a type parameter */ + current_source_file.add_symbol_dependency (f.type_reference.type.symbol, SourceFileDependencyType.HEADER_SHALLOW); + } + } else { + if (f.type_reference.type != null) { + /* is null if it references a type parameter */ + current_source_file.add_symbol_dependency (f.type_reference.type.symbol, SourceFileDependencyType.SOURCE); + } + } + } + public override void visit_begin_method (Method m) { current_symbol = m.symbol; + + if (m.return_type.type != null) { + /* is null if it is void or a reference to a type parameter */ + current_source_file.add_symbol_dependency (m.return_type.type.symbol, SourceFileDependencyType.HEADER_SHALLOW); + } } public override void visit_end_method (Method m) { current_symbol = current_symbol.parent_symbol; } + public override void visit_formal_parameter (FormalParameter p) { + if (p.type_reference.type != null) { + /* is null if it references a type parameter */ + current_source_file.add_symbol_dependency (p.type_reference.type.symbol, SourceFileDependencyType.HEADER_SHALLOW); + } + } + public override void visit_named_argument (NamedArgument n) { } @@ -92,12 +124,20 @@ namespace Vala { /* var type */ decl.type_reference = decl.initializer.static_type; } + + if (decl.type_reference.type != null) { + current_source_file.add_symbol_dependency (decl.type_reference.type.symbol, SourceFileDependencyType.SOURCE); + } decl.symbol = new Symbol (node = decl); current_symbol.add (decl.name, decl.symbol); } public override void visit_begin_foreach_statement (ForeachStatement stmt) { + if (stmt.type_reference.type != null) { + current_source_file.add_symbol_dependency (stmt.type_reference.type.symbol, SourceFileDependencyType.SOURCE); + } + stmt.symbol = new Symbol (node = stmt.type_reference); current_symbol.add (stmt.variable_name, stmt.symbol); } @@ -181,6 +221,8 @@ namespace Vala { stderr.printf ("symbol ´%s´ not found\n", expr.name); } + current_source_file.add_symbol_dependency (expr.symbol_reference, SourceFileDependencyType.SOURCE); + expr.static_type = get_static_type_for_node (expr.symbol_reference.node); } @@ -203,6 +245,8 @@ namespace Vala { stderr.printf ("%s: member ´%s´ not found\n", expr.source_reference.to_string (), expr.member_name); } + current_source_file.add_symbol_dependency (expr.symbol_reference, SourceFileDependencyType.SOURCE); + expr.static_type = get_static_type_for_node (expr.symbol_reference.node); } @@ -212,10 +256,14 @@ namespace Vala { } public override void visit_object_creation_expression (ObjectCreationExpression expr) { + current_source_file.add_symbol_dependency (expr.type_reference.type.symbol, SourceFileDependencyType.SOURCE); + expr.static_type = expr.type_reference; } public override void visit_cast_expression (CastExpression expr) { + current_source_file.add_symbol_dependency (expr.type_reference.type.symbol, SourceFileDependencyType.SOURCE); + expr.static_type = expr.type_reference; } } diff --git a/vala/vala/valasourcefile.vala b/vala/vala/valasourcefile.vala index c05161c..7b19fc0 100644 --- a/vala/vala/valasourcefile.vala +++ b/vala/vala/valasourcefile.vala @@ -30,9 +30,13 @@ namespace Vala { List using_directives; - Namespace global_namespace = new Namespace (); + Namespace global_namespace; List namespaces; + private void init () { + global_namespace = new Namespace (source_reference = new SourceReference (file = this)); + } + public void add_using_directive (NamespaceReference ns) { using_directives.append (ns); } @@ -49,6 +53,10 @@ namespace Vala { return global_namespace; } + public ref List get_namespaces () { + return namespaces.copy (); + } + public void accept (CodeVisitor visitor) { visitor.visit_begin_source_file (this); @@ -65,14 +73,74 @@ namespace Vala { visitor.visit_end_source_file (this); } - public ref string get_cheader_filename () { - var basename = filename.ndup (filename.len (-1) - ".vala".len (-1)); - return "%s.h".printf (basename); + string cheader_filename = null; + + public string get_cheader_filename () { + if (cheader_filename == null) { + var basename = filename.ndup (filename.len (-1) - ".vala".len (-1)); + cheader_filename = "%s.h".printf (basename); + } + return cheader_filename; } - public ref string get_csource_filename () { - var basename = filename.ndup (filename.len (-1) - ".vala".len (-1)); - return "%s.c".printf (basename); + string csource_filename = null; + + public string get_csource_filename () { + if (csource_filename == null) { + var basename = filename.ndup (filename.len (-1) - ".vala".len (-1)); + csource_filename = "%s.c".printf (basename); + } + return csource_filename; + } + + public List header_external_includes; + public List header_internal_includes; + public List source_includes; + + public List header_internal_full_dependencies; + public List header_internal_dependencies; + public SourceFileCycle cycle; // null = not in a cycle; if not null, don't write typedefs + public bool is_cycle_head; // if true, write typedefs for all types in the cycle + public int mark; // used for cycle detection, 0 = white (not yet visited), 1 = gray (currently visiting), 2 = black (already visited) + + public void add_symbol_dependency (Symbol sym, SourceFileDependencyType dep_type) { + Type_ t; + + if (sym.node is Type_) { + t = (Type_) sym.node; + } else if (sym.node is Method) { + if (sym.parent_symbol.node is Type_) { + t = (Type_) sym.parent_symbol.node; + } else { + return; + } + } else { + return; + } + + if (dep_type == SourceFileDependencyType.SOURCE) { + source_includes.concat (t.get_cheader_filenames ()); + return; + } + + if (t.source_reference.file.pkg) { + /* external package */ + header_external_includes.concat (t.get_cheader_filenames ()); + return; + } + + if (dep_type == SourceFileDependencyType.HEADER_FULL || !t.is_reference_type ()) { + header_internal_includes.concat (t.get_cheader_filenames ()); + header_internal_full_dependencies.append (t.source_reference.file); + } + + header_internal_dependencies.append (t.source_reference.file); } } + + public enum SourceFileDependencyType { + HEADER_FULL, + HEADER_SHALLOW, + SOURCE + } } diff --git a/vala/vala/valasourcefilecycle.vala b/vala/vala/valasourcefilecycle.vala new file mode 100644 index 0000000..f7762a1 --- /dev/null +++ b/vala/vala/valasourcefilecycle.vala @@ -0,0 +1,30 @@ +/* valasourcefilecycle.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 + */ + +using GLib; + +namespace Vala { + public class SourceFileCycle { + public List files; + public SourceFile head; + } +} diff --git a/vala/vala/valastatement.vala b/vala/vala/valastatement.vala index 3e01a91..0a6cc2e 100644 --- a/vala/vala/valastatement.vala +++ b/vala/vala/valastatement.vala @@ -24,5 +24,6 @@ using GLib; namespace Vala { public abstract class Statement : CodeNode { + public SourceReference source_reference { get; construct; } } } diff --git a/vala/vala/valastruct.vala b/vala/vala/valastruct.vala index 9d5db89..fa40910 100644 --- a/vala/vala/valastruct.vala +++ b/vala/vala/valastruct.vala @@ -24,10 +24,6 @@ using GLib; namespace Vala { public class Struct : Type_ { - public string name { get; construct; } - public SourceReference source_reference { get; construct; } - public weak Namespace @namespace; - List type_parameters; List constants; List fields; @@ -55,6 +51,8 @@ namespace Vala { } public void add_method (Method m) { + return_if_fail (m != null); + methods.append (m); } @@ -116,7 +114,7 @@ namespace Vala { public override ref string get_upper_case_cname (string infix) { return get_lower_case_cname (infix).up (-1); } - + public override bool is_reference_type () { return reference_type; } @@ -131,6 +129,17 @@ namespace Vala { set_cname (((StringLiteral) lit).eval ()); } } + } else if (arg.name.collate ("cheader_filename") == 0) { + /* this will already be checked during semantic analysis */ + if (arg.argument is LiteralExpression) { + var lit = ((LiteralExpression) arg.argument).literal; + if (lit is StringLiteral) { + var val = ((StringLiteral) lit).eval (); + foreach (string filename in val.split (",", 0)) { + cheader_filenames.append (filename); + } + } + } } } } diff --git a/vala/vala/valatype.vala b/vala/vala/valatype.vala index 0c987ea..66b0361 100644 --- a/vala/vala/valatype.vala +++ b/vala/vala/valatype.vala @@ -24,8 +24,20 @@ using GLib; namespace Vala { public abstract class Type_ : CodeNode { + public string name { get; construct; } + public SourceReference source_reference { get; construct; } + public Namespace @namespace; + public abstract string get_cname (); public abstract bool is_reference_type (); public abstract string get_upper_case_cname (string infix); + + public List cheader_filenames; + public ref List get_cheader_filenames () { + if (cheader_filenames == null) { + cheader_filenames = @namespace.get_cheader_filenames (); + } + return cheader_filenames.copy (); + } } } diff --git a/vala/vala/valatypereference.vala b/vala/vala/valatypereference.vala index ea2a8a4..1511eff 100644 --- a/vala/vala/valatypereference.vala +++ b/vala/vala/valatypereference.vala @@ -91,6 +91,10 @@ namespace Vala { } public ref string get_cname () { + if (type == null && type_parameter == null) { + return "void"; + } + string ptr; string arr; if (type_parameter == null && !type.is_reference_type () && !is_ref) { diff --git a/vala/vala/valawhilestatement.vala b/vala/vala/valawhilestatement.vala index 932e9b2..61a9d50 100644 --- a/vala/vala/valawhilestatement.vala +++ b/vala/vala/valawhilestatement.vala @@ -26,7 +26,6 @@ namespace Vala { public class WhileStatement : Statement { public Expression condition { get; construct; } public Statement body { get; construct; } - public SourceReference source_reference { get; construct; } public static ref WhileStatement new (Expression cond, Statement body, SourceReference source) { return (new WhileStatement (condition = cond, body = body, source_reference = source)); diff --git a/vala/valac/generator.c b/vala/valac/generator.c index b97c9bc..dc1eace 100644 --- a/vala/valac/generator.c +++ b/vala/valac/generator.c @@ -372,6 +372,7 @@ vala_code_generator_find_static_type_of_expression (ValaCodeGenerator *generator break; case VALA_EXPRESSION_TYPE_INVOCATION: vala_code_generator_find_static_type_of_expression (generator, expr->invocation.call); + expr->array_type = expr->invocation.call->static_type_symbol->method->return_type->array_type; expr->static_type_symbol = expr->invocation.call->static_type_symbol->method->return_type->symbol; break; case VALA_EXPRESSION_TYPE_IS: @@ -685,7 +686,12 @@ vala_code_generator_process_member_access (ValaCodeGenerator *generator, ValaExp if (!expr->field->is_struct_field) { fprintf (generator->c_file, ")"); } - fprintf (generator->c_file, "->%s", expr->member_access.right); + + if ((expr->field->modifiers & VALA_MODIFIER_PRIVATE) != 0) { + fprintf (generator->c_file, "->priv->%s", expr->member_access.right); + } else { + fprintf (generator->c_file, "->%s", expr->member_access.right); + } } } } @@ -1777,6 +1783,7 @@ vala_code_generator_process_source_file (ValaCodeGenerator *generator, ValaSourc fprintf (generator->h_file, "\n"); fprintf (generator->h_file, "#include \n"); + fprintf (generator->h_file, "#include \n"); fprintf (generator->h_file, "#include \n"); fprintf (generator->h_file, "\n");