Separate errordomain from enum declaration, fixes bug 512616
authorJuerg Billeter <j@bitron.ch>
Thu, 7 Feb 2008 15:48:07 +0000 (15:48 +0000)
committerJürg Billeter <juergbi@src.gnome.org>
Thu, 7 Feb 2008 15:48:07 +0000 (15:48 +0000)
2008-02-07  Juerg Billeter  <j@bitron.ch>
* vala/Makefile.am, vala/parser.y, vala/scanner.l, vala/vala.h,
  vala/valacodecontext.vala, vala/valacodegenerator.vala,
  vala/valacodevisitor.vala, vala/valaenum.vala,
  vala/valaerrorcode.vala, vala/valaerrordomain.vala,
  vala/valaerrortype.vala, vala/valainterfacewriter.vala,
  vala/valanamespace.vala, vala/valasemanticanalyzer.vala,
  gobject/valaccodegenerator.vala, tests/exceptions.vala:

  Separate errordomain from enum declaration, fixes bug 512616

svn path=/trunk/; revision=989

17 files changed:
ChangeLog
gobject/valaccodegenerator.vala
tests/exceptions.vala
vala/Makefile.am
vala/parser.y
vala/scanner.l
vala/vala.h
vala/valacodecontext.vala
vala/valacodegenerator.vala
vala/valacodevisitor.vala
vala/valaenum.vala
vala/valaerrorcode.vala [new file with mode: 0644]
vala/valaerrordomain.vala [new file with mode: 0644]
vala/valaerrortype.vala [new file with mode: 0644]
vala/valainterfacewriter.vala
vala/valanamespace.vala
vala/valasemanticanalyzer.vala

index c5b0de0..6c04eec 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,17 @@
 2008-02-07  Jürg Billeter  <j@bitron.ch>
 
+       * vala/Makefile.am, vala/parser.y, vala/scanner.l, vala/vala.h,
+         vala/valacodecontext.vala, vala/valacodegenerator.vala,
+         vala/valacodevisitor.vala, vala/valaenum.vala,
+         vala/valaerrorcode.vala, vala/valaerrordomain.vala,
+         vala/valaerrortype.vala, vala/valainterfacewriter.vala,
+         vala/valanamespace.vala, vala/valasemanticanalyzer.vala,
+         gobject/valaccodegenerator.vala, tests/exceptions.vala:
+
+         Separate errordomain from enum declaration, fixes bug 512616
+
+2008-02-07  Jürg Billeter  <j@bitron.ch>
+
        * gobject/valaccodegenerator.vala: use 0 as array length when array
          is a null literal
 
index 5762214..b386911 100644 (file)
@@ -273,34 +273,52 @@ public class Vala.CCodeGenerator : CodeGenerator {
                header_type_definition.append (cenum);
 
                en.accept_children (this);
+       }
+
+       public override void visit_enum_value (EnumValue! ev) {
+               if (ev.value == null) {
+                       cenum.add_value (new CCodeEnumValue (ev.get_cname ()));
+               } else {
+                       ev.value.accept (this);
+                       cenum.add_value (new CCodeEnumValue (ev.get_cname (), (CCodeExpression) ev.value.ccodenode));
+               }
+       }
 
-               if (en.error_domain) {
-                       string quark_fun_name = en.get_lower_case_cprefix () + "quark";
+       public override void visit_error_domain (ErrorDomain edomain) {
+               cenum = new CCodeEnum (edomain.get_cname ());
 
-                       var error_domain_define = new CCodeMacroReplacement (en.get_upper_case_cname (), quark_fun_name + " ()");
-                       header_type_definition.append (error_domain_define);
+               if (edomain.source_reference.comment != null) {
+                       header_type_definition.append (new CCodeComment (edomain.source_reference.comment));
+               }
+               header_type_definition.append (cenum);
 
-                       var cquark_fun = new CCodeFunction (quark_fun_name, gquark_type.data_type.get_cname ());
-                       var cquark_block = new CCodeBlock ();
+               edomain.accept_children (this);
 
-                       var cquark_call = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_static_string"));
-                       cquark_call.add_argument (new CCodeConstant ("\"" + en.get_lower_case_cname () + "-quark\""));
+               string quark_fun_name = edomain.get_lower_case_cprefix () + "quark";
 
-                       cquark_block.add_statement (new CCodeReturnStatement (cquark_call));
+               var error_domain_define = new CCodeMacroReplacement (edomain.get_upper_case_cname (), quark_fun_name + " ()");
+               header_type_definition.append (error_domain_define);
 
-                       header_type_member_declaration.append (cquark_fun.copy ());
+               var cquark_fun = new CCodeFunction (quark_fun_name, gquark_type.data_type.get_cname ());
+               var cquark_block = new CCodeBlock ();
 
-                       cquark_fun.block = cquark_block;
-                       source_type_member_definition.append (cquark_fun);
-               }
+               var cquark_call = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_static_string"));
+               cquark_call.add_argument (new CCodeConstant ("\"" + edomain.get_lower_case_cname () + "-quark\""));
+
+               cquark_block.add_statement (new CCodeReturnStatement (cquark_call));
+
+               header_type_member_declaration.append (cquark_fun.copy ());
+
+               cquark_fun.block = cquark_block;
+               source_type_member_definition.append (cquark_fun);
        }
 
-       public override void visit_enum_value (EnumValue! ev) {
-               if (ev.value == null) {
-                       cenum.add_value (new CCodeEnumValue (ev.get_cname ()));
+       public override void visit_error_code (ErrorCode ecode) {
+               if (ecode.value == null) {
+                       cenum.add_value (new CCodeEnumValue (ecode.get_cname ()));
                } else {
-                       ev.value.accept (this);
-                       cenum.add_value (new CCodeEnumValue (ev.get_cname (), (CCodeExpression) ev.value.ccodenode));
+                       ecode.value.accept (this);
+                       cenum.add_value (new CCodeEnumValue (ecode.get_cname (), (CCodeExpression) ecode.value.ccodenode));
                }
        }
 
@@ -2686,15 +2704,14 @@ public class Vala.CCodeGenerator : CodeGenerator {
                                // ensure variable argument list ends with NULL
                                creation_call.add_argument (new CCodeConstant ("NULL"));
                        }
-               } else if (expr.symbol_reference is EnumValue) {
-                       // error code
-                       var ev = (EnumValue) expr.symbol_reference;
-                       var en = (Enum) ev.parent_symbol;
+               } else if (expr.symbol_reference is ErrorCode) {
+                       var ecode = (ErrorCode) expr.symbol_reference;
+                       var edomain = (ErrorDomain) ecode.parent_symbol;
 
                        creation_call = new CCodeFunctionCall (new CCodeIdentifier ("g_set_error"));
                        creation_call.add_argument (new CCodeIdentifier ("error"));
-                       creation_call.add_argument (new CCodeIdentifier (en.get_upper_case_cname ()));
-                       creation_call.add_argument (new CCodeIdentifier (ev.get_cname ()));
+                       creation_call.add_argument (new CCodeIdentifier (edomain.get_upper_case_cname ()));
+                       creation_call.add_argument (new CCodeIdentifier (ecode.get_cname ()));
 
                        foreach (Expression arg in expr.get_argument_list ()) {
                                creation_call.add_argument ((CCodeExpression) arg.ccodenode);
@@ -3243,6 +3260,14 @@ public class Vala.CCodeGenerator : CodeGenerator {
                return null;
        }
 
+       public override CodeBinding create_error_domain_binding (ErrorDomain node) {
+               return null;
+       }
+
+       public override CodeBinding create_error_code_binding (ErrorCode node) {
+               return null;
+       }
+
        public override CodeBinding create_delegate_binding (Delegate! node) {
                return null;
        }
index 1da885f..6f6397a 100644 (file)
@@ -1,8 +1,7 @@
 using GLib;
 using Gee;
 
-[ErrorDomain]
-enum Maman.BarError {
+errordomain Maman.BarError {
        FOO,
        BAR,
        LIST
index d2453c1..d10e4dd 100644 (file)
@@ -58,6 +58,9 @@ libvalacore_la_VALASOURCES = \
        valaemptystatement.vala \
        valaenum.vala \
        valaenumvalue.vala \
+       valaerrorcode.vala \
+       valaerrordomain.vala \
+       valaerrortype.vala \
        valaexpression.vala \
        valaexpressionstatement.vala \
        valafield.vala \
index eec9afd..821af95 100644 (file)
@@ -78,6 +78,7 @@ static gboolean check_is_struct (ValaSymbol *symbol, ValaSourceReference *src);
        ValaBlock *block;
        ValaInterface *interface;
        ValaEnumValue *enum_value;
+       ValaErrorCode *error_code;
        ValaConstant *constant;
        ValaField *field;
        ValaMethod *method;
@@ -171,6 +172,7 @@ static gboolean check_is_struct (ValaSymbol *symbol, ValaSourceReference *src);
 %token ELSE "else"
 %token ENSURES "ensures"
 %token ENUM "enum"
+%token ERRORDOMAIN "errordomain"
 %token VALA_FALSE "false"
 %token FINALLY "finally"
 %token FOR "for"
@@ -2559,6 +2561,7 @@ namespace_member_declaration
        | struct_declaration
        | interface_declaration
        | enum_declaration
+       | errordomain_declaration
        | delegate_declaration
        | constant_declaration
          {
@@ -3947,6 +3950,114 @@ enum_method_declaration
          }
        ;
 
+errordomain_declaration
+       : comment opt_attributes opt_access_modifier ERRORDOMAIN identifier opt_name_specifier
+         {
+               ValaSourceReference *src;
+
+               char *name = $5;
+         
+               ValaSymbol *parent_symbol = VALA_SYMBOL (g_object_ref (symbol_stack->data));
+               ValaScope *parent_scope = VALA_SCOPE (scope_stack->data);
+
+               if ($6 != NULL) {
+                       ValaSourceReference *ns_src = src(@5);
+                       g_object_unref (parent_symbol);
+                       parent_symbol = vala_scope_lookup (parent_scope, $5);
+                       if (parent_symbol != NULL) {
+                               if (check_is_namespace (parent_symbol, src)) {
+                                       if (!vala_source_file_get_pkg (current_source_file)) {
+                                               vala_namespace_set_pkg (VALA_NAMESPACE (parent_symbol), FALSE);
+                                       }
+                               }
+                       } else {
+                               parent_symbol = VALA_SYMBOL (vala_code_context_create_namespace (context, $5, ns_src));
+                               vala_namespace_set_pkg (VALA_NAMESPACE (parent_symbol), vala_source_file_get_pkg (current_source_file));
+                               vala_namespace_add_namespace (VALA_NAMESPACE (symbol_stack->data), VALA_NAMESPACE (parent_symbol));
+                       }
+                       parent_scope = vala_symbol_get_scope (parent_symbol);
+                       g_free ($5);
+                       g_object_unref (ns_src);
+                       
+                       name = $6;
+               }
+               
+               src = src_com(@5, $1);
+               ValaErrorDomain *edomain = vala_code_context_create_error_domain (context, name, src);
+               g_free (name);
+               g_object_unref (src);
+
+               vala_namespace_add_error_domain (VALA_NAMESPACE (parent_symbol), edomain);
+               vala_source_file_add_node (current_source_file, VALA_CODE_NODE (edomain));
+               g_object_unref (parent_symbol);
+
+               VALA_CODE_NODE (edomain)->attributes = $2;
+
+               if ($3 != -1) {
+                       vala_symbol_set_access (VALA_SYMBOL (edomain), $3);
+               }
+               
+               push_symbol (VALA_SYMBOL (edomain));
+         }
+         errordomain_body
+         {
+               g_object_unref (pop_symbol ());
+         }
+       ;
+
+errordomain_body
+       : OPEN_BRACE opt_errordomain_member_declarations opt_errordomain_method_declarations CLOSE_BRACE
+       ;
+
+opt_errordomain_member_declarations
+       : /* empty */
+       | errordomain_member_declarations opt_comma
+       ;
+
+errordomain_member_declarations
+       : errordomain_member_declaration
+       | errordomain_member_declarations COMMA errordomain_member_declaration
+       ;
+
+errordomain_member_declaration
+       : opt_attributes identifier
+         {
+               ValaErrorCode *ec = vala_code_context_create_error_code (context, $2);
+               g_free ($2);
+               vala_error_domain_add_code (VALA_ERROR_DOMAIN (symbol_stack->data), ec);
+               g_object_unref (ec);
+         }
+       | opt_attributes identifier ASSIGN expression
+         {
+               ValaErrorCode *ec = vala_code_context_create_error_code_with_value (context, $2, $4);
+               g_free ($2);
+               g_object_unref ($4);
+               vala_error_domain_add_code (VALA_ERROR_DOMAIN (symbol_stack->data), ec);
+               g_object_unref (ec);
+         }
+       ;
+
+opt_errordomain_method_declarations
+       : /* empty */
+       | errordomain_method_declarations
+       ;
+
+errordomain_method_declarations
+       : SEMICOLON errordomain_method_declaration
+       | errordomain_method_declarations errordomain_method_declaration
+       ;
+
+errordomain_method_declaration
+       : method_declaration
+         {
+               /* skip declarations with errors */
+               if ($1 != NULL) {
+                       vala_error_domain_add_method (VALA_ERROR_DOMAIN (symbol_stack->data), $1);
+                       g_object_unref ($1);
+               }
+         }
+       ;
+
 delegate_declaration
        : comment opt_attributes opt_access_modifier opt_modifiers DELEGATE type identifier opt_name_specifier opt_type_parameter_list OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS opt_throws_declaration SEMICOLON
          {
index 88445db..9838dc8 100644 (file)
@@ -151,6 +151,7 @@ generic_type                        {type_name}("<"{space}{type_name}("?"|"*"+)?(","{space}{type_name
 "else"         { uploc; return ELSE; }
 "ensures"      { uploc; return ENSURES; }
 "enum"         { uploc; return ENUM; }
+"errordomain"  { uploc; return ERRORDOMAIN; }
 "false"                { uploc; return VALA_FALSE; }
 "finally"      { uploc; return FINALLY; }
 "for"          { uploc; return FOR; }
index 8f5e21f..c6c0304 100644 (file)
@@ -26,6 +26,8 @@
 #include <vala/valaemptystatement.h>
 #include <vala/valaenum.h>
 #include <vala/valaenumvalue.h>
+#include <vala/valaerrorcode.h>
+#include <vala/valaerrordomain.h>
 #include <vala/valaexpression.h>
 #include <vala/valaexpressionstatement.h>
 #include <vala/valafield.h>
index 2ad5016..0b557e0 100644 (file)
@@ -457,6 +457,24 @@ public class Vala.CodeContext : Object {
                return node;
        }
 
+       public ErrorDomain create_error_domain (string! name, SourceReference source_reference = null) {
+               var node = new ErrorDomain (name, source_reference);
+               node.code_binding = codegen.create_error_domain_binding (node);
+               return node;
+       }
+
+       public ErrorCode create_error_code (string! name) {
+               var node = new ErrorCode (name);
+               node.code_binding = codegen.create_error_code_binding (node);
+               return node;
+       }
+
+       public ErrorCode create_error_code_with_value (string! name, Expression value) {
+               var node = new ErrorCode.with_value (name, value);
+               node.code_binding = codegen.create_error_code_binding (node);
+               return node;
+       }
+
        public Delegate! create_delegate (string name, DataType return_type, SourceReference source_reference = null) {
                var node = new Delegate (name, return_type, source_reference);
                node.code_binding = codegen.create_delegate_binding (node);
index ae8f91c..facf920 100644 (file)
@@ -58,6 +58,14 @@ public class Vala.CodeGenerator : CodeVisitor {
                return null;
        }
 
+       public virtual CodeBinding create_error_domain_binding (ErrorDomain node) {
+               return null;
+       }
+
+       public virtual CodeBinding create_error_code_binding (ErrorCode node) {
+               return null;
+       }
+
        public virtual CodeBinding create_delegate_binding (Delegate! node) {
                return null;
        }
index 5c55f66..b39e2f3 100644 (file)
@@ -84,6 +84,22 @@ public abstract class Vala.CodeVisitor : Object {
        }
 
        /**
+        * Visit operation called for error domains.
+        *
+        * @param edomain an error domain
+        */
+       public virtual void visit_error_domain (ErrorDomain edomain) {
+       }
+
+       /**
+        * Visit operation called for error codes.
+        *
+        * @param ecode an error code
+        */
+       public virtual void visit_error_code (ErrorCode ecode) {
+       }
+
+       /**
         * Visit operation called for delegates.
         *
         * @param d a delegate
index 4190d26..d70a52b 100644 (file)
@@ -1,6 +1,6 @@
 /* valaenum.vala
  *
- * Copyright (C) 2006-2007  Jürg Billeter
+ * Copyright (C) 2006-2008  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
@@ -32,11 +32,6 @@ public class Vala.Enum : Typesymbol {
         */
        public bool is_flags { get; set; }
 
-       /**
-        * Specifies whether this enum represents an error domain.
-        */
-       public bool error_domain { get; set; }
-
        private Gee.List<EnumValue> values = new ArrayList<EnumValue> ();
        private Gee.List<Method> methods = new ArrayList<Method> ();
        private string cname;
@@ -207,8 +202,6 @@ public class Vala.Enum : Typesymbol {
                                process_ccode_attribute (a);
                        } else if (a.name == "Flags") {
                                is_flags = true;
-                       } else if (a.name == "ErrorDomain") {
-                               error_domain = true;
                        }
                }
        }
diff --git a/vala/valaerrorcode.vala b/vala/valaerrorcode.vala
new file mode 100644 (file)
index 0000000..da4eb3b
--- /dev/null
@@ -0,0 +1,77 @@
+/* valaerrorcode.vala
+ *
+ * Copyright (C) 2008  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.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ *     Jürg Billeter <j@bitron.ch>
+ */
+
+using GLib;
+
+/**
+ * Represents an enum member in the source code.
+ */
+public class Vala.ErrorCode : Symbol {
+       /**
+        * Specifies the numerical representation of this enum value.
+        */
+       public Expression value { get; set; }
+
+       private string cname;
+
+       /**
+        * Creates a new enum value.
+        *
+        * @param name enum value name
+        * @return     newly created enum value
+        */
+       public ErrorCode (construct string! name) {
+       }
+
+       /**
+        * Creates a new enum value with the specified numerical representation.
+        *
+        * @param name  enum value name
+        * @param value numerical representation
+        * @return      newly created enum value
+        */
+       public ErrorCode.with_value (construct string! name, construct Expression value) {
+       }
+       
+       public override void accept (CodeVisitor! visitor) {
+               visitor.visit_error_code (this);
+       }
+
+       public override void accept_children (CodeVisitor! visitor) {
+               if (value != null) {
+                       value.accept (visitor);
+               }
+       }
+
+       /**
+        * Returns the name of this error code as it is used in C code.
+        *
+        * @return the name to be used in C code
+        */
+       public string! get_cname () {
+               if (cname == null) {
+                       var edomain = (ErrorDomain) parent_symbol;
+                       cname = "%s%s".printf (edomain.get_cprefix (), name);
+               }
+               return cname;
+       }
+}
diff --git a/vala/valaerrordomain.vala b/vala/valaerrordomain.vala
new file mode 100644 (file)
index 0000000..437866b
--- /dev/null
@@ -0,0 +1,217 @@
+/* valaerrordomain.vala
+ *
+ * Copyright (C) 2008  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.1 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;
+using Gee;
+
+/**
+ * Represents an error domain declaration in the source code.
+ */
+public class Vala.ErrorDomain : Typesymbol {
+       private Gee.List<ErrorCode> codes = new ArrayList<ErrorCode> ();
+       private Gee.List<Method> methods = new ArrayList<Method> ();
+       private string cname;
+       private string cprefix;
+       private string lower_case_cprefix;
+       private string lower_case_csuffix;
+
+       /**
+        * Creates a new error domain.
+        *
+        * @param name             type name
+        * @param source_reference reference to source code
+        * @return                 newly created error domain
+        */
+       public ErrorDomain (construct string! name, construct SourceReference source_reference = null) {
+       }
+       
+       /**
+        * Appends the specified code to the list of error codes.
+        *
+        * @param ecode an error code
+        */
+       public void add_code (ErrorCode ecode) {
+               codes.add (ecode);
+               scope.add (ecode.name, ecode);
+       }
+
+       /**
+        * Adds the specified method as a member to this error domain.
+        *
+        * @param m a method
+        */
+       public void add_method (Method! m) {
+               if (m is CreationMethod) {
+                       Report.error (m.source_reference, "construction methods may only be declared within classes and structs");
+               
+                       m.error = true;
+                       return;
+               }
+               if (m.instance) {
+                       m.this_parameter = new FormalParameter ("this", new ValueType (this));
+                       m.scope.add (m.this_parameter.name, m.this_parameter);
+               }
+
+               methods.add (m);
+               scope.add (m.name, m);
+       }
+
+       /**
+        * Returns a copy of the list of error codes.
+        *
+        * @return list of error codes
+        */
+       public Collection<ErrorCode> get_codes () {
+               return new ReadOnlyCollection<ErrorCode> (codes);
+       }
+
+       /**
+        * Returns a copy of the list of methods.
+        *
+        * @return list of methods
+        */
+       public Collection<Method> get_methods () {
+               return new ReadOnlyCollection<Method> (methods);
+       }
+
+       public override void accept (CodeVisitor! visitor) {
+               visitor.visit_error_domain (this);
+       }
+
+       public override void accept_children (CodeVisitor! visitor) {
+               foreach (ErrorCode ecode in codes) {
+                       ecode.accept (visitor);
+               }
+
+               foreach (Method m in methods) {
+                       m.accept (visitor);
+               }
+       }
+
+       public override string get_cname (bool const_type = false) {
+               if (cname == null) {
+                       cname = "%s%s".printf (parent_symbol.get_cprefix (), name);
+               }
+               return cname;
+       }
+
+       public override string! get_lower_case_cprefix () {
+               if (lower_case_cprefix == null) {
+                       lower_case_cprefix = "%s_".printf (get_lower_case_cname (null));
+               }
+               return lower_case_cprefix;
+       }
+
+       private string get_lower_case_csuffix () {
+               if (lower_case_csuffix == null) {
+                       lower_case_csuffix = camel_case_to_lower_case (name);
+               }
+               return lower_case_csuffix;
+       }
+
+       public override string get_lower_case_cname (string infix) {
+               if (infix == null) {
+                       infix = "";
+               }
+               return "%s%s%s".printf (parent_symbol.get_lower_case_cprefix (), infix, get_lower_case_csuffix ());
+       }
+
+       public override string get_upper_case_cname (string infix) {
+               return get_lower_case_cname (null).up ();
+       }
+
+       public override bool is_reference_type () {
+               return false;
+       }
+       
+       private void set_cname (string! cname) {
+               this.cname = cname;
+       }
+       
+       /**
+        * Returns the string to be prepended to the name of members of this
+        * error domain 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 error
+        * domain 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 ("lower_case_csuffix")) {
+                       lower_case_csuffix = a.get_string ("lower_case_csuffix");
+               }
+               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 () {
+               return "G_TYPE_POINTER";
+       }
+       
+       public override string get_marshaller_type_name () {
+               return "POINTER";
+       }
+
+       public override string get_get_value_function () {
+               return "g_value_get_pointer";
+       }
+       
+       public override string get_set_value_function () {
+               return "g_value_set_pointer";
+       }
+}
diff --git a/vala/valaerrortype.vala b/vala/valaerrortype.vala
new file mode 100644 (file)
index 0000000..8fefb2d
--- /dev/null
@@ -0,0 +1,38 @@
+/* valaerrortype.vala
+ *
+ * Copyright (C) 2008  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.1 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;
+
+/**
+ * A class type.
+ */
+public class Vala.ErrorType : ReferenceType {
+       /**
+        * The error domain or null for generic error.
+        */
+       public weak ErrorDomain? error_domain { get; set; }
+
+       public ErrorType (ErrorDomain? error_domain) {
+               this.error_domain = error_domain;
+               this.data_type = error_domain;
+       }
+}
index 51269a4..ede7732 100644 (file)
@@ -312,10 +312,6 @@ public class Vala.InterfaceWriter : CodeVisitor {
                        write_indent ();
                        write_string ("[Flags]");
                }
-               if (en.error_domain) {
-                       write_indent ();
-                       write_string ("[ErrorDomain]");
-               }
 
                write_indent ();
                write_accessibility (en);
@@ -336,6 +332,48 @@ public class Vala.InterfaceWriter : CodeVisitor {
                write_newline ();
        }
 
+       public override void visit_error_domain (ErrorDomain edomain) {
+               if (edomain.source_reference != null && edomain.source_reference.file.pkg) {
+                       return;
+               }
+
+               if (!check_accessibility (edomain)) {
+                       return;
+               }
+
+               write_indent ();
+
+               var first = true;
+               string cheaders;
+               foreach (string cheader in edomain.get_cheader_filenames ()) {
+                       if (first) {
+                               cheaders = cheader;
+                               first = false;
+                       } else {
+                               cheaders = "%s,%s".printf (cheaders, cheader);
+                       }
+               }
+               write_string ("[CCode (cprefix = \"%s\", cheader_filename = \"%s\")]".printf (edomain.get_cprefix (), cheaders));
+
+               write_indent ();
+               write_accessibility (edomain);
+               write_string ("errordomain ");
+               write_identifier (edomain.name);
+               write_begin_block ();
+
+               edomain.accept_children (this);
+
+               write_end_block ();
+               write_newline ();
+       }
+
+       public override void visit_error_code (ErrorCode ecode) {
+               write_indent ();
+               write_identifier (ecode.name);
+               write_string (",");
+               write_newline ();
+       }
+
        public override void visit_constant (Constant! c) {
                if (c.source_reference != null && c.source_reference.file.pkg) {
                        return;
index ef4653a..f0953c5 100644 (file)
@@ -36,6 +36,7 @@ public class Vala.Namespace : Symbol {
        private Gee.List<Interface> interfaces = new ArrayList<Interface> ();
        private Gee.List<Struct> structs = new ArrayList<Struct> ();
        private Gee.List<Enum> enums = new ArrayList<Enum> ();
+       private Gee.List<ErrorDomain> error_domains = new ArrayList<ErrorDomain> ();
        private Gee.List<Delegate> delegates = new ArrayList<Delegate> ();
        private Gee.List<Constant> constants = new ArrayList<Constant> ();
        private Gee.List<Field> fields = new ArrayList<Field> ();
@@ -117,7 +118,17 @@ public class Vala.Namespace : Symbol {
                enums.add (en);
                scope.add (en.name, en);
        }
-                       
+
+       /**
+        * Adds the specified error domain to this namespace.
+        *
+        * @param edomain an error domain
+        */
+       public void add_error_domain (ErrorDomain edomain) {
+               error_domains.add (edomain);
+               scope.add (edomain.name, edomain);
+       }
+
        /**
         * Adds the specified delegate to this namespace.
         *
index a05edcf..b386ad9 100644 (file)
@@ -2063,7 +2063,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                                expr.symbol_reference = constructor;
 
                                type_args = ((MemberAccess) expr.member_name.inner).get_type_arguments ();
-                       } else if (constructor_sym is EnumValue) {
+                       } else if (constructor_sym is ErrorCode) {
                                type_sym = constructor_sym.parent_symbol;
 
                                expr.symbol_reference = constructor_sym;
@@ -2075,9 +2075,8 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                        } else if (type_sym is Struct) {
                                type = (Typesymbol) type_sym;
                                expr.type_reference = new ValueType (type);
-                       } else if (type_sym is Enum && ((Enum) type_sym).error_domain) {
-                               type = (Typesymbol) type_sym;
-                               expr.type_reference = new ValueType (type);
+                       } else if (type_sym is ErrorDomain) {
+                               expr.type_reference = new ErrorType ((ErrorDomain) type_sym);
                        } else {
                                expr.error = true;
                                Report.error (expr.source_reference, "`%s' is not a class, struct, or error domain".printf (type_sym.get_full_name ()));