2005-12-27 Atsushi Enomoto <atsushi@ximian.com>
[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                         NoArg,
28                         AddressOf
29                 };
30
31                 public AType ArgType;
32                 public Expression Expr;
33                 public string ParamName;
34                 
35                 public Argument (Expression expr, AType type)
36                         : this ("", expr, type)
37                 {
38                 }
39
40                 public Argument (string paramName, Expression expr, AType type)
41                 {
42                         this.ParamName = paramName;
43                         expr = Parser.SetValueRequiredFlag (expr);
44                         if (type == AType.AddressOf)
45                                 expr = Parser.SetAddressOf (expr);
46                         this.Expr = expr;
47                         this.ArgType = type;
48                 }
49
50                 public Type Type {
51                         get {
52                                 if (ArgType == AType.Ref )
53                                         return TypeManager.LookupType (Expr.Type.ToString () + "&");
54                                 else
55                                         return Expr.Type;
56                         }
57                 }
58
59                 public Parameter.Modifier GetParameterModifier ()
60                 {
61                         switch (ArgType) {
62                         case AType.Ref:
63                                 return Parameter.Modifier.REF | Parameter.Modifier.ISBYREF;
64
65                         default:
66                                 return Parameter.Modifier.NONE;
67                         }
68                 }
69
70                 public static string FullDesc (Argument a)
71                 {
72                         return (a.ArgType == AType.Ref ? "ref " : "") +
73                                 TypeManager.MonoBASIC_Name (a.Expr.Type);
74                 }
75
76                 public bool ResolveMethodGroup (EmitContext ec, Location loc)
77                 {
78                         // FIXME: csc doesn't report any error if you try to use `ref' or
79                         //        `out' in a delegate creation expression.
80                         Expr = Expr.Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.MethodGroup);
81                         if (Expr == null)
82                                 return false;
83
84                         return true;
85                 }
86
87                 public bool Resolve (EmitContext ec, Location loc)
88                 {
89                         // Optional void arguments - MyCall (1,,2) - are resolved later
90                         // in VerifyArgsCompat
91                         if (ArgType == AType.NoArg || ArgType == AType.Ref) 
92                         {
93                                 return true;                            
94                         }
95
96 /*
97                         if (ArgType == AType.Ref) {
98                                 Expr = Expr.Resolve (ec);
99                                 if (Expr == null)
100                                         return false;
101
102                                 Expr = Expr.ResolveLValue (ec, Expr);
103                         } else */
104
105                         if (ArgType == AType.AddressOf) {
106                                 Expression temp_expr = Expr;
107                                 
108                                 if (temp_expr is SimpleName) {
109                                         SimpleName sn = temp_expr as SimpleName;
110                                         temp_expr = sn.DoResolveAllowStatic(ec);
111                                 }
112                                 else if (temp_expr is MemberAccess)     {
113                                         MemberAccess ma = temp_expr as MemberAccess;
114                                         temp_expr = ma.DoResolve(ec);
115                                 }
116
117                                 if (temp_expr is MethodGroupExpr)
118                                         return true;
119
120                                 ArgType = AType.Expression;
121                                 Expr = Expr.Resolve (ec);
122                         }
123                         else
124                                 Expr = Expr.Resolve (ec);
125                         
126                         if (Expr == null)
127                                 return false;
128
129                         if (ArgType == AType.Expression)
130                                 return true;
131
132                         if (Expr.eclass != ExprClass.Variable){
133                                 //
134                                 // We just probe to match the CSC output
135                                 //
136                                 if (Expr.eclass == ExprClass.PropertyAccess ||
137                                     Expr.eclass == ExprClass.IndexerAccess){
138                                         Report.Error (
139                                                 206, loc,
140                                                 "A property or indexer can not be passed as an out or ref " +
141                                                 "parameter");
142                                 } else {
143                                         Report.Error (
144                                                 1510, loc,
145                                                 "An lvalue is required as an argument to out or ref");
146                                 }
147                                 return false;
148                         }
149                                 
150                         return true;
151                 }
152
153                 public void Emit (EmitContext ec)
154                 {
155                         //
156                         // Ref  parameters need to have their addresses taken.
157                         //
158                         // ParameterReferences might already be references, so we want
159                         // to pass just the value
160                         //
161                         if (ArgType == AType.Ref ){
162                                 AddressOp mode = AddressOp.Store;
163
164                                 if (ArgType == AType.Ref)
165                                         mode |= AddressOp.Load;
166                                 
167                                 if (Expr is ParameterReference){
168                                         ParameterReference pr = (ParameterReference) Expr;
169
170                                         if (pr.is_ref)
171                                                 pr.EmitLoad (ec);
172                                         else {
173                                                 
174                                                 pr.AddressOf (ec, mode);
175                                         }
176                                 } else
177                                         ((IMemoryLocation)Expr).AddressOf (ec, mode);
178                         } else
179                                 Expr.Emit (ec);
180                 }
181         }
182 }