if (TypeManager.IsGenericParameter (VariableType))
return true;
- if (VariableType == TypeManager.void_type) {
- Expression.Error_VoidInvalidInTheContext (Location);
- return false;
- }
-
if (VariableType.IsAbstract && VariableType.IsSealed) {
FieldBase.Error_VariableOfStaticClass (Location, Name, VariableType);
return false;
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 ();
}
/// </remarks>
public class Block : Statement {
public Block Parent;
- public readonly Location StartLocation;
+ public Location StartLocation;
public Location EndLocation = Location.Null;
public ExplicitBlock Explicit;
e = ce.ConvertImplicitly (variable_type);
if (e == null) {
if (TypeManager.IsReferenceType (variable_type))
- Const.Error_ConstantCanBeInitializedWithNullOnly (vi.Location, vi.Name);
+ Const.Error_ConstantCanBeInitializedWithNullOnly (variable_type, vi.Location, vi.Name);
else
ce.Error_ValueCannotBeConverted (ec, vi.Location, variable_type, false);
continue;
// Check possible empty statement (CS0642)
if (Report.WarningLevel >= 3 &&
ix + 1 < statement_count &&
- statements [ix + 1] is Block)
+ statements [ix + 1] is ExplicitBlock)
CheckPossibleMistakenEmptyStatement (s);
//
if (scope_initializers != null) {
SymbolWriter.OpenCompilerGeneratedBlock (ec.ig);
- bool omit_debug_info = ec.OmitDebuggingInfo;
- ec.OmitDebuggingInfo = true;
- foreach (StatementExpression s in scope_initializers)
- s.Emit (ec);
- ec.OmitDebuggingInfo = omit_debug_info;
+ using (ec.Set (EmitContext.Flags.OmitDebuggingInfo)) {
+ foreach (StatementExpression s in scope_initializers)
+ s.Emit (ec);
+ }
SymbolWriter.CloseCompilerGeneratedBlock (ec.ig);
}
am_storey.DefineType ();
am_storey.ResolveType ();
- am_storey.DefineMembers ();
+ am_storey.Define ();
am_storey.Parent.PartialContainer.AddCompilerGeneratedClass (am_storey);
}
converted = new Conditional (new Binary (Binary.Operator.LogicalOr,
new Binary (Binary.Operator.Equality, e, new NullLiteral (loc)),
new Binary (Binary.Operator.Equality, new MemberAccess (e, "Length"), new IntConstant (0, loc))),
- NullPointer.Null,
+ new NullPointer (loc),
converted);
converted = converted.Resolve (ec);
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);
}
}
/// Implementation of the foreach C# statement
/// </summary>
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, loc));
+ 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)
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);
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
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);
{
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];
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);
ig.MarkLabel (loop [i]);
}
- ((IAssignMethod) variable).EmitAssign (ec, conv, false, false);
+ ((IAssignMethod) for_each.variable).EmitAssign (ec, conv, false, false);
statement.Emit (ec);
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]);
}
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;
{
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'
}
}
- 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)