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