refactor emit method
authorJuerg Billeter <j@bitron.ch>
Thu, 27 Sep 2007 12:08:41 +0000 (12:08 +0000)
committerJürg Billeter <juergbi@src.gnome.org>
Thu, 27 Sep 2007 12:08:41 +0000 (12:08 +0000)
2007-09-27  Juerg Billeter  <j@bitron.ch>

* gobject/valaccodeassignmentbinding.vala: refactor emit method

svn path=/trunk/; revision=632

ChangeLog
gobject/valaccodeassignmentbinding.vala

index 592b4d6..3e059ee 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
 2007-09-27  Jürg Billeter  <j@bitron.ch>
 
+       * gobject/valaccodeassignmentbinding.vala: refactor emit method
+
+2007-09-27  Jürg Billeter  <j@bitron.ch>
+
        * vala/valacodebinding.vala, vala/valasemanticanalyzer.vala,
          gobject/Makefile.am, gobject/valaccodeassignmentbinding.vala,
          gobject/valaccodeexpressionbinding.vala,
index 2249438..5ea3e58 100644 (file)
@@ -33,350 +33,368 @@ public class Vala.CCodeAssignmentBinding : CCodeExpressionBinding {
        public CCodeAssignmentBinding (construct CodeGenerator! codegen, construct Assignment! assignment) {
        }
 
-       public override void emit () {
-               assignment.accept_children (codegen);
+       private void emit_property_assignment () {
+               var ma = assignment.left as MemberAccess;
 
-               MemberAccess ma = assignment.left as MemberAccess;
+               var prop = (Property) assignment.left.symbol_reference;
 
-               if (assignment.left.symbol_reference is Property) {
-                       var prop = (Property) assignment.left.symbol_reference;
+               if (prop.set_accessor.construction && codegen.current_type_symbol is Class && codegen.in_creation_method) {
+                       // this property is used as a construction parameter
+                       var cpointer = new CCodeIdentifier ("__params_it");
                        
-                       if (prop.set_accessor.construction && codegen.current_type_symbol is Class && codegen.in_creation_method) {
-                               // 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, prop.get_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 (prop.type_reference.data_type.get_type_id ()));
+                       ccomma.append_expression (cvalueinit);
+                       
+                       // set GValue for current parameter
+                       var cvalueset = new CCodeFunctionCall (codegen.get_value_setter_function (prop.type_reference));
+                       cvalueset.add_argument (gvaluearg);
+                       cvalueset.add_argument ((CCodeExpression) assignment.right.ccodenode);
+                       ccomma.append_expression (cvalueset);
+                       
+                       // move pointer to next parameter in array
+                       ccomma.append_expression (new CCodeUnaryExpression (CCodeUnaryOperator.POSTFIX_INCREMENT, cpointer));
+                       
+                       codenode = ccomma;
+               } else {
+                       CCodeExpression cexpr = (CCodeExpression) assignment.right.ccodenode;
+
+                       if (!prop.no_accessor_method) {
+                               cexpr = codegen.get_implicit_cast_expression (cexpr, assignment.right.static_type, prop.type_reference);
+                       }
+
+                       if (assignment.operator != AssignmentOperator.SIMPLE) {
+                               CCodeBinaryOperator cop;
+                               if (assignment.operator == AssignmentOperator.BITWISE_OR) {
+                                       cop = CCodeBinaryOperator.BITWISE_OR;
+                               } else if (assignment.operator == AssignmentOperator.BITWISE_AND) {
+                                       cop = CCodeBinaryOperator.BITWISE_AND;
+                               } else if (assignment.operator == AssignmentOperator.BITWISE_XOR) {
+                                       cop = CCodeBinaryOperator.BITWISE_XOR;
+                               } else if (assignment.operator == AssignmentOperator.ADD) {
+                                       cop = CCodeBinaryOperator.PLUS;
+                               } else if (assignment.operator == AssignmentOperator.SUB) {
+                                       cop = CCodeBinaryOperator.MINUS;
+                               } else if (assignment.operator == AssignmentOperator.MUL) {
+                                       cop = CCodeBinaryOperator.MUL;
+                               } else if (assignment.operator == AssignmentOperator.DIV) {
+                                       cop = CCodeBinaryOperator.DIV;
+                               } else if (assignment.operator == AssignmentOperator.PERCENT) {
+                                       cop = CCodeBinaryOperator.MOD;
+                               } else if (assignment.operator == AssignmentOperator.SHIFT_LEFT) {
+                                       cop = CCodeBinaryOperator.SHIFT_LEFT;
+                               } else if (assignment.operator == AssignmentOperator.SHIFT_RIGHT) {
+                                       cop = CCodeBinaryOperator.SHIFT_RIGHT;
+                               }
+                               cexpr = new CCodeBinaryExpression (cop, (CCodeExpression) assignment.left.ccodenode, new CCodeParenthesizedExpression (cexpr));
+                       }
+                       
+                       var ccall = codegen.get_property_set_call (prop, ma, cexpr);
+                       
+                       // assignments are expressions, so return the current property value, except if we're sure that it can't be used
+                       if (!(assignment.parent_node is ExpressionStatement)) {
                                var ccomma = new CCodeCommaExpression ();
-                               // set name in array for current parameter
-                               var cnamemember = new CCodeMemberAccess.pointer (cpointer, "name");
-                               var cnameassign = new CCodeAssignment (cnamemember, prop.get_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 (prop.type_reference.data_type.get_type_id ()));
-                               ccomma.append_expression (cvalueinit);
-                               
-                               // set GValue for current parameter
-                               var cvalueset = new CCodeFunctionCall (codegen.get_value_setter_function (prop.type_reference));
-                               cvalueset.add_argument (gvaluearg);
-                               cvalueset.add_argument ((CCodeExpression) assignment.right.ccodenode);
-                               ccomma.append_expression (cvalueset);
-                               
-                               // move pointer to next parameter in array
-                               ccomma.append_expression (new CCodeUnaryExpression (CCodeUnaryOperator.POSTFIX_INCREMENT, cpointer));
+                               ccomma.append_expression (ccall); // update property
+                               ccomma.append_expression ((CCodeExpression) ma.ccodenode); // current property value
                                
                                codenode = ccomma;
                        } else {
-                               CCodeExpression cexpr = (CCodeExpression) assignment.right.ccodenode;
+                               codenode = ccall;
+                       }
+               }
+       }
 
-                               if (!prop.no_accessor_method) {
-                                       cexpr = codegen.get_implicit_cast_expression (cexpr, assignment.right.static_type, prop.type_reference);
-                               }
+       private void emit_signal_assignment () {
+               var ma = assignment.left as MemberAccess;
 
-                               if (assignment.operator != AssignmentOperator.SIMPLE) {
-                                       CCodeBinaryOperator cop;
-                                       if (assignment.operator == AssignmentOperator.BITWISE_OR) {
-                                               cop = CCodeBinaryOperator.BITWISE_OR;
-                                       } else if (assignment.operator == AssignmentOperator.BITWISE_AND) {
-                                               cop = CCodeBinaryOperator.BITWISE_AND;
-                                       } else if (assignment.operator == AssignmentOperator.BITWISE_XOR) {
-                                               cop = CCodeBinaryOperator.BITWISE_XOR;
-                                       } else if (assignment.operator == AssignmentOperator.ADD) {
-                                               cop = CCodeBinaryOperator.PLUS;
-                                       } else if (assignment.operator == AssignmentOperator.SUB) {
-                                               cop = CCodeBinaryOperator.MINUS;
-                                       } else if (assignment.operator == AssignmentOperator.MUL) {
-                                               cop = CCodeBinaryOperator.MUL;
-                                       } else if (assignment.operator == AssignmentOperator.DIV) {
-                                               cop = CCodeBinaryOperator.DIV;
-                                       } else if (assignment.operator == AssignmentOperator.PERCENT) {
-                                               cop = CCodeBinaryOperator.MOD;
-                                       } else if (assignment.operator == AssignmentOperator.SHIFT_LEFT) {
-                                               cop = CCodeBinaryOperator.SHIFT_LEFT;
-                                       } else if (assignment.operator == AssignmentOperator.SHIFT_RIGHT) {
-                                               cop = CCodeBinaryOperator.SHIFT_RIGHT;
-                                       }
-                                       cexpr = new CCodeBinaryExpression (cop, (CCodeExpression) assignment.left.ccodenode, new CCodeParenthesizedExpression (cexpr));
-                               }
-                               
-                               var ccall = codegen.get_property_set_call (prop, ma, cexpr);
-                               
-                               // assignments are expressions, so return the current property value, except if we're sure that it can't be used
-                               if (!(assignment.parent_node is ExpressionStatement)) {
-                                       var ccomma = new CCodeCommaExpression ();
-                                       ccomma.append_expression (ccall); // update property
-                                       ccomma.append_expression ((CCodeExpression) ma.ccodenode); // current property value
-                                       
-                                       codenode = ccomma;
-                               } else {
-                                       codenode = ccall;
+               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 DBusSignal) {
+                               connect_func = "dbus_g_proxy_connect_signal";
+                       } else {
+                               connect_func = "g_signal_connect_object";
+                               if (!m.instance) {
+                                       connect_func = "g_signal_connect";
                                }
                        }
-               } else if (assignment.left.symbol_reference is Signal) {
-                       var sig = (Signal) assignment.left.symbol_reference;
+               } else if (assignment.operator == AssignmentOperator.SUB) {
+                       if (sig is DBusSignal) {
+                               connect_func = "dbus_g_proxy_disconnect_signal";
+                       } 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;
+               }
+
+               var ccall = new CCodeFunctionCall (new CCodeIdentifier (connect_func));
+       
+               if (ma.inner != null) {
+                       ccall.add_argument ((CCodeExpression) ma.inner.ccodenode);
+               } else {
+                       ccall.add_argument (new CCodeIdentifier ("self"));
+               }
+
+               if (!disconnect || sig is DBusSignal) {
+                       ccall.add_argument (sig.get_canonical_cconstant ());
+               } else {
+                       ccall.add_argument (new CCodeConstant ("G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA"));
+                       
+                       // get signal id
+                       var ccomma = new CCodeCommaExpression ();
+                       var temp_decl = codegen.get_temp_variable_declarator (codegen.uint_type);
+                       codegen.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 ());
+                       var decl_type = (DataType) 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)));
+                       parse_call.add_argument (new CCodeConstant ("NULL"));
+                       parse_call.add_argument (new CCodeConstant ("FALSE"));
+                       ccomma.append_expression (parse_call);
+                       ccomma.append_expression (new CCodeIdentifier (temp_decl.name));
                        
-                       var m = (Method) assignment.right.symbol_reference;
+                       ccall.add_argument (ccomma);
 
-                       string connect_func;
-                       bool disconnect = false;
+                       ccall.add_argument (new CCodeConstant ("0"));
+                       ccall.add_argument (new CCodeConstant ("NULL"));
+               }
 
-                       if (assignment.operator == AssignmentOperator.ADD) {
-                               if (sig is DBusSignal) {
-                                       connect_func = "dbus_g_proxy_connect_signal";
+               ccall.add_argument (new CCodeCastExpression (new CCodeIdentifier (m.get_cname ()), "GCallback"));
+
+               if (m.instance) {
+                       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 {
-                                       connect_func = "g_signal_connect_object";
-                                       if (!m.instance) {
-                                               connect_func = "g_signal_connect";
-                                       }
+                                       ccall.add_argument (new CCodeIdentifier ("self"));
                                }
-                       } else if (assignment.operator == AssignmentOperator.SUB) {
+                       } else if (assignment.right is LambdaExpression) {
+                               ccall.add_argument (new CCodeIdentifier ("self"));
+                       }
+                       if (!disconnect) {
                                if (sig is DBusSignal) {
-                                       connect_func = "dbus_g_proxy_disconnect_signal";
+                                       // free_data_func
+                                       ccall.add_argument (new CCodeConstant ("NULL"));
                                } else {
-                                       connect_func = "g_signal_handlers_disconnect_matched";
+                                       // connect_flags
+                                       ccall.add_argument (new CCodeConstant ("0"));
                                }
-                               disconnect = true;
-                       } else {
-                               assignment.error = true;
-                               Report.error (assignment.source_reference, "Specified compound assignment type for signals not supported.");
-                               return;
                        }
-
-                       var ccall = new CCodeFunctionCall (new CCodeIdentifier (connect_func));
+               } else {
+                       ccall.add_argument (new CCodeConstant ("NULL"));
+               }
                
-                       if (ma.inner != null) {
-                               ccall.add_argument ((CCodeExpression) ma.inner.ccodenode);
-                       } else {
-                               ccall.add_argument (new CCodeIdentifier ("self"));
+               codenode = ccall;
+               
+               if (sig is DBusSignal && !disconnect) {
+                       bool first = true;
+                       foreach (FormalParameter param in m.get_parameters ()) {
+                               if (first) {
+                                       // skip sender parameter
+                                       first = false;
+                                       continue;
+                               }
+                               sig.add_parameter (param);
                        }
 
-                       if (!disconnect || sig is DBusSignal) {
-                               ccall.add_argument (sig.get_canonical_cconstant ());
-                       } else {
-                               ccall.add_argument (new CCodeConstant ("G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA"));
-                               
-                               // get signal id
-                               var ccomma = new CCodeCommaExpression ();
-                               var temp_decl = codegen.get_temp_variable_declarator (codegen.uint_type);
-                               codegen.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 ());
-                               var decl_type = (DataType) 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)));
-                               parse_call.add_argument (new CCodeConstant ("NULL"));
-                               parse_call.add_argument (new CCodeConstant ("FALSE"));
-                               ccomma.append_expression (parse_call);
-                               ccomma.append_expression (new CCodeIdentifier (temp_decl.name));
-                               
-                               ccall.add_argument (ccomma);
+                       sig.accept (codegen);
 
-                               ccall.add_argument (new CCodeConstant ("0"));
-                               ccall.add_argument (new CCodeConstant ("NULL"));
-                       }
+                       // FIXME should only be done once per marshaller
+                       var register_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_object_register_marshaller"));
+                       register_call.add_argument (new CCodeIdentifier (codegen.get_signal_marshaller_function (sig)));
+                       register_call.add_argument (new CCodeIdentifier ("G_TYPE_NONE"));
 
-                       ccall.add_argument (new CCodeCastExpression (new CCodeIdentifier (m.get_cname ()), "GCallback"));
-
-                       if (m.instance) {
-                               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) {
-                                       if (sig is DBusSignal) {
-                                               // free_data_func
-                                               ccall.add_argument (new CCodeConstant ("NULL"));
-                                       } else {
-                                               // connect_flags
-                                               ccall.add_argument (new CCodeConstant ("0"));
-                                       }
-                               }
+                       var add_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_add_signal"));
+                       if (ma.inner != null) {
+                               add_call.add_argument ((CCodeExpression) ma.inner.ccodenode);
                        } else {
-                               ccall.add_argument (new CCodeConstant ("NULL"));
+                               add_call.add_argument (new CCodeIdentifier ("self"));
                        }
-                       
-                       codenode = ccall;
-                       
-                       if (sig is DBusSignal && !disconnect) {
-                               bool first = true;
-                               foreach (FormalParameter param in m.get_parameters ()) {
-                                       if (first) {
-                                               // skip sender parameter
-                                               first = false;
-                                               continue;
-                                       }
-                                       sig.add_parameter (param);
+                       add_call.add_argument (sig.get_canonical_cconstant ());
+
+                       first = true;
+                       foreach (FormalParameter param in m.get_parameters ()) {
+                               if (first) {
+                                       // skip sender parameter
+                                       first = false;
+                                       continue;
                                }
+                               if (param.type_reference.data_type is Array && ((Array) param.type_reference.data_type).element_type != codegen.string_type.data_type) {
+                                       var array = (Array) param.type_reference.data_type;
+                                       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.element_type.get_type_id ()));
+                                       register_call.add_argument (carray_type);
+                                       add_call.add_argument (carray_type);
+                               } else {
+                                       register_call.add_argument (new CCodeIdentifier (param.type_reference.data_type.get_type_id ()));
+                                       add_call.add_argument (new CCodeIdentifier (param.type_reference.data_type.get_type_id ()));
+                               }
+                       }
+                       register_call.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
+                       add_call.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
+
+                       var ccomma = new CCodeCommaExpression ();
+                       ccomma.append_expression (register_call);
+                       ccomma.append_expression (add_call);
+                       ccomma.append_expression (ccall);
+                       codenode = ccomma;
+               }
+       }
 
-                               sig.accept (codegen);
+       private void emit_non_array_element_access () {
+               // custom element access
+               CCodeExpression rhs = (CCodeExpression) assignment.right.ccodenode;
 
-                               // FIXME should only be done once per marshaller
-                               var register_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_object_register_marshaller"));
-                               register_call.add_argument (new CCodeIdentifier (codegen.get_signal_marshaller_function (sig)));
-                               register_call.add_argument (new CCodeIdentifier ("G_TYPE_NONE"));
+               rhs = codegen.get_implicit_cast_expression (rhs, assignment.right.static_type, assignment.left.static_type);
 
-                               var add_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_add_signal"));
-                               if (ma.inner != null) {
-                                       add_call.add_argument ((CCodeExpression) ma.inner.ccodenode);
-                               } else {
-                                       add_call.add_argument (new CCodeIdentifier ("self"));
-                               }
-                               add_call.add_argument (sig.get_canonical_cconstant ());
-
-                               first = true;
-                               foreach (FormalParameter param in m.get_parameters ()) {
-                                       if (first) {
-                                               // skip sender parameter
-                                               first = false;
-                                               continue;
-                                       }
-                                       if (param.type_reference.data_type is Array && ((Array) param.type_reference.data_type).element_type != codegen.string_type.data_type) {
-                                               var array = (Array) param.type_reference.data_type;
-                                               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.element_type.get_type_id ()));
-                                               register_call.add_argument (carray_type);
-                                               add_call.add_argument (carray_type);
-                                       } else {
-                                               register_call.add_argument (new CCodeIdentifier (param.type_reference.data_type.get_type_id ()));
-                                               add_call.add_argument (new CCodeIdentifier (param.type_reference.data_type.get_type_id ()));
-                                       }
-                               }
-                               register_call.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
-                               add_call.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
+               var expr = (ElementAccess) assignment.left;
+               var container_type = expr.container.static_type.data_type;
+               Collection<Expression> indices = expr.get_indices ();
+               Iterator<Expression> indices_it = indices.iterator ();
+               indices_it.next ();
 
-                               var ccomma = new CCodeCommaExpression ();
-                               ccomma.append_expression (register_call);
-                               ccomma.append_expression (add_call);
-                               ccomma.append_expression (ccall);
-                               codenode = ccomma;
-                       }
-               } else if (assignment.left is ElementAccess && !(((ElementAccess) assignment.left).container.static_type.data_type is Array)) {
-                       // custom element access
-                       CCodeExpression rhs = (CCodeExpression) assignment.right.ccodenode;
-
-                       rhs = codegen.get_implicit_cast_expression (rhs, assignment.right.static_type, assignment.left.static_type);
-
-                       var expr = (ElementAccess) assignment.left;
-                       var container_type = expr.container.static_type.data_type;
-                       Collection<Expression> indices = expr.get_indices ();
-                       Iterator<Expression> indices_it = indices.iterator ();
-                       indices_it.next ();
-
-                       var ccontainer = (CCodeExpression) expr.container.ccodenode;
-                       var cindex = (CCodeExpression) indices_it.get ().ccodenode;
-
-                       if (container_type != null && codegen.list_type != null && codegen.map_type != null &&
-                           (container_type.is_subtype_of (codegen.list_type) || container_type.is_subtype_of (codegen.map_type))) {
-                               var set_method = (Method) container_type.scope.lookup ("set");
-                               Collection<FormalParameter> set_params = set_method.get_parameters ();
-                               Iterator<FormalParameter> set_params_it = set_params.iterator ();
-                               set_params_it.next ();
-                               var set_param = set_params_it.get ();
-
-                               if (set_param.type_reference.type_parameter != null) {
-                                       var index_type = SemanticAnalyzer.get_actual_type (expr.container.static_type, set_method, set_param.type_reference, assignment);
-                                       cindex = codegen.convert_to_generic_pointer (cindex, index_type);
-                               }
+               var ccontainer = (CCodeExpression) expr.container.ccodenode;
+               var cindex = (CCodeExpression) indices_it.get ().ccodenode;
 
-                               var set_ccall = new CCodeFunctionCall (new CCodeIdentifier (set_method.get_cname ()));
-                               set_ccall.add_argument (new CCodeCastExpression (ccontainer, container_type.get_cname () + "*"));
-                               set_ccall.add_argument (cindex);
-                               set_ccall.add_argument (codegen.convert_to_generic_pointer (rhs, expr.static_type));
+               if (container_type != null && codegen.list_type != null && codegen.map_type != null &&
+                   (container_type.is_subtype_of (codegen.list_type) || container_type.is_subtype_of (codegen.map_type))) {
+                       var set_method = (Method) container_type.scope.lookup ("set");
+                       Collection<FormalParameter> set_params = set_method.get_parameters ();
+                       Iterator<FormalParameter> set_params_it = set_params.iterator ();
+                       set_params_it.next ();
+                       var set_param = set_params_it.get ();
 
-                               codenode = set_ccall;
-                       } else {
-                               Report.error (assignment.source_reference, "internal error: unsupported element access");
-                               assignment.error = true;
+                       if (set_param.type_reference.type_parameter != null) {
+                               var index_type = SemanticAnalyzer.get_actual_type (expr.container.static_type, set_method, set_param.type_reference, assignment);
+                               cindex = codegen.convert_to_generic_pointer (cindex, index_type);
                        }
+
+                       var set_ccall = new CCodeFunctionCall (new CCodeIdentifier (set_method.get_cname ()));
+                       set_ccall.add_argument (new CCodeCastExpression (ccontainer, container_type.get_cname () + "*"));
+                       set_ccall.add_argument (cindex);
+                       set_ccall.add_argument (codegen.convert_to_generic_pointer (rhs, expr.static_type));
+
+                       codenode = set_ccall;
                } else {
-                       CCodeExpression rhs = (CCodeExpression) assignment.right.ccodenode;
+                       Report.error (assignment.source_reference, "internal error: unsupported element access");
+                       assignment.error = true;
+               }
+       }
+
+       private void emit_simple_assignment () {
+               CCodeExpression rhs = (CCodeExpression) assignment.right.ccodenode;
 
-                       rhs = codegen.get_implicit_cast_expression (rhs, assignment.right.static_type, assignment.left.static_type);
+               rhs = codegen.get_implicit_cast_expression (rhs, assignment.right.static_type, assignment.left.static_type);
 
-                       bool unref_old = (codegen.memory_management && assignment.left.static_type.takes_ownership);
-                       bool array = false;
-                       if (assignment.left.static_type.data_type is Array) {
-                               array = !(codegen.get_array_length_cexpression (assignment.left, 1) is CCodeConstant);
+               bool unref_old = (codegen.memory_management && assignment.left.static_type.takes_ownership);
+               bool array = false;
+               if (assignment.left.static_type.data_type is Array) {
+                       array = !(codegen.get_array_length_cexpression (assignment.left, 1) is CCodeConstant);
+               }
+               
+               if (unref_old || array) {
+                       var ccomma = new CCodeCommaExpression ();
+                       
+                       var temp_decl = codegen.get_temp_variable_declarator (assignment.left.static_type);
+                       codegen.temp_vars.insert (0, temp_decl);
+                       ccomma.append_expression (new CCodeAssignment (new CCodeIdentifier (temp_decl.name), rhs));
+                       if (unref_old) {
+                               /* unref old value */
+                               ccomma.append_expression (codegen.get_unref_expression ((CCodeExpression) assignment.left.ccodenode, assignment.left.static_type, assignment.left));
                        }
                        
-                       if (unref_old || array) {
-                               var ccomma = new CCodeCommaExpression ();
-                               
-                               var temp_decl = codegen.get_temp_variable_declarator (assignment.left.static_type);
-                               codegen.temp_vars.insert (0, temp_decl);
-                               ccomma.append_expression (new CCodeAssignment (new CCodeIdentifier (temp_decl.name), rhs));
-                               if (unref_old) {
-                                       /* unref old value */
-                                       ccomma.append_expression (codegen.get_unref_expression ((CCodeExpression) assignment.left.ccodenode, assignment.left.static_type, assignment.left));
-                               }
-                               
-                               if (array) {
-                                       var arr = (Array) assignment.left.static_type.data_type;
-                                       for (int dim = 1; dim <= arr.rank; dim++) {
-                                               var lhs_array_len = codegen.get_array_length_cexpression (assignment.left, dim);
-                                               var rhs_array_len = codegen.get_array_length_cexpression (assignment.right, dim);
-                                               ccomma.append_expression (new CCodeAssignment (lhs_array_len, rhs_array_len));
-                                       }
+                       if (array) {
+                               var arr = (Array) assignment.left.static_type.data_type;
+                               for (int dim = 1; dim <= arr.rank; dim++) {
+                                       var lhs_array_len = codegen.get_array_length_cexpression (assignment.left, dim);
+                                       var rhs_array_len = codegen.get_array_length_cexpression (assignment.right, dim);
+                                       ccomma.append_expression (new CCodeAssignment (lhs_array_len, rhs_array_len));
                                }
-                               
-                               ccomma.append_expression (new CCodeIdentifier (temp_decl.name));
-                               
-                               rhs = ccomma;
                        }
                        
-                       var cop = CCodeAssignmentOperator.SIMPLE;
-                       if (assignment.operator == AssignmentOperator.BITWISE_OR) {
-                               cop = CCodeAssignmentOperator.BITWISE_OR;
-                       } else if (assignment.operator == AssignmentOperator.BITWISE_AND) {
-                               cop = CCodeAssignmentOperator.BITWISE_AND;
-                       } else if (assignment.operator == AssignmentOperator.BITWISE_XOR) {
-                               cop = CCodeAssignmentOperator.BITWISE_XOR;
-                       } else if (assignment.operator == AssignmentOperator.ADD) {
-                               cop = CCodeAssignmentOperator.ADD;
-                       } else if (assignment.operator == AssignmentOperator.SUB) {
-                               cop = CCodeAssignmentOperator.SUB;
-                       } else if (assignment.operator == AssignmentOperator.MUL) {
-                               cop = CCodeAssignmentOperator.MUL;
-                       } else if (assignment.operator == AssignmentOperator.DIV) {
-                               cop = CCodeAssignmentOperator.DIV;
-                       } else if (assignment.operator == AssignmentOperator.PERCENT) {
-                               cop = CCodeAssignmentOperator.PERCENT;
-                       } else if (assignment.operator == AssignmentOperator.SHIFT_LEFT) {
-                               cop = CCodeAssignmentOperator.SHIFT_LEFT;
-                       } else if (assignment.operator == AssignmentOperator.SHIFT_RIGHT) {
-                               cop = CCodeAssignmentOperator.SHIFT_RIGHT;
-                       }
+                       ccomma.append_expression (new CCodeIdentifier (temp_decl.name));
+                       
+                       rhs = ccomma;
+               }
                
-                       codenode = new CCodeAssignment ((CCodeExpression) assignment.left.ccodenode, rhs, cop);
-
-                       if (unref_old && assignment.left.ccodenode is CCodeElementAccess) {
-                               // ensure that index expression in element access doesn't get evaluated more than once
-                               // except when it's a simple expression
-                               var cea = (CCodeElementAccess) assignment.left.ccodenode;
-                               if (!(cea.index is CCodeConstant || cea.index is CCodeIdentifier)) {
-                                       var index_temp_decl = codegen.get_temp_variable_declarator (codegen.int_type);
-                                       codegen.temp_vars.insert (0, index_temp_decl);
-                                       
-                                       var ccomma = new CCodeCommaExpression ();
-                                       ccomma.append_expression (new CCodeAssignment (new CCodeIdentifier (index_temp_decl.name), cea.index));
-                                       ccomma.append_expression (codenode);
-
-                                       cea.index = new CCodeIdentifier (index_temp_decl.name);
-                                       
-                                       codenode = ccomma;
-                               }
+               var cop = CCodeAssignmentOperator.SIMPLE;
+               if (assignment.operator == AssignmentOperator.BITWISE_OR) {
+                       cop = CCodeAssignmentOperator.BITWISE_OR;
+               } else if (assignment.operator == AssignmentOperator.BITWISE_AND) {
+                       cop = CCodeAssignmentOperator.BITWISE_AND;
+               } else if (assignment.operator == AssignmentOperator.BITWISE_XOR) {
+                       cop = CCodeAssignmentOperator.BITWISE_XOR;
+               } else if (assignment.operator == AssignmentOperator.ADD) {
+                       cop = CCodeAssignmentOperator.ADD;
+               } else if (assignment.operator == AssignmentOperator.SUB) {
+                       cop = CCodeAssignmentOperator.SUB;
+               } else if (assignment.operator == AssignmentOperator.MUL) {
+                       cop = CCodeAssignmentOperator.MUL;
+               } else if (assignment.operator == AssignmentOperator.DIV) {
+                       cop = CCodeAssignmentOperator.DIV;
+               } else if (assignment.operator == AssignmentOperator.PERCENT) {
+                       cop = CCodeAssignmentOperator.PERCENT;
+               } else if (assignment.operator == AssignmentOperator.SHIFT_LEFT) {
+                       cop = CCodeAssignmentOperator.SHIFT_LEFT;
+               } else if (assignment.operator == AssignmentOperator.SHIFT_RIGHT) {
+                       cop = CCodeAssignmentOperator.SHIFT_RIGHT;
+               }
+       
+               codenode = new CCodeAssignment ((CCodeExpression) assignment.left.ccodenode, rhs, cop);
+
+               if (unref_old && assignment.left.ccodenode is CCodeElementAccess) {
+                       // ensure that index expression in element access doesn't get evaluated more than once
+                       // except when it's a simple expression
+                       var cea = (CCodeElementAccess) assignment.left.ccodenode;
+                       if (!(cea.index is CCodeConstant || cea.index is CCodeIdentifier)) {
+                               var index_temp_decl = codegen.get_temp_variable_declarator (codegen.int_type);
+                               codegen.temp_vars.insert (0, index_temp_decl);
+                               
+                               var ccomma = new CCodeCommaExpression ();
+                               ccomma.append_expression (new CCodeAssignment (new CCodeIdentifier (index_temp_decl.name), cea.index));
+                               ccomma.append_expression (codenode);
+
+                               cea.index = new CCodeIdentifier (index_temp_decl.name);
+                               
+                               codenode = ccomma;
                        }
                }
+       }
+
+       public override void emit () {
+               assignment.accept_children (codegen);
+
+               if (assignment.left.symbol_reference is Property) {
+                       emit_property_assignment ();
+               } else if (assignment.left.symbol_reference is Signal) {
+                       emit_signal_assignment ();
+               } else if (assignment.left is ElementAccess && !(((ElementAccess) assignment.left).container.static_type.data_type is Array)) {
+                       emit_non_array_element_access ();
+               } else {
+                       emit_simple_assignment ();
+               }
 
                assignment.ccodenode = codenode;
        }