add basic support for flags, fixes bug 434511
authorJürg Billeter <j@bitron.ch>
Mon, 30 Apr 2007 09:27:07 +0000 (09:27 +0000)
committerJürg Billeter <juergbi@src.gnome.org>
Mon, 30 Apr 2007 09:27:07 +0000 (09:27 +0000)
2007-04-30  Jürg Billeter  <j@bitron.ch>

* vala/parser.y, vala/valasymbolbuilder.vala,
  vala/valaattributeprocessor.vala, vala/valasemanticanalyzer.vala,
  vala/valacodegenerator.vala, vala/valainterfacewriter.vala,
  vala/valaflags.vala: add basic support for flags, fixes bug 434511

svn path=/trunk/; revision=292

vala/ChangeLog
vala/vala/parser.y
vala/vala/valaattributeprocessor.vala
vala/vala/valacodegenerator.vala
vala/vala/valaenum.vala
vala/vala/valaflags.vala
vala/vala/valainterfacewriter.vala
vala/vala/valasemanticanalyzer.vala
vala/vala/valasymbolbuilder.vala

index 6c3d2d1..c7971b5 100644 (file)
@@ -1,5 +1,12 @@
 2007-04-30  Jürg Billeter  <j@bitron.ch>
 
+       * vala/parser.y, vala/valasymbolbuilder.vala,
+         vala/valaattributeprocessor.vala, vala/valasemanticanalyzer.vala,
+         vala/valacodegenerator.vala, vala/valainterfacewriter.vala,
+         vala/valaflags.vala: add basic support for flags, fixes bug 434511
+
+2007-04-30  Jürg Billeter  <j@bitron.ch>
+
        * vala/valasemanticanalyzer.vala: check that void return values are not
          used, fixes bug 434503
 
index 229683c..06e69a3 100644 (file)
@@ -332,6 +332,10 @@ static void yyerror (YYLTYPE *locp, ValaParser *parser, const char *msg);
 %type <list> enum_member_declarations
 %type <enum_value> enum_member_declaration
 %type <flags> flags_declaration
+%type <list> flags_body
+%type <list> opt_flags_member_declarations
+%type <list> flags_member_declarations
+%type <flags_value> flags_member_declaration
 %type <callback> callback_declaration
 %type <constant> constant_declaration
 %type <field> field_declaration
@@ -3155,29 +3159,62 @@ flags_declaration
                        name = $6;
                }
                
+               GList *l;
                ValaSourceReference *src = src_com(@5, $1);
                $$ = vala_flags_new (name, src);
                g_free (name);
                g_object_unref (src);
+
+               VALA_CODE_NODE($$)->attributes = $2;
+
+               if ($3 != 0) {
+                       VALA_DATA_TYPE($$)->access = $3;
+               }
+               for (l = $7; l != NULL; l = l->next) {
+                       vala_flags_add_value ($$, l->data);
+                       g_object_unref (l->data);
+               }
          }
        ;
 
 flags_body
        : OPEN_BRACE opt_flags_member_declarations CLOSE_BRACE
+         {
+               $$ = $2;
+         }
        ;
 
 opt_flags_member_declarations
        : /* empty */
-       | flags_member_declarations
+         {
+               $$ = NULL;
+         }
+       | flags_member_declarations opt_comma
        ;
 
 flags_member_declarations
        : flags_member_declaration
+         {
+               $$ = g_list_append (NULL, $1);
+         }
        | flags_member_declarations COMMA flags_member_declaration
+         {
+               $$ = g_list_append ($1, $3);
+         }
        ;
 
 flags_member_declaration
        : opt_attributes identifier
+         {
+               $$ = vala_flags_value_new ($2);
+               g_free ($2);
+         }
+       | opt_attributes identifier ASSIGN expression
+         {
+               $$ = vala_flags_value_new_with_value ($2, $4);
+               g_free ($2);
+               g_object_unref ($4);
+         }
        ;
 
 callback_declaration
index f1fa963..2c4901f 100644 (file)
@@ -56,6 +56,10 @@ public class Vala.AttributeProcessor : CodeVisitor {
                en.process_attributes ();
        }
 
+       public override void visit_begin_flags (Flags! fl) {
+               fl.process_attributes ();
+       }
+
        public override void visit_begin_method (Method! m) {
                m.process_attributes ();
        }
index 4b79237..8a88071 100644 (file)
@@ -1065,7 +1065,7 @@ public class Vala.CodeGenerator : CodeVisitor {
                
                source_type_member_definition.append (base_init);
        }
-       
+
        public override void visit_begin_enum (Enum! en) {
                cenum = new CCodeEnum (en.get_cname ());
 
@@ -1086,6 +1086,26 @@ public class Vala.CodeGenerator : CodeVisitor {
                cenum.add_value (ev.get_cname (), val);
        }
 
+       public override void visit_begin_flags (Flags! fl) {
+               cenum = new CCodeEnum (fl.get_cname ());
+
+               if (fl.source_reference.comment != null) {
+                       header_type_definition.append (new CCodeComment (fl.source_reference.comment));
+               }
+               header_type_definition.append (cenum);
+       }
+
+       public override void visit_flags_value (FlagsValue! fv) {
+               string val;
+               if (fv.value is LiteralExpression) {
+                       var lit = ((LiteralExpression) fv.value).literal;
+                       if (lit is IntegerLiteral) {
+                               val = ((IntegerLiteral) lit).value;
+                       }
+               }
+               cenum.add_value (fv.get_cname (), val);
+       }
+
        public override void visit_end_callback (Callback! cb) {
                var cfundecl = new CCodeFunctionDeclarator (cb.get_cname ());
                foreach (FormalParameter param in cb.get_parameters ()) {
index 341f450..a759c00 100644 (file)
@@ -148,5 +148,5 @@ public class Vala.Enum : DataType {
 
        public override string get_default_value () {
                return "0";
-       }       
+       }
 }
index f14ebff..d47cb8b 100644 (file)
@@ -1,6 +1,6 @@
 /* valaflags.vala
  *
- * Copyright (C) 2006  Jürg Billeter
+ * Copyright (C) 2006-2007  Jürg Billeter
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -26,8 +26,9 @@ using GLib;
  * Represents a flags declaration in the source code.
  */
 public class Vala.Flags : DataType {
-       List<FlagsValue> values;
-       string cname;
+       private List<FlagsValue> values;
+       private string cname;
+       private string cprefix;
 
        /**
         * Creates a new flags.
@@ -36,11 +37,9 @@ public class Vala.Flags : DataType {
         * @param source reference to source code
         * @return       newly created flags
         */
-       public Flags (string! _name, SourceReference source) {
-               name = _name;
-               source_reference = source;
+       public Flags (construct string! name, construct SourceReference source_reference = null) {
        }
-       
+
        /**
         * Appends the specified flags value to the list of values.
         *
@@ -49,10 +48,10 @@ public class Vala.Flags : DataType {
        public void add_value (FlagsValue! value) {
                values.append (value);
        }
-       
+
        public override void accept (CodeVisitor! visitor) {
                visitor.visit_begin_flags (this);
-               
+
                foreach (FlagsValue value in values) {
                        value.accept (visitor);
                }
@@ -66,7 +65,7 @@ public class Vala.Flags : DataType {
                }
                return cname;
        }
-       
+
        public override ref string get_upper_case_cname (string infix) {
                return "%s%s".printf (@namespace.get_lower_case_cprefix (), Namespace.camel_case_to_lower_case (name)).up ();
        }
@@ -75,6 +74,64 @@ public class Vala.Flags : DataType {
                return false;
        }
 
+       private void set_cname (string! cname) {
+               this.cname = cname;
+       }
+
+       /**
+        * Returns the string to be prepended to the name of members of this
+        * enum when used in C code.
+        *
+        * @return the prefix to be used in C code
+        */
+       public string! get_cprefix () {
+               if (cprefix == null) {
+                       cprefix = "%s_".printf (get_upper_case_cname (null));
+               }
+               return cprefix;
+       }
+
+       /**
+        * Sets the string to be prepended to the name of members of this enum
+        * when used in C code.
+        *
+        * @param cprefix the prefix to be used in C code
+        */
+       public void set_cprefix (string! cprefix) {
+               this.cprefix = cprefix;
+       }
+
+       private void process_ccode_attribute (Attribute! a) {
+               if (a.has_argument ("cname")) {
+                       set_cname (a.get_string ("cname"));
+               }
+               if (a.has_argument ("cprefix")) {
+                       set_cprefix (a.get_string ("cprefix"));
+               }
+               if (a.has_argument ("cheader_filename")) {
+                       var val = a.get_string ("cheader_filename");
+                       foreach (string filename in val.split (",")) {
+                               add_cheader_filename (filename);
+                       }
+               }
+       }
+
+       /**
+        * Process all associated attributes.
+        */
+       public void process_attributes () {
+               foreach (Attribute a in attributes) {
+                       if (a.name == "CCode") {
+                               process_ccode_attribute (a);
+                       }
+               }
+       }
+
+       public override string get_type_id () {
+               // FIXME: use GType-registered flags
+               return "G_TYPE_INT";
+       }
+
        public override string get_marshaller_type_name () {
                return "FLAGS";
        }
@@ -82,7 +139,7 @@ public class Vala.Flags : DataType {
        public override string get_get_value_function () {
                return "g_value_get_flags";
        }
-       
+
        public override string get_set_value_function () {
                return "g_value_set_flags";
        }
index dbee461..e518ffc 100644 (file)
@@ -199,10 +199,10 @@ public class Vala.InterfaceWriter : CodeVisitor {
                        internal_scope = true;
                        return;
                }
-               
+
                write_indent ();
                write_string ("[CCode (cprefix = \"%s\")]".printf (en.get_cprefix ()));
-               
+
                write_indent ();
                write_string ("public enum ");
                write_identifier (en.name);
@@ -214,7 +214,7 @@ public class Vala.InterfaceWriter : CodeVisitor {
                        internal_scope = false;
                        return;
                }
-               
+
                write_end_block ();
                write_newline ();
        }
@@ -223,13 +223,49 @@ public class Vala.InterfaceWriter : CodeVisitor {
                if (internal_scope) {
                        return;
                }
-               
+
                write_indent ();
                write_identifier (ev.name);
                write_string (",");
                write_newline ();
        }
 
+       public override void visit_begin_flags (Flags! fl) {
+               if (fl.access == MemberAccessibility.PRIVATE) {
+                       internal_scope = true;
+                       return;
+               }
+
+               write_indent ();
+               write_string ("[CCode (cprefix = \"%s\")]".printf (fl.get_cprefix ()));
+
+               write_indent ();
+               write_string ("public flags ");
+               write_identifier (fl.name);
+               write_begin_block ();
+       }
+
+       public override void visit_end_flags (Flags! fl) {
+               if (fl.access == MemberAccessibility.PRIVATE) {
+                       internal_scope = false;
+                       return;
+               }
+
+               write_end_block ();
+               write_newline ();
+       }
+
+       public override void visit_flags_value (FlagsValue! fv) {
+               if (internal_scope) {
+                       return;
+               }
+
+               write_indent ();
+               write_identifier (fv.name);
+               write_string (",");
+               write_newline ();
+       }
+
        public override void visit_constant (Constant! c) {
                if (internal_scope) {
                        return;
index 547dc87..39e5582 100644 (file)
@@ -957,7 +957,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                } else if (node is VariableDeclarator) {
                        var decl = (VariableDeclarator) node;
                        return decl.type_reference;
-               } else if (node is EnumValue) {
+               } else if (node is EnumValue || node is FlagsValue) {
                        var type = new TypeReference ();
                        type.data_type = (DataType) node.symbol.parent_symbol.node;
                        return type;
index 9336241..33548a1 100644 (file)
@@ -134,21 +134,21 @@ public class Vala.SymbolBuilder : CodeVisitor {
                
                current_symbol = current_symbol.parent_symbol;
        }
-       
+
        public override void visit_begin_enum (Enum! en) {
                if (add_symbol (en.name, en) == null) {
                        return;
                }
-               
+
                current_symbol = en.symbol;
        }
-       
+
        public override void visit_end_enum (Enum! en) {
                if (en.error) {
                        /* skip enums with errors */
                        return;
                }
-               
+
                current_symbol = current_symbol.parent_symbol;
        }
 
@@ -156,7 +156,29 @@ public class Vala.SymbolBuilder : CodeVisitor {
                ev.symbol = new Symbol (ev);
                current_symbol.add (ev.name, ev.symbol);
        }
-       
+
+       public override void visit_begin_flags (Flags! fl) {
+               if (add_symbol (fl.name, fl) == null) {
+                       return;
+               }
+               
+               current_symbol = fl.symbol;
+       }
+
+       public override void visit_end_flags (Flags! fl) {
+               if (fl.error) {
+                       /* skip flags with errors */
+                       return;
+               }
+
+               current_symbol = current_symbol.parent_symbol;
+       }
+
+       public override void visit_flags_value (FlagsValue! fv) {
+               fv.symbol = new Symbol (fv);
+               current_symbol.add (fv.name, fv.symbol);
+       }
+
        public override void visit_begin_callback (Callback! cb) {
                if (add_symbol (cb.name, cb) == null) {
                        return;