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