2001-10-22 Ravi Pratap <ravi@ximian.com>
[mono.git] / mcs / mcs / assign.cs
1 //
2 // assign.cs: Assignment representation for the IL tree.
3 //
4 // Author:
5 //   Miguel de Icaza (miguel@ximian.com)
6 //
7 // (C) 2001 Ximian, Inc.
8 //
9 using System;
10 using System.Reflection;
11 using System.Reflection.Emit;
12
13 namespace CIR {
14         public class Assign : ExpressionStatement {
15                 Expression target, source;
16                 Location l;
17                 
18                 public Assign (Expression target, Expression source, Location l)
19                 {
20                         this.target = target;
21                         this.source = source;
22                         this.l = l;
23                 }
24
25                 public Expression Target {
26                         get {
27                                 return target;
28                         }
29
30                         set {
31                                 target = value;
32                         }
33                 }
34
35                 public Expression Source {
36                         get {
37                                 return source;
38                         }
39
40                         set {
41                                 source = value;
42                         }
43                 }
44
45                 public override Expression DoResolve (EmitContext ec)
46                 {
47                         source = source.Resolve (ec);
48                         if (source == null)
49                                 return null;
50                         
51                         target = target.ResolveLValue (ec, source);
52                         
53                         if (target == null)
54                                 return null;
55
56                         Type target_type = target.Type;
57                         Type source_type = source.Type;
58
59                         type = target_type;
60                         eclass = ExprClass.Value;
61                         
62                         //
63                         // If we are doing a property assignment, then
64                         // set the `value' field on the property, and Resolve
65                         // it.
66                         //
67                         if (target is PropertyExpr){
68                                 PropertyExpr property_assign = (PropertyExpr) target;
69
70                                 //
71                                 // FIXME: Maybe handle this in the LValueResolve
72                                 //
73                                 if (!property_assign.VerifyAssignable ())
74                                         return null;
75                                 
76                                 return this;
77                         }
78
79                         if (target is IndexerAccess){
80                                 IndexerAccess ia = (IndexerAccess) target;
81
82                                 return this;
83                         }
84
85                         if (source is New && target_type.IsSubclassOf (TypeManager.value_type)){
86                                 New n = (New) source;
87
88                                 n.ValueTypeVariable = target;
89
90                                 return n;
91                         }
92                         
93                         if (target_type != source_type){
94                                 source = ConvertImplicitRequired (ec, source, target_type, l);
95                                 if (source == null)
96                                         return null;
97                         }
98
99                         if (target.ExprClass != ExprClass.Variable){
100                                 Report.Error (131, l,
101                                               "Left hand of an assignment must be a variable, " +
102                                               "a property or an indexer");
103                                 return null;
104                         }
105
106                         return this;
107                 }
108
109                 void Emit (EmitContext ec, bool is_statement)
110                 {
111                         ILGenerator ig = ec.ig;
112                         ExprClass eclass = target.ExprClass;
113                         
114                         if (eclass == ExprClass.Variable){
115
116                                 //
117                                 // If it is an instance field, load the this pointer
118                                 //
119                                 if (target is FieldExpr){
120                                         FieldExpr fe = (FieldExpr) target;
121                                         
122                                         if (!fe.FieldInfo.IsStatic)
123                                                 ig.Emit (OpCodes.Ldarg_0);
124                                 }
125
126                                 source.Emit (ec);
127
128                                 if (!is_statement)
129                                         ig.Emit (OpCodes.Dup);
130
131                                 ((IStackStore) target).Store (ec);
132                         } else if (eclass == ExprClass.PropertyAccess){
133                                 PropertyExpr pe = (PropertyExpr) target;
134
135                                 if (is_statement){
136                                         pe.Value = source;
137                                         pe.Emit (ec);
138                                 } else {
139                                         LocalTemporary tempo;
140                                         
141                                         tempo = new LocalTemporary (ec, source.Type);
142
143                                         pe.Value = tempo;
144                                         source.Emit (ec);
145                                         tempo.Store (ec);
146                                         target.Emit (ec);
147
148                                         tempo.Emit (ec);
149                                 }
150                         } else if (eclass == ExprClass.IndexerAccess){
151                                 IndexerAccess ia = (IndexerAccess) target;
152
153                                 if (is_statement)
154                                         ia.EmitSet (ec, source);
155                                 else {
156                                         LocalTemporary tempo;
157                                         
158                                         tempo = new LocalTemporary (ec, source.Type);
159
160                                         source.Emit (ec);
161                                         tempo.Store (ec);
162                                         ia.EmitSet (ec, source);
163
164                                         tempo.Emit (ec);
165                                 }
166                         }
167                 }
168                 
169                 public override void Emit (EmitContext ec)
170                 {
171                         Emit (ec, false);
172                 }
173
174                 public override void EmitStatement (EmitContext ec)
175                 {
176                         Emit (ec, true);
177                 }
178         }
179 }
180
181
182
183