f9d94c8ca745db244e811130801c25a170aeff36
[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                         target = target.Resolve (ec);
48                         source = source.Resolve (ec);
49
50                         if (target == null || source == null)
51                                 return null;
52
53                         Type target_type = target.Type;
54                         Type source_type = source.Type;
55
56                         type = target_type;
57                         eclass = ExprClass.Value;
58                         
59                         //
60                         // If we are doing a property assignment, then
61                         // set the `value' field on the property, and Resolve
62                         // it.
63                         //
64                         if (target is PropertyExpr){
65                                 PropertyExpr property_assign = (PropertyExpr) target;
66                                 
67                                 if (!property_assign.VerifyAssignable ())
68                                         return null;
69                                 
70                                 return this;
71                         }
72                         
73                         if (source is New && target_type.IsSubclassOf (TypeManager.value_type)){
74                                 New n = (New) source;
75
76                                 n.ValueTypeVariable = target;
77
78                                 return n;
79                         }
80                         
81                         if (target_type != source_type){
82                                 source = ConvertImplicitRequired (ec, source, target_type, l);
83                                 if (source == null)
84                                         return null;
85                         }
86                         
87                         if (!(target is LValue)){
88                                 Report.Error (131, l, "Left hand of an assignment must be a variable, a property or an indexer");
89                                 return null;
90                         }
91
92                         return this;
93                 }
94
95                 void Emit (EmitContext ec, bool is_statement)
96                 {
97                         ILGenerator ig = ec.ig;
98                         ExprClass eclass = target.ExprClass;
99                         
100                         if (eclass == ExprClass.Variable){
101
102                                 //
103                                 // If it is an instance field, load the this pointer
104                                 //
105                                 if (target is FieldExpr){
106                                         FieldExpr fe = (FieldExpr) target;
107                                         
108                                         if (!fe.FieldInfo.IsStatic)
109                                                 ig.Emit (OpCodes.Ldarg_0);
110                                 }
111
112                                 source.Emit (ec);
113
114                                 if (!is_statement)
115                                         ig.Emit (OpCodes.Dup);
116
117                                 ((LValue) target).Store (ec);
118                         } else if (eclass == ExprClass.PropertyAccess){
119                                 PropertyExpr pe = (PropertyExpr) target;
120
121                                 if (is_statement){
122                                         pe.Value = source;
123                                         pe.Emit (ec);
124                                 } else {
125                                         LocalTemporary tempo;
126                                         
127                                         tempo = new LocalTemporary (ec, source.Type);
128
129                                         pe.Value = tempo;
130                                         source.Emit (ec);
131                                         tempo.Store (ec);
132                                         target.Emit (ec);
133
134                                         tempo.Emit (ec);
135                                 }
136                         } else if (eclass == ExprClass.IndexerAccess){
137                                 
138                                 throw new Exception ("Can not assign to indexers yet");
139                         }
140                 }
141                 
142                 public override void Emit (EmitContext ec)
143                 {
144                         Emit (ec, false);
145                 }
146
147                 public override void EmitStatement (EmitContext ec)
148                 {
149                         Emit (ec, true);
150                 }
151         }
152 }
153
154
155
156