2001-10-07 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 (TypeContainer tc)
46                 {
47                         target = target.Resolve (tc);
48                         source = source.Resolve (tc);
49
50                         if (target == null || source == null)
51                                 return null;
52
53                         Type target_type = target.Type;
54                         
55                         Type source_type = source.Type;
56
57                         if (target_type != source_type){
58                                 source = ConvertImplicitRequired (tc, source, target_type, l);
59                                 if (source == null)
60                                         return null;
61                         }
62                         
63                         if (!(target is LValue)){
64                                 Report.Error (131, "Left hand of an assignment must be a variable, a property or an indexer");
65                         }
66                         type = target_type;
67                         eclass = ExprClass.Value;
68                         return this;
69                 }
70
71                 void Emit (EmitContext ec, bool is_statement)
72                 {
73                         ILGenerator ig = ec.ig;
74                         
75                         if (target.ExprClass == ExprClass.Variable){
76
77                                 //
78                                 // If it is an instance field, load the this pointer
79                                 //
80                                 if (target is FieldExpr){
81                                         FieldExpr fe = (FieldExpr) target;
82                                         
83                                         if (!fe.FieldInfo.IsStatic)
84                                                 ig.Emit (OpCodes.Ldarg_0);
85                                 }
86
87                                 source.Emit (ec);
88
89                                 if (!is_statement)
90                                         ig.Emit (OpCodes.Dup);
91
92                                 ((LValue) target).Store (ec);
93                         } else if (target.ExprClass == ExprClass.PropertyAccess){
94                                 // FIXME
95                                 throw new Exception ("Can not assign to properties yet");
96                         } else if (target.ExprClass == ExprClass.IndexerAccess){
97                                 // FIXME
98                                 throw new Exception ("Can not assign to indexers yet");
99                         }
100                 }
101                 
102                 public override void Emit (EmitContext ec)
103                 {
104                         Emit (ec, false);
105                 }
106
107                 public override void EmitStatement (EmitContext ec)
108                 {
109                         Emit (ec, true);
110                 }
111         }
112 }
113
114
115
116