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