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
.MonoBASIC
{
21 /// Represents a single method parameter
23 public class Parameter
: Attributable
{
25 public enum Modifier
: byte {
31 // This is a flag which says that it's either REF or OUT.
36 public readonly Expression TypeName
;
37 public readonly Modifier ModFlags
;
38 public readonly string Name
;
39 public Type parameter_type
;
40 public readonly Expression ParameterInitializer
;
41 public readonly bool IsOptional
;
43 public Parameter (Expression type
, string name
, Modifier mod
, Attributes attrs
)
49 ParameterInitializer
= null;
53 public Parameter (Expression type
, string name
, Modifier mod
, Attributes attrs
, Expression pi
)
59 ParameterInitializer
= pi
;
63 public Parameter (Expression type
, string name
, Modifier mod
, Attributes attrs
, Expression pi
, bool opt
)
69 ParameterInitializer
= pi
;
73 public override AttributeTargets AttributeTargets
{
75 return AttributeTargets
.Parameter
;
80 // Resolve is used in method definitions
82 public bool Resolve (DeclSpace ds
, Location l
)
84 parameter_type
= ds
.ResolveType (TypeName
, false, l
);
86 if (parameter_type
== TypeManager
.void_type
){
87 Report
.Error (1536, l
, "`void' parameter is not permitted");
91 return parameter_type
!= null;
94 public Type
ExternalType (DeclSpace ds
, Location l
)
96 if ((ModFlags
& Parameter
.Modifier
.ISBYREF
) != 0){
97 string n
= parameter_type
.FullName
+ "&";
99 Type t
= RootContext
.LookupType (ds
, n
, false, l
);
104 return parameter_type
;
107 public Type ParameterType
{
109 return parameter_type
;
113 public ParameterAttributes Attributes
{
115 int flags
= ((int) ModFlags
) & ~
((int) Parameter
.Modifier
.ISBYREF
);
116 switch ((Modifier
) flags
) {
118 return ParameterAttributes
.None
;
120 return ParameterAttributes
.None
;
122 return ParameterAttributes
.Out
;
123 case Modifier
.OPTIONAL
:
124 return ParameterAttributes
.Optional
;
125 case Modifier
.PARAMS
:
129 return ParameterAttributes
.None
;
134 /// Returns the signature for this parameter evaluating it on the
137 public string GetSignature (DeclSpace ds
, Location loc
)
139 if (parameter_type
== null){
140 if (!Resolve (ds
, loc
))
144 return ExternalType (ds
, loc
).FullName
;
149 /// Represents the methods parameters
151 public class Parameters
{
152 public Parameter
[] FixedParameters
;
153 public readonly Parameter ArrayParameter
;
158 static Parameters empty_parameters
;
160 public Parameters (Parameter
[] fixed_parameters
, Parameter array_parameter
, Location l
)
162 FixedParameters
= fixed_parameters
;
163 ArrayParameter
= array_parameter
;
168 /// This is used to reuse a set of empty parameters, because they
171 public static Parameters EmptyReadOnlyParameters
{
173 if (empty_parameters
== null)
174 empty_parameters
= new Parameters (null, null, Location
.Null
);
176 return empty_parameters
;
180 public bool HasOptional()
184 foreach (Parameter p
in FixedParameters
)
196 /// Returns the number of standard (i.e. non-optional) parameters
198 public int CountStandardParams()
201 if (FixedParameters
== null)
204 foreach (Parameter p
in FixedParameters
) {
212 /// Returns the number of optional parameters
214 public int CountOptionalParams()
217 if (FixedParameters
== null)
220 foreach (Parameter p
in FixedParameters
) {
227 public Expression
GetDefaultValue (int i
)
229 Parameter p
= FixedParameters
[i
];
231 return p
.ParameterInitializer
;
236 public void AppendParameter (Parameter p
)
238 if (FixedParameters
!= null)
240 Parameter
[] pa
= new Parameter
[FixedParameters
.Length
+1];
241 FixedParameters
.CopyTo (pa
, 0);
242 pa
[FixedParameters
.Length
] = p
;
243 FixedParameters
= pa
;
247 FixedParameters
= new Parameter
[1];
248 FixedParameters
[0] = p
;
252 public void PrependParameter (Parameter p
)
254 Parameter
[] pa
= new Parameter
[FixedParameters
.Length
+1];
255 FixedParameters
.CopyTo (pa
, 1);
257 FixedParameters
= pa
;
260 public Parameters
Copy (Location l
)
262 Parameters p
= new Parameters (null, null, l
);
263 p
.FixedParameters
= new Parameter
[this.FixedParameters
.Length
];
264 this.FixedParameters
.CopyTo (p
.FixedParameters
, 0);
272 return (FixedParameters
== null) && (ArrayParameter
== null);
276 public void ComputeSignature (DeclSpace ds
)
279 if (FixedParameters
!= null){
280 for (int i
= 0; i
< FixedParameters
.Length
; i
++){
281 Parameter par
= FixedParameters
[i
];
283 signature
+= par
.GetSignature (ds
, loc
);
287 // Note: as per the spec, the `params' arguments (ArrayParameter)
288 // are not used in the signature computation for a method
292 static void Error_DuplicateParameterName (string name
)
295 100, "The parameter name `" + name
+ "' is a duplicate");
298 public bool VerifyArgs ()
303 if (FixedParameters
== null)
306 count
= FixedParameters
.Length
;
307 string array_par_name
= ArrayParameter
!= null ? ArrayParameter
.Name
: null;
308 for (i
= 0; i
< count
; i
++){
309 string base_name
= FixedParameters
[i
].Name
;
311 for (j
= i
+ 1; j
< count
; j
++){
312 if (base_name
!= FixedParameters
[j
].Name
)
314 Error_DuplicateParameterName (base_name
);
318 if (base_name
== array_par_name
){
319 Error_DuplicateParameterName (base_name
);
327 /// Returns the signature of the Parameters evaluated in
328 /// the @tc environment
330 public string GetSignature (DeclSpace ds
)
332 if (signature
== null){
334 ComputeSignature (ds
);
341 /// Returns the paramenter information based on the name
343 public Parameter
GetParameterByName (string name
, out int idx
)
348 if (FixedParameters
!= null){
349 foreach (Parameter par
in FixedParameters
){
350 if (par
.Name
== name
){
358 if (ArrayParameter
!= null){
359 if (name
== ArrayParameter
.Name
){
361 return ArrayParameter
;
368 bool ComputeParameterTypes (DeclSpace ds
)
370 int extra
= (ArrayParameter
!= null) ? 1 : 0;
374 if (FixedParameters
== null)
377 pc
= extra
+ FixedParameters
.Length
;
379 types
= new Type
[pc
];
382 FixedParameters
= null;
387 if (FixedParameters
!= null){
388 foreach (Parameter p
in FixedParameters
){
391 if (p
.Resolve (ds
, loc
))
392 t
= p
.ExternalType (ds
, loc
);
402 if (ArrayParameter
.Resolve (ds
, loc
))
403 types
[i
] = ArrayParameter
.ExternalType (ds
, loc
);
417 // This variant is used by Delegates, because they need to
418 // resolve/define names, instead of the plain LookupType
420 public bool ComputeAndDefineParameterTypes (DeclSpace ds
)
422 int extra
= (ArrayParameter
!= null) ? 1 : 0;
426 if (FixedParameters
== null)
429 pc
= extra
+ FixedParameters
.Length
;
431 types
= new Type
[pc
];
434 FixedParameters
= null;
440 if (FixedParameters
!= null){
441 foreach (Parameter p
in FixedParameters
){
444 if (p
.Resolve (ds
, loc
))
445 t
= p
.ExternalType (ds
, loc
);
455 if (ArrayParameter
.Resolve (ds
, loc
))
456 types
[i
] = ArrayParameter
.ExternalType (ds
, loc
);
462 // invalidate the cached types
472 /// Returns the argument types as an array
474 static Type
[] no_types
= new Type
[0];
476 public Type
[] GetParameterInfo (DeclSpace ds
)
481 if (FixedParameters
== null && ArrayParameter
== null)
484 if (ComputeParameterTypes (ds
) == false){
493 /// Returns the type of a given parameter, and stores in the `is_out'
494 /// boolean whether this is an out or ref parameter.
496 /// Note that the returned type will not contain any dereference in this
497 /// case (ie, you get "int" for a ref int instead of "int&"
499 public Type
GetParameterInfo (DeclSpace ds
, int idx
, out Parameter
.Modifier mod
)
501 mod
= Parameter
.Modifier
.NONE
;
504 FixedParameters
= null;
508 if (FixedParameters
== null && ArrayParameter
== null)
512 if (ComputeParameterTypes (ds
) == false)
516 // If this is a request for the variable lenght arg.
518 int array_idx
= (FixedParameters
!= null ? FixedParameters
.Length
: 0);
519 if (idx
== array_idx
)
523 // Otherwise, it is a fixed parameter
525 Parameter p
= FixedParameters
[idx
];
528 if ((mod
& (Parameter
.Modifier
.REF
| Parameter
.Modifier
.OUT
)) != 0)
529 mod
|= Parameter
.Modifier
.ISBYREF
;
531 return p
.ParameterType
;
534 public CallingConventions
GetCallingConvention ()
536 // For now this is the only correc thing to do
537 return CallingConventions
.Standard
;