support file comments, BREAK, CONTINUE support break and continue, add
authorJürg Billeter <j@bitron.ch>
Sun, 21 May 2006 11:51:46 +0000 (11:51 +0000)
committerJürg Billeter <juergbi@src.gnome.org>
Sun, 21 May 2006 11:51:46 +0000 (11:51 +0000)
2006-05-21  Jürg Billeter  <j@bitron.ch>

* 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

39 files changed:
vala/ChangeLog
vala/bindings/glib-2.0.vala
vala/ccode/valaccodeblock.vala
vala/ccode/valaccodeenum.vala
vala/ccode/valaccodefunction.vala
vala/ccode/valaccodenewline.vala [new file with mode: 0644]
vala/ccode/valaccodeoncesection.vala [new file with mode: 0644]
vala/ccode/valaccodewriter.vala
vala/vala/parser.y
vala/vala/scanner.l
vala/vala/vala.h
vala/vala/valablock.vala
vala/vala/valabreakstatement.vala [new file with mode: 0644]
vala/vala/valaclass.vala
vala/vala/valacodecontext.vala
vala/vala/valacodegenerator.vala
vala/vala/valacodevisitor.vala
vala/vala/valacontinuestatement.vala [new file with mode: 0644]
vala/vala/valadeclarationstatement.vala
vala/vala/valaemptystatement.vala
vala/vala/valaenum.vala
vala/vala/valaenumvalue.vala
vala/vala/valaexpressionstatement.vala
vala/vala/valafield.vala
vala/vala/valaforeachstatement.vala
vala/vala/valaforstatement.vala
vala/vala/valaifstatement.vala
vala/vala/valanamespace.vala
vala/vala/valaparser.vala
vala/vala/valareturnstatement.vala
vala/vala/valasemanticanalyzer.vala
vala/vala/valasourcefile.vala
vala/vala/valasourcefilecycle.vala [new file with mode: 0644]
vala/vala/valastatement.vala
vala/vala/valastruct.vala
vala/vala/valatype.vala
vala/vala/valatypereference.vala
vala/vala/valawhilestatement.vala
vala/valac/generator.c

index 423f5fc..7f9dccd 100644 (file)
@@ -1,3 +1,47 @@
+2006-05-21  Jürg Billeter  <j@bitron.ch>
+
+       * 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  <j@bitron.ch>
 
        * vala/valacodegenerator.vala: include header file in corresponding
index f06c771..2ec8d53 100644 (file)
  *     Jürg Billeter <j@bitron.ch>
  */
 
-[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<G> nth_prev (uint n);
                
+               public List<G> find_custom (G data, CompareFunc func);
+               
                public List<G> find (G data);
                public int position (List<G> llink);
                public int index (G data);
@@ -277,6 +297,12 @@ namespace GLib {
                public List<G> prev;
        }
        
+       public struct CompareFunc {
+       }
+       
+       [CCode (cname = "strcmp")]
+       public static GLib.CompareFunc strcmp;
+       
        [ReferenceType ()]
        public struct HashTable<K,V> {
                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;
index ae79a7d..b82260e 100644 (file)
@@ -24,15 +24,16 @@ using GLib;
 
 namespace Vala {
        public class CCodeBlock : CCodeStatement {
-               ref List<ref CCodeStatement> statements;
+               List<CCodeNode> 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);
                                }
index 8fca688..6ccd1ea 100644 (file)
@@ -28,20 +28,32 @@ namespace Vala {
                List<string> 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 ();
                }
        }
 }
index afe5e88..3f2e104 100644 (file)
@@ -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 (file)
index 0000000..235d78b
--- /dev/null
@@ -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 <j@bitron.ch>
+ */
+
+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 (file)
index 0000000..5280d4d
--- /dev/null
@@ -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 <j@bitron.ch>
+ */
+
+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 ();
+               }
+       }
+}
index 9467ea3..cac8c52 100644 (file)
@@ -74,7 +74,9 @@ namespace Vala {
                }
                
                public void write_comment (string text) {
+                       write_indent ();
                        stream.printf ("/*%s*/", text);
+                       write_newline ();
                }
        }
 }
index 8a59629..33ffbd0 100644 (file)
@@ -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 <list> statement_expression_list
 %type <statement> foreach_statement
 %type <statement> jump_statement
+%type <statement> break_statement
+%type <statement> continue_statement
 %type <statement> return_statement
 %type <namespace> namespace_declaration
 %type <class> 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;
+               }
          }
        ;
 
index 0eeaf6b..396f822 100644 (file)
@@ -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); }
-<IN_COMMENT>[^*\n]*            { uploc; yymore (); }
-<IN_COMMENT>"*"+[^*/\n]*               { uploc; yymore (); }
+"/*"                           { uploc; file_comment = (yylineno == 1); BEGIN (IN_COMMENT); }
+<IN_COMMENT>"*/"               { uploc; BEGIN (INITIAL); yytext[strlen (yytext) - 2] = '\0'; vala_parser_push_comment (parser, g_strdup (yytext), file_comment); }
+<IN_COMMENT>[^*\n]+            { uploc; yymore (); }
+<IN_COMMENT>"*"                        { uploc; yymore (); }
 <IN_COMMENT>\n                 { yylloc->first_line = yylloc->last_line = yylineno; yylloc->first_column = 1; yylloc->last_column = 0; yymore (); }
-<IN_COMMENT>"*/"               { 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; }
index a459120..4655928 100644 (file)
@@ -3,12 +3,14 @@
 #include <vala/valabinaryexpression.h>
 #include <vala/valablock.h>
 #include <vala/valabooleanliteral.h>
+#include <vala/valabreakstatement.h>
 #include <vala/valacastexpression.h>
 #include <vala/valacharacterliteral.h>
 #include <vala/valaclass.h>
 #include <vala/valacodecontext.h>
 #include <vala/valaconditionalexpression.h>
 #include <vala/valaconstant.h>
+#include <vala/valacontinuestatement.h>
 #include <vala/valadeclarationstatement.h>
 #include <vala/valaemptystatement.h>
 #include <vala/valaenum.h>
index dcc057f..3866688 100644 (file)
@@ -25,7 +25,6 @@ using GLib;
 namespace Vala {
        public class Block : Statement {
                public List<Statement> statement_list { get; construct; }
-               public SourceReference source_reference { get; construct; }
                
                public static ref Block new (List<Statement> 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 (file)
index 0000000..6aff3be
--- /dev/null
@@ -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 <j@bitron.ch>
+ */
+
+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);
+               }
+       }
+}
index 77a8a46..f45e170 100644 (file)
@@ -24,7 +24,6 @@ using GLib;
 
 namespace Vala {
        public class Class : Struct {
-               public SourceReference source_reference { get; construct; }
                public List<TypeReference> base_types;
                public Class base_class;
                
index 8d625e1..55a322a 100644 (file)
@@ -27,6 +27,8 @@ namespace Vala {
                List<SourceFile> source_files;
                public Symbol root = new Symbol ();
                
+               List<SourceFileCycle> cycles;
+               
                public ref List<SourceFile> 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<SourceFile> 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;
+               }
        }
 }
index 26af22a..d73d581 100644 (file)
@@ -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<string> 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);
index e3b695a..e2ded90 100644 (file)
@@ -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 (file)
index 0000000..fa7c845
--- /dev/null
@@ -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 <j@bitron.ch>
+ */
+
+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);
+               }
+       }
+}
index ea2c82c..1339e57 100644 (file)
@@ -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));
index bc2e0c4..633d70b 100644 (file)
@@ -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));
                }
index b5491b9..fd34dd4 100644 (file)
@@ -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<EnumValue> 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 () {
index 4148548..7136f8d 100644 (file)
@@ -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;
+               }
        }
 }
index 37cf482..8ccb9b8 100644 (file)
@@ -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));
index 83e9079..9b544d5 100644 (file)
@@ -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) {
index bf86a4a..1b19758 100644 (file)
@@ -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));
index f032b76..5fd32cb 100644 (file)
@@ -28,7 +28,6 @@ namespace Vala {
                public Expression condition { get; construct; }
                public List<Expression> iterator { get; construct; }
                public Statement body { get; construct; }
-               public SourceReference source_reference { get; construct; }
 
                public static ref ForStatement new (List<StatementExpression> init, Expression cond, List<StatementExpression> iter, Statement body, SourceReference source) {
                        return (new ForStatement (initializer = init, condition = cond, iterator = iter, body = body, source_reference = source));
index 2c550d7..3e731f6 100644 (file)
@@ -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));
index 3cd627b..6704b33 100644 (file)
@@ -65,6 +65,10 @@ namespace Vala {
                        en.@namespace = this;
                }
 
+               public ref List<Struct> get_structs () {
+                       return structs.copy ();
+               }
+
                public ref List<Class> get_classes () {
                        return classes.copy ();
                }
@@ -168,6 +172,15 @@ namespace Vala {
                        this.lower_case_cprefix = cprefix;
                }
                
+               List<string> cheader_filenames;
+               
+               public ref List<string> 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);
+                                                       }
+                                               }
+                                       }
                                }
                        }
                }
index c18ea8c..6138965 100644 (file)
@@ -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 ()]
index eae7e0a..b129393 100644 (file)
@@ -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));
index 7cdd42f..2e7f045 100644 (file)
@@ -26,6 +26,7 @@ namespace Vala {
        public class SemanticAnalyzer : CodeVisitor {
                Symbol root_symbol;
                Symbol current_symbol;
+               SourceFile current_source_file;
                
                List<NamespaceReference> 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;
                }
        }
index c05161c..7b19fc0 100644 (file)
@@ -30,9 +30,13 @@ namespace Vala {
                
                List<NamespaceReference> using_directives;
 
-               Namespace global_namespace = new Namespace ();
+               Namespace global_namespace;
                List<Namespace> 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<Namespace> 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<string> header_external_includes;
+               public List<string> header_internal_includes;
+               public List<string> source_includes;
+               
+               public List<SourceFile> header_internal_full_dependencies;
+               public List<SourceFile> 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 (file)
index 0000000..f7762a1
--- /dev/null
@@ -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 <j@bitron.ch>
+ */
+
+using GLib;
+
+namespace Vala {
+       public class SourceFileCycle {
+               public List<SourceFile> files;
+               public SourceFile head;
+       }
+}
index 3e01a91..0a6cc2e 100644 (file)
@@ -24,5 +24,6 @@ using GLib;
 
 namespace Vala {
        public abstract class Statement : CodeNode {
+               public SourceReference source_reference { get; construct; }
        }
 }
index 9d5db89..fa40910 100644 (file)
@@ -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<string> type_parameters;
                List<Constant> constants;
                List<Field> 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);
+                                                       }
+                                               }
+                                       }
                                }
                        }
                }
index 0c987ea..66b0361 100644 (file)
@@ -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<string> cheader_filenames;
+               public ref List<string> get_cheader_filenames () {
+                       if (cheader_filenames == null) {
+                               cheader_filenames = @namespace.get_cheader_filenames ();
+                       }
+                       return cheader_filenames.copy ();
+               }
        }
 }
index ea2a8a4..1511eff 100644 (file)
@@ -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) {
index 932e9b2..61a9d50 100644 (file)
@@ -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));
index b97c9bc..dc1eace 100644 (file)
@@ -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 <stdio.h>\n");
+       fprintf (generator->h_file, "#include <string.h>\n");
        fprintf (generator->h_file, "#include <glib-object.h>\n");
        fprintf (generator->h_file, "\n");