]> git.pld-linux.org Git - packages/vala.git/commitdiff
- added, updates to svn 2004
authoraredridel <aredridel@pld-linux.org>
Sun, 9 Nov 2008 19:44:04 +0000 (19:44 +0000)
committercvs2git <feedback@pld-linux.org>
Sun, 24 Jun 2012 12:13:13 +0000 (12:13 +0000)
Changed files:
    vala-0.5.1-2004.patch -> 1.1

vala-0.5.1-2004.patch [new file with mode: 0644]

diff --git a/vala-0.5.1-2004.patch b/vala-0.5.1-2004.patch
new file mode 100644 (file)
index 0000000..3da3e24
--- /dev/null
@@ -0,0 +1,10306 @@
+Index: vala/valablock.vala
+===================================================================
+--- vala/valablock.vala        (revision 1971)
++++ vala/valablock.vala        (revision 2004)
+@@ -90,4 +90,29 @@
+                       stmt.accept (visitor);
+               }
+       }
++
++      public override bool check (SemanticAnalyzer analyzer) {
++              if (checked) {
++                      return !error;
++              }
++
++              checked = true;
++
++              owner = analyzer.current_symbol.scope;
++              analyzer.current_symbol = this;
++
++              accept_children (analyzer);
++
++              foreach (LocalVariable local in get_local_variables ()) {
++                      local.active = false;
++              }
++
++              foreach (Statement stmt in get_statements()) {
++                      add_error_types (stmt.get_error_types ());
++              }
++
++              analyzer.current_symbol = analyzer.current_symbol.parent_symbol;
++
++              return !error;
++      }
+ }
+Index: vala/valalocalvariable.vala
+===================================================================
+--- vala/valalocalvariable.vala        (revision 1971)
++++ vala/valalocalvariable.vala        (revision 2004)
+@@ -98,4 +98,96 @@
+                       variable_type = new_type;
+               }
+       }
++
++      public override bool check (SemanticAnalyzer analyzer) {
++              if (checked) {
++                      return !error;
++              }
++
++              checked = true;
++
++              if (initializer != null) {
++                      initializer.target_type = variable_type;
++              }
++
++              accept_children (analyzer);
++
++              if (variable_type == null) {
++                      /* var type */
++
++                      if (initializer == null) {
++                              error = true;
++                              Report.error (source_reference, "var declaration not allowed without initializer");
++                              return false;
++                      }
++                      if (initializer.value_type == null) {
++                              error = true;
++                              Report.error (source_reference, "var declaration not allowed with non-typed initializer");
++                              return false;
++                      }
++
++                      variable_type = initializer.value_type.copy ();
++                      variable_type.value_owned = true;
++                      variable_type.floating_reference = false;
++
++                      initializer.target_type = variable_type;
++              }
++
++              if (initializer != null) {
++                      if (initializer.value_type == null) {
++                              if (!(initializer is MemberAccess) && !(initializer is LambdaExpression)) {
++                                      error = true;
++                                      Report.error (source_reference, "expression type not allowed as initializer");
++                                      return false;
++                              }
++
++                              if (initializer.symbol_reference is Method &&
++                                  variable_type is DelegateType) {
++                                      var m = (Method) initializer.symbol_reference;
++                                      var dt = (DelegateType) variable_type;
++                                      var cb = dt.delegate_symbol;
++
++                                      /* check whether method matches callback type */
++                                      if (!cb.matches_method (m)) {
++                                              error = true;
++                                              Report.error (source_reference, "declaration of method `%s' doesn't match declaration of callback `%s'".printf (m.get_full_name (), cb.get_full_name ()));
++                                              return false;
++                                      }
++
++                                      initializer.value_type = variable_type;
++                              } else {
++                                      error = true;
++                                      Report.error (source_reference, "expression type not allowed as initializer");
++                                      return false;
++                              }
++                      }
++
++                      if (!initializer.value_type.compatible (variable_type)) {
++                              error = true;
++                              Report.error (source_reference, "Assignment: Cannot convert from `%s' to `%s'".printf (initializer.value_type.to_string (), variable_type.to_string ()));
++                              return false;
++                      }
++
++                      if (initializer.value_type.is_disposable ()) {
++                              /* rhs transfers ownership of the expression */
++                              if (!(variable_type is PointerType) && !variable_type.value_owned) {
++                                      /* lhs doesn't own the value */
++                                      error = true;
++                                      Report.error (source_reference, "Invalid assignment from owned expression to unowned variable");
++                                      return false;
++                              }
++                      }
++              }
++
++              analyzer.current_source_file.add_type_dependency (variable_type, SourceFileDependencyType.SOURCE);
++
++              analyzer.current_symbol.scope.add (name, this);
++
++              var block = (Block) analyzer.current_symbol;
++              block.add_local_variable (this);
++
++              active = true;
++
++              return !error;
++      }
+ }
+Index: vala/valainterface.vala
+===================================================================
+--- vala/valainterface.vala    (revision 1971)
++++ vala/valainterface.vala    (revision 2004)
+@@ -540,4 +540,61 @@
+               return null;
+       }
++
++      public override bool check (SemanticAnalyzer analyzer) {
++              if (checked) {
++                      return !error;
++              }
++
++              checked = true;
++
++              process_attributes ();
++
++              var old_source_file = analyzer.current_source_file;
++              var old_symbol = analyzer.current_symbol;
++
++              if (source_reference != null) {
++                      analyzer.current_source_file = source_reference.file;
++              }
++              analyzer.current_symbol = this;
++
++              foreach (DataType prerequisite_reference in get_prerequisites ()) {
++                      // check whether prerequisite is at least as accessible as the interface
++                      if (!analyzer.is_type_accessible (this, prerequisite_reference)) {
++                              error = true;
++                              Report.error (source_reference, "prerequisite `%s` is less accessible than interface `%s`".printf (prerequisite_reference.to_string (), get_full_name ()));
++                              return false;
++                      }
++
++                      analyzer.current_source_file.add_type_dependency (prerequisite_reference, SourceFileDependencyType.HEADER_FULL);
++              }
++
++              /* check prerequisites */
++              Class prereq_class;
++              foreach (DataType prereq in get_prerequisites ()) {
++                      TypeSymbol class_or_interface = prereq.data_type;
++                      /* skip on previous errors */
++                      if (class_or_interface == null) {
++                              error = true;
++                              continue;
++                      }
++                      /* interfaces are not allowed to have multiple instantiable prerequisites */
++                      if (class_or_interface is Class) {
++                              if (prereq_class != null) {
++                                      error = true;
++                                      Report.error (source_reference, "%s: Interfaces cannot have multiple instantiable prerequisites (`%s' and `%s')".printf (get_full_name (), class_or_interface.get_full_name (), prereq_class.get_full_name ()));
++                                      return false;
++                              }
++
++                              prereq_class = (Class) class_or_interface;
++                      }
++              }
++
++              accept_children (analyzer);
++
++              analyzer.current_source_file = old_source_file;
++              analyzer.current_symbol = old_symbol;
++
++              return !error;
++      }
+ }
+Index: vala/valamethod.vala
+===================================================================
+--- vala/valamethod.vala       (revision 1971)
++++ vala/valamethod.vala       (revision 2004)
+@@ -594,4 +594,152 @@
+                       }
+               }
+       }
++
++      public override bool check (SemanticAnalyzer analyzer) {
++              if (checked) {
++                      return !error;
++              }
++
++              checked = true;
++
++              process_attributes ();
++
++              if (is_abstract) {
++                      if (parent_symbol is Class) {
++                              var cl = (Class) parent_symbol;
++                              if (!cl.is_abstract) {
++                                      error = true;
++                                      Report.error (source_reference, "Abstract methods may not be declared in non-abstract classes");
++                                      return false;
++                              }
++                      } else if (!(parent_symbol is Interface)) {
++                              error = true;
++                              Report.error (source_reference, "Abstract methods may not be declared outside of classes and interfaces");
++                              return false;
++                      }
++              } else if (is_virtual) {
++                      if (!(parent_symbol is Class) && !(parent_symbol is Interface)) {
++                              error = true;
++                              Report.error (source_reference, "Virtual methods may not be declared outside of classes and interfaces");
++                              return false;
++                      }
++
++                      if (parent_symbol is Class) {
++                              var cl = (Class) parent_symbol;
++                              if (cl.is_compact) {
++                                      Report.error (source_reference, "Virtual methods may not be declared in compact classes");
++                                      return false;
++                              }
++                      }
++              } else if (overrides) {
++                      if (!(parent_symbol is Class)) {
++                              error = true;
++                              Report.error (source_reference, "Methods may not be overridden outside of classes");
++                              return false;
++                      }
++              }
++
++              if (is_abstract && body != null) {
++                      Report.error (source_reference, "Abstract methods cannot have bodies");
++              } else if (external && body != null) {
++                      Report.error (source_reference, "Extern methods cannot have bodies");
++              } else if (!is_abstract && !external && !external_package && body == null) {
++                      Report.error (source_reference, "Non-abstract, non-extern methods must have bodies");
++              }
++
++              var old_symbol = analyzer.current_symbol;
++              var old_return_type = analyzer.current_return_type;
++              analyzer.current_symbol = this;
++              analyzer.current_return_type = return_type;
++
++              var init_attr = get_attribute ("ModuleInit");
++              if (init_attr != null) {
++                      source_reference.file.context.module_init_method = this;
++              }
++
++              if (!is_internal_symbol ()) {
++                      if (return_type is ValueType) {
++                              analyzer.current_source_file.add_type_dependency (return_type, SourceFileDependencyType.HEADER_FULL);
++                      } else {
++                              analyzer.current_source_file.add_type_dependency (return_type, SourceFileDependencyType.HEADER_SHALLOW);
++                      }
++              }
++              analyzer.current_source_file.add_type_dependency (return_type, SourceFileDependencyType.SOURCE);
++
++              accept_children (analyzer);
++
++              analyzer.current_symbol = old_symbol;
++              analyzer.current_return_type = old_return_type;
++
++              if (analyzer.current_symbol.parent_symbol is Method) {
++                      /* lambda expressions produce nested methods */
++                      var up_method = (Method) analyzer.current_symbol.parent_symbol;
++                      analyzer.current_return_type = up_method.return_type;
++              }
++
++              if (analyzer.current_symbol is Struct) {
++                      if (is_abstract || is_virtual || overrides) {
++                              Report.error (source_reference, "A struct member `%s' cannot be marked as override, virtual, or abstract".printf (get_full_name ()));
++                              return false;
++                      }
++              } else if (overrides && base_method == null) {
++                      Report.error (source_reference, "%s: no suitable method found to override".printf (get_full_name ()));
++              }
++
++              // check whether return type is at least as accessible as the method
++              if (!analyzer.is_type_accessible (this, return_type)) {
++                      error = true;
++                      Report.error (source_reference, "return type `%s` is less accessible than method `%s`".printf (return_type.to_string (), get_full_name ()));
++                      return false;
++              }
++
++              foreach (Expression precondition in get_preconditions ()) {
++                      if (precondition.error) {
++                              // if there was an error in the precondition, skip this check
++                              error = true;
++                              return false;
++                      }
++
++                      if (!precondition.value_type.compatible (analyzer.bool_type)) {
++                              error = true;
++                              Report.error (precondition.source_reference, "Precondition must be boolean");
++                              return false;
++                      }
++              }
++
++              foreach (Expression postcondition in get_postconditions ()) {
++                      if (postcondition.error) {
++                              // if there was an error in the postcondition, skip this check
++                              error = true;
++                              return false;
++                      }
++
++                      if (!postcondition.value_type.compatible (analyzer.bool_type)) {
++                              error = true;
++                              Report.error (postcondition.source_reference, "Postcondition must be boolean");
++                              return false;
++                      }
++              }
++
++              if (tree_can_fail && name == "main") {
++                      Report.error (source_reference, "\"main\" method cannot throw errors");
++              }
++
++              // check that all errors that can be thrown in the method body are declared
++              if (body != null) { 
++                      foreach (DataType body_error_type in body.get_error_types ()) {
++                              bool can_propagate_error = false;
++                              foreach (DataType method_error_type in get_error_types ()) {
++                                      if (body_error_type.compatible (method_error_type)) {
++                                              can_propagate_error = true;
++                                      }
++                              }
++                              if (!can_propagate_error) {
++                                      Report.warning (body_error_type.source_reference, "unhandled error `%s'".printf (body_error_type.to_string()));
++                              }
++                      }
++              }
++
++              return !error;
++      }
+ }
+Index: vala/valafield.vala
+===================================================================
+--- vala/valafield.vala        (revision 1971)
++++ vala/valafield.vala        (revision 2004)
+@@ -195,4 +195,44 @@
+               }
+               attr.add_argument ("type", new StringLiteral ("\"%s\"".printf (ctype)));
+       }
++
++      public override bool check (SemanticAnalyzer analyzer) {
++              if (checked) {
++                      return !error;
++              }
++
++              checked = true;
++
++              process_attributes ();
++
++              if (initializer != null) {
++                      initializer.target_type = field_type;
++              }
++
++              accept_children (analyzer);
++
++              if (binding == MemberBinding.INSTANCE && parent_symbol is Interface) {
++                      error = true;
++                      Report.error (source_reference, "Interfaces may not have instance fields");
++                      return false;
++              }
++
++              if (!is_internal_symbol ()) {
++                      if (field_type is ValueType) {
++                              analyzer.current_source_file.add_type_dependency (field_type, SourceFileDependencyType.HEADER_FULL);
++                      } else {
++                              analyzer.current_source_file.add_type_dependency (field_type, SourceFileDependencyType.HEADER_SHALLOW);
++                      }
++              } else {
++                      if (parent_symbol is Namespace) {
++                              error = true;
++                              Report.error (source_reference, "Namespaces may not have private members");
++                              return false;
++                      }
++
++                      analyzer.current_source_file.add_type_dependency (field_type, SourceFileDependencyType.SOURCE);
++              }
++
++              return !error;
++      }
+ }
+Index: vala/valadostatement.vala
+===================================================================
+--- vala/valadostatement.vala  (revision 1971)
++++ vala/valadostatement.vala  (revision 2004)
+@@ -86,4 +86,31 @@
+                       condition = new_node;
+               }
+       }
++
++      public override bool check (SemanticAnalyzer analyzer) {
++              if (checked) {
++                      return !error;
++              }
++
++              checked = true;
++
++              accept_children (analyzer);
++
++              if (condition.error) {
++                      /* if there was an error in the condition, skip this check */
++                      error = true;
++                      return false;
++              }
++
++              if (!condition.value_type.compatible (analyzer.bool_type)) {
++                      error = true;
++                      Report.error (condition.source_reference, "Condition must be boolean");
++                      return false;
++              }
++
++              add_error_types (condition.get_error_types ());
++              add_error_types (body.get_error_types ());
++
++              return !error;
++      }
+ }
+Index: vala/valanamespace.vala
+===================================================================
+--- vala/valanamespace.vala    (revision 1971)
++++ vala/valanamespace.vala    (revision 2004)
+@@ -515,4 +515,16 @@
+                       }
+               }
+       }
++
++      public override bool check (SemanticAnalyzer analyzer) {
++              if (checked) {
++                      return !error;
++              }
++
++              checked = true;
++
++              process_attributes ();
++
++              return !error;
++      }
+ }
+Index: vala/valawhilestatement.vala
+===================================================================
+--- vala/valawhilestatement.vala       (revision 1971)
++++ vala/valawhilestatement.vala       (revision 2004)
+@@ -86,4 +86,31 @@
+                       condition = new_node;
+               }
+       }
++
++      public override bool check (SemanticAnalyzer analyzer) {
++              if (checked) {
++                      return !error;
++              }
++
++              checked = true;
++
++              accept_children (analyzer);
++
++              if (condition.error) {
++                      /* if there was an error in the condition, skip this check */
++                      error = true;
++                      return false;
++              }
++
++              if (!condition.value_type.compatible (analyzer.bool_type)) {
++                      error = true;
++                      Report.error (condition.source_reference, "Condition must be boolean");
++                      return false;
++              }
++
++              add_error_types (condition.get_error_types ());
++              add_error_types (body.get_error_types ());
++
++              return !error;
++      }
+ }
+Index: vala/valaconstant.vala
+===================================================================
+--- vala/valaconstant.vala     (revision 1971)
++++ vala/valaconstant.vala     (revision 2004)
+@@ -150,4 +150,29 @@
+                       }
+               }
+       }
++
++      public override bool check (SemanticAnalyzer analyzer) {
++              if (checked) {
++                      return !error;
++              }
++
++              checked = true;
++
++              process_attributes ();
++
++              type_reference.accept (analyzer);
++
++              if (!external_package) {
++                      if (initializer == null) {
++                              error = true;
++                              Report.error (source_reference, "A const field requires a initializer to be provided");
++                      } else {
++                              initializer.target_type = type_reference;
++
++                              initializer.accept (analyzer);
++                      }
++              }
++
++              return !error;
++      }
+ }
+Index: vala/valadynamicproperty.vala
+===================================================================
+--- vala/valadynamicproperty.vala      (revision 1971)
++++ vala/valadynamicproperty.vala      (revision 2004)
+@@ -40,4 +40,7 @@
+               return new ArrayList<string> ();
+       }
++      public override bool check (SemanticAnalyzer analyzer) {
++              return true;
++      }
+ }
+Index: vala/valaforeachstatement.vala
+===================================================================
+--- vala/valaforeachstatement.vala     (revision 1971)
++++ vala/valaforeachstatement.vala     (revision 2004)
+@@ -134,4 +134,119 @@
+                       type_reference = new_type;
+               }
+       }
++
++      public override bool check (SemanticAnalyzer analyzer) {
++              if (checked) {
++                      return !error;
++              }
++
++              checked = true;
++
++              // analyze collection expression first, used for type inference
++              collection.accept (analyzer);
++
++              if (collection.error) {
++                      // ignore inner error
++                      error = true;
++                      return false;
++              } else if (collection.value_type == null) {
++                      Report.error (collection.source_reference, "invalid collection expression");
++                      error = true;
++                      return false;
++              }
++
++              var collection_type = collection.value_type.copy ();
++              collection.target_type = collection_type.copy ();
++              
++              DataType element_data_type = null;
++              bool element_owned = false;
++
++              if (collection_type.is_array ()) {
++                      var array_type = (ArrayType) collection_type;
++                      element_data_type = array_type.element_type;
++              } else if (collection_type.compatible (analyzer.glist_type) || collection_type.compatible (analyzer.gslist_type)) {
++                      if (collection_type.get_type_arguments ().size > 0) {
++                              element_data_type = (DataType) collection_type.get_type_arguments ().get (0);
++                      }
++              } else if (analyzer.iterable_type != null && collection_type.compatible (analyzer.iterable_type)) {
++                      element_owned = true;
++
++                      if (analyzer.list_type == null || !collection_type.compatible (new ObjectType (analyzer.list_type))) {
++                              // don't use iterator objects for lists for performance reasons
++                              var foreach_iterator_type = new ObjectType (analyzer.iterator_type);
++                              foreach_iterator_type.value_owned = true;
++                              foreach_iterator_type.add_type_argument (type_reference);
++                              iterator_variable = new LocalVariable (foreach_iterator_type, "%s_it".printf (variable_name));
++
++                              add_local_variable (iterator_variable);
++                              iterator_variable.active = true;
++                      }
++
++                      var it_method = (Method) analyzer.iterable_type.data_type.scope.lookup ("iterator");
++                      if (it_method.return_type.get_type_arguments ().size > 0) {
++                              var type_arg = it_method.return_type.get_type_arguments ().get (0);
++                              if (type_arg.type_parameter != null) {
++                                      element_data_type = SemanticAnalyzer.get_actual_type (collection_type, it_method, type_arg, this);
++                              } else {
++                                      element_data_type = type_arg;
++                              }
++                      }
++              } else {
++                      error = true;
++                      Report.error (source_reference, "Gee.List not iterable");
++                      return false;
++              }
++
++              if (element_data_type == null) {
++                      error = true;
++                      Report.error (collection.source_reference, "missing type argument for collection");
++                      return false;
++              }
++
++              // analyze element type
++              if (type_reference == null) {
++                      // var type
++                      type_reference = element_data_type.copy ();
++              } else if (!element_data_type.compatible (type_reference)) {
++                      error = true;
++                      Report.error (source_reference, "Foreach: Cannot convert from `%s' to `%s'".printf (element_data_type.to_string (), type_reference.to_string ()));
++                      return false;
++              } else if (element_data_type.is_disposable () && element_owned && !type_reference.value_owned) {
++                      error = true;
++                      Report.error (source_reference, "Foreach: Invalid assignment from owned expression to unowned variable");
++                      return false;
++              }
++              
++              analyzer.current_source_file.add_type_dependency (type_reference, SourceFileDependencyType.SOURCE);
++
++              element_variable = new LocalVariable (type_reference, variable_name);
++
++              body.scope.add (variable_name, element_variable);
++
++              body.add_local_variable (element_variable);
++              element_variable.active = true;
++
++              // analyze body
++              owner = analyzer.current_symbol.scope;
++              analyzer.current_symbol = this;
++
++              body.accept (analyzer);
++
++              foreach (LocalVariable local in get_local_variables ()) {
++                      local.active = false;
++              }
++
++              analyzer.current_symbol = analyzer.current_symbol.parent_symbol;
++
++              collection_variable = new LocalVariable (collection_type, "%s_collection".printf (variable_name));
++
++              add_local_variable (collection_variable);
++              collection_variable.active = true;
++
++
++              add_error_types (collection.get_error_types ());
++              add_error_types (body.get_error_types ());
++
++              return !error;
++      }
+ }
+Index: vala/valadeclarationstatement.vala
+===================================================================
+--- vala/valadeclarationstatement.vala (revision 1971)
++++ vala/valadeclarationstatement.vala (revision 2004)
+@@ -48,4 +48,25 @@
+       
+               visitor.visit_declaration_statement (this);
+       }
++
++      public override bool check (SemanticAnalyzer analyzer) {
++              if (checked) {
++                      return !error;
++              }
++
++              checked = true;
++
++              var local = declaration as LocalVariable;
++              if (local != null && local.initializer != null) {
++                      foreach (DataType error_type in local.initializer.get_error_types ()) {
++                              // ensure we can trace back which expression may throw errors of this type
++                              var initializer_error_type = error_type.copy ();
++                              initializer_error_type.source_reference = local.initializer.source_reference;
++
++                              add_error_type (initializer_error_type);
++                      }
++              }
++
++              return !error;
++      }
+ }
+Index: vala/valaelementaccess.vala
+===================================================================
+--- vala/valaelementaccess.vala        (revision 1971)
++++ vala/valaelementaccess.vala        (revision 2004)
+@@ -85,4 +85,127 @@
+               }
+               return container.is_pure ();
+       }
++
++      public override bool check (SemanticAnalyzer analyzer) {
++              if (checked) {
++                      return !error;
++              }
++
++              checked = true;
++
++              container.accept (analyzer);
++
++              if (container.value_type == null) {
++                      /* don't proceed if a child expression failed */
++                      error = true;
++                      return false;
++              }
++
++              var container_type = container.value_type.data_type;
++
++              if (container is MemberAccess && container.symbol_reference is Signal) {
++                      // signal detail access
++                      if (get_indices ().size != 1) {
++                              error = true;
++                              Report.error (source_reference, "Element access with more than one dimension is not supported for signals");
++                              return false;
++                      }
++                      get_indices ().get (0).target_type = analyzer.string_type.copy ();
++              }
++
++              foreach (Expression index in get_indices ()) {
++                      index.accept (analyzer);
++              }
++
++              bool index_int_type_check = true;
++
++              var pointer_type = container.value_type as PointerType;
++
++              /* assign a value_type when possible */
++              if (container.value_type is ArrayType) {
++                      var array_type = (ArrayType) container.value_type;
++                      value_type = array_type.element_type.copy ();
++                      if (!lvalue) {
++                              value_type.value_owned = false;
++                      }
++              } else if (pointer_type != null && !pointer_type.base_type.is_reference_type_or_type_parameter ()) {
++                      value_type = pointer_type.base_type.copy ();
++              } else if (container_type == analyzer.string_type.data_type) {
++                      if (get_indices ().size != 1) {
++                              error = true;
++                              Report.error (source_reference, "Element access with more than one dimension is not supported for strings");
++                              return false;
++                      }
++
++                      value_type = analyzer.unichar_type;
++              } else if (container_type != null && analyzer.list_type != null && analyzer.map_type != null &&
++                         (container_type.is_subtype_of (analyzer.list_type) || container_type.is_subtype_of (analyzer.map_type))) {
++                      Gee.List<Expression> indices = get_indices ();
++                      if (indices.size != 1) {
++                              error = true;
++                              Report.error (source_reference, "Element access with more than one dimension is not supported for the specified type");
++                              return false;
++                      }
++                      Iterator<Expression> indices_it = indices.iterator ();
++                      indices_it.next ();
++                      var index = indices_it.get ();
++                      index_int_type_check = false;
++
++                      // lookup symbol in interface instead of class as implemented interface methods are not in VAPI files
++                      Symbol get_sym = null;
++                      if (container_type.is_subtype_of (analyzer.list_type)) {
++                              get_sym = analyzer.list_type.scope.lookup ("get");
++                      } else if (container_type.is_subtype_of (analyzer.map_type)) {
++                              get_sym = analyzer.map_type.scope.lookup ("get");
++                      }
++                      var get_method = (Method) get_sym;
++                      Gee.List<FormalParameter> get_params = get_method.get_parameters ();
++                      Iterator<FormalParameter> get_params_it = get_params.iterator ();
++                      get_params_it.next ();
++                      var get_param = get_params_it.get ();
++
++                      var index_type = get_param.parameter_type;
++                      if (index_type.type_parameter != null) {
++                              index_type = analyzer.get_actual_type (container.value_type, get_method, get_param.parameter_type, this);
++                      }
++
++                      if (!index.value_type.compatible (index_type)) {
++                              error = true;
++                              Report.error (source_reference, "index expression: Cannot convert from `%s' to `%s'".printf (index.value_type.to_string (), index_type.to_string ()));
++                              return false;
++                      }
++
++                      value_type = analyzer.get_actual_type (container.value_type, get_method, get_method.return_type, this).copy ();
++                      if (lvalue) {
++                              // get () returns owned value, set () accepts unowned value
++                              value_type.value_owned = false;
++                      }
++              } else if (container is MemberAccess && container.symbol_reference is Signal) {
++                      index_int_type_check = false;
++
++                      symbol_reference = container.symbol_reference;
++                      value_type = container.value_type;
++              } else {
++                      error = true;
++                      Report.error (source_reference, "The expression `%s' does not denote an Array".printf (container.value_type.to_string ()));
++              }
++
++              if (index_int_type_check) {
++                      /* check if the index is of type integer */
++                      foreach (Expression e in get_indices ()) {
++                              /* don't proceed if a child expression failed */
++                              if (e.value_type == null) {
++                                      return false;
++                              }
++
++                              /* check if the index is of type integer */
++                              if (!(e.value_type.data_type is Struct) || !((Struct) e.value_type.data_type).is_integer_type ()) {
++                                      error = true;
++                                      Report.error (e.source_reference, "Expression of integer type expected");
++                              }
++                      }
++              }
++
++              return !error;
++      }
+ }
+Index: vala/valacatchclause.vala
+===================================================================
+--- vala/valacatchclause.vala  (revision 1971)
++++ vala/valacatchclause.vala  (revision 2004)
+@@ -1,4 +1,4 @@
+-/* valacatchclause.vala
++/* valacatchvala
+  *
+  * Copyright (C) 2007-2008  Jürg Billeter
+  *
+@@ -62,7 +62,7 @@
+       private DataType _data_type;
+       /**
+-       * Creates a new catch clause.
++       * Creates a new catch 
+        *
+        * @param type_reference   error type
+        * @param variable_name    error variable name
+@@ -94,4 +94,27 @@
+                       error_type = new_type;
+               }
+       }
++
++      public override bool check (SemanticAnalyzer analyzer) {
++              if (checked) {
++                      return !error;
++              }
++
++              checked = true;
++
++              if (error_type != null) {
++                      analyzer.current_source_file.add_type_dependency (error_type, SourceFileDependencyType.SOURCE);
++
++                      error_variable = new LocalVariable (error_type.copy (), variable_name);
++
++                      body.scope.add (variable_name, error_variable);
++                      body.add_local_variable (error_variable);
++              } else {
++                      error_type = new ErrorType (null, null, source_reference);
++              }
++
++              accept_children (analyzer);
++
++              return !error;
++      }
+ }
+Index: vala/valainitializerlist.vala
+===================================================================
+--- vala/valainitializerlist.vala      (revision 1971)
++++ vala/valainitializerlist.vala      (revision 2004)
+@@ -1,4 +1,4 @@
+-/* valainitializerlist.vala
++/* valainitializervala
+  *
+  * Copyright (C) 2006-2008  Jürg Billeter, Raffaele Sandrini
+  *
+@@ -31,7 +31,7 @@
+       private Gee.List<Expression> initializers = new ArrayList<Expression> ();
+       
+       /**
+-       * Appends the specified expression to this initializer list.
++       * Appends the specified expression to this initializer 
+        *
+        * @param expr an expression
+        */
+@@ -41,7 +41,7 @@
+       }
+       
+       /**
+-       * Returns a copy of the expression list.
++       * Returns a copy of the expression 
+        *
+        * @return expression list
+        */
+@@ -50,14 +50,14 @@
+       }
+       /**
+-       * Returns the initializer count in this initializer list.
++       * Returns the initializer count in this initializer 
+        */
+       public int size {
+               get { return initializers.size; }
+       }
+       /**
+-       * Creates a new initializer list.
++       * Creates a new initializer 
+        *
+        * @param source_reference reference to source code
+        * @return                 newly created initializer list
+@@ -92,4 +92,80 @@
+                       }
+               }
+       }
++
++      public override bool check (SemanticAnalyzer analyzer) {
++              if (checked) {
++                      return !error;
++              }
++
++              checked = true;
++
++              if (target_type == null) {
++                      error = true;
++                      Report.error (source_reference, "initializer list used for unknown type");
++                      return false;
++              } else if (target_type is ArrayType) {
++                      /* initializer is used as array initializer */
++                      var array_type = (ArrayType) target_type;
++
++                      foreach (Expression e in get_initializers ()) {
++                              e.target_type = array_type.element_type.copy ();
++                      }
++              } else if (target_type.data_type is Struct) {
++                      /* initializer is used as struct initializer */
++                      var st = (Struct) target_type.data_type;
++
++                      var field_it = st.get_fields ().iterator ();
++                      foreach (Expression e in get_initializers ()) {
++                              Field field = null;
++                              while (field == null) {
++                                      if (!field_it.next ()) {
++                                              error = true;
++                                              Report.error (e.source_reference, "too many expressions in initializer list for `%s'".printf (target_type.to_string ()));
++                                              return false;
++                                      }
++                                      field = field_it.get ();
++                                      if (field.binding != MemberBinding.INSTANCE) {
++                                              // we only initialize instance fields
++                                              field = null;
++                                      }
++                              }
++
++                              e.target_type = field.field_type.copy ();
++                              if (!target_type.value_owned) {
++                                      e.target_type.value_owned = false;
++                              }
++                      }
++              } else {
++                      error = true;
++                      Report.error (source_reference, "initializer list used for `%s', which is neither array nor struct".printf (target_type.to_string ()));
++                      return false;
++              }
++
++              accept_children (analyzer);
++
++              bool error = false;
++              foreach (Expression e in get_initializers ()) {
++                      if (e.value_type == null) {
++                              error = true;
++                              continue;
++                      }
++
++                      var unary = e as UnaryExpression;
++                      if (unary != null && (unary.operator == UnaryOperator.REF || unary.operator == UnaryOperator.OUT)) {
++                              // TODO check type for ref and out expressions
++                      } else if (!e.value_type.compatible (e.target_type)) {
++                              error = true;
++                              e.error = true;
++                              Report.error (e.source_reference, "Expected initializer of type `%s' but got `%s'".printf (e.target_type.to_string (), e.value_type.to_string ()));
++                      }
++              }
++
++              if (!error) {
++                      /* everything seems to be correct */
++                      value_type = target_type;
++              }
++
++              return !error;
++      }
+ }
+Index: vala/valaproperty.vala
+===================================================================
+--- vala/valaproperty.vala     (revision 1971)
++++ vala/valaproperty.vala     (revision 2004)
+@@ -34,7 +34,9 @@
+               get { return _data_type; }
+               set {
+                       _data_type = value;
+-                      _data_type.parent_node = this;
++                      if (value != null) {
++                              _data_type.parent_node = this;
++                      }
+               }
+       }
+       
+@@ -409,6 +411,8 @@
+               checked = true;
++              process_attributes ();
++
+               var old_source_file = analyzer.current_source_file;
+               var old_symbol = analyzer.current_symbol;
+Index: vala/valaerrorcode.vala
+===================================================================
+--- vala/valaerrorcode.vala    (revision 1971)
++++ vala/valaerrorcode.vala    (revision 2004)
+@@ -72,4 +72,16 @@
+               }
+               return cname;
+       }
++
++      public override bool check (SemanticAnalyzer analyzer) {
++              if (checked) {
++                      return !error;
++              }
++
++              checked = true;
++
++              accept_children (analyzer);
++
++              return !error;
++      }
+ }
+Index: vala/valaformalparameter.vala
+===================================================================
+--- vala/valaformalparameter.vala      (revision 1971)
++++ vala/valaformalparameter.vala      (revision 2004)
+@@ -174,6 +174,8 @@
+               checked = true;
++              process_attributes ();
++
+               var old_source_file = analyzer.current_source_file;
+               var old_symbol = analyzer.current_symbol;
+Index: vala/valadeletestatement.vala
+===================================================================
+--- vala/valadeletestatement.vala      (revision 1971)
++++ vala/valadeletestatement.vala      (revision 2004)
+@@ -43,4 +43,26 @@
+       public override void accept_children (CodeVisitor visitor) {
+               expression.accept (visitor);
+       }
++
++      public override bool check (SemanticAnalyzer analyzer) {
++              if (checked) {
++                      return !error;
++              }
++
++              checked = true;
++
++              accept_children (analyzer);
++
++              if (expression.error) {
++                      // if there was an error in the inner expression, skip this check
++                      return false;
++              }
++
++              if (!(expression.value_type is PointerType)) {
++                      error = true;
++                      Report.error (source_reference, "delete operator not supported for `%s'".printf (expression.value_type.to_string ()));
++              }
++
++              return !error;
++      }
+ }
+Index: vala/valadestructor.vala
+===================================================================
+--- vala/valadestructor.vala   (revision 1971)
++++ vala/valadestructor.vala   (revision 2004)
+@@ -60,4 +60,21 @@
+                       body.accept (visitor);
+               }
+       }
++
++      public override bool check (SemanticAnalyzer analyzer) {
++              if (checked) {
++                      return !error;
++              }
++
++              checked = true;
++
++              owner = analyzer.current_symbol.scope;
++              analyzer.current_symbol = this;
++
++              accept_children (analyzer);
++
++              analyzer.current_symbol = analyzer.current_symbol.parent_symbol;
++
++              return !error;
++      }
+ }
+Index: vala/valaassignment.vala
+===================================================================
+--- vala/valaassignment.vala   (revision 1971)
++++ vala/valaassignment.vala   (revision 2004)
+@@ -1,6 +1,6 @@
+ /* valaassignment.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
+@@ -97,6 +97,289 @@
+       public override bool is_pure () {
+               return false;
+       }
++
++      public override bool check (SemanticAnalyzer analyzer) {
++              if (checked) {
++                      return !error;
++              }
++
++              checked = true;
++
++              left.lvalue = true;
++
++              left.accept (analyzer);
++
++              if (left.error) {
++                      // skip on error in inner expression
++                      error = true;
++                      return false;
++              }
++
++              if (left is MemberAccess) {
++                      var ma = (MemberAccess) left;
++
++                      if (!(ma.symbol_reference is Signal || ma.symbol_reference is DynamicProperty) && ma.value_type == null) {
++                              error = true;
++                              Report.error (source_reference, "unsupported lvalue in assignment");
++                              return false;
++                      }
++                      if (ma.prototype_access) {
++                              error = true;
++                              Report.error (source_reference, "Access to instance member `%s' denied".printf (ma.symbol_reference.get_full_name ()));
++                              return false;
++                      }
++
++                      if (ma.error || ma.symbol_reference == null) {
++                              error = true;
++                              /* if no symbol found, skip this check */
++                              return false;
++                      }
++
++                      if (ma.symbol_reference is DynamicSignal) {
++                              // target_type not available for dynamic signals
++                      } else if (ma.symbol_reference is Signal) {
++                              var sig = (Signal) ma.symbol_reference;
++                              right.target_type = new DelegateType (sig.get_delegate (ma.inner.value_type));
++                      } else {
++                              right.target_type = ma.value_type;
++                      }
++              } else if (left is ElementAccess) {
++                      var ea = (ElementAccess) left;
++
++                      if (ea.container is MemberAccess && ea.container.symbol_reference is Signal) {
++                              var ma = (MemberAccess) ea.container;
++                              var sig = (Signal) ea.container.symbol_reference;
++                              right.target_type = new DelegateType (sig.get_delegate (ma.inner.value_type));
++                      } else {
++                              right.target_type = left.value_type;
++                      }
++              } else if (left is PointerIndirection) {
++                      right.target_type = left.value_type;
++              } else {
++                      error = true;
++                      Report.error (source_reference, "unsupported lvalue in assignment");
++                      return false;
++              }
++
++              right.accept (analyzer);
++
++              if (right.error) {
++                      // skip on error in inner expression
++                      error = true;
++                      return false;
++              }
++
++              if (operator != AssignmentOperator.SIMPLE && left is MemberAccess) {
++                      // transform into simple assignment
++                      // FIXME: only do this if the backend doesn't support
++                      // the assignment natively
++
++                      var ma = (MemberAccess) left;
++
++                      if (!(ma.symbol_reference is Signal)) {
++                              var old_value = new MemberAccess (ma.inner, ma.member_name);
++
++                              var bin = new BinaryExpression (BinaryOperator.PLUS, old_value, new ParenthesizedExpression (right, right.source_reference));
++                              bin.target_type = right.target_type;
++                              right.target_type = right.target_type.copy ();
++                              right.target_type.value_owned = false;
++
++                              if (operator == AssignmentOperator.BITWISE_OR) {
++                                      bin.operator = BinaryOperator.BITWISE_OR;
++                              } else if (operator == AssignmentOperator.BITWISE_AND) {
++                                      bin.operator = BinaryOperator.BITWISE_AND;
++                              } else if (operator == AssignmentOperator.BITWISE_XOR) {
++                                      bin.operator = BinaryOperator.BITWISE_XOR;
++                              } else if (operator == AssignmentOperator.ADD) {
++                                      bin.operator = BinaryOperator.PLUS;
++                              } else if (operator == AssignmentOperator.SUB) {
++                                      bin.operator = BinaryOperator.MINUS;
++                              } else if (operator == AssignmentOperator.MUL) {
++                                      bin.operator = BinaryOperator.MUL;
++                              } else if (operator == AssignmentOperator.DIV) {
++                                      bin.operator = BinaryOperator.DIV;
++                              } else if (operator == AssignmentOperator.PERCENT) {
++                                      bin.operator = BinaryOperator.MOD;
++                              } else if (operator == AssignmentOperator.SHIFT_LEFT) {
++                                      bin.operator = BinaryOperator.SHIFT_LEFT;
++                              } else if (operator == AssignmentOperator.SHIFT_RIGHT) {
++                                      bin.operator = BinaryOperator.SHIFT_RIGHT;
++                              }
++
++                              right = bin;
++                              right.accept (analyzer);
++
++                              operator = AssignmentOperator.SIMPLE;
++                      }
++              }
++
++              if (left.symbol_reference is Signal) {
++                      var sig = (Signal) left.symbol_reference;
++
++                      var m = right.symbol_reference as Method;
++
++                      if (m == null) {
++                              error = true;
++                              Report.error (right.source_reference, "unsupported expression for signal handler");
++                              return false;
++                      }
++
++                      var dynamic_sig = sig as DynamicSignal;
++                      if (dynamic_sig != null) {
++                              bool first = true;
++                              foreach (FormalParameter param in dynamic_sig.handler.value_type.get_parameters ()) {
++                                      if (first) {
++                                              // skip sender parameter
++                                              first = false;
++                                      } else {
++                                              dynamic_sig.add_parameter (param.copy ());
++                                      }
++                              }
++                              right.target_type = new DelegateType (sig.get_delegate (new ObjectType ((ObjectTypeSymbol) sig.parent_symbol)));
++                      } else if (!right.value_type.compatible (right.target_type)) {
++                              var delegate_type = (DelegateType) right.target_type;
++
++                              error = true;
++                              Report.error (right.source_reference, "method `%s' is incompatible with signal `%s', expected `%s'".printf (right.value_type.to_string (), right.target_type.to_string (), delegate_type.delegate_symbol.get_prototype_string (m.name)));
++                              return false;
++                      }
++              } else if (left is MemberAccess) {
++                      var ma = (MemberAccess) left;
++
++                      if (ma.symbol_reference is Property) {
++                              var prop = (Property) ma.symbol_reference;
++
++                              var dynamic_prop = prop as DynamicProperty;
++                              if (dynamic_prop != null) {
++                                      dynamic_prop.property_type = right.value_type.copy ();
++                                      left.value_type = dynamic_prop.property_type.copy ();
++                              }
++
++                              if (prop.set_accessor == null
++                                  || (!prop.set_accessor.writable && !(analyzer.find_current_method () is CreationMethod || analyzer.is_in_constructor ()))) {
++                                      ma.error = true;
++                                      Report.error (ma.source_reference, "Property `%s' is read-only".printf (prop.get_full_name ()));
++                                      return false;
++                              }
++                      } else if (ma.symbol_reference is LocalVariable && right.value_type == null) {
++                              var local = (LocalVariable) ma.symbol_reference;
++
++                              if (right.symbol_reference is Method &&
++                                  local.variable_type is DelegateType) {
++                                      var m = (Method) right.symbol_reference;
++                                      var dt = (DelegateType) local.variable_type;
++                                      var cb = dt.delegate_symbol;
++
++                                      /* check whether method matches callback type */
++                                      if (!cb.matches_method (m)) {
++                                              error = true;
++                                              Report.error (source_reference, "declaration of method `%s' doesn't match declaration of callback `%s'".printf (m.get_full_name (), cb.get_full_name ()));
++                                              return false;
++                                      }
++
++                                      right.value_type = local.variable_type;
++                              } else {
++                                      error = true;
++                                      Report.error (source_reference, "Assignment: Invalid callback assignment attempt");
++                                      return false;
++                              }
++                      } else if (ma.symbol_reference is Field && right.value_type == null) {
++                              var f = (Field) ma.symbol_reference;
++
++                              if (right.symbol_reference is Method &&
++                                  f.field_type is DelegateType) {
++                                      var m = (Method) right.symbol_reference;
++                                      var dt = (DelegateType) f.field_type;
++                                      var cb = dt.delegate_symbol;
++
++                                      /* check whether method matches callback type */
++                                      if (!cb.matches_method (m)) {
++                                              f.error = true;
++                                              Report.error (source_reference, "declaration of method `%s' doesn't match declaration of callback `%s'".printf (m.get_full_name (), cb.get_full_name ()));
++                                              return false;
++                                      }
++
++                                      right.value_type = f.field_type;
++                              } else {
++                                      error = true;
++                                      Report.error (source_reference, "Assignment: Invalid callback assignment attempt");
++                                      return false;
++                              }
++                      } else if (left.value_type != null && right.value_type != null) {
++                              /* if there was an error on either side,
++                               * i.e. {left|right}.value_type == null, skip type check */
++
++                              if (!right.value_type.compatible (left.value_type)) {
++                                      error = true;
++                                      Report.error (source_reference, "Assignment: Cannot convert from `%s' to `%s'".printf (right.value_type.to_string (), left.value_type.to_string ()));
++                                      return false;
++                              }
++
++                              if (right.value_type.is_disposable ()) {
++                                      /* rhs transfers ownership of the expression */
++                                      if (!(left.value_type is PointerType) && !left.value_type.value_owned) {
++                                              /* lhs doesn't own the value */
++                                              error = true;
++                                              Report.error (source_reference, "Invalid assignment from owned expression to unowned variable");
++                                      }
++                              } else if (left.value_type.value_owned) {
++                                      /* lhs wants to own the value
++                                       * rhs doesn't transfer the ownership
++                                       * code generator needs to add reference
++                                       * increment calls */
++                              }
++                      }
++              } else if (left is ElementAccess) {
++                      var ea = (ElementAccess) left;
++
++                      if (!right.value_type.compatible (left.value_type)) {
++                              error = true;
++                              Report.error (source_reference, "Assignment: Cannot convert from `%s' to `%s'".printf (right.value_type.to_string (), left.value_type.to_string ()));
++                              return false;
++                      }
++
++                      if (right.value_type.is_disposable ()) {
++                              /* rhs transfers ownership of the expression */
++
++                              DataType element_type;
++
++                              if (ea.container.value_type is ArrayType) {
++                                      var array_type = (ArrayType) ea.container.value_type;
++                                      element_type = array_type.element_type;
++                              } else {
++                                      var args = ea.container.value_type.get_type_arguments ();
++                                      assert (args.size == 1);
++                                      element_type = args.get (0);
++                              }
++
++                              if (!(element_type is PointerType) && !element_type.value_owned) {
++                                      /* lhs doesn't own the value */
++                                      error = true;
++                                      Report.error (source_reference, "Invalid assignment from owned expression to unowned variable");
++                                      return false;
++                              }
++                      } else if (left.value_type.value_owned) {
++                              /* lhs wants to own the value
++                               * rhs doesn't transfer the ownership
++                               * code generator needs to add reference
++                               * increment calls */
++                      }
++              } else {
++                      return false;
++              }
++
++              if (left.value_type != null) {
++                      value_type = left.value_type.copy ();
++                      value_type.value_owned = false;
++              } else {
++                      value_type = null;
++              }
++
++              add_error_types (left.get_error_types ());
++              add_error_types (right.get_error_types ());
++
++              return !error;
++      }
+ }
+       
+ public enum Vala.AssignmentOperator {
+Index: vala/valalockstatement.vala
+===================================================================
+--- vala/valalockstatement.vala        (revision 1971)
++++ vala/valalockstatement.vala        (revision 2004)
+@@ -47,4 +47,31 @@
+               body.accept (visitor);
+               visitor.visit_lock_statement (this);
+       }
++
++      public override bool check (SemanticAnalyzer analyzer) {
++              if (checked) {
++                      return !error;
++              }
++
++              checked = true;
++
++              /* resource must be a member access and denote a Lockable */
++              if (!(resource is MemberAccess && resource.symbol_reference is Lockable)) {
++                      error = true;
++                      resource.error = true;
++                      Report.error (resource.source_reference, "Expression is either not a member access or does not denote a lockable member");
++                      return false;
++              }
++
++              /* parent symbol must be the current class */
++              if (resource.symbol_reference.parent_symbol != analyzer.current_class) {
++                      error = true;
++                      resource.error = true;
++                      Report.error (resource.source_reference, "Only members of the current class are lockable");
++              }
++
++              ((Lockable) resource.symbol_reference).set_lock_used (true);
++
++              return !error;
++      }
+ }
+Index: vala/valathrowstatement.vala
+===================================================================
+--- vala/valathrowstatement.vala       (revision 1971)
++++ vala/valathrowstatement.vala       (revision 2004)
+@@ -72,4 +72,24 @@
+                       error_expression = new_node;
+               }
+       }
++
++      public override bool check (SemanticAnalyzer analyzer) {
++              if (checked) {
++                      return !error;
++              }
++
++              checked = true;
++
++              error_expression.target_type = new ErrorType (null, null, source_reference);
++              error_expression.target_type.value_owned = true;
++
++              accept_children (analyzer);
++
++              var error_type = error_expression.value_type.copy ();
++              error_type.source_reference = source_reference;
++
++              add_error_type (error_type);
++
++              return !error;
++      }
+ }
+Index: vala/valamemberaccess.vala
+===================================================================
+--- vala/valamemberaccess.vala (revision 1971)
++++ vala/valamemberaccess.vala (revision 2004)
+@@ -174,4 +174,355 @@
+                       return false;
+               }
+       }
++
++      public override bool check (SemanticAnalyzer analyzer) {
++              if (checked) {
++                      return !error;
++              }
++
++              checked = true;
++
++              Symbol base_symbol = null;
++              FormalParameter this_parameter = null;
++              bool may_access_instance_members = false;
++
++              symbol_reference = null;
++
++              if (qualified) {
++                      base_symbol = analyzer.root_symbol;
++                      symbol_reference = analyzer.root_symbol.scope.lookup (member_name);
++              } else if (inner == null) {
++                      if (member_name == "this") {
++                              if (!analyzer.is_in_instance_method ()) {
++                                      error = true;
++                                      Report.error (source_reference, "This access invalid outside of instance methods");
++                                      return false;
++                              }
++                      }
++
++                      base_symbol = analyzer.current_symbol;
++
++                      var sym = analyzer.current_symbol;
++                      while (sym != null && symbol_reference == null) {
++                              if (this_parameter == null) {
++                                      if (sym is CreationMethod) {
++                                              var cm = (CreationMethod) sym;
++                                              this_parameter = cm.this_parameter;
++                                              may_access_instance_members = true;
++                                      } else if (sym is Property) {
++                                              var prop = (Property) sym;
++                                              this_parameter = prop.this_parameter;
++                                              may_access_instance_members = true;
++                                      } else if (sym is Constructor) {
++                                              var c = (Constructor) sym;
++                                              this_parameter = c.this_parameter;
++                                              may_access_instance_members = true;
++                                      } else if (sym is Destructor) {
++                                              var d = (Destructor) sym;
++                                              this_parameter = d.this_parameter;
++                                              may_access_instance_members = true;
++                                      } else if (sym is Method) {
++                                              var m = (Method) sym;
++                                              this_parameter = m.this_parameter;
++                                              may_access_instance_members = (m.binding == MemberBinding.INSTANCE);
++                                      }
++                              }
++
++                              symbol_reference = analyzer.symbol_lookup_inherited (sym, member_name);
++                              sym = sym.parent_symbol;
++                      }
++
++                      if (symbol_reference == null) {
++                              foreach (UsingDirective ns in analyzer.current_source_file.get_using_directives ()) {
++                                      var local_sym = ns.namespace_symbol.scope.lookup (member_name);
++                                      if (local_sym != null) {
++                                              if (symbol_reference != null) {
++                                                      error = true;
++                                                      Report.error (source_reference, "`%s' is an ambiguous reference between `%s' and `%s'".printf (member_name, symbol_reference.get_full_name (), local_sym.get_full_name ()));
++                                                      return false;
++                                              }
++                                              symbol_reference = local_sym;
++                                      }
++                              }
++                      }
++              } else {
++                      if (inner.error) {
++                              /* if there was an error in the inner expression, skip this check */
++                              error = true;
++                              return false;
++                      }
++
++                      if (pointer_member_access) {
++                              var pointer_type = inner.value_type as PointerType;
++                              if (pointer_type != null && pointer_type.base_type is ValueType) {
++                                      // transform foo->bar to (*foo).bar
++                                      inner = new PointerIndirection (inner, source_reference);
++                                      inner.accept (analyzer);
++                                      pointer_member_access = false;
++                              }
++                      }
++
++                      if (inner is MemberAccess) {
++                              var ma = (MemberAccess) inner;
++                              if (ma.prototype_access) {
++                                      error = true;
++                                      Report.error (source_reference, "Access to instance member `%s' denied".printf (inner.symbol_reference.get_full_name ()));
++                                      return false;
++                              }
++                      }
++
++                      if (inner is MemberAccess || inner is BaseAccess) {
++                              base_symbol = inner.symbol_reference;
++
++                              if (symbol_reference == null && (base_symbol is Namespace || base_symbol is TypeSymbol)) {
++                                      symbol_reference = base_symbol.scope.lookup (member_name);
++                                      if (inner is BaseAccess) {
++                                              // inner expression is base access
++                                              // access to instance members of the base type possible
++                                              may_access_instance_members = true;
++                                      }
++                              }
++                      }
++
++                      if (symbol_reference == null && inner.value_type != null) {
++                              if (pointer_member_access) {
++                                      symbol_reference = inner.value_type.get_pointer_member (member_name);
++                              } else {
++                                      if (inner.value_type.data_type != null) {
++                                              base_symbol = inner.value_type.data_type;
++                                      }
++                                      symbol_reference = inner.value_type.get_member (member_name);
++                              }
++                              if (symbol_reference != null) {
++                                      // inner expression is variable, field, or parameter
++                                      // access to instance members of the corresponding type possible
++                                      may_access_instance_members = true;
++                              }
++                      }
++
++                      if (symbol_reference == null && inner.value_type != null && inner.value_type.is_dynamic) {
++                              // allow late bound members for dynamic types
++                              var dynamic_object_type = (ObjectType) inner.value_type;
++                              if (parent_node is InvocationExpression) {
++                                      var invoc = (InvocationExpression) parent_node;
++                                      if (invoc.call == this) {
++                                              // dynamic method
++                                              DataType ret_type;
++                                              if (invoc.target_type != null) {
++                                                      ret_type = invoc.target_type.copy ();
++                                                      ret_type.value_owned = true;
++                                              } else if (invoc.parent_node is ExpressionStatement) {
++                                                      ret_type = new VoidType ();
++                                              } else {
++                                                      // expect dynamic object of the same type
++                                                      ret_type = inner.value_type.copy ();
++                                              }
++                                              var m = new DynamicMethod (inner.value_type, member_name, ret_type, source_reference);
++                                              m.invocation = invoc;
++                                              m.add_error_type (new ErrorType (null, null));
++                                              m.access = SymbolAccessibility.PUBLIC;
++                                              m.add_parameter (new FormalParameter.with_ellipsis ());
++                                              dynamic_object_type.type_symbol.scope.add (null, m);
++                                              symbol_reference = m;
++                                      }
++                              } else if (parent_node is Assignment) {
++                                      var a = (Assignment) parent_node;
++                                      if (a.left == this
++                                          && (a.operator == AssignmentOperator.ADD
++                                              || a.operator == AssignmentOperator.SUB)) {
++                                              // dynamic signal
++                                              var s = new DynamicSignal (inner.value_type, member_name, new VoidType (), source_reference);
++                                              s.handler = a.right;
++                                              s.access = SymbolAccessibility.PUBLIC;
++                                              dynamic_object_type.type_symbol.scope.add (null, s);
++                                              symbol_reference = s;
++                                      } else if (a.left == this) {
++                                              // dynamic property assignment
++                                              var prop = new DynamicProperty (inner.value_type, member_name, source_reference);
++                                              prop.access = SymbolAccessibility.PUBLIC;
++                                              prop.set_accessor = new PropertyAccessor (false, true, false, null, prop.source_reference);
++                                              prop.set_accessor.access = SymbolAccessibility.PUBLIC;
++                                              prop.owner = inner.value_type.data_type.scope;
++                                              dynamic_object_type.type_symbol.scope.add (null, prop);
++                                              symbol_reference = prop;
++                                      }
++                              }
++                              if (symbol_reference == null) {
++                                      // dynamic property read access
++                                      var prop = new DynamicProperty (inner.value_type, member_name, source_reference);
++                                      if (target_type != null) {
++                                              prop.property_type = target_type;
++                                      } else {
++                                              // expect dynamic object of the same type
++                                              prop.property_type = inner.value_type.copy ();
++                                      }
++                                      prop.access = SymbolAccessibility.PUBLIC;
++                                      prop.get_accessor = new PropertyAccessor (true, false, false, null, prop.source_reference);
++                                      prop.get_accessor.access = SymbolAccessibility.PUBLIC;
++                                      prop.owner = inner.value_type.data_type.scope;
++                                      dynamic_object_type.type_symbol.scope.add (null, prop);
++                                      symbol_reference = prop;
++                              }
++                              if (symbol_reference != null) {
++                                      may_access_instance_members = true;
++                              }
++                      }
++              }
++
++              if (symbol_reference == null) {
++                      error = true;
++
++                      string base_type_name = "(null)";
++                      if (inner != null && inner.value_type != null) {
++                              base_type_name = inner.value_type.to_string ();
++                      } else if (base_symbol != null) {
++                              base_type_name = base_symbol.get_full_name ();
++                      }
++
++                      Report.error (source_reference, "The name `%s' does not exist in the context of `%s'".printf (member_name, base_type_name));
++                      return false;
++              }
++
++              var member = symbol_reference;
++              var access = SymbolAccessibility.PUBLIC;
++              bool instance = false;
++              bool klass = false;
++              if (member is Field) {
++                      var f = (Field) member;
++                      access = f.access;
++                      instance = (f.binding == MemberBinding.INSTANCE);
++                      klass = (f.binding == MemberBinding.CLASS);
++              } else if (member is Method) {
++                      var m = (Method) member;
++                      access = m.access;
++                      if (!(m is CreationMethod)) {
++                              instance = (m.binding == MemberBinding.INSTANCE);
++                      }
++                      klass = (m.binding == MemberBinding.CLASS);
++              } else if (member is Property) {
++                      var prop = (Property) member;
++                      if (!prop.check (analyzer)) {
++                              error = true;
++                              return false;
++                      }
++                      access = prop.access;
++                      if (lvalue) {
++                              if (prop.set_accessor == null) {
++                                      error = true;
++                                      Report.error (source_reference, "Property `%s' is read-only".printf (prop.get_full_name ()));
++                                      return false;
++                              }
++                              if (prop.access == SymbolAccessibility.PUBLIC) {
++                                      access = prop.set_accessor.access;
++                              } else if (prop.access == SymbolAccessibility.PROTECTED
++                                         && prop.set_accessor.access != SymbolAccessibility.PUBLIC) {
++                                      access = prop.set_accessor.access;
++                              }
++                      } else {
++                              if (prop.get_accessor == null) {
++                                      error = true;
++                                      Report.error (source_reference, "Property `%s' is write-only".printf (prop.get_full_name ()));
++                                      return false;
++                              }
++                              if (prop.access == SymbolAccessibility.PUBLIC) {
++                                      access = prop.get_accessor.access;
++                              } else if (prop.access == SymbolAccessibility.PROTECTED
++                                         && prop.get_accessor.access != SymbolAccessibility.PUBLIC) {
++                                      access = prop.get_accessor.access;
++                              }
++                      }
++                      instance = (prop.binding == MemberBinding.INSTANCE);
++              } else if (member is Signal) {
++                      instance = true;
++              }
++
++              if (access == SymbolAccessibility.PRIVATE) {
++                      var target_type = member.parent_symbol;
++
++                      bool in_target_type = false;
++                      for (Symbol this_symbol = analyzer.current_symbol; this_symbol != null; this_symbol = this_symbol.parent_symbol) {
++                              if (target_type == this_symbol) {
++                                      in_target_type = true;
++                                      break;
++                              }
++                      }
++
++                      if (!in_target_type) {
++                              error = true;
++                              Report.error (source_reference, "Access to private member `%s' denied".printf (member.get_full_name ()));
++                              return false;
++                      }
++              }
++              if ((instance || klass) && !may_access_instance_members) {
++                      prototype_access = true;
++
++                      if (symbol_reference is Method) {
++                              // also set static type for prototype access
++                              // required when using instance methods as delegates in constants
++                              // TODO replace by MethodPrototype
++                              value_type = analyzer.get_value_type_for_symbol (symbol_reference, lvalue);
++                      } else if (symbol_reference is Field) {
++                              value_type = new FieldPrototype ((Field) symbol_reference);
++                      }
++              } else {
++                      // implicit this access
++                      if (instance && inner == null) {
++                              inner = new MemberAccess (null, "this", source_reference);
++                              inner.value_type = this_parameter.parameter_type.copy ();
++                              inner.symbol_reference = this_parameter;
++                      }
++
++                      value_type = analyzer.get_value_type_for_symbol (symbol_reference, lvalue);
++
++                      // resolve generic return values
++                      if (value_type != null && value_type.type_parameter != null) {
++                              if (inner != null) {
++                                      value_type = analyzer.get_actual_type (inner.value_type, symbol_reference, value_type, this);
++                                      if (value_type == null) {
++                                              return false;
++                                      }
++                              }
++                      }
++
++                      if (symbol_reference is Method) {
++                              var m = (Method) symbol_reference;
++
++                              Method base_method;
++                              if (m.base_method != null) {
++                                      base_method = m.base_method;
++                              } else if (m.base_interface_method != null) {
++                                      base_method = m.base_interface_method;
++                              } else {
++                                      base_method = m;
++                              }
++
++                              if (instance && base_method.parent_symbol != null) {
++                                      inner.target_type = analyzer.get_data_type_for_symbol ((TypeSymbol) base_method.parent_symbol);
++                              }
++                      } else if (symbol_reference is Property) {
++                              var prop = (Property) symbol_reference;
++
++                              Property base_property;
++                              if (prop.base_property != null) {
++                                      base_property = prop.base_property;
++                              } else if (prop.base_interface_property != null) {
++                                      base_property = prop.base_interface_property;
++                              } else {
++                                      base_property = prop;
++                              }
++
++                              if (instance && base_property.parent_symbol != null) {
++                                      inner.target_type = analyzer.get_data_type_for_symbol ((TypeSymbol) base_property.parent_symbol);
++                              }
++                      } else if ((symbol_reference is Field
++                                  || symbol_reference is Signal)
++                                 && instance && symbol_reference.parent_symbol != null) {
++                              inner.target_type = analyzer.get_data_type_for_symbol ((TypeSymbol) symbol_reference.parent_symbol);
++                      }
++              }
++
++              analyzer.current_source_file.add_symbol_dependency (symbol_reference, SourceFileDependencyType.SOURCE);
++
++              return !error;
++      }
+ }
+Index: vala/valaenumvalue.vala
+===================================================================
+--- vala/valaenumvalue.vala    (revision 1971)
++++ vala/valaenumvalue.vala    (revision 2004)
+@@ -128,4 +128,18 @@
+       public void set_cname (string cname) {
+               this.cname = cname;
+       }
++
++      public override bool check (SemanticAnalyzer analyzer) {
++              if (checked) {
++                      return !error;
++              }
++
++              checked = true;
++
++              process_attributes ();
++
++              accept_children (analyzer);
++
++              return !error;
++      }
+ }
+Index: vala/valabinaryexpression.vala
+===================================================================
+--- vala/valabinaryexpression.vala     (revision 1971)
++++ vala/valabinaryexpression.vala     (revision 2004)
+@@ -20,7 +20,7 @@
+  *    Jürg Billeter <j@bitron.ch>
+  */
+-using GLib;
++using Gee;
+ /**
+  * Represents an expression with two operands in the source code.
+@@ -137,6 +137,169 @@
+       public override bool is_non_null () {
+               return left.is_non_null () && right.is_non_null ();
+       }
++
++      public override bool check (SemanticAnalyzer analyzer) {
++              if (checked) {
++                      return !error;
++              }
++
++              checked = true;
++
++              if (left.error || right.error) {
++                      /* if there were any errors in inner expressions, skip type check */
++                      error = true;
++                      return false;
++              }
++
++              if (left.value_type == null) {
++                      Report.error (left.source_reference, "invalid left operand");
++                      error = true;
++                      return false;
++              }
++
++              if (operator != BinaryOperator.IN && right.value_type == null) {
++                      Report.error (right.source_reference, "invalid right operand");
++                      error = true;
++                      return false;
++              }
++
++              if (left.value_type.data_type == analyzer.string_type.data_type
++                  && operator == BinaryOperator.PLUS) {
++                      // string concatenation
++
++                      if (right.value_type == null || right.value_type.data_type != analyzer.string_type.data_type) {
++                              error = true;
++                              Report.error (source_reference, "Operands must be strings");
++                              return false;
++                      }
++
++                      value_type = analyzer.string_type.copy ();
++                      if (left.is_constant () && right.is_constant ()) {
++                              value_type.value_owned = false;
++                      } else {
++                              value_type.value_owned = true;
++                      }
++              } else if (operator == BinaryOperator.PLUS
++                         || operator == BinaryOperator.MINUS
++                         || operator == BinaryOperator.MUL
++                         || operator == BinaryOperator.DIV) {
++                      // check for pointer arithmetic
++                      if (left.value_type is PointerType) {
++                              var offset_type = right.value_type.data_type as Struct;
++                              if (offset_type != null && offset_type.is_integer_type ()) {
++                                      if (operator == BinaryOperator.PLUS
++                                          || operator == BinaryOperator.MINUS) {
++                                              // pointer arithmetic: pointer +/- offset
++                                              value_type = left.value_type.copy ();
++                                      }
++                              } else if (right.value_type is PointerType) {
++                                      // pointer arithmetic: pointer - pointer
++                                      value_type = analyzer.size_t_type;
++                              }
++                      }
++
++                      if (value_type == null) {
++                              value_type = analyzer.get_arithmetic_result_type (left.value_type, right.value_type);
++                      }
++
++                      if (value_type == null) {
++                              error = true;
++                              Report.error (source_reference, "Arithmetic operation not supported for types `%s' and `%s'".printf (left.value_type.to_string (), right.value_type.to_string ()));
++                              return false;
++                      }
++              } else if (operator == BinaryOperator.MOD
++                         || operator == BinaryOperator.SHIFT_LEFT
++                         || operator == BinaryOperator.SHIFT_RIGHT
++                         || operator == BinaryOperator.BITWISE_XOR) {
++                      value_type = analyzer.get_arithmetic_result_type (left.value_type, right.value_type);
++
++                      if (value_type == null) {
++                              error = true;
++                              Report.error (source_reference, "Arithmetic operation not supported for types `%s' and `%s'".printf (left.value_type.to_string (), right.value_type.to_string ()));
++                              return false;
++                      }
++              } else if (operator == BinaryOperator.LESS_THAN
++                         || operator == BinaryOperator.GREATER_THAN
++                         || operator == BinaryOperator.LESS_THAN_OR_EQUAL
++                         || operator == BinaryOperator.GREATER_THAN_OR_EQUAL) {
++                      if (left.value_type.compatible (analyzer.string_type)
++                          && right.value_type.compatible (analyzer.string_type)) {
++                              // string comparison
++                              } else if (left.value_type is PointerType && right.value_type is PointerType) {
++                                      // pointer arithmetic
++                      } else {
++                              var resulting_type = analyzer.get_arithmetic_result_type (left.value_type, right.value_type);
++
++                              if (resulting_type == null) {
++                                      error = true;
++                                      Report.error (source_reference, "Relational operation not supported for types `%s' and `%s'".printf (left.value_type.to_string (), right.value_type.to_string ()));
++                                      return false;
++                              }
++                      }
++
++                      value_type = analyzer.bool_type;
++              } else if (operator == BinaryOperator.EQUALITY
++                         || operator == BinaryOperator.INEQUALITY) {
++                      /* relational operation */
++
++                      if (!right.value_type.compatible (left.value_type)
++                          && !left.value_type.compatible (right.value_type)) {
++                              Report.error (source_reference, "Equality operation: `%s' and `%s' are incompatible".printf (right.value_type.to_string (), left.value_type.to_string ()));
++                              error = true;
++                              return false;
++                      }
++
++                      if (left.value_type.compatible (analyzer.string_type)
++                          && right.value_type.compatible (analyzer.string_type)) {
++                              // string comparison
++                      }
++
++                      value_type = analyzer.bool_type;
++              } else if (operator == BinaryOperator.BITWISE_AND
++                         || operator == BinaryOperator.BITWISE_OR) {
++                      // integer type or flags type
++
++                      value_type = left.value_type;
++              } else if (operator == BinaryOperator.AND
++                         || operator == BinaryOperator.OR) {
++                      if (!left.value_type.compatible (analyzer.bool_type) || !right.value_type.compatible (analyzer.bool_type)) {
++                              error = true;
++                              Report.error (source_reference, "Operands must be boolean");
++                      }
++
++                      value_type = analyzer.bool_type;
++              } else if (operator == BinaryOperator.IN) {
++                      // integer type or flags type or collection/map
++
++                      /* handle collections and maps */
++                      var container_type = right.value_type.data_type;
++                      
++                      if ((analyzer.collection_type != null && container_type.is_subtype_of (analyzer.collection_type))
++                          || (analyzer.map_type != null && container_type.is_subtype_of (analyzer.map_type))) {
++                              Symbol contains_sym = null;
++                              if (container_type.is_subtype_of (analyzer.collection_type)) {
++                                      contains_sym = analyzer.collection_type.scope.lookup ("contains");
++                              } else if (container_type.is_subtype_of (analyzer.map_type)) {
++                                      contains_sym = analyzer.map_type.scope.lookup ("contains");
++                              }
++                              var contains_method = (Method) contains_sym;
++                              Gee.List<FormalParameter> contains_params = contains_method.get_parameters ();
++                              Iterator<FormalParameter> contains_params_it = contains_params.iterator ();
++                              contains_params_it.next ();
++                              var contains_param = contains_params_it.get ();
++
++                              var key_type = analyzer.get_actual_type (right.value_type, contains_method, contains_param.parameter_type, this);
++                              left.target_type = key_type;
++                      }
++                      
++                      value_type = analyzer.bool_type;
++                      
++              } else {
++                      assert_not_reached ();
++              }
++
++              return !error;
++      }
+ }
+ public enum Vala.BinaryOperator {
+Index: vala/valacreationmethod.vala
+===================================================================
+--- vala/valacreationmethod.vala       (revision 1971)
++++ vala/valacreationmethod.vala       (revision 2004)
+@@ -114,4 +114,42 @@
+                       return "%s%s_%s".printf (parent.get_lower_case_cprefix (), infix, name);
+               }
+       }
++
++      public override bool check (SemanticAnalyzer analyzer) {
++              if (checked) {
++                      return !error;
++              }
++
++              checked = true;
++
++              process_attributes ();
++
++              if (type_name != null && type_name != analyzer.current_symbol.name) {
++                      // type_name is null for constructors generated by GIdlParser
++                      Report.error (source_reference, "missing return type in method `%s.%s´".printf (analyzer.current_symbol.get_full_name (), type_name));
++                      error = true;
++                      return false;
++              }
++
++              analyzer.current_symbol = this;
++              analyzer.current_return_type = return_type;
++
++              accept_children (analyzer);
++
++              analyzer.current_symbol = analyzer.current_symbol.parent_symbol;
++              analyzer.current_return_type = null;
++
++              if (analyzer.current_symbol.parent_symbol is Method) {
++                      /* lambda expressions produce nested methods */
++                      var up_method = (Method) analyzer.current_symbol.parent_symbol;
++                      analyzer.current_return_type = up_method.return_type;
++              }
++
++              if (is_abstract || is_virtual || overrides) {
++                      Report.error (source_reference, "The creation method `%s' cannot be marked as override, virtual, or abstract".printf (get_full_name ()));
++                      return false;
++              }
++
++              return !error;
++      }
+ }
+Index: vala/valadelegate.vala
+===================================================================
+--- vala/valadelegate.vala     (revision 1971)
++++ vala/valadelegate.vala     (revision 2004)
+@@ -327,4 +327,18 @@
+               return str;
+       }
++
++      public override bool check (SemanticAnalyzer analyzer) {
++              if (checked) {
++                      return !error;
++              }
++
++              checked = true;
++
++              process_attributes ();
++
++              accept_children (analyzer);
++
++              return !error;
++      }
+ }
+Index: vala/valaobjectcreationexpression.vala
+===================================================================
+--- vala/valaobjectcreationexpression.vala     (revision 1971)
++++ vala/valaobjectcreationexpression.vala     (revision 2004)
+@@ -149,4 +149,201 @@
+                       type_reference = new_type;
+               }
+       }
++
++      public override bool check (SemanticAnalyzer analyzer) {
++              if (checked) {
++                      return !error;
++              }
++
++              checked = true;
++
++              if (member_name != null) {
++                      member_name.accept (analyzer);
++              }
++
++              TypeSymbol type = null;
++
++              if (type_reference == null) {
++                      if (member_name == null) {
++                              error = true;
++                              Report.error (source_reference, "Incomplete object creation expression");
++                              return false;
++                      }
++
++                      if (member_name.symbol_reference == null) {
++                              error = true;
++                              return false;
++                      }
++
++                      var constructor_sym = member_name.symbol_reference;
++                      var type_sym = member_name.symbol_reference;
++
++                      var type_args = member_name.get_type_arguments ();
++
++                      if (constructor_sym is Method) {
++                              type_sym = constructor_sym.parent_symbol;
++
++                              var constructor = (Method) constructor_sym;
++                              if (!(constructor_sym is CreationMethod)) {
++                                      error = true;
++                                      Report.error (source_reference, "`%s' is not a creation method".printf (constructor.get_full_name ()));
++                                      return false;
++                              }
++
++                              symbol_reference = constructor;
++
++                              // inner expression can also be base access when chaining constructors
++                              var ma = member_name.inner as MemberAccess;
++                              if (ma != null) {
++                                      type_args = ma.get_type_arguments ();
++                              }
++                      }
++
++                      if (type_sym is Class) {
++                              type = (TypeSymbol) type_sym;
++                              type_reference = new ObjectType ((Class) type);
++                      } else if (type_sym is Struct) {
++                              type = (TypeSymbol) type_sym;
++                              type_reference = new ValueType (type);
++                      } else if (type_sym is ErrorCode) {
++                              type_reference = new ErrorType ((ErrorDomain) type_sym.parent_symbol, (ErrorCode) type_sym, source_reference);
++                              symbol_reference = type_sym;
++                      } else {
++                              error = true;
++                              Report.error (source_reference, "`%s' is not a class, struct, or error code".printf (type_sym.get_full_name ()));
++                              return false;
++                      }
++
++                      foreach (DataType type_arg in type_args) {
++                              type_reference.add_type_argument (type_arg);
++
++                              analyzer.current_source_file.add_type_dependency (type_arg, SourceFileDependencyType.SOURCE);
++                      }
++              } else {
++                      type = type_reference.data_type;
++              }
++
++              analyzer.current_source_file.add_symbol_dependency (type, SourceFileDependencyType.SOURCE);
++
++              value_type = type_reference.copy ();
++              value_type.value_owned = true;
++
++              int given_num_type_args = type_reference.get_type_arguments ().size;
++              int expected_num_type_args = 0;
++
++              if (type is Class) {
++                      var cl = (Class) type;
++
++                      expected_num_type_args = cl.get_type_parameters ().size;
++
++                      if (struct_creation) {
++                              error = true;
++                              Report.error (source_reference, "syntax error, use `new' to create new objects");
++                              return false;
++                      }
++
++                      if (cl.is_abstract) {
++                              value_type = null;
++                              error = true;
++                              Report.error (source_reference, "Can't create instance of abstract class `%s'".printf (cl.get_full_name ()));
++                              return false;
++                      }
++
++                      if (symbol_reference == null) {
++                              symbol_reference = cl.default_construction_method;
++                      }
++
++                      while (cl != null) {
++                              if (cl == analyzer.initially_unowned_type) {
++                                      value_type.floating_reference = true;
++                                      break;
++                              }
++
++                              cl = cl.base_class;
++                      }
++              } else if (type is Struct) {
++                      var st = (Struct) type;
++
++                      expected_num_type_args = st.get_type_parameters ().size;
++
++                      if (!struct_creation) {
++                              Report.warning (source_reference, "deprecated syntax, don't use `new' to initialize structs");
++                      }
++
++                      if (symbol_reference == null) {
++                              symbol_reference = st.default_construction_method;
++                      }
++              }
++
++              if (expected_num_type_args > given_num_type_args) {
++                      error = true;
++                      Report.error (source_reference, "too few type arguments");
++                      return false;
++              } else if (expected_num_type_args < given_num_type_args) {
++                      error = true;
++                      Report.error (source_reference, "too many type arguments");
++                      return false;
++              }
++
++              if (symbol_reference == null && get_argument_list ().size != 0) {
++                      value_type = null;
++                      error = true;
++                      Report.error (source_reference, "No arguments allowed when constructing type `%s'".printf (type.get_full_name ()));
++                      return false;
++              }
++
++              if (symbol_reference is Method) {
++                      var m = (Method) symbol_reference;
++
++                      var args = get_argument_list ();
++                      Iterator<Expression> arg_it = args.iterator ();
++                      foreach (FormalParameter param in m.get_parameters ()) {
++                              if (param.ellipsis) {
++                                      break;
++                              }
++
++                              if (arg_it.next ()) {
++                                      Expression arg = arg_it.get ();
++
++                                      /* store expected type for callback parameters */
++                                      arg.target_type = param.parameter_type;
++                              }
++                      }
++
++                      foreach (Expression arg in args) {
++                              arg.accept (analyzer);
++                      }
++
++                      analyzer.check_arguments (this, new MethodType (m), m.get_parameters (), args);
++
++                      foreach (DataType error_type in m.get_error_types ()) {
++                              // ensure we can trace back which expression may throw errors of this type
++                              var call_error_type = error_type.copy ();
++                              call_error_type.source_reference = source_reference;
++
++                              add_error_type (call_error_type);
++                      }
++              } else if (type_reference is ErrorType) {
++                      accept_children (analyzer);
++
++                      if (get_argument_list ().size == 0) {
++                              error = true;
++                              Report.error (source_reference, "Too few arguments, errors need at least 1 argument");
++                      } else {
++                              Iterator<Expression> arg_it = get_argument_list ().iterator ();
++                              arg_it.next ();
++                              var ex = arg_it.get ();
++                              if (ex.value_type == null || !ex.value_type.compatible (analyzer.string_type)) {
++                                      error = true;
++                                      Report.error (source_reference, "Invalid type for argument 1");
++                              }
++                      }
++              }
++
++              foreach (MemberInitializer init in get_object_initializer ()) {
++                      analyzer.visit_member_initializer (init, type_reference);
++              }
++
++              return !error;
++      }
+ }
+Index: vala/valaerrordomain.vala
+===================================================================
+--- vala/valaerrordomain.vala  (revision 1971)
++++ vala/valaerrordomain.vala  (revision 2004)
+@@ -215,4 +215,18 @@
+       public override string? get_set_value_function () {
+               return "g_value_set_pointer";
+       }
++
++      public override bool check (SemanticAnalyzer analyzer) {
++              if (checked) {
++                      return !error;
++              }
++
++              checked = true;
++
++              process_attributes ();
++
++              accept_children (analyzer);
++
++              return !error;
++      }
+ }
+Index: vala/valaifstatement.vala
+===================================================================
+--- vala/valaifstatement.vala  (revision 1971)
++++ vala/valaifstatement.vala  (revision 2004)
+@@ -86,4 +86,35 @@
+                       condition = new_node;
+               }
+       }
++
++      public override bool check (SemanticAnalyzer analyzer) {
++              if (checked) {
++                      return !error;
++              }
++
++              checked = true;
++
++              accept_children (analyzer);
++
++              if (condition.error) {
++                      /* if there was an error in the condition, skip this check */
++                      error = true;
++                      return false;
++              }
++
++              if (!condition.value_type.compatible (analyzer.bool_type)) {
++                      error = true;
++                      Report.error (condition.source_reference, "Condition must be boolean");
++                      return false;
++              }
++
++              add_error_types (condition.get_error_types ());
++              add_error_types (true_statement.get_error_types ());
++
++              if (false_statement != null) {
++                      add_error_types (false_statement.get_error_types ());
++              }
++
++              return !error;
++      }
+ }
+Index: vala/valaswitchsection.vala
+===================================================================
+--- vala/valaswitchsection.vala        (revision 1971)
++++ vala/valaswitchsection.vala        (revision 2004)
+@@ -80,4 +80,31 @@
+                       st.accept (visitor);
+               }
+       }
++
++      public override bool check (SemanticAnalyzer analyzer) {
++              if (checked) {
++                      return !error;
++              }
++
++              checked = true;
++
++              foreach (SwitchLabel label in get_labels ()) {
++                      label.accept (analyzer);
++              }
++
++              owner = analyzer.current_symbol.scope;
++              analyzer.current_symbol = this;
++
++              foreach (Statement st in get_statements ()) {
++                      st.accept (analyzer);
++              }
++
++              foreach (LocalVariable local in get_local_variables ()) {
++                      local.active = false;
++              }
++
++              analyzer.current_symbol = analyzer.current_symbol.parent_symbol;
++
++              return !error;
++      }
+ }
+Index: vala/valaenum.vala
+===================================================================
+--- vala/valaenum.vala (revision 1971)
++++ vala/valaenum.vala (revision 2004)
+@@ -289,4 +289,26 @@
+       public override string? get_default_value () {
+               return "0";
+       }
++
++      public override string? get_type_signature () {
++              if (is_flags) {
++                      return "u";
++              } else {
++                      return "i";
++              }
++      }
++
++      public override bool check (SemanticAnalyzer analyzer) {
++              if (checked) {
++                      return !error;
++              }
++
++              checked = true;
++
++              process_attributes ();
++
++              accept_children (analyzer);
++
++              return !error;
++      }
+ }
+Index: vala/valapropertyaccessor.vala
+===================================================================
+--- vala/valapropertyaccessor.vala     (revision 1971)
++++ vala/valapropertyaccessor.vala     (revision 2004)
+@@ -131,4 +131,55 @@
+                       }
+               }
+       }
++
++      public override bool check (SemanticAnalyzer analyzer) {
++              if (checked) {
++                      return !error;
++              }
++
++              checked = true;
++
++              process_attributes ();
++
++              var old_return_type = analyzer.current_return_type;
++              if (readable) {
++                      analyzer.current_return_type = prop.property_type;
++              } else {
++                      // void
++                      analyzer.current_return_type = new VoidType ();
++              }
++
++              if (!prop.external_package) {
++                      if (body == null && !prop.interface_only && !prop.is_abstract) {
++                              /* no accessor body specified, insert default body */
++
++                              if (prop.parent_symbol is Interface) {
++                                      error = true;
++                                      Report.error (source_reference, "Automatic properties can't be used in interfaces");
++                                      return false;
++                              }
++                              automatic_body = true;
++                              body = new Block (source_reference);
++                              var ma = new MemberAccess.simple ("_%s".printf (prop.name), source_reference);
++                              if (readable) {
++                                      body.add_statement (new ReturnStatement (ma, source_reference));
++                              } else {
++                                      var assignment = new Assignment (ma, new MemberAccess.simple ("value", source_reference), AssignmentOperator.SIMPLE, source_reference);
++                                      body.add_statement (new ExpressionStatement (assignment));
++                              }
++                      }
++
++                      if (body != null && (writable || construction)) {
++                              var value_type = prop.property_type.copy ();
++                              value_parameter = new FormalParameter ("value", value_type, source_reference);
++                              body.scope.add (value_parameter.name, value_parameter);
++                      }
++              }
++
++              accept_children (analyzer);
++
++              analyzer.current_return_type = old_return_type;
++
++              return !error;
++      }
+ }
+Index: vala/valaobjecttype.vala
+===================================================================
+--- vala/valaobjecttype.vala   (revision 1971)
++++ vala/valaobjecttype.vala   (revision 2004)
+@@ -98,4 +98,8 @@
+                       return null;
+               }
+       }
++
++      public override bool check (SemanticAnalyzer analyzer) {
++              return type_symbol.check (analyzer);
++      }
+ }
+Index: vala/valasemanticanalyzer.vala
+===================================================================
+--- vala/valasemanticanalyzer.vala     (revision 1971)
++++ vala/valasemanticanalyzer.vala     (revision 2004)
+@@ -30,46 +30,44 @@
+ public class Vala.SemanticAnalyzer : CodeVisitor {
+       public CodeContext context { get; set; }
+-      Symbol root_symbol;
++      public Symbol root_symbol;
+       public Symbol current_symbol { get; set; }
+       public SourceFile current_source_file { get; set; }
+-      DataType current_return_type;
+-      Class current_class;
+-      Struct current_struct;
++      public DataType current_return_type;
++      public Class current_class;
++      public Struct current_struct;
+-      Gee.List<UsingDirective> current_using_directives;
++      public DataType bool_type;
++      public DataType string_type;
++      public DataType uchar_type;
++      public DataType short_type;
++      public DataType ushort_type;
++      public DataType int_type;
++      public DataType uint_type;
++      public DataType long_type;
++      public DataType ulong_type;
++      public DataType size_t_type;
++      public DataType ssize_t_type;
++      public DataType int8_type;
++      public DataType unichar_type;
++      public DataType double_type;
++      public DataType type_type;
++      public Class object_type;
++      public TypeSymbol initially_unowned_type;
++      public DataType glist_type;
++      public DataType gslist_type;
++      public Class gerror_type;
++      public DataType iterable_type;
++      public Interface iterator_type;
++      public Interface list_type;
++      public Interface collection_type;
++      public Interface map_type;
+-      DataType bool_type;
+-      DataType string_type;
+-      DataType uchar_type;
+-      DataType short_type;
+-      DataType ushort_type;
+-      DataType int_type;
+-      DataType uint_type;
+-      DataType long_type;
+-      DataType ulong_type;
+-      DataType size_t_type;
+-      DataType ssize_t_type;
+-      DataType int8_type;
+-      DataType unichar_type;
+-      DataType double_type;
+-      DataType type_type;
+-      Class object_type;
+-      TypeSymbol initially_unowned_type;
+-      DataType glist_type;
+-      DataType gslist_type;
+-      Class gerror_type;
+-      DataType iterable_type;
+-      Interface iterator_type;
+-      Interface list_type;
+-      Interface collection_type;
+-      Interface map_type;
+-
+       private int next_lambda_id = 0;
+       // keep replaced alive to make sure they remain valid
+       // for the whole execution of CodeNode.accept
+-      Gee.List<CodeNode> replaced_nodes = new ArrayList<CodeNode> ();
++      public Gee.List<CodeNode> replaced_nodes = new ArrayList<CodeNode> ();
+       public SemanticAnalyzer () {
+       }
+@@ -129,499 +127,65 @@
+       public override void visit_source_file (SourceFile file) {
+               current_source_file = file;
+-              current_using_directives = file.get_using_directives ();
+               next_lambda_id = 0;
+               file.accept_children (this);
+-
+-              current_using_directives = null;
+       }
+       public override void visit_namespace (Namespace ns) {
+-              ns.process_attributes ();
++              ns.check (this);
+       }
+       public override void visit_class (Class cl) {
+-              cl.process_attributes ();
+-
+-              current_symbol = cl;
+-              current_class = cl;
+-
+-              foreach (DataType base_type_reference in cl.get_base_types ()) {
+-                      // check whether base type is at least as accessible as the class
+-                      if (!is_type_accessible (cl, base_type_reference)) {
+-                              cl.error = true;
+-                              Report.error (cl.source_reference, "base type `%s` is less accessible than class `%s`".printf (base_type_reference.to_string (), cl.get_full_name ()));
+-                              return;
+-                      }
+-
+-                      current_source_file.add_type_dependency (base_type_reference, SourceFileDependencyType.HEADER_FULL);
+-              }
+-
+-              cl.accept_children (this);
+-
+-              /* compact classes cannot implement interfaces */
+-              if (cl.is_compact) {
+-                      foreach (DataType base_type in cl.get_base_types ()) {
+-                              if (base_type.data_type is Interface) {
+-                                      cl.error = true;
+-                                      Report.error (cl.source_reference, "compact classes `%s` may not implement interfaces".printf (cl.get_full_name ()));
+-                              }
+-                      }
+-              }
+-
+-              /* gather all prerequisites */
+-              Gee.List<TypeSymbol> prerequisites = new ArrayList<TypeSymbol> ();
+-              foreach (DataType base_type in cl.get_base_types ()) {
+-                      if (base_type.data_type is Interface) {
+-                              get_all_prerequisites ((Interface) base_type.data_type, prerequisites);
+-                      }
+-              }
+-              /* check whether all prerequisites are met */
+-              Gee.List<string> missing_prereqs = new ArrayList<string> ();
+-              foreach (TypeSymbol prereq in prerequisites) {
+-                      if (!class_is_a (cl, prereq)) {
+-                              missing_prereqs.insert (0, prereq.get_full_name ());
+-                      }
+-              }
+-              /* report any missing prerequisites */
+-              if (missing_prereqs.size > 0) {
+-                      cl.error = true;
+-
+-                      string error_string = "%s: some prerequisites (".printf (cl.get_full_name ());
+-                      bool first = true;
+-                      foreach (string s in missing_prereqs) {
+-                              if (first) {
+-                                      error_string = "%s`%s'".printf (error_string, s);
+-                                      first = false;
+-                              } else {
+-                                      error_string = "%s, `%s'".printf (error_string, s);
+-                              }
+-                      }
+-                      error_string += ") are not met";
+-                      Report.error (cl.source_reference, error_string);
+-              }
+-
+-              /* VAPI classes don't have to specify overridden methods */
+-              if (!cl.external_package) {
+-                      /* all abstract symbols defined in base types have to be at least defined (or implemented) also in this type */
+-                      foreach (DataType base_type in cl.get_base_types ()) {
+-                              if (base_type.data_type is Interface) {
+-                                      Interface iface = (Interface) base_type.data_type;
+-
+-                                      if (cl.base_class != null && cl.base_class.is_subtype_of (iface)) {
+-                                              // reimplementation of interface, class is not required to reimplement all methods
+-                                              break;
+-                                      }
+-
+-                                      /* We do not need to do expensive equality checking here since this is done
+-                                       * already. We only need to guarantee the symbols are present.
+-                                       */
+-
+-                                      /* check methods */
+-                                      foreach (Method m in iface.get_methods ()) {
+-                                              if (m.is_abstract) {
+-                                                      Symbol sym = null;
+-                                                      var base_class = cl;
+-                                                      while (base_class != null && !(sym is Method)) {
+-                                                              sym = base_class.scope.lookup (m.name);
+-                                                              base_class = base_class.base_class;
+-                                                      }
+-                                                      if (!(sym is Method)) {
+-                                                              cl.error = true;
+-                                                              Report.error (cl.source_reference, "`%s' does not implement interface method `%s'".printf (cl.get_full_name (), m.get_full_name ()));
+-                                                      }
+-                                              }
+-                                      }
+-
+-                                      /* check properties */
+-                                      foreach (Property prop in iface.get_properties ()) {
+-                                              if (prop.is_abstract) {
+-                                                      Symbol sym = null;
+-                                                      var base_class = cl;
+-                                                      while (base_class != null && !(sym is Property)) {
+-                                                              sym = base_class.scope.lookup (prop.name);
+-                                                              base_class = base_class.base_class;
+-                                                      }
+-                                                      if (!(sym is Property)) {
+-                                                              cl.error = true;
+-                                                              Report.error (cl.source_reference, "`%s' does not implement interface property `%s'".printf (cl.get_full_name (), prop.get_full_name ()));
+-                                                      }
+-                                              }
+-                                      }
+-                              }
+-                      }
+-
+-                      /* all abstract symbols defined in base classes have to be implemented in non-abstract classes */
+-                      if (!cl.is_abstract) {
+-                              var base_class = cl.base_class;
+-                              while (base_class != null && base_class.is_abstract) {
+-                                      foreach (Method base_method in base_class.get_methods ()) {
+-                                              if (base_method.is_abstract) {
+-                                                      var override_method = symbol_lookup_inherited (cl, base_method.name) as Method;
+-                                                      if (override_method == null || !override_method.overrides) {
+-                                                              cl.error = true;
+-                                                              Report.error (cl.source_reference, "`%s' does not implement abstract method `%s'".printf (cl.get_full_name (), base_method.get_full_name ()));
+-                                                      }
+-                                              }
+-                                      }
+-                                      foreach (Property base_property in base_class.get_properties ()) {
+-                                              if (base_property.is_abstract) {
+-                                                      var override_property = symbol_lookup_inherited (cl, base_property.name) as Property;
+-                                                      if (override_property == null || !override_property.overrides) {
+-                                                              cl.error = true;
+-                                                              Report.error (cl.source_reference, "`%s' does not implement abstract property `%s'".printf (cl.get_full_name (), base_property.get_full_name ()));
+-                                                      }
+-                                              }
+-                                      }
+-                                      base_class = base_class.base_class;
+-                              }
+-                      }
+-              }
+-
+-              current_symbol = current_symbol.parent_symbol;
+-              current_class = null;
++              cl.check (this);
+       }
+-      private void get_all_prerequisites (Interface iface, Gee.List<TypeSymbol> list) {
+-              foreach (DataType prereq in iface.get_prerequisites ()) {
+-                      TypeSymbol type = prereq.data_type;
+-                      /* skip on previous errors */
+-                      if (type == null) {
+-                              continue;
+-                      }
+-
+-                      list.add (type);
+-                      if (type is Interface) {
+-                              get_all_prerequisites ((Interface) type, list);
+-
+-                      }
+-              }
+-      }
+-
+-      private bool class_is_a (Class cl, TypeSymbol t) {
+-              if (cl == t) {
+-                      return true;
+-              }
+-
+-              foreach (DataType base_type in cl.get_base_types ()) {
+-                      if (base_type.data_type is Class) {
+-                              if (class_is_a ((Class) base_type.data_type, t)) {
+-                                      return true;
+-                              }
+-                      } else if (base_type.data_type == t) {
+-                              return true;
+-                      }
+-              }
+-
+-              return false;
+-      }
+-
+       public override void visit_struct (Struct st) {
+-              st.process_attributes ();
+-
+-              current_symbol = st;
+-              current_struct = st;
+-
+-              st.accept_children (this);
+-
+-              if (!st.external && !st.external_package && st.get_base_types ().size == 0 && st.get_fields ().size == 0) {
+-                      Report.error (st.source_reference, "structs cannot be empty");
+-              }
+-
+-              current_symbol = current_symbol.parent_symbol;
+-              current_struct = null;
++              st.check (this);
+       }
+       public override void visit_interface (Interface iface) {
+-              iface.process_attributes ();
+-
+-              current_symbol = iface;
+-
+-              foreach (DataType prerequisite_reference in iface.get_prerequisites ()) {
+-                      // check whether prerequisite is at least as accessible as the interface
+-                      if (!is_type_accessible (iface, prerequisite_reference)) {
+-                              iface.error = true;
+-                              Report.error (iface.source_reference, "prerequisite `%s` is less accessible than interface `%s`".printf (prerequisite_reference.to_string (), iface.get_full_name ()));
+-                              return;
+-                      }
+-
+-                      current_source_file.add_type_dependency (prerequisite_reference, SourceFileDependencyType.HEADER_FULL);
+-              }
+-
+-              /* check prerequisites */
+-              Class prereq_class;
+-              foreach (DataType prereq in iface.get_prerequisites ()) {
+-                      TypeSymbol class_or_interface = prereq.data_type;
+-                      /* skip on previous errors */
+-                      if (class_or_interface == null) {
+-                              iface.error = true;
+-                              continue;
+-                      }
+-                      /* interfaces are not allowed to have multiple instantiable prerequisites */
+-                      if (class_or_interface is Class) {
+-                              if (prereq_class != null) {
+-                                      iface.error = true;
+-                                      Report.error (iface.source_reference, "%s: Interfaces cannot have multiple instantiable prerequisites (`%s' and `%s')".printf (iface.get_full_name (), class_or_interface.get_full_name (), prereq_class.get_full_name ()));
+-                                      return;
+-                              }
+-
+-                              prereq_class = (Class) class_or_interface;
+-                      }
+-              }
+-
+-              iface.accept_children (this);
+-
+-              current_symbol = current_symbol.parent_symbol;
++              iface.check (this);
+       }
+       public override void visit_enum (Enum en) {
+-              en.process_attributes ();
+-
+-              en.accept_children (this);
++              en.check (this);
+       }
+       public override void visit_enum_value (EnumValue ev) {
+-              ev.process_attributes ();
+-
+-              ev.accept_children (this);
++              ev.check (this);
+       }
+       public override void visit_error_domain (ErrorDomain ed) {
+-              ed.process_attributes ();
++              ed.check (this);
++      }
+-              ed.accept_children (this);
++      public override void visit_error_code (ErrorCode ec) {
++              ec.check (this);
+       }
+       public override void visit_delegate (Delegate d) {
+-              d.process_attributes ();
+-
+-              d.accept_children (this);
++              d.check (this);
+       }
+       public override void visit_constant (Constant c) {
+-              c.process_attributes ();
+-
+-              c.type_reference.accept (this);
+-
+-              if (!c.external_package) {
+-                      if (c.initializer == null) {
+-                              c.error = true;
+-                              Report.error (c.source_reference, "A const field requires a initializer to be provided");
+-                      } else {
+-                              c.initializer.target_type = c.type_reference;
+-
+-                              c.initializer.accept (this);
+-                      }
+-              }
++              c.check (this);
+       }
+       public override void visit_field (Field f) {
+-              f.process_attributes ();
+-
+-              if (f.initializer != null) {
+-                      f.initializer.target_type = f.field_type;
+-              }
+-
+-              f.accept_children (this);
+-
+-              if (f.binding == MemberBinding.INSTANCE && f.parent_symbol is Interface) {
+-                      f.error = true;
+-                      Report.error (f.source_reference, "Interfaces may not have instance fields");
+-                      return;
+-              }
+-
+-              if (!f.is_internal_symbol ()) {
+-                      if (f.field_type is ValueType) {
+-                              current_source_file.add_type_dependency (f.field_type, SourceFileDependencyType.HEADER_FULL);
+-                      } else {
+-                              current_source_file.add_type_dependency (f.field_type, SourceFileDependencyType.HEADER_SHALLOW);
+-                      }
+-              } else {
+-                      if (f.parent_symbol is Namespace) {
+-                              f.error = true;
+-                              Report.error (f.source_reference, "Namespaces may not have private members");
+-                              return;
+-                      }
+-
+-                      current_source_file.add_type_dependency (f.field_type, SourceFileDependencyType.SOURCE);
+-              }
++              f.check (this);
+       }
+       public override void visit_method (Method m) {
+-              m.process_attributes ();
+-
+-              if (m.is_abstract) {
+-                      if (m.parent_symbol is Class) {
+-                              var cl = (Class) m.parent_symbol;
+-                              if (!cl.is_abstract) {
+-                                      m.error = true;
+-                                      Report.error (m.source_reference, "Abstract methods may not be declared in non-abstract classes");
+-                                      return;
+-                              }
+-                      } else if (!(m.parent_symbol is Interface)) {
+-                              m.error = true;
+-                              Report.error (m.source_reference, "Abstract methods may not be declared outside of classes and interfaces");
+-                              return;
+-                      }
+-              } else if (m.is_virtual) {
+-                      if (!(m.parent_symbol is Class) && !(m.parent_symbol is Interface)) {
+-                              m.error = true;
+-                              Report.error (m.source_reference, "Virtual methods may not be declared outside of classes and interfaces");
+-                              return;
+-                      }
+-
+-                      if (m.parent_symbol is Class) {
+-                              var cl = (Class) m.parent_symbol;
+-                              if (cl.is_compact) {
+-                                      Report.error (m.source_reference, "Virtual methods may not be declared in compact classes");
+-                                      return;
+-                              }
+-                      }
+-              } else if (m.overrides) {
+-                      if (!(m.parent_symbol is Class)) {
+-                              m.error = true;
+-                              Report.error (m.source_reference, "Methods may not be overridden outside of classes");
+-                              return;
+-                      }
+-              }
+-
+-              if (m.is_abstract && m.body != null) {
+-                      Report.error (m.source_reference, "Abstract methods cannot have bodies");
+-              } else if (m.external && m.body != null) {
+-                      Report.error (m.source_reference, "Extern methods cannot have bodies");
+-              } else if (!m.is_abstract && !m.external && !m.external_package && m.body == null) {
+-                      Report.error (m.source_reference, "Non-abstract, non-extern methods must have bodies");
+-              }
+-
+-              var old_symbol = current_symbol;
+-              var old_return_type = current_return_type;
+-              current_symbol = m;
+-              current_return_type = m.return_type;
+-
+-              var init_attr = m.get_attribute ("ModuleInit");
+-              if (init_attr != null) {
+-                      m.source_reference.file.context.module_init_method = m;
+-              }
+-
+-              if (!m.is_internal_symbol ()) {
+-                      if (m.return_type is ValueType) {
+-                              current_source_file.add_type_dependency (m.return_type, SourceFileDependencyType.HEADER_FULL);
+-                      } else {
+-                              current_source_file.add_type_dependency (m.return_type, SourceFileDependencyType.HEADER_SHALLOW);
+-                      }
+-              }
+-              current_source_file.add_type_dependency (m.return_type, SourceFileDependencyType.SOURCE);
+-
+-              m.accept_children (this);
+-
+-              current_symbol = old_symbol;
+-              current_return_type = old_return_type;
+-
+-              if (current_symbol.parent_symbol is Method) {
+-                      /* lambda expressions produce nested methods */
+-                      var up_method = (Method) current_symbol.parent_symbol;
+-                      current_return_type = up_method.return_type;
+-              }
+-
+-              if (current_symbol is Struct) {
+-                      if (m.is_abstract || m.is_virtual || m.overrides) {
+-                              Report.error (m.source_reference, "A struct member `%s' cannot be marked as override, virtual, or abstract".printf (m.get_full_name ()));
+-                              return;
+-                      }
+-              } else if (m.overrides && m.base_method == null) {
+-                      Report.error (m.source_reference, "%s: no suitable method found to override".printf (m.get_full_name ()));
+-              }
+-
+-              // check whether return type is at least as accessible as the method
+-              if (!is_type_accessible (m, m.return_type)) {
+-                      m.error = true;
+-                      Report.error (m.source_reference, "return type `%s` is less accessible than method `%s`".printf (m.return_type.to_string (), m.get_full_name ()));
+-                      return;
+-              }
+-
+-              foreach (Expression precondition in m.get_preconditions ()) {
+-                      if (precondition.error) {
+-                              // if there was an error in the precondition, skip this check
+-                              m.error = true;
+-                              return;
+-                      }
+-
+-                      if (!precondition.value_type.compatible (bool_type)) {
+-                              m.error = true;
+-                              Report.error (precondition.source_reference, "Precondition must be boolean");
+-                              return;
+-                      }
+-              }
+-
+-              foreach (Expression postcondition in m.get_postconditions ()) {
+-                      if (postcondition.error) {
+-                              // if there was an error in the postcondition, skip this check
+-                              m.error = true;
+-                              return;
+-                      }
+-
+-                      if (!postcondition.value_type.compatible (bool_type)) {
+-                              m.error = true;
+-                              Report.error (postcondition.source_reference, "Postcondition must be boolean");
+-                              return;
+-                      }
+-              }
+-
+-              if (m.tree_can_fail && m.name == "main") {
+-                      Report.error (m.source_reference, "\"main\" method cannot throw errors");
+-              }
+-
+-              // check that all errors that can be thrown in the method body are declared
+-              if (m.body != null) { 
+-                      foreach (DataType body_error_type in m.body.get_error_types ()) {
+-                              bool can_propagate_error = false;
+-                              foreach (DataType method_error_type in m.get_error_types ()) {
+-                                      if (body_error_type.compatible (method_error_type)) {
+-                                              can_propagate_error = true;
+-                                      }
+-                              }
+-                              if (!can_propagate_error) {
+-                                      Report.warning (body_error_type.source_reference, "unhandled error `%s'".printf (body_error_type.to_string()));
+-                              }
+-                      }
+-              }
++              m.check (this);
+       }
+       public override void visit_creation_method (CreationMethod m) {
+-              m.process_attributes ();
+-
+-              if (m.type_name != null && m.type_name != current_symbol.name) {
+-                      // type_name is null for constructors generated by GIdlParser
+-                      Report.error (m.source_reference, "missing return type in method `%s.%s´".printf (current_symbol.get_full_name (), m.type_name));
+-                      m.error = true;
+-                      return;
+-              }
+-
+-              current_symbol = m;
+-              current_return_type = m.return_type;
+-
+-              m.accept_children (this);
+-
+-              current_symbol = current_symbol.parent_symbol;
+-              current_return_type = null;
+-
+-              if (current_symbol.parent_symbol is Method) {
+-                      /* lambda expressions produce nested methods */
+-                      var up_method = (Method) current_symbol.parent_symbol;
+-                      current_return_type = up_method.return_type;
+-              }
+-
+-              if (m.is_abstract || m.is_virtual || m.overrides) {
+-                      Report.error (m.source_reference, "The creation method `%s' cannot be marked as override, virtual, or abstract".printf (m.get_full_name ()));
+-                      return;
+-              }
++              m.check (this);
+       }
+       public override void visit_formal_parameter (FormalParameter p) {
+-              p.process_attributes ();
+-
+               p.check (this);
+       }
+@@ -640,562 +204,71 @@
+       }
+       public override void visit_property (Property prop) {
+-              prop.process_attributes ();
+-
+               prop.check (this);
+       }
+       public override void visit_property_accessor (PropertyAccessor acc) {
+-              acc.process_attributes ();
+-
+-              var old_return_type = current_return_type;
+-              if (acc.readable) {
+-                      current_return_type = acc.prop.property_type;
+-              } else {
+-                      // void
+-                      current_return_type = new VoidType ();
+-              }
+-
+-              if (!acc.prop.external_package) {
+-                      if (acc.body == null && !acc.prop.interface_only && !acc.prop.is_abstract) {
+-                              /* no accessor body specified, insert default body */
+-
+-                              if (acc.prop.parent_symbol is Interface) {
+-                                      acc.error = true;
+-                                      Report.error (acc.source_reference, "Automatic properties can't be used in interfaces");
+-                                      return;
+-                              }
+-                              acc.automatic_body = true;
+-                              acc.body = new Block (acc.source_reference);
+-                              var ma = new MemberAccess.simple ("_%s".printf (acc.prop.name), acc.source_reference);
+-                              if (acc.readable) {
+-                                      acc.body.add_statement (new ReturnStatement (ma, acc.source_reference));
+-                              } else {
+-                                      var assignment = new Assignment (ma, new MemberAccess.simple ("value", acc.source_reference), AssignmentOperator.SIMPLE, acc.source_reference);
+-                                      acc.body.add_statement (new ExpressionStatement (assignment));
+-                              }
+-                      }
+-
+-                      if (acc.body != null && (acc.writable || acc.construction)) {
+-                              var value_type = acc.prop.property_type.copy ();
+-                              acc.value_parameter = new FormalParameter ("value", value_type, acc.source_reference);
+-                              acc.body.scope.add (acc.value_parameter.name, acc.value_parameter);
+-                      }
+-              }
+-
+-              acc.accept_children (this);
+-
+-              current_return_type = old_return_type;
++              acc.check (this);
+       }
+       public override void visit_signal (Signal sig) {
+-              sig.process_attributes ();
+-
+-              sig.accept_children (this);
++              sig.check (this);
+       }
+       public override void visit_constructor (Constructor c) {
+-              c.this_parameter = new FormalParameter ("this", new ObjectType (current_class));
+-              c.scope.add (c.this_parameter.name, c.this_parameter);
+-
+-              c.owner = current_symbol.scope;
+-              current_symbol = c;
+-
+-              c.accept_children (this);
+-
+-              foreach (DataType body_error_type in c.body.get_error_types ()) {
+-                      Report.warning (body_error_type.source_reference, "unhandled error `%s'".printf (body_error_type.to_string()));
+-              }
+-
+-              current_symbol = current_symbol.parent_symbol;
++              c.check (this);
+       }
+       public override void visit_destructor (Destructor d) {
+-              d.owner = current_symbol.scope;
+-              current_symbol = d;
+-
+-              d.accept_children (this);
+-
+-              current_symbol = current_symbol.parent_symbol;
++              d.check (this);
+       }
+       public override void visit_block (Block b) {
+-              b.owner = current_symbol.scope;
+-              current_symbol = b;
+-
+-              b.accept_children (this);
+-
+-              foreach (LocalVariable local in b.get_local_variables ()) {
+-                      local.active = false;
+-              }
+-
+-              foreach (Statement stmt in b.get_statements()) {
+-                      b.add_error_types (stmt.get_error_types ());
+-              }
+-
+-              current_symbol = current_symbol.parent_symbol;
++              b.check (this);
+       }
+       public override void visit_declaration_statement (DeclarationStatement stmt) {
+-              var local = stmt.declaration as LocalVariable;
+-              if (local != null && local.initializer != null) {
+-                      foreach (DataType error_type in local.initializer.get_error_types ()) {
+-                              // ensure we can trace back which expression may throw errors of this type
+-                              var initializer_error_type = error_type.copy ();
+-                              initializer_error_type.source_reference = local.initializer.source_reference;
+-
+-                              stmt.add_error_type (initializer_error_type);
+-                      }
+-              }
++              stmt.check (this);
+       }
+       public override void visit_local_variable (LocalVariable local) {
+-              if (local.initializer != null) {
+-                      local.initializer.target_type = local.variable_type;
+-              }
+-
+-              local.accept_children (this);
+-
+-              if (local.variable_type == null) {
+-                      /* var type */
+-
+-                      if (local.initializer == null) {
+-                              local.error = true;
+-                              Report.error (local.source_reference, "var declaration not allowed without initializer");
+-                              return;
+-                      }
+-                      if (local.initializer.value_type == null) {
+-                              local.error = true;
+-                              Report.error (local.source_reference, "var declaration not allowed with non-typed initializer");
+-                              return;
+-                      }
+-
+-                      local.variable_type = local.initializer.value_type.copy ();
+-                      local.variable_type.value_owned = true;
+-                      local.variable_type.floating_reference = false;
+-
+-                      local.initializer.target_type = local.variable_type;
+-              }
+-
+-              if (local.initializer != null) {
+-                      if (local.initializer.value_type == null) {
+-                              if (!(local.initializer is MemberAccess) && !(local.initializer is LambdaExpression)) {
+-                                      local.error = true;
+-                                      Report.error (local.source_reference, "expression type not allowed as initializer");
+-                                      return;
+-                              }
+-
+-                              if (local.initializer.symbol_reference is Method &&
+-                                  local.variable_type is DelegateType) {
+-                                      var m = (Method) local.initializer.symbol_reference;
+-                                      var dt = (DelegateType) local.variable_type;
+-                                      var cb = dt.delegate_symbol;
+-
+-                                      /* check whether method matches callback type */
+-                                      if (!cb.matches_method (m)) {
+-                                              local.error = true;
+-                                              Report.error (local.source_reference, "declaration of method `%s' doesn't match declaration of callback `%s'".printf (m.get_full_name (), cb.get_full_name ()));
+-                                              return;
+-                                      }
+-
+-                                      local.initializer.value_type = local.variable_type;
+-                              } else {
+-                                      local.error = true;
+-                                      Report.error (local.source_reference, "expression type not allowed as initializer");
+-                                      return;
+-                              }
+-                      }
+-
+-                      if (!local.initializer.value_type.compatible (local.variable_type)) {
+-                              local.error = true;
+-                              Report.error (local.source_reference, "Assignment: Cannot convert from `%s' to `%s'".printf (local.initializer.value_type.to_string (), local.variable_type.to_string ()));
+-                              return;
+-                      }
+-
+-                      if (local.initializer.value_type.is_disposable ()) {
+-                              /* rhs transfers ownership of the expression */
+-                              if (!(local.variable_type is PointerType) && !local.variable_type.value_owned) {
+-                                      /* lhs doesn't own the value */
+-                                      local.error = true;
+-                                      Report.error (local.source_reference, "Invalid assignment from owned expression to unowned variable");
+-                                      return;
+-                              }
+-                      }
+-              }
+-
+-              current_source_file.add_type_dependency (local.variable_type, SourceFileDependencyType.SOURCE);
+-
+-              current_symbol.scope.add (local.name, local);
+-
+-              var block = (Block) current_symbol;
+-              block.add_local_variable (local);
+-
+-              local.active = true;
++              local.check (this);
+       }
+-      /**
+-       * Visit operation called for initializer lists
+-       *
+-       * @param list an initializer list
+-       */
+       public override void visit_initializer_list (InitializerList list) {
+-              if (list.target_type == null) {
+-                      list.error = true;
+-                      Report.error (list.source_reference, "initializer list used for unknown type");
+-                      return;
+-              } else if (list.target_type is ArrayType) {
+-                      /* initializer is used as array initializer */
+-                      var array_type = (ArrayType) list.target_type;
+-
+-                      foreach (Expression e in list.get_initializers ()) {
+-                              e.target_type = array_type.element_type.copy ();
+-                      }
+-              } else if (list.target_type.data_type is Struct) {
+-                      /* initializer is used as struct initializer */
+-                      var st = (Struct) list.target_type.data_type;
+-
+-                      var field_it = st.get_fields ().iterator ();
+-                      foreach (Expression e in list.get_initializers ()) {
+-                              Field field = null;
+-                              while (field == null) {
+-                                      if (!field_it.next ()) {
+-                                              list.error = true;
+-                                              Report.error (e.source_reference, "too many expressions in initializer list for `%s'".printf (list.target_type.to_string ()));
+-                                              return;
+-                                      }
+-                                      field = field_it.get ();
+-                                      if (field.binding != MemberBinding.INSTANCE) {
+-                                              // we only initialize instance fields
+-                                              field = null;
+-                                      }
+-                              }
+-
+-                              e.target_type = field.field_type.copy ();
+-                              if (!list.target_type.value_owned) {
+-                                      e.target_type.value_owned = false;
+-                              }
+-                      }
+-              } else {
+-                      list.error = true;
+-                      Report.error (list.source_reference, "initializer list used for `%s', which is neither array nor struct".printf (list.target_type.to_string ()));
+-                      return;
+-              }
+-
+-              list.accept_children (this);
+-
+-              bool error = false;
+-              foreach (Expression e in list.get_initializers ()) {
+-                      if (e.value_type == null) {
+-                              error = true;
+-                              continue;
+-                      }
+-
+-                      var unary = e as UnaryExpression;
+-                      if (unary != null && (unary.operator == UnaryOperator.REF || unary.operator == UnaryOperator.OUT)) {
+-                              // TODO check type for ref and out expressions
+-                      } else if (!e.value_type.compatible (e.target_type)) {
+-                              error = true;
+-                              e.error = true;
+-                              Report.error (e.source_reference, "Expected initializer of type `%s' but got `%s'".printf (e.target_type.to_string (), e.value_type.to_string ()));
+-                      }
+-              }
+-
+-              if (!error) {
+-                      /* everything seems to be correct */
+-                      list.value_type = list.target_type;
+-              }
++              list.check (this);
+       }
+       public override void visit_expression_statement (ExpressionStatement stmt) {
+-              if (stmt.expression.error) {
+-                      // ignore inner error
+-                      stmt.error = true;
+-                      return;
+-              }
+-
+-              stmt.add_error_types (stmt.expression.get_error_types ());
++              stmt.check (this);
+       }
+       public override void visit_if_statement (IfStatement stmt) {
+-              stmt.accept_children (this);
+-
+-              if (stmt.condition.error) {
+-                      /* if there was an error in the condition, skip this check */
+-                      stmt.error = true;
+-                      return;
+-              }
+-
+-              if (!stmt.condition.value_type.compatible (bool_type)) {
+-                      stmt.error = true;
+-                      Report.error (stmt.condition.source_reference, "Condition must be boolean");
+-                      return;
+-              }
+-
+-              stmt.add_error_types (stmt.condition.get_error_types ());
+-              stmt.add_error_types (stmt.true_statement.get_error_types ());
+-
+-              if (stmt.false_statement != null) {
+-                      stmt.add_error_types (stmt.false_statement.get_error_types ());
+-              }
++              stmt.check (this);
+       }
+       public override void visit_switch_section (SwitchSection section) {
+-              foreach (SwitchLabel label in section.get_labels ()) {
+-                      label.accept (this);
+-              }
+-
+-              section.owner = current_symbol.scope;
+-              current_symbol = section;
+-
+-              foreach (Statement st in section.get_statements ()) {
+-                      st.accept (this);
+-              }
+-
+-              foreach (LocalVariable local in section.get_local_variables ()) {
+-                      local.active = false;
+-              }
+-
+-              current_symbol = current_symbol.parent_symbol;
++              section.check (this);
+       }
+       public override void visit_while_statement (WhileStatement stmt) {
+-              stmt.accept_children (this);
+-
+-              if (stmt.condition.error) {
+-                      /* if there was an error in the condition, skip this check */
+-                      stmt.error = true;
+-                      return;
+-              }
+-
+-              if (!stmt.condition.value_type.compatible (bool_type)) {
+-                      stmt.error = true;
+-                      Report.error (stmt.condition.source_reference, "Condition must be boolean");
+-                      return;
+-              }
+-
+-              stmt.add_error_types (stmt.condition.get_error_types ());
+-              stmt.add_error_types (stmt.body.get_error_types ());
++              stmt.check (this);
+       }
+       public override void visit_do_statement (DoStatement stmt) {
+-              stmt.accept_children (this);
+-
+-              if (stmt.condition.error) {
+-                      /* if there was an error in the condition, skip this check */
+-                      stmt.error = true;
+-                      return;
+-              }
+-
+-              if (!stmt.condition.value_type.compatible (bool_type)) {
+-                      stmt.error = true;
+-                      Report.error (stmt.condition.source_reference, "Condition must be boolean");
+-                      return;
+-              }
+-
+-              stmt.add_error_types (stmt.condition.get_error_types ());
+-              stmt.add_error_types (stmt.body.get_error_types ());
++              stmt.check (this);
+       }
+       public override void visit_for_statement (ForStatement stmt) {
+-              stmt.accept_children (this);
+-
+-              if (stmt.condition != null && stmt.condition.error) {
+-                      /* if there was an error in the condition, skip this check */
+-                      stmt.error = true;
+-                      return;
+-              }
+-
+-              if (stmt.condition != null && !stmt.condition.value_type.compatible (bool_type)) {
+-                      stmt.error = true;
+-                      Report.error (stmt.condition.source_reference, "Condition must be boolean");
+-                      return;
+-              }
+-
+-              if (stmt.condition != null) {
+-                      stmt.add_error_types (stmt.condition.get_error_types ());
+-              }
+-
+-              stmt.add_error_types (stmt.body.get_error_types ());
+-              foreach (Expression exp in stmt.get_initializer ()) {
+-                      stmt.add_error_types (exp.get_error_types ());
+-              }
+-              foreach (Expression exp in stmt.get_iterator ()) {
+-                      stmt.add_error_types (exp.get_error_types ());
+-              }
++              stmt.check (this);
+       }
+       public override void visit_foreach_statement (ForeachStatement stmt) {
+-              // analyze collection expression first, used for type inference
+-              stmt.collection.accept (this);
+-
+-              if (stmt.collection.error) {
+-                      // ignore inner error
+-                      stmt.error = true;
+-                      return;
+-              } else if (stmt.collection.value_type == null) {
+-                      Report.error (stmt.collection.source_reference, "invalid collection expression");
+-                      stmt.error = true;
+-                      return;
+-              }
+-
+-              var collection_type = stmt.collection.value_type.copy ();
+-              stmt.collection.target_type = collection_type.copy ();
+-              
+-              DataType element_data_type = null;
+-              bool element_owned = false;
+-
+-              if (collection_type.is_array ()) {
+-                      var array_type = (ArrayType) collection_type;
+-                      element_data_type = array_type.element_type;
+-              } else if (collection_type.compatible (glist_type) || collection_type.compatible (gslist_type)) {
+-                      if (collection_type.get_type_arguments ().size > 0) {
+-                              element_data_type = (DataType) collection_type.get_type_arguments ().get (0);
+-                      }
+-              } else if (iterable_type != null && collection_type.compatible (iterable_type)) {
+-                      element_owned = true;
+-
+-                      if (list_type == null || !collection_type.compatible (new ObjectType (list_type))) {
+-                              // don't use iterator objects for lists for performance reasons
+-                              var foreach_iterator_type = new ObjectType (iterator_type);
+-                              foreach_iterator_type.value_owned = true;
+-                              foreach_iterator_type.add_type_argument (stmt.type_reference);
+-                              stmt.iterator_variable = new LocalVariable (foreach_iterator_type, "%s_it".printf (stmt.variable_name));
+-
+-                              stmt.add_local_variable (stmt.iterator_variable);
+-                              stmt.iterator_variable.active = true;
+-                      }
+-
+-                      var it_method = (Method) iterable_type.data_type.scope.lookup ("iterator");
+-                      if (it_method.return_type.get_type_arguments ().size > 0) {
+-                              var type_arg = it_method.return_type.get_type_arguments ().get (0);
+-                              if (type_arg.type_parameter != null) {
+-                                      element_data_type = SemanticAnalyzer.get_actual_type (collection_type, it_method, type_arg, stmt);
+-                              } else {
+-                                      element_data_type = type_arg;
+-                              }
+-                      }
+-              } else {
+-                      stmt.error = true;
+-                      Report.error (stmt.source_reference, "Gee.List not iterable");
+-                      return;
+-              }
+-
+-              if (element_data_type == null) {
+-                      stmt.error = true;
+-                      Report.error (stmt.collection.source_reference, "missing type argument for collection");
+-                      return;
+-              }
+-
+-              // analyze element type
+-              if (stmt.type_reference == null) {
+-                      // var type
+-                      stmt.type_reference = element_data_type.copy ();
+-              } else if (!element_data_type.compatible (stmt.type_reference)) {
+-                      stmt.error = true;
+-                      Report.error (stmt.source_reference, "Foreach: Cannot convert from `%s' to `%s'".printf (element_data_type.to_string (), stmt.type_reference.to_string ()));
+-                      return;
+-              } else if (element_data_type.is_disposable () && element_owned && !stmt.type_reference.value_owned) {
+-                      stmt.error = true;
+-                      Report.error (stmt.source_reference, "Foreach: Invalid assignment from owned expression to unowned variable");
+-                      return;
+-              }
+-              
+-              current_source_file.add_type_dependency (stmt.type_reference, SourceFileDependencyType.SOURCE);
+-
+-              stmt.element_variable = new LocalVariable (stmt.type_reference, stmt.variable_name);
+-
+-              stmt.body.scope.add (stmt.variable_name, stmt.element_variable);
+-
+-              stmt.body.add_local_variable (stmt.element_variable);
+-              stmt.element_variable.active = true;
+-
+-              // analyze body
+-              stmt.owner = current_symbol.scope;
+-              current_symbol = stmt;
+-
+-              stmt.body.accept (this);
+-
+-              foreach (LocalVariable local in stmt.get_local_variables ()) {
+-                      local.active = false;
+-              }
+-
+-              current_symbol = current_symbol.parent_symbol;
+-
+-              stmt.collection_variable = new LocalVariable (collection_type, "%s_collection".printf (stmt.variable_name));
+-
+-              stmt.add_local_variable (stmt.collection_variable);
+-              stmt.collection_variable.active = true;
+-
+-
+-              stmt.add_error_types (stmt.collection.get_error_types ());
+-              stmt.add_error_types (stmt.body.get_error_types ());
++              stmt.check (this);
+       }
+       public override void visit_return_statement (ReturnStatement stmt) {
+-              if (stmt.return_expression != null) {
+-                      stmt.return_expression.target_type = current_return_type;
+-              }
+-
+-              stmt.accept_children (this);
+-
+-              if (stmt.return_expression != null && stmt.return_expression.error) {
+-                      // ignore inner error
+-                      stmt.error = true;
+-                      return;
+-              }
+-
+-              if (current_return_type == null) {
+-                      stmt.error = true;
+-                      Report.error (stmt.source_reference, "Return not allowed in this context");
+-                      return;
+-              }
+-
+-              if (stmt.return_expression == null) {
+-                      if (current_return_type is VoidType) {
+-                              return;
+-                      } else {
+-                              stmt.error = true;
+-                              Report.error (stmt.source_reference, "Return without value in non-void function");
+-                              return;
+-                      }
+-              }
+-
+-              if (current_return_type is VoidType) {
+-                      Report.error (stmt.source_reference, "Return with value in void function");
+-                      return;
+-              }
+-
+-              if (stmt.return_expression.value_type == null) {
+-                      stmt.error = true;
+-                      Report.error (stmt.source_reference, "Invalid expression in return value");
+-                      return;
+-              }
+-
+-              if (!stmt.return_expression.value_type.compatible (current_return_type)) {
+-                      stmt.error = true;
+-                      Report.error (stmt.source_reference, "Return: Cannot convert from `%s' to `%s'".printf (stmt.return_expression.value_type.to_string (), current_return_type.to_string ()));
+-                      return;
+-              }
+-
+-              if (stmt.return_expression.value_type.is_disposable () &&
+-                  !current_return_type.value_owned) {
+-                      stmt.error = true;
+-                      Report.error (stmt.source_reference, "Return value transfers ownership but method return type hasn't been declared to transfer ownership");
+-                      return;
+-              }
+-
+-              if (stmt.return_expression.symbol_reference is LocalVariable &&
+-                  stmt.return_expression.value_type.is_disposable () &&
+-                  !current_return_type.value_owned) {
+-                      Report.warning (stmt.source_reference, "Local variable with strong reference used as return value and method return type hasn't been declared to transfer ownership");
+-              }
+-
+-              if (context.non_null && stmt.return_expression is NullLiteral
+-                  && !current_return_type.nullable) {
+-                      Report.warning (stmt.source_reference, "`null' incompatible with return type `%s`".printf (current_return_type.to_string ()));
+-              }
+-
+-              stmt.add_error_types (stmt.return_expression.get_error_types ());
++              stmt.check (this);
+       }
+       public override void visit_yield_statement (YieldStatement stmt) {
+@@ -1203,178 +276,27 @@
+       }
+       public override void visit_throw_statement (ThrowStatement stmt) {
+-              stmt.error_expression.target_type = new ErrorType (null, null, stmt.source_reference);
+-              stmt.error_expression.target_type.value_owned = true;
+-
+-              stmt.accept_children (this);
+-
+-              var error_type = stmt.error_expression.value_type.copy ();
+-              error_type.source_reference = stmt.source_reference;
+-
+-              stmt.add_error_type (error_type);
++              stmt.check (this);
+       }
+       public override void visit_try_statement (TryStatement stmt) {
+-              stmt.accept_children (this);
++              stmt.check (this);
+       }
+       public override void visit_catch_clause (CatchClause clause) {
+-              if (clause.error_type != null) {
+-                      current_source_file.add_type_dependency (clause.error_type, SourceFileDependencyType.SOURCE);
+-
+-                      clause.error_variable = new LocalVariable (clause.error_type.copy (), clause.variable_name);
+-
+-                      clause.body.scope.add (clause.variable_name, clause.error_variable);
+-                      clause.body.add_local_variable (clause.error_variable);
+-              } else {
+-                      clause.error_type = new ErrorType (null, null, clause.source_reference);
+-              }
+-
+-              clause.accept_children (this);
++              clause.check (this);
+       }
+       public override void visit_lock_statement (LockStatement stmt) {
+-              /* resource must be a member access and denote a Lockable */
+-              if (!(stmt.resource is MemberAccess && stmt.resource.symbol_reference is Lockable)) {
+-                      stmt.error = true;
+-                      stmt.resource.error = true;
+-                      Report.error (stmt.resource.source_reference, "Expression is either not a member access or does not denote a lockable member");
+-                      return;
+-              }
+-
+-              /* parent symbol must be the current class */
+-              if (stmt.resource.symbol_reference.parent_symbol != current_class) {
+-                      stmt.error = true;
+-                      stmt.resource.error = true;
+-                      Report.error (stmt.resource.source_reference, "Only members of the current class are lockable");
+-              }
+-
+-              ((Lockable) stmt.resource.symbol_reference).set_lock_used (true);
++              stmt.check (this);
+       }
+       public override void visit_delete_statement (DeleteStatement stmt) {
+-              stmt.accept_children (this);
+-
+-              if (stmt.expression.error) {
+-                      // if there was an error in the inner expression, skip this check
+-                      return;
+-              }
+-
+-              if (!(stmt.expression.value_type is PointerType)) {
+-                      stmt.error = true;
+-                      Report.error (stmt.source_reference, "delete operator not supported for `%s'".printf (stmt.expression.value_type.to_string ()));
+-              }
++              stmt.check (this);
+       }
+-      private int create_sizes_from_initializer_list (InitializerList il, int rank, Gee.List<Literal> sl) {
+-              var init = new IntegerLiteral (il.size.to_string (), il.source_reference);
+-              init.accept (this);
+-              sl.add (init);
+-
+-              int subsize = -1;
+-              foreach (Expression e in il.get_initializers ()) {
+-                      if (e is InitializerList) {
+-                              if (rank == 1) {
+-                                      il.error = true;
+-                                      e.error = true;
+-                                      Report.error (e.source_reference, "Expected array element, got array initializer list");
+-                                      return -1;
+-                              }
+-                              int size = create_sizes_from_initializer_list ((InitializerList)e, rank - 1, sl);
+-                              if (size == -1) {
+-                                      return -1;
+-                              }
+-                              if (subsize >= 0 && subsize != size) {
+-                                      il.error = true;
+-                                      Report.error (il.source_reference, "Expected initializer list of size %d, got size %d".printf (subsize, size));
+-                                      return -1;
+-                              } else {
+-                                      subsize = size;
+-                              }
+-                      } else {
+-                              if (rank != 1) {
+-                                      il.error = true;
+-                                      e.error = true;
+-                                      Report.error (e.source_reference, "Expected array initializer list, got array element");
+-                                      return -1;
+-                              }
+-                      }
+-              }
+-              return il.size;
+-      }
+-
+-      /**
+-       * Visit operations called for array creation expresions.
+-       *
+-       * @param expr an array creation expression
+-       */
+       public override void visit_array_creation_expression (ArrayCreationExpression expr) {
+-              Gee.List<Expression> size = expr.get_sizes ();
+-              var initlist = expr.initializer_list;
+-
+-              if (expr.element_type != null) {
+-                      expr.element_type.accept (this);
+-              }
+-
+-              foreach (Expression e in size) {
+-                      e.accept (this);
+-              }
+-
+-              var calc_sizes = new ArrayList<Literal> ();
+-              if (initlist != null) {
+-                      initlist.target_type = new ArrayType (expr.element_type, expr.rank, expr.source_reference);
+-
+-                      initlist.accept (this);
+-
+-                      var ret = create_sizes_from_initializer_list (initlist, expr.rank, calc_sizes);
+-                      if (ret == -1) {
+-                              expr.error = true;
+-                      }
+-              }
+-
+-              if (size.size > 0) {
+-                      /* check for errors in the size list */
+-                      foreach (Expression e in size) {
+-                              if (e.value_type == null) {
+-                                      /* return on previous error */
+-                                      return;
+-                              } else if (!(e.value_type.data_type is Struct) || !((Struct) e.value_type.data_type).is_integer_type ()) {
+-                                      expr.error = true;
+-                                      Report.error (e.source_reference, "Expression of integer type expected");
+-                              }
+-                      }
+-              } else {
+-                      if (initlist == null) {
+-                              expr.error = true;
+-                              /* this is an internal error because it is already handeld by the parser */
+-                              Report.error (expr.source_reference, "internal error: initializer list expected");
+-                      } else {
+-                              foreach (Expression size in calc_sizes) {
+-                                      expr.append_size (size);
+-                              }
+-                      }
+-              }
+-
+-              if (expr.error) {
+-                      return;
+-              }
+-
+-              /* check for wrong elements inside the initializer */
+-              if (expr.initializer_list != null && expr.initializer_list.value_type == null) {
+-                      return;
+-              }
+-
+-              /* try to construct the type of the array */
+-              if (expr.element_type == null) {
+-                      expr.error = true;
+-                      Report.error (expr.source_reference, "Cannot determine the element type of the created array");
+-                      return;
+-              }
+-
+-              expr.element_type.value_owned = true;
+-
+-              expr.value_type = new ArrayType (expr.element_type, expr.rank, expr.source_reference);
+-              expr.value_type.value_owned = true;
++              expr.check (this);
+       }
+       public override void visit_boolean_literal (BooleanLiteral expr) {
+@@ -1401,7 +323,7 @@
+               expr.value_type = new NullType (expr.source_reference);
+       }
+-      private DataType? get_value_type_for_symbol (Symbol sym, bool lvalue) {
++      public DataType? get_value_type_for_symbol (Symbol sym, bool lvalue) {
+               if (sym is Field) {
+                       var f = (Field) sym;
+                       var type = f.field_type.copy ();
+@@ -1525,346 +447,7 @@
+       }
+       
+       public override void visit_member_access (MemberAccess expr) {
+-              Symbol base_symbol = null;
+-              FormalParameter this_parameter = null;
+-              bool may_access_instance_members = false;
+-
+-              expr.symbol_reference = null;
+-
+-              if (expr.qualified) {
+-                      base_symbol = root_symbol;
+-                      expr.symbol_reference = root_symbol.scope.lookup (expr.member_name);
+-              } else if (expr.inner == null) {
+-                      if (expr.member_name == "this") {
+-                              if (!is_in_instance_method ()) {
+-                                      expr.error = true;
+-                                      Report.error (expr.source_reference, "This access invalid outside of instance methods");
+-                                      return;
+-                              }
+-                      }
+-
+-                      base_symbol = current_symbol;
+-
+-                      var sym = current_symbol;
+-                      while (sym != null && expr.symbol_reference == null) {
+-                              if (this_parameter == null) {
+-                                      if (sym is CreationMethod) {
+-                                              var cm = (CreationMethod) sym;
+-                                              this_parameter = cm.this_parameter;
+-                                              may_access_instance_members = true;
+-                                      } else if (sym is Property) {
+-                                              var prop = (Property) sym;
+-                                              this_parameter = prop.this_parameter;
+-                                              may_access_instance_members = true;
+-                                      } else if (sym is Constructor) {
+-                                              var c = (Constructor) sym;
+-                                              this_parameter = c.this_parameter;
+-                                              may_access_instance_members = true;
+-                                      } else if (sym is Destructor) {
+-                                              var d = (Destructor) sym;
+-                                              this_parameter = d.this_parameter;
+-                                              may_access_instance_members = true;
+-                                      } else if (sym is Method) {
+-                                              var m = (Method) sym;
+-                                              this_parameter = m.this_parameter;
+-                                              may_access_instance_members = (m.binding == MemberBinding.INSTANCE);
+-                                      }
+-                              }
+-
+-                              expr.symbol_reference = symbol_lookup_inherited (sym, expr.member_name);
+-                              sym = sym.parent_symbol;
+-                      }
+-
+-                      if (expr.symbol_reference == null) {
+-                              foreach (UsingDirective ns in current_using_directives) {
+-                                      var local_sym = ns.namespace_symbol.scope.lookup (expr.member_name);
+-                                      if (local_sym != null) {
+-                                              if (expr.symbol_reference != null) {
+-                                                      expr.error = true;
+-                                                      Report.error (expr.source_reference, "`%s' is an ambiguous reference between `%s' and `%s'".printf (expr.member_name, expr.symbol_reference.get_full_name (), local_sym.get_full_name ()));
+-                                                      return;
+-                                              }
+-                                              expr.symbol_reference = local_sym;
+-                                      }
+-                              }
+-                      }
+-              } else {
+-                      if (expr.inner.error) {
+-                              /* if there was an error in the inner expression, skip this check */
+-                              expr.error = true;
+-                              return;
+-                      }
+-
+-                      if (expr.pointer_member_access) {
+-                              var pointer_type = expr.inner.value_type as PointerType;
+-                              if (pointer_type != null && pointer_type.base_type is ValueType) {
+-                                      // transform foo->bar to (*foo).bar
+-                                      expr.inner = new PointerIndirection (expr.inner, expr.source_reference);
+-                                      expr.inner.accept (this);
+-                                      expr.pointer_member_access = false;
+-                              }
+-                      }
+-
+-                      if (expr.inner is MemberAccess) {
+-                              var ma = (MemberAccess) expr.inner;
+-                              if (ma.prototype_access) {
+-                                      expr.error = true;
+-                                      Report.error (expr.source_reference, "Access to instance member `%s' denied".printf (expr.inner.symbol_reference.get_full_name ()));
+-                                      return;
+-                              }
+-                      }
+-
+-                      if (expr.inner is MemberAccess || expr.inner is BaseAccess) {
+-                              base_symbol = expr.inner.symbol_reference;
+-
+-                              if (expr.symbol_reference == null && (base_symbol is Namespace || base_symbol is TypeSymbol)) {
+-                                      expr.symbol_reference = base_symbol.scope.lookup (expr.member_name);
+-                                      if (expr.inner is BaseAccess) {
+-                                              // inner expression is base access
+-                                              // access to instance members of the base type possible
+-                                              may_access_instance_members = true;
+-                                      }
+-                              }
+-                      }
+-
+-                      if (expr.symbol_reference == null && expr.inner.value_type != null) {
+-                              if (expr.pointer_member_access) {
+-                                      expr.symbol_reference = expr.inner.value_type.get_pointer_member (expr.member_name);
+-                              } else {
+-                                      if (expr.inner.value_type.data_type != null) {
+-                                              base_symbol = expr.inner.value_type.data_type;
+-                                      }
+-                                      expr.symbol_reference = expr.inner.value_type.get_member (expr.member_name);
+-                              }
+-                              if (expr.symbol_reference != null) {
+-                                      // inner expression is variable, field, or parameter
+-                                      // access to instance members of the corresponding type possible
+-                                      may_access_instance_members = true;
+-                              }
+-                      }
+-
+-                      if (expr.symbol_reference == null && expr.inner.value_type != null && expr.inner.value_type.is_dynamic) {
+-                              // allow late bound members for dynamic types
+-                              var dynamic_object_type = (ObjectType) expr.inner.value_type;
+-                              if (expr.parent_node is InvocationExpression) {
+-                                      var invoc = (InvocationExpression) expr.parent_node;
+-                                      if (invoc.call == expr) {
+-                                              // dynamic method
+-                                              DataType ret_type;
+-                                              if (invoc.target_type != null) {
+-                                                      ret_type = invoc.target_type.copy ();
+-                                                      ret_type.value_owned = true;
+-                                              } else if (invoc.parent_node is ExpressionStatement) {
+-                                                      ret_type = new VoidType ();
+-                                              } else {
+-                                                      // expect dynamic object of the same type
+-                                                      ret_type = expr.inner.value_type.copy ();
+-                                              }
+-                                              var m = new DynamicMethod (expr.inner.value_type, expr.member_name, ret_type, expr.source_reference);
+-                                              m.invocation = invoc;
+-                                              m.add_error_type (new ErrorType (null, null));
+-                                              m.access = SymbolAccessibility.PUBLIC;
+-                                              m.add_parameter (new FormalParameter.with_ellipsis ());
+-                                              dynamic_object_type.type_symbol.scope.add (null, m);
+-                                              expr.symbol_reference = m;
+-                                      }
+-                              } else if (expr.parent_node is Assignment) {
+-                                      var a = (Assignment) expr.parent_node;
+-                                      if (a.left == expr
+-                                          && (a.operator == AssignmentOperator.ADD
+-                                              || a.operator == AssignmentOperator.SUB)) {
+-                                              // dynamic signal
+-                                              var s = new DynamicSignal (expr.inner.value_type, expr.member_name, new VoidType (), expr.source_reference);
+-                                              s.handler = a.right;
+-                                              s.access = SymbolAccessibility.PUBLIC;
+-                                              dynamic_object_type.type_symbol.scope.add (null, s);
+-                                              expr.symbol_reference = s;
+-                                      } else if (a.left == expr) {
+-                                              // dynamic property assignment
+-                                              var prop = new DynamicProperty (expr.inner.value_type, expr.member_name, expr.source_reference);
+-                                              prop.access = SymbolAccessibility.PUBLIC;
+-                                              prop.set_accessor = new PropertyAccessor (false, true, false, null, null);
+-                                              prop.set_accessor.access = SymbolAccessibility.PUBLIC;
+-                                              prop.owner = expr.inner.value_type.data_type.scope;
+-                                              dynamic_object_type.type_symbol.scope.add (null, prop);
+-                                              expr.symbol_reference = prop;
+-                                      }
+-                              }
+-                              if (expr.symbol_reference == null) {
+-                                      // dynamic property read access
+-                                      var prop = new DynamicProperty (expr.inner.value_type, expr.member_name, expr.source_reference);
+-                                      if (expr.target_type != null) {
+-                                              prop.property_type = expr.target_type;
+-                                      } else {
+-                                              // expect dynamic object of the same type
+-                                              prop.property_type = expr.inner.value_type.copy ();
+-                                      }
+-                                      prop.access = SymbolAccessibility.PUBLIC;
+-                                      prop.get_accessor = new PropertyAccessor (true, false, false, null, null);
+-                                      prop.get_accessor.access = SymbolAccessibility.PUBLIC;
+-                                      prop.owner = expr.inner.value_type.data_type.scope;
+-                                      dynamic_object_type.type_symbol.scope.add (null, prop);
+-                                      expr.symbol_reference = prop;
+-                              }
+-                              if (expr.symbol_reference != null) {
+-                                      may_access_instance_members = true;
+-                              }
+-                      }
+-              }
+-
+-              if (expr.symbol_reference == null) {
+-                      expr.error = true;
+-
+-                      string base_type_name = "(null)";
+-                      if (expr.inner != null && expr.inner.value_type != null) {
+-                              base_type_name = expr.inner.value_type.to_string ();
+-                      } else if (base_symbol != null) {
+-                              base_type_name = base_symbol.get_full_name ();
+-                      }
+-
+-                      Report.error (expr.source_reference, "The name `%s' does not exist in the context of `%s'".printf (expr.member_name, base_type_name));
+-                      return;
+-              }
+-
+-              var member = expr.symbol_reference;
+-              var access = SymbolAccessibility.PUBLIC;
+-              bool instance = false;
+-              bool klass = false;
+-              if (member is Field) {
+-                      var f = (Field) member;
+-                      access = f.access;
+-                      instance = (f.binding == MemberBinding.INSTANCE);
+-                      klass = (f.binding == MemberBinding.CLASS);
+-              } else if (member is Method) {
+-                      var m = (Method) member;
+-                      access = m.access;
+-                      if (!(m is CreationMethod)) {
+-                              instance = (m.binding == MemberBinding.INSTANCE);
+-                      }
+-                      klass = (m.binding == MemberBinding.CLASS);
+-              } else if (member is Property) {
+-                      var prop = (Property) member;
+-                      if (!prop.check (this)) {
+-                              expr.error = true;
+-                              return;
+-                      }
+-                      access = prop.access;
+-                      if (expr.lvalue) {
+-                              if (prop.set_accessor == null) {
+-                                      expr.error = true;
+-                                      Report.error (expr.source_reference, "Property `%s' is read-only".printf (prop.get_full_name ()));
+-                                      return;
+-                              }
+-                              if (prop.access == SymbolAccessibility.PUBLIC) {
+-                                      access = prop.set_accessor.access;
+-                              } else if (prop.access == SymbolAccessibility.PROTECTED
+-                                         && prop.set_accessor.access != SymbolAccessibility.PUBLIC) {
+-                                      access = prop.set_accessor.access;
+-                              }
+-                      } else {
+-                              if (prop.get_accessor == null) {
+-                                      expr.error = true;
+-                                      Report.error (expr.source_reference, "Property `%s' is write-only".printf (prop.get_full_name ()));
+-                                      return;
+-                              }
+-                              if (prop.access == SymbolAccessibility.PUBLIC) {
+-                                      access = prop.get_accessor.access;
+-                              } else if (prop.access == SymbolAccessibility.PROTECTED
+-                                         && prop.get_accessor.access != SymbolAccessibility.PUBLIC) {
+-                                      access = prop.get_accessor.access;
+-                              }
+-                      }
+-                      instance = (prop.binding == MemberBinding.INSTANCE);
+-              } else if (member is Signal) {
+-                      instance = true;
+-              }
+-
+-              if (access == SymbolAccessibility.PRIVATE) {
+-                      var target_type = member.parent_symbol;
+-
+-                      bool in_target_type = false;
+-                      for (Symbol this_symbol = current_symbol; this_symbol != null; this_symbol = this_symbol.parent_symbol) {
+-                              if (target_type == this_symbol) {
+-                                      in_target_type = true;
+-                                      break;
+-                              }
+-                      }
+-
+-                      if (!in_target_type) {
+-                              expr.error = true;
+-                              Report.error (expr.source_reference, "Access to private member `%s' denied".printf (member.get_full_name ()));
+-                              return;
+-                      }
+-              }
+-              if ((instance || klass) && !may_access_instance_members) {
+-                      expr.prototype_access = true;
+-
+-                      if (expr.symbol_reference is Method) {
+-                              // also set static type for prototype access
+-                              // required when using instance methods as delegates in constants
+-                              // TODO replace by MethodPrototype
+-                              expr.value_type = get_value_type_for_symbol (expr.symbol_reference, expr.lvalue);
+-                      } else if (expr.symbol_reference is Field) {
+-                              expr.value_type = new FieldPrototype ((Field) expr.symbol_reference);
+-                      }
+-              } else {
+-                      // implicit this access
+-                      if (instance && expr.inner == null) {
+-                              expr.inner = new MemberAccess (null, "this", expr.source_reference);
+-                              expr.inner.value_type = this_parameter.parameter_type.copy ();
+-                              expr.inner.symbol_reference = this_parameter;
+-                      }
+-
+-                      expr.value_type = get_value_type_for_symbol (expr.symbol_reference, expr.lvalue);
+-
+-                      // resolve generic return values
+-                      if (expr.value_type != null && expr.value_type.type_parameter != null) {
+-                              if (expr.inner != null) {
+-                                      expr.value_type = get_actual_type (expr.inner.value_type, expr.symbol_reference, expr.value_type, expr);
+-                                      if (expr.value_type == null) {
+-                                              return;
+-                                      }
+-                              }
+-                      }
+-
+-                      if (expr.symbol_reference is Method) {
+-                              var m = (Method) expr.symbol_reference;
+-
+-                              Method base_method;
+-                              if (m.base_method != null) {
+-                                      base_method = m.base_method;
+-                              } else if (m.base_interface_method != null) {
+-                                      base_method = m.base_interface_method;
+-                              } else {
+-                                      base_method = m;
+-                              }
+-
+-                              if (instance && base_method.parent_symbol != null) {
+-                                      expr.inner.target_type = get_data_type_for_symbol ((TypeSymbol) base_method.parent_symbol);
+-                              }
+-                      } else if (expr.symbol_reference is Property) {
+-                              var prop = (Property) expr.symbol_reference;
+-
+-                              Property base_property;
+-                              if (prop.base_property != null) {
+-                                      base_property = prop.base_property;
+-                              } else if (prop.base_interface_property != null) {
+-                                      base_property = prop.base_interface_property;
+-                              } else {
+-                                      base_property = prop;
+-                              }
+-
+-                              if (instance && base_property.parent_symbol != null) {
+-                                      expr.inner.target_type = get_data_type_for_symbol ((TypeSymbol) base_property.parent_symbol);
+-                              }
+-                      } else if ((expr.symbol_reference is Field
+-                                  || expr.symbol_reference is Signal)
+-                                 && instance && expr.symbol_reference.parent_symbol != null) {
+-                              expr.inner.target_type = get_data_type_for_symbol ((TypeSymbol) expr.symbol_reference.parent_symbol);
+-                      }
+-              }
+-
+-              current_source_file.add_symbol_dependency (expr.symbol_reference, SourceFileDependencyType.SOURCE);
++              expr.check (this);
+       }
+       public static DataType get_data_type_for_symbol (TypeSymbol sym) {
+@@ -1889,300 +472,10 @@
+       }
+       public override void visit_invocation_expression (InvocationExpression expr) {
+-              expr.call.accept (this);
+-
+-              if (expr.call.error) {
+-                      /* if method resolving didn't succeed, skip this check */
+-                      expr.error = true;
+-                      return;
+-              }
+-
+-              if (expr.call is MemberAccess) {
+-                      var ma = (MemberAccess) expr.call;
+-                      if (ma.prototype_access) {
+-                              expr.error = true;
+-                              Report.error (expr.source_reference, "Access to instance member `%s' denied".printf (expr.call.symbol_reference.get_full_name ()));
+-                              return;
+-                      }
+-              }
+-
+-              var mtype = expr.call.value_type;
+-
+-              if (mtype is ObjectType) {
+-                      // constructor chain-up
+-                      var cm = find_current_method () as CreationMethod;
+-                      assert (cm != null);
+-                      if (cm.chain_up) {
+-                              expr.error = true;
+-                              Report.error (expr.source_reference, "Multiple constructor calls in the same constructor are not permitted");
+-                              return;
+-                      }
+-                      cm.chain_up = true;
+-              }
+-
+-              // check for struct construction
+-              if (expr.call is MemberAccess &&
+-                  ((expr.call.symbol_reference is CreationMethod
+-                    && expr.call.symbol_reference.parent_symbol is Struct)
+-                   || expr.call.symbol_reference is Struct)) {
+-                      var struct_creation_expression = new ObjectCreationExpression ((MemberAccess) expr.call, expr.source_reference);
+-                      struct_creation_expression.struct_creation = true;
+-                      foreach (Expression arg in expr.get_argument_list ()) {
+-                              struct_creation_expression.add_argument (arg);
+-                      }
+-                      struct_creation_expression.target_type = expr.target_type;
+-                      replaced_nodes.add (expr);
+-                      expr.parent_node.replace_expression (expr, struct_creation_expression);
+-                      struct_creation_expression.accept (this);
+-                      return;
+-              } else if (expr.call is MemberAccess
+-                         && expr.call.symbol_reference is CreationMethod) {
+-                      // constructor chain-up
+-                      var cm = find_current_method () as CreationMethod;
+-                      assert (cm != null);
+-                      if (cm.chain_up) {
+-                              expr.error = true;
+-                              Report.error (expr.source_reference, "Multiple constructor calls in the same constructor are not permitted");
+-                              return;
+-                      }
+-                      cm.chain_up = true;
+-              }
+-
+-              Gee.List<FormalParameter> params;
+-
+-              if (mtype != null && mtype.is_invokable ()) {
+-                      params = mtype.get_parameters ();
+-              } else {
+-                      expr.error = true;
+-                      Report.error (expr.source_reference, "invocation not supported in this context");
+-                      return;
+-              }
+-
+-              Expression last_arg = null;
+-
+-              var args = expr.get_argument_list ();
+-              Iterator<Expression> arg_it = args.iterator ();
+-              foreach (FormalParameter param in params) {
+-                      if (param.ellipsis) {
+-                              break;
+-                      }
+-
+-                      if (arg_it.next ()) {
+-                              Expression arg = arg_it.get ();
+-
+-                              /* store expected type for callback parameters */
+-                              arg.target_type = param.parameter_type;
+-
+-                              // resolve generic type parameters
+-                              var ma = expr.call as MemberAccess;
+-                              if (arg.target_type.type_parameter != null) {
+-                                      if (ma != null && ma.inner != null) {
+-                                              arg.target_type = get_actual_type (ma.inner.value_type, ma.symbol_reference, arg.target_type, arg);
+-                                              assert (arg.target_type != null);
+-                                      }
+-                              }
+-
+-                              last_arg = arg;
+-                      }
+-              }
+-
+-              // printf arguments
+-              if (mtype is MethodType && ((MethodType) mtype).method_symbol.printf_format) {
+-                      StringLiteral format_literal = null;
+-                      if (last_arg != null) {
+-                              // use last argument as format string
+-                              format_literal = last_arg as StringLiteral;
+-                      } else {
+-                              // use instance as format string for string.printf (...)
+-                              var ma = expr.call as MemberAccess;
+-                              if (ma != null) {
+-                                      format_literal = ma.inner as StringLiteral;
+-                              }
+-                      }
+-                      if (format_literal != null) {
+-                              string format = format_literal.eval ();
+-
+-                              bool unsupported_format = false;
+-
+-                              weak string format_it = format;
+-                              unichar c = format_it.get_char ();
+-                              while (c != '\0') {
+-                                      if (c != '%') {
+-                                              format_it = format_it.next_char ();
+-                                              c = format_it.get_char ();
+-                                              continue;
+-                                      }
+-
+-                                      format_it = format_it.next_char ();
+-                                      c = format_it.get_char ();
+-                                      // flags
+-                                      while (c == '#' || c == '0' || c == '-' || c == ' ' || c == '+') {
+-                                              format_it = format_it.next_char ();
+-                                              c = format_it.get_char ();
+-                                      }
+-                                      // field width
+-                                      while (c >= '0' && c <= '9') {
+-                                              format_it = format_it.next_char ();
+-                                              c = format_it.get_char ();
+-                                      }
+-                                      // precision
+-                                      if (c == '.') {
+-                                              format_it = format_it.next_char ();
+-                                              c = format_it.get_char ();
+-                                              while (c >= '0' && c <= '9') {
+-                                                      format_it = format_it.next_char ();
+-                                                      c = format_it.get_char ();
+-                                              }
+-                                      }
+-                                      // length modifier
+-                                      int length = 0;
+-                                      if (c == 'h') {
+-                                              length = -1;
+-                                              format_it = format_it.next_char ();
+-                                              c = format_it.get_char ();
+-                                              if (c == 'h') {
+-                                                      length = -2;
+-                                                      format_it = format_it.next_char ();
+-                                                      c = format_it.get_char ();
+-                                              }
+-                                      } else if (c == 'l') {
+-                                              length = 1;
+-                                              format_it = format_it.next_char ();
+-                                              c = format_it.get_char ();
+-                                      } else if (c == 'z') {
+-                                              length = 2;
+-                                              format_it = format_it.next_char ();
+-                                              c = format_it.get_char ();
+-                                      }
+-                                      // conversion specifier
+-                                      DataType param_type = null;
+-                                      if (c == 'd' || c == 'i' || c == 'c') {
+-                                              // integer
+-                                              if (length == -2) {
+-                                                      param_type = int8_type;
+-                                              } else if (length == -1) {
+-                                                      param_type = short_type;
+-                                              } else if (length == 0) {
+-                                                      param_type = int_type;
+-                                              } else if (length == 1) {
+-                                                      param_type = long_type;
+-                                              } else if (length == 2) {
+-                                                      param_type = ssize_t_type;
+-                                              }
+-                                      } else if (c == 'o' || c == 'u' || c == 'x' || c == 'X') {
+-                                              // unsigned integer
+-                                              if (length == -2) {
+-                                                      param_type = uchar_type;
+-                                              } else if (length == -1) {
+-                                                      param_type = ushort_type;
+-                                              } else if (length == 0) {
+-                                                      param_type = uint_type;
+-                                              } else if (length == 1) {
+-                                                      param_type = ulong_type;
+-                                              } else if (length == 2) {
+-                                                      param_type = size_t_type;
+-                                              }
+-                                      } else if (c == 'e' || c == 'E' || c == 'f' || c == 'F'
+-                                                 || c == 'g' || c == 'G' || c == 'a' || c == 'A') {
+-                                              // double
+-                                              param_type = double_type;
+-                                      } else if (c == 's') {
+-                                              // string
+-                                              param_type = string_type;
+-                                      } else if (c == 'p') {
+-                                              // pointer
+-                                              param_type = new PointerType (new VoidType ());
+-                                      } else if (c == '%') {
+-                                              // literal %
+-                                      } else {
+-                                              unsupported_format = true;
+-                                              break;
+-                                      }
+-                                      if (c != '\0') {
+-                                              format_it = format_it.next_char ();
+-                                              c = format_it.get_char ();
+-                                      }
+-                                      if (param_type != null) {
+-                                              if (arg_it.next ()) {
+-                                                      Expression arg = arg_it.get ();
+-
+-                                                      arg.target_type = param_type;
+-                                              } else {
+-                                                      Report.error (expr.source_reference, "Too few arguments for specified format");
+-                                                      return;
+-                                              }
+-                                      }
+-                              }
+-                              if (!unsupported_format && arg_it.next ()) {
+-                                      Report.error (expr.source_reference, "Too many arguments for specified format");
+-                                      return;
+-                              }
+-                      }
+-              }
+-
+-              foreach (Expression arg in expr.get_argument_list ()) {
+-                      arg.accept (this);
+-              }
+-
+-              DataType ret_type;
+-
+-              ret_type = mtype.get_return_type ();
+-              params = mtype.get_parameters ();
+-
+-              if (ret_type is VoidType) {
+-                      // void return type
+-                      if (!(expr.parent_node is ExpressionStatement)
+-                          && !(expr.parent_node is ForStatement)
+-                          && !(expr.parent_node is YieldStatement)) {
+-                              // A void method invocation can be in the initializer or
+-                              // iterator of a for statement
+-                              expr.error = true;
+-                              Report.error (expr.source_reference, "invocation of void method not allowed as expression");
+-                              return;
+-                      }
+-              }
+-
+-              // resolve generic return values
+-              var ma = expr.call as MemberAccess;
+-              if (ret_type.type_parameter != null) {
+-                      if (ma != null && ma.inner != null) {
+-                              ret_type = get_actual_type (ma.inner.value_type, ma.symbol_reference, ret_type, expr);
+-                              if (ret_type == null) {
+-                                      return;
+-                              }
+-                      }
+-              }
+-              Gee.List<DataType> resolved_type_args = new ArrayList<DataType> ();
+-              foreach (DataType type_arg in ret_type.get_type_arguments ()) {
+-                      if (type_arg.type_parameter != null && ma != null && ma.inner != null) {
+-                              resolved_type_args.add (get_actual_type (ma.inner.value_type, ma.symbol_reference, type_arg, expr));
+-                      } else {
+-                              resolved_type_args.add (type_arg);
+-                      }
+-              }
+-              ret_type = ret_type.copy ();
+-              ret_type.remove_all_type_arguments ();
+-              foreach (DataType resolved_type_arg in resolved_type_args) {
+-                      ret_type.add_type_argument (resolved_type_arg);
+-              }
+-
+-              if (mtype is MethodType) {
+-                      var m = ((MethodType) mtype).method_symbol;
+-                      foreach (DataType error_type in m.get_error_types ()) {
+-                              // ensure we can trace back which expression may throw errors of this type
+-                              var call_error_type = error_type.copy ();
+-                              call_error_type.source_reference = expr.source_reference;
+-
+-                              expr.add_error_type (call_error_type);
+-                      }
+-              }
+-
+-              expr.value_type = ret_type;
+-
+-              check_arguments (expr, mtype, params, expr.get_argument_list ());
++              expr.check (this);
+       }
+-      private bool check_arguments (Expression expr, DataType mtype, Gee.List<FormalParameter> params, Gee.List<Expression> args) {
++      public bool check_arguments (Expression expr, DataType mtype, Gee.List<FormalParameter> params, Gee.List<Expression> args) {
+               Expression prev_arg = null;
+               Iterator<Expression> arg_it = args.iterator ();
+@@ -2480,121 +773,10 @@
+       }
+       public override void visit_element_access (ElementAccess expr) {
+-              expr.container.accept (this);
+-
+-              if (expr.container.value_type == null) {
+-                      /* don't proceed if a child expression failed */
+-                      expr.error = true;
+-                      return;
+-              }
+-
+-              var container_type = expr.container.value_type.data_type;
+-
+-              if (expr.container is MemberAccess && expr.container.symbol_reference is Signal) {
+-                      // signal detail access
+-                      if (expr.get_indices ().size != 1) {
+-                              expr.error = true;
+-                              Report.error (expr.source_reference, "Element access with more than one dimension is not supported for signals");
+-                              return;
+-                      }
+-                      expr.get_indices ().get (0).target_type = string_type.copy ();
+-              }
+-
+-              foreach (Expression index in expr.get_indices ()) {
+-                      index.accept (this);
+-              }
+-
+-              bool index_int_type_check = true;
+-
+-              var pointer_type = expr.container.value_type as PointerType;
+-
+-              /* assign a value_type when possible */
+-              if (expr.container.value_type is ArrayType) {
+-                      var array_type = (ArrayType) expr.container.value_type;
+-                      expr.value_type = array_type.element_type.copy ();
+-                      if (!expr.lvalue) {
+-                              expr.value_type.value_owned = false;
+-                      }
+-              } else if (pointer_type != null && !pointer_type.base_type.is_reference_type_or_type_parameter ()) {
+-                      expr.value_type = pointer_type.base_type.copy ();
+-              } else if (container_type == string_type.data_type) {
+-                      if (expr.get_indices ().size != 1) {
+-                              expr.error = true;
+-                              Report.error (expr.source_reference, "Element access with more than one dimension is not supported for strings");
+-                              return;
+-                      }
+-
+-                      expr.value_type = unichar_type;
+-              } else if (container_type != null && list_type != null && map_type != null &&
+-                         (container_type.is_subtype_of (list_type) || container_type.is_subtype_of (map_type))) {
+-                      Gee.List<Expression> indices = expr.get_indices ();
+-                      if (indices.size != 1) {
+-                              expr.error = true;
+-                              Report.error (expr.source_reference, "Element access with more than one dimension is not supported for the specified type");
+-                              return;
+-                      }
+-                      Iterator<Expression> indices_it = indices.iterator ();
+-                      indices_it.next ();
+-                      var index = indices_it.get ();
+-                      index_int_type_check = false;
+-
+-                      // lookup symbol in interface instead of class as implemented interface methods are not in VAPI files
+-                      Symbol get_sym = null;
+-                      if (container_type.is_subtype_of (list_type)) {
+-                              get_sym = list_type.scope.lookup ("get");
+-                      } else if (container_type.is_subtype_of (map_type)) {
+-                              get_sym = map_type.scope.lookup ("get");
+-                      }
+-                      var get_method = (Method) get_sym;
+-                      Gee.List<FormalParameter> get_params = get_method.get_parameters ();
+-                      Iterator<FormalParameter> get_params_it = get_params.iterator ();
+-                      get_params_it.next ();
+-                      var get_param = get_params_it.get ();
+-
+-                      var index_type = get_param.parameter_type;
+-                      if (index_type.type_parameter != null) {
+-                              index_type = get_actual_type (expr.container.value_type, get_method, get_param.parameter_type, expr);
+-                      }
+-
+-                      if (!index.value_type.compatible (index_type)) {
+-                              expr.error = true;
+-                              Report.error (expr.source_reference, "index expression: Cannot convert from `%s' to `%s'".printf (index.value_type.to_string (), index_type.to_string ()));
+-                              return;
+-                      }
+-
+-                      expr.value_type = get_actual_type (expr.container.value_type, get_method, get_method.return_type, expr).copy ();
+-                      if (expr.lvalue) {
+-                              // get () returns owned value, set () accepts unowned value
+-                              expr.value_type.value_owned = false;
+-                      }
+-              } else if (expr.container is MemberAccess && expr.container.symbol_reference is Signal) {
+-                      index_int_type_check = false;
+-
+-                      expr.symbol_reference = expr.container.symbol_reference;
+-                      expr.value_type = expr.container.value_type;
+-              } else {
+-                      expr.error = true;
+-                      Report.error (expr.source_reference, "The expression `%s' does not denote an Array".printf (expr.container.value_type.to_string ()));
+-              }
+-
+-              if (index_int_type_check) {
+-                      /* check if the index is of type integer */
+-                      foreach (Expression e in expr.get_indices ()) {
+-                              /* don't proceed if a child expression failed */
+-                              if (e.value_type == null) {
+-                                      return;
+-                              }
+-
+-                              /* check if the index is of type integer */
+-                              if (!(e.value_type.data_type is Struct) || !((Struct) e.value_type.data_type).is_integer_type ()) {
+-                                      expr.error = true;
+-                                      Report.error (e.source_reference, "Expression of integer type expected");
+-                              }
+-                      }
+-              }
++              expr.check (this);
+       }
+-      private bool is_in_instance_method () {
++      public bool is_in_instance_method () {
+               var sym = current_symbol;
+               while (sym != null) {
+                       if (sym is CreationMethod) {
+@@ -2652,195 +834,10 @@
+       }
+       public override void visit_object_creation_expression (ObjectCreationExpression expr) {
+-              if (expr.member_name != null) {
+-                      expr.member_name.accept (this);
+-              }
+-
+-              TypeSymbol type = null;
+-
+-              if (expr.type_reference == null) {
+-                      if (expr.member_name == null) {
+-                              expr.error = true;
+-                              Report.error (expr.source_reference, "Incomplete object creation expression");
+-                              return;
+-                      }
+-
+-                      if (expr.member_name.symbol_reference == null) {
+-                              expr.error = true;
+-                              return;
+-                      }
+-
+-                      var constructor_sym = expr.member_name.symbol_reference;
+-                      var type_sym = expr.member_name.symbol_reference;
+-
+-                      var type_args = expr.member_name.get_type_arguments ();
+-
+-                      if (constructor_sym is Method) {
+-                              type_sym = constructor_sym.parent_symbol;
+-
+-                              var constructor = (Method) constructor_sym;
+-                              if (!(constructor_sym is CreationMethod)) {
+-                                      expr.error = true;
+-                                      Report.error (expr.source_reference, "`%s' is not a creation method".printf (constructor.get_full_name ()));
+-                                      return;
+-                              }
+-
+-                              expr.symbol_reference = constructor;
+-
+-                              // inner expression can also be base access when chaining constructors
+-                              var ma = expr.member_name.inner as MemberAccess;
+-                              if (ma != null) {
+-                                      type_args = ma.get_type_arguments ();
+-                              }
+-                      }
+-
+-                      if (type_sym is Class) {
+-                              type = (TypeSymbol) type_sym;
+-                              expr.type_reference = new ObjectType ((Class) type);
+-                      } else if (type_sym is Struct) {
+-                              type = (TypeSymbol) type_sym;
+-                              expr.type_reference = new ValueType (type);
+-                      } else if (type_sym is ErrorCode) {
+-                              expr.type_reference = new ErrorType ((ErrorDomain) type_sym.parent_symbol, (ErrorCode) type_sym, expr.source_reference);
+-                              expr.symbol_reference = type_sym;
+-                      } else {
+-                              expr.error = true;
+-                              Report.error (expr.source_reference, "`%s' is not a class, struct, or error code".printf (type_sym.get_full_name ()));
+-                              return;
+-                      }
+-
+-                      foreach (DataType type_arg in type_args) {
+-                              expr.type_reference.add_type_argument (type_arg);
+-
+-                              current_source_file.add_type_dependency (type_arg, SourceFileDependencyType.SOURCE);
+-                      }
+-              } else {
+-                      type = expr.type_reference.data_type;
+-              }
+-
+-              current_source_file.add_symbol_dependency (type, SourceFileDependencyType.SOURCE);
+-
+-              expr.value_type = expr.type_reference.copy ();
+-              expr.value_type.value_owned = true;
+-
+-              int given_num_type_args = expr.type_reference.get_type_arguments ().size;
+-              int expected_num_type_args = 0;
+-
+-              if (type is Class) {
+-                      var cl = (Class) type;
+-
+-                      expected_num_type_args = cl.get_type_parameters ().size;
+-
+-                      if (expr.struct_creation) {
+-                              expr.error = true;
+-                              Report.error (expr.source_reference, "syntax error, use `new' to create new objects");
+-                              return;
+-                      }
+-
+-                      if (cl.is_abstract) {
+-                              expr.value_type = null;
+-                              expr.error = true;
+-                              Report.error (expr.source_reference, "Can't create instance of abstract class `%s'".printf (cl.get_full_name ()));
+-                              return;
+-                      }
+-
+-                      if (expr.symbol_reference == null) {
+-                              expr.symbol_reference = cl.default_construction_method;
+-                      }
+-
+-                      while (cl != null) {
+-                              if (cl == initially_unowned_type) {
+-                                      expr.value_type.floating_reference = true;
+-                                      break;
+-                              }
+-
+-                              cl = cl.base_class;
+-                      }
+-              } else if (type is Struct) {
+-                      var st = (Struct) type;
+-
+-                      expected_num_type_args = st.get_type_parameters ().size;
+-
+-                      if (!expr.struct_creation) {
+-                              Report.warning (expr.source_reference, "deprecated syntax, don't use `new' to initialize structs");
+-                      }
+-
+-                      if (expr.symbol_reference == null) {
+-                              expr.symbol_reference = st.default_construction_method;
+-                      }
+-              }
+-
+-              if (expected_num_type_args > given_num_type_args) {
+-                      expr.error = true;
+-                      Report.error (expr.source_reference, "too few type arguments");
+-                      return;
+-              } else if (expected_num_type_args < given_num_type_args) {
+-                      expr.error = true;
+-                      Report.error (expr.source_reference, "too many type arguments");
+-                      return;
+-              }
+-
+-              if (expr.symbol_reference == null && expr.get_argument_list ().size != 0) {
+-                      expr.value_type = null;
+-                      expr.error = true;
+-                      Report.error (expr.source_reference, "No arguments allowed when constructing type `%s'".printf (type.get_full_name ()));
+-                      return;
+-              }
+-
+-              if (expr.symbol_reference is Method) {
+-                      var m = (Method) expr.symbol_reference;
+-
+-                      var args = expr.get_argument_list ();
+-                      Iterator<Expression> arg_it = args.iterator ();
+-                      foreach (FormalParameter param in m.get_parameters ()) {
+-                              if (param.ellipsis) {
+-                                      break;
+-                              }
+-
+-                              if (arg_it.next ()) {
+-                                      Expression arg = arg_it.get ();
+-
+-                                      /* store expected type for callback parameters */
+-                                      arg.target_type = param.parameter_type;
+-                              }
+-                      }
+-
+-                      foreach (Expression arg in args) {
+-                              arg.accept (this);
+-                      }
+-
+-                      check_arguments (expr, new MethodType (m), m.get_parameters (), args);
+-
+-                      foreach (DataType error_type in m.get_error_types ()) {
+-                              // ensure we can trace back which expression may throw errors of this type
+-                              var call_error_type = error_type.copy ();
+-                              call_error_type.source_reference = expr.source_reference;
+-
+-                              expr.add_error_type (call_error_type);
+-                      }
+-              } else if (expr.type_reference is ErrorType) {
+-                      expr.accept_children (this);
+-
+-                      if (expr.get_argument_list ().size == 0) {
+-                              expr.error = true;
+-                              Report.error (expr.source_reference, "Too few arguments, errors need at least 1 argument");
+-                      } else {
+-                              Iterator<Expression> arg_it = expr.get_argument_list ().iterator ();
+-                              arg_it.next ();
+-                              var ex = arg_it.get ();
+-                              if (ex.value_type == null || !ex.value_type.compatible (string_type)) {
+-                                      expr.error = true;
+-                                      Report.error (expr.source_reference, "Invalid type for argument 1");
+-                              }
+-                      }
+-              }
+-
+-              foreach (MemberInitializer init in expr.get_object_initializer ()) {
+-                      visit_member_initializer (init, expr.type_reference);
+-              }
++              expr.check (this);
+       }
+-      void visit_member_initializer (MemberInitializer init, DataType type) {
++      public void visit_member_initializer (MemberInitializer init, DataType type) {
+               init.accept (this);
+               init.symbol_reference = symbol_lookup_inherited (type.data_type, init.name);
+@@ -3084,7 +1081,7 @@
+               expr.value_type.value_owned = true;
+       }
+-      private DataType? get_arithmetic_result_type (DataType left_type, DataType right_type) {
++      public DataType? get_arithmetic_result_type (DataType left_type, DataType right_type) {
+                if (!(left_type.data_type is Struct) || !(right_type.data_type is Struct)) {
+                       // at least one operand not struct
+                       return null;
+@@ -3117,158 +1114,7 @@
+       }
+       public override void visit_binary_expression (BinaryExpression expr) {
+-              if (expr.left.error || expr.right.error) {
+-                      /* if there were any errors in inner expressions, skip type check */
+-                      expr.error = true;
+-                      return;
+-              }
+-
+-              if (expr.left.value_type == null) {
+-                      Report.error (expr.left.source_reference, "invalid left operand");
+-                      expr.error = true;
+-                      return;
+-              }
+-
+-              if (expr.operator != BinaryOperator.IN && expr.right.value_type == null) {
+-                      Report.error (expr.right.source_reference, "invalid right operand");
+-                      expr.error = true;
+-                      return;
+-              }
+-
+-              if (expr.left.value_type.data_type == string_type.data_type
+-                  && expr.operator == BinaryOperator.PLUS) {
+-                      // string concatenation
+-
+-                      if (expr.right.value_type == null || expr.right.value_type.data_type != string_type.data_type) {
+-                              expr.error = true;
+-                              Report.error (expr.source_reference, "Operands must be strings");
+-                              return;
+-                      }
+-
+-                      expr.value_type = string_type.copy ();
+-                      if (expr.left.is_constant () && expr.right.is_constant ()) {
+-                              expr.value_type.value_owned = false;
+-                      } else {
+-                              expr.value_type.value_owned = true;
+-                      }
+-              } else if (expr.operator == BinaryOperator.PLUS
+-                         || expr.operator == BinaryOperator.MINUS
+-                         || expr.operator == BinaryOperator.MUL
+-                         || expr.operator == BinaryOperator.DIV) {
+-                      // check for pointer arithmetic
+-                      if (expr.left.value_type is PointerType) {
+-                              var offset_type = expr.right.value_type.data_type as Struct;
+-                              if (offset_type != null && offset_type.is_integer_type ()) {
+-                                      if (expr.operator == BinaryOperator.PLUS
+-                                          || expr.operator == BinaryOperator.MINUS) {
+-                                              // pointer arithmetic: pointer +/- offset
+-                                              expr.value_type = expr.left.value_type.copy ();
+-                                      }
+-                              } else if (expr.right.value_type is PointerType) {
+-                                      // pointer arithmetic: pointer - pointer
+-                                      expr.value_type = size_t_type;
+-                              }
+-                      }
+-
+-                      if (expr.value_type == null) {
+-                              expr.value_type = get_arithmetic_result_type (expr.left.value_type, expr.right.value_type);
+-                      }
+-
+-                      if (expr.value_type == null) {
+-                              expr.error = true;
+-                              Report.error (expr.source_reference, "Arithmetic operation not supported for types `%s' and `%s'".printf (expr.left.value_type.to_string (), expr.right.value_type.to_string ()));
+-                              return;
+-                      }
+-              } else if (expr.operator == BinaryOperator.MOD
+-                         || expr.operator == BinaryOperator.SHIFT_LEFT
+-                         || expr.operator == BinaryOperator.SHIFT_RIGHT
+-                         || expr.operator == BinaryOperator.BITWISE_XOR) {
+-                      expr.value_type = get_arithmetic_result_type (expr.left.value_type, expr.right.value_type);
+-
+-                      if (expr.value_type == null) {
+-                              expr.error = true;
+-                              Report.error (expr.source_reference, "Arithmetic operation not supported for types `%s' and `%s'".printf (expr.left.value_type.to_string (), expr.right.value_type.to_string ()));
+-                              return;
+-                      }
+-              } else if (expr.operator == BinaryOperator.LESS_THAN
+-                         || expr.operator == BinaryOperator.GREATER_THAN
+-                         || expr.operator == BinaryOperator.LESS_THAN_OR_EQUAL
+-                         || expr.operator == BinaryOperator.GREATER_THAN_OR_EQUAL) {
+-                      if (expr.left.value_type.compatible (string_type)
+-                          && expr.right.value_type.compatible (string_type)) {
+-                              // string comparison
+-                              } else if (expr.left.value_type is PointerType && expr.right.value_type is PointerType) {
+-                                      // pointer arithmetic
+-                      } else {
+-                              var resulting_type = get_arithmetic_result_type (expr.left.value_type, expr.right.value_type);
+-
+-                              if (resulting_type == null) {
+-                                      expr.error = true;
+-                                      Report.error (expr.source_reference, "Relational operation not supported for types `%s' and `%s'".printf (expr.left.value_type.to_string (), expr.right.value_type.to_string ()));
+-                                      return;
+-                              }
+-                      }
+-
+-                      expr.value_type = bool_type;
+-              } else if (expr.operator == BinaryOperator.EQUALITY
+-                         || expr.operator == BinaryOperator.INEQUALITY) {
+-                      /* relational operation */
+-
+-                      if (!expr.right.value_type.compatible (expr.left.value_type)
+-                          && !expr.left.value_type.compatible (expr.right.value_type)) {
+-                              Report.error (expr.source_reference, "Equality operation: `%s' and `%s' are incompatible".printf (expr.right.value_type.to_string (), expr.left.value_type.to_string ()));
+-                              expr.error = true;
+-                              return;
+-                      }
+-
+-                      if (expr.left.value_type.compatible (string_type)
+-                          && expr.right.value_type.compatible (string_type)) {
+-                              // string comparison
+-                      }
+-
+-                      expr.value_type = bool_type;
+-              } else if (expr.operator == BinaryOperator.BITWISE_AND
+-                         || expr.operator == BinaryOperator.BITWISE_OR) {
+-                      // integer type or flags type
+-
+-                      expr.value_type = expr.left.value_type;
+-              } else if (expr.operator == BinaryOperator.AND
+-                         || expr.operator == BinaryOperator.OR) {
+-                      if (!expr.left.value_type.compatible (bool_type) || !expr.right.value_type.compatible (bool_type)) {
+-                              expr.error = true;
+-                              Report.error (expr.source_reference, "Operands must be boolean");
+-                      }
+-
+-                      expr.value_type = bool_type;
+-              } else if (expr.operator == BinaryOperator.IN) {
+-                      // integer type or flags type or collection/map
+-
+-                      /* handle collections and maps */
+-                      var container_type = expr.right.value_type.data_type;
+-                      
+-                      if ((collection_type != null && container_type.is_subtype_of (collection_type))
+-                          || (map_type != null && container_type.is_subtype_of (map_type))) {
+-                              Symbol contains_sym = null;
+-                              if (container_type.is_subtype_of (collection_type)) {
+-                                      contains_sym = collection_type.scope.lookup ("contains");
+-                              } else if (container_type.is_subtype_of (map_type)) {
+-                                      contains_sym = map_type.scope.lookup ("contains");
+-                              }
+-                              var contains_method = (Method) contains_sym;
+-                              Gee.List<FormalParameter> contains_params = contains_method.get_parameters ();
+-                              Iterator<FormalParameter> contains_params_it = contains_params.iterator ();
+-                              contains_params_it.next ();
+-                              var contains_param = contains_params_it.get ();
+-
+-                              var key_type = get_actual_type (expr.right.value_type, contains_method, contains_param.parameter_type, expr);
+-                              expr.left.target_type = key_type;
+-                      }
+-                      
+-                      expr.value_type = bool_type;
+-                      
+-              } else {
+-                      assert_not_reached ();
+-              }
++              expr.check (this);
+       }
+       public override void visit_type_check (TypeCheck expr) {
+@@ -3314,7 +1160,7 @@
+               return result;
+       }
+-      private Method? find_current_method () {
++      public Method? find_current_method () {
+               var sym = current_symbol;
+               while (sym != null) {
+                       if (sym is Method) {
+@@ -3325,7 +1171,7 @@
+               return null;
+       }
+-      private bool is_in_constructor () {
++      public bool is_in_constructor () {
+               var sym = current_symbol;
+               while (sym != null) {
+                       if (sym is Constructor) {
+@@ -3405,277 +1251,6 @@
+       }
+       public override void visit_assignment (Assignment a) {
+-              a.left.lvalue = true;
+-
+-              a.left.accept (this);
+-
+-              if (a.left.error) {
+-                      // skip on error in inner expression
+-                      a.error = true;
+-                      return;
+-              }
+-
+-              if (a.left is MemberAccess) {
+-                      var ma = (MemberAccess) a.left;
+-
+-                      if (!(ma.symbol_reference is Signal || ma.symbol_reference is DynamicProperty) && ma.value_type == null) {
+-                              a.error = true;
+-                              Report.error (a.source_reference, "unsupported lvalue in assignment");
+-                              return;
+-                      }
+-                      if (ma.prototype_access) {
+-                              a.error = true;
+-                              Report.error (a.source_reference, "Access to instance member `%s' denied".printf (ma.symbol_reference.get_full_name ()));
+-                              return;
+-                      }
+-
+-                      if (ma.error || ma.symbol_reference == null) {
+-                              a.error = true;
+-                              /* if no symbol found, skip this check */
+-                              return;
+-                      }
+-
+-                      if (ma.symbol_reference is DynamicSignal) {
+-                              // target_type not available for dynamic signals
+-                      } else if (ma.symbol_reference is Signal) {
+-                              var sig = (Signal) ma.symbol_reference;
+-                              a.right.target_type = new DelegateType (sig.get_delegate (ma.inner.value_type));
+-                      } else {
+-                              a.right.target_type = ma.value_type;
+-                      }
+-              } else if (a.left is ElementAccess) {
+-                      var ea = (ElementAccess) a.left;
+-
+-                      if (ea.container is MemberAccess && ea.container.symbol_reference is Signal) {
+-                              var ma = (MemberAccess) ea.container;
+-                              var sig = (Signal) ea.container.symbol_reference;
+-                              a.right.target_type = new DelegateType (sig.get_delegate (ma.inner.value_type));
+-                      } else {
+-                              a.right.target_type = a.left.value_type;
+-                      }
+-              } else if (a.left is PointerIndirection) {
+-                      a.right.target_type = a.left.value_type;
+-              } else {
+-                      a.error = true;
+-                      Report.error (a.source_reference, "unsupported lvalue in assignment");
+-                      return;
+-              }
+-
+-              a.right.accept (this);
+-
+-              if (a.right.error) {
+-                      // skip on error in inner expression
+-                      a.error = true;
+-                      return;
+-              }
+-
+-              if (a.operator != AssignmentOperator.SIMPLE && a.left is MemberAccess) {
+-                      // transform into simple assignment
+-                      // FIXME: only do this if the backend doesn't support
+-                      // the assignment natively
+-
+-                      var ma = (MemberAccess) a.left;
+-
+-                      if (!(ma.symbol_reference is Signal)) {
+-                              var old_value = new MemberAccess (ma.inner, ma.member_name);
+-
+-                              var bin = new BinaryExpression (BinaryOperator.PLUS, old_value, new ParenthesizedExpression (a.right, a.right.source_reference));
+-                              bin.target_type = a.right.target_type;
+-                              a.right.target_type = a.right.target_type.copy ();
+-                              a.right.target_type.value_owned = false;
+-
+-                              if (a.operator == AssignmentOperator.BITWISE_OR) {
+-                                      bin.operator = BinaryOperator.BITWISE_OR;
+-                              } else if (a.operator == AssignmentOperator.BITWISE_AND) {
+-                                      bin.operator = BinaryOperator.BITWISE_AND;
+-                              } else if (a.operator == AssignmentOperator.BITWISE_XOR) {
+-                                      bin.operator = BinaryOperator.BITWISE_XOR;
+-                              } else if (a.operator == AssignmentOperator.ADD) {
+-                                      bin.operator = BinaryOperator.PLUS;
+-                              } else if (a.operator == AssignmentOperator.SUB) {
+-                                      bin.operator = BinaryOperator.MINUS;
+-                              } else if (a.operator == AssignmentOperator.MUL) {
+-                                      bin.operator = BinaryOperator.MUL;
+-                              } else if (a.operator == AssignmentOperator.DIV) {
+-                                      bin.operator = BinaryOperator.DIV;
+-                              } else if (a.operator == AssignmentOperator.PERCENT) {
+-                                      bin.operator = BinaryOperator.MOD;
+-                              } else if (a.operator == AssignmentOperator.SHIFT_LEFT) {
+-                                      bin.operator = BinaryOperator.SHIFT_LEFT;
+-                              } else if (a.operator == AssignmentOperator.SHIFT_RIGHT) {
+-                                      bin.operator = BinaryOperator.SHIFT_RIGHT;
+-                              }
+-
+-                              a.right = bin;
+-                              a.right.accept (this);
+-
+-                              a.operator = AssignmentOperator.SIMPLE;
+-                      }
+-              }
+-
+-              if (a.left.symbol_reference is Signal) {
+-                      var sig = (Signal) a.left.symbol_reference;
+-
+-                      var m = a.right.symbol_reference as Method;
+-
+-                      if (m == null) {
+-                              a.error = true;
+-                              Report.error (a.right.source_reference, "unsupported expression for signal handler");
+-                              return;
+-                      }
+-
+-                      var dynamic_sig = sig as DynamicSignal;
+-                      if (dynamic_sig != null) {
+-                              bool first = true;
+-                              foreach (FormalParameter param in dynamic_sig.handler.value_type.get_parameters ()) {
+-                                      if (first) {
+-                                              // skip sender parameter
+-                                              first = false;
+-                                      } else {
+-                                              dynamic_sig.add_parameter (param.copy ());
+-                                      }
+-                              }
+-                              a.right.target_type = new DelegateType (sig.get_delegate (new ObjectType ((ObjectTypeSymbol) sig.parent_symbol)));
+-                      } else if (!a.right.value_type.compatible (a.right.target_type)) {
+-                              var delegate_type = (DelegateType) a.right.target_type;
+-
+-                              a.error = true;
+-                              Report.error (a.right.source_reference, "method `%s' is incompatible with signal `%s', expected `%s'".printf (a.right.value_type.to_string (), a.right.target_type.to_string (), delegate_type.delegate_symbol.get_prototype_string (m.name)));
+-                              return;
+-                      }
+-              } else if (a.left is MemberAccess) {
+-                      var ma = (MemberAccess) a.left;
+-
+-                      if (ma.symbol_reference is Property) {
+-                              var prop = (Property) ma.symbol_reference;
+-
+-                              var dynamic_prop = prop as DynamicProperty;
+-                              if (dynamic_prop != null) {
+-                                      dynamic_prop.property_type = a.right.value_type.copy ();
+-                                      a.left.value_type = dynamic_prop.property_type.copy ();
+-                              }
+-
+-                              if (prop.set_accessor == null
+-                                  || (!prop.set_accessor.writable && !(find_current_method () is CreationMethod || is_in_constructor ()))) {
+-                                      ma.error = true;
+-                                      Report.error (ma.source_reference, "Property `%s' is read-only".printf (prop.get_full_name ()));
+-                                      return;
+-                              }
+-                      } else if (ma.symbol_reference is LocalVariable && a.right.value_type == null) {
+-                              var local = (LocalVariable) ma.symbol_reference;
+-
+-                              if (a.right.symbol_reference is Method &&
+-                                  local.variable_type is DelegateType) {
+-                                      var m = (Method) a.right.symbol_reference;
+-                                      var dt = (DelegateType) local.variable_type;
+-                                      var cb = dt.delegate_symbol;
+-
+-                                      /* check whether method matches callback type */
+-                                      if (!cb.matches_method (m)) {
+-                                              a.error = true;
+-                                              Report.error (a.source_reference, "declaration of method `%s' doesn't match declaration of callback `%s'".printf (m.get_full_name (), cb.get_full_name ()));
+-                                              return;
+-                                      }
+-
+-                                      a.right.value_type = local.variable_type;
+-                              } else {
+-                                      a.error = true;
+-                                      Report.error (a.source_reference, "Assignment: Invalid callback assignment attempt");
+-                                      return;
+-                              }
+-                      } else if (ma.symbol_reference is Field && a.right.value_type == null) {
+-                              var f = (Field) ma.symbol_reference;
+-
+-                              if (a.right.symbol_reference is Method &&
+-                                  f.field_type is DelegateType) {
+-                                      var m = (Method) a.right.symbol_reference;
+-                                      var dt = (DelegateType) f.field_type;
+-                                      var cb = dt.delegate_symbol;
+-
+-                                      /* check whether method matches callback type */
+-                                      if (!cb.matches_method (m)) {
+-                                              f.error = true;
+-                                              Report.error (a.source_reference, "declaration of method `%s' doesn't match declaration of callback `%s'".printf (m.get_full_name (), cb.get_full_name ()));
+-                                              return;
+-                                      }
+-
+-                                      a.right.value_type = f.field_type;
+-                              } else {
+-                                      a.error = true;
+-                                      Report.error (a.source_reference, "Assignment: Invalid callback assignment attempt");
+-                                      return;
+-                              }
+-                      } else if (a.left.value_type != null && a.right.value_type != null) {
+-                              /* if there was an error on either side,
+-                               * i.e. a.{left|right}.value_type == null, skip type check */
+-
+-                              if (!a.right.value_type.compatible (a.left.value_type)) {
+-                                      a.error = true;
+-                                      Report.error (a.source_reference, "Assignment: Cannot convert from `%s' to `%s'".printf (a.right.value_type.to_string (), a.left.value_type.to_string ()));
+-                                      return;
+-                              }
+-
+-                              if (a.right.value_type.is_disposable ()) {
+-                                      /* rhs transfers ownership of the expression */
+-                                      if (!(a.left.value_type is PointerType) && !a.left.value_type.value_owned) {
+-                                              /* lhs doesn't own the value */
+-                                              a.error = true;
+-                                              Report.error (a.source_reference, "Invalid assignment from owned expression to unowned variable");
+-                                      }
+-                              } else if (a.left.value_type.value_owned) {
+-                                      /* lhs wants to own the value
+-                                       * rhs doesn't transfer the ownership
+-                                       * code generator needs to add reference
+-                                       * increment calls */
+-                              }
+-                      }
+-              } else if (a.left is ElementAccess) {
+-                      var ea = (ElementAccess) a.left;
+-
+-                      if (!a.right.value_type.compatible (a.left.value_type)) {
+-                              a.error = true;
+-                              Report.error (a.source_reference, "Assignment: Cannot convert from `%s' to `%s'".printf (a.right.value_type.to_string (), a.left.value_type.to_string ()));
+-                              return;
+-                      }
+-
+-                      if (a.right.value_type.is_disposable ()) {
+-                              /* rhs transfers ownership of the expression */
+-
+-                              DataType element_type;
+-
+-                              if (ea.container.value_type is ArrayType) {
+-                                      var array_type = (ArrayType) ea.container.value_type;
+-                                      element_type = array_type.element_type;
+-                              } else {
+-                                      var args = ea.container.value_type.get_type_arguments ();
+-                                      assert (args.size == 1);
+-                                      element_type = args.get (0);
+-                              }
+-
+-                              if (!(element_type is PointerType) && !element_type.value_owned) {
+-                                      /* lhs doesn't own the value */
+-                                      a.error = true;
+-                                      Report.error (a.source_reference, "Invalid assignment from owned expression to unowned variable");
+-                                      return;
+-                              }
+-                      } else if (a.left.value_type.value_owned) {
+-                              /* lhs wants to own the value
+-                               * rhs doesn't transfer the ownership
+-                               * code generator needs to add reference
+-                               * increment calls */
+-                      }
+-              } else {
+-                      return;
+-              }
+-
+-              if (a.left.value_type != null) {
+-                      a.value_type = a.left.value_type.copy ();
+-                      a.value_type.value_owned = false;
+-              } else {
+-                      a.value_type = null;
+-              }
+-
+-              a.add_error_types (a.left.get_error_types ());
+-              a.add_error_types (a.right.get_error_types ());
++              a.check (this);
+       }
+ }
+Index: vala/valasignal.vala
+===================================================================
+--- vala/valasignal.vala       (revision 1971)
++++ vala/valasignal.vala       (revision 2004)
+@@ -218,5 +218,19 @@
+               
+               return generated_method;
+       }
++
++      public override bool check (SemanticAnalyzer analyzer) {
++              if (checked) {
++                      return !error;
++              }
++
++              checked = true;
++
++              process_attributes ();
++
++              accept_children (analyzer);
++
++              return !error;
++      }
+ }
+Index: vala/valaexpressionstatement.vala
+===================================================================
+--- vala/valaexpressionstatement.vala  (revision 1971)
++++ vala/valaexpressionstatement.vala  (revision 2004)
+@@ -1,6 +1,6 @@
+ /* valaexpressionstatement.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
+@@ -85,4 +85,22 @@
+               return null;
+       }
++
++      public override bool check (SemanticAnalyzer analyzer) {
++              if (checked) {
++                      return !error;
++              }
++
++              checked = true;
++
++              if (expression.error) {
++                      // ignore inner error
++                      error = true;
++                      return false;
++              }
++
++              add_error_types (expression.get_error_types ());
++
++              return !error;
++      }
+ }
+Index: vala/valainvocationexpression.vala
+===================================================================
+--- vala/valainvocationexpression.vala (revision 1971)
++++ vala/valainvocationexpression.vala (revision 2004)
+@@ -120,4 +120,306 @@
+       public override bool is_pure () {
+               return false;
+       }
++
++      public override bool check (SemanticAnalyzer analyzer) {
++              if (checked) {
++                      return !error;
++              }
++
++              checked = true;
++
++              call.accept (analyzer);
++
++              if (call.error) {
++                      /* if method resolving didn't succeed, skip this check */
++                      error = true;
++                      return false;
++              }
++
++              if (call is MemberAccess) {
++                      var ma = (MemberAccess) call;
++                      if (ma.prototype_access) {
++                              error = true;
++                              Report.error (source_reference, "Access to instance member `%s' denied".printf (call.symbol_reference.get_full_name ()));
++                              return false;
++                      }
++              }
++
++              var mtype = call.value_type;
++
++              if (mtype is ObjectType) {
++                      // constructor chain-up
++                      var cm = analyzer.find_current_method () as CreationMethod;
++                      assert (cm != null);
++                      if (cm.chain_up) {
++                              error = true;
++                              Report.error (source_reference, "Multiple constructor calls in the same constructor are not permitted");
++                              return false;
++                      }
++                      cm.chain_up = true;
++              }
++
++              // check for struct construction
++              if (call is MemberAccess &&
++                  ((call.symbol_reference is CreationMethod
++                    && call.symbol_reference.parent_symbol is Struct)
++                   || call.symbol_reference is Struct)) {
++                      var struct_creation_expression = new ObjectCreationExpression ((MemberAccess) call, source_reference);
++                      struct_creation_expression.struct_creation = true;
++                      foreach (Expression arg in get_argument_list ()) {
++                              struct_creation_expression.add_argument (arg);
++                      }
++                      struct_creation_expression.target_type = target_type;
++                      analyzer.replaced_nodes.add (this);
++                      parent_node.replace_expression (this, struct_creation_expression);
++                      struct_creation_expression.accept (analyzer);
++                      return false;
++              } else if (call is MemberAccess
++                         && call.symbol_reference is CreationMethod) {
++                      // constructor chain-up
++                      var cm = analyzer.find_current_method () as CreationMethod;
++                      assert (cm != null);
++                      if (cm.chain_up) {
++                              error = true;
++                              Report.error (source_reference, "Multiple constructor calls in the same constructor are not permitted");
++                              return false;
++                      }
++                      cm.chain_up = true;
++              }
++
++              Gee.List<FormalParameter> params;
++
++              if (mtype != null && mtype.is_invokable ()) {
++                      params = mtype.get_parameters ();
++              } else {
++                      error = true;
++                      Report.error (source_reference, "invocation not supported in this context");
++                      return false;
++              }
++
++              Expression last_arg = null;
++
++              var args = get_argument_list ();
++              Iterator<Expression> arg_it = args.iterator ();
++              foreach (FormalParameter param in params) {
++                      if (param.ellipsis) {
++                              break;
++                      }
++
++                      if (arg_it.next ()) {
++                              Expression arg = arg_it.get ();
++
++                              /* store expected type for callback parameters */
++                              arg.target_type = param.parameter_type;
++
++                              // resolve generic type parameters
++                              var ma = call as MemberAccess;
++                              if (arg.target_type.type_parameter != null) {
++                                      if (ma != null && ma.inner != null) {
++                                              arg.target_type = analyzer.get_actual_type (ma.inner.value_type, ma.symbol_reference, arg.target_type, arg);
++                                              assert (arg.target_type != null);
++                                      }
++                              }
++
++                              last_arg = arg;
++                      }
++              }
++
++              // printf arguments
++              if (mtype is MethodType && ((MethodType) mtype).method_symbol.printf_format) {
++                      StringLiteral format_literal = null;
++                      if (last_arg != null) {
++                              // use last argument as format string
++                              format_literal = last_arg as StringLiteral;
++                      } else {
++                              // use instance as format string for string.printf (...)
++                              var ma = call as MemberAccess;
++                              if (ma != null) {
++                                      format_literal = ma.inner as StringLiteral;
++                              }
++                      }
++                      if (format_literal != null) {
++                              string format = format_literal.eval ();
++
++                              bool unsupported_format = false;
++
++                              weak string format_it = format;
++                              unichar c = format_it.get_char ();
++                              while (c != '\0') {
++                                      if (c != '%') {
++                                              format_it = format_it.next_char ();
++                                              c = format_it.get_char ();
++                                              continue;
++                                      }
++
++                                      format_it = format_it.next_char ();
++                                      c = format_it.get_char ();
++                                      // flags
++                                      while (c == '#' || c == '0' || c == '-' || c == ' ' || c == '+') {
++                                              format_it = format_it.next_char ();
++                                              c = format_it.get_char ();
++                                      }
++                                      // field width
++                                      while (c >= '0' && c <= '9') {
++                                              format_it = format_it.next_char ();
++                                              c = format_it.get_char ();
++                                      }
++                                      // precision
++                                      if (c == '.') {
++                                              format_it = format_it.next_char ();
++                                              c = format_it.get_char ();
++                                              while (c >= '0' && c <= '9') {
++                                                      format_it = format_it.next_char ();
++                                                      c = format_it.get_char ();
++                                              }
++                                      }
++                                      // length modifier
++                                      int length = 0;
++                                      if (c == 'h') {
++                                              length = -1;
++                                              format_it = format_it.next_char ();
++                                              c = format_it.get_char ();
++                                              if (c == 'h') {
++                                                      length = -2;
++                                                      format_it = format_it.next_char ();
++                                                      c = format_it.get_char ();
++                                              }
++                                      } else if (c == 'l') {
++                                              length = 1;
++                                              format_it = format_it.next_char ();
++                                              c = format_it.get_char ();
++                                      } else if (c == 'z') {
++                                              length = 2;
++                                              format_it = format_it.next_char ();
++                                              c = format_it.get_char ();
++                                      }
++                                      // conversion specifier
++                                      DataType param_type = null;
++                                      if (c == 'd' || c == 'i' || c == 'c') {
++                                              // integer
++                                              if (length == -2) {
++                                                      param_type = analyzer.int8_type;
++                                              } else if (length == -1) {
++                                                      param_type = analyzer.short_type;
++                                              } else if (length == 0) {
++                                                      param_type = analyzer.int_type;
++                                              } else if (length == 1) {
++                                                      param_type = analyzer.long_type;
++                                              } else if (length == 2) {
++                                                      param_type = analyzer.ssize_t_type;
++                                              }
++                                      } else if (c == 'o' || c == 'u' || c == 'x' || c == 'X') {
++                                              // unsigned integer
++                                              if (length == -2) {
++                                                      param_type = analyzer.uchar_type;
++                                              } else if (length == -1) {
++                                                      param_type = analyzer.ushort_type;
++                                              } else if (length == 0) {
++                                                      param_type = analyzer.uint_type;
++                                              } else if (length == 1) {
++                                                      param_type = analyzer.ulong_type;
++                                              } else if (length == 2) {
++                                                      param_type = analyzer.size_t_type;
++                                              }
++                                      } else if (c == 'e' || c == 'E' || c == 'f' || c == 'F'
++                                                 || c == 'g' || c == 'G' || c == 'a' || c == 'A') {
++                                              // double
++                                              param_type = analyzer.double_type;
++                                      } else if (c == 's') {
++                                              // string
++                                              param_type = analyzer.string_type;
++                                      } else if (c == 'p') {
++                                              // pointer
++                                              param_type = new PointerType (new VoidType ());
++                                      } else if (c == '%') {
++                                              // literal %
++                                      } else {
++                                              unsupported_format = true;
++                                              break;
++                                      }
++                                      if (c != '\0') {
++                                              format_it = format_it.next_char ();
++                                              c = format_it.get_char ();
++                                      }
++                                      if (param_type != null) {
++                                              if (arg_it.next ()) {
++                                                      Expression arg = arg_it.get ();
++
++                                                      arg.target_type = param_type;
++                                              } else {
++                                                      Report.error (source_reference, "Too few arguments for specified format");
++                                                      return false;
++                                              }
++                                      }
++                              }
++                              if (!unsupported_format && arg_it.next ()) {
++                                      Report.error (source_reference, "Too many arguments for specified format");
++                                      return false;
++                              }
++                      }
++              }
++
++              foreach (Expression arg in get_argument_list ()) {
++                      arg.accept (analyzer);
++              }
++
++              DataType ret_type;
++
++              ret_type = mtype.get_return_type ();
++              params = mtype.get_parameters ();
++
++              if (ret_type is VoidType) {
++                      // void return type
++                      if (!(parent_node is ExpressionStatement)
++                          && !(parent_node is ForStatement)
++                          && !(parent_node is YieldStatement)) {
++                              // A void method invocation can be in the initializer or
++                              // iterator of a for statement
++                              error = true;
++                              Report.error (source_reference, "invocation of void method not allowed as expression");
++                              return false;
++                      }
++              }
++
++              // resolve generic return values
++              var ma = call as MemberAccess;
++              if (ret_type.type_parameter != null) {
++                      if (ma != null && ma.inner != null) {
++                              ret_type = analyzer.get_actual_type (ma.inner.value_type, ma.symbol_reference, ret_type, this);
++                              if (ret_type == null) {
++                                      return false;
++                              }
++                      }
++              }
++              Gee.List<DataType> resolved_type_args = new ArrayList<DataType> ();
++              foreach (DataType type_arg in ret_type.get_type_arguments ()) {
++                      if (type_arg.type_parameter != null && ma != null && ma.inner != null) {
++                              resolved_type_args.add (analyzer.get_actual_type (ma.inner.value_type, ma.symbol_reference, type_arg, this));
++                      } else {
++                              resolved_type_args.add (type_arg);
++                      }
++              }
++              ret_type = ret_type.copy ();
++              ret_type.remove_all_type_arguments ();
++              foreach (DataType resolved_type_arg in resolved_type_args) {
++                      ret_type.add_type_argument (resolved_type_arg);
++              }
++
++              if (mtype is MethodType) {
++                      var m = ((MethodType) mtype).method_symbol;
++                      foreach (DataType error_type in m.get_error_types ()) {
++                              // ensure we can trace back which expression may throw errors of this type
++                              var call_error_type = error_type.copy ();
++                              call_error_type.source_reference = source_reference;
++
++                              add_error_type (call_error_type);
++                      }
++              }
++
++              value_type = ret_type;
++
++              analyzer.check_arguments (this, mtype, params, get_argument_list ());
++
++              return !error;
++      }
+ }
+Index: vala/valatrystatement.vala
+===================================================================
+--- vala/valatrystatement.vala (revision 1971)
++++ vala/valatrystatement.vala (revision 2004)
+@@ -86,4 +86,16 @@
+                       finally_body.accept (visitor);
+               }
+       }
++
++      public override bool check (SemanticAnalyzer analyzer) {
++              if (checked) {
++                      return !error;
++              }
++
++              checked = true;
++
++              accept_children (analyzer);
++
++              return !error;
++      }
+ }
+Index: vala/valareturnstatement.vala
+===================================================================
+--- vala/valareturnstatement.vala      (revision 1971)
++++ vala/valareturnstatement.vala      (revision 2004)
+@@ -70,4 +70,77 @@
+                       return_expression = new_node;
+               }
+       }
++
++      public override bool check (SemanticAnalyzer analyzer) {
++              if (checked) {
++                      return !error;
++              }
++
++              checked = true;
++
++              if (return_expression != null) {
++                      return_expression.target_type = analyzer.current_return_type;
++              }
++
++              accept_children (analyzer);
++
++              if (return_expression != null && return_expression.error) {
++                      // ignore inner error
++                      error = true;
++                      return false;
++              }
++
++              if (analyzer.current_return_type == null) {
++                      error = true;
++                      Report.error (source_reference, "Return not allowed in this context");
++                      return false;
++              }
++
++              if (return_expression == null) {
++                      if (!(analyzer.current_return_type is VoidType)) {
++                              error = true;
++                              Report.error (source_reference, "Return without value in non-void function");
++                      }
++                      return !error;
++              }
++
++              if (analyzer.current_return_type is VoidType) {
++                      Report.error (source_reference, "Return with value in void function");
++                      return false;
++              }
++
++              if (return_expression.value_type == null) {
++                      error = true;
++                      Report.error (source_reference, "Invalid expression in return value");
++                      return false;
++              }
++
++              if (!return_expression.value_type.compatible (analyzer.current_return_type)) {
++                      error = true;
++                      Report.error (source_reference, "Return: Cannot convert from `%s' to `%s'".printf (return_expression.value_type.to_string (), analyzer.current_return_type.to_string ()));
++                      return false;
++              }
++
++              if (return_expression.value_type.is_disposable () &&
++                  !analyzer.current_return_type.value_owned) {
++                      error = true;
++                      Report.error (source_reference, "Return value transfers ownership but method return type hasn't been declared to transfer ownership");
++                      return false;
++              }
++
++              if (return_expression.symbol_reference is LocalVariable &&
++                  return_expression.value_type.is_disposable () &&
++                  !analyzer.current_return_type.value_owned) {
++                      Report.warning (source_reference, "Local variable with strong reference used as return value and method return type hasn't been declared to transfer ownership");
++              }
++
++              if (analyzer.context.non_null && return_expression is NullLiteral
++                  && !analyzer.current_return_type.nullable) {
++                      Report.warning (source_reference, "`null' incompatible with return type `%s`".printf (analyzer.current_return_type.to_string ()));
++              }
++
++              add_error_types (return_expression.get_error_types ());
++
++              return !error;
++      }
+ }
+Index: vala/valaclass.vala
+===================================================================
+--- vala/valaclass.vala        (revision 1971)
++++ vala/valaclass.vala        (revision 2004)
+@@ -814,5 +814,202 @@
+                       }
+               }
+       }
++
++      private void get_all_prerequisites (Interface iface, Gee.List<TypeSymbol> list) {
++              foreach (DataType prereq in iface.get_prerequisites ()) {
++                      TypeSymbol type = prereq.data_type;
++                      /* skip on previous errors */
++                      if (type == null) {
++                              continue;
++                      }
++
++                      list.add (type);
++                      if (type is Interface) {
++                              get_all_prerequisites ((Interface) type, list);
++
++                      }
++              }
++      }
++
++      private bool class_is_a (Class cl, TypeSymbol t) {
++              if (cl == t) {
++                      return true;
++              }
++
++              foreach (DataType base_type in cl.get_base_types ()) {
++                      if (base_type.data_type is Class) {
++                              if (class_is_a ((Class) base_type.data_type, t)) {
++                                      return true;
++                              }
++                      } else if (base_type.data_type == t) {
++                              return true;
++                      }
++              }
++
++              return false;
++      }
++
++      public override bool check (SemanticAnalyzer analyzer) {
++              if (checked) {
++                      return !error;
++              }
++
++              checked = true;
++
++              process_attributes ();
++
++              var old_source_file = analyzer.current_source_file;
++              var old_symbol = analyzer.current_symbol;
++              var old_class = analyzer.current_class;
++
++              if (source_reference != null) {
++                      analyzer.current_source_file = source_reference.file;
++              }
++              analyzer.current_symbol = this;
++              analyzer.current_class = this;
++
++              foreach (DataType base_type_reference in get_base_types ()) {
++                      if (!base_type_reference.check (analyzer)) {
++                              error = true;
++                              return false;
++                      }
++
++                      // check whether base type is at least as accessible as the class
++                      if (!analyzer.is_type_accessible (this, base_type_reference)) {
++                              error = true;
++                              Report.error (source_reference, "base type `%s` is less accessible than class `%s`".printf (base_type_reference.to_string (), get_full_name ()));
++                              return false;
++                      }
++
++                      analyzer.current_source_file.add_type_dependency (base_type_reference, SourceFileDependencyType.HEADER_FULL);
++              }
++
++              accept_children (analyzer);
++
++              /* compact classes cannot implement interfaces */
++              if (is_compact) {
++                      foreach (DataType base_type in get_base_types ()) {
++                              if (base_type.data_type is Interface) {
++                                      error = true;
++                                      Report.error (source_reference, "compact classes `%s` may not implement interfaces".printf (get_full_name ()));
++                              }
++                      }
++              }
++
++              /* gather all prerequisites */
++              Gee.List<TypeSymbol> prerequisites = new ArrayList<TypeSymbol> ();
++              foreach (DataType base_type in get_base_types ()) {
++                      if (base_type.data_type is Interface) {
++                              get_all_prerequisites ((Interface) base_type.data_type, prerequisites);
++                      }
++              }
++              /* check whether all prerequisites are met */
++              Gee.List<string> missing_prereqs = new ArrayList<string> ();
++              foreach (TypeSymbol prereq in prerequisites) {
++                      if (!class_is_a (this, prereq)) {
++                              missing_prereqs.insert (0, prereq.get_full_name ());
++                      }
++              }
++              /* report any missing prerequisites */
++              if (missing_prereqs.size > 0) {
++                      error = true;
++
++                      string error_string = "%s: some prerequisites (".printf (get_full_name ());
++                      bool first = true;
++                      foreach (string s in missing_prereqs) {
++                              if (first) {
++                                      error_string = "%s`%s'".printf (error_string, s);
++                                      first = false;
++                              } else {
++                                      error_string = "%s, `%s'".printf (error_string, s);
++                              }
++                      }
++                      error_string += ") are not met";
++                      Report.error (source_reference, error_string);
++              }
++
++              /* VAPI classes don't have to specify overridden methods */
++              if (!external_package) {
++                      /* all abstract symbols defined in base types have to be at least defined (or implemented) also in this type */
++                      foreach (DataType base_type in get_base_types ()) {
++                              if (base_type.data_type is Interface) {
++                                      Interface iface = (Interface) base_type.data_type;
++
++                                      if (base_class != null && base_class.is_subtype_of (iface)) {
++                                              // reimplementation of interface, class is not required to reimplement all methods
++                                              break;
++                                      }
++
++                                      /* We do not need to do expensive equality checking here since this is done
++                                       * already. We only need to guarantee the symbols are present.
++                                       */
++
++                                      /* check methods */
++                                      foreach (Method m in iface.get_methods ()) {
++                                              if (m.is_abstract) {
++                                                      Symbol sym = null;
++                                                      var base_class = this;
++                                                      while (base_class != null && !(sym is Method)) {
++                                                              sym = base_class.scope.lookup (m.name);
++                                                              base_class = base_class.base_class;
++                                                      }
++                                                      if (!(sym is Method)) {
++                                                              error = true;
++                                                              Report.error (source_reference, "`%s' does not implement interface method `%s'".printf (get_full_name (), m.get_full_name ()));
++                                                      }
++                                              }
++                                      }
++
++                                      /* check properties */
++                                      foreach (Property prop in iface.get_properties ()) {
++                                              if (prop.is_abstract) {
++                                                      Symbol sym = null;
++                                                      var base_class = this;
++                                                      while (base_class != null && !(sym is Property)) {
++                                                              sym = base_class.scope.lookup (prop.name);
++                                                              base_class = base_class.base_class;
++                                                      }
++                                                      if (!(sym is Property)) {
++                                                              error = true;
++                                                              Report.error (source_reference, "`%s' does not implement interface property `%s'".printf (get_full_name (), prop.get_full_name ()));
++                                                      }
++                                              }
++                                      }
++                              }
++                      }
++
++                      /* all abstract symbols defined in base classes have to be implemented in non-abstract classes */
++                      if (!is_abstract) {
++                              var base_class = base_class;
++                              while (base_class != null && base_class.is_abstract) {
++                                      foreach (Method base_method in base_class.get_methods ()) {
++                                              if (base_method.is_abstract) {
++                                                      var override_method = analyzer.symbol_lookup_inherited (this, base_method.name) as Method;
++                                                      if (override_method == null || !override_method.overrides) {
++                                                              error = true;
++                                                              Report.error (source_reference, "`%s' does not implement abstract method `%s'".printf (get_full_name (), base_method.get_full_name ()));
++                                                      }
++                                              }
++                                      }
++                                      foreach (Property base_property in base_class.get_properties ()) {
++                                              if (base_property.is_abstract) {
++                                                      var override_property = analyzer.symbol_lookup_inherited (this, base_property.name) as Property;
++                                                      if (override_property == null || !override_property.overrides) {
++                                                              error = true;
++                                                              Report.error (source_reference, "`%s' does not implement abstract property `%s'".printf (get_full_name (), base_property.get_full_name ()));
++                                                      }
++                                              }
++                                      }
++                                      base_class = base_class.base_class;
++                              }
++                      }
++              }
++
++              analyzer.current_source_file = old_source_file;
++              analyzer.current_symbol = old_symbol;
++              analyzer.current_class = old_class;
++
++              return !error;
++      }
+ }
+Index: vala/valaforstatement.vala
+===================================================================
+--- vala/valaforstatement.vala (revision 1971)
++++ vala/valaforstatement.vala (revision 2004)
+@@ -156,4 +156,40 @@
+                       }
+               }
+       }
++
++      public override bool check (SemanticAnalyzer analyzer) {
++              if (checked) {
++                      return !error;
++              }
++
++              checked = true;
++
++              accept_children (analyzer);
++
++              if (condition != null && condition.error) {
++                      /* if there was an error in the condition, skip this check */
++                      error = true;
++                      return false;
++              }
++
++              if (condition != null && !condition.value_type.compatible (analyzer.bool_type)) {
++                      error = true;
++                      Report.error (condition.source_reference, "Condition must be boolean");
++                      return false;
++              }
++
++              if (condition != null) {
++                      add_error_types (condition.get_error_types ());
++              }
++
++              add_error_types (body.get_error_types ());
++              foreach (Expression exp in get_initializer ()) {
++                      add_error_types (exp.get_error_types ());
++              }
++              foreach (Expression exp in get_iterator ()) {
++                      add_error_types (exp.get_error_types ());
++              }
++
++              return !error;
++      }
+ }
+Index: vala/valaarraycreationexpression.vala
+===================================================================
+--- vala/valaarraycreationexpression.vala      (revision 1971)
++++ vala/valaarraycreationexpression.vala      (revision 2004)
+@@ -106,4 +106,118 @@
+                       element_type = new_type;
+               }
+       }
++
++      private int create_sizes_from_initializer_list (SemanticAnalyzer analyzer, InitializerList il, int rank, Gee.List<Literal> sl) {
++              var init = new IntegerLiteral (il.size.to_string (), il.source_reference);
++              init.accept (analyzer);
++              sl.add (init);
++
++              int subsize = -1;
++              foreach (Expression e in il.get_initializers ()) {
++                      if (e is InitializerList) {
++                              if (rank == 1) {
++                                      il.error = true;
++                                      e.error = true;
++                                      Report.error (e.source_reference, "Expected array element, got array initializer list");
++                                      return -1;
++                              }
++                              int size = create_sizes_from_initializer_list (analyzer, (InitializerList) e, rank - 1, sl);
++                              if (size == -1) {
++                                      return -1;
++                              }
++                              if (subsize >= 0 && subsize != size) {
++                                      il.error = true;
++                                      Report.error (il.source_reference, "Expected initializer list of size %d, got size %d".printf (subsize, size));
++                                      return -1;
++                              } else {
++                                      subsize = size;
++                              }
++                      } else {
++                              if (rank != 1) {
++                                      il.error = true;
++                                      e.error = true;
++                                      Report.error (e.source_reference, "Expected array initializer list, got array element");
++                                      return -1;
++                              }
++                      }
++              }
++              return il.size;
++      }
++
++      public override bool check (SemanticAnalyzer analyzer) {
++              if (checked) {
++                      return !error;
++              }
++
++              checked = true;
++
++              Gee.List<Expression> size = get_sizes ();
++              var initlist = initializer_list;
++
++              if (element_type != null) {
++                      element_type.accept (analyzer);
++              }
++
++              foreach (Expression e in size) {
++                      e.accept (analyzer);
++              }
++
++              var calc_sizes = new ArrayList<Literal> ();
++              if (initlist != null) {
++                      initlist.target_type = new ArrayType (element_type, rank, source_reference);
++
++                      initlist.accept (analyzer);
++
++                      var ret = create_sizes_from_initializer_list (analyzer, initlist, rank, calc_sizes);
++                      if (ret == -1) {
++                              error = true;
++                      }
++              }
++
++              if (size.size > 0) {
++                      /* check for errors in the size list */
++                      foreach (Expression e in size) {
++                              if (e.value_type == null) {
++                                      /* return on previous error */
++                                      return false;
++                              } else if (!(e.value_type.data_type is Struct) || !((Struct) e.value_type.data_type).is_integer_type ()) {
++                                      error = true;
++                                      Report.error (e.source_reference, "Expression of integer type expected");
++                              }
++                      }
++              } else {
++                      if (initlist == null) {
++                              error = true;
++                              /* this is an internal error because it is already handeld by the parser */
++                              Report.error (source_reference, "internal error: initializer list expected");
++                      } else {
++                              foreach (Expression size in calc_sizes) {
++                                      append_size (size);
++                              }
++                      }
++              }
++
++              if (error) {
++                      return false;
++              }
++
++              /* check for wrong elements inside the initializer */
++              if (initializer_list != null && initializer_list.value_type == null) {
++                      return false;
++              }
++
++              /* try to construct the type of the array */
++              if (element_type == null) {
++                      error = true;
++                      Report.error (source_reference, "Cannot determine the element type of the created array");
++                      return false;
++              }
++
++              element_type.value_owned = true;
++
++              value_type = new ArrayType (element_type, rank, source_reference);
++              value_type.value_owned = true;
++
++              return !error;
++      }
+ }
+Index: vala/valastruct.vala
+===================================================================
+--- vala/valastruct.vala       (revision 1971)
++++ vala/valastruct.vala       (revision 2004)
+@@ -605,4 +605,28 @@
+               return false;
+       }
++
++      public override bool check (SemanticAnalyzer analyzer) {
++              if (checked) {
++                      return !error;
++              }
++
++              checked = true;
++
++              process_attributes ();
++
++              analyzer.current_symbol = this;
++              analyzer.current_struct = this;
++
++              accept_children (analyzer);
++
++              if (!external && !external_package && get_base_types ().size == 0 && get_fields ().size == 0) {
++                      Report.error (source_reference, "structs cannot be empty");
++              }
++
++              analyzer.current_symbol = analyzer.current_symbol.parent_symbol;
++              analyzer.current_struct = null;
++
++              return !error;
++      }
+ }
+Index: vala/valaconstructor.vala
+===================================================================
+--- vala/valaconstructor.vala  (revision 1971)
++++ vala/valaconstructor.vala  (revision 2004)
+@@ -60,4 +60,28 @@
+                       body.accept (visitor);
+               }
+       }
++
++      public override bool check (SemanticAnalyzer analyzer) {
++              if (checked) {
++                      return !error;
++              }
++
++              checked = true;
++
++              this_parameter = new FormalParameter ("this", new ObjectType (analyzer.current_class));
++              scope.add (this_parameter.name, this_parameter);
++
++              owner = analyzer.current_symbol.scope;
++              analyzer.current_symbol = this;
++
++              accept_children (analyzer);
++
++              foreach (DataType body_error_type in body.get_error_types ()) {
++                      Report.warning (body_error_type.source_reference, "unhandled error `%s'".printf (body_error_type.to_string()));
++              }
++
++              analyzer.current_symbol = analyzer.current_symbol.parent_symbol;
++
++              return !error;
++      }
+ }
+Index: ChangeLog
+===================================================================
+--- ChangeLog  (revision 1971)
++++ ChangeLog  (revision 2004)
+@@ -1,5 +1,273 @@
++2008-11-09  Jürg Billeter  <j@bitron.ch>
++
++      * vala/valaclass.vala:
++      * vala/valainterface.vala:
++      * vala/valamemberaccess.vala:
++      * vala/valaobjecttype.vala:
++      * vala/valasemanticanalyzer.vala:
++
++      Ensure attributes of base types are processed before querying
++      C header filenames
++
++2008-11-07  Jürg Billeter  <j@bitron.ch>
++
++      * vala/valablock.vala:
++      * vala/valacatchclause.vala:
++      * vala/valadeclarationstatement.vala:
++      * vala/valadeletestatement.vala:
++      * vala/valadostatement.vala:
++      * vala/valaexpressionstatement.vala:
++      * vala/valaforstatement.vala:
++      * vala/valaifstatement.vala:
++      * vala/valainitializerlist.vala:
++      * vala/valalocalvariable.vala:
++      * vala/valalockstatement.vala:
++      * vala/valasemanticanalyzer.vala:
++      * vala/valaswitchsection.vala:
++      * vala/valatrystatement.vala:
++      * vala/valawhilestatement.vala:
++
++      Move statement checking to code nodes
++
++2008-11-07  Jürg Billeter  <j@bitron.ch>
++
++      * vapi/glib-2.0.vapi:
++
++      Add g_rmdir binding
++
++2008-11-07  Jürg Billeter  <j@bitron.ch>
++
++      * gobject/valadbusclientmodule.vala:
++
++      Fix D-Bus methods with out parameters but no return value
++
++2008-11-07  Jürg Billeter  <j@bitron.ch>
++
++      * vala/valaconstant.vala:
++      * vala/valaconstructor.vala:
++      * vala/valacreationmethod.vala:
++      * vala/valadestructor.vala:
++      * vala/valafield.vala:
++      * vala/valaformalparameter.vala:
++      * vala/valaproperty.vala:
++      * vala/valapropertyaccessor.vala:
++      * vala/valasemanticanalyzer.vala:
++      * vala/valasignal.vala:
++
++      Move member checking to code nodes
++
++2008-11-07  Jürg Billeter  <j@bitron.ch>
++
++      * vala/valadelegate.vala:
++      * vala/valaenum.vala:
++      * vala/valaenumvalue.vala:
++      * vala/valaerrorcode.vala:
++      * vala/valaerrordomain.vala:
++      * vala/valainterface.vala:
++      * vala/valanamespace.vala:
++      * vala/valasemanticanalyzer.vala:
++      * vala/valastruct.vala:
++
++      Move type symbol checking to code nodes
++
++2008-11-07  Jürg Billeter  <j@bitron.ch>
++
++      * vala/valaarraycreationexpression.vala:
++      * vala/valasemanticanalyzer.vala:
++
++      Move array creation expression checking to
++      ArrayCreationExpression.check
++
++2008-11-07  Jürg Billeter  <j@bitron.ch>
++
++      * vala/valasemanticanalyzer.vala:
++      * vala/valathrowstatement.vala:
++
++      Move throw statement checking to ThrowStatement.check
++
++2008-11-07  Jürg Billeter  <j@bitron.ch>
++
++      * vala/valareturnstatement.vala:
++      * vala/valasemanticanalyzer.vala:
++
++      Move return statement checking to ReturnStatement.check
++
++2008-11-07  Jürg Billeter  <j@bitron.ch>
++
++      * vala/valaforeachstatement.vala:
++      * vala/valasemanticanalyzer.vala:
++
++      Move foreach statement checking to ForeachStatement.check
++
++2008-11-07  Jürg Billeter  <j@bitron.ch>
++
++      * vala/valaelementaccess.vala:
++      * vala/valasemanticanalyzer.vala:
++
++      Move element access checking to ElementAccess.check
++
++2008-11-07  Jürg Billeter  <j@bitron.ch>
++
++      * vapigen/valagirparser.vala:
++
++      Set source_reference in parsed nodes
++
++2008-11-06  Jürg Billeter  <j@bitron.ch>
++
++      * vala/valamethod.vala:
++      * vala/valasemanticanalyzer.vala:
++
++      Move method checking to Method.check
++
++2008-11-06  Jürg Billeter  <j@bitron.ch>
++
++      * vala/valaclass.vala:
++      * vala/valasemanticanalyzer.vala:
++
++      Move class checking to Class.check
++
++2008-11-06  Jürg Billeter  <j@bitron.ch>
++
++      * gobject/Makefile.am:
++      * gobject/valaccodedynamicsignalmodule.vala:
++      * gobject/valaccodegenerator.vala:
++      * gobject/valadbusclientmodule.vala:
++      * gobject/valagerrormodule.vala:
++      * gobject/valagobjectmodule.vala:
++
++      Move dynamic signal generation to GObjectModule and
++      DBusClientModule
++
++2008-11-06  Jürg Billeter  <j@bitron.ch>
++
++      * gobject/Makefile.am:
++      * gobject/valaccodedynamicpropertymodule.vala:
++      * gobject/valaccodedynamicsignalmodule.vala:
++      * gobject/valaccodegenerator.vala:
++      * gobject/valadbusclientmodule.vala:
++      * gobject/valagobjectmodule.vala:
++
++      Move dynamic property generation to GObjectModule and
++      DBusClientModule
++
++2008-11-06  Jürg Billeter  <j@bitron.ch>
++
++      * gobject/valaccodebasemodule.vala:
++      * gobject/valagobjectmodule.vala:
++
++      Move constructor code generation to GObjectModule
++
++2008-11-05  Jürg Billeter  <j@bitron.ch>
++
++      * vala/valainvocationexpression.vala:
++      * vala/valasemanticanalyzer.vala:
++
++      Move invocation expression checking to InvocationExpression.check
++
++2008-11-05  Jürg Billeter  <j@bitron.ch>
++
++      * vala/valamemberaccess.vala:
++      * vala/valasemanticanalyzer.vala:
++
++      Move member access checking to MemberAccess.check
++
++2008-11-05  Jürg Billeter  <j@bitron.ch>
++
++      * vala/valabinaryexpression.vala:
++      * vala/valaobjectcreationexpression.vala:
++      * vala/valasemanticanalyzer.vala:
++
++      Move object creation expression checking to
++      ObjectCreationExpression.check
++
++2008-11-05  Jürg Billeter  <j@bitron.ch>
++
++      * vala/valabinaryexpression.vala:
++      * vala/valasemanticanalyzer.vala:
++
++      Move binary expression checking to BinaryExpression.check
++
++2008-11-05  Jürg Billeter  <j@bitron.ch>
++
++      * vala/valaassignment.vala:
++      * vala/valasemanticanalyzer.vala:
++
++      Move assignment checking to Assignment.check
++
++2008-11-05  Jürg Billeter  <j@bitron.ch>
++
++      * vala/valaenum.vala:
++      * gobject/valadbusclientmodule.vala:
++      * gobject/valagsignalmodule.vala:
++
++      Support enums in D-Bus clients and servers, fixes bug 534105
++
++2008-11-05  Jürg Billeter  <j@bitron.ch>
++
++      * gobject/Makefile.am:
++      * gobject/valaccodebasemodule.vala:
++      * gobject/valaccodecontrolflowmodule.vala:
++      * gobject/valaccodegenerator.vala:
++      * gobject/valaccodememberaccessmodule.vala:
++
++      Add CCodeControlFlowModule
++
++2008-11-04  Jürg Billeter  <j@bitron.ch>
++
++      * vala/valadynamicproperty.vala:
++      * vala/valaproperty.vala:
++      * vala/valasemanticanalyzer.vala:
++
++      Fix crash when using dynamic properties, fixes bug 559304
++
++2008-11-04  Jürg Billeter  <j@bitron.ch>
++
++      * gobject/valaccodememberaccessmodule.vala:
++      * gobject/valagsignalmodule.vala:
++
++      Move signal emission to GSignalModule
++
++2008-11-04  Jürg Billeter  <j@bitron.ch>
++
++      * gobject/valaccodebasemodule.vala:
++      * gobject/valaccodedelegatemodule.vala:
++
++      Move delegate wrapper generation to CCodeDelegateModule
++
++2008-11-04  Jürg Billeter  <j@bitron.ch>
++
++      * gobject/valaccodearraymodule.vala:
++      * gobject/valaccodebasemodule.vala:
++
++      Move array dup wrapper generation to CCodeArrayModule
++
++2008-11-04  Jürg Billeter  <j@bitron.ch>
++
++      * gobject/valaccodebasemodule.vala:
++      * gobject/valagobjectmodule.vala:
++
++      Move construct property assignment to GObjectModule
++
++2008-11-04  Jürg Billeter  <j@bitron.ch>
++
++      * gobject/valaccodeassignmentmodule.vala:
++      * gobject/valagsignalmodule.vala:
++
++      Move signal connection and disconnection to GSignalModule
++
++2008-11-04  Jürg Billeter  <j@bitron.ch>
++
++      * gobject/valaccodearraymodule.vala:
++      * gobject/valagsignalmodule.vala:
++
++      Move detailed signal emission to GSignalModule
++
+ 2008-11-03  Jürg Billeter  <j@bitron.ch>
++      * configure.ac: Post-release version bump
++
++2008-11-03  Jürg Billeter  <j@bitron.ch>
++
+       * NEWS: update for 0.5.1 release
+ 2008-11-03  Jürg Billeter  <j@bitron.ch>
+Index: vapigen/valagirparser.vala
+===================================================================
+--- vapigen/valagirparser.vala (revision 1971)
++++ vapigen/valagirparser.vala (revision 2004)
+@@ -153,7 +153,10 @@
+                       ns = new Namespace (namespace_name);
+                       new_namespace = true;
+               } else {
+-                      ns.source_reference = new SourceReference (current_source_file);
++                      if (ns.external_package) {
++                              ns.attributes = null;
++                              ns.source_reference = get_current_src ();
++                      }
+               }
+               string cheader = get_attribute (ns.name, "c:header-filename");
+@@ -221,7 +224,7 @@
+       Struct parse_alias () {
+               start_element ("alias");
+-              var st = new Struct (reader.get_attribute ("name"));
++              var st = new Struct (reader.get_attribute ("name"), get_current_src ());
+               st.access = SymbolAccessibility.PUBLIC;
+               st.add_base_type (parse_type_from_name (reader.get_attribute ("target")));
+               next ();
+@@ -231,7 +234,7 @@
+       Enum parse_enumeration () {
+               start_element ("enumeration");
+-              var en = new Enum (reader.get_attribute ("name"));
++              var en = new Enum (reader.get_attribute ("name"), get_current_src ());
+               en.access = SymbolAccessibility.PUBLIC;
+               next ();
+@@ -274,7 +277,7 @@
+       Enum parse_bitfield () {
+               start_element ("bitfield");
+-              var en = new Enum (reader.get_attribute ("name"));
++              var en = new Enum (reader.get_attribute ("name"), get_current_src ());
+               en.access = SymbolAccessibility.PUBLIC;
+               next ();
+               while (current_token == MarkupTokenType.START_ELEMENT) {
+@@ -308,7 +311,7 @@
+               } else {
+                       return_type = new VoidType ();
+               }
+-              var m = new Method (name, return_type);
++              var m = new Method (name, return_type, get_current_src ());
+               m.access = SymbolAccessibility.PUBLIC;
+               m.binding = MemberBinding.STATIC;
+               var parameters = new ArrayList<FormalParameter> ();
+@@ -360,14 +363,14 @@
+               if (reader.name == "varargs") {
+                       start_element ("varargs");
+                       next ();
+-                      param = new FormalParameter.with_ellipsis ();
++                      param = new FormalParameter.with_ellipsis (get_current_src ());
+                       end_element ("varargs");
+               } else {
+                       var type = parse_type (out array_length_idx);
+                       if (transfer == "full") {
+                               type.value_owned = true;
+                       }
+-                      param = new FormalParameter (name, type);
++                      param = new FormalParameter (name, type, get_current_src ());
+                       if (direction == "out") {
+                               param.direction = ParameterDirection.OUT;
+                       } else if (direction == "inout") {
+@@ -455,7 +458,7 @@
+       Struct parse_record () {
+               start_element ("record");
+-              var st = new Struct (reader.get_attribute ("name"));
++              var st = new Struct (reader.get_attribute ("name"), get_current_src ());
+               st.access = SymbolAccessibility.PUBLIC;
+               next ();
+               while (current_token == MarkupTokenType.START_ELEMENT) {
+@@ -479,7 +482,7 @@
+       Class parse_class () {
+               start_element ("class");
+-              var cl = new Class (reader.get_attribute ("name"));
++              var cl = new Class (reader.get_attribute ("name"), get_current_src ());
+               cl.access = SymbolAccessibility.PUBLIC;
+               string parent = reader.get_attribute ("parent");
+@@ -575,7 +578,7 @@
+       Interface parse_interface () {
+               start_element ("interface");
+-              var iface = new Interface (reader.get_attribute ("name"));
++              var iface = new Interface (reader.get_attribute ("name"), get_current_src ());
+               iface.access = SymbolAccessibility.PUBLIC;
+               next ();
+               var methods = new ArrayList<Method> ();
+@@ -619,7 +622,7 @@
+               string name = reader.get_attribute ("name");
+               next ();
+               var type = parse_type ();
+-              var field = new Field (name, type, null);
++              var field = new Field (name, type, null, get_current_src ());
+               field.access = SymbolAccessibility.PUBLIC;
+               end_element ("field");
+               return field;
+@@ -630,7 +633,7 @@
+               string name = string.joinv ("_", reader.get_attribute ("name").split ("-"));
+               next ();
+               var type = parse_type ();
+-              var prop = new Property (name, type, null, null);
++              var prop = new Property (name, type, null, null, get_current_src ());
+               prop.access = SymbolAccessibility.PUBLIC;
+               prop.get_accessor = new PropertyAccessor (true, false, false, null, null);
+               prop.set_accessor = new PropertyAccessor (false, true, false, null, null);
+@@ -648,7 +651,7 @@
+               } else {
+                       return_type = new VoidType ();
+               }
+-              var d = new Delegate (name, return_type);
++              var d = new Delegate (name, return_type, get_current_src ());
+               d.access = SymbolAccessibility.PUBLIC;
+               if (current_token == MarkupTokenType.START_ELEMENT && reader.name == "parameters") {
+                       start_element ("parameters");
+@@ -669,7 +672,7 @@
+               var return_type = parse_return_value ();
+-              var m = new CreationMethod (null, name);
++              var m = new CreationMethod (null, name, get_current_src ());
+               m.access = SymbolAccessibility.PUBLIC;
+               m.has_construct_function = false;
+               if (m.name.has_prefix ("new_")) {
+@@ -698,7 +701,7 @@
+               } else {
+                       return_type = new VoidType ();
+               }
+-              var m = new Method (name, return_type);
++              var m = new Method (name, return_type, get_current_src ());
+               m.access = SymbolAccessibility.PUBLIC;
+               if (current_token == MarkupTokenType.START_ELEMENT && reader.name == "parameters") {
+                       start_element ("parameters");
+@@ -726,7 +729,7 @@
+               } else {
+                       return_type = new VoidType ();
+               }
+-              var m = new Method (name, return_type);
++              var m = new Method (name, return_type, get_current_src ());
+               m.access = SymbolAccessibility.PUBLIC;
+               m.is_virtual = true;
+               if (current_token == MarkupTokenType.START_ELEMENT && reader.name == "parameters") {
+@@ -828,7 +831,7 @@
+               string name = reader.get_attribute ("name");
+               next ();
+               var type = parse_type ();
+-              var c = new Constant (name, type, null, null);
++              var c = new Constant (name, type, null, get_current_src ());
+               c.access = SymbolAccessibility.PUBLIC;
+               end_element ("constant");
+               return c;
+Index: vapi/glib-2.0.vapi
+===================================================================
+--- vapi/glib-2.0.vapi (revision 1971)
++++ vapi/glib-2.0.vapi (revision 2004)
+@@ -2205,6 +2205,8 @@
+               public static int create_with_parents (string pathname, int mode);
+               [CCode (cname = "mkdtemp")]
+               public static weak string mkdtemp (string template);
++              [CCode (cname = "g_rmdir")]
++              public static int remove (string filename);
+       }
+       [Compact]
+Index: configure.ac
+===================================================================
+--- configure.ac       (revision 1971)
++++ configure.ac       (revision 2004)
+@@ -1,4 +1,4 @@
+-AC_INIT([vala], [0.5.1], [j@bitron.ch], [vala])
++AC_INIT([vala], [0.5.2], [j@bitron.ch], [vala])
+ AC_CONFIG_SRCDIR([Makefile.am])
+ AC_CONFIG_HEADERS(config.h)
+ AM_INIT_AUTOMAKE([dist-bzip2])
+Index: gobject/valaccodedynamicpropertymodule.vala
+===================================================================
+--- gobject/valaccodedynamicpropertymodule.vala        (revision 1971)
++++ gobject/valaccodedynamicpropertymodule.vala        (revision 2004)
+@@ -1,238 +0,0 @@
+-/* valaccodedynamicpropertymodule.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;
+-
+-/**
+- * The link between a dynamic property and generated code.
+- */
+-public class Vala.CCodeDynamicPropertyModule : CCodeDelegateModule {
+-      int dynamic_property_id;
+-
+-      public CCodeDynamicPropertyModule (CCodeGenerator codegen, CCodeModule? next) {
+-              base (codegen, next);
+-      }
+-
+-      public override string get_dynamic_property_getter_cname (DynamicProperty node) {
+-              string getter_cname = "_dynamic_get_%s%d".printf (node.name, dynamic_property_id++);
+-
+-              var dynamic_property = (DynamicProperty) node;
+-
+-              var func = new CCodeFunction (getter_cname, node.property_type.get_cname ());
+-              func.modifiers |= CCodeModifiers.STATIC | CCodeModifiers.INLINE;
+-
+-              func.add_parameter (new CCodeFormalParameter ("obj", dynamic_property.dynamic_type.get_cname ()));
+-
+-              var block = new CCodeBlock ();
+-              if (dynamic_property.dynamic_type.data_type == dbus_object_type) {
+-                      generate_dbus_property_getter_wrapper (node, block);
+-              } else if (dynamic_property.dynamic_type.data_type != null
+-                         && dynamic_property.dynamic_type.data_type.is_subtype_of (gobject_type)) {
+-                      generate_gobject_property_getter_wrapper (node, block);
+-              } else {
+-                      Report.error (node.source_reference, "dynamic properties are not supported for `%s'".printf (dynamic_property.dynamic_type.to_string ()));
+-              }
+-
+-              // append to C source file
+-              source_type_member_declaration.append (func.copy ());
+-
+-              func.block = block;
+-              source_type_member_definition.append (func);
+-
+-              return getter_cname;
+-      }
+-
+-      public override string get_dynamic_property_setter_cname (DynamicProperty node) {
+-              string setter_cname = "_dynamic_set_%s%d".printf (node.name, dynamic_property_id++);
+-
+-              var dynamic_property = (DynamicProperty) node;
+-
+-              var func = new CCodeFunction (setter_cname, "void");
+-              func.modifiers |= CCodeModifiers.STATIC | CCodeModifiers.INLINE;
+-
+-              func.add_parameter (new CCodeFormalParameter ("obj", dynamic_property.dynamic_type.get_cname ()));
+-              func.add_parameter (new CCodeFormalParameter ("value", node.property_type.get_cname ()));
+-
+-              var block = new CCodeBlock ();
+-              if (dynamic_property.dynamic_type.data_type == dbus_object_type) {
+-                      generate_dbus_property_setter_wrapper (node, block);
+-              } else if (dynamic_property.dynamic_type.data_type != null
+-                         && dynamic_property.dynamic_type.data_type.is_subtype_of (gobject_type)) {
+-                      generate_gobject_property_setter_wrapper (node, block);
+-              } else {
+-                      Report.error (node.source_reference, "dynamic properties are not supported for `%s'".printf (dynamic_property.dynamic_type.to_string ()));
+-              }
+-
+-              // append to C source file
+-              source_type_member_declaration.append (func.copy ());
+-
+-              func.block = block;
+-              source_type_member_definition.append (func);
+-
+-              return setter_cname;
+-      }
+-
+-      void generate_gobject_property_getter_wrapper (DynamicProperty node, CCodeBlock block) {
+-              var cdecl = new CCodeDeclaration (node.property_type.get_cname ());
+-              cdecl.add_declarator (new CCodeVariableDeclarator ("result"));
+-              block.add_statement (cdecl);
+-
+-              var call = new CCodeFunctionCall (new CCodeIdentifier ("g_object_get"));
+-              call.add_argument (new CCodeIdentifier ("obj"));
+-              call.add_argument (node.get_canonical_cconstant ());
+-              call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("result")));
+-              call.add_argument (new CCodeConstant ("NULL"));
+-
+-              block.add_statement (new CCodeExpressionStatement (call));
+-
+-              block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("result")));
+-      }
+-
+-      void generate_gobject_property_setter_wrapper (DynamicProperty node, CCodeBlock block) {
+-              var call = new CCodeFunctionCall (new CCodeIdentifier ("g_object_set"));
+-              call.add_argument (new CCodeIdentifier ("obj"));
+-              call.add_argument (node.get_canonical_cconstant ());
+-              call.add_argument (new CCodeIdentifier ("value"));
+-              call.add_argument (new CCodeConstant ("NULL"));
+-
+-              block.add_statement (new CCodeExpressionStatement (call));
+-      }
+-
+-      void create_dbus_property_proxy (DynamicProperty node, CCodeBlock block) {
+-              var prop_proxy_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_new_from_proxy"));
+-              prop_proxy_call.add_argument (new CCodeIdentifier ("obj"));
+-              prop_proxy_call.add_argument (new CCodeConstant ("DBUS_INTERFACE_PROPERTIES"));
+-              prop_proxy_call.add_argument (new CCodeConstant ("NULL"));
+-
+-              var prop_proxy_decl = new CCodeDeclaration ("DBusGProxy*");
+-              prop_proxy_decl.add_declarator (new CCodeVariableDeclarator.with_initializer ("property_proxy", prop_proxy_call));
+-              block.add_statement (prop_proxy_decl);
+-      }
+-
+-      void generate_dbus_property_getter_wrapper (DynamicProperty node, CCodeBlock block) {
+-              create_dbus_property_proxy (node, block);
+-
+-              // initialize GValue
+-              var cvalinit = new CCodeInitializerList ();
+-              cvalinit.append (new CCodeConstant ("0"));
+-
+-              var cval_decl = new CCodeDeclaration ("GValue");
+-              cval_decl.add_declarator (new CCodeVariableDeclarator.with_initializer ("gvalue", cvalinit));
+-              block.add_statement (cval_decl);
+-
+-              var val_ptr = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("gvalue"));
+-
+-              // call Get method on property proxy
+-              var cdecl = new CCodeDeclaration (node.property_type.get_cname ());
+-              cdecl.add_declarator (new CCodeVariableDeclarator ("result"));
+-              block.add_statement (cdecl);
+-
+-              var ccall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_call"));
+-              ccall.add_argument (new CCodeIdentifier ("property_proxy"));
+-              ccall.add_argument (new CCodeConstant ("\"Get\""));
+-              ccall.add_argument (new CCodeConstant ("NULL"));
+-
+-              ccall.add_argument (new CCodeIdentifier ("G_TYPE_STRING"));
+-              var get_iface = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_get_interface"));
+-              get_iface.add_argument (new CCodeIdentifier ("obj"));
+-              ccall.add_argument (get_iface);
+-
+-              ccall.add_argument (new CCodeIdentifier ("G_TYPE_STRING"));
+-              ccall.add_argument (new CCodeConstant ("\"%s\"".printf (Symbol.lower_case_to_camel_case (node.name))));
+-
+-              ccall.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
+-
+-              ccall.add_argument (new CCodeIdentifier ("G_TYPE_VALUE"));
+-              ccall.add_argument (val_ptr);
+-
+-              ccall.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
+-
+-              block.add_statement (new CCodeExpressionStatement (ccall));
+-
+-              // unref property proxy
+-              var prop_proxy_unref = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
+-              prop_proxy_unref.add_argument (new CCodeIdentifier ("property_proxy"));
+-              block.add_statement (new CCodeExpressionStatement (prop_proxy_unref));
+-
+-              // assign value to result variable
+-              var cget_call = new CCodeFunctionCall (new CCodeIdentifier (node.property_type.data_type.get_get_value_function ()));
+-              cget_call.add_argument (val_ptr);
+-              var assign = new CCodeAssignment (new CCodeIdentifier ("result"), cget_call);
+-              block.add_statement (new CCodeExpressionStatement (assign));
+-
+-              // return result
+-              block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("result")));
+-      }
+-
+-      void generate_dbus_property_setter_wrapper (DynamicProperty node, CCodeBlock block) {
+-              create_dbus_property_proxy (node, block);
+-
+-              // initialize GValue
+-              var cvalinit = new CCodeInitializerList ();
+-              cvalinit.append (new CCodeConstant ("0"));
+-
+-              var cval_decl = new CCodeDeclaration ("GValue");
+-              cval_decl.add_declarator (new CCodeVariableDeclarator.with_initializer ("gvalue", cvalinit));
+-              block.add_statement (cval_decl);
+-
+-              var val_ptr = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("gvalue"));
+-
+-              var cinit_call = new CCodeFunctionCall (new CCodeIdentifier ("g_value_init"));
+-              cinit_call.add_argument (val_ptr);
+-              cinit_call.add_argument (new CCodeIdentifier (node.property_type.data_type.get_type_id ()));
+-              block.add_statement (new CCodeExpressionStatement (cinit_call));
+-
+-              var cset_call = new CCodeFunctionCall (new CCodeIdentifier (node.property_type.data_type.get_set_value_function ()));
+-              cset_call.add_argument (val_ptr);
+-              cset_call.add_argument (new CCodeIdentifier ("value"));
+-              block.add_statement (new CCodeExpressionStatement (cset_call));
+-
+-              // call Set method on property proxy
+-              var ccall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_call"));
+-              ccall.add_argument (new CCodeIdentifier ("property_proxy"));
+-              ccall.add_argument (new CCodeConstant ("\"Set\""));
+-              ccall.add_argument (new CCodeConstant ("NULL"));
+-
+-              ccall.add_argument (new CCodeIdentifier ("G_TYPE_STRING"));
+-              var get_iface = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_get_interface"));
+-              get_iface.add_argument (new CCodeIdentifier ("obj"));
+-              ccall.add_argument (get_iface);
+-
+-              ccall.add_argument (new CCodeIdentifier ("G_TYPE_STRING"));
+-              ccall.add_argument (new CCodeConstant ("\"%s\"".printf (Symbol.lower_case_to_camel_case (node.name))));
+-
+-              ccall.add_argument (new CCodeIdentifier ("G_TYPE_VALUE"));
+-              ccall.add_argument (val_ptr);
+-
+-              ccall.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
+-
+-              ccall.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
+-
+-              block.add_statement (new CCodeExpressionStatement (ccall));
+-
+-              // unref property proxy
+-              var prop_proxy_unref = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
+-              prop_proxy_unref.add_argument (new CCodeIdentifier ("property_proxy"));
+-              block.add_statement (new CCodeExpressionStatement (prop_proxy_unref));
+-      }
+-}
+Index: gobject/valaccodedynamicsignalmodule.vala
+===================================================================
+--- gobject/valaccodedynamicsignalmodule.vala  (revision 1971)
++++ gobject/valaccodedynamicsignalmodule.vala  (revision 2004)
+@@ -1,195 +0,0 @@
+-/* valaccodedynamicsignalmodule.vala
+- *
+- * Copyright (C) 2007-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;
+-
+-/**
+- * The link between a dynamic signal and generated code.
+- */
+-public class Vala.CCodeDynamicSignalModule : CCodeDynamicPropertyModule {
+-      public CCodeDynamicSignalModule (CCodeGenerator codegen, CCodeModule? next) {
+-              base (codegen, next);
+-      }
+-
+-      int signal_wrapper_id;
+-
+-      public override string get_dynamic_signal_cname (DynamicSignal node) {
+-              return "dynamic_%s%d_".printf (node.name, signal_wrapper_id++);
+-      }
+-
+-      public override string get_dynamic_signal_connect_wrapper_name (DynamicSignal node) {
+-              var dynamic_signal = (DynamicSignal) node;
+-
+-              string connect_wrapper_name = "_%sconnect".printf (get_dynamic_signal_cname (node));
+-              var func = new CCodeFunction (connect_wrapper_name, "void");
+-              func.add_parameter (new CCodeFormalParameter ("obj", "gpointer"));
+-              func.add_parameter (new CCodeFormalParameter ("signal_name", "const char *"));
+-              func.add_parameter (new CCodeFormalParameter ("handler", "GCallback"));
+-              func.add_parameter (new CCodeFormalParameter ("data", "gpointer"));
+-              var block = new CCodeBlock ();
+-              if (dynamic_signal.dynamic_type.data_type == dbus_object_type) {
+-                      generate_dbus_connect_wrapper (node, block);
+-              } else if (dynamic_signal.dynamic_type.data_type != null
+-                         && dynamic_signal.dynamic_type.data_type.is_subtype_of (gobject_type)) {
+-                      generate_gobject_connect_wrapper (node, block);
+-              } else {
+-                      Report.error (node.source_reference, "dynamic signals are not supported for `%s'".printf (dynamic_signal.dynamic_type.to_string ()));
+-              }
+-
+-              // append to C source file
+-              source_type_member_declaration.append (func.copy ());
+-
+-              func.block = block;
+-              source_type_member_definition.append (func);
+-
+-              return connect_wrapper_name;
+-      }
+-
+-      public override string get_dynamic_signal_disconnect_wrapper_name (DynamicSignal node) {
+-              var dynamic_signal = (DynamicSignal) node;
+-
+-              string disconnect_wrapper_name = "_%sdisconnect".printf (get_dynamic_signal_cname (node));
+-              var func = new CCodeFunction (disconnect_wrapper_name, "void");
+-              func.add_parameter (new CCodeFormalParameter ("obj", "gpointer"));
+-              func.add_parameter (new CCodeFormalParameter ("signal_name", "const char *"));
+-              func.add_parameter (new CCodeFormalParameter ("handler", "GCallback"));
+-              func.add_parameter (new CCodeFormalParameter ("data", "gpointer"));
+-              var block = new CCodeBlock ();
+-              if (dynamic_signal.dynamic_type.data_type == dbus_object_type) {
+-                      generate_dbus_disconnect_wrapper (node, block);
+-              } else {
+-                      Report.error (node.source_reference, "dynamic signals are not supported for `%s'".printf (dynamic_signal.dynamic_type.to_string ()));
+-              }
+-
+-              // append to C source file
+-              source_type_member_declaration.append (func.copy ());
+-
+-              func.block = block;
+-              source_type_member_definition.append (func);
+-
+-              return disconnect_wrapper_name;
+-      }
+-
+-      void generate_gobject_connect_wrapper (DynamicSignal node, CCodeBlock block) {
+-              var dynamic_signal = (DynamicSignal) node;
+-
+-              var m = (Method) dynamic_signal.handler.symbol_reference;
+-
+-              node.accept (codegen);
+-
+-              string connect_func = "g_signal_connect_object";
+-              if (m.binding != MemberBinding.INSTANCE) {
+-                      connect_func = "g_signal_connect";
+-              }
+-
+-              var call = new CCodeFunctionCall (new CCodeIdentifier (connect_func));
+-              call.add_argument (new CCodeIdentifier ("obj"));
+-              call.add_argument (new CCodeIdentifier ("signal_name"));
+-              call.add_argument (new CCodeIdentifier ("handler"));
+-              call.add_argument (new CCodeIdentifier ("data"));
+-
+-              if (m.binding == MemberBinding.INSTANCE) {
+-                      call.add_argument (new CCodeConstant ("0"));
+-              }
+-
+-              block.add_statement (new CCodeExpressionStatement (call));
+-      }
+-
+-      void generate_dbus_connect_wrapper (DynamicSignal node, CCodeBlock block) {
+-              var dynamic_signal = (DynamicSignal) node;
+-
+-              var m = (Method) dynamic_signal.handler.symbol_reference;
+-
+-              node.accept (codegen);
+-
+-              // FIXME should only be done once per marshaller
+-              var register_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_object_register_marshaller"));
+-              head.generate_marshaller (node.get_parameters (), node.return_type, true);
+-              register_call.add_argument (new CCodeIdentifier (head.get_marshaller_function (node.get_parameters (), node.return_type, null, true)));
+-              register_call.add_argument (new CCodeIdentifier ("G_TYPE_NONE"));
+-
+-              var add_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_add_signal"));
+-              add_call.add_argument (new CCodeIdentifier ("obj"));
+-              add_call.add_argument (new CCodeConstant ("\"%s\"".printf (Symbol.lower_case_to_camel_case (node.name))));
+-
+-              bool first = true;
+-              foreach (FormalParameter param in m.get_parameters ()) {
+-                      if (first) {
+-                              // skip sender parameter
+-                              first = false;
+-                              continue;
+-                      }
+-
+-                      var array_type = param.parameter_type as ArrayType;
+-                      if (array_type != null) {
+-                              if (array_type.element_type.data_type == string_type.data_type) {
+-                                      register_call.add_argument (new CCodeIdentifier ("G_TYPE_STRV"));
+-                                      add_call.add_argument (new CCodeIdentifier ("G_TYPE_STRV"));
+-                              } else {
+-                                      if (array_type.element_type.data_type.get_type_id () == null) {
+-                                              Report.error (param.source_reference, "unsupported parameter type for D-Bus signals");
+-                                              return;
+-                                      }
+-
+-                                      var carray_type = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_type_get_collection"));
+-                                      carray_type.add_argument (new CCodeConstant ("\"GArray\""));
+-                                      carray_type.add_argument (new CCodeIdentifier (array_type.element_type.data_type.get_type_id ()));
+-                                      register_call.add_argument (carray_type);
+-                                      add_call.add_argument (carray_type);
+-                              }
+-                      } else {
+-                              if (param.parameter_type.get_type_id () == null) {
+-                                      Report.error (param.source_reference, "unsupported parameter type for D-Bus signals");
+-                                      return;
+-                              }
+-
+-                              register_call.add_argument (new CCodeIdentifier (param.parameter_type.get_type_id ()));
+-                              add_call.add_argument (new CCodeIdentifier (param.parameter_type.get_type_id ()));
+-                      }
+-              }
+-              register_call.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
+-              add_call.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
+-
+-              block.add_statement (new CCodeExpressionStatement (register_call));
+-              block.add_statement (new CCodeExpressionStatement (add_call));
+-
+-              var call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_connect_signal"));
+-              call.add_argument (new CCodeIdentifier ("obj"));
+-              call.add_argument (new CCodeIdentifier ("signal_name"));
+-              call.add_argument (new CCodeIdentifier ("handler"));
+-              call.add_argument (new CCodeIdentifier ("data"));
+-              call.add_argument (new CCodeConstant ("NULL"));
+-              block.add_statement (new CCodeExpressionStatement (call));
+-      }
+-
+-      void generate_dbus_disconnect_wrapper (DynamicSignal node, CCodeBlock block) {
+-              var dynamic_signal = (DynamicSignal) node;
+-
+-              var call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_disconnect_signal"));
+-              call.add_argument (new CCodeIdentifier ("obj"));
+-              call.add_argument (new CCodeIdentifier ("signal_name"));
+-              call.add_argument (new CCodeIdentifier ("handler"));
+-              call.add_argument (new CCodeIdentifier ("data"));
+-              block.add_statement (new CCodeExpressionStatement (call));
+-      }
+-}
+Index: gobject/valagsignalmodule.vala
+===================================================================
+--- gobject/valagsignalmodule.vala     (revision 1971)
++++ gobject/valagsignalmodule.vala     (revision 2004)
+@@ -47,6 +47,17 @@
+                       return ("VOID");
+               } else if (dbus && t.get_type_signature ().has_prefix ("(")) {
+                       return ("BOXED");
++              } else if (t.data_type is Enum) {
++                      var en = (Enum) t.data_type;
++                      if (dbus) {
++                              if (en.is_flags) {
++                                      return ("UINT");
++                              } else {
++                                      return ("INT");
++                              }
++                      } else {
++                              return en.get_marshaller_type_name ();
++                      }
+               } else {
+                       return t.data_type.get_marshaller_type_name ();
+               }
+@@ -266,6 +277,13 @@
+                               get_value_function = "g_value_get_pointer";
+                       } else if (dbus && p.parameter_type.get_type_signature ().has_prefix ("(")) {
+                               get_value_function = "g_value_get_boxed";
++                      } else if (dbus && p.parameter_type.data_type is Enum) {
++                              var en = (Enum) p.parameter_type.data_type;
++                              if (en.is_flags) {
++                                      get_value_function = "g_value_get_uint";
++                              } else {
++                                      get_value_function = "g_value_get_int";
++                              }
+                       } else {
+                               get_value_function = p.parameter_type.data_type.get_get_value_function ();
+                       }
+@@ -306,6 +324,13 @@
+                               set_fc = new CCodeFunctionCall (new CCodeIdentifier ("g_value_take_object"));
+                       } else if (dbus && return_type.get_type_signature ().has_prefix ("(")) {
+                               set_fc = new CCodeFunctionCall (new CCodeIdentifier ("g_value_take_boxed"));
++                      } else if (dbus && return_type.data_type is Enum) {
++                              var en = (Enum) return_type.data_type;
++                              if (en.is_flags) {
++                                      set_fc = new CCodeFunctionCall (new CCodeIdentifier ("g_value_set_uint"));
++                              } else {
++                                      set_fc = new CCodeFunctionCall (new CCodeIdentifier ("g_value_set_int"));
++                              }
+                       } else {
+                               set_fc = new CCodeFunctionCall (new CCodeIdentifier (return_type.data_type.get_set_value_function ()));
+                       }
+@@ -378,5 +403,228 @@
+               return csignew;
+       }
++
++      public override void visit_element_access (ElementAccess expr) {
++              if (expr.container is MemberAccess && expr.container.symbol_reference is Signal) {
++                      // detailed signal emission
++                      var sig = (Signal) expr.symbol_reference;
++                      var ma = (MemberAccess) expr.container;
++
++                      expr.accept_children (codegen);
++
++                      var detail_expr = expr.get_indices ().get (0) as StringLiteral;
++                      string signal_detail = detail_expr.eval ();
++                      
++                      var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_emit_by_name"));
++
++                      // FIXME: use C cast if debugging disabled
++                      var ccast = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT"));
++                      ccast.add_argument ((CCodeExpression) ma.inner.ccodenode);
++                      ccall.add_argument (ccast);
++
++                      ccall.add_argument (sig.get_canonical_cconstant (signal_detail));
++                      
++                      expr.ccodenode = ccall;
++              } else {
++                      base.visit_element_access (expr);
++              }
++      }
++
++      CCodeExpression? emit_signal_assignment (Assignment assignment) {
++              var sig = (Signal) assignment.left.symbol_reference;
++              
++              var m = (Method) assignment.right.symbol_reference;
++
++              string connect_func;
++              bool disconnect = false;
++
++              if (assignment.operator == AssignmentOperator.ADD) {
++                      if (sig is DynamicSignal) {
++                              connect_func = head.get_dynamic_signal_connect_wrapper_name ((DynamicSignal) sig);
++                      } else {
++                              connect_func = "g_signal_connect_object";
++                              if (m.binding != MemberBinding.INSTANCE) {
++                                      connect_func = "g_signal_connect";
++                              }
++                      }
++              } else if (assignment.operator == AssignmentOperator.SUB) {
++                      if (sig is DynamicSignal) {
++                              connect_func = head.get_dynamic_signal_disconnect_wrapper_name ((DynamicSignal) sig);
++                      } else {
++                              connect_func = "g_signal_handlers_disconnect_matched";
++                      }
++                      disconnect = true;
++              } else {
++                      assignment.error = true;
++                      Report.error (assignment.source_reference, "Specified compound assignment type for signals not supported.");
++                      return null;
++              }
++
++              var ccall = new CCodeFunctionCall (new CCodeIdentifier (connect_func));
++
++              string signal_detail = null;
++
++              // first argument: instance of sender
++              MemberAccess ma;
++              if (assignment.left is ElementAccess) {
++                      var ea = (ElementAccess) assignment.left;
++                      ma = (MemberAccess) ea.container;
++                      var detail_expr = ea.get_indices ().get (0) as StringLiteral;
++                      if (detail_expr == null) {
++                              assignment.error = true;
++                              Report.error (detail_expr.source_reference, "internal error: only literal string details supported");
++                              return null;
++                      }
++                      signal_detail = detail_expr.eval ();
++              } else {
++                      ma = (MemberAccess) assignment.left;
++              }
++              if (ma.inner != null) {
++                      ccall.add_argument ((CCodeExpression) get_ccodenode (ma.inner));
++              } else {
++                      ccall.add_argument (new CCodeIdentifier ("self"));
++              }
++
++              if (sig is DynamicSignal) {
++                      // dynamic_signal_connect or dynamic_signal_disconnect
++
++                      // second argument: signal name
++                      ccall.add_argument (new CCodeConstant ("\"%s\"".printf (sig.name)));
++              } else if (!disconnect) {
++                      // g_signal_connect_object or g_signal_connect
++
++                      // second argument: signal name
++                      ccall.add_argument (sig.get_canonical_cconstant (signal_detail));
++              } else {
++                      // g_signal_handlers_disconnect_matched
++
++                      // second argument: mask
++                      if (signal_detail == null) {
++                              ccall.add_argument (new CCodeConstant ("G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA"));
++                      } else {
++                              ccall.add_argument (new CCodeConstant ("G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DETAIL | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA"));
++                      }
++
++                      // get signal id
++                      var ccomma = new CCodeCommaExpression ();
++                      var temp_decl = get_temp_variable (uint_type);
++                      temp_vars.insert (0, temp_decl);
++                      var parse_call = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_parse_name"));
++                      parse_call.add_argument (sig.get_canonical_cconstant (signal_detail));
++                      var decl_type = (TypeSymbol) sig.parent_symbol;
++                      parse_call.add_argument (new CCodeIdentifier (decl_type.get_type_id ()));
++                      parse_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (temp_decl.name)));
++                      if (signal_detail == null) {
++                              parse_call.add_argument (new CCodeConstant ("NULL"));
++                      } else {
++                              var detail_temp_decl = get_temp_variable (gquark_type);
++                              temp_vars.insert (0, detail_temp_decl);
++                              parse_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (detail_temp_decl.name)));
++                      }
++                      parse_call.add_argument (new CCodeConstant ("FALSE"));
++                      ccomma.append_expression (parse_call);
++                      ccomma.append_expression (new CCodeIdentifier (temp_decl.name));
++
++                      // third argument: signal_id
++                      ccall.add_argument (ccomma);
++
++                      // fourth argument: detail
++                      ccall.add_argument (new CCodeConstant ("0"));
++                      // fifth argument: closure
++                      ccall.add_argument (new CCodeConstant ("NULL"));
++              }
++              
++              // third resp. sixth argument: handler
++              ccall.add_argument (new CCodeCastExpression ((CCodeExpression) assignment.right.ccodenode, "GCallback"));
++
++              if (m.binding == MemberBinding.INSTANCE) {
++                      // g_signal_connect_object or g_signal_handlers_disconnect_matched
++                      // or dynamic_signal_connect or dynamic_signal_disconnect
++
++                      // fourth resp. seventh argument: object/user_data
++                      if (assignment.right is MemberAccess) {
++                              var right_ma = (MemberAccess) assignment.right;
++                              if (right_ma.inner != null) {
++                                      ccall.add_argument ((CCodeExpression) right_ma.inner.ccodenode);
++                              } else {
++                                      ccall.add_argument (new CCodeIdentifier ("self"));
++                              }
++                      } else if (assignment.right is LambdaExpression) {
++                              ccall.add_argument (new CCodeIdentifier ("self"));
++                      }
++                      if (!disconnect && !(sig is DynamicSignal)) {
++                              // g_signal_connect_object
++
++                              // fifth argument: connect_flags
++                              ccall.add_argument (new CCodeConstant ("0"));
++                      }
++              } else {
++                      // g_signal_connect or g_signal_handlers_disconnect_matched
++                      // or dynamic_signal_connect or dynamic_signal_disconnect
++
++                      // fourth resp. seventh argument: user_data
++                      ccall.add_argument (new CCodeConstant ("NULL"));
++              }
++              
++              return ccall;
++      }
++
++      public override void visit_assignment (Assignment assignment) {
++              if (assignment.left.symbol_reference is Signal) {
++                      assignment.right.accept (codegen);
++
++                      if (assignment.left.error || assignment.right.error) {
++                              assignment.error = true;
++                              return;
++                      }
++
++                      assignment.ccodenode = emit_signal_assignment (assignment);
++              } else {
++                      base.visit_assignment (assignment);
++              }
++      }
++
++      public override void visit_member_access (MemberAccess expr) {
++              CCodeExpression pub_inst = null;
++      
++              if (expr.inner != null) {
++                      pub_inst = (CCodeExpression) expr.inner.ccodenode;
++              }
++
++              if (expr.symbol_reference is Signal) {
++                      var sig = (Signal) expr.symbol_reference;
++                      var cl = (TypeSymbol) sig.parent_symbol;
++                      
++                      if (expr.inner is BaseAccess && sig.is_virtual) {
++                              var m = sig.get_method_handler ();
++                              var base_class = (Class) m.parent_symbol;
++                              var vcast = new CCodeFunctionCall (new CCodeIdentifier ("%s_CLASS".printf (base_class.get_upper_case_cname (null))));
++                              vcast.add_argument (new CCodeIdentifier ("%s_parent_class".printf (current_class.get_lower_case_cname (null))));
++                              
++                              expr.ccodenode = new CCodeMemberAccess.pointer (vcast, m.name);
++                              return;
++                      }
++
++                      if (sig.has_emitter) {
++                              var ccall = new CCodeFunctionCall (new CCodeIdentifier ("%s_%s".printf (cl.get_lower_case_cname (null), sig.name)));
++
++                              ccall.add_argument (pub_inst);
++                              expr.ccodenode = ccall;
++                      } else {
++                              var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_emit_by_name"));
++
++                              // FIXME: use C cast if debugging disabled
++                              var ccast = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT"));
++                              ccast.add_argument (pub_inst);
++                              ccall.add_argument (ccast);
++
++                              ccall.add_argument (sig.get_canonical_cconstant ());
++                              
++                              expr.ccodenode = ccall;
++                      }
++              } else {
++                      base.visit_member_access (expr);
++              }
++      }
+ }
+Index: gobject/valaccodememberaccessmodule.vala
+===================================================================
+--- gobject/valaccodememberaccessmodule.vala   (revision 1971)
++++ gobject/valaccodememberaccessmodule.vala   (revision 2004)
+@@ -23,12 +23,23 @@
+ using GLib;
+-public class Vala.CCodeMemberAccessModule : CCodeMethodModule {
++public class Vala.CCodeMemberAccessModule : CCodeControlFlowModule {
+       public CCodeMemberAccessModule (CCodeGenerator codegen, CCodeModule? next) {
+               base (codegen, next);
+       }
+-      private void process_cmember (MemberAccess expr, CCodeExpression? pub_inst, DataType? base_type) {
++      public override void visit_member_access (MemberAccess expr) {
++              CCodeExpression pub_inst = null;
++              DataType base_type = null;
++      
++              if (expr.inner != null) {
++                      pub_inst = (CCodeExpression) expr.inner.ccodenode;
++
++                      if (expr.inner.value_type != null) {
++                              base_type = expr.inner.value_type;
++                      }
++              }
++
+               if (expr.symbol_reference is Method) {
+                       var m = (Method) expr.symbol_reference;
+                       
+@@ -259,53 +270,7 @@
+                                       }
+                               }
+                       }
+-              } else if (expr.symbol_reference is Signal) {
+-                      var sig = (Signal) expr.symbol_reference;
+-                      var cl = (TypeSymbol) sig.parent_symbol;
+-                      
+-                      if (expr.inner is BaseAccess && sig.is_virtual) {
+-                              var m = sig.get_method_handler ();
+-                              var base_class = (Class) m.parent_symbol;
+-                              var vcast = new CCodeFunctionCall (new CCodeIdentifier ("%s_CLASS".printf (base_class.get_upper_case_cname (null))));
+-                              vcast.add_argument (new CCodeIdentifier ("%s_parent_class".printf (current_class.get_lower_case_cname (null))));
+-                              
+-                              expr.ccodenode = new CCodeMemberAccess.pointer (vcast, m.name);
+-                              return;
+-                      }
+-
+-                      if (sig.has_emitter) {
+-                              var ccall = new CCodeFunctionCall (new CCodeIdentifier ("%s_%s".printf (cl.get_lower_case_cname (null), sig.name)));
+-
+-                              ccall.add_argument (pub_inst);
+-                              expr.ccodenode = ccall;
+-                      } else {
+-                              var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_emit_by_name"));
+-
+-                              // FIXME: use C cast if debugging disabled
+-                              var ccast = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT"));
+-                              ccast.add_argument (pub_inst);
+-                              ccall.add_argument (ccast);
+-
+-                              ccall.add_argument (sig.get_canonical_cconstant ());
+-                              
+-                              expr.ccodenode = ccall;
+-                      }
+               }
+       }
+-
+-      public override void visit_member_access (MemberAccess expr) {
+-              CCodeExpression pub_inst = null;
+-              DataType base_type = null;
+-      
+-              if (expr.inner != null) {
+-                      pub_inst = (CCodeExpression) expr.inner.ccodenode;
+-
+-                      if (expr.inner.value_type != null) {
+-                              base_type = expr.inner.value_type;
+-                      }
+-              }
+-
+-              process_cmember (expr, pub_inst, base_type);
+-      }
+ }
+Index: gobject/valadbusclientmodule.vala
+===================================================================
+--- gobject/valadbusclientmodule.vala  (revision 1971)
++++ gobject/valadbusclientmodule.vala  (revision 2004)
+@@ -29,6 +29,8 @@
+  * The link between a dynamic method and generated code.
+  */
+ public class Vala.DBusClientModule : GAsyncModule {
++      int dynamic_property_id;
++
+       public DBusClientModule (CCodeGenerator codegen, CCodeModule? next) {
+               base (codegen, next);
+       }
+@@ -433,6 +435,10 @@
+                               block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("result")));
+                       }
+               } else {
++                      if (found_out) {
++                              ccall.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
++                      }
++
+                       block.add_statement (new CCodeExpressionStatement (ccall));
+                       // don't access result when error occured
+@@ -460,6 +466,13 @@
+                       }
+                       carray_type.add_argument (get_dbus_g_type (array_type.element_type));
+                       return carray_type;
++              } else if (data_type.data_type is Enum) {
++                      var en = (Enum) data_type.data_type;
++                      if (en.is_flags) {
++                              return new CCodeIdentifier ("G_TYPE_UINT");
++                      } else {
++                              return new CCodeIdentifier ("G_TYPE_INT");
++                      }
+               } else if (data_type.data_type == null) {
+                       critical ("Internal error during DBus type generation with: %s", data_type.to_string ());
+                       return new CCodeIdentifier ("G_TYPE_NONE");
+@@ -502,4 +515,291 @@
+                       return true;
+               }
+       }
++
++      public override string get_dynamic_property_getter_cname (DynamicProperty prop) {
++              if (prop.dynamic_type.data_type != dbus_object_type) {
++                      return base.get_dynamic_property_getter_cname (prop);
++              }
++
++              string getter_cname = "_dynamic_get_%s%d".printf (prop.name, dynamic_property_id++);
++
++              var func = new CCodeFunction (getter_cname, prop.property_type.get_cname ());
++              func.modifiers |= CCodeModifiers.STATIC | CCodeModifiers.INLINE;
++
++              func.add_parameter (new CCodeFormalParameter ("obj", prop.dynamic_type.get_cname ()));
++
++              var block = new CCodeBlock ();
++              generate_dbus_property_getter_wrapper (prop, block);
++
++              // append to C source file
++              source_type_member_declaration.append (func.copy ());
++
++              func.block = block;
++              source_type_member_definition.append (func);
++
++              return getter_cname;
++      }
++
++      public override string get_dynamic_property_setter_cname (DynamicProperty prop) {
++              if (prop.dynamic_type.data_type != dbus_object_type) {
++                      return base.get_dynamic_property_setter_cname (prop);
++              }
++
++              string setter_cname = "_dynamic_set_%s%d".printf (prop.name, dynamic_property_id++);
++
++              var func = new CCodeFunction (setter_cname, "void");
++              func.modifiers |= CCodeModifiers.STATIC | CCodeModifiers.INLINE;
++
++              func.add_parameter (new CCodeFormalParameter ("obj", prop.dynamic_type.get_cname ()));
++              func.add_parameter (new CCodeFormalParameter ("value", prop.property_type.get_cname ()));
++
++              var block = new CCodeBlock ();
++              generate_dbus_property_setter_wrapper (prop, block);
++
++              // append to C source file
++              source_type_member_declaration.append (func.copy ());
++
++              func.block = block;
++              source_type_member_definition.append (func);
++
++              return setter_cname;
++      }
++
++      void create_dbus_property_proxy (DynamicProperty node, CCodeBlock block) {
++              var prop_proxy_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_new_from_proxy"));
++              prop_proxy_call.add_argument (new CCodeIdentifier ("obj"));
++              prop_proxy_call.add_argument (new CCodeConstant ("DBUS_INTERFACE_PROPERTIES"));
++              prop_proxy_call.add_argument (new CCodeConstant ("NULL"));
++
++              var prop_proxy_decl = new CCodeDeclaration ("DBusGProxy*");
++              prop_proxy_decl.add_declarator (new CCodeVariableDeclarator.with_initializer ("property_proxy", prop_proxy_call));
++              block.add_statement (prop_proxy_decl);
++      }
++
++      void generate_dbus_property_getter_wrapper (DynamicProperty node, CCodeBlock block) {
++              create_dbus_property_proxy (node, block);
++
++              // initialize GValue
++              var cvalinit = new CCodeInitializerList ();
++              cvalinit.append (new CCodeConstant ("0"));
++
++              var cval_decl = new CCodeDeclaration ("GValue");
++              cval_decl.add_declarator (new CCodeVariableDeclarator.with_initializer ("gvalue", cvalinit));
++              block.add_statement (cval_decl);
++
++              var val_ptr = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("gvalue"));
++
++              // call Get method on property proxy
++              var cdecl = new CCodeDeclaration (node.property_type.get_cname ());
++              cdecl.add_declarator (new CCodeVariableDeclarator ("result"));
++              block.add_statement (cdecl);
++
++              var ccall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_call"));
++              ccall.add_argument (new CCodeIdentifier ("property_proxy"));
++              ccall.add_argument (new CCodeConstant ("\"Get\""));
++              ccall.add_argument (new CCodeConstant ("NULL"));
++
++              ccall.add_argument (new CCodeIdentifier ("G_TYPE_STRING"));
++              var get_iface = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_get_interface"));
++              get_iface.add_argument (new CCodeIdentifier ("obj"));
++              ccall.add_argument (get_iface);
++
++              ccall.add_argument (new CCodeIdentifier ("G_TYPE_STRING"));
++              ccall.add_argument (new CCodeConstant ("\"%s\"".printf (Symbol.lower_case_to_camel_case (node.name))));
++
++              ccall.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
++
++              ccall.add_argument (new CCodeIdentifier ("G_TYPE_VALUE"));
++              ccall.add_argument (val_ptr);
++
++              ccall.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
++
++              block.add_statement (new CCodeExpressionStatement (ccall));
++
++              // unref property proxy
++              var prop_proxy_unref = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
++              prop_proxy_unref.add_argument (new CCodeIdentifier ("property_proxy"));
++              block.add_statement (new CCodeExpressionStatement (prop_proxy_unref));
++
++              // assign value to result variable
++              var cget_call = new CCodeFunctionCall (new CCodeIdentifier (node.property_type.data_type.get_get_value_function ()));
++              cget_call.add_argument (val_ptr);
++              var assign = new CCodeAssignment (new CCodeIdentifier ("result"), cget_call);
++              block.add_statement (new CCodeExpressionStatement (assign));
++
++              // return result
++              block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("result")));
++      }
++
++      void generate_dbus_property_setter_wrapper (DynamicProperty node, CCodeBlock block) {
++              create_dbus_property_proxy (node, block);
++
++              // initialize GValue
++              var cvalinit = new CCodeInitializerList ();
++              cvalinit.append (new CCodeConstant ("0"));
++
++              var cval_decl = new CCodeDeclaration ("GValue");
++              cval_decl.add_declarator (new CCodeVariableDeclarator.with_initializer ("gvalue", cvalinit));
++              block.add_statement (cval_decl);
++
++              var val_ptr = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("gvalue"));
++
++              var cinit_call = new CCodeFunctionCall (new CCodeIdentifier ("g_value_init"));
++              cinit_call.add_argument (val_ptr);
++              cinit_call.add_argument (new CCodeIdentifier (node.property_type.data_type.get_type_id ()));
++              block.add_statement (new CCodeExpressionStatement (cinit_call));
++
++              var cset_call = new CCodeFunctionCall (new CCodeIdentifier (node.property_type.data_type.get_set_value_function ()));
++              cset_call.add_argument (val_ptr);
++              cset_call.add_argument (new CCodeIdentifier ("value"));
++              block.add_statement (new CCodeExpressionStatement (cset_call));
++
++              // call Set method on property proxy
++              var ccall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_call"));
++              ccall.add_argument (new CCodeIdentifier ("property_proxy"));
++              ccall.add_argument (new CCodeConstant ("\"Set\""));
++              ccall.add_argument (new CCodeConstant ("NULL"));
++
++              ccall.add_argument (new CCodeIdentifier ("G_TYPE_STRING"));
++              var get_iface = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_get_interface"));
++              get_iface.add_argument (new CCodeIdentifier ("obj"));
++              ccall.add_argument (get_iface);
++
++              ccall.add_argument (new CCodeIdentifier ("G_TYPE_STRING"));
++              ccall.add_argument (new CCodeConstant ("\"%s\"".printf (Symbol.lower_case_to_camel_case (node.name))));
++
++              ccall.add_argument (new CCodeIdentifier ("G_TYPE_VALUE"));
++              ccall.add_argument (val_ptr);
++
++              ccall.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
++
++              ccall.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
++
++              block.add_statement (new CCodeExpressionStatement (ccall));
++
++              // unref property proxy
++              var prop_proxy_unref = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
++              prop_proxy_unref.add_argument (new CCodeIdentifier ("property_proxy"));
++              block.add_statement (new CCodeExpressionStatement (prop_proxy_unref));
++      }
++
++      public override string get_dynamic_signal_connect_wrapper_name (DynamicSignal sig) {
++              if (sig.dynamic_type.data_type != dbus_object_type) {
++                      return base.get_dynamic_signal_connect_wrapper_name (sig);
++              }
++
++              string connect_wrapper_name = "_%sconnect".printf (get_dynamic_signal_cname (sig));
++              var func = new CCodeFunction (connect_wrapper_name, "void");
++              func.add_parameter (new CCodeFormalParameter ("obj", "gpointer"));
++              func.add_parameter (new CCodeFormalParameter ("signal_name", "const char *"));
++              func.add_parameter (new CCodeFormalParameter ("handler", "GCallback"));
++              func.add_parameter (new CCodeFormalParameter ("data", "gpointer"));
++              var block = new CCodeBlock ();
++              generate_dbus_connect_wrapper (sig, block);
++
++              // append to C source file
++              source_type_member_declaration.append (func.copy ());
++
++              func.block = block;
++              source_type_member_definition.append (func);
++
++              return connect_wrapper_name;
++      }
++
++      public override string get_dynamic_signal_disconnect_wrapper_name (DynamicSignal sig) {
++              if (sig.dynamic_type.data_type != dbus_object_type) {
++                      return base.get_dynamic_signal_disconnect_wrapper_name (sig);
++              }
++
++              string disconnect_wrapper_name = "_%sdisconnect".printf (get_dynamic_signal_cname (sig));
++              var func = new CCodeFunction (disconnect_wrapper_name, "void");
++              func.add_parameter (new CCodeFormalParameter ("obj", "gpointer"));
++              func.add_parameter (new CCodeFormalParameter ("signal_name", "const char *"));
++              func.add_parameter (new CCodeFormalParameter ("handler", "GCallback"));
++              func.add_parameter (new CCodeFormalParameter ("data", "gpointer"));
++              var block = new CCodeBlock ();
++              generate_dbus_disconnect_wrapper (sig, block);
++
++              // append to C source file
++              source_type_member_declaration.append (func.copy ());
++
++              func.block = block;
++              source_type_member_definition.append (func);
++
++              return disconnect_wrapper_name;
++      }
++
++      void generate_dbus_connect_wrapper (DynamicSignal sig, CCodeBlock block) {
++              var m = (Method) sig.handler.symbol_reference;
++
++              sig.accept (codegen);
++
++              // FIXME should only be done once per marshaller
++              var register_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_object_register_marshaller"));
++              head.generate_marshaller (sig.get_parameters (), sig.return_type, true);
++              register_call.add_argument (new CCodeIdentifier (head.get_marshaller_function (sig.get_parameters (), sig.return_type, null, true)));
++              register_call.add_argument (new CCodeIdentifier ("G_TYPE_NONE"));
++
++              var add_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_add_signal"));
++              add_call.add_argument (new CCodeIdentifier ("obj"));
++              add_call.add_argument (new CCodeConstant ("\"%s\"".printf (Symbol.lower_case_to_camel_case (sig.name))));
++
++              bool first = true;
++              foreach (FormalParameter param in m.get_parameters ()) {
++                      if (first) {
++                              // skip sender parameter
++                              first = false;
++                              continue;
++                      }
++
++                      var array_type = param.parameter_type as ArrayType;
++                      if (array_type != null) {
++                              if (array_type.element_type.data_type == string_type.data_type) {
++                                      register_call.add_argument (new CCodeIdentifier ("G_TYPE_STRV"));
++                                      add_call.add_argument (new CCodeIdentifier ("G_TYPE_STRV"));
++                              } else {
++                                      if (array_type.element_type.data_type.get_type_id () == null) {
++                                              Report.error (param.source_reference, "unsupported parameter type for D-Bus signals");
++                                              return;
++                                      }
++
++                                      var carray_type = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_type_get_collection"));
++                                      carray_type.add_argument (new CCodeConstant ("\"GArray\""));
++                                      carray_type.add_argument (new CCodeIdentifier (array_type.element_type.data_type.get_type_id ()));
++                                      register_call.add_argument (carray_type);
++                                      add_call.add_argument (carray_type);
++                              }
++                      } else {
++                              if (param.parameter_type.get_type_id () == null) {
++                                      Report.error (param.source_reference, "unsupported parameter type for D-Bus signals");
++                                      return;
++                              }
++
++                              register_call.add_argument (new CCodeIdentifier (param.parameter_type.get_type_id ()));
++                              add_call.add_argument (new CCodeIdentifier (param.parameter_type.get_type_id ()));
++                      }
++              }
++              register_call.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
++              add_call.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
++
++              block.add_statement (new CCodeExpressionStatement (register_call));
++              block.add_statement (new CCodeExpressionStatement (add_call));
++
++              var call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_connect_signal"));
++              call.add_argument (new CCodeIdentifier ("obj"));
++              call.add_argument (new CCodeIdentifier ("signal_name"));
++              call.add_argument (new CCodeIdentifier ("handler"));
++              call.add_argument (new CCodeIdentifier ("data"));
++              call.add_argument (new CCodeConstant ("NULL"));
++              block.add_statement (new CCodeExpressionStatement (call));
++      }
++
++      void generate_dbus_disconnect_wrapper (DynamicSignal sig, CCodeBlock block) {
++              var call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_disconnect_signal"));
++              call.add_argument (new CCodeIdentifier ("obj"));
++              call.add_argument (new CCodeIdentifier ("signal_name"));
++              call.add_argument (new CCodeIdentifier ("handler"));
++              call.add_argument (new CCodeIdentifier ("data"));
++              block.add_statement (new CCodeExpressionStatement (call));
++      }
+ }
+Index: gobject/valagerrormodule.vala
+===================================================================
+--- gobject/valagerrormodule.vala      (revision 1971)
++++ gobject/valagerrormodule.vala      (revision 2004)
+@@ -23,7 +23,7 @@
+ using GLib;
+ using Gee;
+-public class Vala.GErrorModule : CCodeDynamicSignalModule {
++public class Vala.GErrorModule : CCodeDelegateModule {
+       private int current_try_id = 0;
+       private int next_try_id = 0;
+Index: gobject/valaccodeassignmentmodule.vala
+===================================================================
+--- gobject/valaccodeassignmentmodule.vala     (revision 1971)
++++ gobject/valaccodeassignmentmodule.vala     (revision 2004)
+@@ -89,145 +89,6 @@
+               }
+       }
+-      CCodeExpression? emit_signal_assignment (Assignment assignment) {
+-              var sig = (Signal) assignment.left.symbol_reference;
+-              
+-              var m = (Method) assignment.right.symbol_reference;
+-
+-              string connect_func;
+-              bool disconnect = false;
+-
+-              if (assignment.operator == AssignmentOperator.ADD) {
+-                      if (sig is DynamicSignal) {
+-                              connect_func = head.get_dynamic_signal_connect_wrapper_name ((DynamicSignal) sig);
+-                      } else {
+-                              connect_func = "g_signal_connect_object";
+-                              if (m.binding != MemberBinding.INSTANCE) {
+-                                      connect_func = "g_signal_connect";
+-                              }
+-                      }
+-              } else if (assignment.operator == AssignmentOperator.SUB) {
+-                      if (sig is DynamicSignal) {
+-                              connect_func = head.get_dynamic_signal_disconnect_wrapper_name ((DynamicSignal) sig);
+-                      } else {
+-                              connect_func = "g_signal_handlers_disconnect_matched";
+-                      }
+-                      disconnect = true;
+-              } else {
+-                      assignment.error = true;
+-                      Report.error (assignment.source_reference, "Specified compound assignment type for signals not supported.");
+-                      return null;
+-              }
+-
+-              var ccall = new CCodeFunctionCall (new CCodeIdentifier (connect_func));
+-
+-              string signal_detail = null;
+-
+-              // first argument: instance of sender
+-              MemberAccess ma;
+-              if (assignment.left is ElementAccess) {
+-                      var ea = (ElementAccess) assignment.left;
+-                      ma = (MemberAccess) ea.container;
+-                      var detail_expr = ea.get_indices ().get (0) as StringLiteral;
+-                      if (detail_expr == null) {
+-                              assignment.error = true;
+-                              Report.error (detail_expr.source_reference, "internal error: only literal string details supported");
+-                              return null;
+-                      }
+-                      signal_detail = detail_expr.eval ();
+-              } else {
+-                      ma = (MemberAccess) assignment.left;
+-              }
+-              if (ma.inner != null) {
+-                      ccall.add_argument ((CCodeExpression) get_ccodenode (ma.inner));
+-              } else {
+-                      ccall.add_argument (new CCodeIdentifier ("self"));
+-              }
+-
+-              if (sig is DynamicSignal) {
+-                      // dynamic_signal_connect or dynamic_signal_disconnect
+-
+-                      // second argument: signal name
+-                      ccall.add_argument (new CCodeConstant ("\"%s\"".printf (sig.name)));
+-              } else if (!disconnect) {
+-                      // g_signal_connect_object or g_signal_connect
+-
+-                      // second argument: signal name
+-                      ccall.add_argument (sig.get_canonical_cconstant (signal_detail));
+-              } else {
+-                      // g_signal_handlers_disconnect_matched
+-
+-                      // second argument: mask
+-                      if (signal_detail == null) {
+-                              ccall.add_argument (new CCodeConstant ("G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA"));
+-                      } else {
+-                              ccall.add_argument (new CCodeConstant ("G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DETAIL | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA"));
+-                      }
+-
+-                      // get signal id
+-                      var ccomma = new CCodeCommaExpression ();
+-                      var temp_decl = get_temp_variable (uint_type);
+-                      temp_vars.insert (0, temp_decl);
+-                      var parse_call = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_parse_name"));
+-                      parse_call.add_argument (sig.get_canonical_cconstant (signal_detail));
+-                      var decl_type = (TypeSymbol) sig.parent_symbol;
+-                      parse_call.add_argument (new CCodeIdentifier (decl_type.get_type_id ()));
+-                      parse_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (temp_decl.name)));
+-                      if (signal_detail == null) {
+-                              parse_call.add_argument (new CCodeConstant ("NULL"));
+-                      } else {
+-                              var detail_temp_decl = get_temp_variable (gquark_type);
+-                              temp_vars.insert (0, detail_temp_decl);
+-                              parse_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (detail_temp_decl.name)));
+-                      }
+-                      parse_call.add_argument (new CCodeConstant ("FALSE"));
+-                      ccomma.append_expression (parse_call);
+-                      ccomma.append_expression (new CCodeIdentifier (temp_decl.name));
+-
+-                      // third argument: signal_id
+-                      ccall.add_argument (ccomma);
+-
+-                      // fourth argument: detail
+-                      ccall.add_argument (new CCodeConstant ("0"));
+-                      // fifth argument: closure
+-                      ccall.add_argument (new CCodeConstant ("NULL"));
+-              }
+-              
+-              // third resp. sixth argument: handler
+-              ccall.add_argument (new CCodeCastExpression ((CCodeExpression) assignment.right.ccodenode, "GCallback"));
+-
+-              if (m.binding == MemberBinding.INSTANCE) {
+-                      // g_signal_connect_object or g_signal_handlers_disconnect_matched
+-                      // or dynamic_signal_connect or dynamic_signal_disconnect
+-
+-                      // fourth resp. seventh argument: object/user_data
+-                      if (assignment.right is MemberAccess) {
+-                              var right_ma = (MemberAccess) assignment.right;
+-                              if (right_ma.inner != null) {
+-                                      ccall.add_argument ((CCodeExpression) right_ma.inner.ccodenode);
+-                              } else {
+-                                      ccall.add_argument (new CCodeIdentifier ("self"));
+-                              }
+-                      } else if (assignment.right is LambdaExpression) {
+-                              ccall.add_argument (new CCodeIdentifier ("self"));
+-                      }
+-                      if (!disconnect && !(sig is DynamicSignal)) {
+-                              // g_signal_connect_object
+-
+-                              // fifth argument: connect_flags
+-                              ccall.add_argument (new CCodeConstant ("0"));
+-                      }
+-              } else {
+-                      // g_signal_connect or g_signal_handlers_disconnect_matched
+-                      // or dynamic_signal_connect or dynamic_signal_disconnect
+-
+-                      // fourth resp. seventh argument: user_data
+-                      ccall.add_argument (new CCodeConstant ("NULL"));
+-              }
+-              
+-              return ccall;
+-      }
+-
+       private CCodeExpression? emit_non_array_element_access (Assignment assignment) {
+               // custom element access
+               CCodeExpression rhs = (CCodeExpression) assignment.right.ccodenode;
+@@ -373,8 +234,6 @@
+               if (assignment.left.symbol_reference is Property) {
+                       assignment.ccodenode = emit_property_assignment (assignment);
+-              } else if (assignment.left.symbol_reference is Signal) {
+-                      assignment.ccodenode = emit_signal_assignment (assignment);
+               } else if (assignment.left is ElementAccess
+                          && !(((ElementAccess) assignment.left).container.value_type is ArrayType)
+                          && !(((ElementAccess) assignment.left).container.value_type is PointerType)) {
+Index: gobject/valaccodecontrolflowmodule.vala
+===================================================================
+--- gobject/valaccodecontrolflowmodule.vala    (revision 0)
++++ gobject/valaccodecontrolflowmodule.vala    (revision 2004)
+@@ -0,0 +1,572 @@
++/* valaccodecontrolflowmodule.vala
++ *
++ * Copyright (C) 2006-2008  Jürg Billeter, Raffaele Sandrini
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Lesser General Public
++ * License as published by the Free Software Foundation; either
++ * version 2.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>
++ *    Raffaele Sandrini <raffaele@sandrini.ch>
++ */
++
++using GLib;
++using Gee;
++
++public class Vala.CCodeControlFlowModule : CCodeMethodModule {
++      public CCodeControlFlowModule (CCodeGenerator codegen, CCodeModule? next) {
++              base (codegen, next);
++      }
++
++      public override void visit_if_statement (IfStatement stmt) {
++              stmt.accept_children (codegen);
++
++              if (stmt.false_statement != null) {
++                      stmt.ccodenode = new CCodeIfStatement ((CCodeExpression) stmt.condition.ccodenode, (CCodeStatement) stmt.true_statement.ccodenode, (CCodeStatement) stmt.false_statement.ccodenode);
++              } else {
++                      stmt.ccodenode = new CCodeIfStatement ((CCodeExpression) stmt.condition.ccodenode, (CCodeStatement) stmt.true_statement.ccodenode);
++              }
++              
++              create_temp_decl (stmt, stmt.condition.temp_vars);
++      }
++
++      void visit_string_switch_statement (SwitchStatement stmt) {
++              // we need a temporary variable to save the property value
++              var temp_var = get_temp_variable (stmt.expression.value_type, true, stmt);
++              stmt.expression.temp_vars.insert (0, temp_var);
++
++              var ctemp = new CCodeIdentifier (temp_var.name);
++              var cinit = new CCodeAssignment (ctemp, (CCodeExpression) stmt.expression.ccodenode);
++              var czero = new CCodeConstant ("0");
++
++              var cswitchblock = new CCodeFragment ();
++              stmt.ccodenode = cswitchblock;
++
++              var cisnull = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeConstant ("NULL"), ctemp);
++              var cquark = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_string"));
++              cquark.add_argument (ctemp);
++
++              var ccond = new CCodeConditionalExpression (cisnull, new CCodeConstant ("0"), cquark);
++
++              temp_var = get_temp_variable (gquark_type);
++              stmt.expression.temp_vars.insert (0, temp_var);
++
++              int label_count = 0;
++
++              foreach (SwitchSection section in stmt.get_sections ()) {
++                      if (section.has_default_label ()) {
++                              continue;
++                      }
++
++                      foreach (SwitchLabel label in section.get_labels ()) {
++                              var cexpr = (CCodeExpression) label.expression.ccodenode;
++
++                              if (is_constant_ccode_expression (cexpr)) {
++                                      var cname = "%s_label%d".printf (temp_var.name, label_count++);
++                                      var cdecl = new CCodeDeclaration (gquark_type.get_cname ());
++
++                                      cdecl.modifiers = CCodeModifiers.STATIC;
++                                      cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer (cname, czero));
++
++                                      cswitchblock.append (cdecl);
++                              }
++                      }
++              }
++
++              cswitchblock.append (new CCodeExpressionStatement (cinit));
++
++              ctemp = new CCodeIdentifier (temp_var.name);
++              cinit = new CCodeAssignment (ctemp, ccond);
++
++              cswitchblock.append (new CCodeExpressionStatement (cinit));
++              create_temp_decl (stmt, stmt.expression.temp_vars);
++
++              Gee.List<Statement> default_statements = null;
++              label_count = 0;
++
++              // generate nested if statements                
++              CCodeStatement ctopstmt = null;
++              CCodeIfStatement coldif = null;
++
++              foreach (SwitchSection section in stmt.get_sections ()) {
++                      if (section.has_default_label ()) {
++                              default_statements = section.get_statements ();
++                              continue;
++                      }
++
++                      CCodeBinaryExpression cor = null;
++                      foreach (SwitchLabel label in section.get_labels ()) {
++                              var cexpr = (CCodeExpression) label.expression.ccodenode;
++
++                              if (is_constant_ccode_expression (cexpr)) {
++                                      var cname = new CCodeIdentifier ("%s_label%d".printf (temp_var.name, label_count++));
++                                      var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, czero, cname);
++                                      var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_static_string"));
++                                      var cinit = new CCodeParenthesizedExpression (new CCodeAssignment (cname, ccall));
++
++                                      ccall.add_argument (cexpr);
++
++                                      cexpr = new CCodeConditionalExpression (ccond, cname, cinit);
++                              } else {
++                                      var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_string"));
++                                      ccall.add_argument (cexpr);
++                                      cexpr = ccall;
++                              }
++
++                              var ccmp = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ctemp, cexpr);
++
++                              if (cor == null) {
++                                      cor = ccmp;
++                              } else {
++                                      cor = new CCodeBinaryExpression (CCodeBinaryOperator.OR, cor, ccmp);
++                              }
++                      }
++
++                      var cblock = new CCodeBlock ();
++                      foreach (CodeNode body_stmt in section.get_statements ()) {
++                              if (body_stmt.ccodenode is CCodeFragment) {
++                                      foreach (CCodeNode cstmt in ((CCodeFragment) body_stmt.ccodenode).get_children ()) {
++                                              cblock.add_statement (cstmt);
++                                      }
++                              } else {
++                                      cblock.add_statement (body_stmt.ccodenode);
++                              }
++                      }
++
++                      var cdo = new CCodeDoStatement (cblock, new CCodeConstant ("0"));
++                      var cif = new CCodeIfStatement (cor, cdo);
++
++                      if (coldif != null) {
++                              coldif.false_statement = cif;
++                      } else {
++                              ctopstmt = cif;
++                      }
++
++                      coldif = cif;
++              }
++      
++              if (default_statements != null) {
++                      var cblock = new CCodeBlock ();
++                      foreach (CodeNode body_stmt in default_statements) {
++                              cblock.add_statement (body_stmt.ccodenode);
++                      }
++              
++                      var cdo = new CCodeDoStatement (cblock, new CCodeConstant ("0"));
++
++                      if (coldif == null) {
++                              // there is only one section and that section
++                              // contains a default label
++                              ctopstmt = cdo;
++                      } else {
++                              coldif.false_statement = cdo;
++                      }
++              }
++      
++              cswitchblock.append (ctopstmt);
++      }
++
++      public override void visit_switch_statement (SwitchStatement stmt) {
++              if (stmt.expression.value_type.compatible (string_type)) {
++                      visit_string_switch_statement (stmt);
++                      return;
++              }
++
++              var cswitch = new CCodeSwitchStatement ((CCodeExpression) stmt.expression.ccodenode);
++              stmt.ccodenode = cswitch;
++
++              foreach (SwitchSection section in stmt.get_sections ()) {
++                      if (section.has_default_label ()) {
++                              cswitch.add_statement (new CCodeLabel ("default"));
++                              var cdefaultblock = new CCodeBlock ();
++                              cswitch.add_statement (cdefaultblock);
++                              foreach (CodeNode default_stmt in section.get_statements ()) {
++                                      cdefaultblock.add_statement (default_stmt.ccodenode);
++                              }
++                              continue;
++                      }
++
++                      foreach (SwitchLabel label in section.get_labels ()) {
++                              cswitch.add_statement (new CCodeCaseStatement ((CCodeExpression) label.expression.ccodenode));
++                      }
++
++                      var cblock = new CCodeBlock ();
++                      cswitch.add_statement (cblock);
++                      foreach (CodeNode body_stmt in section.get_statements ()) {
++                              cblock.add_statement (body_stmt.ccodenode);
++                      }
++              }
++      }
++
++      public override void visit_switch_section (SwitchSection section) {
++              visit_block (section);
++      }
++
++      public override void visit_while_statement (WhileStatement stmt) {
++              stmt.accept_children (codegen);
++
++              stmt.ccodenode = new CCodeWhileStatement ((CCodeExpression) stmt.condition.ccodenode, (CCodeStatement) stmt.body.ccodenode);
++              
++              create_temp_decl (stmt, stmt.condition.temp_vars);
++      }
++
++      public override void visit_do_statement (DoStatement stmt) {
++              stmt.accept_children (codegen);
++
++              stmt.ccodenode = new CCodeDoStatement ((CCodeStatement) stmt.body.ccodenode, (CCodeExpression) stmt.condition.ccodenode);
++              
++              create_temp_decl (stmt, stmt.condition.temp_vars);
++      }
++
++      public override void visit_for_statement (ForStatement stmt) {
++              stmt.accept_children (codegen);
++
++              CCodeExpression ccondition = null;
++              if (stmt.condition != null) {
++                      ccondition = (CCodeExpression) stmt.condition.ccodenode;
++              }
++
++              var cfor = new CCodeForStatement (ccondition, (CCodeStatement) stmt.body.ccodenode);
++              stmt.ccodenode = cfor;
++              
++              foreach (Expression init_expr in stmt.get_initializer ()) {
++                      cfor.add_initializer ((CCodeExpression) init_expr.ccodenode);
++                      create_temp_decl (stmt, init_expr.temp_vars);
++              }
++              
++              foreach (Expression it_expr in stmt.get_iterator ()) {
++                      cfor.add_iterator ((CCodeExpression) it_expr.ccodenode);
++                      create_temp_decl (stmt, it_expr.temp_vars);
++              }
++
++              if (stmt.condition != null) {
++                      create_temp_decl (stmt, stmt.condition.temp_vars);
++              }
++      }
++
++      public override void visit_foreach_statement (ForeachStatement stmt) {
++              stmt.element_variable.active = true;
++              stmt.collection_variable.active = true;
++              if (stmt.iterator_variable != null) {
++                      stmt.iterator_variable.active = true;
++              }
++
++              visit_block (stmt);
++
++              var cblock = new CCodeBlock ();
++              // sets #line
++              stmt.ccodenode = cblock;
++
++              var cfrag = new CCodeFragment ();
++              append_temp_decl (cfrag, stmt.collection.temp_vars);
++              cblock.add_statement (cfrag);
++              
++              var collection_backup = stmt.collection_variable;
++              var collection_type = collection_backup.variable_type.copy ();
++              var ccoldecl = new CCodeDeclaration (collection_type.get_cname ());
++              var ccolvardecl = new CCodeVariableDeclarator.with_initializer (collection_backup.name, (CCodeExpression) stmt.collection.ccodenode);
++              ccolvardecl.line = cblock.line;
++              ccoldecl.add_declarator (ccolvardecl);
++              cblock.add_statement (ccoldecl);
++              
++              if (stmt.tree_can_fail && stmt.collection.tree_can_fail) {
++                      // exception handling
++                      var cfrag = new CCodeFragment ();
++                      head.add_simple_check (stmt.collection, cfrag);
++                      cblock.add_statement (cfrag);
++              }
++
++              if (stmt.collection.value_type is ArrayType) {
++                      var array_type = (ArrayType) stmt.collection.value_type;
++                      
++                      var array_len = head.get_array_length_cexpression (stmt.collection);
++
++                      // store array length for use by _vala_array_free
++                      var clendecl = new CCodeDeclaration ("int");
++                      clendecl.add_declarator (new CCodeVariableDeclarator.with_initializer (head.get_array_length_cname (collection_backup.name, 1), array_len));
++                      cblock.add_statement (clendecl);
++
++                      if (array_len is CCodeConstant) {
++                              // the array has no length parameter i.e. it is NULL-terminated array
++
++                              var it_name = "%s_it".printf (stmt.variable_name);
++                      
++                              var citdecl = new CCodeDeclaration (collection_type.get_cname ());
++                              citdecl.add_declarator (new CCodeVariableDeclarator (it_name));
++                              cblock.add_statement (citdecl);
++                              
++                              var cbody = new CCodeBlock ();
++
++                              CCodeExpression element_expr = new CCodeIdentifier ("*%s".printf (it_name));
++
++                              var element_type = array_type.element_type.copy ();
++                              element_type.value_owned = false;
++                              element_expr = transform_expression (element_expr, element_type, stmt.type_reference);
++
++                              var cfrag = new CCodeFragment ();
++                              append_temp_decl (cfrag, temp_vars);
++                              cbody.add_statement (cfrag);
++                              temp_vars.clear ();
++
++                              var cdecl = new CCodeDeclaration (stmt.type_reference.get_cname ());
++                              cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer (stmt.variable_name, element_expr));
++                              cbody.add_statement (cdecl);
++
++                              // add array length variable for stacked arrays
++                              if (stmt.type_reference is ArrayType) {
++                                      var inner_array_type = (ArrayType) stmt.type_reference;
++                                      for (int dim = 1; dim <= inner_array_type.rank; dim++) {
++                                              cdecl = new CCodeDeclaration ("int");
++                                              cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer (head.get_array_length_cname (stmt.variable_name, dim), new CCodeConstant ("-1")));
++                                              cbody.add_statement (cdecl);
++                                      }
++                              }
++
++                              cbody.add_statement (stmt.body.ccodenode);
++                              
++                              var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier ("*%s".printf (it_name)), new CCodeConstant ("NULL"));
++                              
++                              var cfor = new CCodeForStatement (ccond, cbody);
++
++                              cfor.add_initializer (new CCodeAssignment (new CCodeIdentifier (it_name), new CCodeIdentifier (collection_backup.name)));
++              
++                              cfor.add_iterator (new CCodeAssignment (new CCodeIdentifier (it_name), new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, new CCodeIdentifier (it_name), new CCodeConstant ("1"))));
++                              cblock.add_statement (cfor);
++                      } else {
++                              // the array has a length parameter
++
++                              var it_name = (stmt.variable_name + "_it");
++                      
++                              var citdecl = new CCodeDeclaration ("int");
++                              citdecl.add_declarator (new CCodeVariableDeclarator (it_name));
++                              cblock.add_statement (citdecl);
++                              
++                              var cbody = new CCodeBlock ();
++
++                              CCodeExpression element_expr = new CCodeElementAccess (new CCodeIdentifier (collection_backup.name), new CCodeIdentifier (it_name));
++
++                              var element_type = array_type.element_type.copy ();
++                              element_type.value_owned = false;
++                              element_expr = transform_expression (element_expr, element_type, stmt.type_reference);
++
++                              var cfrag = new CCodeFragment ();
++                              append_temp_decl (cfrag, temp_vars);
++                              cbody.add_statement (cfrag);
++                              temp_vars.clear ();
++
++                              var cdecl = new CCodeDeclaration (stmt.type_reference.get_cname ());
++                              cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer (stmt.variable_name, element_expr));
++                              cbody.add_statement (cdecl);
++
++                              // add array length variable for stacked arrays
++                              if (stmt.type_reference is ArrayType) {
++                                      var inner_array_type = (ArrayType) stmt.type_reference;
++                                      for (int dim = 1; dim <= inner_array_type.rank; dim++) {
++                                              cdecl = new CCodeDeclaration ("int");
++                                              cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer (head.get_array_length_cname (stmt.variable_name, dim), new CCodeConstant ("-1")));
++                                              cbody.add_statement (cdecl);
++                                      }
++                              }
++
++                              cbody.add_statement (stmt.body.ccodenode);
++                              
++                              var ccond_ind1 = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, array_len, new CCodeConstant ("-1"));
++                              var ccond_ind2 = new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, new CCodeIdentifier (it_name), array_len);
++                              var ccond_ind = new CCodeBinaryExpression (CCodeBinaryOperator.AND, ccond_ind1, ccond_ind2);
++                              
++                              /* only check for null if the containers elements are of reference-type */
++                              CCodeBinaryExpression ccond;
++                              if (array_type.element_type.is_reference_type_or_type_parameter ()) {
++                                      var ccond_term1 = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, array_len, new CCodeConstant ("-1"));
++                                      var ccond_term2 = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeElementAccess (new CCodeIdentifier (collection_backup.name), new CCodeIdentifier (it_name)), new CCodeConstant ("NULL"));
++                                      var ccond_term = new CCodeBinaryExpression (CCodeBinaryOperator.AND, ccond_term1, ccond_term2);
++
++                                      ccond = new CCodeBinaryExpression (CCodeBinaryOperator.OR, new CCodeParenthesizedExpression (ccond_ind), new CCodeParenthesizedExpression (ccond_term));
++                              } else {
++                                      /* assert when trying to iterate over value-type arrays of unknown length */
++                                      var cassert = new CCodeFunctionCall (new CCodeIdentifier ("g_assert"));
++                                      cassert.add_argument (ccond_ind1);
++                                      cblock.add_statement (new CCodeExpressionStatement (cassert));
++
++                                      ccond = ccond_ind2;
++                              }
++                              
++                              var cfor = new CCodeForStatement (ccond, cbody);
++                              cfor.add_initializer (new CCodeAssignment (new CCodeIdentifier (it_name), new CCodeConstant ("0")));
++                              cfor.add_iterator (new CCodeAssignment (new CCodeIdentifier (it_name), new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, new CCodeIdentifier (it_name), new CCodeConstant ("1"))));
++                              cblock.add_statement (cfor);
++                      }
++              } else if (stmt.collection.value_type.compatible (new ObjectType (glist_type)) || stmt.collection.value_type.compatible (new ObjectType (gslist_type))) {
++                      // iterating over a GList or GSList
++
++                      var it_name = "%s_it".printf (stmt.variable_name);
++              
++                      var citdecl = new CCodeDeclaration (collection_type.get_cname ());
++                      var citvardecl = new CCodeVariableDeclarator (it_name);
++                      citvardecl.line = cblock.line;
++                      citdecl.add_declarator (citvardecl);
++                      cblock.add_statement (citdecl);
++                      
++                      var cbody = new CCodeBlock ();
++
++                      CCodeExpression element_expr = new CCodeMemberAccess.pointer (new CCodeIdentifier (it_name), "data");
++
++                      if (collection_type.get_type_arguments ().size != 1) {
++                              Report.error (stmt.source_reference, "internal error: missing generic type argument");
++                              stmt.error = true;
++                              return;
++                      }
++
++                      var element_data_type = collection_type.get_type_arguments ().get (0).copy ();
++                      element_data_type.value_owned = false;
++                      element_data_type.is_type_argument = true;
++                      element_expr = transform_expression (element_expr, element_data_type, stmt.type_reference);
++
++                      var cfrag = new CCodeFragment ();
++                      append_temp_decl (cfrag, temp_vars);
++                      cbody.add_statement (cfrag);
++                      temp_vars.clear ();
++
++                      var cdecl = new CCodeDeclaration (stmt.type_reference.get_cname ());
++                      var cvardecl = new CCodeVariableDeclarator.with_initializer (stmt.variable_name, element_expr);
++                      cvardecl.line = cblock.line;
++                      cdecl.add_declarator (cvardecl);
++                      cbody.add_statement (cdecl);
++                      
++                      cbody.add_statement (stmt.body.ccodenode);
++                      
++                      var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier (it_name), new CCodeConstant ("NULL"));
++                      
++                      var cfor = new CCodeForStatement (ccond, cbody);
++                      
++                      cfor.add_initializer (new CCodeAssignment (new CCodeIdentifier (it_name), new CCodeIdentifier (collection_backup.name)));
++
++                      cfor.add_iterator (new CCodeAssignment (new CCodeIdentifier (it_name), new CCodeMemberAccess.pointer (new CCodeIdentifier (it_name), "next")));
++                      cblock.add_statement (cfor);
++              } else if (list_type != null && stmt.collection.value_type.compatible (new ObjectType (list_type))) {
++                      // iterating over a Gee.List, use integer to avoid the cost of an iterator object
++
++                      var it_name = "%s_it".printf (stmt.variable_name);
++
++                      var citdecl = new CCodeDeclaration ("int");
++                      citdecl.add_declarator (new CCodeVariableDeclarator (it_name));
++                      cblock.add_statement (citdecl);
++                      
++                      var cbody = new CCodeBlock ();
++
++                      var get_method = (Method) list_type.scope.lookup ("get");
++                      var get_ccall = new CCodeFunctionCall (new CCodeIdentifier (get_method.get_cname ()));
++                      get_ccall.add_argument (new InstanceCast (new CCodeIdentifier (collection_backup.name), list_type));
++                      get_ccall.add_argument (new CCodeIdentifier (it_name));
++                      CCodeExpression element_expr = get_ccall;
++
++                      var element_type = SemanticAnalyzer.get_actual_type (stmt.collection.value_type, get_method, get_method.return_type, stmt);
++
++                      element_expr = transform_expression (element_expr, element_type, stmt.type_reference);
++
++                      var cfrag = new CCodeFragment ();
++                      append_temp_decl (cfrag, temp_vars);
++                      cbody.add_statement (cfrag);
++                      temp_vars.clear ();
++
++                      var cdecl = new CCodeDeclaration (stmt.type_reference.get_cname ());
++                      var cvardecl = new CCodeVariableDeclarator.with_initializer (stmt.variable_name, element_expr);
++                      cvardecl.line = cblock.line;
++                      cdecl.add_declarator (cvardecl);
++                      cbody.add_statement (cdecl);
++
++                      cbody.add_statement (stmt.body.ccodenode);
++
++                      var list_len = new CCodeFunctionCall (new CCodeIdentifier ("gee_collection_get_size"));
++                      list_len.add_argument (new InstanceCast (new CCodeIdentifier (collection_backup.name), this.collection_type));
++
++                      var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, new CCodeIdentifier (it_name), list_len);
++
++                      var cfor = new CCodeForStatement (ccond, cbody);
++                      cfor.add_initializer (new CCodeAssignment (new CCodeIdentifier (it_name), new CCodeConstant ("0")));
++                      cfor.add_iterator (new CCodeAssignment (new CCodeIdentifier (it_name), new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, new CCodeIdentifier (it_name), new CCodeConstant ("1"))));
++                      cfor.line = cblock.line;
++                      cblock.add_statement (cfor);
++              } else if (iterable_type != null && stmt.collection.value_type.compatible (new ObjectType (iterable_type))) {
++                      // iterating over a Gee.Iterable, use iterator
++
++                      var it_name = "%s_it".printf (stmt.variable_name);
++
++                      var citdecl = new CCodeDeclaration (iterator_type.get_cname () + "*");
++                      var it_method = (Method) iterable_type.scope.lookup ("iterator");
++                      var it_ccall = new CCodeFunctionCall (new CCodeIdentifier (it_method.get_cname ()));
++                      it_ccall.add_argument (new InstanceCast (new CCodeIdentifier (collection_backup.name), iterable_type));
++                      var citvardecl = new CCodeVariableDeclarator.with_initializer (it_name, it_ccall);
++                      citvardecl.line = cblock.line;
++                      citdecl.add_declarator (citvardecl);
++                      cblock.add_statement (citdecl);
++                      
++                      var cbody = new CCodeBlock ();
++
++                      var get_method = (Method) iterator_type.scope.lookup ("get");
++                      var get_ccall = new CCodeFunctionCall (new CCodeIdentifier (get_method.get_cname ()));
++                      get_ccall.add_argument (new CCodeIdentifier (it_name));
++                      CCodeExpression element_expr = get_ccall;
++
++                      Iterator<DataType> type_arg_it = it_method.return_type.get_type_arguments ().iterator ();
++                      type_arg_it.next ();
++                      var it_type = SemanticAnalyzer.get_actual_type (stmt.collection.value_type, it_method, type_arg_it.get (), stmt);
++
++                      element_expr = transform_expression (element_expr, it_type, stmt.type_reference);
++
++                      var cfrag = new CCodeFragment ();
++                      append_temp_decl (cfrag, temp_vars);
++                      cbody.add_statement (cfrag);
++                      temp_vars.clear ();
++
++                      var cdecl = new CCodeDeclaration (stmt.type_reference.get_cname ());
++                      var cvardecl = new CCodeVariableDeclarator.with_initializer (stmt.variable_name, element_expr);
++                      cvardecl.line = cblock.line;
++                      cdecl.add_declarator (cvardecl);
++                      cbody.add_statement (cdecl);
++                      
++                      cbody.add_statement (stmt.body.ccodenode);
++
++                      var next_method = (Method) iterator_type.scope.lookup ("next");
++                      var next_ccall = new CCodeFunctionCall (new CCodeIdentifier (next_method.get_cname ()));
++                      next_ccall.add_argument (new CCodeIdentifier (it_name));
++
++                      var cwhile = new CCodeWhileStatement (next_ccall, cbody);
++                      cwhile.line = cblock.line;
++                      cblock.add_statement (cwhile);
++              }
++
++              foreach (LocalVariable local in stmt.get_local_variables ()) {
++                      if (requires_destroy (local.variable_type)) {
++                              var ma = new MemberAccess.simple (local.name);
++                              ma.symbol_reference = local;
++                              var cunref = new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier (get_variable_cname (local.name)), local.variable_type, ma));
++                              cunref.line = cblock.line;
++                              cblock.add_statement (cunref);
++                      }
++              }
++      }
++
++      public override void visit_break_statement (BreakStatement stmt) {
++              stmt.ccodenode = new CCodeBreakStatement ();
++
++              create_local_free (stmt, true);
++      }
++
++      public override void visit_continue_statement (ContinueStatement stmt) {
++              stmt.ccodenode = new CCodeContinueStatement ();
++
++              create_local_free (stmt, true);
++      }
++}
++
+Index: gobject/valaccodebasemodule.vala
+===================================================================
+--- gobject/valaccodebasemodule.vala   (revision 1971)
++++ gobject/valaccodebasemodule.vala   (revision 2004)
+@@ -78,7 +78,6 @@
+       public Gee.Set<string> c_keywords;
+       
+       public int next_temp_var_id = 0;
+-      private int next_array_dup_id = 0;
+       public bool in_creation_method = false;
+       public bool in_constructor = false;
+       public bool in_static_or_class_ctor = false;
+@@ -213,36 +212,6 @@
+               }
+       }
+-      public override CCodeExpression get_construct_property_assignment (CCodeConstant canonical_cconstant, DataType property_type, CCodeExpression value) {
+-              // this property is used as a construction parameter
+-              var cpointer = new CCodeIdentifier ("__params_it");
+-              
+-              var ccomma = new CCodeCommaExpression ();
+-              // set name in array for current parameter
+-              var cnamemember = new CCodeMemberAccess.pointer (cpointer, "name");
+-              var cnameassign = new CCodeAssignment (cnamemember, canonical_cconstant);
+-              ccomma.append_expression (cnameassign);
+-              
+-              var gvaluearg = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeMemberAccess.pointer (cpointer, "value"));
+-              
+-              // initialize GValue in array for current parameter
+-              var cvalueinit = new CCodeFunctionCall (new CCodeIdentifier ("g_value_init"));
+-              cvalueinit.add_argument (gvaluearg);
+-              cvalueinit.add_argument (new CCodeIdentifier (property_type.get_type_id ()));
+-              ccomma.append_expression (cvalueinit);
+-              
+-              // set GValue for current parameter
+-              var cvalueset = new CCodeFunctionCall (get_value_setter_function (property_type));
+-              cvalueset.add_argument (gvaluearg);
+-              cvalueset.add_argument (value);
+-              ccomma.append_expression (cvalueset);
+-              
+-              // move pointer to next parameter in array
+-              ccomma.append_expression (new CCodeUnaryExpression (CCodeUnaryOperator.POSTFIX_INCREMENT, cpointer));
+-
+-              return ccomma;
+-      }
+-
+       private CCodeIncludeDirective get_internal_include (string filename) {
+               return new CCodeIncludeDirective (filename, context.library == null);
+       }
+@@ -939,7 +908,7 @@
+               }
+       }
+-      private bool is_constant_ccode_expression (CCodeExpression cexpr) {
++      public bool is_constant_ccode_expression (CCodeExpression cexpr) {
+               if (cexpr is CCodeConstant) {
+                       return true;
+               } else if (cexpr is CCodeBinaryExpression) {
+@@ -1208,133 +1177,6 @@
+               current_return_type = null;
+       }
+-      public override void visit_constructor (Constructor c) {
+-              current_method_inner_error = false;
+-              in_constructor = true;
+-
+-              if (c.binding == MemberBinding.CLASS || c.binding == MemberBinding.STATIC) {
+-                      in_static_or_class_ctor = true;
+-              }
+-              c.accept_children (codegen);
+-              in_static_or_class_ctor = false;
+-
+-              in_constructor = false;
+-
+-              var cl = (Class) c.parent_symbol;
+-
+-              if (c.binding == MemberBinding.INSTANCE) {
+-                      function = new CCodeFunction ("%s_constructor".printf (cl.get_lower_case_cname (null)), "GObject *");
+-                      function.modifiers = CCodeModifiers.STATIC;
+-              
+-                      function.add_parameter (new CCodeFormalParameter ("type", "GType"));
+-                      function.add_parameter (new CCodeFormalParameter ("n_construct_properties", "guint"));
+-                      function.add_parameter (new CCodeFormalParameter ("construct_properties", "GObjectConstructParam *"));
+-              
+-                      source_type_member_declaration.append (function.copy ());
+-
+-
+-                      var cblock = new CCodeBlock ();
+-                      var cdecl = new CCodeDeclaration ("GObject *");
+-                      cdecl.add_declarator (new CCodeVariableDeclarator ("obj"));
+-                      cblock.add_statement (cdecl);
+-
+-                      cdecl = new CCodeDeclaration ("%sClass *".printf (cl.get_cname ()));
+-                      cdecl.add_declarator (new CCodeVariableDeclarator ("klass"));
+-                      cblock.add_statement (cdecl);
+-
+-                      cdecl = new CCodeDeclaration ("GObjectClass *");
+-                      cdecl.add_declarator (new CCodeVariableDeclarator ("parent_class"));
+-                      cblock.add_statement (cdecl);
+-
+-
+-                      var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_class_peek"));
+-                      ccall.add_argument (new CCodeIdentifier (cl.get_type_id ()));
+-                      var ccast = new CCodeFunctionCall (new CCodeIdentifier ("%s_CLASS".printf (cl.get_upper_case_cname (null))));
+-                      ccast.add_argument (ccall);
+-                      cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("klass"), ccast)));
+-
+-                      ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_class_peek_parent"));
+-                      ccall.add_argument (new CCodeIdentifier ("klass"));
+-                      ccast = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT_CLASS"));
+-                      ccast.add_argument (ccall);
+-                      cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("parent_class"), ccast)));
+-
+-              
+-                      ccall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (new CCodeIdentifier ("parent_class"), "constructor"));
+-                      ccall.add_argument (new CCodeIdentifier ("type"));
+-                      ccall.add_argument (new CCodeIdentifier ("n_construct_properties"));
+-                      ccall.add_argument (new CCodeIdentifier ("construct_properties"));
+-                      cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("obj"), ccall)));
+-
+-
+-                      ccall = new InstanceCast (new CCodeIdentifier ("obj"), cl);
+-
+-                      cdecl = new CCodeDeclaration ("%s *".printf (cl.get_cname ()));
+-                      cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("self", ccall));
+-              
+-                      cblock.add_statement (cdecl);
+-
+-                      if (current_method_inner_error) {
+-                              /* always separate error parameter and inner_error local variable
+-                               * as error may be set to NULL but we're always interested in inner errors
+-                               */
+-                              var cdecl = new CCodeDeclaration ("GError *");
+-                              cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("inner_error", new CCodeConstant ("NULL")));
+-                              cblock.add_statement (cdecl);
+-                      }
+-
+-
+-                      cblock.add_statement (c.body.ccodenode);
+-              
+-                      cblock.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("obj")));
+-              
+-                      function.block = cblock;
+-
+-                      if (c.source_reference.comment != null) {
+-                              source_type_member_definition.append (new CCodeComment (c.source_reference.comment));
+-                      }
+-                      source_type_member_definition.append (function);
+-              } else if (c.binding == MemberBinding.CLASS) {
+-                      // class constructor
+-
+-                      var base_init = new CCodeFunction ("%s_base_init".printf (cl.get_lower_case_cname (null)), "void");
+-                      base_init.add_parameter (new CCodeFormalParameter ("klass", "%sClass *".printf (cl.get_cname ())));
+-                      base_init.modifiers = CCodeModifiers.STATIC;
+-
+-                      source_type_member_declaration.append (base_init.copy ());
+-
+-                      var block = (CCodeBlock) c.body.ccodenode;
+-                      if (current_method_inner_error) {
+-                              /* always separate error parameter and inner_error local variable
+-                               * as error may be set to NULL but we're always interested in inner errors
+-                               */
+-                              var cdecl = new CCodeDeclaration ("GError *");
+-                              cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("inner_error", new CCodeConstant ("NULL")));
+-                              block.prepend_statement (cdecl);
+-                      }
+-
+-                      base_init.block = block;
+-              
+-                      source_type_member_definition.append (base_init);
+-              } else if (c.binding == MemberBinding.STATIC) {
+-                      // static class constructor
+-                      // add to class_init
+-
+-                      if (current_method_inner_error) {
+-                              /* always separate error parameter and inner_error local variable
+-                               * as error may be set to NULL but we're always interested in inner errors
+-                               */
+-                              var cdecl = new CCodeDeclaration ("GError *");
+-                              cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("inner_error", new CCodeConstant ("NULL")));
+-                              class_init_fragment.append (cdecl);
+-                      }
+-
+-                      class_init_fragment.append (c.body.ccodenode);
+-              } else {
+-                      Report.error (c.source_reference, "internal error: constructors must have instance, class, or static binding");
+-              }
+-      }
+-
+       public override void visit_destructor (Destructor d) {
+               current_method_inner_error = false;
+@@ -1600,12 +1442,12 @@
+               }
+       }
+-      public CCodeExpression? get_dup_func_expression (DataType type, SourceReference? source_reference) {
+-              var cl = type.data_type as Class;
++      public virtual CCodeExpression? get_dup_func_expression (DataType type, SourceReference? source_reference) {
+               if (type is ErrorType) {
+                       return new CCodeIdentifier ("g_error_copy");
+               } else if (type.data_type != null) {
+                       string dup_function;
++                      var cl = type.data_type as Class;
+                       if (type.data_type.is_reference_counting ()) {
+                               dup_function = type.data_type.get_ref_function ();
+                               if (type.data_type is Interface && dup_function == null) {
+@@ -1631,8 +1473,6 @@
+               } else if (type.type_parameter != null && current_type_symbol is Class) {
+                       string func_name = "%s_dup_func".printf (type.type_parameter.name.down ());
+                       return new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), func_name);
+-              } else if (type is ArrayType) {
+-                      return new CCodeIdentifier (generate_array_dup_wrapper ((ArrayType) type));
+               } else if (type is PointerType) {
+                       var pointer_type = (PointerType) type;
+                       return get_dup_func_expression (pointer_type.base_type, source_reference);
+@@ -1641,78 +1481,6 @@
+               }
+       }
+-      string generate_array_dup_wrapper (ArrayType array_type) {
+-              string dup_func = "_vala_array_dup%d".printf (++next_array_dup_id);
+-
+-              if (!add_wrapper (dup_func)) {
+-                      // wrapper already defined
+-                      return dup_func;
+-              }
+-
+-              // declaration
+-
+-              var function = new CCodeFunction (dup_func, array_type.get_cname ());
+-              function.modifiers = CCodeModifiers.STATIC;
+-
+-              function.add_parameter (new CCodeFormalParameter ("self", array_type.get_cname ()));
+-              // total length over all dimensions
+-              function.add_parameter (new CCodeFormalParameter ("length", "int"));
+-
+-              // definition
+-
+-              var block = new CCodeBlock ();
+-
+-              if (requires_copy (array_type.element_type)) {
+-                      var old_temp_vars = temp_vars;
+-
+-                      var cdecl = new CCodeDeclaration (array_type.get_cname ());
+-                      var cvardecl = new CCodeVariableDeclarator ("result");
+-                      cdecl.add_declarator (cvardecl);
+-                      var gnew = new CCodeFunctionCall (new CCodeIdentifier ("g_new0"));
+-                      gnew.add_argument (new CCodeIdentifier (array_type.element_type.get_cname ()));
+-                      gnew.add_argument (new CCodeIdentifier ("length"));
+-                      cvardecl.initializer = gnew;
+-                      block.add_statement (cdecl);
+-
+-                      var idx_decl = new CCodeDeclaration ("int");
+-                      idx_decl.add_declarator (new CCodeVariableDeclarator ("i"));
+-                      block.add_statement (idx_decl);
+-
+-                      var loop_body = new CCodeBlock ();
+-                      loop_body.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeElementAccess (new CCodeIdentifier ("result"), new CCodeIdentifier ("i")), get_ref_cexpression (array_type.element_type, new CCodeElementAccess (new CCodeIdentifier ("self"), new CCodeIdentifier ("i")), null, array_type))));
+-
+-                      var cfor = new CCodeForStatement (new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, new CCodeIdentifier ("i"), new CCodeIdentifier ("length")), loop_body);
+-                      cfor.add_initializer (new CCodeAssignment (new CCodeIdentifier ("i"), new CCodeConstant ("0")));
+-                      cfor.add_iterator (new CCodeUnaryExpression (CCodeUnaryOperator.POSTFIX_INCREMENT, new CCodeIdentifier ("i")));
+-                      block.add_statement (cfor);
+-
+-                      block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("result")));
+-
+-                      var cfrag = new CCodeFragment ();
+-                      append_temp_decl (cfrag, temp_vars);
+-                      block.add_statement (cfrag);
+-                      temp_vars = old_temp_vars;
+-              } else {
+-                      var dup_call = new CCodeFunctionCall (new CCodeIdentifier ("g_memdup"));
+-                      dup_call.add_argument (new CCodeIdentifier ("self"));
+-
+-                      var sizeof_call = new CCodeFunctionCall (new CCodeIdentifier ("sizeof"));
+-                      sizeof_call.add_argument (new CCodeIdentifier (array_type.element_type.get_cname ()));
+-                      dup_call.add_argument (new CCodeBinaryExpression (CCodeBinaryOperator.MUL, new CCodeIdentifier ("length"), sizeof_call));
+-
+-                      block.add_statement (new CCodeReturnStatement (dup_call));
+-              }
+-
+-              // append to file
+-
+-              source_type_member_declaration.append (function.copy ());
+-
+-              function.block = block;
+-              source_type_member_definition.append (function);
+-
+-              return dup_func;
+-      }
+-
+       private string generate_struct_dup_wrapper (ValueType value_type) {
+               string dup_func = "_%sdup".printf (value_type.type_symbol.get_lower_case_cprefix ());
+@@ -2084,546 +1852,6 @@
+               ((CodeNode) stmt).ccodenode = cfrag;
+       }
+-      public override void visit_if_statement (IfStatement stmt) {
+-              stmt.accept_children (codegen);
+-
+-              if (stmt.false_statement != null) {
+-                      stmt.ccodenode = new CCodeIfStatement ((CCodeExpression) stmt.condition.ccodenode, (CCodeStatement) stmt.true_statement.ccodenode, (CCodeStatement) stmt.false_statement.ccodenode);
+-              } else {
+-                      stmt.ccodenode = new CCodeIfStatement ((CCodeExpression) stmt.condition.ccodenode, (CCodeStatement) stmt.true_statement.ccodenode);
+-              }
+-              
+-              create_temp_decl (stmt, stmt.condition.temp_vars);
+-      }
+-
+-      void visit_string_switch_statement (SwitchStatement stmt) {
+-              // we need a temporary variable to save the property value
+-              var temp_var = get_temp_variable (stmt.expression.value_type, true, stmt);
+-              stmt.expression.temp_vars.insert (0, temp_var);
+-
+-              var ctemp = new CCodeIdentifier (temp_var.name);
+-              var cinit = new CCodeAssignment (ctemp, (CCodeExpression) stmt.expression.ccodenode);
+-              var czero = new CCodeConstant ("0");
+-
+-              var cswitchblock = new CCodeFragment ();
+-              stmt.ccodenode = cswitchblock;
+-
+-              var cisnull = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeConstant ("NULL"), ctemp);
+-              var cquark = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_string"));
+-              cquark.add_argument (ctemp);
+-
+-              var ccond = new CCodeConditionalExpression (cisnull, new CCodeConstant ("0"), cquark);
+-
+-              temp_var = get_temp_variable (gquark_type);
+-              stmt.expression.temp_vars.insert (0, temp_var);
+-
+-              int label_count = 0;
+-
+-              foreach (SwitchSection section in stmt.get_sections ()) {
+-                      if (section.has_default_label ()) {
+-                              continue;
+-                      }
+-
+-                      foreach (SwitchLabel label in section.get_labels ()) {
+-                              var cexpr = (CCodeExpression) label.expression.ccodenode;
+-
+-                              if (is_constant_ccode_expression (cexpr)) {
+-                                      var cname = "%s_label%d".printf (temp_var.name, label_count++);
+-                                      var cdecl = new CCodeDeclaration (gquark_type.get_cname ());
+-
+-                                      cdecl.modifiers = CCodeModifiers.STATIC;
+-                                      cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer (cname, czero));
+-
+-                                      cswitchblock.append (cdecl);
+-                              }
+-                      }
+-              }
+-
+-              cswitchblock.append (new CCodeExpressionStatement (cinit));
+-
+-              ctemp = new CCodeIdentifier (temp_var.name);
+-              cinit = new CCodeAssignment (ctemp, ccond);
+-
+-              cswitchblock.append (new CCodeExpressionStatement (cinit));
+-              create_temp_decl (stmt, stmt.expression.temp_vars);
+-
+-              Gee.List<Statement> default_statements = null;
+-              label_count = 0;
+-
+-              // generate nested if statements                
+-              CCodeStatement ctopstmt = null;
+-              CCodeIfStatement coldif = null;
+-
+-              foreach (SwitchSection section in stmt.get_sections ()) {
+-                      if (section.has_default_label ()) {
+-                              default_statements = section.get_statements ();
+-                              continue;
+-                      }
+-
+-                      CCodeBinaryExpression cor = null;
+-                      foreach (SwitchLabel label in section.get_labels ()) {
+-                              var cexpr = (CCodeExpression) label.expression.ccodenode;
+-
+-                              if (is_constant_ccode_expression (cexpr)) {
+-                                      var cname = new CCodeIdentifier ("%s_label%d".printf (temp_var.name, label_count++));
+-                                      var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, czero, cname);
+-                                      var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_static_string"));
+-                                      var cinit = new CCodeParenthesizedExpression (new CCodeAssignment (cname, ccall));
+-
+-                                      ccall.add_argument (cexpr);
+-
+-                                      cexpr = new CCodeConditionalExpression (ccond, cname, cinit);
+-                              } else {
+-                                      var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_string"));
+-                                      ccall.add_argument (cexpr);
+-                                      cexpr = ccall;
+-                              }
+-
+-                              var ccmp = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ctemp, cexpr);
+-
+-                              if (cor == null) {
+-                                      cor = ccmp;
+-                              } else {
+-                                      cor = new CCodeBinaryExpression (CCodeBinaryOperator.OR, cor, ccmp);
+-                              }
+-                      }
+-
+-                      var cblock = new CCodeBlock ();
+-                      foreach (CodeNode body_stmt in section.get_statements ()) {
+-                              if (body_stmt.ccodenode is CCodeFragment) {
+-                                      foreach (CCodeNode cstmt in ((CCodeFragment) body_stmt.ccodenode).get_children ()) {
+-                                              cblock.add_statement (cstmt);
+-                                      }
+-                              } else {
+-                                      cblock.add_statement (body_stmt.ccodenode);
+-                              }
+-                      }
+-
+-                      var cdo = new CCodeDoStatement (cblock, new CCodeConstant ("0"));
+-                      var cif = new CCodeIfStatement (cor, cdo);
+-
+-                      if (coldif != null) {
+-                              coldif.false_statement = cif;
+-                      } else {
+-                              ctopstmt = cif;
+-                      }
+-
+-                      coldif = cif;
+-              }
+-      
+-              if (default_statements != null) {
+-                      var cblock = new CCodeBlock ();
+-                      foreach (CodeNode body_stmt in default_statements) {
+-                              cblock.add_statement (body_stmt.ccodenode);
+-                      }
+-              
+-                      var cdo = new CCodeDoStatement (cblock, new CCodeConstant ("0"));
+-
+-                      if (coldif == null) {
+-                              // there is only one section and that section
+-                              // contains a default label
+-                              ctopstmt = cdo;
+-                      } else {
+-                              coldif.false_statement = cdo;
+-                      }
+-              }
+-      
+-              cswitchblock.append (ctopstmt);
+-      }
+-
+-      public override void visit_switch_statement (SwitchStatement stmt) {
+-              if (stmt.expression.value_type.compatible (string_type)) {
+-                      visit_string_switch_statement (stmt);
+-                      return;
+-              }
+-
+-              var cswitch = new CCodeSwitchStatement ((CCodeExpression) stmt.expression.ccodenode);
+-              stmt.ccodenode = cswitch;
+-
+-              foreach (SwitchSection section in stmt.get_sections ()) {
+-                      if (section.has_default_label ()) {
+-                              cswitch.add_statement (new CCodeLabel ("default"));
+-                              var cdefaultblock = new CCodeBlock ();
+-                              cswitch.add_statement (cdefaultblock);
+-                              foreach (CodeNode default_stmt in section.get_statements ()) {
+-                                      cdefaultblock.add_statement (default_stmt.ccodenode);
+-                              }
+-                              continue;
+-                      }
+-
+-                      foreach (SwitchLabel label in section.get_labels ()) {
+-                              cswitch.add_statement (new CCodeCaseStatement ((CCodeExpression) label.expression.ccodenode));
+-                      }
+-
+-                      var cblock = new CCodeBlock ();
+-                      cswitch.add_statement (cblock);
+-                      foreach (CodeNode body_stmt in section.get_statements ()) {
+-                              cblock.add_statement (body_stmt.ccodenode);
+-                      }
+-              }
+-      }
+-
+-      public override void visit_switch_section (SwitchSection section) {
+-              visit_block (section);
+-      }
+-
+-      public override void visit_while_statement (WhileStatement stmt) {
+-              stmt.accept_children (codegen);
+-
+-              stmt.ccodenode = new CCodeWhileStatement ((CCodeExpression) stmt.condition.ccodenode, (CCodeStatement) stmt.body.ccodenode);
+-              
+-              create_temp_decl (stmt, stmt.condition.temp_vars);
+-      }
+-
+-      public override void visit_do_statement (DoStatement stmt) {
+-              stmt.accept_children (codegen);
+-
+-              stmt.ccodenode = new CCodeDoStatement ((CCodeStatement) stmt.body.ccodenode, (CCodeExpression) stmt.condition.ccodenode);
+-              
+-              create_temp_decl (stmt, stmt.condition.temp_vars);
+-      }
+-
+-      public override void visit_for_statement (ForStatement stmt) {
+-              stmt.accept_children (codegen);
+-
+-              CCodeExpression ccondition = null;
+-              if (stmt.condition != null) {
+-                      ccondition = (CCodeExpression) stmt.condition.ccodenode;
+-              }
+-
+-              var cfor = new CCodeForStatement (ccondition, (CCodeStatement) stmt.body.ccodenode);
+-              stmt.ccodenode = cfor;
+-              
+-              foreach (Expression init_expr in stmt.get_initializer ()) {
+-                      cfor.add_initializer ((CCodeExpression) init_expr.ccodenode);
+-                      create_temp_decl (stmt, init_expr.temp_vars);
+-              }
+-              
+-              foreach (Expression it_expr in stmt.get_iterator ()) {
+-                      cfor.add_iterator ((CCodeExpression) it_expr.ccodenode);
+-                      create_temp_decl (stmt, it_expr.temp_vars);
+-              }
+-
+-              if (stmt.condition != null) {
+-                      create_temp_decl (stmt, stmt.condition.temp_vars);
+-              }
+-      }
+-
+-      public override void visit_foreach_statement (ForeachStatement stmt) {
+-              stmt.element_variable.active = true;
+-              stmt.collection_variable.active = true;
+-              if (stmt.iterator_variable != null) {
+-                      stmt.iterator_variable.active = true;
+-              }
+-
+-              visit_block (stmt);
+-
+-              var cblock = new CCodeBlock ();
+-              // sets #line
+-              stmt.ccodenode = cblock;
+-
+-              var cfrag = new CCodeFragment ();
+-              append_temp_decl (cfrag, stmt.collection.temp_vars);
+-              cblock.add_statement (cfrag);
+-              
+-              var collection_backup = stmt.collection_variable;
+-              var collection_type = collection_backup.variable_type.copy ();
+-              var ccoldecl = new CCodeDeclaration (collection_type.get_cname ());
+-              var ccolvardecl = new CCodeVariableDeclarator.with_initializer (collection_backup.name, (CCodeExpression) stmt.collection.ccodenode);
+-              ccolvardecl.line = cblock.line;
+-              ccoldecl.add_declarator (ccolvardecl);
+-              cblock.add_statement (ccoldecl);
+-              
+-              if (stmt.tree_can_fail && stmt.collection.tree_can_fail) {
+-                      // exception handling
+-                      var cfrag = new CCodeFragment ();
+-                      head.add_simple_check (stmt.collection, cfrag);
+-                      cblock.add_statement (cfrag);
+-              }
+-
+-              if (stmt.collection.value_type is ArrayType) {
+-                      var array_type = (ArrayType) stmt.collection.value_type;
+-                      
+-                      var array_len = head.get_array_length_cexpression (stmt.collection);
+-
+-                      // store array length for use by _vala_array_free
+-                      var clendecl = new CCodeDeclaration ("int");
+-                      clendecl.add_declarator (new CCodeVariableDeclarator.with_initializer (head.get_array_length_cname (collection_backup.name, 1), array_len));
+-                      cblock.add_statement (clendecl);
+-
+-                      if (array_len is CCodeConstant) {
+-                              // the array has no length parameter i.e. it is NULL-terminated array
+-
+-                              var it_name = "%s_it".printf (stmt.variable_name);
+-                      
+-                              var citdecl = new CCodeDeclaration (collection_type.get_cname ());
+-                              citdecl.add_declarator (new CCodeVariableDeclarator (it_name));
+-                              cblock.add_statement (citdecl);
+-                              
+-                              var cbody = new CCodeBlock ();
+-
+-                              CCodeExpression element_expr = new CCodeIdentifier ("*%s".printf (it_name));
+-
+-                              var element_type = array_type.element_type.copy ();
+-                              element_type.value_owned = false;
+-                              element_expr = transform_expression (element_expr, element_type, stmt.type_reference);
+-
+-                              var cfrag = new CCodeFragment ();
+-                              append_temp_decl (cfrag, temp_vars);
+-                              cbody.add_statement (cfrag);
+-                              temp_vars.clear ();
+-
+-                              var cdecl = new CCodeDeclaration (stmt.type_reference.get_cname ());
+-                              cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer (stmt.variable_name, element_expr));
+-                              cbody.add_statement (cdecl);
+-
+-                              // add array length variable for stacked arrays
+-                              if (stmt.type_reference is ArrayType) {
+-                                      var inner_array_type = (ArrayType) stmt.type_reference;
+-                                      for (int dim = 1; dim <= inner_array_type.rank; dim++) {
+-                                              cdecl = new CCodeDeclaration ("int");
+-                                              cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer (head.get_array_length_cname (stmt.variable_name, dim), new CCodeConstant ("-1")));
+-                                              cbody.add_statement (cdecl);
+-                                      }
+-                              }
+-
+-                              cbody.add_statement (stmt.body.ccodenode);
+-                              
+-                              var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier ("*%s".printf (it_name)), new CCodeConstant ("NULL"));
+-                              
+-                              var cfor = new CCodeForStatement (ccond, cbody);
+-
+-                              cfor.add_initializer (new CCodeAssignment (new CCodeIdentifier (it_name), new CCodeIdentifier (collection_backup.name)));
+-              
+-                              cfor.add_iterator (new CCodeAssignment (new CCodeIdentifier (it_name), new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, new CCodeIdentifier (it_name), new CCodeConstant ("1"))));
+-                              cblock.add_statement (cfor);
+-                      } else {
+-                              // the array has a length parameter
+-
+-                              var it_name = (stmt.variable_name + "_it");
+-                      
+-                              var citdecl = new CCodeDeclaration ("int");
+-                              citdecl.add_declarator (new CCodeVariableDeclarator (it_name));
+-                              cblock.add_statement (citdecl);
+-                              
+-                              var cbody = new CCodeBlock ();
+-
+-                              CCodeExpression element_expr = new CCodeElementAccess (new CCodeIdentifier (collection_backup.name), new CCodeIdentifier (it_name));
+-
+-                              var element_type = array_type.element_type.copy ();
+-                              element_type.value_owned = false;
+-                              element_expr = transform_expression (element_expr, element_type, stmt.type_reference);
+-
+-                              var cfrag = new CCodeFragment ();
+-                              append_temp_decl (cfrag, temp_vars);
+-                              cbody.add_statement (cfrag);
+-                              temp_vars.clear ();
+-
+-                              var cdecl = new CCodeDeclaration (stmt.type_reference.get_cname ());
+-                              cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer (stmt.variable_name, element_expr));
+-                              cbody.add_statement (cdecl);
+-
+-                              // add array length variable for stacked arrays
+-                              if (stmt.type_reference is ArrayType) {
+-                                      var inner_array_type = (ArrayType) stmt.type_reference;
+-                                      for (int dim = 1; dim <= inner_array_type.rank; dim++) {
+-                                              cdecl = new CCodeDeclaration ("int");
+-                                              cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer (head.get_array_length_cname (stmt.variable_name, dim), new CCodeConstant ("-1")));
+-                                              cbody.add_statement (cdecl);
+-                                      }
+-                              }
+-
+-                              cbody.add_statement (stmt.body.ccodenode);
+-                              
+-                              var ccond_ind1 = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, array_len, new CCodeConstant ("-1"));
+-                              var ccond_ind2 = new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, new CCodeIdentifier (it_name), array_len);
+-                              var ccond_ind = new CCodeBinaryExpression (CCodeBinaryOperator.AND, ccond_ind1, ccond_ind2);
+-                              
+-                              /* only check for null if the containers elements are of reference-type */
+-                              CCodeBinaryExpression ccond;
+-                              if (array_type.element_type.is_reference_type_or_type_parameter ()) {
+-                                      var ccond_term1 = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, array_len, new CCodeConstant ("-1"));
+-                                      var ccond_term2 = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeElementAccess (new CCodeIdentifier (collection_backup.name), new CCodeIdentifier (it_name)), new CCodeConstant ("NULL"));
+-                                      var ccond_term = new CCodeBinaryExpression (CCodeBinaryOperator.AND, ccond_term1, ccond_term2);
+-
+-                                      ccond = new CCodeBinaryExpression (CCodeBinaryOperator.OR, new CCodeParenthesizedExpression (ccond_ind), new CCodeParenthesizedExpression (ccond_term));
+-                              } else {
+-                                      /* assert when trying to iterate over value-type arrays of unknown length */
+-                                      var cassert = new CCodeFunctionCall (new CCodeIdentifier ("g_assert"));
+-                                      cassert.add_argument (ccond_ind1);
+-                                      cblock.add_statement (new CCodeExpressionStatement (cassert));
+-
+-                                      ccond = ccond_ind2;
+-                              }
+-                              
+-                              var cfor = new CCodeForStatement (ccond, cbody);
+-                              cfor.add_initializer (new CCodeAssignment (new CCodeIdentifier (it_name), new CCodeConstant ("0")));
+-                              cfor.add_iterator (new CCodeAssignment (new CCodeIdentifier (it_name), new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, new CCodeIdentifier (it_name), new CCodeConstant ("1"))));
+-                              cblock.add_statement (cfor);
+-                      }
+-              } else if (stmt.collection.value_type.compatible (new ObjectType (glist_type)) || stmt.collection.value_type.compatible (new ObjectType (gslist_type))) {
+-                      // iterating over a GList or GSList
+-
+-                      var it_name = "%s_it".printf (stmt.variable_name);
+-              
+-                      var citdecl = new CCodeDeclaration (collection_type.get_cname ());
+-                      var citvardecl = new CCodeVariableDeclarator (it_name);
+-                      citvardecl.line = cblock.line;
+-                      citdecl.add_declarator (citvardecl);
+-                      cblock.add_statement (citdecl);
+-                      
+-                      var cbody = new CCodeBlock ();
+-
+-                      CCodeExpression element_expr = new CCodeMemberAccess.pointer (new CCodeIdentifier (it_name), "data");
+-
+-                      if (collection_type.get_type_arguments ().size != 1) {
+-                              Report.error (stmt.source_reference, "internal error: missing generic type argument");
+-                              stmt.error = true;
+-                              return;
+-                      }
+-
+-                      var element_data_type = collection_type.get_type_arguments ().get (0).copy ();
+-                      element_data_type.value_owned = false;
+-                      element_data_type.is_type_argument = true;
+-                      element_expr = transform_expression (element_expr, element_data_type, stmt.type_reference);
+-
+-                      var cfrag = new CCodeFragment ();
+-                      append_temp_decl (cfrag, temp_vars);
+-                      cbody.add_statement (cfrag);
+-                      temp_vars.clear ();
+-
+-                      var cdecl = new CCodeDeclaration (stmt.type_reference.get_cname ());
+-                      var cvardecl = new CCodeVariableDeclarator.with_initializer (stmt.variable_name, element_expr);
+-                      cvardecl.line = cblock.line;
+-                      cdecl.add_declarator (cvardecl);
+-                      cbody.add_statement (cdecl);
+-                      
+-                      cbody.add_statement (stmt.body.ccodenode);
+-                      
+-                      var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier (it_name), new CCodeConstant ("NULL"));
+-                      
+-                      var cfor = new CCodeForStatement (ccond, cbody);
+-                      
+-                      cfor.add_initializer (new CCodeAssignment (new CCodeIdentifier (it_name), new CCodeIdentifier (collection_backup.name)));
+-
+-                      cfor.add_iterator (new CCodeAssignment (new CCodeIdentifier (it_name), new CCodeMemberAccess.pointer (new CCodeIdentifier (it_name), "next")));
+-                      cblock.add_statement (cfor);
+-              } else if (list_type != null && stmt.collection.value_type.compatible (new ObjectType (list_type))) {
+-                      // iterating over a Gee.List, use integer to avoid the cost of an iterator object
+-
+-                      var it_name = "%s_it".printf (stmt.variable_name);
+-
+-                      var citdecl = new CCodeDeclaration ("int");
+-                      citdecl.add_declarator (new CCodeVariableDeclarator (it_name));
+-                      cblock.add_statement (citdecl);
+-                      
+-                      var cbody = new CCodeBlock ();
+-
+-                      var get_method = (Method) list_type.scope.lookup ("get");
+-                      var get_ccall = new CCodeFunctionCall (new CCodeIdentifier (get_method.get_cname ()));
+-                      get_ccall.add_argument (new InstanceCast (new CCodeIdentifier (collection_backup.name), list_type));
+-                      get_ccall.add_argument (new CCodeIdentifier (it_name));
+-                      CCodeExpression element_expr = get_ccall;
+-
+-                      var element_type = SemanticAnalyzer.get_actual_type (stmt.collection.value_type, get_method, get_method.return_type, stmt);
+-
+-                      element_expr = transform_expression (element_expr, element_type, stmt.type_reference);
+-
+-                      var cfrag = new CCodeFragment ();
+-                      append_temp_decl (cfrag, temp_vars);
+-                      cbody.add_statement (cfrag);
+-                      temp_vars.clear ();
+-
+-                      var cdecl = new CCodeDeclaration (stmt.type_reference.get_cname ());
+-                      var cvardecl = new CCodeVariableDeclarator.with_initializer (stmt.variable_name, element_expr);
+-                      cvardecl.line = cblock.line;
+-                      cdecl.add_declarator (cvardecl);
+-                      cbody.add_statement (cdecl);
+-
+-                      cbody.add_statement (stmt.body.ccodenode);
+-
+-                      var list_len = new CCodeFunctionCall (new CCodeIdentifier ("gee_collection_get_size"));
+-                      list_len.add_argument (new InstanceCast (new CCodeIdentifier (collection_backup.name), this.collection_type));
+-
+-                      var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, new CCodeIdentifier (it_name), list_len);
+-
+-                      var cfor = new CCodeForStatement (ccond, cbody);
+-                      cfor.add_initializer (new CCodeAssignment (new CCodeIdentifier (it_name), new CCodeConstant ("0")));
+-                      cfor.add_iterator (new CCodeAssignment (new CCodeIdentifier (it_name), new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, new CCodeIdentifier (it_name), new CCodeConstant ("1"))));
+-                      cfor.line = cblock.line;
+-                      cblock.add_statement (cfor);
+-              } else if (iterable_type != null && stmt.collection.value_type.compatible (new ObjectType (iterable_type))) {
+-                      // iterating over a Gee.Iterable, use iterator
+-
+-                      var it_name = "%s_it".printf (stmt.variable_name);
+-
+-                      var citdecl = new CCodeDeclaration (iterator_type.get_cname () + "*");
+-                      var it_method = (Method) iterable_type.scope.lookup ("iterator");
+-                      var it_ccall = new CCodeFunctionCall (new CCodeIdentifier (it_method.get_cname ()));
+-                      it_ccall.add_argument (new InstanceCast (new CCodeIdentifier (collection_backup.name), iterable_type));
+-                      var citvardecl = new CCodeVariableDeclarator.with_initializer (it_name, it_ccall);
+-                      citvardecl.line = cblock.line;
+-                      citdecl.add_declarator (citvardecl);
+-                      cblock.add_statement (citdecl);
+-                      
+-                      var cbody = new CCodeBlock ();
+-
+-                      var get_method = (Method) iterator_type.scope.lookup ("get");
+-                      var get_ccall = new CCodeFunctionCall (new CCodeIdentifier (get_method.get_cname ()));
+-                      get_ccall.add_argument (new CCodeIdentifier (it_name));
+-                      CCodeExpression element_expr = get_ccall;
+-
+-                      Iterator<DataType> type_arg_it = it_method.return_type.get_type_arguments ().iterator ();
+-                      type_arg_it.next ();
+-                      var it_type = SemanticAnalyzer.get_actual_type (stmt.collection.value_type, it_method, type_arg_it.get (), stmt);
+-
+-                      element_expr = transform_expression (element_expr, it_type, stmt.type_reference);
+-
+-                      var cfrag = new CCodeFragment ();
+-                      append_temp_decl (cfrag, temp_vars);
+-                      cbody.add_statement (cfrag);
+-                      temp_vars.clear ();
+-
+-                      var cdecl = new CCodeDeclaration (stmt.type_reference.get_cname ());
+-                      var cvardecl = new CCodeVariableDeclarator.with_initializer (stmt.variable_name, element_expr);
+-                      cvardecl.line = cblock.line;
+-                      cdecl.add_declarator (cvardecl);
+-                      cbody.add_statement (cdecl);
+-                      
+-                      cbody.add_statement (stmt.body.ccodenode);
+-
+-                      var next_method = (Method) iterator_type.scope.lookup ("next");
+-                      var next_ccall = new CCodeFunctionCall (new CCodeIdentifier (next_method.get_cname ()));
+-                      next_ccall.add_argument (new CCodeIdentifier (it_name));
+-
+-                      var cwhile = new CCodeWhileStatement (next_ccall, cbody);
+-                      cwhile.line = cblock.line;
+-                      cblock.add_statement (cwhile);
+-              }
+-
+-              foreach (LocalVariable local in stmt.get_local_variables ()) {
+-                      if (requires_destroy (local.variable_type)) {
+-                              var ma = new MemberAccess.simple (local.name);
+-                              ma.symbol_reference = local;
+-                              var cunref = new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier (get_variable_cname (local.name)), local.variable_type, ma));
+-                              cunref.line = cblock.line;
+-                              cblock.add_statement (cunref);
+-                      }
+-              }
+-      }
+-
+-      public override void visit_break_statement (BreakStatement stmt) {
+-              stmt.ccodenode = new CCodeBreakStatement ();
+-
+-              create_local_free (stmt, true);
+-      }
+-
+-      public override void visit_continue_statement (ContinueStatement stmt) {
+-              stmt.ccodenode = new CCodeContinueStatement ();
+-
+-              create_local_free (stmt, true);
+-      }
+-
+       public void append_local_free (Symbol sym, CCodeFragment cfrag, bool stop_at_loop) {
+               var b = (Block) sym;
+@@ -2661,7 +1889,7 @@
+               }
+       }
+-      private void create_local_free (CodeNode stmt, bool stop_at_loop = false) {
++      public void create_local_free (CodeNode stmt, bool stop_at_loop = false) {
+               var cfrag = new CCodeFragment ();
+       
+               append_local_free (current_symbol, cfrag, stop_at_loop);
+@@ -2992,7 +2220,7 @@
+               return true;
+       }
+-      private CCodeExpression? get_ref_cexpression (DataType expression_type, CCodeExpression cexpr, Expression? expr, CodeNode node) {
++      public CCodeExpression? get_ref_cexpression (DataType expression_type, CCodeExpression cexpr, Expression? expr, CodeNode node) {
+               if (expression_type is ValueType && !expression_type.nullable) {
+                       // normal value type, no null check
+                       // (copy (&expr, &temp), temp)
+@@ -3785,7 +3013,7 @@
+               return cexpr;
+       }
+-      private CCodeExpression get_implicit_cast_expression (CCodeExpression source_cexpr, DataType? expression_type, DataType? target_type, Expression? expr = null) {
++      public virtual CCodeExpression get_implicit_cast_expression (CCodeExpression source_cexpr, DataType? expression_type, DataType? target_type, Expression? expr = null) {
+               var cexpr = source_cexpr;
+               if (expression_type.data_type != null && expression_type.data_type == target_type.data_type) {
+@@ -3811,180 +3039,11 @@
+                       } else {
+                               return cexpr;
+                       }
+-              } else if (target_type is DelegateType && expression_type is MethodType) {
+-                      var dt = (DelegateType) target_type;
+-                      var mt = (MethodType) expression_type;
+-
+-                      var method = mt.method_symbol;
+-                      if (method.base_method != null) {
+-                              method = method.base_method;
+-                      } else if (method.base_interface_method != null) {
+-                              method = method.base_interface_method;
+-                      }
+-
+-                      return new CCodeIdentifier (generate_delegate_wrapper (method, dt.delegate_symbol));
+               } else {
+                       return cexpr;
+               }
+       }
+-      private string generate_delegate_wrapper (Method m, Delegate d) {
+-              string delegate_name;
+-              var sig = d.parent_symbol as Signal;
+-              var dynamic_sig = sig as DynamicSignal;
+-              if (dynamic_sig != null) {
+-                      delegate_name = head.get_dynamic_signal_cname (dynamic_sig);
+-              } else if (sig != null) {
+-                      delegate_name = sig.parent_symbol.get_lower_case_cprefix () + sig.get_cname ();
+-              } else {
+-                      delegate_name = Symbol.camel_case_to_lower_case (d.get_cname ());
+-              }
+-
+-              string wrapper_name = "_%s_%s".printf (m.get_cname (), delegate_name);
+-
+-              if (!add_wrapper (wrapper_name)) {
+-                      // wrapper already defined
+-                      return wrapper_name;
+-              }
+-
+-              // declaration
+-
+-              var function = new CCodeFunction (wrapper_name, m.return_type.get_cname ());
+-              function.modifiers = CCodeModifiers.STATIC;
+-              m.ccodenode = function;
+-
+-              var cparam_map = new HashMap<int,CCodeFormalParameter> (direct_hash, direct_equal);
+-
+-              if (d.has_target) {
+-                      var cparam = new CCodeFormalParameter ("self", "gpointer");
+-                      cparam_map.set (get_param_pos (d.cinstance_parameter_position), cparam);
+-              }
+-
+-              var d_params = d.get_parameters ();
+-              foreach (FormalParameter param in d_params) {
+-                      // ensure that C code node has been generated
+-                      param.accept (codegen);
+-
+-                      cparam_map.set (get_param_pos (param.cparameter_position), (CCodeFormalParameter) param.ccodenode);
+-
+-                      // handle array parameters
+-                      if (!param.no_array_length && param.parameter_type is ArrayType) {
+-                              var array_type = (ArrayType) param.parameter_type;
+-                              
+-                              var length_ctype = "int";
+-                              if (param.direction != ParameterDirection.IN) {
+-                                      length_ctype = "int*";
+-                              }
+-                              
+-                              for (int dim = 1; dim <= array_type.rank; dim++) {
+-                                      var cparam = new CCodeFormalParameter (head.get_array_length_cname (param.name, dim), length_ctype);
+-                                      cparam_map.set (get_param_pos (param.carray_length_parameter_position + 0.01 * dim), cparam);
+-                              }
+-                      }
+-
+-              }
+-
+-              if (m.get_error_types ().size > 0) {
+-                      var cparam = new CCodeFormalParameter ("error", "GError**");
+-                      cparam_map.set (get_param_pos (-1), cparam);
+-              }
+-
+-              // append C parameters in the right order
+-              int last_pos = -1;
+-              int min_pos;
+-              while (true) {
+-                      min_pos = -1;
+-                      foreach (int pos in cparam_map.get_keys ()) {
+-                              if (pos > last_pos && (min_pos == -1 || pos < min_pos)) {
+-                                      min_pos = pos;
+-                              }
+-                      }
+-                      if (min_pos == -1) {
+-                              break;
+-                      }
+-                      function.add_parameter (cparam_map.get (min_pos));
+-                      last_pos = min_pos;
+-              }
+-
+-
+-              // definition
+-
+-              var carg_map = new HashMap<int,CCodeExpression> (direct_hash, direct_equal);
+-
+-              int i = 0;
+-              if (m.binding == MemberBinding.INSTANCE) {
+-                      CCodeExpression arg;
+-                      if (d.has_target) {
+-                              arg = new CCodeIdentifier ("self");
+-                      } else {
+-                              // use first delegate parameter as instance
+-                              arg = new CCodeIdentifier ((d_params.get (0).ccodenode as CCodeFormalParameter).name);
+-                              i = 1;
+-                      }
+-                      carg_map.set (get_param_pos (m.cinstance_parameter_position), arg);
+-              }
+-
+-              foreach (FormalParameter param in m.get_parameters ()) {
+-                      CCodeExpression arg;
+-                      arg = new CCodeIdentifier ((d_params.get (i).ccodenode as CCodeFormalParameter).name);
+-                      carg_map.set (get_param_pos (param.cparameter_position), arg);
+-
+-                      // handle array arguments
+-                      if (!param.no_array_length && param.parameter_type is ArrayType) {
+-                              var array_type = (ArrayType) param.parameter_type;
+-                              for (int dim = 1; dim <= array_type.rank; dim++) {
+-                                      CCodeExpression clength;
+-                                      if (d_params.get (i).no_array_length) {
+-                                              clength = new CCodeConstant ("-1");
+-                                      } else {
+-                                              clength = new CCodeIdentifier (head.get_array_length_cname (d_params.get (i).name, dim));
+-                                      }
+-                                      carg_map.set (get_param_pos (param.carray_length_parameter_position + 0.01 * dim), clength);
+-                              }
+-                      }
+-
+-                      i++;
+-              }
+-
+-              if (m.get_error_types ().size > 0) {
+-                      carg_map.set (get_param_pos (-1), new CCodeIdentifier ("error"));
+-              }
+-
+-              var ccall = new CCodeFunctionCall (new CCodeIdentifier (m.get_cname ()));
+-
+-              // append C arguments in the right order
+-              last_pos = -1;
+-              while (true) {
+-                      min_pos = -1;
+-                      foreach (int pos in carg_map.get_keys ()) {
+-                              if (pos > last_pos && (min_pos == -1 || pos < min_pos)) {
+-                                      min_pos = pos;
+-                              }
+-                      }
+-                      if (min_pos == -1) {
+-                              break;
+-                      }
+-                      ccall.add_argument (carg_map.get (min_pos));
+-                      last_pos = min_pos;
+-              }
+-
+-              var block = new CCodeBlock ();
+-              if (m.return_type is VoidType) {
+-                      block.add_statement (new CCodeExpressionStatement (ccall));
+-              } else {
+-                      block.add_statement (new CCodeReturnStatement (ccall));
+-              }
+-
+-              // append to file
+-
+-              source_type_member_declaration.append (function.copy ());
+-
+-              function.block = block;
+-              source_type_member_definition.append (function);
+-
+-              return wrapper_name;
+-      }
+-
+       public CCodeFunctionCall get_property_set_call (Property prop, MemberAccess ma, CCodeExpression cexpr) {
+               if (ma.inner is BaseAccess) {
+                       if (prop.base_property != null) {
+Index: gobject/valaccodedelegatemodule.vala
+===================================================================
+--- gobject/valaccodedelegatemodule.vala       (revision 1971)
++++ gobject/valaccodedelegatemodule.vala       (revision 2004)
+@@ -21,7 +21,7 @@
+  *    Raffaele Sandrini <raffaele@sandrini.ch>
+  */
+-using GLib;
++using Gee;
+ /**
+  * The link between an assignment and generated code.
+@@ -166,4 +166,179 @@
+       public override string get_delegate_target_destroy_notify_cname (string delegate_cname) {
+               return "%s_target_destroy_notify".printf (delegate_cname);
+       }
++
++      public override CCodeExpression get_implicit_cast_expression (CCodeExpression source_cexpr, DataType? expression_type, DataType? target_type, Expression? expr = null) {
++              if (target_type is DelegateType && expression_type is MethodType) {
++                      var dt = (DelegateType) target_type;
++                      var mt = (MethodType) expression_type;
++
++                      var method = mt.method_symbol;
++                      if (method.base_method != null) {
++                              method = method.base_method;
++                      } else if (method.base_interface_method != null) {
++                              method = method.base_interface_method;
++                      }
++
++                      return new CCodeIdentifier (generate_delegate_wrapper (method, dt.delegate_symbol));
++              } else {
++                      return base.get_implicit_cast_expression (source_cexpr, expression_type, target_type, expr);
++              }
++      }
++
++      private string generate_delegate_wrapper (Method m, Delegate d) {
++              string delegate_name;
++              var sig = d.parent_symbol as Signal;
++              var dynamic_sig = sig as DynamicSignal;
++              if (dynamic_sig != null) {
++                      delegate_name = head.get_dynamic_signal_cname (dynamic_sig);
++              } else if (sig != null) {
++                      delegate_name = sig.parent_symbol.get_lower_case_cprefix () + sig.get_cname ();
++              } else {
++                      delegate_name = Symbol.camel_case_to_lower_case (d.get_cname ());
++              }
++
++              string wrapper_name = "_%s_%s".printf (m.get_cname (), delegate_name);
++
++              if (!add_wrapper (wrapper_name)) {
++                      // wrapper already defined
++                      return wrapper_name;
++              }
++
++              // declaration
++
++              var function = new CCodeFunction (wrapper_name, m.return_type.get_cname ());
++              function.modifiers = CCodeModifiers.STATIC;
++              m.ccodenode = function;
++
++              var cparam_map = new HashMap<int,CCodeFormalParameter> (direct_hash, direct_equal);
++
++              if (d.has_target) {
++                      var cparam = new CCodeFormalParameter ("self", "gpointer");
++                      cparam_map.set (get_param_pos (d.cinstance_parameter_position), cparam);
++              }
++
++              var d_params = d.get_parameters ();
++              foreach (FormalParameter param in d_params) {
++                      // ensure that C code node has been generated
++                      param.accept (codegen);
++
++                      cparam_map.set (get_param_pos (param.cparameter_position), (CCodeFormalParameter) param.ccodenode);
++
++                      // handle array parameters
++                      if (!param.no_array_length && param.parameter_type is ArrayType) {
++                              var array_type = (ArrayType) param.parameter_type;
++                              
++                              var length_ctype = "int";
++                              if (param.direction != ParameterDirection.IN) {
++                                      length_ctype = "int*";
++                              }
++                              
++                              for (int dim = 1; dim <= array_type.rank; dim++) {
++                                      var cparam = new CCodeFormalParameter (head.get_array_length_cname (param.name, dim), length_ctype);
++                                      cparam_map.set (get_param_pos (param.carray_length_parameter_position + 0.01 * dim), cparam);
++                              }
++                      }
++
++              }
++
++              if (m.get_error_types ().size > 0) {
++                      var cparam = new CCodeFormalParameter ("error", "GError**");
++                      cparam_map.set (get_param_pos (-1), cparam);
++              }
++
++              // append C parameters in the right order
++              int last_pos = -1;
++              int min_pos;
++              while (true) {
++                      min_pos = -1;
++                      foreach (int pos in cparam_map.get_keys ()) {
++                              if (pos > last_pos && (min_pos == -1 || pos < min_pos)) {
++                                      min_pos = pos;
++                              }
++                      }
++                      if (min_pos == -1) {
++                              break;
++                      }
++                      function.add_parameter (cparam_map.get (min_pos));
++                      last_pos = min_pos;
++              }
++
++
++              // definition
++
++              var carg_map = new HashMap<int,CCodeExpression> (direct_hash, direct_equal);
++
++              int i = 0;
++              if (m.binding == MemberBinding.INSTANCE) {
++                      CCodeExpression arg;
++                      if (d.has_target) {
++                              arg = new CCodeIdentifier ("self");
++                      } else {
++                              // use first delegate parameter as instance
++                              arg = new CCodeIdentifier ((d_params.get (0).ccodenode as CCodeFormalParameter).name);
++                              i = 1;
++                      }
++                      carg_map.set (get_param_pos (m.cinstance_parameter_position), arg);
++              }
++
++              foreach (FormalParameter param in m.get_parameters ()) {
++                      CCodeExpression arg;
++                      arg = new CCodeIdentifier ((d_params.get (i).ccodenode as CCodeFormalParameter).name);
++                      carg_map.set (get_param_pos (param.cparameter_position), arg);
++
++                      // handle array arguments
++                      if (!param.no_array_length && param.parameter_type is ArrayType) {
++                              var array_type = (ArrayType) param.parameter_type;
++                              for (int dim = 1; dim <= array_type.rank; dim++) {
++                                      CCodeExpression clength;
++                                      if (d_params.get (i).no_array_length) {
++                                              clength = new CCodeConstant ("-1");
++                                      } else {
++                                              clength = new CCodeIdentifier (head.get_array_length_cname (d_params.get (i).name, dim));
++                                      }
++                                      carg_map.set (get_param_pos (param.carray_length_parameter_position + 0.01 * dim), clength);
++                              }
++                      }
++
++                      i++;
++              }
++
++              if (m.get_error_types ().size > 0) {
++                      carg_map.set (get_param_pos (-1), new CCodeIdentifier ("error"));
++              }
++
++              var ccall = new CCodeFunctionCall (new CCodeIdentifier (m.get_cname ()));
++
++              // append C arguments in the right order
++              last_pos = -1;
++              while (true) {
++                      min_pos = -1;
++                      foreach (int pos in carg_map.get_keys ()) {
++                              if (pos > last_pos && (min_pos == -1 || pos < min_pos)) {
++                                      min_pos = pos;
++                              }
++                      }
++                      if (min_pos == -1) {
++                              break;
++                      }
++                      ccall.add_argument (carg_map.get (min_pos));
++                      last_pos = min_pos;
++              }
++
++              var block = new CCodeBlock ();
++              if (m.return_type is VoidType) {
++                      block.add_statement (new CCodeExpressionStatement (ccall));
++              } else {
++                      block.add_statement (new CCodeReturnStatement (ccall));
++              }
++
++              // append to file
++
++              source_type_member_declaration.append (function.copy ());
++
++              function.block = block;
++              source_type_member_definition.append (function);
++
++              return wrapper_name;
++      }
+ }
+Index: gobject/valaccodearraymodule.vala
+===================================================================
+--- gobject/valaccodearraymodule.vala  (revision 1971)
++++ gobject/valaccodearraymodule.vala  (revision 2004)
+@@ -28,6 +28,8 @@
+  * The link between an assignment and generated code.
+  */
+ public class Vala.CCodeArrayModule : CCodeInvocationExpressionModule {
++      private int next_array_dup_id = 0;
++
+       public CCodeArrayModule (CCodeGenerator codegen, CCodeModule? next) {
+               base (codegen, next);
+       }
+@@ -280,26 +282,6 @@
+                       get_ccall.add_argument (cindex);
+                       expr.ccodenode = convert_from_generic_pointer (get_ccall, expr.value_type);
+-              } else if (expr.container is MemberAccess && expr.container.symbol_reference is Signal) {
+-                      // should be moved to the GSignal module
+-
+-                      // detailed signal emission
+-                      var sig = (Signal) expr.symbol_reference;
+-                      var ma = (MemberAccess) expr.container;
+-
+-                      var detail_expr = expr.get_indices ().get (0) as StringLiteral;
+-                      string signal_detail = detail_expr.eval ();
+-                      
+-                      var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_emit_by_name"));
+-
+-                      // FIXME: use C cast if debugging disabled
+-                      var ccast = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT"));
+-                      ccast.add_argument ((CCodeExpression) ma.inner.ccodenode);
+-                      ccall.add_argument (ccast);
+-
+-                      ccall.add_argument (sig.get_canonical_cconstant (signal_detail));
+-                      
+-                      expr.ccodenode = ccall;
+               } else {
+                       // access to element in an array
+                       for (int i = 1; i < rank; i++) {
+@@ -416,4 +398,84 @@
+               source_type_member_definition.append (fun);
+       }
++
++      public override CCodeExpression? get_dup_func_expression (DataType type, SourceReference? source_reference) {
++              if (type is ArrayType) {
++                      return new CCodeIdentifier (generate_array_dup_wrapper ((ArrayType) type));
++              } else {
++                      return base.get_dup_func_expression (type, source_reference);
++              }
++      }
++
++      string generate_array_dup_wrapper (ArrayType array_type) {
++              string dup_func = "_vala_array_dup%d".printf (++next_array_dup_id);
++
++              if (!add_wrapper (dup_func)) {
++                      // wrapper already defined
++                      return dup_func;
++              }
++
++              // declaration
++
++              var function = new CCodeFunction (dup_func, array_type.get_cname ());
++              function.modifiers = CCodeModifiers.STATIC;
++
++              function.add_parameter (new CCodeFormalParameter ("self", array_type.get_cname ()));
++              // total length over all dimensions
++              function.add_parameter (new CCodeFormalParameter ("length", "int"));
++
++              // definition
++
++              var block = new CCodeBlock ();
++
++              if (requires_copy (array_type.element_type)) {
++                      var old_temp_vars = temp_vars;
++
++                      var cdecl = new CCodeDeclaration (array_type.get_cname ());
++                      var cvardecl = new CCodeVariableDeclarator ("result");
++                      cdecl.add_declarator (cvardecl);
++                      var gnew = new CCodeFunctionCall (new CCodeIdentifier ("g_new0"));
++                      gnew.add_argument (new CCodeIdentifier (array_type.element_type.get_cname ()));
++                      gnew.add_argument (new CCodeIdentifier ("length"));
++                      cvardecl.initializer = gnew;
++                      block.add_statement (cdecl);
++
++                      var idx_decl = new CCodeDeclaration ("int");
++                      idx_decl.add_declarator (new CCodeVariableDeclarator ("i"));
++                      block.add_statement (idx_decl);
++
++                      var loop_body = new CCodeBlock ();
++                      loop_body.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeElementAccess (new CCodeIdentifier ("result"), new CCodeIdentifier ("i")), get_ref_cexpression (array_type.element_type, new CCodeElementAccess (new CCodeIdentifier ("self"), new CCodeIdentifier ("i")), null, array_type))));
++
++                      var cfor = new CCodeForStatement (new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, new CCodeIdentifier ("i"), new CCodeIdentifier ("length")), loop_body);
++                      cfor.add_initializer (new CCodeAssignment (new CCodeIdentifier ("i"), new CCodeConstant ("0")));
++                      cfor.add_iterator (new CCodeUnaryExpression (CCodeUnaryOperator.POSTFIX_INCREMENT, new CCodeIdentifier ("i")));
++                      block.add_statement (cfor);
++
++                      block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("result")));
++
++                      var cfrag = new CCodeFragment ();
++                      append_temp_decl (cfrag, temp_vars);
++                      block.add_statement (cfrag);
++                      temp_vars = old_temp_vars;
++              } else {
++                      var dup_call = new CCodeFunctionCall (new CCodeIdentifier ("g_memdup"));
++                      dup_call.add_argument (new CCodeIdentifier ("self"));
++
++                      var sizeof_call = new CCodeFunctionCall (new CCodeIdentifier ("sizeof"));
++                      sizeof_call.add_argument (new CCodeIdentifier (array_type.element_type.get_cname ()));
++                      dup_call.add_argument (new CCodeBinaryExpression (CCodeBinaryOperator.MUL, new CCodeIdentifier ("length"), sizeof_call));
++
++                      block.add_statement (new CCodeReturnStatement (dup_call));
++              }
++
++              // append to file
++
++              source_type_member_declaration.append (function.copy ());
++
++              function.block = block;
++              source_type_member_definition.append (function);
++
++              return dup_func;
++      }
+ }
+Index: gobject/Makefile.am
+===================================================================
+--- gobject/Makefile.am        (revision 1971)
++++ gobject/Makefile.am        (revision 2004)
+@@ -16,9 +16,8 @@
+       valaccodeassignmentmodule.vala \
+       valaccodebasemodule.vala \
+       valaccodecompiler.vala \
++      valaccodecontrolflowmodule.vala \
+       valaccodedelegatemodule.vala \
+-      valaccodedynamicpropertymodule.vala \
+-      valaccodedynamicsignalmodule.vala \
+       valaccodegenerator.vala \
+       valaccodeinvocationexpressionmodule.vala \
+       valaccodememberaccessmodule.vala \
+Index: gobject/valagobjectmodule.vala
+===================================================================
+--- gobject/valagobjectmodule.vala     (revision 1971)
++++ gobject/valagobjectmodule.vala     (revision 2004)
+@@ -24,6 +24,9 @@
+ using GLib;
+ public class Vala.GObjectModule : GTypeModule {
++      int dynamic_property_id;
++      int signal_wrapper_id;
++
+       public GObjectModule (CCodeGenerator codegen, CCodeModule? next) {
+               base (codegen, next);
+       }
+@@ -1453,5 +1456,290 @@
+               return cspec;
+       }
++
++      public override CCodeExpression get_construct_property_assignment (CCodeConstant canonical_cconstant, DataType property_type, CCodeExpression value) {
++              // this property is used as a construction parameter
++              var cpointer = new CCodeIdentifier ("__params_it");
++              
++              var ccomma = new CCodeCommaExpression ();
++              // set name in array for current parameter
++              var cnamemember = new CCodeMemberAccess.pointer (cpointer, "name");
++              var cnameassign = new CCodeAssignment (cnamemember, canonical_cconstant);
++              ccomma.append_expression (cnameassign);
++              
++              var gvaluearg = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeMemberAccess.pointer (cpointer, "value"));
++              
++              // initialize GValue in array for current parameter
++              var cvalueinit = new CCodeFunctionCall (new CCodeIdentifier ("g_value_init"));
++              cvalueinit.add_argument (gvaluearg);
++              cvalueinit.add_argument (new CCodeIdentifier (property_type.get_type_id ()));
++              ccomma.append_expression (cvalueinit);
++              
++              // set GValue for current parameter
++              var cvalueset = new CCodeFunctionCall (get_value_setter_function (property_type));
++              cvalueset.add_argument (gvaluearg);
++              cvalueset.add_argument (value);
++              ccomma.append_expression (cvalueset);
++              
++              // move pointer to next parameter in array
++              ccomma.append_expression (new CCodeUnaryExpression (CCodeUnaryOperator.POSTFIX_INCREMENT, cpointer));
++
++              return ccomma;
++      }
++
++      public override void visit_constructor (Constructor c) {
++              current_method_inner_error = false;
++              in_constructor = true;
++
++              if (c.binding == MemberBinding.CLASS || c.binding == MemberBinding.STATIC) {
++                      in_static_or_class_ctor = true;
++              }
++              c.accept_children (codegen);
++              in_static_or_class_ctor = false;
++
++              in_constructor = false;
++
++              var cl = (Class) c.parent_symbol;
++
++              if (c.binding == MemberBinding.INSTANCE) {
++                      function = new CCodeFunction ("%s_constructor".printf (cl.get_lower_case_cname (null)), "GObject *");
++                      function.modifiers = CCodeModifiers.STATIC;
++              
++                      function.add_parameter (new CCodeFormalParameter ("type", "GType"));
++                      function.add_parameter (new CCodeFormalParameter ("n_construct_properties", "guint"));
++                      function.add_parameter (new CCodeFormalParameter ("construct_properties", "GObjectConstructParam *"));
++              
++                      source_type_member_declaration.append (function.copy ());
++
++
++                      var cblock = new CCodeBlock ();
++                      var cdecl = new CCodeDeclaration ("GObject *");
++                      cdecl.add_declarator (new CCodeVariableDeclarator ("obj"));
++                      cblock.add_statement (cdecl);
++
++                      cdecl = new CCodeDeclaration ("%sClass *".printf (cl.get_cname ()));
++                      cdecl.add_declarator (new CCodeVariableDeclarator ("klass"));
++                      cblock.add_statement (cdecl);
++
++                      cdecl = new CCodeDeclaration ("GObjectClass *");
++                      cdecl.add_declarator (new CCodeVariableDeclarator ("parent_class"));
++                      cblock.add_statement (cdecl);
++
++
++                      var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_class_peek"));
++                      ccall.add_argument (new CCodeIdentifier (cl.get_type_id ()));
++                      var ccast = new CCodeFunctionCall (new CCodeIdentifier ("%s_CLASS".printf (cl.get_upper_case_cname (null))));
++                      ccast.add_argument (ccall);
++                      cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("klass"), ccast)));
++
++                      ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_class_peek_parent"));
++                      ccall.add_argument (new CCodeIdentifier ("klass"));
++                      ccast = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT_CLASS"));
++                      ccast.add_argument (ccall);
++                      cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("parent_class"), ccast)));
++
++              
++                      ccall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (new CCodeIdentifier ("parent_class"), "constructor"));
++                      ccall.add_argument (new CCodeIdentifier ("type"));
++                      ccall.add_argument (new CCodeIdentifier ("n_construct_properties"));
++                      ccall.add_argument (new CCodeIdentifier ("construct_properties"));
++                      cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("obj"), ccall)));
++
++
++                      ccall = new InstanceCast (new CCodeIdentifier ("obj"), cl);
++
++                      cdecl = new CCodeDeclaration ("%s *".printf (cl.get_cname ()));
++                      cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("self", ccall));
++              
++                      cblock.add_statement (cdecl);
++
++                      if (current_method_inner_error) {
++                              /* always separate error parameter and inner_error local variable
++                               * as error may be set to NULL but we're always interested in inner errors
++                               */
++                              var cdecl = new CCodeDeclaration ("GError *");
++                              cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("inner_error", new CCodeConstant ("NULL")));
++                              cblock.add_statement (cdecl);
++                      }
++
++
++                      cblock.add_statement (c.body.ccodenode);
++              
++                      cblock.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("obj")));
++              
++                      function.block = cblock;
++
++                      if (c.source_reference.comment != null) {
++                              source_type_member_definition.append (new CCodeComment (c.source_reference.comment));
++                      }
++                      source_type_member_definition.append (function);
++              } else if (c.binding == MemberBinding.CLASS) {
++                      // class constructor
++
++                      var base_init = new CCodeFunction ("%s_base_init".printf (cl.get_lower_case_cname (null)), "void");
++                      base_init.add_parameter (new CCodeFormalParameter ("klass", "%sClass *".printf (cl.get_cname ())));
++                      base_init.modifiers = CCodeModifiers.STATIC;
++
++                      source_type_member_declaration.append (base_init.copy ());
++
++                      var block = (CCodeBlock) c.body.ccodenode;
++                      if (current_method_inner_error) {
++                              /* always separate error parameter and inner_error local variable
++                               * as error may be set to NULL but we're always interested in inner errors
++                               */
++                              var cdecl = new CCodeDeclaration ("GError *");
++                              cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("inner_error", new CCodeConstant ("NULL")));
++                              block.prepend_statement (cdecl);
++                      }
++
++                      base_init.block = block;
++              
++                      source_type_member_definition.append (base_init);
++              } else if (c.binding == MemberBinding.STATIC) {
++                      // static class constructor
++                      // add to class_init
++
++                      if (current_method_inner_error) {
++                              /* always separate error parameter and inner_error local variable
++                               * as error may be set to NULL but we're always interested in inner errors
++                               */
++                              var cdecl = new CCodeDeclaration ("GError *");
++                              cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("inner_error", new CCodeConstant ("NULL")));
++                              class_init_fragment.append (cdecl);
++                      }
++
++                      class_init_fragment.append (c.body.ccodenode);
++              } else {
++                      Report.error (c.source_reference, "internal error: constructors must have instance, class, or static binding");
++              }
++      }
++
++      public override string get_dynamic_property_getter_cname (DynamicProperty prop) {
++              if (prop.dynamic_type.data_type == null
++                  || !prop.dynamic_type.data_type.is_subtype_of (gobject_type)) {
++                      return base.get_dynamic_property_getter_cname (prop);
++              }
++
++              string getter_cname = "_dynamic_get_%s%d".printf (prop.name, dynamic_property_id++);
++
++              var func = new CCodeFunction (getter_cname, prop.property_type.get_cname ());
++              func.modifiers |= CCodeModifiers.STATIC | CCodeModifiers.INLINE;
++
++              func.add_parameter (new CCodeFormalParameter ("obj", prop.dynamic_type.get_cname ()));
++
++              var block = new CCodeBlock ();
++              generate_gobject_property_getter_wrapper (prop, block);
++
++              // append to C source file
++              source_type_member_declaration.append (func.copy ());
++
++              func.block = block;
++              source_type_member_definition.append (func);
++
++              return getter_cname;
++      }
++
++      public override string get_dynamic_property_setter_cname (DynamicProperty prop) {
++              if (prop.dynamic_type.data_type == null
++                  || !prop.dynamic_type.data_type.is_subtype_of (gobject_type)) {
++                      return base.get_dynamic_property_setter_cname (prop);
++              }
++
++              string setter_cname = "_dynamic_set_%s%d".printf (prop.name, dynamic_property_id++);
++
++              var func = new CCodeFunction (setter_cname, "void");
++              func.modifiers |= CCodeModifiers.STATIC | CCodeModifiers.INLINE;
++
++              func.add_parameter (new CCodeFormalParameter ("obj", prop.dynamic_type.get_cname ()));
++              func.add_parameter (new CCodeFormalParameter ("value", prop.property_type.get_cname ()));
++
++              var block = new CCodeBlock ();
++              generate_gobject_property_setter_wrapper (prop, block);
++
++              // append to C source file
++              source_type_member_declaration.append (func.copy ());
++
++              func.block = block;
++              source_type_member_definition.append (func);
++
++              return setter_cname;
++      }
++
++      void generate_gobject_property_getter_wrapper (DynamicProperty node, CCodeBlock block) {
++              var cdecl = new CCodeDeclaration (node.property_type.get_cname ());
++              cdecl.add_declarator (new CCodeVariableDeclarator ("result"));
++              block.add_statement (cdecl);
++
++              var call = new CCodeFunctionCall (new CCodeIdentifier ("g_object_get"));
++              call.add_argument (new CCodeIdentifier ("obj"));
++              call.add_argument (node.get_canonical_cconstant ());
++              call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("result")));
++              call.add_argument (new CCodeConstant ("NULL"));
++
++              block.add_statement (new CCodeExpressionStatement (call));
++
++              block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("result")));
++      }
++
++      void generate_gobject_property_setter_wrapper (DynamicProperty node, CCodeBlock block) {
++              var call = new CCodeFunctionCall (new CCodeIdentifier ("g_object_set"));
++              call.add_argument (new CCodeIdentifier ("obj"));
++              call.add_argument (node.get_canonical_cconstant ());
++              call.add_argument (new CCodeIdentifier ("value"));
++              call.add_argument (new CCodeConstant ("NULL"));
++
++              block.add_statement (new CCodeExpressionStatement (call));
++      }
++
++      public override string get_dynamic_signal_cname (DynamicSignal node) {
++              return "dynamic_%s%d_".printf (node.name, signal_wrapper_id++);
++      }
++
++      public override string get_dynamic_signal_connect_wrapper_name (DynamicSignal sig) {
++              if (sig.dynamic_type.data_type == null
++                  || !sig.dynamic_type.data_type.is_subtype_of (gobject_type)) {
++                      return base.get_dynamic_signal_connect_wrapper_name (sig);
++              }
++
++              string connect_wrapper_name = "_%sconnect".printf (get_dynamic_signal_cname (sig));
++              var func = new CCodeFunction (connect_wrapper_name, "void");
++              func.add_parameter (new CCodeFormalParameter ("obj", "gpointer"));
++              func.add_parameter (new CCodeFormalParameter ("signal_name", "const char *"));
++              func.add_parameter (new CCodeFormalParameter ("handler", "GCallback"));
++              func.add_parameter (new CCodeFormalParameter ("data", "gpointer"));
++              var block = new CCodeBlock ();
++              generate_gobject_connect_wrapper (sig, block);
++
++              // append to C source file
++              source_type_member_declaration.append (func.copy ());
++
++              func.block = block;
++              source_type_member_definition.append (func);
++
++              return connect_wrapper_name;
++      }
++
++      void generate_gobject_connect_wrapper (DynamicSignal sig, CCodeBlock block) {
++              var m = (Method) sig.handler.symbol_reference;
++
++              sig.accept (codegen);
++
++              string connect_func = "g_signal_connect_object";
++              if (m.binding != MemberBinding.INSTANCE) {
++                      connect_func = "g_signal_connect";
++              }
++
++              var call = new CCodeFunctionCall (new CCodeIdentifier (connect_func));
++              call.add_argument (new CCodeIdentifier ("obj"));
++              call.add_argument (new CCodeIdentifier ("signal_name"));
++              call.add_argument (new CCodeIdentifier ("handler"));
++              call.add_argument (new CCodeIdentifier ("data"));
++
++              if (m.binding == MemberBinding.INSTANCE) {
++                      call.add_argument (new CCodeConstant ("0"));
++              }
++
++              block.add_statement (new CCodeExpressionStatement (call));
++      }
+ }
+Index: gobject/valaccodegenerator.vala
+===================================================================
+--- gobject/valaccodegenerator.vala    (revision 1971)
++++ gobject/valaccodegenerator.vala    (revision 2004)
+@@ -35,13 +35,12 @@
+               head = new CCodeBaseModule (this, head);
+               head = new CCodeStructModule (this, head);
+               head = new CCodeMethodModule (this, head);
++              head = new CCodeControlFlowModule (this, head);
+               head = new CCodeMemberAccessModule (this, head);
+               head = new CCodeAssignmentModule (this, head);
+               head = new CCodeInvocationExpressionModule (this, head);
+               head = new CCodeArrayModule (this, head);
+               head = new CCodeDelegateModule (this, head);
+-              head = new CCodeDynamicPropertyModule (this, head);
+-              head = new CCodeDynamicSignalModule (this, head);
+               head = new GErrorModule (this, head);
+               head = new GTypeModule (this, head);
+               head = new GObjectModule (this, head);
This page took 0.490853 seconds and 4 git commands to generate.