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;
13 namespace Mono.CSharp {
16 /// This interface is implemented by expressions that can be assigned to.
19 /// This interface is implemented by Expressions whose values can not
20 /// store the result on the top of the stack.
22 /// Expressions implementing this (Properties, Indexers and Arrays) would
23 /// perform an assignment of the Expression "source" into its final
26 /// No values on the top of the stack are expected to be left by
27 /// invoking this method.
29 public interface IAssignMethod {
30 void EmitAssign (EmitContext ec, Expression source);
34 /// An Expression to hold a temporary value.
37 /// The LocalTemporary class is used to hold temporary values of a given
38 /// type to "simulate" the expression semantics on property and indexer
39 /// access whose return values are void.
41 /// The local temporary is used to alter the normal flow of code generation
42 /// basically it creates a local variable, and its emit instruction generates
43 /// code to access this value, return its address or save its value.
45 public class LocalTemporary : Expression, IMemoryLocation {
48 public LocalTemporary (EmitContext ec, Type t)
51 eclass = ExprClass.Value;
52 builder = ec.GetTemporaryStorage (t);
55 public override Expression DoResolve (EmitContext ec)
60 public override void Emit (EmitContext ec)
62 ec.ig.Emit (OpCodes.Ldloc, builder);
65 public void Store (EmitContext ec)
67 ec.ig.Emit (OpCodes.Stloc, builder);
70 public void AddressOf (EmitContext ec)
72 ec.ig.Emit (OpCodes.Ldloca, builder);
77 /// The Assign node takes care of assigning the value of source into
78 /// the expression represented by target.
80 public class Assign : ExpressionStatement {
81 Expression target, source;
84 public Assign (Expression target, Expression source, Location l)
91 public Expression Target {
101 public Expression Source {
111 public override Expression DoResolve (EmitContext ec)
113 source = source.Resolve (ec);
117 target = target.ResolveLValue (ec, source);
122 Type target_type = target.Type;
123 Type source_type = source.Type;
126 eclass = ExprClass.Value;
129 // If we are doing a property assignment, then
130 // set the `value' field on the property, and Resolve
133 if (target is PropertyExpr){
134 PropertyExpr property_assign = (PropertyExpr) target;
137 // FIXME: Maybe handle this in the LValueResolve
139 if (!property_assign.VerifyAssignable ())
145 if (target is IndexerAccess){
146 IndexerAccess ia = (IndexerAccess) target;
151 if (source is New && target_type.IsSubclassOf (TypeManager.value_type)){
152 New n = (New) source;
154 n.ValueTypeVariable = target;
159 if (target_type != source_type){
160 source = ConvertImplicitRequired (ec, source, target_type, l);
165 if (target.ExprClass != ExprClass.Variable){
166 Report.Error (131, l,
167 "Left hand of an assignment must be a variable, " +
168 "a property or an indexer");
175 void Emit (EmitContext ec, bool is_statement)
177 ILGenerator ig = ec.ig;
178 ExprClass eclass = target.ExprClass;
181 // FIXME! We need a way to "probe" if the process can
182 // just use `dup' to propagate the result
184 IAssignMethod am = (IAssignMethod) target;
187 am.EmitAssign (ec, source);
189 LocalTemporary tempo;
191 tempo = new LocalTemporary (ec, source.Type);
195 am.EmitAssign (ec, source);
200 public override void Emit (EmitContext ec)
205 public override void EmitStatement (EmitContext ec)