2 // parameter.cs: Parameter definition.
4 // Author: Miguel de Icaza (miguel@gnu.org)
6 // Licensed under the terms of the GNU GPL
8 // (C) 2001 Ximian, Inc (http://www.ximian.com)
13 using System.Reflection;
14 using System.Reflection.Emit;
15 using System.Collections;
17 namespace Mono.CSharp {
21 /// Represents a single method parameter
23 public class Parameter {
25 public enum Modifier : byte {
32 public readonly Expression TypeName;
33 public readonly Modifier ModFlags;
34 public Attributes OptAttributes;
35 public readonly string Name;
36 public Type parameter_type;
38 public Parameter (Expression type, string name, Modifier mod, Attributes attrs)
43 OptAttributes = attrs;
47 // Resolve is used in method definitions
49 public bool Resolve (DeclSpace ds, Location l)
51 parameter_type = ds.ResolveType (TypeName, false, l);
52 return parameter_type != null;
56 // ResolveAndDefine is used by delegate declarations, because
57 // they happen during the initial tree resolution process
59 public bool ResolveAndDefine (DeclSpace ds)
61 // FIXME: Should use something else instead of Location.Null
62 parameter_type = ds.ResolveType (TypeName, true, Location.Null);
63 return parameter_type != null;
66 public Type ExternalType (DeclSpace ds, Location l)
68 if ((ModFlags & (Parameter.Modifier.REF | Parameter.Modifier.OUT)) != 0){
69 string n = parameter_type.FullName + "&";
71 Type t = RootContext.LookupType (ds, n, false, l);
76 return parameter_type;
79 public Type ParameterType {
81 return parameter_type;
85 public ParameterAttributes Attributes {
89 return ParameterAttributes.None;
91 return ParameterAttributes.None;
93 return ParameterAttributes.Out;
98 return ParameterAttributes.None;
103 /// Returns the signature for this parameter evaluating it on the
106 public string GetSignature (DeclSpace ds, Location loc)
108 if (parameter_type == null){
109 if (!Resolve (ds, loc))
113 return ExternalType (ds, loc).FullName;
118 /// Represents the methods parameters
120 public class Parameters {
121 public Parameter [] FixedParameters;
122 public readonly Parameter ArrayParameter;
127 static Parameters empty_parameters;
129 public Parameters (Parameter [] fixed_parameters, Parameter array_parameter, Location l)
131 FixedParameters = fixed_parameters;
132 ArrayParameter = array_parameter;
137 /// This is used to reuse a set of empty parameters, because they
140 public static Parameters GetEmptyReadOnlyParameters ()
142 if (empty_parameters == null)
143 empty_parameters = new Parameters (null, null, Location.Null);
145 return empty_parameters;
150 return (FixedParameters == null) && (ArrayParameter == null);
154 public void ComputeSignature (DeclSpace ds)
157 if (FixedParameters != null){
158 for (int i = 0; i < FixedParameters.Length; i++){
159 Parameter par = FixedParameters [i];
161 signature += par.GetSignature (ds, loc);
165 // Note: as per the spec, the `params' arguments (ArrayParameter)
166 // are not used in the signature computation for a method
170 static void error100 (string name)
173 100, "The parameter name `" + name + "' is a duplicate");
176 public bool VerifyArgs ()
181 if (FixedParameters == null)
184 count = FixedParameters.Length;
185 string array_par_name = ArrayParameter != null ? ArrayParameter.Name : null;
186 for (i = 0; i < count; i++){
187 string base_name = FixedParameters [i].Name;
189 for (j = i + 1; j < count; j++){
190 if (base_name != FixedParameters [j].Name)
192 error100 (base_name);
196 if (base_name == array_par_name){
197 error100 (base_name);
205 /// Returns the signature of the Parameters evaluated in
206 /// the @tc environment
208 public string GetSignature (DeclSpace ds)
210 if (signature == null){
212 ComputeSignature (ds);
219 /// Returns the paramenter information based on the name
221 public Parameter GetParameterByName (string name, out int idx)
226 if (FixedParameters != null){
227 foreach (Parameter par in FixedParameters){
228 if (par.Name == name){
236 if (ArrayParameter != null){
237 if (name == ArrayParameter.Name){
239 return ArrayParameter;
246 bool ComputeParameterTypes (DeclSpace ds)
248 int extra = (ArrayParameter != null) ? 1 : 0;
252 if (FixedParameters == null)
255 pc = extra + FixedParameters.Length;
257 types = new Type [pc];
260 FixedParameters = null;
265 if (FixedParameters != null){
266 foreach (Parameter p in FixedParameters){
269 if (p.Resolve (ds, loc))
270 t = p.ExternalType (ds, loc);
283 if (ArrayParameter.Resolve (ds, loc))
284 types [i] = ArrayParameter.ExternalType (ds, loc);
293 // This variant is used by Delegates, because they need to
294 // resolve/define names, instead of the plain LookupType
296 public bool ComputeAndDefineParameterTypes (DeclSpace ds)
298 int extra = (ArrayParameter != null) ? 1 : 0;
302 if (FixedParameters == null)
305 pc = extra + FixedParameters.Length;
307 types = new Type [pc];
310 FixedParameters = null;
316 if (FixedParameters != null){
317 foreach (Parameter p in FixedParameters){
320 if (p.ResolveAndDefine (ds))
321 t = p.ExternalType (ds, loc);
331 if (ArrayParameter.ResolveAndDefine (ds))
332 types [i] = ArrayParameter.ExternalType (ds, loc);
338 // invalidate the cached types
348 /// Returns the argument types as an array
350 static Type [] no_types = new Type [0];
352 public Type [] GetParameterInfo (DeclSpace ds)
357 if (FixedParameters == null && ArrayParameter == null)
360 if (ComputeParameterTypes (ds) == false){
369 /// Returns the type of a given parameter, and stores in the `is_out'
370 /// boolean whether this is an out or ref parameter.
372 /// Note that the returned type will not contain any dereference in this
373 /// case (ie, you get "int" for a ref int instead of "int&"
375 public Type GetParameterInfo (DeclSpace ds, int idx, out bool is_out)
380 FixedParameters = null;
384 if (FixedParameters == null && ArrayParameter == null)
388 if (ComputeParameterTypes (ds) == false){
394 // If this is a request for the variable lenght arg.
396 int array_idx = (FixedParameters != null ? FixedParameters.Length : 0);
397 if (idx == array_idx){
403 // Otherwise, it is a fixed parameter
405 Parameter p = FixedParameters [idx];
406 is_out = ((p.ModFlags & (Parameter.Modifier.REF | Parameter.Modifier.OUT)) != 0);
408 return p.ParameterType;
411 public CallingConventions GetCallingConvention ()
413 // For now this is the only correc thing to do
414 return CallingConventions.Standard;