2 // assign.cs: Assignments.
5 // Miguel de Icaza (miguel@ximian.com)
7 // (C) 2001 Ximian, Inc.
10 using System.Reflection;
11 using System.Reflection.Emit;
16 // This interface is implemented by Expressions whose values can not
17 // store the result on the top of the stack.
19 // Expressions implementing this (Properties and Indexers) would
20 // perform an assignment of the Expression "source" into its final
23 // No values on the top of the stack are expected to be left by
24 // invoking this method.
26 public interface IAssignMethod {
27 void EmitAssign (EmitContext ec, Expression source);
31 // The LocalTemporary class is used to hold temporary values of a given
32 // type to "simulate" the expression semantics on property and indexer
33 // access whose return values are void.
35 // The local temporary is used to alter the normal flow of code generation
36 // basically it creates a local variable, and its emit instruction generates
37 // code to access this value, return its address or save its value.
39 public class LocalTemporary : Expression, IStackStore, IMemoryLocation {
42 public LocalTemporary (EmitContext ec, Type t)
45 eclass = ExprClass.Value;
46 builder = ec.GetTemporaryStorage (t);
49 public override Expression DoResolve (EmitContext ec)
54 public override void Emit (EmitContext ec)
56 ec.ig.Emit (OpCodes.Ldloc, builder);
59 public void Store (EmitContext ec)
61 ec.ig.Emit (OpCodes.Stloc, builder);
64 public void AddressOf (EmitContext ec)
66 ec.ig.Emit (OpCodes.Ldloca, builder);
71 // The Assign node takes care of assigning the value of source into
72 // the expression represented by target.
74 public class Assign : ExpressionStatement {
75 Expression target, source;
78 public Assign (Expression target, Expression source, Location l)
85 public Expression Target {
95 public Expression Source {
105 public override Expression DoResolve (EmitContext ec)
107 source = source.Resolve (ec);
111 target = target.ResolveLValue (ec, source);
116 Type target_type = target.Type;
117 Type source_type = source.Type;
120 eclass = ExprClass.Value;
123 // If we are doing a property assignment, then
124 // set the `value' field on the property, and Resolve
127 if (target is PropertyExpr){
128 PropertyExpr property_assign = (PropertyExpr) target;
131 // FIXME: Maybe handle this in the LValueResolve
133 if (!property_assign.VerifyAssignable ())
139 if (target is IndexerAccess){
140 IndexerAccess ia = (IndexerAccess) target;
145 if (source is New && target_type.IsSubclassOf (TypeManager.value_type)){
146 New n = (New) source;
148 n.ValueTypeVariable = target;
153 if (target_type != source_type){
154 source = ConvertImplicitRequired (ec, source, target_type, l);
159 if (target.ExprClass != ExprClass.Variable){
160 Report.Error (131, l,
161 "Left hand of an assignment must be a variable, " +
162 "a property or an indexer");
169 void Emit (EmitContext ec, bool is_statement)
171 ILGenerator ig = ec.ig;
172 ExprClass eclass = target.ExprClass;
174 if (eclass == ExprClass.Variable){
177 // If it is an instance field, load the this pointer
179 if (target is FieldExpr){
180 FieldExpr fe = (FieldExpr) target;
182 if (!fe.FieldInfo.IsStatic)
183 ig.Emit (OpCodes.Ldarg_0);
189 ig.Emit (OpCodes.Dup);
191 ((IStackStore) target).Store (ec);
192 } else if (eclass == ExprClass.PropertyAccess ||
193 eclass == ExprClass.IndexerAccess){
194 IAssignMethod am = (IAssignMethod) target;
197 am.EmitAssign (ec, source);
199 LocalTemporary tempo;
201 tempo = new LocalTemporary (ec, source.Type);
205 am.EmitAssign (ec, source);
209 Console.WriteLine ("Unhandled class: " + eclass + "\n Type:" + target);
213 public override void Emit (EmitContext ec)
218 public override void EmitStatement (EmitContext ec)