-//\r
-// parameter.cs: Parameter definition.\r
-//\r
-// Author: Miguel de Icaza (miguel@gnu.org)\r
-//\r
-// Licensed under the terms of the GNU GPL\r
-//\r
-// (C) 2001 Ximian, Inc (http://www.ximian.com)\r
-//\r
-//\r
-//\r
-using System;\r
-using System.Reflection;\r
-using System.Reflection.Emit;\r
-using System.Collections;\r
-\r
-namespace Mono.CSharp {\r
-\r
-\r
- /// <summary>\r
- /// Represents a single method parameter\r
- /// </summary>\r
- public class Parameter {\r
- [Flags]\r
- public enum Modifier : byte {\r
- NONE = 0,\r
- REF = 1,\r
- OUT = 2,\r
- PARAMS = 4,\r
- }\r
-\r
- public readonly string TypeName;\r
- public readonly string Name;\r
- public readonly Modifier ModFlags;\r
- public Attributes OptAttributes;\r
- public Type ParameterType;\r
- \r
- public Parameter (string type, string name, Modifier mod, Attributes attrs)\r
- {\r
- Name = name;\r
- ModFlags = mod;\r
- TypeName = type;\r
- OptAttributes = attrs;\r
- }\r
-\r
- public bool Resolve (DeclSpace ds, Location l)\r
- {\r
- ParameterType = RootContext.LookupType (ds, TypeName, false, l);\r
- return ParameterType != null;\r
- }\r
-\r
- public Type ExternalType (DeclSpace ds, Location l)\r
- {\r
- if ((ModFlags & (Parameter.Modifier.REF | Parameter.Modifier.OUT)) != 0){\r
- string n = ParameterType.FullName + "&";\r
-\r
- Type t = RootContext.LookupType (ds, n, false, l);\r
-\r
- return t;\r
- }\r
- \r
- return ParameterType;\r
- }\r
- \r
- public ParameterAttributes Attributes {\r
- get {\r
- switch (ModFlags){\r
- case Modifier.NONE:\r
- return ParameterAttributes.None;\r
- case Modifier.REF:\r
- return ParameterAttributes.None;\r
- case Modifier.OUT:\r
- return ParameterAttributes.Out;\r
- case Modifier.PARAMS:\r
- return 0;\r
- }\r
- \r
- return ParameterAttributes.None;\r
- }\r
- }\r
- \r
- /// <summary>\r
- /// Returns the signature for this parameter evaluating it on the\r
- /// @tc context\r
- /// </summary>\r
- public string GetSignature (DeclSpace ds, Location loc)\r
- {\r
- if (ParameterType == null){\r
- if (!Resolve (ds, loc))\r
- return null;\r
- }\r
-\r
- return ExternalType (ds, loc).FullName;\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// Represents the methods parameters\r
- /// </summary>\r
- public class Parameters {\r
- public Parameter [] FixedParameters;\r
- public readonly Parameter ArrayParameter;\r
- string signature;\r
- Type [] types;\r
- Location loc;\r
- \r
- static Parameters empty_parameters;\r
- \r
- public Parameters (Parameter [] fixed_parameters, Parameter array_parameter, Location l)\r
- {\r
- FixedParameters = fixed_parameters;\r
- ArrayParameter = array_parameter;\r
- loc = l;\r
- }\r
-\r
- /// <summary>\r
- /// This is used to reuse a set of empty parameters, because they\r
- /// are common\r
- /// </summary>\r
- public static Parameters GetEmptyReadOnlyParameters ()\r
- {\r
- if (empty_parameters == null)\r
- empty_parameters = new Parameters (null, null, Location.Null);\r
- \r
- return empty_parameters;\r
- }\r
- \r
- public bool Empty {\r
- get {\r
- return (FixedParameters == null) && (ArrayParameter == null);\r
- }\r
- }\r
- \r
- public void ComputeSignature (DeclSpace ds)\r
- {\r
- signature = "";\r
- if (FixedParameters != null){\r
- for (int i = 0; i < FixedParameters.Length; i++){\r
- Parameter par = FixedParameters [i];\r
- \r
- signature += par.GetSignature (ds, loc);\r
- }\r
- }\r
- //\r
- // Note: as per the spec, the `params' arguments (ArrayParameter)\r
- // are not used in the signature computation for a method\r
- //\r
- }\r
-\r
- static void error100 (string name)\r
- {\r
- Report.Error (\r
- 100, "The parameter name `" + name + "' is a duplicate");\r
- }\r
- \r
- public bool VerifyArgs ()\r
- {\r
- int count;\r
- int i, j;\r
-\r
- if (FixedParameters == null)\r
- return true;\r
- \r
- count = FixedParameters.Length;\r
- string array_par_name = ArrayParameter != null ? ArrayParameter.Name : null;\r
- for (i = 0; i < count; i++){\r
- string base_name = FixedParameters [i].Name;\r
- \r
- for (j = i + 1; j < count; j++){\r
- if (base_name != FixedParameters [j].Name)\r
- continue;\r
- error100 (base_name);\r
- return false;\r
- }\r
-\r
- if (base_name == array_par_name){\r
- error100 (base_name);\r
- return false;\r
- }\r
- }\r
- return true;\r
- }\r
- \r
- /// <summary>\r
- /// Returns the signature of the Parameters evaluated in\r
- /// the @tc environment\r
- /// </summary>\r
- public string GetSignature (DeclSpace ds)\r
- {\r
- if (signature == null){\r
- VerifyArgs ();\r
- ComputeSignature (ds);\r
- }\r
- \r
- return signature;\r
- }\r
- \r
- /// <summary>\r
- /// Returns the paramenter information based on the name\r
- /// </summary>\r
- public Parameter GetParameterByName (string name, out int idx)\r
- {\r
- idx = 0;\r
- int i = 0;\r
-\r
- if (FixedParameters != null){\r
- foreach (Parameter par in FixedParameters){\r
- if (par.Name == name){\r
- idx = i;\r
- return par;\r
- }\r
- i++;\r
- }\r
- }\r
-\r
- if (ArrayParameter != null){\r
- if (name == ArrayParameter.Name){\r
- idx = i;\r
- return ArrayParameter;\r
- }\r
- }\r
- \r
- return null;\r
- }\r
-\r
- bool ComputeParameterTypes (DeclSpace ds)\r
- {\r
- int extra = (ArrayParameter != null) ? 1 : 0;\r
- int i = 0;\r
- int pc;\r
-\r
- if (FixedParameters == null)\r
- pc = extra;\r
- else\r
- pc = extra + FixedParameters.Length;\r
- \r
- types = new Type [pc];\r
- \r
- if (!VerifyArgs ()){\r
- FixedParameters = null;\r
- return false;\r
- }\r
-\r
- if (FixedParameters != null){\r
- foreach (Parameter p in FixedParameters){\r
- Type t = null;\r
- \r
- if (p.Resolve (ds, loc))\r
- t = p.ExternalType (ds, loc);\r
- \r
- types [i] = t;\r
- i++;\r
- }\r
- }\r
- \r
- if (extra > 0){\r
- if (ArrayParameter.Resolve (ds, loc))\r
- types [i] = ArrayParameter.ExternalType (ds, loc);\r
- }\r
-\r
- return true;\r
- }\r
- \r
- /// <summary>\r
- /// Returns the argument types as an array\r
- /// </summary>\r
- static Type [] no_types = new Type [0];\r
- \r
- public Type [] GetParameterInfo (DeclSpace ds)\r
- {\r
- if (types != null)\r
- return types;\r
- \r
- if (FixedParameters == null && ArrayParameter == null)\r
- return no_types;\r
-\r
- if (ComputeParameterTypes (ds) == false)\r
- return null;\r
- \r
- return types;\r
- }\r
-\r
- /// <summary>\r
- /// Returns the type of a given parameter, and stores in the `is_out'\r
- /// boolean whether this is an out or ref parameter.\r
- ///\r
- /// Note that the returned type will not contain any dereference in this\r
- /// case (ie, you get "int" for a ref int instead of "int&"\r
- /// </summary>\r
- public Type GetParameterInfo (DeclSpace ds, int idx, out bool is_out)\r
- {\r
- is_out = false;\r
- \r
- if (!VerifyArgs ()){\r
- FixedParameters = null;\r
- return null;\r
- }\r
-\r
- if (FixedParameters == null && ArrayParameter == null)\r
- return null;\r
- \r
- if (types == null)\r
- if (ComputeParameterTypes (ds) == false){\r
- is_out = false;\r
- return null;\r
- }\r
-\r
- //\r
- // If this is a request for the variable lenght arg.\r
- //\r
- int array_idx = (FixedParameters != null ? FixedParameters.Length : 0);\r
- if (idx == array_idx){\r
- is_out = false;\r
- return types [idx];\r
- } \r
-\r
- //\r
- // Otherwise, it is a fixed parameter\r
- //\r
- Parameter p = FixedParameters [idx];\r
- is_out = ((p.ModFlags & (Parameter.Modifier.REF | Parameter.Modifier.OUT)) != 0);\r
-\r
- return p.ParameterType;\r
- }\r
-\r
- public CallingConventions GetCallingConvention ()\r
- {\r
- // For now this is the only correc thing to do\r
- return CallingConventions.Standard;\r
- }\r
- }\r
-}\r
- \r
- \r
-\r
+//
+// parameter.cs: Parameter definition.
+//
+// Author: Miguel de Icaza (miguel@gnu.org)
+//
+// Licensed under the terms of the GNU GPL
+//
+// (C) 2001 Ximian, Inc (http://www.ximian.com)
+//
+//
+//
+using System;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Collections;
+
+namespace Mono.MonoBASIC {
+
+
+ /// <summary>
+ /// Represents a single method parameter
+ /// </summary>
+ public class Parameter {
+ [Flags]
+ public enum Modifier : byte {
+ NONE = 0,
+ VAL = 0,
+ REF = 1,
+ OUT = 2,
+ PARAMS = 4,
+ // This is a flag which says that it's either REF or OUT.
+ ISBYREF = 8,
+ OPTIONAL = 16
+ }
+
+ public readonly Expression TypeName;
+ public readonly Modifier ModFlags;
+ public Attributes OptAttributes;
+ public readonly string Name;
+ public Type parameter_type;
+ public readonly Expression ParameterInitializer;
+ public readonly bool IsOptional;
+
+ public Parameter (Expression type, string name, Modifier mod, Attributes attrs)
+ {
+ Name = name;
+ ModFlags = mod;
+ TypeName = type;
+ OptAttributes = attrs;
+ ParameterInitializer = null;
+ IsOptional = false;
+ }
+
+ public Parameter (Expression type, string name, Modifier mod, Attributes attrs, Expression pi)
+ {
+ Name = name;
+ ModFlags = mod;
+ TypeName = type;
+ OptAttributes = attrs;
+ ParameterInitializer = pi;
+ IsOptional = false;
+ }
+
+ public Parameter (Expression type, string name, Modifier mod, Attributes attrs, Expression pi, bool opt)
+ {
+ Name = name;
+ ModFlags = mod;
+ TypeName = type;
+ OptAttributes = attrs;
+ ParameterInitializer = pi;
+ IsOptional = opt;
+ }
+
+
+ // <summary>
+ // Resolve is used in method definitions
+ // </summary>
+ public bool Resolve (DeclSpace ds, Location l)
+ {
+ parameter_type = ds.ResolveType (TypeName, false, l);
+
+ if (parameter_type == TypeManager.void_type){
+ Report.Error (1536, l, "`void' parameter is not permitted");
+ return false;
+ }
+
+ return parameter_type != null;
+ }
+
+ public Type ExternalType (DeclSpace ds, Location l)
+ {
+ if ((ModFlags & Parameter.Modifier.ISBYREF) != 0){
+ string n = parameter_type.FullName + "&";
+
+ Type t = RootContext.LookupType (ds, n, false, l);
+
+ return t;
+ }
+
+ return parameter_type;
+ }
+
+ public Type ParameterType {
+ get {
+ return parameter_type;
+ }
+ }
+
+ public ParameterAttributes Attributes {
+ get {
+ int flags = ((int) ModFlags) & ~((int) Parameter.Modifier.ISBYREF);
+ switch ((Modifier) flags) {
+ case Modifier.NONE:
+ return ParameterAttributes.None;
+ case Modifier.REF:
+ return ParameterAttributes.None;
+ case Modifier.OUT:
+ return ParameterAttributes.Out;
+ case Modifier.PARAMS:
+ return 0;
+ }
+
+ return ParameterAttributes.None;
+ }
+ }
+
+ /// <summary>
+ /// Returns the signature for this parameter evaluating it on the
+ /// @tc context
+ /// </summary>
+ public string GetSignature (DeclSpace ds, Location loc)
+ {
+ if (parameter_type == null){
+ if (!Resolve (ds, loc))
+ return null;
+ }
+
+ return ExternalType (ds, loc).FullName;
+ }
+ }
+
+ /// <summary>
+ /// Represents the methods parameters
+ /// </summary>
+ public class Parameters {
+ public Parameter [] FixedParameters;
+ public readonly Parameter ArrayParameter;
+ string signature;
+ Type [] types;
+ Location loc;
+
+ static Parameters empty_parameters;
+
+ public Parameters (Parameter [] fixed_parameters, Parameter array_parameter, Location l)
+ {
+ FixedParameters = fixed_parameters;
+ ArrayParameter = array_parameter;
+ loc = l;
+ }
+
+ /// <summary>
+ /// This is used to reuse a set of empty parameters, because they
+ /// are common
+ /// </summary>
+ public static Parameters EmptyReadOnlyParameters {
+ get {
+ if (empty_parameters == null)
+ empty_parameters = new Parameters (null, null, Location.Null);
+
+ return empty_parameters;
+ }
+ }
+
+ public bool HasOptional()
+ {
+ bool res = false;
+
+ foreach (Parameter p in FixedParameters)
+ {
+ if (p.IsOptional)
+ {
+ res = true;
+ break;
+ }
+ }
+ return (res);
+ }
+
+ /// <summary>
+ /// Returns the number of standard (i.e. non-optional) parameters
+ /// </summary>
+ public int CountStandardParams()
+ {
+ int res = 0;
+ if (FixedParameters == null)
+ return 0;
+
+ foreach (Parameter p in FixedParameters) {
+ if (!p.IsOptional)
+ res++;
+ }
+ return (res);
+ }
+
+ /// <summary>
+ /// Returns the number of optional parameters
+ /// </summary>
+ public int CountOptionalParams()
+ {
+ int res = 0;
+ if (FixedParameters == null)
+ return 0;
+
+ foreach (Parameter p in FixedParameters) {
+ if (p.IsOptional)
+ res++;
+ }
+ return (res);
+ }
+
+ public Expression GetDefaultValue (int i)
+ {
+ Parameter p = FixedParameters[i];
+ if (p.IsOptional)
+ return p.ParameterInitializer;
+ else
+ return null;
+ }
+
+ public void AppendParameter (Parameter p)
+ {
+ if (FixedParameters != null)
+ {
+ Parameter [] pa = new Parameter [FixedParameters.Length+1];
+ FixedParameters.CopyTo (pa, 0);
+ pa[FixedParameters.Length] = p;
+ FixedParameters = pa;
+ }
+ else
+ {
+ FixedParameters = new Parameter [1];
+ FixedParameters[0] = p;
+ }
+ }
+
+ public void PrependParameter (Parameter p)
+ {
+ Parameter [] pa = new Parameter [FixedParameters.Length+1];
+ FixedParameters.CopyTo (pa, 1);
+ pa[0] = p;
+ FixedParameters = pa;
+ }
+
+ public Parameters Copy (Location l)
+ {
+ Parameters p = new Parameters (null, null, l);
+ p.FixedParameters = new Parameter[this.FixedParameters.Length];
+ this.FixedParameters.CopyTo (p.FixedParameters, 0);
+
+ return (p);
+
+ }
+
+ public bool Empty {
+ get {
+ return (FixedParameters == null) && (ArrayParameter == null);
+ }
+ }
+
+ public void ComputeSignature (DeclSpace ds)
+ {
+ signature = "";
+ if (FixedParameters != null){
+ for (int i = 0; i < FixedParameters.Length; i++){
+ Parameter par = FixedParameters [i];
+
+ signature += par.GetSignature (ds, loc);
+ }
+ }
+ //
+ // Note: as per the spec, the `params' arguments (ArrayParameter)
+ // are not used in the signature computation for a method
+ //
+ }
+
+ static void Error_DuplicateParameterName (string name)
+ {
+ Report.Error (
+ 100, "The parameter name `" + name + "' is a duplicate");
+ }
+
+ public bool VerifyArgs ()
+ {
+ int count;
+ int i, j;
+
+ if (FixedParameters == null)
+ return true;
+
+ count = FixedParameters.Length;
+ string array_par_name = ArrayParameter != null ? ArrayParameter.Name : null;
+ for (i = 0; i < count; i++){
+ string base_name = FixedParameters [i].Name;
+
+ for (j = i + 1; j < count; j++){
+ if (base_name != FixedParameters [j].Name)
+ continue;
+ Error_DuplicateParameterName (base_name);
+ return false;
+ }
+
+ if (base_name == array_par_name){
+ Error_DuplicateParameterName (base_name);
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /// <summary>
+ /// Returns the signature of the Parameters evaluated in
+ /// the @tc environment
+ /// </summary>
+ public string GetSignature (DeclSpace ds)
+ {
+ if (signature == null){
+ VerifyArgs ();
+ ComputeSignature (ds);
+ }
+
+ return signature;
+ }
+
+ /// <summary>
+ /// Returns the paramenter information based on the name
+ /// </summary>
+ public Parameter GetParameterByName (string name, out int idx)
+ {
+ idx = 0;
+ int i = 0;
+
+ if (FixedParameters != null){
+ foreach (Parameter par in FixedParameters){
+ if (par.Name == name){
+ idx = i;
+ return par;
+ }
+ i++;
+ }
+ }
+
+ if (ArrayParameter != null){
+ if (name == ArrayParameter.Name){
+ idx = i;
+ return ArrayParameter;
+ }
+ }
+
+ return null;
+ }
+
+ bool ComputeParameterTypes (DeclSpace ds)
+ {
+ int extra = (ArrayParameter != null) ? 1 : 0;
+ int i = 0;
+ int pc;
+
+ if (FixedParameters == null)
+ pc = extra;
+ else
+ pc = extra + FixedParameters.Length;
+
+ types = new Type [pc];
+
+ if (!VerifyArgs ()){
+ FixedParameters = null;
+ return false;
+ }
+
+ bool failed = false;
+ if (FixedParameters != null){
+ foreach (Parameter p in FixedParameters){
+ Type t = null;
+
+ if (p.Resolve (ds, loc))
+ t = p.ExternalType (ds, loc);
+ else
+ failed = true;
+
+ types [i] = t;
+ i++;
+ }
+ }
+
+ if (extra > 0){
+ if (ArrayParameter.Resolve (ds, loc))
+ types [i] = ArrayParameter.ExternalType (ds, loc);
+ else
+ failed = true;
+ }
+
+ if (failed){
+ types = null;
+ return false;
+ }
+
+ return true;
+ }
+
+ //
+ // This variant is used by Delegates, because they need to
+ // resolve/define names, instead of the plain LookupType
+ //
+ public bool ComputeAndDefineParameterTypes (DeclSpace ds)
+ {
+ int extra = (ArrayParameter != null) ? 1 : 0;
+ int i = 0;
+ int pc;
+
+ if (FixedParameters == null)
+ pc = extra;
+ else
+ pc = extra + FixedParameters.Length;
+
+ types = new Type [pc];
+
+ if (!VerifyArgs ()){
+ FixedParameters = null;
+ return false;
+ }
+
+ bool ok_flag = true;
+
+ if (FixedParameters != null){
+ foreach (Parameter p in FixedParameters){
+ Type t = null;
+
+ if (p.Resolve (ds, loc))
+ t = p.ExternalType (ds, loc);
+ else
+ ok_flag = false;
+
+ types [i] = t;
+ i++;
+ }
+ }
+
+ if (extra > 0){
+ if (ArrayParameter.Resolve (ds, loc))
+ types [i] = ArrayParameter.ExternalType (ds, loc);
+ else
+ ok_flag = false;
+ }
+
+ //
+ // invalidate the cached types
+ //
+ if (!ok_flag){
+ types = null;
+ }
+
+ return ok_flag;
+ }
+
+ /// <summary>
+ /// Returns the argument types as an array
+ /// </summary>
+ static Type [] no_types = new Type [0];
+
+ public Type [] GetParameterInfo (DeclSpace ds)
+ {
+ if (types != null)
+ return types;
+
+ if (FixedParameters == null && ArrayParameter == null)
+ return no_types;
+
+ if (ComputeParameterTypes (ds) == false){
+ types = null;
+ return null;
+ }
+
+ return types;
+ }
+
+ /// <summary>
+ /// Returns the type of a given parameter, and stores in the `is_out'
+ /// boolean whether this is an out or ref parameter.
+ ///
+ /// Note that the returned type will not contain any dereference in this
+ /// case (ie, you get "int" for a ref int instead of "int&"
+ /// </summary>
+ public Type GetParameterInfo (DeclSpace ds, int idx, out Parameter.Modifier mod)
+ {
+ mod = Parameter.Modifier.NONE;
+
+ if (!VerifyArgs ()){
+ FixedParameters = null;
+ return null;
+ }
+
+ if (FixedParameters == null && ArrayParameter == null)
+ return null;
+
+ if (types == null)
+ if (ComputeParameterTypes (ds) == false)
+ return null;
+
+ //
+ // If this is a request for the variable lenght arg.
+ //
+ int array_idx = (FixedParameters != null ? FixedParameters.Length : 0);
+ if (idx == array_idx)
+ return types [idx];
+
+ //
+ // Otherwise, it is a fixed parameter
+ //
+ Parameter p = FixedParameters [idx];
+ mod = p.ModFlags;
+
+ if ((mod & (Parameter.Modifier.REF | Parameter.Modifier.OUT)) != 0)
+ mod |= Parameter.Modifier.ISBYREF;
+
+ return p.ParameterType;
+ }
+
+ public CallingConventions GetCallingConvention ()
+ {
+ // For now this is the only correc thing to do
+ return CallingConventions.Standard;
+ }
+ }
+}