X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmbas%2Fparameter.cs;h=5350497e138d4b29c66f3900f85b5ac8eeeed952;hb=c8f61053ec1cc2826c90c6f11e030c09e130e5c0;hp=ab125da9719db7706f4402dfa288341c340e9fd6;hpb=4ca77be3daabf041e4ba5b863f8095e50afe551f;p=mono.git diff --git a/mcs/mbas/parameter.cs b/mcs/mbas/parameter.cs index ab125da9719..5350497e138 100644 --- a/mcs/mbas/parameter.cs +++ b/mcs/mbas/parameter.cs @@ -14,57 +14,94 @@ using System.Reflection; using System.Reflection.Emit; using System.Collections; -namespace Mono.CSharp { +namespace Mono.MonoBASIC { /// /// Represents a single method parameter /// - public class Parameter { + public class Parameter : Attributable { + ParameterBuilder builder; + [Flags] public enum Modifier : byte { NONE = 0, + VAL = 0, REF = 1, - OUT = 2, +// OUT = 2, PARAMS = 4, // This is a flag which says that it's either REF or OUT. - ISBYREF = 8 + ISBYREF = 8, + OPTIONAL = 16 } public readonly Expression TypeName; public readonly Modifier ModFlags; - public Attributes OptAttributes; public readonly string Name; public Type parameter_type; - + public Expression ParameterInitializer; + public readonly bool IsOptional; + public Parameter (Expression type, string name, Modifier mod, Attributes attrs) + : base (attrs) + { + Name = name; + ModFlags = mod; + TypeName = type; + ParameterInitializer = null; + IsOptional = false; + } + + public Parameter (Expression type, string name, Modifier mod, Attributes attrs, Expression pi) + : base (attrs) + { + Name = name; + ModFlags = mod; + TypeName = type; + ParameterInitializer = pi; + IsOptional = false; + } + + public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb) + { + if (a.Type == TypeManager.marshal_as_attr_type) { + UnmanagedMarshal marshal = UnmanagedMarshal.DefineUnmanagedMarshal (a.UnmanagedType); + builder.SetMarshal (marshal); + } else + builder.SetCustomAttribute (cb); + } + + public Parameter (Expression type, string name, Modifier mod, Attributes attrs, Expression pi, bool opt) + : base (attrs) { Name = name; ModFlags = mod; TypeName = type; - OptAttributes = attrs; + ParameterInitializer = pi; + IsOptional = opt; } + public override AttributeTargets AttributeTargets { + get { + return AttributeTargets.Parameter; + } + } + // // Resolve is used in method definitions // public bool Resolve (DeclSpace ds, Location l) { parameter_type = ds.ResolveType (TypeName, false, l); - return parameter_type != null; - } - // - // ResolveAndDefine is used by delegate declarations, because - // they happen during the initial tree resolution process - // - public bool ResolveAndDefine (DeclSpace ds) - { - // FIXME: Should use something else instead of Location.Null - parameter_type = ds.ResolveType (TypeName, true, Location.Null); + 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){ @@ -86,13 +123,18 @@ namespace Mono.CSharp { public ParameterAttributes Attributes { get { - switch (ModFlags){ + int flags = ((int) ModFlags) & ~((int) Parameter.Modifier.ISBYREF | (int) Parameter.Modifier.REF); + switch ((Modifier) flags) { case Modifier.NONE: return ParameterAttributes.None; case Modifier.REF: return ParameterAttributes.None; +/* case Modifier.OUT: return ParameterAttributes.Out; +*/ + case Modifier.OPTIONAL: + return ParameterAttributes.Optional; case Modifier.PARAMS: return 0; } @@ -114,6 +156,49 @@ namespace Mono.CSharp { return ExternalType (ds, loc).FullName; } + + public bool DefineParameter (EmitContext ec, MethodBuilder mb, ConstructorBuilder cb, int index, Location loc) + { + if (mb == null) + builder = cb.DefineParameter (index, Attributes, Name); + else + builder = mb.DefineParameter (index, Attributes, Name); + + if (ParameterInitializer != null) { + if (ParameterInitializer is MemberAccess) { + MemberAccess ma = ParameterInitializer as MemberAccess; + + ParameterInitializer = ma.Resolve(ec); + } else + ParameterInitializer = ParameterInitializer.Resolve (ec); + + if (ParameterInitializer == null) { + Report.Error(-1, "Internal error - Non supported argument type in optional parameter"); + return false; + } + + if (parameter_type != ParameterInitializer.Type) { + Expression conv = Expression.ConvertImplicit (ec, ParameterInitializer, parameter_type, loc); + if (conv == null) { + Report.Error (30439, loc, "Constant expression '" + ParameterInitializer + "' not representable in type '" + parameter_type + "'"); + return false; + } + ParameterInitializer = conv; + } + + if (!(ParameterInitializer is Constant)) { + Report.Error (30059, loc, "Constant expression is required"); + return false; + } + + builder.SetConstant (((Constant) ParameterInitializer).GetValue()); + + } + + if (OptAttributes != null) + OptAttributes.Emit (ec, this); + return true; + } } /// @@ -134,7 +219,7 @@ namespace Mono.CSharp { ArrayParameter = array_parameter; loc = l; } - + /// /// This is used to reuse a set of empty parameters, because they /// are common @@ -148,6 +233,96 @@ namespace Mono.CSharp { } } + public bool HasOptional() + { + bool res = false; + + foreach (Parameter p in FixedParameters) + { + if (p.IsOptional) + { + res = true; + break; + } + } + return (res); + } + + /// + /// Returns the number of standard (i.e. non-optional) parameters + /// + public int CountStandardParams() + { + int res = 0; + if (FixedParameters == null) + return 0; + + foreach (Parameter p in FixedParameters) { + if (!p.IsOptional) + res++; + } + return (res); + } + + /// + /// Returns the number of optional parameters + /// + 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); @@ -170,7 +345,7 @@ namespace Mono.CSharp { // } - static void error100 (string name) + static void Error_DuplicateParameterName (string name) { Report.Error ( 100, "The parameter name `" + name + "' is a duplicate"); @@ -190,14 +365,14 @@ namespace Mono.CSharp { string base_name = FixedParameters [i].Name; for (j = i + 1; j < count; j++){ - if (base_name != FixedParameters [j].Name) + if (base_name.ToLower () != FixedParameters [j].Name.ToLower ()) continue; - error100 (base_name); + Error_DuplicateParameterName (base_name); return false; } - if (base_name == array_par_name){ - error100 (base_name); + if ((array_par_name != null) && (base_name.ToLower () == array_par_name.ToLower ())) { + Error_DuplicateParameterName (base_name); return false; } } @@ -228,7 +403,7 @@ namespace Mono.CSharp { if (FixedParameters != null){ foreach (Parameter par in FixedParameters){ - if (par.Name == name){ + if (par.Name.ToLower() == name.ToLower()) { idx = i; return par; } @@ -237,7 +412,7 @@ namespace Mono.CSharp { } if (ArrayParameter != null){ - if (name == ArrayParameter.Name){ + if (name.ToLower () == ArrayParameter.Name.ToLower ()) { idx = i; return ArrayParameter; } @@ -279,14 +454,16 @@ namespace Mono.CSharp { } } - if (failed) - types = null; - if (extra > 0){ if (ArrayParameter.Resolve (ds, loc)) types [i] = ArrayParameter.ExternalType (ds, loc); - else - return false; + else + failed = true; + } + + if (failed){ + types = null; + return false; } return true; @@ -320,7 +497,7 @@ namespace Mono.CSharp { foreach (Parameter p in FixedParameters){ Type t = null; - if (p.ResolveAndDefine (ds)) + if (p.Resolve (ds, loc)) t = p.ExternalType (ds, loc); else ok_flag = false; @@ -331,7 +508,7 @@ namespace Mono.CSharp { } if (extra > 0){ - if (ArrayParameter.ResolveAndDefine (ds)) + if (ArrayParameter.Resolve (ds, loc)) types [i] = ArrayParameter.ExternalType (ds, loc); else ok_flag = false; @@ -404,7 +581,7 @@ namespace Mono.CSharp { Parameter p = FixedParameters [idx]; mod = p.ModFlags; - if ((mod & (Parameter.Modifier.REF | Parameter.Modifier.OUT)) != 0) + if ((mod & (Parameter.Modifier.REF )) != 0) mod |= Parameter.Modifier.ISBYREF; return p.ParameterType; @@ -415,8 +592,43 @@ namespace Mono.CSharp { // For now this is the only correc thing to do return CallingConventions.Standard; } - } -} - + public void LabelParameters (EmitContext ec, MethodBase builder, Location loc) + { + // + // Define each type attribute (in/out/ref) and + // the argument names. + // + Parameter [] p = FixedParameters; + int i = 0; + + MethodBuilder mb = null; + ConstructorBuilder cb = null; + + if (builder is MethodBuilder) + mb = (MethodBuilder) builder; + else + cb = (ConstructorBuilder) builder; + + if (p != null){ + for (i = 0; i < p.Length; i++) { + p [i].DefineParameter (ec, mb, cb, i + 1, loc); + } + } + if (ArrayParameter != null) { + ParameterBuilder pb; + Parameter array_param = ArrayParameter; + + if (mb == null) + pb = cb.DefineParameter (i + 1, array_param.Attributes, array_param.Name); + else + pb = mb.DefineParameter (i + 1, array_param.Attributes, array_param.Name); + + CustomAttributeBuilder a = new CustomAttributeBuilder (TypeManager.cons_param_array_attribute, new object [0]); + pb.SetCustomAttribute (a); + } + } + + } +}