X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fanonymous.cs;h=b11557f31afc3bc858bd50a9cb67b2e431a49da0;hb=24b2c4de33c81f823f3da28ccf5a8e12f560820d;hp=c8d8ed5cd289860fdde029d708e4d9fdee18a2cd;hpb=07e26f59c574c7a2e816882a8826d5bd66f7f9c5;p=mono.git diff --git a/mcs/mcs/anonymous.cs b/mcs/mcs/anonymous.cs index c8d8ed5cd28..b11557f31af 100644 --- a/mcs/mcs/anonymous.cs +++ b/mcs/mcs/anonymous.cs @@ -58,12 +58,13 @@ namespace Mono.CSharp { public class AnonymousMethodStorey : CompilerGeneratedClass { class StoreyFieldPair { - public AnonymousMethodStorey Storey; - public Field Field; + public readonly AnonymousMethodStorey Storey; + public readonly Field Field; - public StoreyFieldPair (AnonymousMethodStorey storey) + public StoreyFieldPair (AnonymousMethodStorey storey, Field field) { this.Storey = storey; + this.Field = field; } public override int GetHashCode () @@ -77,7 +78,7 @@ namespace Mono.CSharp { } } - class HoistedGenericField : Field + sealed class HoistedGenericField : Field { public HoistedGenericField (DeclSpace parent, FullNamedExpression type, int mod, string name, Attributes attrs, Location loc) @@ -98,6 +99,37 @@ namespace Mono.CSharp { } } + // + // Needed to delay hoisted _this_ initialization. When an anonymous + // method is used inside ctor and _this_ is hoisted, base ctor has to + // be called first, otherwise _this_ will be initialized with + // uninitialized value. + // + sealed class ThisInitializer : Statement + { + readonly HoistedThis hoisted_this; + + public ThisInitializer (HoistedThis hoisted_this) + { + this.hoisted_this = hoisted_this; + } + + protected override void DoEmit (EmitContext ec) + { + hoisted_this.EmitHoistingAssignment (ec); + } + + protected override void CloneTo (CloneContext clonectx, Statement target) + { + // Nothing to clone + } + + public override void MutateHoistedGenericType (AnonymousMethodStorey storey) + { + // Nothing to mutate + } + } + // Unique storey ID public readonly int ID; static int unique_id; @@ -106,6 +138,7 @@ namespace Mono.CSharp { // A list of StoreyFieldPair with local field keeping parent storey instance ArrayList used_parent_storeys; + ArrayList children_references; // A list of hoisted parameters protected ArrayList hoisted_params; @@ -117,10 +150,6 @@ namespace Mono.CSharp { // Local variable which holds this storey instance public LocalTemporary Instance; - bool references_defined; - bool has_hoisted_variable; - bool is_undone; - public AnonymousMethodStorey (Block block, DeclSpace parent, MemberBase host, GenericMethod generic, string name) : base (parent, generic, MakeMemberName (host, name, generic, block.StartLocation), Modifiers.PRIVATE) { @@ -143,6 +172,14 @@ namespace Mono.CSharp { return new MemberName (tname, args, loc); } + public void AddCapturedThisField (EmitContext ec) + { + TypeExpr type_expr = new TypeExpression (ec.ContainerType, Location); + Field f = AddCompilerGeneratedField ("<>f__this", type_expr); + f.Define (); + hoisted_this = new HoistedThis (this, f); + } + public Field AddCapturedVariable (string name, Type type) { CheckMembersDefined (); @@ -165,27 +202,47 @@ namespace Mono.CSharp { return f; } - public void AddParentStoreyReference (AnonymousMethodStorey s) + // + // Creates a link between block and the anonymous method storey + // + // An anonymous method can reference variables from any outer block, but they are + // hoisted in their own ExplicitBlock. When more than one block is referenced we + // need to create another link between those variable storeys + // + public void AddReferenceFromChildrenBlock (ExplicitBlock block) + { + if (children_references == null) + children_references = new ArrayList (); + + if (!children_references.Contains (block)) + children_references.Add (block); + } + + public void AddParentStoreyReference (AnonymousMethodStorey storey) { CheckMembersDefined (); if (used_parent_storeys == null) used_parent_storeys = new ArrayList (); - else if (used_parent_storeys.IndexOf (s) != -1) + else if (used_parent_storeys.IndexOf (storey) != -1) return; - has_hoisted_variable = true; - used_parent_storeys.Add (new StoreyFieldPair (s)); + TypeExpr type_expr = new TypeExpression (storey.TypeBuilder, Location); + Field f = AddCompilerGeneratedField ("<>f__ref$" + storey.ID, type_expr); + used_parent_storeys.Add (new StoreyFieldPair (storey, f)); } public void CaptureLocalVariable (EmitContext ec, LocalInfo local_info) { + ec.CurrentBlock.Explicit.HasCapturedVariable = true; + if (ec.CurrentBlock.Explicit != local_info.Block.Explicit) + AddReferenceFromChildrenBlock (ec.CurrentBlock.Explicit); + if (local_info.HoistedVariableReference != null) return; HoistedVariable var = new HoistedLocalVariable (this, local_info, GetVariableMangledName (local_info)); local_info.HoistedVariableReference = var; - has_hoisted_variable = true; if (hoisted_locals == null) hoisted_locals = new ArrayList (); @@ -195,7 +252,10 @@ namespace Mono.CSharp { public void CaptureParameter (EmitContext ec, ParameterReference param_ref) { - if (param_ref.HoistedVariable != null) + ec.CurrentBlock.Explicit.HasCapturedVariable = true; + AddReferenceFromChildrenBlock (ec.CurrentBlock.Explicit); + + if (param_ref.GetHoistedVariable (ec) != null) return; if (hoisted_params == null) @@ -206,59 +266,23 @@ namespace Mono.CSharp { hoisted_params.Add (expr); } - public HoistedThis CaptureThis (EmitContext ec, This t) - { - hoisted_this = new HoistedThis (this, t); - return hoisted_this; - } - public void ChangeParentStorey (AnonymousMethodStorey parentStorey) { Parent = parentStorey; type_params = null; } - void DefineStoreyReferences () - { - if (used_parent_storeys == null || references_defined) - return; - - references_defined = true; - - // - // For each used variable from parent scope we allocate its local reference point - // - for (int i = 0; i < used_parent_storeys.Count; ++i) { - StoreyFieldPair sf = (StoreyFieldPair) used_parent_storeys [i]; - AnonymousMethodStorey p_storey = sf.Storey; - TypeExpr type_expr = new TypeExpression (p_storey.TypeBuilder, Location); - - sf.Field = AddCompilerGeneratedField ("<>f__ref$" + p_storey.ID, type_expr); - sf.Field.Define (); - } - } - // // Initializes all hoisted variables // - public void EmitHoistedVariables (EmitContext ec) + public void EmitStoreyInstantiation (EmitContext ec) { // There can be only one instance variable for each storey type if (Instance != null) throw new InternalErrorException (); - // - // A storey with hoisted `this' is an instance method - // - if (!HasHoistedVariables) { - hoisted_this.RemoveHoisting (); - return; - } - SymbolWriter.OpenCompilerGeneratedBlock (ec.ig); - DefineStoreyReferences (); - // // Create an instance of storey type // @@ -275,7 +299,7 @@ namespace Mono.CSharp { TypeArguments targs = new TypeArguments (); if (tparams.Length < CountTypeParameters) { - TypeParameter[] parent_tparams = ec.DeclContainer.Parent.CurrentTypeParameters; + TypeParameter[] parent_tparams = ec.DeclContainer.Parent.PartialContainer.TypeParameters; for (int i = 0; i < parent_tparams.Length; ++i) targs.Add (new TypeParameterExpr (parent_tparams[i], Location)); } @@ -294,10 +318,9 @@ namespace Mono.CSharp { Instance = new LocalTemporary (storey_type_expr.Type); Instance.Store (ec); - SymbolWriter.DefineScopeVariable (ID, Instance.Builder); - EmitHoistedFieldsInitialization (ec); + SymbolWriter.DefineScopeVariable (ID, Instance.Builder); SymbolWriter.CloseCompilerGeneratedBlock (ec.ig); } @@ -323,6 +346,14 @@ namespace Mono.CSharp { } } + // + // Define hoisted `this' in top-level storey only + // + if (OriginalSourceBlock.Explicit.HasCapturedThis && !(Parent is AnonymousMethodStorey)) { + AddCapturedThisField (ec); + OriginalSourceBlock.AddScopeStatement (new ThisInitializer (hoisted_this)); + } + // // Setting currect anonymous method to null blocks any further variable hoisting // @@ -333,10 +364,6 @@ namespace Mono.CSharp { EmitHoistedParameters (ec, hoisted_params); } - if (hoisted_this != null) { - hoisted_this.EmitHoistingAssignment (ec); - } - ec.CurrentAnonymousMethod = ae; } @@ -364,8 +391,6 @@ namespace Mono.CSharp { param.EmitSymbolInfo (); } - DefineStoreyReferences (); - if (used_parent_storeys != null) { foreach (StoreyFieldPair sf in used_parent_storeys) { SymbolWriter.DefineCapturedScope (ID, sf.Storey.ID, sf.Field.Name); @@ -450,21 +475,8 @@ namespace Mono.CSharp { return local_info.Name; } - // - // Returns true when at least one local variable or parameter is - // hoisted, or story is transitioned - // - public bool HasHoistedVariables { - get { - return has_hoisted_variable || hoisted_params != null; - } - set { - has_hoisted_variable = value; - } - } - - public bool IsUndone { - get { return is_undone; } + public HoistedThis HoistedThis { + get { return hoisted_this; } } // @@ -496,7 +508,7 @@ namespace Mono.CSharp { Type t = MutateGenericType (method.DeclaringType); if (t != method.DeclaringType) { method = (MethodInfo) TypeManager.DropGenericMethodArguments (method); - if (method.Module == CodeGen.Module.Builder) + if (method.Module == Module.Builder) method = TypeBuilder.GetMethod (t, method); else method = (MethodInfo) MethodInfo.GetMethodFromHandle (method.MethodHandle, t.TypeHandle); @@ -522,7 +534,7 @@ namespace Mono.CSharp { Type t = MutateGenericType (ctor.DeclaringType); if (t != ctor.DeclaringType) { ctor = (ConstructorInfo) TypeManager.DropGenericMethodArguments (ctor); - if (ctor.Module == CodeGen.Module.Builder) + if (ctor.Module == Module.Builder) return TypeBuilder.GetConstructor (t, ctor); return (ConstructorInfo) ConstructorInfo.GetMethodFromHandle (ctor.MethodHandle, t.TypeHandle); @@ -551,10 +563,9 @@ namespace Mono.CSharp { { int rank = array.GetArrayRank (); Type element = TypeManager.GetElementType (array); - if (element.IsArray) - throw new NotImplementedException (); - - if (TypeManager.IsGenericParameter (element)) { + if (element.IsArray) { + element = MutateArrayType (element); + } else if (TypeManager.IsGenericParameter (element)) { element = MutateGenericArgument (element); } else if (TypeManager.IsGenericType (element)) { element = MutateGenericType (element); @@ -574,7 +585,7 @@ namespace Mono.CSharp { for (int i = 0; i < t_args.Length; ++i) t_args [i] = MutateType (t_args [i]); - return type.GetGenericTypeDefinition ().MakeGenericType (t_args); + return TypeManager.DropGenericTypeArguments (type).MakeGenericType (t_args); } #endif @@ -592,17 +603,14 @@ namespace Mono.CSharp { return type; } + public ArrayList ReferencesFromChildrenBlock { + get { return children_references; } + } + public static void Reset () { unique_id = 0; - } - - public void Undo () - { - is_undone = true; - if (hoisted_this != null) - hoisted_this.RemoveHoisting (); - } + } } public abstract class HoistedVariable @@ -644,10 +652,14 @@ namespace Mono.CSharp { FieldExpr cached_outer_access; protected HoistedVariable (AnonymousMethodStorey storey, string name, Type type) + : this (storey, storey.AddCapturedVariable (name, type)) { - this.storey = storey; + } - this.field = storey.AddCapturedVariable (name, type); + protected HoistedVariable (AnonymousMethodStorey storey, Field field) + { + this.storey = storey; + this.field = field; } public void AddressOf (EmitContext ec, AddressOp mode) @@ -794,17 +806,14 @@ namespace Mono.CSharp { public class HoistedThis : HoistedVariable { - readonly This this_reference; - - public HoistedThis (AnonymousMethodStorey storey, This this_reference) - : base (storey, "<>f__this", this_reference.Type) + public HoistedThis (AnonymousMethodStorey storey, Field field) + : base (storey, field) { - this.this_reference = this_reference; } public void EmitHoistingAssignment (EmitContext ec) { - SimpleAssign a = new SimpleAssign (GetFieldExpression (ec), this_reference); + SimpleAssign a = new SimpleAssign (GetFieldExpression (ec), ec.GetThis (field.Location)); if (a.Resolve (ec) != null) a.EmitStatement (ec); } @@ -817,11 +826,6 @@ namespace Mono.CSharp { public Field Field { get { return field; } } - - public void RemoveHoisting () - { - this_reference.RemoveHoisting (); - } } // @@ -846,11 +850,11 @@ namespace Mono.CSharp { public virtual bool HasExplicitParameters { get { - return Parameters != Parameters.Undefined; + return Parameters != ParametersCompiled.Undefined; } } - public Parameters Parameters { + public ParametersCompiled Parameters { get { return Block.Parameters; } } @@ -860,8 +864,10 @@ namespace Mono.CSharp { // public bool ImplicitStandardConversionExists (EmitContext ec, Type delegate_type) { - using (ec.Set (EmitContext.Flags.ProbingMode)) { - return Compatible (ec, delegate_type) != null; + using (ec.With (EmitContext.Flags.InferReturnType, false)) { + using (ec.Set (EmitContext.Flags.ProbingMode)) { + return Compatible (ec, delegate_type) != null; + } } } @@ -870,7 +876,6 @@ namespace Mono.CSharp { if (TypeManager.IsDelegateType (delegate_type)) return delegate_type; -#if GMCS_SOURCE if (TypeManager.DropGenericTypeArguments (delegate_type) == TypeManager.expression_type) { delegate_type = TypeManager.GetTypeArguments (delegate_type) [0]; if (TypeManager.IsDelegateType (delegate_type)) @@ -880,7 +885,6 @@ namespace Mono.CSharp { GetSignatureForError (), TypeManager.CSharpName (delegate_type)); return null; } -#endif Report.Error (1660, loc, "Cannot convert `{0}' to non-delegate type `{1}'", GetSignatureForError (), TypeManager.CSharpName (delegate_type)); @@ -965,16 +969,12 @@ namespace Mono.CSharp { return false; if (!TypeManager.IsDelegateType (delegate_type)) { -#if GMCS_SOURCE if (TypeManager.DropGenericTypeArguments (delegate_type) != TypeManager.expression_type) return false; - delegate_type = delegate_type.GetGenericArguments () [0]; + delegate_type = TypeManager.GetTypeArguments (delegate_type) [0]; if (!TypeManager.IsDelegateType (delegate_type)) return false; -#else - return false; -#endif } AParametersCollection d_params = TypeManager.GetDelegateParameters (delegate_type); @@ -987,7 +987,7 @@ namespace Mono.CSharp { if (!TypeManager.HasElementType (itype)) continue; - if (!TypeManager.IsGenericParameter (itype.GetElementType ())) + if (!TypeManager.IsGenericParameter (TypeManager.GetElementType (itype))) continue; } type_inference.ExactInference (Parameters.Types [i], itype); @@ -1005,6 +1005,7 @@ namespace Mono.CSharp { if (am == null) return null; + // Stop referencing gmcs NullLiteral type if (am.ReturnType == TypeManager.null_type) am.ReturnType = null; @@ -1054,9 +1055,11 @@ namespace Mono.CSharp { am = CreateExpressionTree (ec, delegate_type); if (!ec.IsInProbingMode) - compatibles.Add (type, am); + compatibles.Add (type, am == null ? EmptyExpression.Null : am); return am; + } catch (CompletionResult){ + throw; } catch (Exception e) { throw new InternalErrorException (e, loc); } @@ -1073,11 +1076,11 @@ namespace Mono.CSharp { return null; } - protected virtual Parameters ResolveParameters (EmitContext ec, TypeInferenceContext tic, Type delegate_type) + protected virtual ParametersCompiled ResolveParameters (EmitContext ec, TypeInferenceContext tic, Type delegate_type) { AParametersCollection delegate_parameters = TypeManager.GetDelegateParameters (delegate_type); - if (Parameters == Parameters.Undefined) { + if (Parameters == ParametersCompiled.Undefined) { // // We provide a set of inaccessible parameters // @@ -1098,7 +1101,7 @@ namespace Mono.CSharp { delegate_parameters.FixedParameters [i].ModFlags, null, loc); } - return Parameters.CreateFullyResolved (fixedpars, delegate_parameters.Types); + return ParametersCompiled.CreateFullyResolved (fixedpars, delegate_parameters.Types); } if (!VerifyExplicitParameters (delegate_type, delegate_parameters, ec.IsInProbingMode)) { @@ -1159,7 +1162,7 @@ namespace Mono.CSharp { protected AnonymousMethodBody CompatibleMethod (EmitContext ec, TypeInferenceContext tic, Type return_type, Type delegate_type) { - Parameters p = ResolveParameters (ec, tic, delegate_type); + ParametersCompiled p = ResolveParameters (ec, tic, delegate_type); if (p == null) return null; @@ -1172,7 +1175,7 @@ namespace Mono.CSharp { return anonymous; } - protected virtual AnonymousMethodBody CompatibleMethodFactory (Type return_type, Type delegate_type, Parameters p, ToplevelBlock b) + protected virtual AnonymousMethodBody CompatibleMethodFactory (Type return_type, Type delegate_type, ParametersCompiled p, ToplevelBlock b) { return new AnonymousMethodBody (p, b, return_type, delegate_type, loc); } @@ -1199,7 +1202,7 @@ namespace Mono.CSharp { public AnonymousMethodMethod (DeclSpace parent, AnonymousExpression am, AnonymousMethodStorey storey, GenericMethod generic, TypeExpr return_type, int mod, string real_name, MemberName name, - Parameters parameters) + ParametersCompiled parameters) : base (parent, generic, return_type, mod | Modifiers.COMPILER_GENERATED, name, parameters, null) { @@ -1224,7 +1227,7 @@ namespace Mono.CSharp { if (!base.ResolveMemberType ()) return false; - if (Storey != null && Storey.IsGeneric && Storey.HasHoistedVariables) { + if (Storey != null && Storey.IsGeneric) { AnonymousMethodStorey gstorey = Storey.GetGenericStorey (); if (gstorey != null) { if (!Parameters.IsEmpty) { @@ -1282,7 +1285,6 @@ namespace Mono.CSharp { this.loc = loc; } - public abstract void AddStoreyReference (AnonymousMethodStorey storey); public abstract string ContainerType { get; } public abstract bool IsIterator { get; } public abstract AnonymousMethodStorey Storey { get; } @@ -1328,12 +1330,25 @@ namespace Mono.CSharp { return res; } + + public void SetHasThisAccess () + { + Block.HasCapturedThis = true; + ExplicitBlock b = Block.Parent.Explicit; + + while (b != null) { + if (b.HasCapturedThis) + return; + + b.HasCapturedThis = true; + b = b.Parent == null ? null : b.Parent.Explicit; + } + } } public class AnonymousMethodBody : AnonymousExpression { - ArrayList referenced_storeys; - protected readonly Parameters parameters; + protected readonly ParametersCompiled parameters; AnonymousMethodStorey storey; AnonymousMethodMethod method; @@ -1341,7 +1356,7 @@ namespace Mono.CSharp { static int unique_id; - public AnonymousMethodBody (Parameters parameters, + public AnonymousMethodBody (ParametersCompiled parameters, ToplevelBlock block, Type return_type, Type delegate_type, Location loc) : base (block, return_type, loc) @@ -1362,23 +1377,6 @@ namespace Mono.CSharp { get { return false; } } - // - // Adds new storey reference to track out of scope variables - // - public override void AddStoreyReference (AnonymousMethodStorey storey) - { - if (referenced_storeys == null) { - referenced_storeys = new ArrayList (2); - } else { - foreach (AnonymousMethodStorey ams in referenced_storeys) { - if (ams == storey) - return; - } - } - - referenced_storeys.Add (storey); - } - public override Expression CreateExpressionTree (EmitContext ec) { Report.Error (1945, loc, "An expression tree cannot contain an anonymous method expression"); @@ -1390,33 +1388,9 @@ namespace Mono.CSharp { if (aec == null && !Compatible (ec)) return false; - if (referenced_storeys != null) - ConnectReferencedStoreys (); - return true; } - void ConnectReferencedStoreys () - { - storey = FindBestMethodStorey (); - - foreach (AnonymousMethodStorey s in referenced_storeys) { - // - // An anonymous method has to have an instance access when - // children anonymous method requires access to parent storey - // hoisted variables - // - for (Block b = Block.Parent; b != s.OriginalSourceBlock; b = b.Parent) - b.Toplevel.HasStoreyAccess = true; - - if (s == storey) - continue; - - s.HasHoistedVariables = true; - Block.Parent.Explicit.PropagateStoreyReference (s); - } - } - // // Creates a host for the anonymous method // @@ -1431,10 +1405,8 @@ namespace Mono.CSharp { // int modifiers; - if (referenced_storeys != null || Block.HasStoreyAccess) { - if (storey == null || storey.IsUndone) - storey = FindBestMethodStorey (); - + if (Block.HasCapturedVariable || Block.HasCapturedThis) { + storey = FindBestMethodStorey (); modifiers = storey != null ? Modifiers.INTERNAL : Modifiers.PRIVATE; } else { if (ec.CurrentAnonymousMethod != null) @@ -1561,7 +1533,6 @@ namespace Mono.CSharp { } MethodInfo delegate_method = method.MethodBuilder; -#if GMCS_SOURCE if (storey != null && storey.MemberName.IsGeneric) { Type t = storey.Instance.Type; @@ -1575,9 +1546,13 @@ namespace Mono.CSharp { t = storey.GetGenericStorey ().MutateType (t); } +#if GMCS_SOURCE delegate_method = TypeBuilder.GetMethod (t, delegate_method); - } +#else + throw new NotSupportedException (); #endif + } + ig.Emit (OpCodes.Ldftn, delegate_method); ConstructorInfo constructor_method = Delegate.GetConstructor (ec.ContainerType, type); @@ -1632,6 +1607,20 @@ namespace Mono.CSharp { // public class AnonymousTypeClass : CompilerGeneratedClass { + sealed class AnonymousParameters : ParametersCompiled + { + public AnonymousParameters (params Parameter[] parameters) + : base (parameters) + { + } + + protected override void ErrorDuplicateName (Parameter p) + { + Report.Error (833, p.Location, "`{0}': An anonymous type cannot have multiple properties with the same name", + p.Name); + } + } + static int types_counter; public const string ClassNamePrefix = "<>__AnonType"; public const string SignatureForError = "anonymous type"; @@ -1646,8 +1635,8 @@ namespace Mono.CSharp { public static AnonymousTypeClass Create (TypeContainer parent, ArrayList parameters, Location loc) { - if (RootContext.Version <= LanguageVersion.ISO_2) - Report.FeatureIsNotAvailable (loc, "anonymous types"); + if (RootContext.MetadataCompatibilityVersion < MetadataVersion.v2) + Report.FeatureIsNotSupported (loc, "anonymous types"); string name = ClassNamePrefix + types_counter++; @@ -1673,7 +1662,7 @@ namespace Mono.CSharp { a_type.SetParameterInfo (null); Constructor c = new Constructor (a_type, name, Modifiers.PUBLIC | Modifiers.DEBUGGER_HIDDEN, - null, new Parameters (ctor_params), null, loc); + null, new AnonymousParameters (ctor_params), null, loc); c.Block = new ToplevelBlock (c.Parameters, loc); // @@ -1688,8 +1677,6 @@ namespace Mono.CSharp { if (!a_type.AddField (f)) { error = true; - Report.Error (833, p.Location, "`{0}': An anonymous type cannot have multiple properties with the same name", - p.Name); continue; } @@ -1737,11 +1724,11 @@ namespace Mono.CSharp { Method equals = new Method (this, null, TypeManager.system_boolean_expr, Modifiers.PUBLIC | Modifiers.OVERRIDE | Modifiers.DEBUGGER_HIDDEN, new MemberName ("Equals", loc), - Mono.CSharp.Parameters.CreateFullyResolved (new Parameter (null, "obj", 0, null, loc), TypeManager.object_type), null); + Mono.CSharp.ParametersCompiled.CreateFullyResolved (new Parameter (null, "obj", 0, null, loc), TypeManager.object_type), null); Method tostring = new Method (this, null, TypeManager.system_string_expr, Modifiers.PUBLIC | Modifiers.OVERRIDE | Modifiers.DEBUGGER_HIDDEN, new MemberName ("ToString", loc), - Mono.CSharp.Parameters.EmptyReadOnlyParameters, null); + Mono.CSharp.ParametersCompiled.EmptyReadOnlyParameters, null); ToplevelBlock equals_block = new ToplevelBlock (equals.Parameters, loc); TypeExpr current_type; @@ -1757,7 +1744,7 @@ namespace Mono.CSharp { new QualifiedAliasMember ("global", "System", loc), "Collections", loc), "Generic", loc); Expression rs_equals = null; - Expression string_concat = new StringConstant ("", loc); + Expression string_concat = new StringConstant ("{", loc); Expression rs_hashcode = new IntConstant (-2128831035, loc); for (int i = 0; i < parameters.Count; ++i) { AnonymousTypeParameter p = (AnonymousTypeParameter) parameters [i]; @@ -1789,13 +1776,15 @@ namespace Mono.CSharp { new MemberAccess (new This (f.Location), f.Name), new NullLiteral (loc)), new Invocation (new MemberAccess ( new MemberAccess (new This (f.Location), f.Name), "ToString"), null), - new StringConstant ("", loc)); + new StringConstant (string.Empty, loc)); if (rs_equals == null) { rs_equals = field_equal; string_concat = new Binary (Binary.Operator.Addition, - new StringConstant (p.Name + " = ", loc), - field_to_string); + string_concat, + new Binary (Binary.Operator.Addition, + new StringConstant (" " + p.Name + " = ", loc), + field_to_string)); continue; } @@ -1811,6 +1800,10 @@ namespace Mono.CSharp { rs_equals = new Binary (Binary.Operator.LogicalAnd, rs_equals, field_equal); } + string_concat = new Binary (Binary.Operator.Addition, + string_concat, + new StringConstant (" }", loc)); + // // Equals (object obj) override // @@ -1834,7 +1827,7 @@ namespace Mono.CSharp { Method hashcode = new Method (this, null, TypeManager.system_int32_expr, Modifiers.PUBLIC | Modifiers.OVERRIDE | Modifiers.DEBUGGER_HIDDEN, new MemberName ("GetHashCode", loc), - Mono.CSharp.Parameters.EmptyReadOnlyParameters, null); + Mono.CSharp.ParametersCompiled.EmptyReadOnlyParameters, null); // // Modified FNV with good avalanche behavior and uniform @@ -1850,7 +1843,10 @@ namespace Mono.CSharp { // hash ^= hash >> 17; // hash += hash << 5; - ToplevelBlock hashcode_block = new ToplevelBlock (loc); + ToplevelBlock hashcode_top = new ToplevelBlock (loc); + Block hashcode_block = new Block (hashcode_top); + hashcode_top.AddStatement (new Unchecked (hashcode_block)); + hashcode_block.AddVariable (TypeManager.system_int32_expr, "hash", loc); LocalVariableReference hash_variable = new LocalVariableReference (hashcode_block, "hash", loc); hashcode_block.AddStatement (new StatementExpression ( @@ -1873,7 +1869,7 @@ namespace Mono.CSharp { new Binary (Binary.Operator.LeftShift, hash_variable, new IntConstant (5, loc))))); hashcode_block.AddStatement (new Return (hash_variable, loc)); - hashcode.Block = hashcode_block; + hashcode.Block = hashcode_top; hashcode.Define (); AddMethod (hashcode);