2009-02-19 Jb Evain <jbevain@novell.com>
[mcs.git] / mcs / parameter.cs
blob392e98d42365ae2b94cdf8e2c91a973ba6d5a8b7
1 //
2 // parameter.cs: Parameter definition.
3 //
4 // Author: Miguel de Icaza (miguel@gnu.org)
5 // Marek Safar (marek.safar@seznam.cz)
6 //
7 // Dual licensed under the terms of the MIT X11 or GNU GPL
8 //
9 // Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
10 // Copyright 2003-2008 Novell, Inc.
13 using System;
14 using System.Reflection;
15 using System.Reflection.Emit;
16 using System.Collections;
17 using System.Text;
19 namespace Mono.CSharp {
21 /// <summary>
22 /// Abstract Base class for parameters of a method.
23 /// </summary>
24 public abstract class ParameterBase : Attributable {
26 protected ParameterBuilder builder;
28 protected ParameterBase (Attributes attrs)
29 : base (attrs)
33 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
35 #if !NET_2_0
36 if (a.Type == TypeManager.marshal_as_attr_type) {
37 UnmanagedMarshal marshal = a.GetMarshal (this);
38 if (marshal != null) {
39 builder.SetMarshal (marshal);
41 return;
43 #endif
44 if (a.HasSecurityAttribute) {
45 a.Error_InvalidSecurityParent ();
46 return;
49 builder.SetCustomAttribute (cb);
52 public override bool IsClsComplianceRequired()
54 return false;
58 /// <summary>
59 /// Class for applying custom attributes on the return type
60 /// </summary>
61 public class ReturnParameter : ParameterBase {
62 public ReturnParameter (MethodBuilder mb, Location location):
63 base (null)
65 try {
66 builder = mb.DefineParameter (0, ParameterAttributes.None, "");
68 catch (ArgumentOutOfRangeException) {
69 Report.RuntimeMissingSupport (location, "custom attributes on the return type");
73 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
75 if (a.Type == TypeManager.cls_compliant_attribute_type) {
76 Report.Warning (3023, 1, a.Location, "CLSCompliant attribute has no meaning when applied to return types. Try putting it on the method instead");
79 // This occurs after Warning -28
80 if (builder == null)
81 return;
83 base.ApplyAttributeBuilder (a, cb);
86 public override AttributeTargets AttributeTargets {
87 get {
88 return AttributeTargets.ReturnValue;
92 public override IResolveContext ResolveContext {
93 get {
94 throw new NotSupportedException ();
98 /// <summary>
99 /// Is never called
100 /// </summary>
101 public override string[] ValidAttributeTargets {
102 get {
103 return null;
108 /// <summary>
109 /// Class for applying custom attributes on the implicit parameter type
110 /// of the 'set' method in properties, and the 'add' and 'remove' methods in events.
111 /// </summary>
112 ///
113 // TODO: should use more code from Parameter.ApplyAttributeBuilder
114 public class ImplicitParameter : ParameterBase {
115 public ImplicitParameter (MethodBuilder mb):
116 base (null)
118 builder = mb.DefineParameter (1, ParameterAttributes.None, "");
121 public override AttributeTargets AttributeTargets {
122 get {
123 return AttributeTargets.Parameter;
127 public override IResolveContext ResolveContext {
128 get {
129 throw new NotSupportedException ();
133 /// <summary>
134 /// Is never called
135 /// </summary>
136 public override string[] ValidAttributeTargets {
137 get {
138 return null;
143 public class ImplicitLambdaParameter : Parameter
145 public ImplicitLambdaParameter (string name, Location loc)
146 : base (null, name, Modifier.NONE, null, loc)
150 public override Type Resolve (IResolveContext ec)
152 if (parameter_type == null)
153 throw new InternalErrorException ("A type of implicit lambda parameter `{0}' is not set",
154 Name);
156 return parameter_type;
159 public Type Type {
160 set { parameter_type = value; }
164 public class ParamsParameter : Parameter {
165 public ParamsParameter (FullNamedExpression type, string name, Attributes attrs, Location loc):
166 base (type, name, Parameter.Modifier.PARAMS, attrs, loc)
170 public override Type Resolve (IResolveContext ec)
172 if (base.Resolve (ec) == null)
173 return null;
175 if (!parameter_type.IsArray || parameter_type.GetArrayRank () != 1) {
176 Report.Error (225, Location, "The params parameter must be a single dimensional array");
177 return null;
180 return parameter_type;
183 public override void ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index)
185 base.ApplyAttributes (mb, cb, index);
187 CustomAttributeBuilder ca = TypeManager.param_array_attr;
188 if (ca == null) {
189 ConstructorInfo ci = TypeManager.GetPredefinedConstructor (TypeManager.param_array_type, Location, Type.EmptyTypes);
190 if (ci == null)
191 return;
193 ca = new CustomAttributeBuilder (ci, new object [0]);
194 if (ca == null)
195 return;
197 TypeManager.param_array_attr = ca;
200 builder.SetCustomAttribute (ca);
204 public class ArglistParameter : Parameter {
205 // Doesn't have proper type because it's never chosen for better conversion
206 public ArglistParameter (Location loc) :
207 base (null, String.Empty, Parameter.Modifier.ARGLIST, null, loc)
211 public override void ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index)
213 // Nothing to do
216 public override bool CheckAccessibility (InterfaceMemberBase member)
218 return true;
221 public override Type Resolve (IResolveContext ec)
223 return typeof (ArglistParameter);
226 public override string GetSignatureForError ()
228 return "__arglist";
232 public interface IParameterData
234 bool HasExtensionMethodModifier { get; }
235 Parameter.Modifier ModFlags { get; }
236 string Name { get; }
240 // Parameter information created by parser
242 public class Parameter : ParameterBase, IParameterData, ILocalVariable {
243 [Flags]
244 public enum Modifier : byte {
245 NONE = 0,
246 REF = REFMASK | ISBYREF,
247 OUT = OUTMASK | ISBYREF,
248 PARAMS = 4,
249 // This is a flag which says that it's either REF or OUT.
250 ISBYREF = 8,
251 ARGLIST = 16,
252 REFMASK = 32,
253 OUTMASK = 64,
254 This = 128
257 static string[] attribute_targets = new string [] { "param" };
259 protected FullNamedExpression TypeName;
260 readonly Modifier modFlags;
261 string name;
262 protected Type parameter_type;
263 public readonly Location Location;
264 int idx;
265 public bool HasAddressTaken;
267 IResolveContext resolve_context;
268 LocalVariableReference expr_tree_variable;
269 static TypeExpr parameter_expr_tree_type;
271 public HoistedVariable HoistedVariableReference;
273 public Parameter (FullNamedExpression type, string name, Modifier mod, Attributes attrs, Location loc)
274 : base (attrs)
276 if (type == TypeManager.system_void_expr)
277 Report.Error (1536, loc, "Invalid parameter type `void'");
279 this.name = name;
280 modFlags = mod;
281 Location = loc;
282 TypeName = type;
285 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
287 if (a.Type == TypeManager.in_attribute_type && ModFlags == Modifier.OUT) {
288 Report.Error (36, a.Location, "An out parameter cannot have the `In' attribute");
289 return;
292 if (a.Type == TypeManager.param_array_type) {
293 Report.Error (674, a.Location, "Do not use `System.ParamArrayAttribute'. Use the `params' keyword instead");
294 return;
297 if (a.Type == TypeManager.out_attribute_type && (ModFlags & Modifier.REF) == Modifier.REF &&
298 TypeManager.in_attribute_type != null && !OptAttributes.Contains (TypeManager.in_attribute_type)) {
299 Report.Error (662, a.Location,
300 "Cannot specify only `Out' attribute on a ref parameter. Use both `In' and `Out' attributes or neither");
301 return;
304 if (a.Type == TypeManager.cls_compliant_attribute_type) {
305 Report.Warning (3022, 1, a.Location, "CLSCompliant attribute has no meaning when applied to parameters. Try putting it on the method instead");
308 // TypeManager.default_parameter_value_attribute_type is null if !NET_2_0, or if System.dll is not referenced
309 if (a.Type == TypeManager.default_parameter_value_attribute_type) {
310 object val = a.GetParameterDefaultValue ();
311 if (val != null) {
312 Type t = val.GetType ();
313 if (t.IsArray || TypeManager.IsSubclassOf (t, TypeManager.type_type)) {
314 if (parameter_type == TypeManager.object_type) {
315 if (!t.IsArray)
316 t = TypeManager.type_type;
318 Report.Error (1910, a.Location, "Argument of type `{0}' is not applicable for the DefaultValue attribute",
319 TypeManager.CSharpName (t));
320 } else {
321 Report.Error (1909, a.Location, "The DefaultValue attribute is not applicable on parameters of type `{0}'",
322 TypeManager.CSharpName (parameter_type)); ;
324 return;
328 if (parameter_type == TypeManager.object_type ||
329 (val == null && !TypeManager.IsGenericParameter (parameter_type) && TypeManager.IsReferenceType (parameter_type)) ||
330 (val != null && TypeManager.TypeToCoreType (val.GetType ()) == parameter_type))
331 builder.SetConstant (val);
332 else
333 Report.Error (1908, a.Location, "The type of the default value should match the type of the parameter");
334 return;
337 base.ApplyAttributeBuilder (a, cb);
340 public virtual bool CheckAccessibility (InterfaceMemberBase member)
342 if (parameter_type == null || TypeManager.IsGenericParameter (parameter_type))
343 return true;
345 return member.IsAccessibleAs (parameter_type);
348 public override IResolveContext ResolveContext {
349 get {
350 return resolve_context;
354 // <summary>
355 // Resolve is used in method definitions
356 // </summary>
357 public virtual Type Resolve (IResolveContext ec)
359 // HACK: to resolve attributes correctly
360 this.resolve_context = ec;
362 if (parameter_type != null)
363 return parameter_type;
365 TypeExpr texpr = TypeName.ResolveAsTypeTerminal (ec, false);
366 if (texpr == null)
367 return null;
369 parameter_type = texpr.Type;
371 if ((modFlags & Parameter.Modifier.ISBYREF) != 0 &&
372 TypeManager.IsSpecialType (parameter_type)) {
373 Report.Error (1601, Location, "Method or delegate parameter cannot be of type `{0}'",
374 GetSignatureForError ());
375 return null;
378 #if GMCS_SOURCE
379 if (parameter_type.IsGenericParameter) {
380 AbstractPropertyEventMethod accessor = ec as AbstractPropertyEventMethod;
381 if (accessor == null || !accessor.IsDummy) {
382 if ((parameter_type.GenericParameterAttributes & GenericParameterAttributes.Covariant) != 0) {
383 Report.Error (-38, Location, "Covariant type parameters cannot be used as method parameters");
384 return null;
385 } else if ((ModFlags & Modifier.ISBYREF) != 0 &&
386 (parameter_type.GenericParameterAttributes & GenericParameterAttributes.Contravariant) != 0) {
387 Report.Error (-37, Location, "Contravariant type parameters cannot be used in output positions");
388 return null;
391 return parameter_type;
393 #endif
395 if ((parameter_type.Attributes & Class.StaticClassAttribute) == Class.StaticClassAttribute) {
396 Report.Error (721, Location, "`{0}': static types cannot be used as parameters",
397 texpr.GetSignatureForError ());
398 return parameter_type;
401 if ((modFlags & Modifier.This) != 0 && parameter_type.IsPointer) {
402 Report.Error (1103, Location, "The type of extension method cannot be `{0}'",
403 TypeManager.CSharpName (parameter_type));
406 return parameter_type;
409 public void ResolveVariable (int idx)
411 this.idx = idx;
414 public bool HasExtensionMethodModifier {
415 get { return (modFlags & Modifier.This) != 0; }
418 public Modifier ModFlags {
419 get { return modFlags & ~Modifier.This; }
422 public string Name {
423 get { return name; }
424 set { name = value; }
427 ParameterAttributes Attributes {
428 get { return ParametersCompiled.GetParameterAttribute (modFlags); }
431 public override AttributeTargets AttributeTargets {
432 get {
433 return AttributeTargets.Parameter;
437 public virtual string GetSignatureForError ()
439 string type_name;
440 if (parameter_type != null)
441 type_name = TypeManager.CSharpName (parameter_type);
442 else
443 type_name = TypeName.GetSignatureForError ();
445 string mod = GetModifierSignature (modFlags);
446 if (mod.Length > 0)
447 return String.Concat (mod, " ", type_name);
449 return type_name;
452 public static string GetModifierSignature (Modifier mod)
454 switch (mod) {
455 case Modifier.OUT:
456 return "out";
457 case Modifier.PARAMS:
458 return "params";
459 case Modifier.REF:
460 return "ref";
461 case Modifier.This:
462 return "this";
463 default:
464 return "";
468 public void IsClsCompliant ()
470 if (AttributeTester.IsClsCompliant (parameter_type))
471 return;
473 Report.Warning (3001, 1, Location, "Argument type `{0}' is not CLS-compliant", GetSignatureForError ());
476 public virtual void ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index)
478 if (mb == null)
479 builder = cb.DefineParameter (index, Attributes, Name);
480 else
481 builder = mb.DefineParameter (index, Attributes, Name);
483 if (OptAttributes != null)
484 OptAttributes.Emit ();
487 public override string[] ValidAttributeTargets {
488 get {
489 return attribute_targets;
493 public Parameter Clone ()
495 Parameter p = (Parameter) MemberwiseClone ();
496 if (attributes != null) {
497 p.attributes = attributes.Clone ();
498 p.attributes.AttachTo (p);
501 return p;
504 public ExpressionStatement CreateExpressionTreeVariable (EmitContext ec)
506 if ((modFlags & Modifier.ISBYREF) != 0)
507 Report.Error (1951, Location, "An expression tree parameter cannot use `ref' or `out' modifier");
509 LocalInfo variable = ec.CurrentBlock.AddTemporaryVariable (
510 ResolveParameterExpressionType (ec, Location), Location);
511 variable.Resolve (ec);
513 expr_tree_variable = new LocalVariableReference (
514 ec.CurrentBlock, variable.Name, Location, variable, false);
516 ArrayList arguments = new ArrayList (2);
517 arguments.Add (new Argument (new TypeOf (
518 new TypeExpression (parameter_type, Location), Location)));
519 arguments.Add (new Argument (new StringConstant (Name, Location)));
520 return new SimpleAssign (ExpressionTreeVariableReference (),
521 Expression.CreateExpressionFactoryCall ("Parameter", null, arguments, Location));
524 public void Emit (EmitContext ec)
526 int arg_idx = idx;
527 if (!ec.IsStatic)
528 arg_idx++;
530 ParameterReference.EmitLdArg (ec.ig, arg_idx);
533 public void EmitAssign (EmitContext ec)
535 int arg_idx = idx;
536 if (!ec.IsStatic)
537 arg_idx++;
539 if (arg_idx <= 255)
540 ec.ig.Emit (OpCodes.Starg_S, (byte) arg_idx);
541 else
542 ec.ig.Emit (OpCodes.Starg, arg_idx);
545 public void EmitAddressOf (EmitContext ec)
547 int arg_idx = idx;
549 if (!ec.IsStatic)
550 arg_idx++;
552 bool is_ref = (ModFlags & Modifier.ISBYREF) != 0;
553 if (is_ref) {
554 ParameterReference.EmitLdArg (ec.ig, arg_idx);
555 } else {
556 if (arg_idx <= 255)
557 ec.ig.Emit (OpCodes.Ldarga_S, (byte) arg_idx);
558 else
559 ec.ig.Emit (OpCodes.Ldarga, arg_idx);
563 public Expression ExpressionTreeVariableReference ()
565 return expr_tree_variable;
569 // System.Linq.Expressions.ParameterExpression type
571 public static TypeExpr ResolveParameterExpressionType (EmitContext ec, Location location)
573 if (parameter_expr_tree_type != null)
574 return parameter_expr_tree_type;
576 Type p_type = TypeManager.parameter_expression_type;
577 if (p_type == null) {
578 p_type = TypeManager.CoreLookupType ("System.Linq.Expressions", "ParameterExpression", Kind.Class, true);
579 TypeManager.parameter_expression_type = p_type;
582 parameter_expr_tree_type = new TypeExpression (p_type, location).
583 ResolveAsTypeTerminal (ec, false);
585 return parameter_expr_tree_type;
590 // Imported or resolved parameter information
592 public class ParameterData : IParameterData
594 readonly string name;
595 readonly Parameter.Modifier modifiers;
597 public ParameterData (string name, Parameter.Modifier modifiers)
599 this.name = name;
600 this.modifiers = modifiers;
603 #region IParameterData Members
605 public bool HasExtensionMethodModifier {
606 get { return (modifiers & Parameter.Modifier.This) != 0; }
609 public Parameter.Modifier ModFlags {
610 get { return modifiers & ~Parameter.Modifier.This; }
613 public string Name {
614 get { return name; }
617 #endregion
620 public abstract class AParametersCollection
622 protected bool has_arglist;
623 protected bool has_params;
625 // Null object pattern
626 protected IParameterData [] parameters;
627 protected Type [] types;
629 public int Count {
630 get { return parameters.Length; }
633 public Type ExtensionMethodType {
634 get {
635 if (Count == 0)
636 return null;
638 return FixedParameters [0].HasExtensionMethodModifier ?
639 types [0] : null;
643 public IParameterData [] FixedParameters {
644 get {
645 return parameters;
649 public static ParameterAttributes GetParameterAttribute (Parameter.Modifier modFlags)
651 return (modFlags & Parameter.Modifier.OUT) == Parameter.Modifier.OUT ?
652 ParameterAttributes.Out : ParameterAttributes.None;
655 public Type [] GetEmitTypes ()
657 Type [] types = null;
658 if (has_arglist) {
659 if (Count == 1)
660 return Type.EmptyTypes;
662 types = new Type [Count - 1];
663 Array.Copy (Types, types, types.Length);
666 for (int i = 0; i < Count; ++i) {
667 if ((FixedParameters [i].ModFlags & Parameter.Modifier.ISBYREF) == 0)
668 continue;
670 if (types == null)
671 types = (Type []) Types.Clone ();
673 types [i] = TypeManager.GetReferenceType (types [i]);
676 if (types == null)
677 types = Types;
679 return types;
682 public string GetSignatureForError ()
684 StringBuilder sb = new StringBuilder ("(");
685 for (int i = 0; i < Count; ++i) {
686 if (i != 0)
687 sb.Append (", ");
688 sb.Append (ParameterDesc (i));
690 sb.Append (')');
691 return sb.ToString ();
694 public bool HasArglist {
695 get { return has_arglist; }
698 public bool HasExtensionMethodType {
699 get {
700 if (Count == 0)
701 return false;
703 return FixedParameters [0].HasExtensionMethodModifier;
707 public bool HasParams {
708 get { return has_params; }
711 public bool IsEmpty {
712 get { return parameters.Length == 0; }
715 public string ParameterDesc (int pos)
717 if (types == null || types [pos] == null)
718 return ((Parameter)FixedParameters [pos]).GetSignatureForError ();
720 string type = TypeManager.CSharpName (types [pos]);
721 if (FixedParameters [pos].HasExtensionMethodModifier)
722 return "this " + type;
724 Parameter.Modifier mod = FixedParameters [pos].ModFlags & ~Parameter.Modifier.ARGLIST;
725 if (mod == 0)
726 return type;
728 return Parameter.GetModifierSignature (mod) + " " + type;
731 public Type[] Types {
732 get { return types; }
733 set { types = value; }
736 #if MS_COMPATIBLE
737 public AParametersCollection InflateTypes (Type[] genArguments, Type[] argTypes)
739 AParametersCollection p = (AParametersCollection) MemberwiseClone (); // Clone ();
741 for (int i = 0; i < Count; ++i) {
742 if (types[i].IsGenericType) {
743 Type[] gen_arguments_open = new Type[types[i].GetGenericTypeDefinition ().GetGenericArguments ().Length];
744 Type[] gen_arguments = types[i].GetGenericArguments ();
745 for (int ii = 0; ii < gen_arguments_open.Length; ++ii) {
746 if (gen_arguments[ii].IsGenericParameter) {
747 Type t = argTypes[gen_arguments[ii].GenericParameterPosition];
748 gen_arguments_open[ii] = t;
749 } else
750 gen_arguments_open[ii] = gen_arguments[ii];
753 p.types[i] = types[i].GetGenericTypeDefinition ().MakeGenericType (gen_arguments_open);
754 continue;
757 if (types[i].IsGenericParameter) {
758 Type gen_argument = argTypes[types[i].GenericParameterPosition];
759 p.types[i] = gen_argument;
760 continue;
764 return p;
766 #endif
770 // A collection of imported or resolved parameters
772 public class ParametersImported : AParametersCollection
774 ParametersImported (AParametersCollection param, Type[] types)
776 this.parameters = param.FixedParameters;
777 this.types = types;
778 has_arglist = param.HasArglist;
779 has_params = param.HasParams;
782 ParametersImported (IParameterData [] parameters, Type [] types, MethodBase method, bool hasParams)
784 this.parameters = parameters;
785 this.types = types;
786 has_arglist = (method.CallingConvention & CallingConventions.VarArgs) != 0;
787 if (has_arglist) {
788 this.parameters = new IParameterData [parameters.Length + 1];
789 parameters.CopyTo (this.parameters, 0);
790 this.parameters [parameters.Length] = new ArglistParameter (Location.Null);
791 this.types = new Type [types.Length + 1];
792 types.CopyTo (this.types, 0);
793 this.types [types.Length] = TypeManager.arg_iterator_type;
795 has_params = hasParams;
798 public ParametersImported (IParameterData [] param, Type[] types)
800 this.parameters = param;
801 this.types = types;
804 public static AParametersCollection Create (MethodBase method)
806 return Create (method.GetParameters (), method);
810 // Generic method parameters importer, param is shared between all instances
812 public static AParametersCollection Create (AParametersCollection param, MethodBase method)
814 if (param.IsEmpty)
815 return param;
817 ParameterInfo [] pi = method.GetParameters ();
818 Type [] types = new Type [pi.Length];
819 for (int i = 0; i < types.Length; i++) {
820 Type t = pi [i].ParameterType;
821 if (t.IsByRef)
822 t = TypeManager.GetElementType (t);
824 types [i] = TypeManager.TypeToCoreType (t);
827 return new ParametersImported (param, types);
831 // Imports SRE parameters
833 public static AParametersCollection Create (ParameterInfo [] pi, MethodBase method)
835 if (pi.Length == 0) {
836 if (method != null && (method.CallingConvention & CallingConventions.VarArgs) != 0)
837 return new ParametersImported (new IParameterData [0], Type.EmptyTypes, method, false);
839 return ParametersCompiled.EmptyReadOnlyParameters;
842 Type [] types = new Type [pi.Length];
843 IParameterData [] par = new IParameterData [pi.Length];
844 bool is_params = false;
845 for (int i = 0; i < types.Length; i++) {
846 types [i] = TypeManager.TypeToCoreType (pi [i].ParameterType);
848 ParameterInfo p = pi [i];
849 Parameter.Modifier mod = 0;
850 if (types [i].IsByRef) {
851 if ((p.Attributes & (ParameterAttributes.Out | ParameterAttributes.In)) == ParameterAttributes.Out)
852 mod = Parameter.Modifier.OUT;
853 else
854 mod = Parameter.Modifier.REF;
857 // Strip reference wrapping
859 types [i] = TypeManager.GetElementType (types [i]);
860 } else if (i == 0 && TypeManager.extension_attribute_type != null && method != null && method.IsStatic &&
861 (method.DeclaringType.Attributes & Class.StaticClassAttribute) == Class.StaticClassAttribute &&
862 method.IsDefined (TypeManager.extension_attribute_type, false)) {
863 mod = Parameter.Modifier.This;
864 } else if (i >= pi.Length - 2 && types [i].IsArray) {
865 if (p.IsDefined (TypeManager.param_array_type, false)) {
866 mod = Parameter.Modifier.PARAMS;
867 is_params = true;
871 par [i] = new ParameterData (p.Name, mod);
874 return method != null ?
875 new ParametersImported (par, types, method, is_params) :
876 new ParametersImported (par, types);
880 /// <summary>
881 /// Represents the methods parameters
882 /// </summary>
883 public class ParametersCompiled : AParametersCollection
885 public static readonly ParametersCompiled EmptyReadOnlyParameters = new ParametersCompiled ();
887 // Used by C# 2.0 delegates
888 public static readonly ParametersCompiled Undefined = new ParametersCompiled ();
890 private ParametersCompiled ()
892 parameters = new Parameter [0];
893 types = Type.EmptyTypes;
896 private ParametersCompiled (Parameter [] parameters, Type [] types)
898 this.parameters = parameters;
899 this.types = types;
902 public ParametersCompiled (params Parameter[] parameters)
904 if (parameters == null)
905 throw new ArgumentException ("Use EmptyReadOnlyParameters");
907 this.parameters = parameters;
908 int count = parameters.Length;
910 if (count == 0)
911 return;
913 if (count == 1) {
914 has_params = (parameters [0].ModFlags & Parameter.Modifier.PARAMS) != 0;
915 return;
918 for (int i = 0; i < count; i++){
919 string base_name = parameters [i].Name;
920 has_params |= (parameters [i].ModFlags & Parameter.Modifier.PARAMS) != 0;
922 for (int j = i + 1; j < count; j++){
923 if (base_name != parameters [j].Name)
924 continue;
926 ErrorDuplicateName (parameters [i]);
927 i = j;
932 public ParametersCompiled (Parameter [] parameters, bool has_arglist) :
933 this (parameters)
935 this.has_arglist = has_arglist;
938 public static ParametersCompiled CreateFullyResolved (Parameter p, Type type)
940 return new ParametersCompiled (new Parameter [] { p }, new Type [] { type });
943 public static ParametersCompiled CreateFullyResolved (Parameter[] parameters, Type[] types)
945 return new ParametersCompiled (parameters, types);
948 public static ParametersCompiled MergeGenerated (ParametersCompiled userParams, bool checkConflicts, Parameter compilerParams, Type compilerTypes)
950 return MergeGenerated (userParams, checkConflicts,
951 new Parameter [] { compilerParams },
952 new Type [] { compilerTypes });
956 // Use this method when you merge compiler generated parameters with user parameters
958 public static ParametersCompiled MergeGenerated (ParametersCompiled userParams, bool checkConflicts, Parameter[] compilerParams, Type[] compilerTypes)
960 Parameter[] all_params = new Parameter [userParams.Count + compilerParams.Length];
961 userParams.FixedParameters.CopyTo(all_params, 0);
963 Type [] all_types;
964 if (userParams.types != null) {
965 all_types = new Type [all_params.Length];
966 userParams.Types.CopyTo (all_types, 0);
967 } else {
968 all_types = null;
971 int last_filled = userParams.Count;
972 int index = 0;
973 foreach (Parameter p in compilerParams) {
974 for (int i = 0; i < last_filled; ++i) {
975 while (p.Name == all_params [i].Name) {
976 if (checkConflicts && i < userParams.Count) {
977 Report.Error (316, userParams [i].Location,
978 "The parameter name `{0}' conflicts with a compiler generated name", p.Name);
980 p.Name = '_' + p.Name;
983 all_params [last_filled] = p;
984 if (all_types != null)
985 all_types [last_filled] = compilerTypes [index++];
986 ++last_filled;
989 ParametersCompiled parameters = new ParametersCompiled (all_params, all_types);
990 parameters.has_params = userParams.has_params;
991 return parameters;
994 protected virtual void ErrorDuplicateName (Parameter p)
996 Report.Error (100, p.Location, "The parameter name `{0}' is a duplicate", p.Name);
999 /// <summary>
1000 /// Returns the parameter information based on the name
1001 /// </summary>
1002 public int GetParameterIndexByName (string name)
1004 for (int idx = 0; idx < Count; ++idx) {
1005 if (parameters [idx].Name == name)
1006 return idx;
1009 return -1;
1012 public bool Resolve (IResolveContext ec)
1014 if (types != null)
1015 return true;
1017 types = new Type [Count];
1019 bool ok = true;
1020 Parameter p;
1021 for (int i = 0; i < FixedParameters.Length; ++i) {
1022 p = this [i];
1023 Type t = p.Resolve (ec);
1024 if (t == null) {
1025 ok = false;
1026 continue;
1029 types [i] = t;
1032 return ok;
1035 public void ResolveVariable ()
1037 for (int i = 0; i < FixedParameters.Length; ++i) {
1038 this [i].ResolveVariable (i);
1042 public CallingConventions CallingConvention
1044 get {
1045 if (HasArglist)
1046 return CallingConventions.VarArgs;
1047 else
1048 return CallingConventions.Standard;
1052 // Define each type attribute (in/out/ref) and
1053 // the argument names.
1054 public void ApplyAttributes (MethodBase builder)
1056 if (Count == 0)
1057 return;
1059 MethodBuilder mb = builder as MethodBuilder;
1060 ConstructorBuilder cb = builder as ConstructorBuilder;
1062 for (int i = 0; i < Count; i++) {
1063 this [i].ApplyAttributes (mb, cb, i + 1);
1067 public void VerifyClsCompliance ()
1069 foreach (Parameter p in FixedParameters)
1070 p.IsClsCompliant ();
1073 public Parameter this [int pos] {
1074 get { return (Parameter) parameters [pos]; }
1077 public Expression CreateExpressionTree (EmitContext ec, Location loc)
1079 ArrayList initializers = new ArrayList (Count);
1080 foreach (Parameter p in FixedParameters) {
1082 // Each parameter expression is stored to local variable
1083 // to save some memory when referenced later.
1085 StatementExpression se = new StatementExpression (p.CreateExpressionTreeVariable (ec));
1086 if (se.Resolve (ec))
1087 ec.CurrentBlock.AddScopeStatement (se);
1089 initializers.Add (p.ExpressionTreeVariableReference ());
1092 return new ArrayCreation (
1093 Parameter.ResolveParameterExpressionType (ec, loc),
1094 "[]", initializers, loc);
1097 public ParametersCompiled Clone ()
1099 ParametersCompiled p = (ParametersCompiled) MemberwiseClone ();
1101 p.parameters = new IParameterData [parameters.Length];
1102 for (int i = 0; i < Count; ++i)
1103 p.parameters [i] = this [i].Clone ();
1105 return p;