2001-10-12 Ravi Pratap <ravi@ximian.com>
[mono.git] / mcs / mcs / assign.cs
index dc9e039803b03a975a65be86923c9e4d5a845cb0..36081efe19fa5bf07bf9e464354075ccedf5a1a4 100755 (executable)
@@ -6,17 +6,20 @@
 //
 // (C) 2001 Ximian, Inc.
 //
-
+using System;
+using System.Reflection;
 using System.Reflection.Emit;
 
 namespace CIR {
-       public class Assign : Expression {
+       public class Assign : ExpressionStatement {
                Expression target, source;
+               Location l;
                
-               public Assign (Expression target, Expression source)
+               public Assign (Expression target, Expression source, Location l)
                {
                        this.target = target;
                        this.source = source;
+                       this.l = l;
                }
 
                public Expression Target {
@@ -39,82 +42,75 @@ namespace CIR {
                        }
                }
 
-               public override Expression Resolve (TypeContainer tc)
+               public override Expression DoResolve (EmitContext ec)
                {
-                       target = target.Resolve (tc);
-                       source = source.Resolve (tc);
+                       target = target.Resolve (ec);
+                       source = source.Resolve (ec);
 
                        if (target == null || source == null)
                                return null;
+
+                       Type target_type = target.Type;
                        
-                       return this;
-               }
+                       Type source_type = source.Type;
 
-               void EmitLocalAssign (LocalVariableReference lv, ILGenerator ig)
-               {
-                       VariableInfo vi = lv.VariableInfo;
-                       int idx = vi.Idx;
-                                       
-                       switch (idx){
-                       case 0:
-                               ig.Emit (OpCodes.Stloc_0);
-                               break;
-                               
-                       case 1:
-                               ig.Emit (OpCodes.Stloc_1);
-                               break;
-                               
-                       case 2:
-                               ig.Emit (OpCodes.Stloc_2);
-                               break;
-                               
-                       case 3:
-                               ig.Emit (OpCodes.Stloc_3);
-                               break;
-                               
-                       default:
-                               if (idx < 255)
-                                       ig.Emit (OpCodes.Stloc_S, idx);
-                               else
-                                       ig.Emit (OpCodes.Stloc, idx);
-                               break;
+                       if (target_type != source_type){
+                               source = ConvertImplicitRequired (ec, source, target_type, l);
+                               if (source == null)
+                                       return null;
                        }
+                       
+                       if (!(target is LValue)){
+                               Report.Error (131, "Left hand of an assignment must be a variable, a property or an indexer");
+                       }
+                       type = target_type;
+                       eclass = ExprClass.Value;
+                       return this;
                }
 
-               public void EmitParameterAssign (ParameterReference pr, ILGenerator ig)
+               void Emit (EmitContext ec, bool is_statement)
                {
-                       int idx = pr.Idx;
+                       ILGenerator ig = ec.ig;
                        
-                       if (idx < 255)
-                               ig.Emit (OpCodes.Starg_S, idx);
-                       else
-                               ig.Emit (OpCodes.Starg, idx);
-               }
+                       if (target.ExprClass == ExprClass.Variable){
 
-               public void EmitFieldAssign (FieldExpr field, ILGenerator ig)
-               {
-                       if (field.IsStatic)
-                               ig.Emit (OpCodes.Stsfld, field.FieldInfo);
-                       else
-                               ig.Emit (OpCodes.Stfld, field.FieldInfo);
+                               //
+                               // If it is an instance field, load the this pointer
+                               //
+                               if (target is FieldExpr){
+                                       FieldExpr fe = (FieldExpr) target;
+                                       
+                                       if (!fe.FieldInfo.IsStatic)
+                                               ig.Emit (OpCodes.Ldarg_0);
+                               }
+
+                               source.Emit (ec);
+
+                               if (!is_statement)
+                                       ig.Emit (OpCodes.Dup);
+
+                               ((LValue) target).Store (ec);
+                       } else if (target.ExprClass == ExprClass.PropertyAccess){
+                               // FIXME
+                               throw new Exception ("Can not assign to properties yet");
+                       } else if (target.ExprClass == ExprClass.IndexerAccess){
+                               // FIXME
+                               throw new Exception ("Can not assign to indexers yet");
+                       }
                }
                
                public override void Emit (EmitContext ec)
                {
-                       if (target.ExprClass == ExprClass.Variable){
-                               source.Emit (ec);
+                       Emit (ec, false);
+               }
 
-                               if (target is LocalVariableReference){
-                                       EmitLocalAssign ((LocalVariableReference) target, ec.ig);
-                               } else if (target is ParameterReference){
-                                       EmitParameterAssign ((ParameterReference) target, ec.ig);
-                               } else if (target is FieldExpr){
-                                       EmitFieldAssign ((FieldExpr) target, ec.ig);
-                               }
-                       } 
+               public override void EmitStatement (EmitContext ec)
+               {
+                       Emit (ec, true);
                }
        }
 }
 
 
 
+