ChangeLog: Updated ChangeLog.
[mono.git] / mcs / mbas / argument.cs
1 //
2 // argument.cs: Arguments representation for the IL tree.
3 //
4 // Author:
5 //   Miguel de Icaza (miguel@ximian.com)
6 //
7 // (C) 2001 Ximian, Inc.
8 //
9 //
10 #define USE_OLD
11
12 namespace Mono.MonoBASIC {
13         using System;
14         using System.Collections;
15         using System.Reflection;
16         using System.Reflection.Emit;
17         using System.Text;
18
19         
20         /// <summary>
21         ///   Used for arguments to New(), Invocation()
22         /// </summary>
23         public class Argument {
24                 public enum AType : byte {
25                         Expression,
26                         Ref,
27                         Out,
28                         NoArg,
29                         AddressOf
30                 };
31
32                 public AType ArgType;
33                 public Expression Expr;
34                 
35                 public Argument (Expression expr, AType type)
36                 {
37                         this.Expr = expr;
38                         this.ArgType = type;
39                 }
40
41                 public Type Type {
42                         get {
43                                 if (ArgType == AType.Ref || ArgType == AType.Out)
44                                         return TypeManager.LookupType (Expr.Type.ToString () + "&");
45                                 else
46                                         return Expr.Type;
47                         }
48                 }
49
50                 public Parameter.Modifier GetParameterModifier ()
51                 {
52                         switch (ArgType) {
53                         case AType.Out:
54                                 return Parameter.Modifier.OUT | Parameter.Modifier.ISBYREF;
55
56                         case AType.Ref:
57                                 return Parameter.Modifier.REF | Parameter.Modifier.ISBYREF;
58
59                         default:
60                                 return Parameter.Modifier.NONE;
61                         }
62                 }
63
64                 public static string FullDesc (Argument a)
65                 {
66                         return (a.ArgType == AType.Ref ? "ref " :
67                                 (a.ArgType == AType.Out ? "out " : "")) +
68                                 TypeManager.MonoBASIC_Name (a.Expr.Type);
69                 }
70
71                 public bool ResolveMethodGroup (EmitContext ec, Location loc)
72                 {
73                         // FIXME: csc doesn't report any error if you try to use `ref' or
74                         //        `out' in a delegate creation expression.
75                         Expr = Expr.Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.MethodGroup);
76                         if (Expr == null)
77                                 return false;
78
79                         return true;
80                 }
81
82                 public bool Resolve (EmitContext ec, Location loc)
83                 {
84                         // Optional void arguments - MyCall (1,,2) - are resolved later
85                         // in VerifyArgsCompat
86                         if (ArgType == AType.NoArg || ArgType == AType.Ref) 
87                         {
88                                 return true;                            
89                         }
90
91 /*
92                         if (ArgType == AType.Ref) {
93                                 Expr = Expr.Resolve (ec);
94                                 if (Expr == null)
95                                         return false;
96
97                                 Expr = Expr.ResolveLValue (ec, Expr);
98                         } else */
99
100                         if (ArgType == AType.Out)
101                                 Expr = Expr.ResolveLValue (ec, new EmptyExpression ());
102                         else if (ArgType == AType.AddressOf) {
103                                 Expression temp_expr = Expr;
104                                 
105                                 if (temp_expr is SimpleName) {
106                                         SimpleName sn = temp_expr as SimpleName;
107                                         temp_expr = sn.DoResolveAllowStatic(ec);
108                                 }
109                                 else if (temp_expr is MemberAccess)     {
110                                         MemberAccess ma = temp_expr as MemberAccess;
111                                         temp_expr = ma.DoResolve(ec);
112                                 }
113
114                                 if (temp_expr is MethodGroupExpr)
115                                         return true;
116
117                                 ArgType = AType.Expression;
118                                 Expr = Expr.Resolve (ec);
119                         }
120                         else
121                                 Expr = Expr.Resolve (ec);
122                         
123                         if (Expr == null)
124                                 return false;
125
126                         if (ArgType == AType.Expression)
127                                 return true;
128
129                         if (Expr.eclass != ExprClass.Variable){
130                                 //
131                                 // We just probe to match the CSC output
132                                 //
133                                 if (Expr.eclass == ExprClass.PropertyAccess ||
134                                     Expr.eclass == ExprClass.IndexerAccess){
135                                         Report.Error (
136                                                 206, loc,
137                                                 "A property or indexer can not be passed as an out or ref " +
138                                                 "parameter");
139                                 } else {
140                                         Report.Error (
141                                                 1510, loc,
142                                                 "An lvalue is required as an argument to out or ref");
143                                 }
144                                 return false;
145                         }
146                                 
147                         return true;
148                 }
149
150                 public void Emit (EmitContext ec)
151                 {
152                         //
153                         // Ref and Out parameters need to have their addresses taken.
154                         //
155                         // ParameterReferences might already be references, so we want
156                         // to pass just the value
157                         //
158                         if (ArgType == AType.Ref || ArgType == AType.Out){
159                                 AddressOp mode = AddressOp.Store;
160
161                                 if (ArgType == AType.Ref)
162                                         mode |= AddressOp.Load;
163                                 
164                                 if (Expr is ParameterReference){
165                                         ParameterReference pr = (ParameterReference) Expr;
166
167                                         if (pr.is_ref)
168                                                 pr.EmitLoad (ec);
169                                         else {
170                                                 
171                                                 pr.AddressOf (ec, mode);
172                                         }
173                                 } else
174                                         ((IMemoryLocation)Expr).AddressOf (ec, mode);
175                         } else
176                                 Expr.Emit (ec);
177                 }
178         }
179 }