2 // parameter.cs: Parameter definition.
4 // Author: Miguel de Icaza (miguel@gnu.org)
5 // Marek Safar (marek.safar@seznam.cz)
7 // Dual licensed under the terms of the MIT X11 or GNU GPL
9 // Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
10 // Copyright 2003-2008 Novell, Inc.
14 using System.Reflection;
15 using System.Reflection.Emit;
18 namespace Mono.CSharp {
21 /// Abstract Base class for parameters of a method.
23 public abstract class ParameterBase : Attributable
25 protected ParameterBuilder builder;
27 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
30 if (a.Type == pa.MarshalAs) {
31 UnmanagedMarshal marshal = a.GetMarshal (this);
32 if (marshal != null) {
33 builder.SetMarshal (marshal);
38 if (a.HasSecurityAttribute) {
39 a.Error_InvalidSecurityParent ();
43 if (a.Type == pa.Dynamic) {
44 a.Error_MisusedDynamicAttribute ();
48 builder.SetCustomAttribute (cb);
51 public ParameterBuilder Builder {
57 public override bool IsClsComplianceRequired()
64 /// Class for applying custom attributes on the return type
66 public class ReturnParameter : ParameterBase
70 // TODO: merge method and mb
71 public ReturnParameter (MemberCore method, MethodBuilder mb, Location location)
75 builder = mb.DefineParameter (0, ParameterAttributes.None, "");
77 catch (ArgumentOutOfRangeException) {
78 method.Compiler.Report.RuntimeMissingSupport (location, "custom attributes on the return type");
82 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
84 if (a.Type == pa.CLSCompliant) {
85 method.Compiler.Report.Warning (3023, 1, a.Location,
86 "CLSCompliant attribute has no meaning when applied to return types. Try putting it on the method instead");
89 // This occurs after Warning -28
93 base.ApplyAttributeBuilder (a, cb, pa);
96 public override AttributeTargets AttributeTargets {
98 return AttributeTargets.ReturnValue;
105 public override string[] ValidAttributeTargets {
113 /// Class for applying custom attributes on the implicit parameter type
114 /// of the 'set' method in properties, and the 'add' and 'remove' methods in events.
117 // TODO: should use more code from Parameter.ApplyAttributeBuilder
118 public class ImplicitParameter : ParameterBase {
119 public ImplicitParameter (MethodBuilder mb)
121 builder = mb.DefineParameter (1, ParameterAttributes.None, "value");
124 public override AttributeTargets AttributeTargets {
126 return AttributeTargets.Parameter;
133 public override string[] ValidAttributeTargets {
140 public class ImplicitLambdaParameter : Parameter
142 public ImplicitLambdaParameter (string name, Location loc)
143 : base (null, name, Modifier.NONE, null, loc)
147 public override Type Resolve (IMemberContext ec)
149 if (parameter_type == null)
150 throw new InternalErrorException ("A type of implicit lambda parameter `{0}' is not set",
153 return parameter_type;
157 set { parameter_type = value; }
161 public class ParamsParameter : Parameter {
162 public ParamsParameter (FullNamedExpression type, string name, Attributes attrs, Location loc):
163 base (type, name, Parameter.Modifier.PARAMS, attrs, loc)
167 public override Type Resolve (IMemberContext ec)
169 if (base.Resolve (ec) == null)
172 if (!parameter_type.IsArray || parameter_type.GetArrayRank () != 1) {
173 ec.Compiler.Report.Error (225, Location, "The params parameter must be a single dimensional array");
177 return parameter_type;
180 public override void ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index)
182 base.ApplyAttributes (mb, cb, index);
183 PredefinedAttributes.Get.ParamArray.EmitAttribute (builder);
187 public class ArglistParameter : Parameter {
188 // Doesn't have proper type because it's never chosen for better conversion
189 public ArglistParameter (Location loc) :
190 base (null, String.Empty, Parameter.Modifier.NONE, null, loc)
194 public override void ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index)
199 public override bool CheckAccessibility (InterfaceMemberBase member)
204 public override Type Resolve (IMemberContext ec)
206 return InternalType.Arglist;
209 public override string GetSignatureForError ()
215 public interface IParameterData
217 Expression DefaultValue { get; }
218 bool HasExtensionMethodModifier { get; }
219 bool HasDefaultValue { get; }
220 Parameter.Modifier ModFlags { get; }
225 // Parameter information created by parser
227 public class Parameter : ParameterBase, IParameterData, ILocalVariable {
229 public enum Modifier : byte {
231 REF = REFMASK | ISBYREF,
232 OUT = OUTMASK | ISBYREF,
234 // This is a flag which says that it's either REF or OUT.
241 static string[] attribute_targets = new string [] { "param" };
243 protected FullNamedExpression TypeName;
244 readonly Modifier modFlags;
246 Expression default_expr;
247 protected Type parameter_type;
248 public readonly Location Location;
250 public bool HasAddressTaken;
252 Expression expr_tree_variable;
253 static TypeExpr parameter_expr_tree_type;
255 HoistedVariable hoisted_variant;
257 public Parameter (FullNamedExpression type, string name, Modifier mod, Attributes attrs, Location loc)
264 // Only assign, attributes will be attached during resolve
265 base.attributes = attrs;
268 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
270 if (a.Type == pa.In && ModFlags == Modifier.OUT) {
271 a.Report.Error (36, a.Location, "An out parameter cannot have the `In' attribute");
275 if (a.Type == pa.ParamArray) {
276 a.Report.Error (674, a.Location, "Do not use `System.ParamArrayAttribute'. Use the `params' keyword instead");
280 if (a.Type == PredefinedAttributes.Get.Out && (ModFlags & Modifier.REF) == Modifier.REF &&
281 !OptAttributes.Contains (pa.In)) {
282 a.Report.Error (662, a.Location,
283 "Cannot specify only `Out' attribute on a ref parameter. Use both `In' and `Out' attributes or neither");
287 if (a.Type == pa.CLSCompliant) {
288 a.Report.Warning (3022, 1, a.Location, "CLSCompliant attribute has no meaning when applied to parameters. Try putting it on the method instead");
291 if (HasDefaultValue && (a.Type == pa.DefaultParameterValue || a.Type == pa.OptionalParameter)) {
292 a.Report.Error (1745, a.Location,
293 "Cannot specify `{0}' attribute on optional parameter `{1}'",
294 TypeManager.CSharpName (a.Type).Replace ("Attribute", ""), Name);
298 if (a.Type == pa.DefaultParameterValue) {
299 object val = a.GetParameterDefaultValue ();
301 Type t = val.GetType ();
302 if (t.IsArray || TypeManager.IsSubclassOf (t, TypeManager.type_type)) {
303 if (parameter_type == TypeManager.object_type) {
305 t = TypeManager.type_type;
307 a.Report.Error (1910, a.Location, "Argument of type `{0}' is not applicable for the DefaultParameterValue attribute",
308 TypeManager.CSharpName (t));
310 a.Report.Error (1909, a.Location, "The DefaultParameterValue attribute is not applicable on parameters of type `{0}'",
311 TypeManager.CSharpName (parameter_type)); ;
317 if (parameter_type == TypeManager.object_type ||
318 (val == null && !TypeManager.IsGenericParameter (parameter_type) && TypeManager.IsReferenceType (parameter_type)) ||
319 (val != null && TypeManager.TypeToCoreType (val.GetType ()) == parameter_type))
320 builder.SetConstant (val);
322 a.Report.Error (1908, a.Location, "The type of the default value should match the type of the parameter");
326 base.ApplyAttributeBuilder (a, cb, pa);
329 public virtual bool CheckAccessibility (InterfaceMemberBase member)
331 if (parameter_type == null || TypeManager.IsGenericParameter (parameter_type))
334 return member.IsAccessibleAs (parameter_type);
338 // Resolve is used in method definitions
340 public virtual Type Resolve (IMemberContext rc)
342 if (parameter_type != null)
343 return parameter_type;
345 if (attributes != null)
346 attributes.AttachTo (this, rc);
348 TypeExpr texpr = TypeName.ResolveAsTypeTerminal (rc, false);
352 parameter_type = texpr.Type;
354 // Ignore all checks for dummy members
355 AbstractPropertyEventMethod pem = rc as AbstractPropertyEventMethod;
356 if (pem != null && pem.IsDummy)
357 return parameter_type;
359 if (default_expr != null)
360 default_expr = ResolveDefaultValue (new ResolveContext (rc));
362 if ((modFlags & Parameter.Modifier.ISBYREF) != 0 &&
363 TypeManager.IsSpecialType (parameter_type)) {
364 rc.Compiler.Report.Error (1601, Location, "Method or delegate parameter cannot be of type `{0}'",
365 GetSignatureForError ());
369 TypeManager.CheckTypeVariance (parameter_type,
370 (modFlags & Parameter.Modifier.ISBYREF) != 0 ? Variance.None : Variance.Contravariant,
373 if (TypeManager.IsGenericParameter (parameter_type))
374 return parameter_type;
376 if ((parameter_type.Attributes & Class.StaticClassAttribute) == Class.StaticClassAttribute) {
377 rc.Compiler.Report.Error (721, Location, "`{0}': static types cannot be used as parameters",
378 texpr.GetSignatureForError ());
379 return parameter_type;
382 if ((modFlags & Modifier.This) != 0 && (parameter_type.IsPointer || TypeManager.IsDynamicType (parameter_type))) {
383 rc.Compiler.Report.Error (1103, Location, "The extension method cannot be of type `{0}'",
384 TypeManager.CSharpName (parameter_type));
387 return parameter_type;
390 Expression ResolveDefaultValue (ResolveContext rc)
392 default_expr = default_expr.Resolve (rc);
393 if (default_expr == null)
396 if (!(default_expr is Constant || default_expr is DefaultValueExpression)) {
397 if (TypeManager.IsNullableType (parameter_type)) {
398 rc.Compiler.Report.Error (1770, default_expr.Location,
399 "The expression being assigned to nullable optional parameter `{0}' must be default value",
402 rc.Compiler.Report.Error (1736, default_expr.Location,
403 "The expression being assigned to optional parameter `{0}' must be a constant or default value",
410 if (TypeManager.IsEqual (default_expr.Type, parameter_type))
413 if (TypeManager.IsNullableType (parameter_type)) {
414 if (Convert.ImplicitNulableConversion (rc, default_expr, parameter_type) != null)
417 var res = Convert.ImplicitConversionStandard (rc, default_expr, parameter_type, default_expr.Location);
419 if (!default_expr.IsNull && TypeManager.IsReferenceType (parameter_type) && parameter_type != TypeManager.string_type) {
420 rc.Compiler.Report.Error (1763, default_expr.Location,
421 "Optional parameter `{0}' of type `{1}' can only be initialized with `null'",
422 Name, GetSignatureForError ());
431 rc.Compiler.Report.Error (1750, Location,
432 "Optional parameter expression of type `{0}' cannot be converted to parameter type `{1}'",
433 TypeManager.CSharpName (default_expr.Type), GetSignatureForError ());
438 public void ResolveVariable (int idx)
443 public bool HasDefaultValue {
444 get { return default_expr != null; }
447 public bool HasExtensionMethodModifier {
448 get { return (modFlags & Modifier.This) != 0; }
452 // Hoisted parameter variant
454 public HoistedVariable HoistedVariant {
456 return hoisted_variant;
459 hoisted_variant = value;
463 public Modifier ModFlags {
464 get { return modFlags & ~Modifier.This; }
469 set { name = value; }
472 ParameterAttributes Attributes {
473 get { return ParametersCompiled.GetParameterAttribute (modFlags) |
474 (HasDefaultValue ? ParameterAttributes.Optional : ParameterAttributes.None); }
477 public override AttributeTargets AttributeTargets {
479 return AttributeTargets.Parameter;
483 public virtual string GetSignatureForError ()
486 if (parameter_type != null)
487 type_name = TypeManager.CSharpName (parameter_type);
489 type_name = TypeName.GetSignatureForError ();
491 string mod = GetModifierSignature (modFlags);
493 return String.Concat (mod, " ", type_name);
498 public static string GetModifierSignature (Modifier mod)
503 case Modifier.PARAMS:
514 public void IsClsCompliant (IMemberContext ctx)
516 if (AttributeTester.IsClsCompliant (parameter_type))
519 ctx.Compiler.Report.Warning (3001, 1, Location,
520 "Argument type `{0}' is not CLS-compliant", GetSignatureForError ());
523 public virtual void ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index)
526 builder = cb.DefineParameter (index, Attributes, Name);
528 builder = mb.DefineParameter (index, Attributes, Name);
530 if (OptAttributes != null)
531 OptAttributes.Emit ();
533 if (HasDefaultValue) {
535 // Emit constant values for true constants only, the other
536 // constant-like expressions will rely on default value expression
538 Constant c = default_expr as Constant;
540 if (default_expr.Type == TypeManager.decimal_type) {
541 builder.SetCustomAttribute (Const.CreateDecimalConstantAttribute (c));
543 builder.SetConstant (c.GetTypedValue ());
548 if (TypeManager.IsDynamicType (parameter_type)) {
549 PredefinedAttributes.Get.Dynamic.EmitAttribute (builder);
551 var trans_flags = TypeManager.HasDynamicTypeUsed (parameter_type);
552 if (trans_flags != null) {
553 var pa = PredefinedAttributes.Get.DynamicTransform;
554 if (pa.Constructor != null || pa.ResolveConstructor (Location, TypeManager.bool_type.MakeArrayType ())) {
555 builder.SetCustomAttribute (
556 new CustomAttributeBuilder (pa.Constructor, new object [] { trans_flags }));
562 public override string[] ValidAttributeTargets {
564 return attribute_targets;
568 public Parameter Clone ()
570 Parameter p = (Parameter) MemberwiseClone ();
571 if (attributes != null)
572 p.attributes = attributes.Clone ();
577 public ExpressionStatement CreateExpressionTreeVariable (BlockContext ec)
579 if ((modFlags & Modifier.ISBYREF) != 0)
580 ec.Report.Error (1951, Location, "An expression tree parameter cannot use `ref' or `out' modifier");
582 expr_tree_variable = new TemporaryVariable (ResolveParameterExpressionType (ec, Location).Type, Location);
583 expr_tree_variable = expr_tree_variable.Resolve (ec);
585 Arguments arguments = new Arguments (2);
586 arguments.Add (new Argument (new TypeOf (
587 new TypeExpression (parameter_type, Location), Location)));
588 arguments.Add (new Argument (new StringConstant (Name, Location)));
589 return new SimpleAssign (ExpressionTreeVariableReference (),
590 Expression.CreateExpressionFactoryCall (ec, "Parameter", null, arguments, Location));
593 public Expression DefaultValue {
594 get { return default_expr; }
595 set { default_expr = value; }
598 public void Emit (EmitContext ec)
604 ParameterReference.EmitLdArg (ec.ig, arg_idx);
607 public void EmitAssign (EmitContext ec)
614 ec.ig.Emit (OpCodes.Starg_S, (byte) arg_idx);
616 ec.ig.Emit (OpCodes.Starg, arg_idx);
619 public void EmitAddressOf (EmitContext ec)
626 bool is_ref = (ModFlags & Modifier.ISBYREF) != 0;
628 ParameterReference.EmitLdArg (ec.ig, arg_idx);
631 ec.ig.Emit (OpCodes.Ldarga_S, (byte) arg_idx);
633 ec.ig.Emit (OpCodes.Ldarga, arg_idx);
637 public Expression ExpressionTreeVariableReference ()
639 return expr_tree_variable;
643 // System.Linq.Expressions.ParameterExpression type
645 public static TypeExpr ResolveParameterExpressionType (IMemberContext ec, Location location)
647 if (parameter_expr_tree_type != null)
648 return parameter_expr_tree_type;
650 Type p_type = TypeManager.parameter_expression_type;
651 if (p_type == null) {
652 p_type = TypeManager.CoreLookupType (ec.Compiler, "System.Linq.Expressions", "ParameterExpression", MemberKind.Class, true);
653 TypeManager.parameter_expression_type = p_type;
656 parameter_expr_tree_type = new TypeExpression (p_type, location).
657 ResolveAsTypeTerminal (ec, false);
659 return parameter_expr_tree_type;
662 public void Warning_UselessOptionalParameter (Report Report)
664 Report.Warning (1066, 1, Location,
665 "The default value specified for optional parameter `{0}' will never be used",
671 // Imported or resolved parameter information
673 public class ParameterData : IParameterData
675 readonly string name;
676 readonly Parameter.Modifier modifiers;
677 readonly Expression default_value;
679 public ParameterData (string name, Parameter.Modifier modifiers)
682 this.modifiers = modifiers;
685 public ParameterData (string name, Parameter.Modifier modifiers, Expression defaultValue)
686 : this (name, modifiers)
688 this.default_value = defaultValue;
691 #region IParameterData Members
693 public Expression DefaultValue {
694 get { return default_value; }
697 public bool HasExtensionMethodModifier {
698 get { return (modifiers & Parameter.Modifier.This) != 0; }
701 public bool HasDefaultValue {
702 get { return default_value != null; }
705 public Parameter.Modifier ModFlags {
706 get { return modifiers & ~Parameter.Modifier.This; }
716 public abstract class AParametersCollection
718 protected bool has_arglist;
719 protected bool has_params;
721 // Null object pattern
722 protected IParameterData [] parameters;
723 protected Type [] types;
725 public ParametersCompiled AsCompiled {
726 get { return (ParametersCompiled) this; }
729 public CallingConventions CallingConvention {
732 CallingConventions.VarArgs :
733 CallingConventions.Standard;
738 get { return parameters.Length; }
741 public Type ExtensionMethodType {
746 return FixedParameters [0].HasExtensionMethodModifier ?
751 public IParameterData [] FixedParameters {
757 public static ParameterAttributes GetParameterAttribute (Parameter.Modifier modFlags)
759 return (modFlags & Parameter.Modifier.OUT) == Parameter.Modifier.OUT ?
760 ParameterAttributes.Out : ParameterAttributes.None;
763 public Type [] GetEmitTypes ()
765 Type [] types = null;
768 return Type.EmptyTypes;
770 types = new Type [Count - 1];
771 Array.Copy (Types, types, types.Length);
774 for (int i = 0; i < Count; ++i) {
775 if ((FixedParameters [i].ModFlags & Parameter.Modifier.ISBYREF) == 0)
779 types = (Type []) Types.Clone ();
781 types [i] = TypeManager.GetReferenceType (types [i]);
791 // Returns the parameter information based on the name
793 public int GetParameterIndexByName (string name)
795 for (int idx = 0; idx < Count; ++idx) {
796 if (parameters [idx].Name == name)
803 public string GetSignatureForError ()
805 StringBuilder sb = new StringBuilder ("(");
806 for (int i = 0; i < Count; ++i) {
809 sb.Append (ParameterDesc (i));
812 return sb.ToString ();
815 public bool HasArglist {
816 get { return has_arglist; }
819 public bool HasExtensionMethodType {
824 return FixedParameters [0].HasExtensionMethodModifier;
828 public bool HasParams {
829 get { return has_params; }
832 public bool IsEmpty {
833 get { return parameters.Length == 0; }
836 public string ParameterDesc (int pos)
838 if (types == null || types [pos] == null)
839 return ((Parameter)FixedParameters [pos]).GetSignatureForError ();
841 string type = TypeManager.CSharpName (types [pos]);
842 if (FixedParameters [pos].HasExtensionMethodModifier)
843 return "this " + type;
845 Parameter.Modifier mod = FixedParameters [pos].ModFlags;
849 return Parameter.GetModifierSignature (mod) + " " + type;
852 public Type[] Types {
853 get { return types; }
854 set { types = value; }
858 public AParametersCollection InflateTypes (Type[] genArguments, Type[] argTypes)
860 AParametersCollection p = (AParametersCollection) MemberwiseClone (); // Clone ();
862 for (int i = 0; i < Count; ++i) {
863 if (types[i].IsGenericType) {
864 Type[] gen_arguments_open = new Type[types[i].GetGenericTypeDefinition ().GetGenericArguments ().Length];
865 Type[] gen_arguments = types[i].GetGenericArguments ();
866 for (int ii = 0; ii < gen_arguments_open.Length; ++ii) {
867 if (gen_arguments[ii].IsGenericParameter) {
868 Type t = argTypes[gen_arguments[ii].GenericParameterPosition];
869 gen_arguments_open[ii] = t;
871 gen_arguments_open[ii] = gen_arguments[ii];
874 p.types[i] = types[i].GetGenericTypeDefinition ().MakeGenericType (gen_arguments_open);
878 if (types[i].IsGenericParameter) {
879 Type gen_argument = argTypes[types[i].GenericParameterPosition];
880 p.types[i] = gen_argument;
891 // A collection of imported or resolved parameters
893 public class ParametersImported : AParametersCollection
895 ParametersImported (AParametersCollection param, Type[] types)
897 this.parameters = param.FixedParameters;
899 has_arglist = param.HasArglist;
900 has_params = param.HasParams;
903 ParametersImported (IParameterData [] parameters, Type [] types, bool hasArglist, bool hasParams)
905 this.parameters = parameters;
907 this.has_arglist = hasArglist;
908 this.has_params = hasParams;
911 public ParametersImported (IParameterData [] param, Type[] types)
913 this.parameters = param;
917 public static AParametersCollection Create (MethodBase method)
919 return Create (method.GetParameters (), method);
923 // Generic method parameters importer, param is shared between all instances
925 public static AParametersCollection Create (AParametersCollection param, MethodBase method)
930 ParameterInfo [] pi = method.GetParameters ();
931 Type [] types = new Type [pi.Length];
932 for (int i = 0; i < types.Length; i++) {
933 Type t = pi [i].ParameterType;
935 t = TypeManager.GetElementType (t);
937 types [i] = TypeManager.TypeToCoreType (t);
940 return new ParametersImported (param, types);
944 // Imports SRE parameters
946 public static AParametersCollection Create (ParameterInfo [] pi, MethodBase method)
948 int varargs = method != null && (method.CallingConvention & CallingConventions.VarArgs) != 0 ? 1 : 0;
950 if (pi.Length == 0 && varargs == 0)
951 return ParametersCompiled.EmptyReadOnlyParameters;
953 Type [] types = new Type [pi.Length + varargs];
954 IParameterData [] par = new IParameterData [pi.Length + varargs];
955 bool is_params = false;
956 PredefinedAttribute extension_attr = PredefinedAttributes.Get.Extension;
957 PredefinedAttribute param_attr = PredefinedAttributes.Get.ParamArray;
958 for (int i = 0; i < pi.Length; i++) {
959 types [i] = TypeManager.TypeToCoreType (pi [i].ParameterType);
961 ParameterInfo p = pi [i];
962 Parameter.Modifier mod = 0;
963 Expression default_value = null;
964 if (types [i].IsByRef) {
965 if ((p.Attributes & (ParameterAttributes.Out | ParameterAttributes.In)) == ParameterAttributes.Out)
966 mod = Parameter.Modifier.OUT;
968 mod = Parameter.Modifier.REF;
971 // Strip reference wrapping
973 types [i] = TypeManager.GetElementType (types [i]);
974 } else if (i == 0 && extension_attr.IsDefined && method != null && method.IsStatic &&
975 (method.DeclaringType.Attributes & Class.StaticClassAttribute) == Class.StaticClassAttribute &&
976 method.IsDefined (extension_attr.Type, false)) {
977 mod = Parameter.Modifier.This;
979 if (i >= pi.Length - 2 && types[i].IsArray) {
980 if (p.IsDefined (param_attr.Type, false)) {
981 mod = Parameter.Modifier.PARAMS;
986 if (!is_params && p.IsOptional) {
987 object value = p.DefaultValue;
988 if (value == Missing.Value) {
989 default_value = EmptyExpression.Null;
990 } else if (value == null) {
991 default_value = new NullLiteral (Location.Null);
993 default_value = Constant.CreateConstant (null, value.GetType (), value, Location.Null);
998 par [i] = new ParameterData (p.Name, mod, default_value);
1002 par [par.Length - 1] = new ArglistParameter (Location.Null);
1003 types [types.Length - 1] = InternalType.Arglist;
1006 return method != null ?
1007 new ParametersImported (par, types, varargs != 0, is_params) :
1008 new ParametersImported (par, types);
1013 /// Represents the methods parameters
1015 public class ParametersCompiled : AParametersCollection
1017 public static readonly ParametersCompiled EmptyReadOnlyParameters = new ParametersCompiled ();
1019 // Used by C# 2.0 delegates
1020 public static readonly ParametersCompiled Undefined = new ParametersCompiled ();
1022 private ParametersCompiled ()
1024 parameters = new Parameter [0];
1025 types = Type.EmptyTypes;
1028 private ParametersCompiled (Parameter [] parameters, Type [] types)
1030 this.parameters = parameters;
1034 public ParametersCompiled (CompilerContext ctx, params Parameter[] parameters)
1036 if (parameters == null)
1037 throw new ArgumentException ("Use EmptyReadOnlyParameters");
1039 this.parameters = parameters;
1040 int count = parameters.Length;
1046 has_params = (parameters [0].ModFlags & Parameter.Modifier.PARAMS) != 0;
1050 for (int i = 0; i < count; i++){
1051 string base_name = parameters [i].Name;
1052 has_params |= (parameters [i].ModFlags & Parameter.Modifier.PARAMS) != 0;
1054 for (int j = i + 1; j < count; j++){
1055 if (base_name != parameters [j].Name)
1058 ErrorDuplicateName (parameters[i], ctx.Report);
1064 public ParametersCompiled (CompilerContext ctx, Parameter [] parameters, bool has_arglist) :
1065 this (ctx, parameters)
1067 this.has_arglist = has_arglist;
1070 public static ParametersCompiled CreateFullyResolved (Parameter p, Type type)
1072 return new ParametersCompiled (new Parameter [] { p }, new Type [] { type });
1075 public static ParametersCompiled CreateFullyResolved (Parameter[] parameters, Type[] types)
1077 return new ParametersCompiled (parameters, types);
1080 public static ParametersCompiled MergeGenerated (CompilerContext ctx, ParametersCompiled userParams, bool checkConflicts, Parameter compilerParams, Type compilerTypes)
1082 return MergeGenerated (ctx, userParams, checkConflicts,
1083 new Parameter [] { compilerParams },
1084 new Type [] { compilerTypes });
1088 // Use this method when you merge compiler generated parameters with user parameters
1090 public static ParametersCompiled MergeGenerated (CompilerContext ctx, ParametersCompiled userParams, bool checkConflicts, Parameter[] compilerParams, Type[] compilerTypes)
1092 Parameter[] all_params = new Parameter [userParams.Count + compilerParams.Length];
1093 userParams.FixedParameters.CopyTo(all_params, 0);
1096 if (userParams.types != null) {
1097 all_types = new Type [all_params.Length];
1098 userParams.Types.CopyTo (all_types, 0);
1103 int last_filled = userParams.Count;
1105 foreach (Parameter p in compilerParams) {
1106 for (int i = 0; i < last_filled; ++i) {
1107 while (p.Name == all_params [i].Name) {
1108 if (checkConflicts && i < userParams.Count) {
1109 ctx.Report.Error (316, userParams[i].Location,
1110 "The parameter name `{0}' conflicts with a compiler generated name", p.Name);
1112 p.Name = '_' + p.Name;
1115 all_params [last_filled] = p;
1116 if (all_types != null)
1117 all_types [last_filled] = compilerTypes [index++];
1121 ParametersCompiled parameters = new ParametersCompiled (all_params, all_types);
1122 parameters.has_params = userParams.has_params;
1126 protected virtual void ErrorDuplicateName (Parameter p, Report Report)
1128 Report.Error (100, p.Location, "The parameter name `{0}' is a duplicate", p.Name);
1131 public bool Resolve (IMemberContext ec)
1136 types = new Type [Count];
1140 for (int i = 0; i < FixedParameters.Length; ++i) {
1142 Type t = p.Resolve (ec);
1154 public void ResolveVariable ()
1156 for (int i = 0; i < FixedParameters.Length; ++i) {
1157 this [i].ResolveVariable (i);
1161 // Define each type attribute (in/out/ref) and
1162 // the argument names.
1163 public void ApplyAttributes (MethodBase builder)
1168 MethodBuilder mb = builder as MethodBuilder;
1169 ConstructorBuilder cb = builder as ConstructorBuilder;
1171 for (int i = 0; i < Count; i++) {
1172 this [i].ApplyAttributes (mb, cb, i + 1);
1176 public void VerifyClsCompliance (IMemberContext ctx)
1178 foreach (Parameter p in FixedParameters)
1179 p.IsClsCompliant (ctx);
1182 public Parameter this [int pos] {
1183 get { return (Parameter) parameters [pos]; }
1186 public Expression CreateExpressionTree (BlockContext ec, Location loc)
1188 var initializers = new ArrayInitializer (Count, loc);
1189 foreach (Parameter p in FixedParameters) {
1191 // Each parameter expression is stored to local variable
1192 // to save some memory when referenced later.
1194 StatementExpression se = new StatementExpression (p.CreateExpressionTreeVariable (ec));
1195 if (se.Resolve (ec))
1196 ec.CurrentBlock.AddScopeStatement (se);
1198 initializers.Add (p.ExpressionTreeVariableReference ());
1201 return new ArrayCreation (
1202 Parameter.ResolveParameterExpressionType (ec, loc),
1203 "[]", initializers, loc);
1206 public ParametersCompiled Clone ()
1208 ParametersCompiled p = (ParametersCompiled) MemberwiseClone ();
1210 p.parameters = new IParameterData [parameters.Length];
1211 for (int i = 0; i < Count; ++i)
1212 p.parameters [i] = this [i].Clone ();