X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fanonymous.cs;h=25fd1675bf445de538a0f262a57f78f0d253e491;hb=3912066fe1134ba665770723a24c8ea9b4f1aea3;hp=9bc786205a28f7adfb0b4f356b0d0b2e40215479;hpb=0fcf330866e1635c2eb62af1a453ffce1526c9e3;p=mono.git diff --git a/mcs/mcs/anonymous.cs b/mcs/mcs/anonymous.cs index 9bc786205a2..25fd1675bf4 100644 --- a/mcs/mcs/anonymous.cs +++ b/mcs/mcs/anonymous.cs @@ -191,15 +191,32 @@ namespace Mono.CSharp { sealed class ThisInitializer : Statement { readonly HoistedThis hoisted_this; + readonly AnonymousMethodStorey parent; - public ThisInitializer (HoistedThis hoisted_this) + public ThisInitializer (HoistedThis hoisted_this, AnonymousMethodStorey parent) { this.hoisted_this = hoisted_this; + this.parent = parent; + } + + public override bool Resolve (BlockContext bc) + { + return base.Resolve (bc); } protected override void DoEmit (EmitContext ec) { - hoisted_this.EmitAssign (ec, new CompilerGeneratedThis (ec.CurrentType, loc), false, false); + Expression source = EmptyExpression.Null; + + if (parent == null) + source = new CompilerGeneratedThis (ec.CurrentType, loc); + else { + source = new FieldExpr (parent.HoistedThis.Field, Location.Null) { + InstanceExpression = new CompilerGeneratedThis (ec.CurrentType, Location.Null) + }; + } + + hoisted_this.EmitAssign (ec, source, false, false); } protected override void CloneTo (CloneContext clonectx, Statement target) @@ -229,6 +246,7 @@ namespace Mono.CSharp { public Expression Instance; bool initialize_hoisted_this; + AnonymousMethodStorey hoisted_this_parent; public AnonymousMethodStorey (ExplicitBlock block, TypeDefinition parent, MemberBase host, TypeParameters tparams, string name, MemberKind kind) : base (parent, MakeMemberName (host, name, parent.Module.CounterAnonymousContainers, tparams, block.StartLocation), @@ -238,13 +256,14 @@ namespace Mono.CSharp { ID = parent.Module.CounterAnonymousContainers++; } - public void AddCapturedThisField (EmitContext ec) + public void AddCapturedThisField (EmitContext ec, AnonymousMethodStorey parent) { TypeExpr type_expr = new TypeExpression (ec.CurrentType, Location); Field f = AddCompilerGeneratedField ("$this", type_expr); hoisted_this = new HoistedThis (this, f); initialize_hoisted_this = true; + hoisted_this_parent = parent; } public Field AddCapturedVariable (string name, TypeSpec type) @@ -315,8 +334,11 @@ namespace Mono.CSharp { var hoisted = localVariable.HoistedVariant; if (hoisted != null && hoisted.Storey != this && hoisted.Storey is StateMachine) { - // TODO: It's too late the field is defined in HoistedLocalVariable ctor + // + // Variable is already hoisted but we need it in storey which can be shared + // hoisted.Storey.hoisted_locals.Remove (hoisted); + hoisted.Storey.Members.Remove (hoisted.Field); hoisted = null; } @@ -550,7 +572,7 @@ namespace Mono.CSharp { // referenced indirectly // if (initialize_hoisted_this) { - rc.CurrentBlock.AddScopeStatement (new ThisInitializer (hoisted_this)); + rc.CurrentBlock.AddScopeStatement (new ThisInitializer (hoisted_this, hoisted_this_parent)); } // @@ -569,6 +591,9 @@ namespace Mono.CSharp { protected virtual void EmitHoistedParameters (EmitContext ec, List hoisted) { foreach (HoistedParameter hp in hoisted) { + if (hp == null) + continue; + // // Parameters could be proxied via local fields for value type storey // @@ -725,6 +750,12 @@ namespace Mono.CSharp { this.field = field; } + public Field Field { + get { + return field; + } + } + public AnonymousMethodStorey Storey { get { return storey; @@ -845,11 +876,7 @@ namespace Mono.CSharp { #region Properties - public Field Field { - get { - return field; - } - } + public bool IsAssigned { get; set; } public ParameterReference Parameter { get { @@ -888,12 +915,6 @@ namespace Mono.CSharp { : base (storey, field) { } - - public Field Field { - get { - return field; - } - } } // @@ -954,6 +975,12 @@ namespace Mono.CSharp { } } + public override bool IsSideEffectFree { + get { + return true; + } + } + public ParametersCompiled Parameters { get { return Block.Parameters; @@ -996,36 +1023,36 @@ namespace Mono.CSharp { return delegate_type; ec.Report.Error (835, loc, "Cannot convert `{0}' to an expression tree of non-delegate type `{1}'", - GetSignatureForError (), TypeManager.CSharpName (delegate_type)); + GetSignatureForError (), delegate_type.GetSignatureForError ()); return null; } ec.Report.Error (1660, loc, "Cannot convert `{0}' to non-delegate type `{1}'", - GetSignatureForError (), TypeManager.CSharpName (delegate_type)); + GetSignatureForError (), delegate_type.GetSignatureForError ()); return null; } - protected bool VerifyExplicitParameters (ResolveContext ec, TypeSpec delegate_type, AParametersCollection parameters) + protected bool VerifyExplicitParameters (ResolveContext ec, TypeInferenceContext tic, TypeSpec delegate_type, AParametersCollection parameters) { - if (VerifyParameterCompatibility (ec, delegate_type, parameters, ec.IsInProbingMode)) + if (VerifyParameterCompatibility (ec, tic, delegate_type, parameters, ec.IsInProbingMode)) return true; if (!ec.IsInProbingMode) ec.Report.Error (1661, loc, "Cannot convert `{0}' to delegate type `{1}' since there is a parameter mismatch", - GetSignatureForError (), TypeManager.CSharpName (delegate_type)); + GetSignatureForError (), delegate_type.GetSignatureForError ()); return false; } - protected bool VerifyParameterCompatibility (ResolveContext ec, TypeSpec delegate_type, AParametersCollection invoke_pd, bool ignore_errors) + protected bool VerifyParameterCompatibility (ResolveContext ec, TypeInferenceContext tic, TypeSpec delegate_type, AParametersCollection invoke_pd, bool ignore_errors) { if (Parameters.Count != invoke_pd.Count) { if (ignore_errors) return false; ec.Report.Error (1593, loc, "Delegate `{0}' does not take `{1}' arguments", - TypeManager.CSharpName (delegate_type), Parameters.Count.ToString ()); + delegate_type.GetSignatureForError (), Parameters.Count.ToString ()); return false; } @@ -1039,10 +1066,10 @@ namespace Mono.CSharp { return false; if (p_mod == Parameter.Modifier.NONE) - ec.Report.Error (1677, loc, "Parameter `{0}' should not be declared with the `{1}' keyword", - (i + 1).ToString (), Parameter.GetModifierSignature (Parameters.FixedParameters [i].ModFlags)); + ec.Report.Error (1677, Parameters[i].Location, "Parameter `{0}' should not be declared with the `{1}' keyword", + (i + 1).ToString (), Parameter.GetModifierSignature (Parameters [i].ModFlags)); else - ec.Report.Error (1676, loc, "Parameter `{0}' must be declared with the `{1}' keyword", + ec.Report.Error (1676, Parameters[i].Location, "Parameter `{0}' must be declared with the `{1}' keyword", (i+1).ToString (), Parameter.GetModifierSignature (p_mod)); error = true; } @@ -1051,22 +1078,18 @@ namespace Mono.CSharp { continue; TypeSpec type = invoke_pd.Types [i]; + + if (tic != null) + type = tic.InflateGenericArgument (ec, type); - // We assume that generic parameters are always inflated - if (TypeManager.IsGenericParameter (type)) - continue; - - if (TypeManager.HasElementType (type) && TypeManager.IsGenericParameter (TypeManager.GetElementType (type))) - continue; - - if (!TypeSpecComparer.IsEqual (invoke_pd.Types [i], Parameters.Types [i])) { + if (!TypeSpecComparer.IsEqual (type, Parameters.Types [i])) { if (ignore_errors) return false; - ec.Report.Error (1678, loc, "Parameter `{0}' is declared as type `{1}' but should be `{2}'", + ec.Report.Error (1678, Parameters [i].Location, "Parameter `{0}' is declared as type `{1}' but should be `{2}'", (i+1).ToString (), - TypeManager.CSharpName (Parameters.Types [i]), - TypeManager.CSharpName (invoke_pd.Types [i])); + Parameters.Types [i].GetSignatureForError (), + invoke_pd.Types [i].GetSignatureForError ()); error = true; } } @@ -1077,7 +1100,7 @@ namespace Mono.CSharp { // // Infers type arguments based on explicit arguments // - public bool ExplicitTypeInference (ResolveContext ec, TypeInferenceContext type_inference, TypeSpec delegate_type) + public bool ExplicitTypeInference (TypeInferenceContext type_inference, TypeSpec delegate_type) { if (!HasExplicitParameters) return false; @@ -1095,9 +1118,19 @@ namespace Mono.CSharp { if (d_params.Count != Parameters.Count) return false; + var ptypes = Parameters.Types; + var dtypes = d_params.Types; for (int i = 0; i < Parameters.Count; ++i) { - if (type_inference.ExactInference (Parameters.Types[i], d_params.Types[i]) == 0) + if (type_inference.ExactInference (ptypes[i], dtypes[i]) == 0) { + // + // Continue when 0 (quick path) does not mean inference failure. Checking for + // same type handles cases like int -> int + // + if (ptypes[i] == dtypes[i]) + continue; + return false; + } } return true; @@ -1214,6 +1247,17 @@ namespace Mono.CSharp { } } else { am = body.Compatible (ec); + + if (body.DirectMethodGroupConversion != null) { + var errors_printer = new SessionReportPrinter (); + var old = ec.Report.SetPrinter (errors_printer); + var expr = new ImplicitDelegateCreation (delegate_type, body.DirectMethodGroupConversion, loc) { + AllowSpecialMethodsInvocation = true + }.Resolve (ec); + ec.Report.SetPrinter (old); + if (expr != null && errors_printer.ErrorsCount == 0) + am = expr; + } } } catch (CompletionResult) { throw; @@ -1270,7 +1314,7 @@ namespace Mono.CSharp { return ParametersCompiled.CreateFullyResolved (fixedpars, delegate_parameters.Types); } - if (!VerifyExplicitParameters (ec, delegate_type, delegate_parameters)) { + if (!VerifyExplicitParameters (ec, tic, delegate_type, delegate_parameters)) { return null; } @@ -1349,10 +1393,10 @@ namespace Mono.CSharp { return null; } - b = b.ConvertToAsyncTask (ec, ec.CurrentMemberDefinition.Parent.PartialContainer, p, return_type, loc); + b = b.ConvertToAsyncTask (ec, ec.CurrentMemberDefinition.Parent.PartialContainer, p, return_type, delegate_type, loc); } - return CompatibleMethodFactory (return_type ?? InternalType.Arglist, delegate_type, p, b); + return CompatibleMethodFactory (return_type ?? InternalType.ErrorType, delegate_type, p, b); } protected virtual AnonymousMethodBody CompatibleMethodFactory (TypeSpec return_type, TypeSpec delegate_type, ParametersCompiled p, ParametersBlock b) @@ -1437,7 +1481,7 @@ namespace Mono.CSharp { } } - protected ParametersBlock block; + protected readonly ParametersBlock block; public TypeSpec ReturnType; @@ -1475,27 +1519,15 @@ namespace Mono.CSharp { BlockContext aec = new BlockContext (ec, block, ReturnType); aec.CurrentAnonymousMethod = ae; - ResolveContext.Options flags = 0; - var am = this as AnonymousMethodBody; if (ec.HasSet (ResolveContext.Options.InferReturnType) && am != null) { am.ReturnTypeInference = new TypeInferenceContext (); } - if (ec.IsInProbingMode) - flags |= ResolveContext.Options.ProbingMode; - - if (ec.HasSet (ResolveContext.Options.FieldInitializerScope)) - flags |= ResolveContext.Options.FieldInitializerScope; - - if (ec.HasSet (ResolveContext.Options.ExpressionTreeConversion)) - flags |= ResolveContext.Options.ExpressionTreeConversion; - - if (ec.HasSet (ResolveContext.Options.BaseInitializer)) - flags |= ResolveContext.Options.BaseInitializer; - - aec.Set (flags); + var bc = ec as BlockContext; + if (bc != null) + aec.FlowOffset = bc.FlowOffset; var errors = ec.Report.Errors; @@ -1564,6 +1596,14 @@ namespace Mono.CSharp { get { return "anonymous method"; } } + // + // Method-group instance for lambdas which can be replaced with + // simple method group call + // + public MethodGroupExpr DirectMethodGroupConversion { + get; set; + } + public override bool IsIterator { get { return false; @@ -1586,7 +1626,9 @@ namespace Mono.CSharp { } public override AnonymousMethodStorey Storey { - get { return storey; } + get { + return storey; + } } #endregion @@ -1631,28 +1673,39 @@ namespace Mono.CSharp { parent = storey = FindBestMethodStorey (); if (storey == null) { - var sm = src_block.ParametersBlock.TopBlock.StateMachine; + var top_block = src_block.ParametersBlock.TopBlock; + var sm = top_block.StateMachine; - // - // Remove hoisted this demand when simple instance method is enough - // if (src_block.HasCapturedThis) { - src_block.ParametersBlock.TopBlock.RemoveThisReferenceFromChildrenBlock (src_block); - // - // Special case where parent class is used to emit instance method - // because currect storey is of value type (async host) and we don't - // want to create another childer storey to host this reference only + // Remove hoisted 'this' request when simple instance method is + // enough. No hoisted variables only 'this' and don't need to + // propagate this to value type state machine. + // + StateMachine sm_parent; + var pb = src_block.ParametersBlock; + do { + sm_parent = pb.StateMachine; + pb = pb.Parent == null ? null : pb.Parent.ParametersBlock; + } while (sm_parent == null && pb != null); + + if (sm_parent == null) { + top_block.RemoveThisReferenceFromChildrenBlock (src_block); + } else if (sm_parent.Kind == MemberKind.Struct) { + // + // Special case where parent class is used to emit instance method + // because currect storey is of value type (async host) and we cannot + // use ldftn on non-boxed instances either to share mutated state + // + parent = sm_parent.Parent.PartialContainer; + } + } else { // - if (sm != null && sm.Kind == MemberKind.Struct) - parent = sm.Parent.PartialContainer; + // For iterators we can host everything in one class + // + if (sm is IteratorStorey) + parent = storey = sm; } - - // - // For iterators we can host everything in one class - // - if (sm is IteratorStorey) - parent = storey = sm; } modifiers = storey != null ? Modifiers.INTERNAL : Modifiers.PRIVATE; @@ -1710,6 +1763,7 @@ namespace Mono.CSharp { // method = DoCreateMethodHost (ec); method.Define (); + method.PrepareEmit (); } bool is_static = (method.ModFlags & Modifiers.STATIC) != 0; @@ -1774,12 +1828,8 @@ namespace Mono.CSharp { // Special case for value type storey where this is not lifted but // droped off to parent class // - for (var b = Block.Parent; b != null; b = b.Parent) { - if (b.ParametersBlock.StateMachine != null) { - ec.Emit (OpCodes.Ldfld, b.ParametersBlock.StateMachine.HoistedThis.Field.Spec); - break; - } - } + if (ec.CurrentAnonymousMethod != null && ec.AsyncTaskStorey != null) + ec.Emit (OpCodes.Ldfld, ec.AsyncTaskStorey.HoistedThis.Field.Spec); } var delegate_method = method.Spec; @@ -1836,7 +1886,7 @@ namespace Mono.CSharp { public override string GetSignatureForError () { - return TypeManager.CSharpName (type); + return type.GetSignatureForError (); } } @@ -1958,7 +2008,7 @@ namespace Mono.CSharp { Method tostring = new Method (this, new TypeExpression (Compiler.BuiltinTypes.String, loc), Modifiers.PUBLIC | Modifiers.OVERRIDE | Modifiers.DEBUGGER_HIDDEN, new MemberName ("ToString", loc), - Mono.CSharp.ParametersCompiled.EmptyReadOnlyParameters, null); + ParametersCompiled.EmptyReadOnlyParameters, null); ToplevelBlock equals_block = new ToplevelBlock (Compiler, equals.ParameterInfo, loc); @@ -1975,7 +2025,7 @@ namespace Mono.CSharp { } var li_other = LocalVariable.CreateCompilerGenerated (CurrentType, equals_block, loc); - equals_block.AddStatement (new BlockVariableDeclaration (new TypeExpression (li_other.Type, loc), li_other)); + equals_block.AddStatement (new BlockVariable (new TypeExpression (li_other.Type, loc), li_other)); var other_variable = new LocalVariableReference (li_other, loc); MemberAccess system_collections_generic = new MemberAccess (new MemberAccess ( @@ -2058,6 +2108,7 @@ namespace Mono.CSharp { equals.Block = equals_block; equals.Define (); + equals.PrepareEmit (); Members.Add (equals); // @@ -2066,7 +2117,7 @@ namespace Mono.CSharp { Method hashcode = new Method (this, new TypeExpression (Compiler.BuiltinTypes.Int, loc), Modifiers.PUBLIC | Modifiers.OVERRIDE | Modifiers.DEBUGGER_HIDDEN, new MemberName ("GetHashCode", loc), - Mono.CSharp.ParametersCompiled.EmptyReadOnlyParameters, null); + ParametersCompiled.EmptyReadOnlyParameters, null); // // Modified FNV with good avalanche behavior and uniform @@ -2087,7 +2138,7 @@ namespace Mono.CSharp { hashcode_top.AddStatement (new Unchecked (hashcode_block, loc)); var li_hash = LocalVariable.CreateCompilerGenerated (Compiler.BuiltinTypes.Int, hashcode_top, loc); - hashcode_block.AddStatement (new BlockVariableDeclaration (new TypeExpression (li_hash.Type, loc), li_hash)); + hashcode_block.AddStatement (new BlockVariable (new TypeExpression (li_hash.Type, loc), li_hash)); LocalVariableReference hash_variable_assign = new LocalVariableReference (li_hash, loc); hashcode_block.AddStatement (new StatementExpression ( new SimpleAssign (hash_variable_assign, rs_hashcode))); @@ -2112,6 +2163,7 @@ namespace Mono.CSharp { hashcode_block.AddStatement (new Return (hash_variable, loc)); hashcode.Block = hashcode_top; hashcode.Define (); + hashcode.PrepareEmit (); Members.Add (hashcode); // @@ -2122,6 +2174,7 @@ namespace Mono.CSharp { tostring_block.AddStatement (new Return (string_concat, loc)); tostring.Block = tostring_block; tostring.Define (); + tostring.PrepareEmit (); Members.Add (tostring); return true;