X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fstatement.cs;h=2cea11aa57686bb27b433cef12d852779a5040c4;hb=3fecd568954d5eec99a7ee3e64dd67d4c6617060;hp=8e56fac26138398d2a7faf1621c39a76993c735e;hpb=00ef06acda2bb2c0d45682cab46a4cdc022bb628;p=mono.git diff --git a/mcs/mcs/statement.cs b/mcs/mcs/statement.cs index 8e56fac2613..2cea11aa576 100644 --- a/mcs/mcs/statement.cs +++ b/mcs/mcs/statement.cs @@ -1442,12 +1442,12 @@ namespace Mono.CSharp { throw new InternalErrorException ("Variable is not readonly"); switch (ro_context) { - case ReadOnlyContext.Fixed: - return "fixed variable"; - case ReadOnlyContext.Foreach: - return "foreach iteration variable"; - case ReadOnlyContext.Using: - return "using variable"; + case ReadOnlyContext.Fixed: + return "fixed variable"; + case ReadOnlyContext.Foreach: + return "foreach iteration variable"; + case ReadOnlyContext.Using: + return "using variable"; } throw new NotImplementedException (); } @@ -1507,7 +1507,7 @@ namespace Mono.CSharp { /// public class Block : Statement { public Block Parent; - public readonly Location StartLocation; + public Location StartLocation; public Location EndLocation = Location.Null; public ExplicitBlock Explicit; @@ -2346,6 +2346,11 @@ namespace Mono.CSharp { { MutateVariables (storey); + if (scope_initializers != null) { + foreach (Statement s in scope_initializers) + s.MutateHoistedGenericType (storey); + } + foreach (Statement s in statements) s.MutateHoistedGenericType (storey); } @@ -3653,7 +3658,7 @@ namespace Mono.CSharp { new QualifiedAliasMember (QualifiedAliasMember.GlobalAlias, "System", loc), "Collections", loc), "Generic", loc); string_dictionary_type = new MemberAccess (system_collections_generic, "Dictionary", - new TypeArguments (loc, + new TypeArguments ( new TypeExpression (TypeManager.string_type, loc), new TypeExpression (TypeManager.int32_type, loc)), loc); #else @@ -3664,7 +3669,7 @@ namespace Mono.CSharp { #endif Field field = new Field (ec.TypeContainer, string_dictionary_type, Modifiers.STATIC | Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED, - CompilerGeneratedClass.MakeName (null, "f", "switch$map", unique_counter++), null, loc); + new MemberName (CompilerGeneratedClass.MakeName (null, "f", "switch$map", unique_counter++), loc), null); if (!field.Define ()) return; ec.TypeContainer.PartialContainer.AddField (field); @@ -4448,7 +4453,7 @@ namespace Mono.CSharp { Unary u = e as Unary; if (u != null && u.Oper == Unary.Operator.AddressOf) { IVariableReference vr = u.Expr as IVariableReference; - if (vr == null || !vr.IsFixedVariable) { + if (vr == null || !vr.IsFixed) { data [i] = new ExpressionEmitter (e, vi); } } @@ -5086,108 +5091,56 @@ namespace Mono.CSharp { /// Implementation of the foreach C# statement /// public class Foreach : Statement { - Expression type; - Expression variable; - Expression expr; - Statement statement; - - public Foreach (Expression type, LocalVariableReference var, Expression expr, - Statement stmt, Location l) - { - this.type = type; - this.variable = var; - this.expr = expr; - statement = stmt; - loc = l; - } - - public Statement Statement { - get { return statement; } - } - - public override bool Resolve (EmitContext ec) - { - expr = expr.Resolve (ec); - if (expr == null) - return false; - - if (expr.IsNull) { - Report.Error (186, loc, "Use of null is not valid in this context"); - return false; - } - - if (expr.eclass == ExprClass.MethodGroup || expr is AnonymousMethodExpression) { - Report.Error (446, expr.Location, "Foreach statement cannot operate on a `{0}'", - expr.ExprClassName); - return false; - } - - if (expr.Type.IsArray) { - statement = new ArrayForeach (type, variable, expr, statement, loc); - } else { - statement = new CollectionForeach (type, variable, expr, statement, loc); - } - - return statement.Resolve (ec); - } - protected override void DoEmit (EmitContext ec) + sealed class ArrayForeach : Statement { - ILGenerator ig = ec.ig; - - Label old_begin = ec.LoopBegin, old_end = ec.LoopEnd; - ec.LoopBegin = ig.DefineLabel (); - ec.LoopEnd = ig.DefineLabel (); - - statement.Emit (ec); - - ec.LoopBegin = old_begin; - ec.LoopEnd = old_end; - } + class ArrayCounter : TemporaryVariable + { + StatementExpression increment; - protected class ArrayCounter : TemporaryVariable - { - StatementExpression increment; + public ArrayCounter (Location loc) + : base (TypeManager.int32_type, loc) + { + } - public ArrayCounter (Location loc) - : base (TypeManager.int32_type, loc) - { - } + public void ResolveIncrement (EmitContext ec) + { + increment = new StatementExpression (new UnaryMutator (UnaryMutator.Mode.PostIncrement, this)); + increment.Resolve (ec); + } - public void ResolveIncrement (EmitContext ec) - { - increment = new StatementExpression (new UnaryMutator (UnaryMutator.Mode.PostIncrement, this, loc)); - increment.Resolve (ec); + public void EmitIncrement (EmitContext ec) + { + increment.Emit (ec); + } } - public void EmitIncrement (EmitContext ec) - { - increment.Emit (ec); - } - } + readonly Foreach for_each; + readonly Statement statement; - protected class ArrayForeach : Statement - { - Expression variable, expr, conv; - Statement statement; - Type array_type; - Expression var_type; + Expression conv; TemporaryVariable[] lengths; + Expression [] length_exprs; ArrayCounter[] counter; - int rank; TemporaryVariable copy; Expression access; - Expression[] length_exprs; - public ArrayForeach (Expression var_type, Expression var, - Expression expr, Statement stmt, Location l) + public ArrayForeach (Foreach @foreach, int rank) { - this.var_type = var_type; - this.variable = var; - this.expr = expr; - statement = stmt; - loc = l; + for_each = @foreach; + statement = for_each.statement; + loc = @foreach.loc; + + counter = new ArrayCounter [rank]; + length_exprs = new Expression [rank]; + + // + // Only use temporary length variables when dealing with + // multi-dimensional arrays + // + if (rank > 1) + lengths = new TemporaryVariable [rank]; } protected override void CloneTo (CloneContext clonectx, Statement target) @@ -5197,27 +5150,21 @@ namespace Mono.CSharp { public override bool Resolve (EmitContext ec) { - array_type = expr.Type; - rank = array_type.GetArrayRank (); - - copy = new TemporaryVariable (array_type, loc); + copy = new TemporaryVariable (for_each.expr.Type, loc); copy.Resolve (ec); - counter = new ArrayCounter [rank]; - lengths = new TemporaryVariable [rank]; - length_exprs = new Expression [rank]; - + int rank = length_exprs.Length; ArrayList list = new ArrayList (rank); for (int i = 0; i < rank; i++) { counter [i] = new ArrayCounter (loc); counter [i].ResolveIncrement (ec); - lengths [i] = new TemporaryVariable (TypeManager.int32_type, loc); - lengths [i].Resolve (ec); - if (rank == 1) { length_exprs [i] = new MemberAccess (copy, "Length").Resolve (ec); } else { + lengths [i] = new TemporaryVariable (TypeManager.int32_type, loc); + lengths [i].Resolve (ec); + ArrayList args = new ArrayList (1); args.Add (new Argument (new IntConstant (i, loc))); length_exprs [i] = new Invocation (new MemberAccess (copy, "GetLength"), args).Resolve (ec); @@ -5230,6 +5177,7 @@ namespace Mono.CSharp { if (access == null) return false; + Expression var_type = for_each.type; VarExpr ve = var_type as VarExpr; if (ve != null) { // Infer implicitly typed local variable from foreach array type @@ -5249,8 +5197,8 @@ namespace Mono.CSharp { ec.StartFlowBranching (FlowBranching.BranchingType.Loop, loc); ec.CurrentBranching.CreateSibling (); - variable = variable.ResolveLValue (ec, conv, loc); - if (variable == null) + for_each.variable = for_each.variable.ResolveLValue (ec, conv, loc); + if (for_each.variable == null) ok = false; ec.StartFlowBranching (FlowBranching.BranchingType.Embedded, loc); @@ -5270,8 +5218,9 @@ namespace Mono.CSharp { { ILGenerator ig = ec.ig; - copy.EmitAssign (ec, expr); + copy.EmitAssign (ec, for_each.expr); + int rank = length_exprs.Length; Label[] test = new Label [rank]; Label[] loop = new Label [rank]; @@ -5279,7 +5228,8 @@ namespace Mono.CSharp { test [i] = ig.DefineLabel (); loop [i] = ig.DefineLabel (); - lengths [i].EmitAssign (ec, length_exprs [i]); + if (lengths != null) + lengths [i].EmitAssign (ec, length_exprs [i]); } IntConstant zero = new IntConstant (0, loc); @@ -5290,7 +5240,7 @@ namespace Mono.CSharp { ig.MarkLabel (loop [i]); } - ((IAssignMethod) variable).EmitAssign (ec, conv, false, false); + ((IAssignMethod) for_each.variable).EmitAssign (ec, conv, false, false); statement.Emit (ec); @@ -5301,7 +5251,12 @@ namespace Mono.CSharp { ig.MarkLabel (test [i]); counter [i].Emit (ec); - lengths [i].Emit (ec); + + if (lengths != null) + lengths [i].Emit (ec); + else + length_exprs [i].Emit (ec); + ig.Emit (OpCodes.Blt, loop [i]); } @@ -5310,20 +5265,78 @@ namespace Mono.CSharp { public override void MutateHoistedGenericType (AnonymousMethodStorey storey) { + for_each.expr.MutateHoistedGenericType (storey); + copy.MutateHoistedGenericType (storey); conv.MutateHoistedGenericType (storey); - variable.MutateHoistedGenericType (storey); statement.MutateHoistedGenericType (storey); - for (int i = 0; i < rank; i++) { + for (int i = 0; i < counter.Length; i++) { counter [i].MutateHoistedGenericType (storey); - lengths [i].MutateHoistedGenericType (storey); + if (lengths != null) + lengths [i].MutateHoistedGenericType (storey); } } } - protected class CollectionForeach : Statement + sealed class CollectionForeach : Statement { + class CollectionForeachStatement : Statement + { + Type type; + Expression variable, current, conv; + Statement statement; + Assign assign; + + public CollectionForeachStatement (Type type, Expression variable, + Expression current, Statement statement, + Location loc) + { + this.type = type; + this.variable = variable; + this.current = current; + this.statement = statement; + this.loc = loc; + } + + protected override void CloneTo (CloneContext clonectx, Statement target) + { + throw new NotImplementedException (); + } + + public override bool Resolve (EmitContext ec) + { + current = current.Resolve (ec); + if (current == null) + return false; + + conv = Convert.ExplicitConversion (ec, current, type, loc); + if (conv == null) + return false; + + assign = new SimpleAssign (variable, conv, loc); + if (assign.Resolve (ec) == null) + return false; + + if (!statement.Resolve (ec)) + return false; + + return true; + } + + protected override void DoEmit (EmitContext ec) + { + assign.EmitStatement (ec); + statement.Emit (ec); + } + + public override void MutateHoistedGenericType (AnonymousMethodStorey storey) + { + assign.MutateHoistedGenericType (storey); + statement.MutateHoistedGenericType (storey); + } + } + Expression variable, expr; Statement statement; @@ -5358,15 +5371,6 @@ namespace Mono.CSharp { { Type return_type = mi.ReturnType; - if ((return_type == TypeManager.ienumerator_type) && (mi.DeclaringType == TypeManager.string_type)) - // - // Apply the same optimization as MS: skip the GetEnumerator - // returning an IEnumerator, and use the one returning a - // CharEnumerator instead. This allows us to avoid the - // try-finally block and the boxing. - // - return false; - // // Ok, we can access it, now make sure that we can do something // with this `GetEnumerator' @@ -5836,60 +5840,65 @@ namespace Mono.CSharp { } } - protected class CollectionForeachStatement : Statement + Expression type; + Expression variable; + Expression expr; + Statement statement; + + public Foreach (Expression type, LocalVariableReference var, Expression expr, + Statement stmt, Location l) { - Type type; - Expression variable, current, conv; - Statement statement; - Assign assign; + this.type = type; + this.variable = var; + this.expr = expr; + statement = stmt; + loc = l; + } - public CollectionForeachStatement (Type type, Expression variable, - Expression current, Statement statement, - Location loc) - { - this.type = type; - this.variable = variable; - this.current = current; - this.statement = statement; - this.loc = loc; - } + public Statement Statement { + get { return statement; } + } - protected override void CloneTo (CloneContext clonectx, Statement target) - { - throw new NotImplementedException (); + public override bool Resolve (EmitContext ec) + { + expr = expr.Resolve (ec); + if (expr == null) + return false; + + if (expr.IsNull) { + Report.Error (186, loc, "Use of null is not valid in this context"); + return false; } - public override bool Resolve (EmitContext ec) - { - current = current.Resolve (ec); - if (current == null) + if (expr.Type == TypeManager.string_type) { + statement = new ArrayForeach (this, 1); + } else if (expr.Type.IsArray) { + statement = new ArrayForeach (this, expr.Type.GetArrayRank ()); + } else { + if (expr.eclass == ExprClass.MethodGroup || expr is AnonymousMethodExpression) { + Report.Error (446, expr.Location, "Foreach statement cannot operate on a `{0}'", + expr.ExprClassName); return false; + } - conv = Convert.ExplicitConversion (ec, current, type, loc); - if (conv == null) - return false; + statement = new CollectionForeach (type, variable, expr, statement, loc); + } - assign = new SimpleAssign (variable, conv, loc); - if (assign.Resolve (ec) == null) - return false; + return statement.Resolve (ec); + } - if (!statement.Resolve (ec)) - return false; + protected override void DoEmit (EmitContext ec) + { + ILGenerator ig = ec.ig; - return true; - } + Label old_begin = ec.LoopBegin, old_end = ec.LoopEnd; + ec.LoopBegin = ig.DefineLabel (); + ec.LoopEnd = ig.DefineLabel (); - protected override void DoEmit (EmitContext ec) - { - assign.EmitStatement (ec); - statement.Emit (ec); - } + statement.Emit (ec); - public override void MutateHoistedGenericType (AnonymousMethodStorey storey) - { - assign.MutateHoistedGenericType (storey); - statement.MutateHoistedGenericType (storey); - } + ec.LoopBegin = old_begin; + ec.LoopEnd = old_end; } protected override void CloneTo (CloneContext clonectx, Statement t)