X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fanonymous.cs;h=36a55cc761b4510cbe67e6cd4532c11d2885e049;hb=2d23bfcbce7a3f7e54dcd5911adb88b244baca35;hp=b11557f31afc3bc858bd50a9cb67b2e431a49da0;hpb=7755c3d7d726d5d85a79763a15f7cc998956ac14;p=mono.git diff --git a/mcs/mcs/anonymous.cs b/mcs/mcs/anonymous.cs index b11557f31af..36a55cc761b 100644 --- a/mcs/mcs/anonymous.cs +++ b/mcs/mcs/anonymous.cs @@ -11,8 +11,7 @@ using System; using System.Text; -using System.Collections; -using System.Collections.Specialized; +using System.Collections.Generic; using System.Reflection; using System.Reflection.Emit; @@ -25,27 +24,14 @@ namespace Mono.CSharp { return "<" + host + ">" + typePrefix + "__" + name + id.ToString ("X"); } - protected CompilerGeneratedClass (DeclSpace parent, MemberName name, int mod) - : base (parent.NamespaceEntry, parent, name, mod | Modifiers.COMPILER_GENERATED | Modifiers.SEALED, null) + protected CompilerGeneratedClass (DeclSpace parent, MemberName name, Modifiers mod) + : base (parent.NamespaceEntry, parent, name, mod | Modifiers.COMPILER_GENERATED, null) { } - protected CompilerGeneratedClass (DeclSpace parent, GenericMethod generic, MemberName name, int mod) - : this (parent, name, mod) - { - if (generic != null) { - ArrayList list = new ArrayList (); - foreach (TypeParameter tparam in generic.TypeParameters) { - if (tparam.Constraints != null) - list.Add (tparam.Constraints.Clone ()); - } - SetParameterInfo (list); - } - } - protected void CheckMembersDefined () { - if (members_defined) + if (HasMembersDefined) throw new InternalErrorException ("Helper class already defined!"); } } @@ -57,7 +43,8 @@ namespace Mono.CSharp { // public class AnonymousMethodStorey : CompilerGeneratedClass { - class StoreyFieldPair { + struct StoreyFieldPair + { public readonly AnonymousMethodStorey Storey; public readonly Field Field; @@ -66,21 +53,11 @@ namespace Mono.CSharp { this.Storey = storey; this.Field = field; } - - public override int GetHashCode () - { - return Storey.ID.GetHashCode (); - } - - public override bool Equals (object obj) - { - return (AnonymousMethodStorey)obj == Storey; - } } sealed class HoistedGenericField : Field { - public HoistedGenericField (DeclSpace parent, FullNamedExpression type, int mod, string name, + public HoistedGenericField (DeclSpace parent, FullNamedExpression type, Modifiers mod, string name, Attributes attrs, Location loc) : base (parent, type, mod, new MemberName (name, loc), attrs) { @@ -92,8 +69,8 @@ namespace Mono.CSharp { return false; AnonymousMethodStorey parent = ((AnonymousMethodStorey) Parent).GetGenericStorey (); - if (parent != null) - member_type = parent.MutateType (member_type); + if (parent != null && parent.Mutator != null) + member_type = parent.Mutator.Mutate (MemberType); return true; } @@ -123,11 +100,6 @@ namespace Mono.CSharp { { // Nothing to clone } - - public override void MutateHoistedGenericType (AnonymousMethodStorey storey) - { - // Nothing to mutate - } } // Unique storey ID @@ -137,12 +109,12 @@ namespace Mono.CSharp { public readonly Block OriginalSourceBlock; // A list of StoreyFieldPair with local field keeping parent storey instance - ArrayList used_parent_storeys; - ArrayList children_references; + List used_parent_storeys; + List children_references; // A list of hoisted parameters - protected ArrayList hoisted_params; - protected ArrayList hoisted_locals; + protected List hoisted_params; + protected List hoisted_locals; // Hoisted this protected HoistedThis hoisted_this; @@ -150,12 +122,22 @@ namespace Mono.CSharp { // Local variable which holds this storey instance public LocalTemporary Instance; - public AnonymousMethodStorey (Block block, DeclSpace parent, MemberBase host, GenericMethod generic, string name) - : base (parent, generic, MakeMemberName (host, name, generic, block.StartLocation), Modifiers.PRIVATE) + TypeParameterMutator mutator; + + public AnonymousMethodStorey (Block block, TypeContainer parent, MemberBase host, GenericMethod generic, string name) + : base (parent, MakeMemberName (host, name, generic, block.StartLocation), Modifiers.PRIVATE | Modifiers.SEALED) { Parent = parent; OriginalSourceBlock = block; ID = unique_id++; + + if (generic != null) { + var hoisted_tparams = generic.CurrentTypeParameters; + type_params = new TypeParameter [hoisted_tparams.Length]; + for (int i = 0; i < type_params.Length; ++i) { + type_params[i] = hoisted_tparams[i].CreateHoistedCopy (spec); + } + } } static MemberName MakeMemberName (MemberBase host, string name, GenericMethod generic, Location loc) @@ -174,13 +156,22 @@ namespace Mono.CSharp { public void AddCapturedThisField (EmitContext ec) { - TypeExpr type_expr = new TypeExpression (ec.ContainerType, Location); + TypeExpr type_expr = new TypeExpression (ec.CurrentType, Location); Field f = AddCompilerGeneratedField ("<>f__this", type_expr); f.Define (); hoisted_this = new HoistedThis (this, f); + + // Inflated type instance has to be updated manually + if (Instance.Type != f.Parent.CurrentType) { + var inflator = new TypeParameterInflator (Instance.Type, TypeParameterSpec.EmptyTypes, TypeSpec.EmptyTypes); + Instance.Type.MemberCache.AddMember (f.Spec.InflateMember (inflator)); + + inflator = new TypeParameterInflator (f.Parent.CurrentType, TypeParameterSpec.EmptyTypes, TypeSpec.EmptyTypes); + f.Parent.CurrentType.MemberCache.AddMember (f.Spec.InflateMember (inflator)); + } } - public Field AddCapturedVariable (string name, Type type) + public Field AddCapturedVariable (string name, TypeSpec type) { CheckMembersDefined (); @@ -188,7 +179,7 @@ namespace Mono.CSharp { if (!IsGeneric) return AddCompilerGeneratedField (name, field_type); - const int mod = Modifiers.INTERNAL | Modifiers.COMPILER_GENERATED; + const Modifiers mod = Modifiers.INTERNAL | Modifiers.COMPILER_GENERATED; Field f = new HoistedGenericField (this, field_type, mod, name, null, Location); AddField (f); return f; @@ -196,7 +187,7 @@ namespace Mono.CSharp { protected Field AddCompilerGeneratedField (string name, FullNamedExpression type) { - const int mod = Modifiers.INTERNAL | Modifiers.COMPILER_GENERATED; + const Modifiers mod = Modifiers.INTERNAL | Modifiers.COMPILER_GENERATED; Field f = new Field (this, type, mod, new MemberName (name, Location), null); AddField (f); return f; @@ -212,45 +203,45 @@ namespace Mono.CSharp { public void AddReferenceFromChildrenBlock (ExplicitBlock block) { if (children_references == null) - children_references = new ArrayList (); + children_references = new List (); if (!children_references.Contains (block)) children_references.Add (block); } - public void AddParentStoreyReference (AnonymousMethodStorey storey) + public void AddParentStoreyReference (EmitContext ec, AnonymousMethodStorey storey) { CheckMembersDefined (); if (used_parent_storeys == null) - used_parent_storeys = new ArrayList (); - else if (used_parent_storeys.IndexOf (storey) != -1) + used_parent_storeys = new List (); + else if (used_parent_storeys.Exists (i => i.Storey == storey)) return; - TypeExpr type_expr = new TypeExpression (storey.TypeBuilder, Location); + TypeExpr type_expr = storey.CreateStoreyTypeExpression (ec); 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) + public void CaptureLocalVariable (ResolveContext 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) + if (local_info.HoistedVariant != null) return; HoistedVariable var = new HoistedLocalVariable (this, local_info, GetVariableMangledName (local_info)); - local_info.HoistedVariableReference = var; + local_info.HoistedVariant = var; if (hoisted_locals == null) - hoisted_locals = new ArrayList (); + hoisted_locals = new List (); hoisted_locals.Add (var); } - public void CaptureParameter (EmitContext ec, ParameterReference param_ref) + public void CaptureParameter (ResolveContext ec, ParameterReference param_ref) { ec.CurrentBlock.Explicit.HasCapturedVariable = true; AddReferenceFromChildrenBlock (ec.CurrentBlock.Explicit); @@ -259,60 +250,98 @@ namespace Mono.CSharp { return; if (hoisted_params == null) - hoisted_params = new ArrayList (2); + hoisted_params = new List (2); - HoistedVariable expr = new HoistedParameter (this, param_ref); - param_ref.Parameter.HoistedVariableReference = expr; + var expr = new HoistedParameter (this, param_ref); + param_ref.Parameter.HoistedVariant = expr; hoisted_params.Add (expr); } - public void ChangeParentStorey (AnonymousMethodStorey parentStorey) - { - Parent = parentStorey; - type_params = null; - } - - // - // Initializes all hoisted variables - // - public void EmitStoreyInstantiation (EmitContext ec) + TypeExpr CreateStoreyTypeExpression (EmitContext ec) { - // There can be only one instance variable for each storey type - if (Instance != null) - throw new InternalErrorException (); - - SymbolWriter.OpenCompilerGeneratedBlock (ec.ig); - // // Create an instance of storey type // - Expression storey_type_expr; - if (is_generic) { + TypeExpr storey_type_expr; + if (CurrentTypeParameters != null) { // // Use current method type parameter (MVAR) for top level storey only. All // nested storeys use class type parameter (VAR) // TypeParameter[] tparams = ec.CurrentAnonymousMethod != null && ec.CurrentAnonymousMethod.Storey != null ? ec.CurrentAnonymousMethod.Storey.TypeParameters : - ec.GenericDeclContainer.TypeParameters; + ec.CurrentTypeParameters; TypeArguments targs = new TypeArguments (); - if (tparams.Length < CountTypeParameters) { - 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)); - } - + // + // Use type parameter name instead of resolved type parameter + // specification to resolve to correctly nested type parameters + // for (int i = 0; i < tparams.Length; ++i) - targs.Add (new TypeParameterExpr (tparams[i], Location)); + targs.Add (new SimpleName (tparams [i].Name, Location)); // new TypeParameterExpr (tparams[i], Location)); - storey_type_expr = new GenericTypeExpr (TypeBuilder, targs, Location); + storey_type_expr = new GenericTypeExpr (Definition, targs, Location); } else { - storey_type_expr = new TypeExpression (TypeBuilder, Location); + storey_type_expr = new TypeExpression (CurrentType, Location); } - Expression e = new New (storey_type_expr, new ArrayList (0), Location).Resolve (ec); + return storey_type_expr; + } + + public void SetNestedStoryParent (AnonymousMethodStorey parentStorey) + { + Parent = parentStorey; + type_params = null; + spec.IsGeneric = false; + spec.DeclaringType = parentStorey.CurrentType; +// MemberName.TypeArguments = null; + } + + protected override bool DoResolveTypeParameters () + { + // Although any storey can have type parameters they are all clones of method type + // parameters therefore have to mutate MVAR references in any of cloned constraints + if (type_params != null) { + for (int i = 0; i < type_params.Length; ++i) { + var spec = type_params[i].Type; + spec.BaseType = mutator.Mutate (spec.BaseType); + if (spec.Interfaces != null) { + var mutated = new TypeSpec[spec.Interfaces.Count]; + for (int ii = 0; ii < mutated.Length; ++ii) { + mutated [ii] = mutator.Mutate (spec.Interfaces[ii]); + } + + spec.Interfaces = mutated; + } + + if (spec.TypeArguments != null) { + spec.TypeArguments = mutator.Mutate (spec.TypeArguments); + } + } + } + + return true; + } + + // + // Initializes all hoisted variables + // + public void EmitStoreyInstantiation (EmitContext ec) + { + // There can be only one instance variable for each storey type + if (Instance != null) + throw new InternalErrorException (); + + SymbolWriter.OpenCompilerGeneratedBlock (ec); + + // + // Create an instance of a storey + // + Expression storey_type_expr = CreateStoreyTypeExpression (ec); + + ResolveContext rc = new ResolveContext (ec.MemberContext); + Expression e = new New (storey_type_expr, null, Location).Resolve (rc); e.Emit (ec); Instance = new LocalTemporary (storey_type_expr.Type); @@ -321,7 +350,7 @@ namespace Mono.CSharp { EmitHoistedFieldsInitialization (ec); SymbolWriter.DefineScopeVariable (ID, Instance.Builder); - SymbolWriter.CloseCompilerGeneratedBlock (ec.ig); + SymbolWriter.CloseCompilerGeneratedBlock (ec); } void EmitHoistedFieldsInitialization (EmitContext ec) @@ -330,18 +359,22 @@ namespace Mono.CSharp { // Initialize all storey reference fields by using local or hoisted variables // if (used_parent_storeys != null) { + var rc = new ResolveContext (ec.MemberContext); + foreach (StoreyFieldPair sf in used_parent_storeys) { // - // Setting local field + // Get instance expression of storey field // Expression instace_expr = GetStoreyInstanceExpression (ec); - FieldExpr f_set_expr = TypeManager.IsGenericType (instace_expr.Type) ? - new FieldExpr (sf.Field.FieldBuilder, instace_expr.Type, Location) : - new FieldExpr (sf.Field.FieldBuilder, Location); + var fs = sf.Field.Spec; + if (TypeManager.IsGenericType (instace_expr.Type)) + fs = MemberCache.GetMember (instace_expr.Type, fs); + + FieldExpr f_set_expr = new FieldExpr (fs, Location); f_set_expr.InstanceExpression = instace_expr; SimpleAssign a = new SimpleAssign (f_set_expr, sf.Storey.GetStoreyInstanceExpression (ec)); - if (a.Resolve (ec) != null) + if (a.Resolve (rc) != null) a.EmitStatement (ec); } } @@ -367,7 +400,7 @@ namespace Mono.CSharp { ec.CurrentAnonymousMethod = ae; } - protected virtual void EmitHoistedParameters (EmitContext ec, ArrayList hoisted) + protected virtual void EmitHoistedParameters (EmitContext ec, IList hoisted) { foreach (HoistedParameter hp in hoisted) { hp.EmitHoistingAssignment (ec); @@ -403,7 +436,7 @@ namespace Mono.CSharp { public AnonymousMethodStorey GetGenericStorey () { DeclSpace storey = this; - while (storey != null && storey.CurrentTypeParameters.Length == 0) + while (storey != null && storey.CurrentTypeParameters == null) storey = storey.Parent; return storey as AnonymousMethodStorey; @@ -450,7 +483,7 @@ namespace Mono.CSharp { // // Access inside of same storey (S -> S) // - return new CompilerGeneratedThis (TypeBuilder, Location); + return new CompilerGeneratedThis (CurrentType, Location); } // // External field access @@ -461,8 +494,8 @@ namespace Mono.CSharp { // // Storey was cached to local field // - FieldExpr f_ind = new FieldExpr (f.FieldBuilder, Location); - f_ind.InstanceExpression = new CompilerGeneratedThis (TypeBuilder, Location); + FieldExpr f_ind = new FieldExpr (f, Location); + f_ind.InstanceExpression = new CompilerGeneratedThis (CurrentType, Location); return f_ind; } @@ -479,131 +512,16 @@ namespace Mono.CSharp { get { return hoisted_this; } } - // - // Mutate type dispatcher - // - public Type MutateType (Type type) - { -#if GMCS_SOURCE - if (TypeManager.IsGenericType (type)) - return MutateGenericType (type); - - if (TypeManager.IsGenericParameter (type)) - return MutateGenericArgument (type); - - if (type.IsArray) - return MutateArrayType (type); -#endif - return type; - } - - // - // Changes method type arguments (MVAR) to storey (VAR) type arguments - // - public MethodInfo MutateGenericMethod (MethodInfo method) - { -#if GMCS_SOURCE - Type [] t_args = TypeManager.GetGenericArguments (method); - if (TypeManager.IsGenericType (method.DeclaringType)) { - Type t = MutateGenericType (method.DeclaringType); - if (t != method.DeclaringType) { - method = (MethodInfo) TypeManager.DropGenericMethodArguments (method); - if (method.Module == Module.Builder) - method = TypeBuilder.GetMethod (t, method); - else - method = (MethodInfo) MethodInfo.GetMethodFromHandle (method.MethodHandle, t.TypeHandle); - } - } - - if (t_args == null || t_args.Length == 0) - return method; - - for (int i = 0; i < t_args.Length; ++i) - t_args [i] = MutateType (t_args [i]); - - return method.GetGenericMethodDefinition ().MakeGenericMethod (t_args); -#else - throw new NotSupportedException (); -#endif - } - - public ConstructorInfo MutateConstructor (ConstructorInfo ctor) - { -#if GMCS_SOURCE - if (TypeManager.IsGenericType (ctor.DeclaringType)) { - Type t = MutateGenericType (ctor.DeclaringType); - if (t != ctor.DeclaringType) { - ctor = (ConstructorInfo) TypeManager.DropGenericMethodArguments (ctor); - if (ctor.Module == Module.Builder) - return TypeBuilder.GetConstructor (t, ctor); - - return (ConstructorInfo) ConstructorInfo.GetMethodFromHandle (ctor.MethodHandle, t.TypeHandle); - } - } -#endif - return ctor; - } - - public FieldInfo MutateField (FieldInfo field) - { -#if GMCS_SOURCE - if (TypeManager.IsGenericType (field.DeclaringType)) { - Type t = MutateGenericType (field.DeclaringType); - if (t != field.DeclaringType) { - // TODO: It should throw on imported types - return TypeBuilder.GetField (t, field); - } + public TypeParameterMutator Mutator { + get { + return mutator; } -#endif - return field; - } - -#if GMCS_SOURCE - protected Type MutateArrayType (Type array) - { - int rank = array.GetArrayRank (); - Type element = TypeManager.GetElementType (array); - if (element.IsArray) { - element = MutateArrayType (element); - } else if (TypeManager.IsGenericParameter (element)) { - element = MutateGenericArgument (element); - } else if (TypeManager.IsGenericType (element)) { - element = MutateGenericType (element); - } else { - return array; + set { + mutator = value; } - - return element.MakeArrayType (rank); } - protected Type MutateGenericType (Type type) - { - Type [] t_args = TypeManager.GetTypeArguments (type); - if (t_args == null || t_args.Length == 0) - return type; - - for (int i = 0; i < t_args.Length; ++i) - t_args [i] = MutateType (t_args [i]); - - return TypeManager.DropGenericTypeArguments (type).MakeGenericType (t_args); - } -#endif - - // - // Changes method generic argument (MVAR) to type generic argument (VAR) - // - public Type MutateGenericArgument (Type type) - { - foreach (TypeParameter tp in CurrentTypeParameters) { - if (tp.Name == type.Name) { - return tp.Type; - } - } - - return type; - } - - public ArrayList ReferencesFromChildrenBlock { + public IList ReferencesFromChildrenBlock { get { return children_references; } } @@ -615,21 +533,26 @@ namespace Mono.CSharp { public abstract class HoistedVariable { - class ExpressionTreeProxy : Expression + // + // Hoisted version of variable references used in expression + // tree has to be delayed until we know its location. The variable + // doesn't know its location until all stories are calculated + // + class ExpressionTreeVariableReference : Expression { readonly HoistedVariable hv; - public ExpressionTreeProxy (HoistedVariable hv) + public ExpressionTreeVariableReference (HoistedVariable hv) { this.hv = hv; } - public override Expression CreateExpressionTree (EmitContext ec) + public override Expression CreateExpressionTree (ResolveContext ec) { throw new NotSupportedException ("ET"); } - public override Expression DoResolve (EmitContext ec) + protected override Expression DoResolve (ResolveContext ec) { eclass = ExprClass.Value; type = TypeManager.expression_type_expr.Type; @@ -638,9 +561,10 @@ namespace Mono.CSharp { public override void Emit (EmitContext ec) { - Expression e = hv.GetFieldExpression (ec).CreateExpressionTree (ec); + ResolveContext rc = new ResolveContext (ec.MemberContext); + Expression e = hv.GetFieldExpression (ec).CreateExpressionTree (rc); // This should never fail - e = e.Resolve (ec); + e = e.Resolve (rc); if (e != null) e.Emit (ec); } @@ -648,10 +572,10 @@ namespace Mono.CSharp { protected readonly AnonymousMethodStorey storey; protected Field field; - Hashtable cached_inner_access; // TODO: Hashtable is too heavyweight + Dictionary cached_inner_access; // TODO: Hashtable is too heavyweight FieldExpr cached_outer_access; - protected HoistedVariable (AnonymousMethodStorey storey, string name, Type type) + protected HoistedVariable (AnonymousMethodStorey storey, string name, TypeSpec type) : this (storey, storey.AddCapturedVariable (name, type)) { } @@ -667,9 +591,9 @@ namespace Mono.CSharp { GetFieldExpression (ec).AddressOf (ec, mode); } - public Expression CreateExpressionTree (EmitContext ec) + public Expression CreateExpressionTree () { - return new ExpressionTreeProxy (this); + return new ExpressionTreeVariableReference (this); } public void Emit (EmitContext ec) @@ -690,27 +614,35 @@ namespace Mono.CSharp { // When setting top-level hoisted variable in generic storey // change storey generic types to method generic types (VAR -> MVAR) // - cached_outer_access = storey.MemberName.IsGeneric ? - new FieldExpr (field.FieldBuilder, storey.Instance.Type, field.Location) : - new FieldExpr (field.FieldBuilder, field.Location); + if (storey.MemberName.IsGeneric) { + var fs = MemberCache.GetMember (storey.Instance.Type, field.Spec); + cached_outer_access = new FieldExpr (fs, field.Location); + } else { + cached_outer_access = new FieldExpr (field, field.Location); + } cached_outer_access.InstanceExpression = storey.GetStoreyInstanceExpression (ec); - cached_outer_access.Resolve (ec); return cached_outer_access; } FieldExpr inner_access; if (cached_inner_access != null) { - inner_access = (FieldExpr) cached_inner_access [ec.CurrentAnonymousMethod]; + if (!cached_inner_access.TryGetValue (ec.CurrentAnonymousMethod, out inner_access)) + inner_access = null; } else { inner_access = null; - cached_inner_access = new Hashtable (4); + cached_inner_access = new Dictionary (4); } if (inner_access == null) { - inner_access = new FieldExpr (field.FieldBuilder, field.Location); + if (field.Parent.MemberName.IsGeneric) { + var fs = MemberCache.GetMember (field.Parent.CurrentType, field.Spec); + inner_access = new FieldExpr (fs, field.Location); + } else { + inner_access = new FieldExpr (field, field.Location); + } + inner_access.InstanceExpression = storey.GetStoreyInstanceExpression (ec); - inner_access.Resolve (ec); cached_inner_access.Add (ec.CurrentAnonymousMethod, inner_access); } @@ -730,7 +662,7 @@ namespace Mono.CSharp { } } - class HoistedParameter : HoistedVariable + public class HoistedParameter : HoistedVariable { sealed class HoistedFieldAssign : Assign { @@ -739,7 +671,7 @@ namespace Mono.CSharp { { } - protected override Expression ResolveConversions (EmitContext ec) + protected override Expression ResolveConversions (ResolveContext ec) { // // Implicit conversion check fails for hoisted type arguments @@ -768,14 +700,14 @@ namespace Mono.CSharp { // // Remove hoisted redirection to emit assignment from original parameter // - HoistedVariable temp = parameter.Parameter.HoistedVariableReference; - parameter.Parameter.HoistedVariableReference = null; + HoistedVariable temp = parameter.Parameter.HoistedVariant; + parameter.Parameter.HoistedVariant = null; Assign a = new HoistedFieldAssign (GetFieldExpression (ec), parameter); - if (a.Resolve (ec) != null) + if (a.Resolve (new ResolveContext (ec.MemberContext)) != null) a.EmitStatement (ec); - parameter.Parameter.HoistedVariableReference = temp; + parameter.Parameter.HoistedVariant = temp; } public override void EmitSymbolInfo () @@ -813,8 +745,8 @@ namespace Mono.CSharp { public void EmitHoistingAssignment (EmitContext ec) { - SimpleAssign a = new SimpleAssign (GetFieldExpression (ec), ec.GetThis (field.Location)); - if (a.Resolve (ec) != null) + SimpleAssign a = new SimpleAssign (GetFieldExpression (ec), new CompilerGeneratedThis (ec.CurrentType, field.Location)); + if (a.Resolve (new ResolveContext (ec.MemberContext)) != null) a.EmitStatement (ec); } @@ -833,13 +765,42 @@ namespace Mono.CSharp { // public class AnonymousMethodExpression : Expression { - ListDictionary compatibles; + // + // Special conversion for nested expression tree lambdas + // + class Quote : ShimExpression + { + public Quote (Expression expr) + : base (expr) + { + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + var args = new Arguments (1); + args.Add (new Argument (expr.CreateExpressionTree (ec))); + return CreateExpressionFactoryCall (ec, "Quote", args); + } + + protected override Expression DoResolve (ResolveContext rc) + { + expr = expr.Resolve (rc); + if (expr == null) + return null; + + eclass = expr.eclass; + type = expr.Type; + return this; + } + } + + Dictionary compatibles; public ToplevelBlock Block; public AnonymousMethodExpression (Location loc) { this.loc = loc; - this.compatibles = new ListDictionary (); + this.compatibles = new Dictionary (); } public override string ExprClassName { @@ -862,55 +823,55 @@ namespace Mono.CSharp { // Returns true if the body of lambda expression can be implicitly // converted to the delegate of type `delegate_type' // - public bool ImplicitStandardConversionExists (EmitContext ec, Type delegate_type) + public bool ImplicitStandardConversionExists (ResolveContext ec, TypeSpec delegate_type) { - using (ec.With (EmitContext.Flags.InferReturnType, false)) { - using (ec.Set (EmitContext.Flags.ProbingMode)) { + using (ec.With (ResolveContext.Options.InferReturnType, false)) { + using (ec.Set (ResolveContext.Options.ProbingMode)) { return Compatible (ec, delegate_type) != null; } } } - protected Type CompatibleChecks (EmitContext ec, Type delegate_type) + protected TypeSpec CompatibleChecks (ResolveContext ec, TypeSpec delegate_type) { - if (TypeManager.IsDelegateType (delegate_type)) + if (delegate_type.IsDelegate) return delegate_type; - if (TypeManager.DropGenericTypeArguments (delegate_type) == TypeManager.expression_type) { - delegate_type = TypeManager.GetTypeArguments (delegate_type) [0]; - if (TypeManager.IsDelegateType (delegate_type)) + if (delegate_type.IsGeneric && delegate_type.GetDefinition () == TypeManager.expression_type) { + delegate_type = delegate_type.TypeArguments [0]; + if (delegate_type.IsDelegate) return delegate_type; - Report.Error (835, loc, "Cannot convert `{0}' to an expression tree of non-delegate type `{1}'", + ec.Report.Error (835, loc, "Cannot convert `{0}' to an expression tree of non-delegate type `{1}'", GetSignatureForError (), TypeManager.CSharpName (delegate_type)); return null; } - Report.Error (1660, loc, "Cannot convert `{0}' to non-delegate type `{1}'", + ec.Report.Error (1660, loc, "Cannot convert `{0}' to non-delegate type `{1}'", GetSignatureForError (), TypeManager.CSharpName (delegate_type)); return null; } - protected bool VerifyExplicitParameters (Type delegate_type, AParametersCollection parameters, bool ignore_error) + protected bool VerifyExplicitParameters (ResolveContext ec, TypeSpec delegate_type, AParametersCollection parameters) { - if (VerifyParameterCompatibility (delegate_type, parameters, ignore_error)) + if (VerifyParameterCompatibility (ec, delegate_type, parameters, ec.IsInProbingMode)) return true; - if (!ignore_error) - Report.Error (1661, loc, + 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)); return false; } - protected bool VerifyParameterCompatibility (Type delegate_type, AParametersCollection invoke_pd, bool ignore_errors) + protected bool VerifyParameterCompatibility (ResolveContext ec, TypeSpec delegate_type, AParametersCollection invoke_pd, bool ignore_errors) { if (Parameters.Count != invoke_pd.Count) { if (ignore_errors) return false; - Report.Error (1593, loc, "Delegate `{0}' does not take `{1}' arguments", + ec.Report.Error (1593, loc, "Delegate `{0}' does not take `{1}' arguments", TypeManager.CSharpName (delegate_type), Parameters.Count.ToString ()); return false; } @@ -925,10 +886,10 @@ namespace Mono.CSharp { return false; if (p_mod == Parameter.Modifier.NONE) - Report.Error (1677, loc, "Parameter `{0}' should not be declared with the `{1}' keyword", + ec.Report.Error (1677, loc, "Parameter `{0}' should not be declared with the `{1}' keyword", (i + 1).ToString (), Parameter.GetModifierSignature (Parameters.FixedParameters [i].ModFlags)); else - Report.Error (1676, loc, "Parameter `{0}' must be declared with the `{1}' keyword", + ec.Report.Error (1676, loc, "Parameter `{0}' must be declared with the `{1}' keyword", (i+1).ToString (), Parameter.GetModifierSignature (p_mod)); error = true; } @@ -936,7 +897,7 @@ namespace Mono.CSharp { if (has_implicit_parameters) continue; - Type type = invoke_pd.Types [i]; + TypeSpec type = invoke_pd.Types [i]; // We assume that generic parameters are always inflated if (TypeManager.IsGenericParameter (type)) @@ -949,7 +910,7 @@ namespace Mono.CSharp { if (ignore_errors) return false; - Report.Error (1678, loc, "Parameter `{0}' is declared as type `{1}' but should be `{2}'", + ec.Report.Error (1678, loc, "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])); @@ -963,26 +924,26 @@ namespace Mono.CSharp { // // Infers type arguments based on explicit arguments // - public bool ExplicitTypeInference (TypeInferenceContext type_inference, Type delegate_type) + public bool ExplicitTypeInference (ResolveContext ec, TypeInferenceContext type_inference, TypeSpec delegate_type) { if (!HasExplicitParameters) return false; - if (!TypeManager.IsDelegateType (delegate_type)) { - if (TypeManager.DropGenericTypeArguments (delegate_type) != TypeManager.expression_type) + if (!delegate_type.IsDelegate) { + if (delegate_type.GetDefinition () != TypeManager.expression_type) return false; delegate_type = TypeManager.GetTypeArguments (delegate_type) [0]; - if (!TypeManager.IsDelegateType (delegate_type)) + if (!delegate_type.IsDelegate) return false; } - AParametersCollection d_params = TypeManager.GetDelegateParameters (delegate_type); + AParametersCollection d_params = Delegate.GetParameters (ec.Compiler, delegate_type); if (d_params.Count != Parameters.Count) return false; for (int i = 0; i < Parameters.Count; ++i) { - Type itype = d_params.Types [i]; + TypeSpec itype = d_params.Types [i]; if (!TypeManager.IsGenericParameter (itype)) { if (!TypeManager.HasElementType (itype)) continue; @@ -995,20 +956,18 @@ namespace Mono.CSharp { return true; } - public Type InferReturnType (EmitContext ec, TypeInferenceContext tic, Type delegate_type) + public TypeSpec InferReturnType (ResolveContext ec, TypeInferenceContext tic, TypeSpec delegate_type) { - AnonymousMethodBody am; - using (ec.Set (EmitContext.Flags.ProbingMode | EmitContext.Flags.InferReturnType)) { - am = CompatibleMethod (ec, tic, GetType (), delegate_type); + AnonymousExpression am; + using (ec.Set (ResolveContext.Options.ProbingMode | ResolveContext.Options.InferReturnType)) { + am = CompatibleMethodBody (ec, tic, InternalType.Arglist, delegate_type); + if (am != null) + am = am.Compatible (ec); } if (am == null) return null; - // Stop referencing gmcs NullLiteral type - if (am.ReturnType == TypeManager.null_type) - am.ReturnType = null; - return am.ReturnType; } @@ -1016,13 +975,13 @@ namespace Mono.CSharp { // Returns AnonymousMethod container if this anonymous method // expression can be implicitly converted to the delegate type `delegate_type' // - public Expression Compatible (EmitContext ec, Type type) + public Expression Compatible (ResolveContext ec, TypeSpec type) { - Expression am = (Expression) compatibles [type]; - if (am != null) + Expression am; + if (compatibles.TryGetValue (type, out am)) return am; - Type delegate_type = CompatibleChecks (ec, type); + TypeSpec delegate_type = CompatibleChecks (ec, type); if (delegate_type == null) return null; @@ -1031,15 +990,8 @@ namespace Mono.CSharp { // needed for the anonymous method. We create the method here. // - MethodInfo invoke_mb = Delegate.GetInvokeMethod ( - ec.ContainerType, delegate_type); - Type return_type = TypeManager.TypeToCoreType (invoke_mb.ReturnType); - -#if MS_COMPATIBLE - Type[] g_args = delegate_type.GetGenericArguments (); - if (return_type.IsGenericParameter) - return_type = g_args [return_type.GenericParameterPosition]; -#endif + var invoke_mb = Delegate.GetInvokeMethod (ec.Compiler, delegate_type); + TypeSpec return_type = invoke_mb.ReturnType; // // Second: the return type of the delegate must be compatible with @@ -1048,37 +1000,69 @@ namespace Mono.CSharp { // to be the delegate type return type. // - try { - int errors = Report.Errors; - am = CompatibleMethod (ec, null, return_type, delegate_type); - if (am != null && delegate_type != type && errors == Report.Errors) - am = CreateExpressionTree (ec, delegate_type); + var body = CompatibleMethodBody (ec, null, return_type, delegate_type); + if (body == null) + return null; - if (!ec.IsInProbingMode) - compatibles.Add (type, am == null ? EmptyExpression.Null : am); + bool etree_conversion = delegate_type != type; - return am; - } catch (CompletionResult){ + try { + if (etree_conversion) { + if (ec.HasSet (ResolveContext.Options.ExpressionTreeConversion)) { + // + // Nested expression tree lambda use same scope as parent + // lambda, this also means no variable capturing between this + // and parent scope + // + am = body.Compatible (ec, ec.CurrentAnonymousMethod); + + // + // Quote nested expression tree + // + if (am != null) + am = new Quote (am); + } else { + int errors = ec.Report.Errors; + + using (ec.Set (ResolveContext.Options.ExpressionTreeConversion)) { + am = body.Compatible (ec); + } + + // + // Rewrite expressions into expression tree when targeting Expression + // + if (am != null && errors == ec.Report.Errors) + am = CreateExpressionTree (ec, delegate_type); + } + } else { + am = body.Compatible (ec); + } + } catch (CompletionResult) { throw; } catch (Exception e) { throw new InternalErrorException (e, loc); } + + if (!ec.IsInProbingMode) + compatibles.Add (type, am == null ? EmptyExpression.Null : am); + + return am; } - protected virtual Expression CreateExpressionTree (EmitContext ec, Type delegate_type) + protected virtual Expression CreateExpressionTree (ResolveContext ec, TypeSpec delegate_type) { return CreateExpressionTree (ec); } - public override Expression CreateExpressionTree (EmitContext ec) + public override Expression CreateExpressionTree (ResolveContext ec) { - Report.Error (1946, loc, "An anonymous method cannot be converted to an expression tree"); + ec.Report.Error (1946, loc, "An anonymous method cannot be converted to an expression tree"); return null; } - protected virtual ParametersCompiled ResolveParameters (EmitContext ec, TypeInferenceContext tic, Type delegate_type) + protected virtual ParametersCompiled ResolveParameters (ResolveContext ec, TypeInferenceContext tic, TypeSpec delegate_type) { - AParametersCollection delegate_parameters = TypeManager.GetDelegateParameters (delegate_type); + var delegate_parameters = Delegate.GetParameters (ec.Compiler, delegate_type); if (Parameters == ParametersCompiled.Undefined) { // @@ -1089,7 +1073,7 @@ namespace Mono.CSharp { for (int i = 0; i < delegate_parameters.Count; i++) { Parameter.Modifier i_mod = delegate_parameters.FixedParameters [i].ModFlags; if (i_mod == Parameter.Modifier.OUT) { - Report.Error (1688, loc, "Cannot convert anonymous " + + ec.Report.Error (1688, loc, "Cannot convert anonymous " + "method block without a parameter list " + "to delegate type `{0}' because it has " + "one or more `out' parameters.", @@ -1104,17 +1088,17 @@ namespace Mono.CSharp { return ParametersCompiled.CreateFullyResolved (fixedpars, delegate_parameters.Types); } - if (!VerifyExplicitParameters (delegate_type, delegate_parameters, ec.IsInProbingMode)) { + if (!VerifyExplicitParameters (ec, delegate_type, delegate_parameters)) { return null; } return Parameters; } - public override Expression DoResolve (EmitContext ec) + protected override Expression DoResolve (ResolveContext ec) { - if (!ec.IsAnonymousMethodAllowed) { - Report.Error (1706, loc, "Anonymous methods and lambda expressions cannot be used in the current context"); + if (ec.HasSet (ResolveContext.Options.ConstantScope)) { + ec.Report.Error (1706, loc, "Anonymous methods and lambda expressions cannot be used in the current context"); return null; } @@ -1129,16 +1113,16 @@ namespace Mono.CSharp { // anywhere', we depend on special conversion // rules. // - type = TypeManager.anonymous_method_type; + type = InternalType.AnonymousMethod; if ((Parameters != null) && !Parameters.Resolve (ec)) return null; // FIXME: The emitted code isn't very careful about reachability // so, ensure we have a 'ret' at the end - if (ec.CurrentBranching != null && - ec.CurrentBranching.CurrentUsageVector.IsUnreachable) - ec.NeedReturnLabel (); + BlockContext bc = ec as BlockContext; + if (bc != null && bc.CurrentBranching != null && bc.CurrentBranching.CurrentUsageVector.IsUnreachable) + bc.NeedReturnLabel (); return this; } @@ -1148,9 +1132,9 @@ namespace Mono.CSharp { // nothing, as we only exist to not do anything. } - public static void Error_AddressOfCapturedVar (IVariableReference var, Location loc) + public static void Error_AddressOfCapturedVar (ResolveContext ec, IVariableReference var, Location loc) { - Report.Error (1686, loc, + ec.Report.Error (1686, loc, "Local variable or parameter `{0}' cannot have their address taken and be used inside an anonymous method or lambda expression", var.Name); } @@ -1160,7 +1144,7 @@ namespace Mono.CSharp { return ExprClassName; } - protected AnonymousMethodBody CompatibleMethod (EmitContext ec, TypeInferenceContext tic, Type return_type, Type delegate_type) + AnonymousMethodBody CompatibleMethodBody (ResolveContext ec, TypeInferenceContext tic, TypeSpec return_type, TypeSpec delegate_type) { ParametersCompiled p = ResolveParameters (ec, tic, delegate_type); if (p == null) @@ -1168,14 +1152,11 @@ namespace Mono.CSharp { ToplevelBlock b = ec.IsInProbingMode ? (ToplevelBlock) Block.PerformClone () : Block; - AnonymousMethodBody anonymous = CompatibleMethodFactory (return_type, delegate_type, p, b); - if (!anonymous.Compatible (ec)) - return null; + return CompatibleMethodFactory (return_type, delegate_type, p, b); - return anonymous; } - protected virtual AnonymousMethodBody CompatibleMethodFactory (Type return_type, Type delegate_type, ParametersCompiled p, ToplevelBlock b) + protected virtual AnonymousMethodBody CompatibleMethodFactory (TypeSpec return_type, TypeSpec delegate_type, ParametersCompiled p, ToplevelBlock b) { return new AnonymousMethodBody (p, b, return_type, delegate_type, loc); } @@ -1201,7 +1182,7 @@ namespace Mono.CSharp { public AnonymousMethodMethod (DeclSpace parent, AnonymousExpression am, AnonymousMethodStorey storey, GenericMethod generic, TypeExpr return_type, - int mod, string real_name, MemberName name, + Modifiers mod, string real_name, MemberName name, ParametersCompiled parameters) : base (parent, generic, return_type, mod | Modifiers.COMPILER_GENERATED, name, parameters, null) @@ -1214,12 +1195,21 @@ namespace Mono.CSharp { Block = am.Block; } - public override EmitContext CreateEmitContext (DeclSpace tc, ILGenerator ig) + public override EmitContext CreateEmitContext (ILGenerator ig) { - EmitContext aec = AnonymousMethod.aec; - aec.ig = ig; - aec.IsStatic = (ModFlags & Modifiers.STATIC) != 0; - return aec; + EmitContext ec = new EmitContext (this, ig, ReturnType); + ec.CurrentAnonymousMethod = AnonymousMethod; + if (AnonymousMethod.return_label != null) { + ec.HasReturnLabel = true; + ec.ReturnLabel = (Label) AnonymousMethod.return_label; + } + + return ec; + } + + protected override void DefineTypeParameters () + { + // Type parameters were cloned } protected override bool ResolveMemberType () @@ -1227,17 +1217,14 @@ namespace Mono.CSharp { if (!base.ResolveMemberType ()) return false; - if (Storey != null && Storey.IsGeneric) { - AnonymousMethodStorey gstorey = Storey.GetGenericStorey (); - if (gstorey != null) { - if (!Parameters.IsEmpty) { - Type [] ptypes = Parameters.Types; - for (int i = 0; i < ptypes.Length; ++i) - ptypes [i] = gstorey.MutateType (ptypes [i]); - } - - member_type = gstorey.MutateType (member_type); + if (Storey != null && Storey.Mutator != null) { + if (!parameters.IsEmpty) { + var mutated = Storey.Mutator.Mutate (parameters.Types); + if (mutated != parameters.Types) + parameters = ParametersCompiled.CreateFullyResolved ((Parameter[]) parameters.FixedParameters, mutated); } + + member_type = Storey.Mutator.Mutate (member_type); } return true; @@ -1245,18 +1232,6 @@ namespace Mono.CSharp { public override void Emit () { - // - // Before emitting any code we have to change all MVAR references to VAR - // when the method is of generic type and has hoisted variables - // - if (Storey == Parent && Storey.IsGeneric) { - AnonymousMethodStorey gstorey = Storey.GetGenericStorey (); - if (gstorey != null) { - AnonymousMethod.aec.ReturnType = gstorey.MutateType (ReturnType); - block.MutateHoistedGenericType (gstorey); - } - } - if (MethodBuilder == null) { Define (); } @@ -1270,18 +1245,16 @@ namespace Mono.CSharp { } } - // - // The block that makes up the body for the anonymous method - // - protected readonly ToplevelBlock Block; + readonly ToplevelBlock block; - public Type ReturnType; - protected EmitContext aec; + public TypeSpec ReturnType; - protected AnonymousExpression (ToplevelBlock block, Type return_type, Location loc) + object return_label; + + protected AnonymousExpression (ToplevelBlock block, TypeSpec return_type, Location loc) { this.ReturnType = return_type; - this.Block = block; + this.block = block; this.loc = loc; } @@ -1289,46 +1262,58 @@ namespace Mono.CSharp { public abstract bool IsIterator { get; } public abstract AnonymousMethodStorey Storey { get; } - public bool Compatible (EmitContext ec) + public AnonymousExpression Compatible (ResolveContext ec) { - // TODO: Implement clone - aec = new EmitContext ( - ec.ResolveContext, ec.TypeContainer, ec.DeclContainer, - Location, null, ReturnType, - (ec.InUnsafe ? Modifiers.UNSAFE : 0), /* No constructor */ false); + return Compatible (ec, this); + } - aec.CurrentAnonymousMethod = this; - aec.IsStatic = ec.IsStatic; + public AnonymousExpression Compatible (ResolveContext ec, AnonymousExpression ae) + { + // TODO: Implement clone + BlockContext aec = new BlockContext (ec.MemberContext, Block, ReturnType); + aec.CurrentAnonymousMethod = ae; IDisposable aec_dispose = null; - EmitContext.Flags flags = 0; - if (ec.InferReturnType) - flags |= EmitContext.Flags.InferReturnType; + ResolveContext.Options flags = 0; + if (ec.HasSet (ResolveContext.Options.InferReturnType)) { + flags |= ResolveContext.Options.InferReturnType; + aec.ReturnTypeInference = new TypeInferenceContext (); + } if (ec.IsInProbingMode) - flags |= EmitContext.Flags.ProbingMode; + flags |= ResolveContext.Options.ProbingMode; + + if (ec.HasSet (ResolveContext.Options.FieldInitializerScope)) + flags |= ResolveContext.Options.FieldInitializerScope; - if (ec.IsInFieldInitializer) - flags |= EmitContext.Flags.InFieldInitializer; + if (ec.IsUnsafe) + flags |= ResolveContext.Options.UnsafeScope; - if (ec.IsInUnsafeScope) - flags |= EmitContext.Flags.InUnsafe; + if (ec.HasSet (ResolveContext.Options.CheckedScope)) + flags |= ResolveContext.Options.CheckedScope; + + if (ec.HasSet (ResolveContext.Options.ExpressionTreeConversion)) + flags |= ResolveContext.Options.ExpressionTreeConversion; // HACK: Flag with 0 cannot be set if (flags != 0) aec_dispose = aec.Set (flags); - bool unreachable; - bool res = aec.ResolveTopBlock (ec, Block, Block.Parameters, null, out unreachable); + bool res = Block.Resolve (ec.CurrentBranching, aec, Block.Parameters, null); + + if (aec.HasReturnLabel) + return_label = aec.ReturnLabel; - if (ec.InferReturnType) - ReturnType = aec.ReturnType; + if (ec.HasSet (ResolveContext.Options.InferReturnType)) { + aec.ReturnTypeInference.FixAllTypes (ec); + ReturnType = aec.ReturnTypeInference.InferredTypeArguments [0]; + } if (aec_dispose != null) { aec_dispose.Dispose (); } - return res; + return res ? this : null; } public void SetHasThisAccess () @@ -1344,6 +1329,16 @@ namespace Mono.CSharp { b = b.Parent == null ? null : b.Parent.Explicit; } } + + // + // The block that makes up the body for the anonymous method + // + public ToplevelBlock Block { + get { + return block; + } + } + } public class AnonymousMethodBody : AnonymousExpression @@ -1353,11 +1348,12 @@ namespace Mono.CSharp { AnonymousMethodMethod method; Field am_cache; + string block_name; static int unique_id; public AnonymousMethodBody (ParametersCompiled parameters, - ToplevelBlock block, Type return_type, Type delegate_type, + ToplevelBlock block, TypeSpec return_type, TypeSpec delegate_type, Location loc) : base (block, return_type, loc) { @@ -1377,17 +1373,22 @@ namespace Mono.CSharp { get { return false; } } - public override Expression CreateExpressionTree (EmitContext ec) + public override Expression CreateExpressionTree (ResolveContext ec) { - Report.Error (1945, loc, "An expression tree cannot contain an anonymous method expression"); + ec.Report.Error (1945, loc, "An expression tree cannot contain an anonymous method expression"); return null; } - bool Define (EmitContext ec) + bool Define (ResolveContext ec) { - if (aec == null && !Compatible (ec)) + if (!Block.Resolved && Compatible (ec) == null) return false; + if (block_name == null) { + MemberCore mc = (MemberCore) ec.MemberContext; + block_name = mc.MemberName.Basename; + } + return true; } @@ -1404,7 +1405,7 @@ namespace Mono.CSharp { // 3, an instance method in compiler generated storey when any hoisted variable exists // - int modifiers; + Modifiers modifiers; if (Block.HasCapturedVariable || Block.HasCapturedThis) { storey = FindBestMethodStorey (); modifiers = storey != null ? Modifiers.INTERNAL : Modifiers.PRIVATE; @@ -1415,26 +1416,25 @@ namespace Mono.CSharp { modifiers = Modifiers.STATIC | Modifiers.PRIVATE; } - DeclSpace parent = storey != null ? storey : ec.TypeContainer; + TypeContainer parent = storey != null ? storey : ec.CurrentTypeDefinition.Parent.PartialContainer; - MemberCore mc = ec.ResolveContext as MemberCore; - string name = CompilerGeneratedClass.MakeName (parent != storey ? mc.Name : null, + MemberCore mc = ec.MemberContext as MemberCore; + string name = CompilerGeneratedClass.MakeName (parent != storey ? block_name : null, "m", null, unique_id++); MemberName member_name; GenericMethod generic_method; - if (storey == null && mc.MemberName.IsGeneric) { + if (storey == null && mc.MemberName.TypeArguments != null) { member_name = new MemberName (name, mc.MemberName.TypeArguments.Clone (), Location); - generic_method = new GenericMethod (parent.NamespaceEntry, parent, member_name, - new TypeExpression (ReturnType, Location), parameters); - - ArrayList list = new ArrayList (); - foreach (TypeParameter tparam in ((IMethodData)mc).GenericMethod.CurrentTypeParameters) { - if (tparam.Constraints != null) - list.Add (tparam.Constraints.Clone ()); + var hoisted_tparams = ec.CurrentTypeParameters; + var type_params = new TypeParameter[hoisted_tparams.Length]; + for (int i = 0; i < type_params.Length; ++i) { + type_params[i] = hoisted_tparams[i].CreateHoistedCopy (null); } - generic_method.SetParameterInfo (list); + + generic_method = new GenericMethod (parent.NamespaceEntry, parent, member_name, type_params, + new TypeExpression (ReturnType, Location), parameters); } else { member_name = new MemberName (name, Location); generic_method = null; @@ -1449,12 +1449,10 @@ namespace Mono.CSharp { real_name, member_name, parameters); } - public override Expression DoResolve (EmitContext ec) + protected override Expression DoResolve (ResolveContext ec) { - if (eclass == ExprClass.Invalid) { - if (!Define (ec)) - return null; - } + if (!Define (ec)) + return null; eclass = ExprClass.Value; return this; @@ -1510,12 +1508,11 @@ namespace Mono.CSharp { } } - ILGenerator ig = ec.ig; - Label l_initialized = ig.DefineLabel (); + Label l_initialized = ec.DefineLabel (); if (am_cache != null) { - ig.Emit (OpCodes.Ldsfld, am_cache.FieldBuilder); - ig.Emit (OpCodes.Brtrue_S, l_initialized); + ec.Emit (OpCodes.Ldsfld, am_cache.Spec); + ec.Emit (OpCodes.Brtrue_S, l_initialized); } // @@ -1523,49 +1520,41 @@ namespace Mono.CSharp { // if (is_static) { - ig.Emit (OpCodes.Ldnull); + ec.Emit (OpCodes.Ldnull); } else if (storey != null) { - Expression e = storey.GetStoreyInstanceExpression (ec).Resolve (ec); + Expression e = storey.GetStoreyInstanceExpression (ec).Resolve (new ResolveContext (ec.MemberContext)); if (e != null) e.Emit (ec); } else { - ig.Emit (OpCodes.Ldarg_0); + ec.Emit (OpCodes.Ldarg_0); } - MethodInfo delegate_method = method.MethodBuilder; + var delegate_method = method.Spec; if (storey != null && storey.MemberName.IsGeneric) { - Type t = storey.Instance.Type; - + TypeSpec t = storey.Instance.Type; + // // Mutate anonymous method instance type if we are in nested // hoisted generic anonymous method storey // if (ec.CurrentAnonymousMethod != null && ec.CurrentAnonymousMethod.Storey != null && - ec.CurrentAnonymousMethod.Storey.IsGeneric) { - t = storey.GetGenericStorey ().MutateType (t); + ec.CurrentAnonymousMethod.Storey.Mutator != null) { + t = storey.Mutator.Mutate (t); } -#if GMCS_SOURCE - delegate_method = TypeBuilder.GetMethod (t, delegate_method); -#else - throw new NotSupportedException (); -#endif + ec.Emit (OpCodes.Ldftn, TypeBuilder.GetMethod (t.GetMetaInfo (), (MethodInfo) delegate_method.GetMetaInfo ())); + } else { + ec.Emit (OpCodes.Ldftn, delegate_method); } - ig.Emit (OpCodes.Ldftn, delegate_method); - - ConstructorInfo constructor_method = Delegate.GetConstructor (ec.ContainerType, type); -#if MS_COMPATIBLE - if (type.IsGenericType && type is TypeBuilder) - constructor_method = TypeBuilder.GetConstructor (type, constructor_method); -#endif - ig.Emit (OpCodes.Newobj, constructor_method); + var constructor_method = Delegate.GetConstructor (ec.MemberContext.Compiler, ec.CurrentType, type); + ec.Emit (OpCodes.Newobj, constructor_method); if (am_cache != null) { - ig.Emit (OpCodes.Stsfld, am_cache.FieldBuilder); - ig.MarkLabel (l_initialized); - ig.Emit (OpCodes.Ldsfld, am_cache.FieldBuilder); + ec.Emit (OpCodes.Stsfld, am_cache.Spec); + ec.MarkLabel (l_initialized); + ec.Emit (OpCodes.Ldsfld, am_cache.Spec); } } @@ -1591,11 +1580,6 @@ namespace Mono.CSharp { return TypeManager.CSharpName (type); } - public override void MutateHoistedGenericType (AnonymousMethodStorey storey) - { - type = storey.MutateType (type); - } - public static void Reset () { unique_id = 0; @@ -1609,12 +1593,12 @@ namespace Mono.CSharp { { sealed class AnonymousParameters : ParametersCompiled { - public AnonymousParameters (params Parameter[] parameters) - : base (parameters) + public AnonymousParameters (CompilerContext ctx, params Parameter[] parameters) + : base (ctx, parameters) { } - protected override void ErrorDuplicateName (Parameter p) + protected override void ErrorDuplicateName (Parameter p, Report Report) { Report.Error (833, p.Location, "`{0}': An anonymous type cannot have multiple properties with the same name", p.Name); @@ -1625,19 +1609,16 @@ namespace Mono.CSharp { public const string ClassNamePrefix = "<>__AnonType"; public const string SignatureForError = "anonymous type"; - readonly ArrayList parameters; + readonly IList parameters; - private AnonymousTypeClass (DeclSpace parent, MemberName name, ArrayList parameters, Location loc) + private AnonymousTypeClass (DeclSpace parent, MemberName name, IList parameters, Location loc) : base (parent, name, (RootContext.EvalMode ? Modifiers.PUBLIC : 0) | Modifiers.SEALED) { this.parameters = parameters; } - public static AnonymousTypeClass Create (TypeContainer parent, ArrayList parameters, Location loc) + public static AnonymousTypeClass Create (CompilerContext ctx, TypeContainer parent, IList parameters, Location loc) { - if (RootContext.MetadataCompatibilityVersion < MetadataVersion.v2) - Report.FeatureIsNotSupported (loc, "anonymous types"); - string name = ClassNamePrefix + types_counter++; SimpleName [] t_args = new SimpleName [parameters.Count]; @@ -1662,8 +1643,8 @@ namespace Mono.CSharp { a_type.SetParameterInfo (null); Constructor c = new Constructor (a_type, name, Modifiers.PUBLIC | Modifiers.DEBUGGER_HIDDEN, - null, new AnonymousParameters (ctor_params), null, loc); - c.Block = new ToplevelBlock (c.Parameters, loc); + null, new AnonymousParameters (ctx, ctor_params), null, loc); + c.Block = new ToplevelBlock (ctx, c.ParameterInfo, loc); // // Create fields and contructor body with field initialization @@ -1684,7 +1665,7 @@ namespace Mono.CSharp { new SimpleAssign (new MemberAccess (new This (p.Location), f.Name), c.Block.GetParameterReference (p.Name, p.Location)))); - ToplevelBlock get_block = new ToplevelBlock (p.Location); + ToplevelBlock get_block = new ToplevelBlock (ctx, p.Location); get_block.AddStatement (new Return ( new MemberAccess (new This (p.Location), f.Name), p.Location)); Accessor get_accessor = new Accessor (get_block, 0, null, null, p.Location); @@ -1707,7 +1688,7 @@ namespace Mono.CSharp { protected override bool AddToContainer (MemberCore symbol, string name) { - MemberCore mc = (MemberCore) defined_names [name]; + MemberCore mc = GetDefinition (name); if (mc == null) { defined_names.Add (name, symbol); @@ -1718,8 +1699,11 @@ namespace Mono.CSharp { return false; } - void DefineOverrides () + protected override bool DoDefineMembers () { + if (!base.DoDefineMembers ()) + return false; + Location loc = Location; Method equals = new Method (this, null, TypeManager.system_boolean_expr, @@ -1730,12 +1714,17 @@ namespace Mono.CSharp { Modifiers.PUBLIC | Modifiers.OVERRIDE | Modifiers.DEBUGGER_HIDDEN, new MemberName ("ToString", loc), Mono.CSharp.ParametersCompiled.EmptyReadOnlyParameters, null); - ToplevelBlock equals_block = new ToplevelBlock (equals.Parameters, loc); + ToplevelBlock equals_block = new ToplevelBlock (Compiler, equals.ParameterInfo, loc); TypeExpr current_type; - if (IsGeneric) - current_type = new GenericTypeExpr (this, loc); - else - current_type = new TypeExpression (TypeBuilder, loc); + if (type_params != null) { + var targs = new TypeArguments (); + foreach (var type_param in type_params) + targs.Add (new TypeParameterExpr (type_param, type_param.Location)); + + current_type = new GenericTypeExpr (Definition, targs, loc); + } else { + current_type = new TypeExpression (Definition, loc); + } equals_block.AddVariable (current_type, "other", loc); LocalVariableReference other_variable = new LocalVariableReference (equals_block, "other", loc); @@ -1747,33 +1736,33 @@ namespace Mono.CSharp { 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]; - Field f = (Field) Fields [i]; + var p = parameters [i]; + var f = Fields [i]; MemberAccess equality_comparer = new MemberAccess (new MemberAccess ( system_collections_generic, "EqualityComparer", - new TypeArguments (new SimpleName (TypeParameters [i].Name, loc)), loc), + new TypeArguments (new SimpleName (CurrentTypeParameters [i].Name, loc)), loc), "Default", loc); - ArrayList arguments_equal = new ArrayList (2); + Arguments arguments_equal = new Arguments (2); arguments_equal.Add (new Argument (new MemberAccess (new This (f.Location), f.Name))); arguments_equal.Add (new Argument (new MemberAccess (other_variable, f.Name))); Expression field_equal = new Invocation (new MemberAccess (equality_comparer, "Equals", loc), arguments_equal); - ArrayList arguments_hashcode = new ArrayList (1); + Arguments arguments_hashcode = new Arguments (1); arguments_hashcode.Add (new Argument (new MemberAccess (new This (f.Location), f.Name))); Expression field_hashcode = new Invocation (new MemberAccess (equality_comparer, "GetHashCode", loc), arguments_hashcode); IntConstant FNV_prime = new IntConstant (16777619, loc); rs_hashcode = new Binary (Binary.Operator.Multiply, - new Binary (Binary.Operator.ExclusiveOr, rs_hashcode, field_hashcode), - FNV_prime); + new Binary (Binary.Operator.ExclusiveOr, rs_hashcode, field_hashcode, loc), + FNV_prime, loc); - Expression field_to_string = new Conditional (new Binary (Binary.Operator.Inequality, - new MemberAccess (new This (f.Location), f.Name), new NullLiteral (loc)), + Expression field_to_string = new Conditional (new BooleanExpression (new Binary (Binary.Operator.Inequality, + new MemberAccess (new This (f.Location), f.Name), new NullLiteral (loc), loc)), new Invocation (new MemberAccess ( new MemberAccess (new This (f.Location), f.Name), "ToString"), null), new StringConstant (string.Empty, loc)); @@ -1784,7 +1773,9 @@ namespace Mono.CSharp { string_concat, new Binary (Binary.Operator.Addition, new StringConstant (" " + p.Name + " = ", loc), - field_to_string)); + field_to_string, + loc), + loc); continue; } @@ -1794,27 +1785,31 @@ namespace Mono.CSharp { string_concat = new Binary (Binary.Operator.Addition, new Binary (Binary.Operator.Addition, string_concat, - new StringConstant (", " + p.Name + " = ", loc)), - field_to_string); + new StringConstant (", " + p.Name + " = ", loc), + loc), + field_to_string, + loc); - rs_equals = new Binary (Binary.Operator.LogicalAnd, rs_equals, field_equal); + rs_equals = new Binary (Binary.Operator.LogicalAnd, rs_equals, field_equal, loc); } string_concat = new Binary (Binary.Operator.Addition, string_concat, - new StringConstant (" }", loc)); + new StringConstant (" }", loc), + loc); // // Equals (object obj) override - // + // + LocalVariableReference other_variable_assign = new LocalVariableReference (equals_block, "other", loc); equals_block.AddStatement (new StatementExpression ( - new SimpleAssign (other_variable, + new SimpleAssign (other_variable_assign, new As (equals_block.GetParameterReference ("obj", loc), current_type, loc), loc))); - Expression equals_test = new Binary (Binary.Operator.Inequality, other_variable, new NullLiteral (loc)); + Expression equals_test = new Binary (Binary.Operator.Inequality, other_variable, new NullLiteral (loc), loc); if (rs_equals != null) - equals_test = new Binary (Binary.Operator.LogicalAnd, equals_test, rs_equals); + equals_test = new Binary (Binary.Operator.LogicalAnd, equals_test, rs_equals, loc); equals_block.AddStatement (new Return (equals_test, loc)); equals.Block = equals_block; @@ -1843,30 +1838,31 @@ namespace Mono.CSharp { // hash ^= hash >> 17; // hash += hash << 5; - ToplevelBlock hashcode_top = new ToplevelBlock (loc); + ToplevelBlock hashcode_top = new ToplevelBlock (Compiler, 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); + LocalVariableReference hash_variable_assign = new LocalVariableReference (hashcode_block, "hash", loc); hashcode_block.AddStatement (new StatementExpression ( - new SimpleAssign (hash_variable, rs_hashcode))); + new SimpleAssign (hash_variable_assign, rs_hashcode))); hashcode_block.AddStatement (new StatementExpression ( new CompoundAssign (Binary.Operator.Addition, hash_variable, - new Binary (Binary.Operator.LeftShift, hash_variable, new IntConstant (13, loc))))); + new Binary (Binary.Operator.LeftShift, hash_variable, new IntConstant (13, loc), loc)))); hashcode_block.AddStatement (new StatementExpression ( new CompoundAssign (Binary.Operator.ExclusiveOr, hash_variable, - new Binary (Binary.Operator.RightShift, hash_variable, new IntConstant (7, loc))))); + new Binary (Binary.Operator.RightShift, hash_variable, new IntConstant (7, loc), loc)))); hashcode_block.AddStatement (new StatementExpression ( new CompoundAssign (Binary.Operator.Addition, hash_variable, - new Binary (Binary.Operator.LeftShift, hash_variable, new IntConstant (3, loc))))); + new Binary (Binary.Operator.LeftShift, hash_variable, new IntConstant (3, loc), loc)))); hashcode_block.AddStatement (new StatementExpression ( new CompoundAssign (Binary.Operator.ExclusiveOr, hash_variable, - new Binary (Binary.Operator.RightShift, hash_variable, new IntConstant (17, loc))))); + new Binary (Binary.Operator.RightShift, hash_variable, new IntConstant (17, loc), loc)))); hashcode_block.AddStatement (new StatementExpression ( new CompoundAssign (Binary.Operator.Addition, hash_variable, - new Binary (Binary.Operator.LeftShift, hash_variable, new IntConstant (5, loc))))); + new Binary (Binary.Operator.LeftShift, hash_variable, new IntConstant (5, loc), loc)))); hashcode_block.AddStatement (new Return (hash_variable, loc)); hashcode.Block = hashcode_top; @@ -1877,19 +1873,12 @@ namespace Mono.CSharp { // ToString () override // - ToplevelBlock tostring_block = new ToplevelBlock (loc); + ToplevelBlock tostring_block = new ToplevelBlock (Compiler, loc); tostring_block.AddStatement (new Return (string_concat, loc)); tostring.Block = tostring_block; tostring.Define (); AddMethod (tostring); - } - - public override bool Define () - { - if (!base.Define ()) - return false; - DefineOverrides (); return true; } @@ -1898,7 +1887,7 @@ namespace Mono.CSharp { return SignatureForError; } - public ArrayList Parameters { + public IList Parameters { get { return parameters; }