X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fstatement.cs;h=51a975d549f59797a6eeff5bfbe67ab96fdd1cc1;hb=21dd2b0200d091c43fce9e1941e8ab5e111f3651;hp=45454aa06ff0041c1c69dbd098ac4b0cf04325dd;hpb=50d3a6417b66b26d0923f868f83be54ed60c08fa;p=mono.git
diff --git a/mcs/mcs/statement.cs b/mcs/mcs/statement.cs
index 45454aa06ff..51a975d549f 100644
--- a/mcs/mcs/statement.cs
+++ b/mcs/mcs/statement.cs
@@ -15,8 +15,7 @@ using System.Text;
using System.Reflection;
using System.Reflection.Emit;
using System.Diagnostics;
-using System.Collections;
-using System.Collections.Specialized;
+using System.Collections.Generic;
namespace Mono.CSharp {
@@ -27,7 +26,7 @@ namespace Mono.CSharp {
/// Resolves the statement, true means that all sub-statements
/// did resolve ok.
//
- public virtual bool Resolve (EmitContext ec)
+ public virtual bool Resolve (BlockContext ec)
{
return true;
}
@@ -36,7 +35,7 @@ namespace Mono.CSharp {
/// We already know that the statement is unreachable, but we still
/// need to resolve it to catch errors.
///
- public virtual bool ResolveUnreachable (EmitContext ec, bool warn)
+ public virtual bool ResolveUnreachable (BlockContext ec, bool warn)
{
//
// This conflicts with csc's way of doing this, but IMHO it's
@@ -48,7 +47,7 @@ namespace Mono.CSharp {
//
if (warn)
- Report.Warning (162, 2, loc, "Unreachable code detected");
+ ec.Report.Warning (162, 2, loc, "Unreachable code detected");
ec.StartFlowBranching (FlowBranching.BranchingType.Block, loc);
bool ok = Resolve (ec);
@@ -62,25 +61,6 @@ namespace Mono.CSharp {
///
protected abstract void DoEmit (EmitContext ec);
- ///
- /// Utility wrapper routine for Error, just to beautify the code
- ///
- public void Error (int error, string format, params object[] args)
- {
- Error (error, String.Format (format, args));
- }
-
- public void Error (int error, string s)
- {
- if (!loc.IsNull)
- Report.Error (error, loc, s);
- else
- Report.Error (error, s);
- }
-
- ///
- /// Return value indicates whether all code paths emitted return.
- ///
public virtual void Emit (EmitContext ec)
{
ec.Mark (loc);
@@ -100,9 +80,9 @@ namespace Mono.CSharp {
return s;
}
- public virtual Expression CreateExpressionTree (EmitContext ec)
+ public virtual Expression CreateExpressionTree (ResolveContext ec)
{
- Report.Error (834, loc, "A lambda expression with statement body cannot be converted to an expresion tree");
+ ec.Report.Error (834, loc, "A lambda expression with statement body cannot be converted to an expresion tree");
return null;
}
@@ -112,96 +92,32 @@ namespace Mono.CSharp {
return Clone (clonectx);
}
-
- public abstract void MutateHoistedGenericType (AnonymousMethodStorey storey);
}
- //
- // This class is used during the Statement.Clone operation
- // to remap objects that have been cloned.
- //
- // Since blocks are cloned by Block.Clone, we need a way for
- // expressions that must reference the block to be cloned
- // pointing to the new cloned block.
- //
- public class CloneContext {
- Hashtable block_map = new Hashtable ();
- Hashtable variable_map;
-
- public void AddBlockMap (Block from, Block to)
- {
- if (block_map.Contains (from))
- return;
- block_map [from] = to;
- }
-
- public Block LookupBlock (Block from)
- {
- Block result = (Block) block_map [from];
-
- if (result == null){
- result = (Block) from.Clone (this);
- block_map [from] = result;
- }
-
- return result;
- }
-
- ///
- /// Remaps block to cloned copy if one exists.
- ///
- public Block RemapBlockCopy (Block from)
- {
- Block mapped_to = (Block)block_map[from];
- if (mapped_to == null)
- return from;
-
- return mapped_to;
- }
-
- public void AddVariableMap (LocalInfo from, LocalInfo to)
- {
- if (variable_map == null)
- variable_map = new Hashtable ();
-
- if (variable_map.Contains (from))
- return;
- variable_map [from] = to;
- }
-
- public LocalInfo LookupVariable (LocalInfo from)
+ public sealed class EmptyStatement : Statement
+ {
+ public EmptyStatement (Location loc)
{
- LocalInfo result = (LocalInfo) variable_map [from];
-
- if (result == null)
- throw new Exception ("LookupVariable: looking up a variable that has not been registered yet");
-
- return result;
+ this.loc = loc;
}
- }
-
- public sealed class EmptyStatement : Statement {
-
- private EmptyStatement () {}
- public static readonly EmptyStatement Value = new EmptyStatement ();
-
- public override bool Resolve (EmitContext ec)
+ public override bool Resolve (BlockContext ec)
{
return true;
}
- public override bool ResolveUnreachable (EmitContext ec, bool warn)
+ public override bool ResolveUnreachable (BlockContext ec, bool warn)
{
return true;
}
- protected override void DoEmit (EmitContext ec)
+ public override void Emit (EmitContext ec)
{
}
- public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+ protected override void DoEmit (EmitContext ec)
{
+ throw new NotSupportedException ();
}
protected override void CloneTo (CloneContext clonectx, Statement target)
@@ -216,77 +132,61 @@ namespace Mono.CSharp {
public Statement FalseStatement;
bool is_true_ret;
-
- public If (Expression expr, Statement true_statement, Location l)
+
+ public If (Expression bool_expr, Statement true_statement, Location l)
+ : this (bool_expr, true_statement, null, l)
{
- this.expr = expr;
- TrueStatement = true_statement;
- loc = l;
}
- public If (Expression expr,
+ public If (Expression bool_expr,
Statement true_statement,
Statement false_statement,
Location l)
{
- this.expr = expr;
+ this.expr = bool_expr;
TrueStatement = true_statement;
FalseStatement = false_statement;
loc = l;
}
- public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
- {
- expr.MutateHoistedGenericType (storey);
- TrueStatement.MutateHoistedGenericType (storey);
- if (FalseStatement != null)
- FalseStatement.MutateHoistedGenericType (storey);
- }
-
- public override bool Resolve (EmitContext ec)
+ public override bool Resolve (BlockContext ec)
{
bool ok = true;
Report.Debug (1, "START IF BLOCK", loc);
- expr = Expression.ResolveBoolean (ec, expr, loc);
- if (expr == null){
+ expr = expr.Resolve (ec);
+ if (expr == null) {
ok = false;
- goto skip;
- }
-
- Assign ass = expr as Assign;
- if (ass != null && ass.Source is Constant) {
- Report.Warning (665, 3, loc, "Assignment in conditional expression is always constant; did you mean to use == instead of = ?");
- }
+ } else {
+ //
+ // Dead code elimination
+ //
+ if (expr is Constant) {
+ bool take = !((Constant) expr).IsDefaultValue;
- //
- // Dead code elimination
- //
- if (expr is Constant){
- bool take = !((Constant) expr).IsDefaultValue;
+ if (take) {
+ if (!TrueStatement.Resolve (ec))
+ return false;
- if (take){
- if (!TrueStatement.Resolve (ec))
- return false;
+ if ((FalseStatement != null) &&
+ !FalseStatement.ResolveUnreachable (ec, true))
+ return false;
+ FalseStatement = null;
+ } else {
+ if (!TrueStatement.ResolveUnreachable (ec, true))
+ return false;
+ TrueStatement = null;
- if ((FalseStatement != null) &&
- !FalseStatement.ResolveUnreachable (ec, true))
- return false;
- FalseStatement = null;
- } else {
- if (!TrueStatement.ResolveUnreachable (ec, true))
- return false;
- TrueStatement = null;
+ if ((FalseStatement != null) &&
+ !FalseStatement.Resolve (ec))
+ return false;
+ }
- if ((FalseStatement != null) &&
- !FalseStatement.Resolve (ec))
- return false;
+ return true;
}
-
- return true;
}
- skip:
+
ec.StartFlowBranching (FlowBranching.BranchingType.Conditional, loc);
ok &= TrueStatement.Resolve (ec);
@@ -307,8 +207,7 @@ namespace Mono.CSharp {
protected override void DoEmit (EmitContext ec)
{
- ILGenerator ig = ec.ig;
- Label false_target = ig.DefineLabel ();
+ Label false_target = ec.DefineLabel ();
Label end;
//
@@ -334,19 +233,19 @@ namespace Mono.CSharp {
if (FalseStatement != null){
bool branch_emitted = false;
- end = ig.DefineLabel ();
+ end = ec.DefineLabel ();
if (!is_true_ret){
- ig.Emit (OpCodes.Br, end);
+ ec.Emit (OpCodes.Br, end);
branch_emitted = true;
}
- ig.MarkLabel (false_target);
+ ec.MarkLabel (false_target);
FalseStatement.Emit (ec);
if (branch_emitted)
- ig.MarkLabel (end);
+ ec.MarkLabel (end);
} else {
- ig.MarkLabel (false_target);
+ ec.MarkLabel (false_target);
}
}
@@ -364,15 +263,15 @@ namespace Mono.CSharp {
public class Do : Statement {
public Expression expr;
public Statement EmbeddedStatement;
-
- public Do (Statement statement, Expression bool_expr, Location l)
+
+ public Do (Statement statement, BooleanExpression bool_expr, Location l)
{
expr = bool_expr;
EmbeddedStatement = statement;
loc = l;
}
- public override bool Resolve (EmitContext ec)
+ public override bool Resolve (BlockContext ec)
{
bool ok = true;
@@ -386,9 +285,9 @@ namespace Mono.CSharp {
ec.EndFlowBranching ();
if (ec.CurrentBranching.CurrentUsageVector.IsUnreachable && !was_unreachable)
- Report.Warning (162, 2, expr.Location, "Unreachable code detected");
+ ec.Report.Warning (162, 2, expr.Location, "Unreachable code detected");
- expr = Expression.ResolveBoolean (ec, expr, loc);
+ expr = expr.Resolve (ec);
if (expr == null)
ok = false;
else if (expr is Constant){
@@ -404,17 +303,16 @@ namespace Mono.CSharp {
protected override void DoEmit (EmitContext ec)
{
- ILGenerator ig = ec.ig;
- Label loop = ig.DefineLabel ();
+ Label loop = ec.DefineLabel ();
Label old_begin = ec.LoopBegin;
Label old_end = ec.LoopEnd;
- ec.LoopBegin = ig.DefineLabel ();
- ec.LoopEnd = ig.DefineLabel ();
+ ec.LoopBegin = ec.DefineLabel ();
+ ec.LoopEnd = ec.DefineLabel ();
- ig.MarkLabel (loop);
+ ec.MarkLabel (loop);
EmbeddedStatement.Emit (ec);
- ig.MarkLabel (ec.LoopBegin);
+ ec.MarkLabel (ec.LoopBegin);
//
// Dead code elimination
@@ -424,22 +322,16 @@ namespace Mono.CSharp {
expr.EmitSideEffect (ec);
if (res)
- ec.ig.Emit (OpCodes.Br, loop);
+ ec.Emit (OpCodes.Br, loop);
} else
expr.EmitBranchable (ec, loop, true);
- ig.MarkLabel (ec.LoopEnd);
+ ec.MarkLabel (ec.LoopEnd);
ec.LoopBegin = old_begin;
ec.LoopEnd = old_end;
}
- public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
- {
- expr.MutateHoistedGenericType (storey);
- EmbeddedStatement.MutateHoistedGenericType (storey);
- }
-
protected override void CloneTo (CloneContext clonectx, Statement t)
{
Do target = (Do) t;
@@ -453,21 +345,21 @@ namespace Mono.CSharp {
public Expression expr;
public Statement Statement;
bool infinite, empty;
-
- public While (Expression bool_expr, Statement statement, Location l)
+
+ public While (BooleanExpression bool_expr, Statement statement, Location l)
{
this.expr = bool_expr;
Statement = statement;
loc = l;
}
- public override bool Resolve (EmitContext ec)
+ public override bool Resolve (BlockContext ec)
{
bool ok = true;
- expr = Expression.ResolveBoolean (ec, expr, loc);
+ expr = expr.Resolve (ec);
if (expr == null)
- return false;
+ ok = false;
//
// Inform whether we are infinite or not
@@ -508,42 +400,41 @@ namespace Mono.CSharp {
return;
}
- ILGenerator ig = ec.ig;
Label old_begin = ec.LoopBegin;
Label old_end = ec.LoopEnd;
- ec.LoopBegin = ig.DefineLabel ();
- ec.LoopEnd = ig.DefineLabel ();
+ ec.LoopBegin = ec.DefineLabel ();
+ ec.LoopEnd = ec.DefineLabel ();
//
// Inform whether we are infinite or not
//
if (expr is Constant){
// expr is 'true', since the 'empty' case above handles the 'false' case
- ig.MarkLabel (ec.LoopBegin);
+ ec.MarkLabel (ec.LoopBegin);
expr.EmitSideEffect (ec);
Statement.Emit (ec);
- ig.Emit (OpCodes.Br, ec.LoopBegin);
+ ec.Emit (OpCodes.Br, ec.LoopBegin);
//
// Inform that we are infinite (ie, `we return'), only
// if we do not `break' inside the code.
//
- ig.MarkLabel (ec.LoopEnd);
+ ec.MarkLabel (ec.LoopEnd);
} else {
- Label while_loop = ig.DefineLabel ();
+ Label while_loop = ec.DefineLabel ();
- ig.Emit (OpCodes.Br, ec.LoopBegin);
- ig.MarkLabel (while_loop);
+ ec.Emit (OpCodes.Br, ec.LoopBegin);
+ ec.MarkLabel (while_loop);
Statement.Emit (ec);
- ig.MarkLabel (ec.LoopBegin);
+ ec.MarkLabel (ec.LoopBegin);
ec.Mark (loc);
expr.EmitBranchable (ec, while_loop, true);
- ig.MarkLabel (ec.LoopEnd);
+ ec.MarkLabel (ec.LoopEnd);
}
ec.LoopBegin = old_begin;
@@ -562,12 +453,6 @@ namespace Mono.CSharp {
target.expr = expr.Clone (clonectx);
target.Statement = Statement.Clone (clonectx);
}
-
- public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
- {
- expr.MutateHoistedGenericType (storey);
- Statement.MutateHoistedGenericType (storey);
- }
}
public class For : Statement {
@@ -578,7 +463,7 @@ namespace Mono.CSharp {
bool infinite, empty;
public For (Statement init_statement,
- Expression test,
+ BooleanExpression test,
Statement increment,
Statement statement,
Location l)
@@ -590,7 +475,7 @@ namespace Mono.CSharp {
loc = l;
}
- public override bool Resolve (EmitContext ec)
+ public override bool Resolve (BlockContext ec)
{
bool ok = true;
@@ -600,7 +485,7 @@ namespace Mono.CSharp {
}
if (Test != null){
- Test = Expression.ResolveBoolean (ec, Test, loc);
+ Test = Test.Resolve (ec);
if (Test == null)
ok = false;
else if (Test is Constant){
@@ -651,7 +536,7 @@ namespace Mono.CSharp {
protected override void DoEmit (EmitContext ec)
{
- if (InitStatement != null && InitStatement != EmptyStatement.Value)
+ if (InitStatement != null)
InitStatement.Emit (ec);
if (empty) {
@@ -659,24 +544,22 @@ namespace Mono.CSharp {
return;
}
- ILGenerator ig = ec.ig;
Label old_begin = ec.LoopBegin;
Label old_end = ec.LoopEnd;
- Label loop = ig.DefineLabel ();
- Label test = ig.DefineLabel ();
+ Label loop = ec.DefineLabel ();
+ Label test = ec.DefineLabel ();
- ec.LoopBegin = ig.DefineLabel ();
- ec.LoopEnd = ig.DefineLabel ();
+ ec.LoopBegin = ec.DefineLabel ();
+ ec.LoopEnd = ec.DefineLabel ();
- ig.Emit (OpCodes.Br, test);
- ig.MarkLabel (loop);
+ ec.Emit (OpCodes.Br, test);
+ ec.MarkLabel (loop);
Statement.Emit (ec);
- ig.MarkLabel (ec.LoopBegin);
- if (Increment != EmptyStatement.Value)
- Increment.Emit (ec);
+ ec.MarkLabel (ec.LoopBegin);
+ Increment.Emit (ec);
- ig.MarkLabel (test);
+ ec.MarkLabel (test);
//
// If test is null, there is no test, and we are just
// an infinite loop
@@ -689,31 +572,19 @@ namespace Mono.CSharp {
//
if (Test is Constant) {
Test.EmitSideEffect (ec);
- ig.Emit (OpCodes.Br, loop);
+ ec.Emit (OpCodes.Br, loop);
} else {
Test.EmitBranchable (ec, loop, true);
}
} else
- ig.Emit (OpCodes.Br, loop);
- ig.MarkLabel (ec.LoopEnd);
+ ec.Emit (OpCodes.Br, loop);
+ ec.MarkLabel (ec.LoopEnd);
ec.LoopBegin = old_begin;
ec.LoopEnd = old_end;
}
- public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
- {
- if (InitStatement != null)
- InitStatement.MutateHoistedGenericType (storey);
- if (Test != null)
- Test.MutateHoistedGenericType (storey);
- if (Increment != null)
- Increment.MutateHoistedGenericType (storey);
-
- Statement.MutateHoistedGenericType (storey);
- }
-
protected override void CloneTo (CloneContext clonectx, Statement t)
{
For target = (For) t;
@@ -737,10 +608,9 @@ namespace Mono.CSharp {
loc = expr.Location;
}
- public override bool Resolve (EmitContext ec)
+ public override bool Resolve (BlockContext ec)
{
- if (expr != null)
- expr = expr.ResolveStatement (ec);
+ expr = expr.ResolveStatement (ec);
return expr != null;
}
@@ -749,11 +619,6 @@ namespace Mono.CSharp {
expr.EmitStatement (ec);
}
- public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
- {
- expr.MutateHoistedGenericType (storey);
- }
-
public override string ToString ()
{
return "StatementExpression (" + expr + ")";
@@ -767,18 +632,67 @@ namespace Mono.CSharp {
}
}
+ //
+ // Simple version of statement list not requiring a block
+ //
+ public class StatementList : Statement
+ {
+ List statements;
+
+ public StatementList (Statement first, Statement second)
+ {
+ statements = new List () { first, second };
+ }
+
+ #region Properties
+ public IList Statements {
+ get {
+ return statements;
+ }
+ }
+ #endregion
+
+ public void Add (Statement statement)
+ {
+ statements.Add (statement);
+ }
+
+ public override bool Resolve (BlockContext ec)
+ {
+ foreach (var s in statements)
+ s.Resolve (ec);
+
+ return true;
+ }
+
+ protected override void DoEmit (EmitContext ec)
+ {
+ foreach (var s in statements)
+ s.Emit (ec);
+ }
+
+ protected override void CloneTo (CloneContext clonectx, Statement target)
+ {
+ StatementList t = (StatementList) target;
+
+ t.statements = new List (statements.Count);
+ foreach (Statement s in statements)
+ t.statements.Add (s.Clone (clonectx));
+ }
+ }
+
// A 'return' or a 'yield break'
public abstract class ExitStatement : Statement
{
protected bool unwind_protect;
- protected abstract bool DoResolve (EmitContext ec);
+ protected abstract bool DoResolve (BlockContext ec);
- public virtual void Error_FinallyClause ()
+ public virtual void Error_FinallyClause (Report Report)
{
Report.Error (157, loc, "Control cannot leave the body of a finally clause");
}
- public sealed override bool Resolve (EmitContext ec)
+ public sealed override bool Resolve (BlockContext ec)
{
if (!DoResolve (ec))
return false;
@@ -794,63 +708,65 @@ namespace Mono.CSharp {
///
/// Implements the return statement
///
- public class Return : ExitStatement {
+ public class Return : ExitStatement
+ {
protected Expression Expr;
public Return (Expression expr, Location l)
{
Expr = expr;
loc = l;
}
-
- protected override bool DoResolve (EmitContext ec)
+
+ #region Properties
+ public Expression Expression {
+ get {
+ return Expr;
+ }
+ }
+ #endregion
+
+ protected override bool DoResolve (BlockContext ec)
{
if (Expr == null) {
if (ec.ReturnType == TypeManager.void_type)
return true;
- Error (126, "An object of a type convertible to `{0}' is required " +
- "for the return statement",
- TypeManager.CSharpName (ec.ReturnType));
+ ec.Report.Error (126, loc,
+ "An object of a type convertible to `{0}' is required for the return statement",
+ TypeManager.CSharpName (ec.ReturnType));
return false;
}
if (ec.CurrentBlock.Toplevel.IsIterator) {
- Report.Error (1622, loc, "Cannot return a value from iterators. Use the yield return " +
+ ec.Report.Error (1622, loc, "Cannot return a value from iterators. Use the yield return " +
"statement to return a value, or yield break to end the iteration");
}
AnonymousExpression am = ec.CurrentAnonymousMethod;
if (am == null && ec.ReturnType == TypeManager.void_type) {
- MemberCore mc = ec.ResolveContext as MemberCore;
- Report.Error (127, loc, "`{0}': A return keyword must not be followed by any expression when method returns void",
- mc.GetSignatureForError ());
+ ec.Report.Error (127, loc, "`{0}': A return keyword must not be followed by any expression when method returns void",
+ ec.GetSignatureForError ());
}
Expr = Expr.Resolve (ec);
if (Expr == null)
return false;
+ if (ec.HasSet (ResolveContext.Options.InferReturnType)) {
+ ec.ReturnTypeInference.AddCommonTypeBound (Expr.Type);
+ return true;
+ }
+
if (Expr.Type != ec.ReturnType) {
- if (ec.InferReturnType) {
- //
- // void cannot be used in contextual return
- //
- if (Expr.Type == TypeManager.void_type)
- return false;
+ Expr = Convert.ImplicitConversionRequired (ec, Expr, ec.ReturnType, loc);
- ec.ReturnType = Expr.Type;
- } else {
- Expr = Convert.ImplicitConversionRequired (
- ec, Expr, ec.ReturnType, loc);
-
- if (Expr == null) {
- if (am != null) {
- Report.Error (1662, loc,
- "Cannot convert `{0}' to delegate type `{1}' because some of the return types in the block are not implicitly convertible to the delegate return type",
- am.ContainerType, am.GetSignatureForError ());
- }
- return false;
+ if (Expr == null) {
+ if (am != null) {
+ ec.Report.Error (1662, loc,
+ "Cannot convert `{0}' to delegate type `{1}' because some of the return types in the block are not implicitly convertible to the delegate return type",
+ am.ContainerType, am.GetSignatureForError ());
}
+ return false;
}
}
@@ -863,19 +779,13 @@ namespace Mono.CSharp {
Expr.Emit (ec);
if (unwind_protect)
- ec.ig.Emit (OpCodes.Stloc, ec.TemporaryReturn ());
+ ec.Emit (OpCodes.Stloc, ec.TemporaryReturn ());
}
if (unwind_protect)
- ec.ig.Emit (OpCodes.Leave, ec.ReturnLabel);
+ ec.Emit (OpCodes.Leave, ec.ReturnLabel);
else
- ec.ig.Emit (OpCodes.Ret);
- }
-
- public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
- {
- if (Expr != null)
- Expr.MutateHoistedGenericType (storey);
+ ec.Emit (OpCodes.Ret);
}
protected override void CloneTo (CloneContext clonectx, Statement t)
@@ -891,13 +801,12 @@ namespace Mono.CSharp {
string target;
LabeledStatement label;
bool unwind_protect;
-
- public override bool Resolve (EmitContext ec)
+
+ public override bool Resolve (BlockContext ec)
{
- int errors = Report.Errors;
unwind_protect = ec.CurrentBranching.AddGotoOrigin (ec.CurrentBranching.CurrentUsageVector, this);
ec.CurrentBranching.CurrentUsageVector.Goto ();
- return errors == Report.Errors;
+ return true;
}
public Goto (string label, Location l)
@@ -926,11 +835,7 @@ namespace Mono.CSharp {
if (label == null)
throw new InternalErrorException ("goto emitted before target resolved");
Label l = label.LabelTarget (ec);
- ec.ig.Emit (unwind_protect ? OpCodes.Leave : OpCodes.Br, l);
- }
-
- public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
- {
+ ec.Emit (unwind_protect ? OpCodes.Leave : OpCodes.Br, l);
}
}
@@ -939,7 +844,6 @@ namespace Mono.CSharp {
bool defined;
bool referenced;
Label label;
- ILGenerator ig;
FlowBranching.UsageVector vectors;
@@ -953,10 +857,9 @@ namespace Mono.CSharp {
{
if (defined)
return label;
- ig = ec.ig;
- label = ec.ig.DefineLabel ();
- defined = true;
+ label = ec.DefineLabel ();
+ defined = true;
return label;
}
@@ -988,7 +891,7 @@ namespace Mono.CSharp {
// nothing to clone
}
- public override bool Resolve (EmitContext ec)
+ public override bool Resolve (BlockContext ec)
{
// this flow-branching will be terminated when the surrounding block ends
ec.StartFlowBranching (this);
@@ -997,14 +900,8 @@ namespace Mono.CSharp {
protected override void DoEmit (EmitContext ec)
{
- if (ig != null && ig != ec.ig)
- throw new InternalErrorException ("cannot happen");
LabelTarget (ec);
- ec.ig.MarkLabel (label);
- }
-
- public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
- {
+ ec.MarkLabel (label);
}
public void AddReference ()
@@ -1029,28 +926,26 @@ namespace Mono.CSharp {
// nothing to clone
}
- public override bool Resolve (EmitContext ec)
+ public override bool Resolve (BlockContext ec)
{
ec.CurrentBranching.CurrentUsageVector.Goto ();
- return true;
- }
- protected override void DoEmit (EmitContext ec)
- {
- if (ec.Switch == null){
- Report.Error (153, loc, "A goto case is only valid inside a switch statement");
- return;
+ if (ec.Switch == null) {
+ ec.Report.Error (153, loc, "A goto case is only valid inside a switch statement");
+ return false;
}
- if (!ec.Switch.GotDefault){
- FlowBranchingBlock.Error_UnknownLabel (loc, "default");
- return;
+ if (!ec.Switch.GotDefault) {
+ FlowBranchingBlock.Error_UnknownLabel (loc, "default", ec.Report);
+ return false;
}
- ec.ig.Emit (OpCodes.Br, ec.Switch.DefaultTarget);
+
+ return true;
}
- public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+ protected override void DoEmit (EmitContext ec)
{
+ ec.Emit (OpCodes.Br, ec.Switch.DefaultTarget);
}
}
@@ -1067,10 +962,10 @@ namespace Mono.CSharp {
loc = l;
}
- public override bool Resolve (EmitContext ec)
+ public override bool Resolve (BlockContext ec)
{
if (ec.Switch == null){
- Report.Error (153, loc, "A goto case is only valid inside a switch statement");
+ ec.Report.Error (153, loc, "A goto case is only valid inside a switch statement");
return false;
}
@@ -1082,11 +977,11 @@ namespace Mono.CSharp {
Constant c = expr as Constant;
if (c == null) {
- Error (150, "A constant value is expected");
+ ec.Report.Error (150, expr.Location, "A constant value is expected");
return false;
}
- Type type = ec.Switch.SwitchType;
+ TypeSpec type = ec.Switch.SwitchType;
Constant res = c.TryReduce (ec, type, c.Location);
if (res == null) {
c.Error_ValueCannotBeConverted (ec, loc, type, true);
@@ -1094,7 +989,7 @@ namespace Mono.CSharp {
}
if (!Convert.ImplicitStandardConversionExists (c, type))
- Report.Warning (469, 2, loc,
+ ec.Report.Warning (469, 2, loc,
"The `goto case' value is not implicitly convertible to type `{0}'",
TypeManager.CSharpName (type));
@@ -1102,11 +997,9 @@ namespace Mono.CSharp {
if (val == null)
val = SwitchLabel.NullStringCase;
- sl = (SwitchLabel) ec.Switch.Elements [val];
-
- if (sl == null){
+ if (!ec.Switch.Elements.TryGetValue (val, out sl)) {
FlowBranchingBlock.Error_UnknownLabel (loc, "case " +
- (c.GetValue () == null ? "null" : val.ToString ()));
+ (c.GetValue () == null ? "null" : val.ToString ()), ec.Report);
return false;
}
@@ -1115,12 +1008,7 @@ namespace Mono.CSharp {
protected override void DoEmit (EmitContext ec)
{
- ec.ig.Emit (OpCodes.Br, sl.GetILLabelCode (ec));
- }
-
- public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
- {
- expr.MutateHoistedGenericType (storey);
+ ec.Emit (OpCodes.Br, sl.GetILLabelCode (ec));
}
protected override void CloneTo (CloneContext clonectx, Statement t)
@@ -1140,7 +1028,7 @@ namespace Mono.CSharp {
loc = l;
}
- public override bool Resolve (EmitContext ec)
+ public override bool Resolve (BlockContext ec)
{
if (expr == null) {
ec.CurrentBranching.CurrentUsageVector.Goto ();
@@ -1153,34 +1041,25 @@ namespace Mono.CSharp {
if (expr == null)
return false;
- Type t = expr.Type;
+ if (Convert.ImplicitConversionExists (ec, expr, TypeManager.exception_type))
+ expr = Convert.ImplicitConversion (ec, expr, TypeManager.exception_type, loc);
+ else
+ ec.Report.Error (155, expr.Location, "The type caught or thrown must be derived from System.Exception");
- if ((t != TypeManager.exception_type) &&
- !TypeManager.IsSubclassOf (t, TypeManager.exception_type) &&
- t != TypeManager.null_type) {
- Error (155, "The type caught or thrown must be derived from System.Exception");
- return false;
- }
return true;
}
protected override void DoEmit (EmitContext ec)
{
if (expr == null)
- ec.ig.Emit (OpCodes.Rethrow);
+ ec.Emit (OpCodes.Rethrow);
else {
expr.Emit (ec);
- ec.ig.Emit (OpCodes.Throw);
+ ec.Emit (OpCodes.Throw);
}
}
- public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
- {
- if (expr != null)
- expr.MutateHoistedGenericType (storey);
- }
-
protected override void CloneTo (CloneContext clonectx, Statement t)
{
Throw target = (Throw) t;
@@ -1199,23 +1078,18 @@ namespace Mono.CSharp {
bool unwind_protect;
- public override bool Resolve (EmitContext ec)
+ public override bool Resolve (BlockContext ec)
{
- int errors = Report.Errors;
unwind_protect = ec.CurrentBranching.AddBreakOrigin (ec.CurrentBranching.CurrentUsageVector, loc);
ec.CurrentBranching.CurrentUsageVector.Goto ();
- return errors == Report.Errors;
+ return true;
}
protected override void DoEmit (EmitContext ec)
{
- ec.ig.Emit (unwind_protect ? OpCodes.Leave : OpCodes.Br, ec.LoopEnd);
+ ec.Emit (unwind_protect ? OpCodes.Leave : OpCodes.Br, ec.LoopEnd);
}
- public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
- {
- }
-
protected override void CloneTo (CloneContext clonectx, Statement t)
{
// nothing needed
@@ -1231,21 +1105,16 @@ namespace Mono.CSharp {
bool unwind_protect;
- public override bool Resolve (EmitContext ec)
+ public override bool Resolve (BlockContext ec)
{
- int errors = Report.Errors;
unwind_protect = ec.CurrentBranching.AddContinueOrigin (ec.CurrentBranching.CurrentUsageVector, loc);
ec.CurrentBranching.CurrentUsageVector.Goto ();
- return errors == Report.Errors;
+ return true;
}
protected override void DoEmit (EmitContext ec)
{
- ec.ig.Emit (unwind_protect ? OpCodes.Leave : OpCodes.Br, ec.LoopBegin);
- }
-
- public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
- {
+ ec.Emit (unwind_protect ? OpCodes.Leave : OpCodes.Br, ec.LoopBegin);
}
protected override void CloneTo (CloneContext clonectx, Statement t)
@@ -1272,13 +1141,13 @@ namespace Mono.CSharp {
public class LocalInfo : IKnownVariable, ILocalVariable {
public readonly FullNamedExpression Type;
- public Type VariableType;
+ public TypeSpec VariableType;
public readonly string Name;
public readonly Location Location;
public readonly Block Block;
public VariableInfo VariableInfo;
- public HoistedVariable HoistedVariableReference;
+ HoistedVariable hoisted_variant;
[Flags]
enum Flags : byte {
@@ -1309,43 +1178,36 @@ namespace Mono.CSharp {
Location = l;
}
- public LocalInfo (DeclSpace ds, Block block, Location l)
+ public LocalInfo (TypeContainer ds, Block block, Location l)
{
- VariableType = ds.IsGeneric ? ds.CurrentType : ds.TypeBuilder;
+ VariableType = ds.IsGeneric ? ds.CurrentType : ds.Definition;
Block = block;
Location = l;
}
public void ResolveVariable (EmitContext ec)
{
- if (HoistedVariableReference != null)
+ if (HoistedVariant != null)
return;
if (builder == null) {
- if (Pinned)
- //
- // This is needed to compile on both .NET 1.x and .NET 2.x
- // the later introduced `DeclareLocal (Type t, bool pinned)'
- //
- builder = TypeManager.DeclareLocalPinned (ec.ig, VariableType);
- else
- builder = ec.ig.DeclareLocal (VariableType);
+ builder = ec.DeclareLocal (VariableType, Pinned);
}
}
public void Emit (EmitContext ec)
{
- ec.ig.Emit (OpCodes.Ldloc, builder);
+ ec.Emit (OpCodes.Ldloc, builder);
}
public void EmitAssign (EmitContext ec)
{
- ec.ig.Emit (OpCodes.Stloc, builder);
+ ec.Emit (OpCodes.Stloc, builder);
}
public void EmitAddressOf (EmitContext ec)
{
- ec.ig.Emit (OpCodes.Ldloca, builder);
+ ec.Emit (OpCodes.Ldloca, builder);
}
public void EmitSymbolInfo (EmitContext ec)
@@ -1354,7 +1216,19 @@ namespace Mono.CSharp {
ec.DefineLocalVariable (Name, builder);
}
- public bool IsThisAssigned (EmitContext ec)
+ //
+ // Hoisted local variable variant
+ //
+ public HoistedVariable HoistedVariant {
+ get {
+ return hoisted_variant;
+ }
+ set {
+ hoisted_variant = value;
+ }
+ }
+
+ public bool IsThisAssigned (BlockContext ec, Block block)
{
if (VariableInfo == null)
throw new Exception ();
@@ -1362,10 +1236,10 @@ namespace Mono.CSharp {
if (!ec.DoFlowAnalysis || ec.CurrentBranching.IsAssigned (VariableInfo))
return true;
- return VariableInfo.TypeInfo.IsFullyInitialized (ec.CurrentBranching, VariableInfo, ec.loc);
+ return VariableInfo.TypeInfo.IsFullyInitialized (ec, VariableInfo, block.StartLocation);
}
- public bool IsAssigned (EmitContext ec)
+ public bool IsAssigned (BlockContext ec)
{
if (VariableInfo == null)
throw new Exception ();
@@ -1373,7 +1247,7 @@ namespace Mono.CSharp {
return !ec.DoFlowAnalysis || ec.CurrentBranching.IsAssigned (VariableInfo);
}
- public bool Resolve (EmitContext ec)
+ public bool Resolve (ResolveContext ec)
{
if (VariableType != null)
return true;
@@ -1384,16 +1258,13 @@ namespace Mono.CSharp {
VariableType = texpr.Type;
- if (TypeManager.IsGenericParameter (VariableType))
- return true;
-
- if (VariableType.IsAbstract && VariableType.IsSealed) {
- FieldBase.Error_VariableOfStaticClass (Location, Name, VariableType);
+ if (VariableType.IsStatic) {
+ FieldBase.Error_VariableOfStaticClass (Location, Name, VariableType, ec.Report);
return false;
}
- if (VariableType.IsPointer && !ec.InUnsafe)
- Expression.UnsafeError (Location);
+ if (VariableType.IsPointer && !ec.IsUnsafe)
+ Expression.UnsafeError (ec, Location);
return true;
}
@@ -1512,7 +1383,8 @@ namespace Mono.CSharp {
public ToplevelBlock Toplevel; // TODO: Use Explicit
[Flags]
- public enum Flags : byte {
+ public enum Flags
+ {
Unchecked = 1,
BlockUsed = 2,
VariablesInitialized = 4,
@@ -1520,8 +1392,10 @@ namespace Mono.CSharp {
Unsafe = 16,
IsIterator = 32,
HasCapturedVariable = 64,
- HasCapturedThis = 128
+ HasCapturedThis = 1 << 7,
+ IsExpressionTree = 1 << 8
}
+
protected Flags flags;
public bool Unchecked {
@@ -1537,7 +1411,7 @@ namespace Mono.CSharp {
//
// The statements in this block
//
- protected ArrayList statements;
+ protected List statements;
//
// An array of Blocks. We keep track of children just
@@ -1546,35 +1420,37 @@ namespace Mono.CSharp {
// Statements and child statements are handled through the
// statements.
//
- ArrayList children;
+ List children;
//
// Labels. (label, block) pairs.
//
- protected HybridDictionary labels;
+ protected Dictionary labels;
//
// Keeps track of (name, type) pairs
//
- IDictionary variables;
+ Dictionary variables;
//
// Keeps track of constants
- HybridDictionary constants;
+ Dictionary constants;
//
// Temporary variables.
//
- ArrayList temporary_variables;
+ List temporary_variables;
//
// If this is a switch section, the enclosing switch block.
//
Block switch_block;
- protected ArrayList scope_initializers;
+ protected List scope_initializers;
- ArrayList anonymous_children;
+ List anonymous_children;
+
+ int? resolving_init_idx;
protected static int id;
@@ -1626,33 +1502,37 @@ namespace Mono.CSharp {
this.EndLocation = end;
this.loc = start;
this_id = id++;
- statements = new ArrayList (4);
+ statements = new List (4);
}
- public Block CreateSwitchBlock (Location start)
- {
- // FIXME: should this be implicit?
- Block new_block = new ExplicitBlock (this, start, start);
- new_block.switch_block = this;
- return new_block;
- }
+ #region Properties
public int ID {
get { return this_id; }
}
- public IDictionary Variables {
+ public IDictionary Variables {
get {
if (variables == null)
- variables = new ListDictionary ();
+ variables = new Dictionary ();
return variables;
}
}
+ #endregion
+
+ public Block CreateSwitchBlock (Location start)
+ {
+ // FIXME: should this be implicit?
+ Block new_block = new ExplicitBlock (this, start, start);
+ new_block.switch_block = this;
+ return new_block;
+ }
+
void AddChild (Block b)
{
if (children == null)
- children = new ArrayList (1);
+ children = new List (1);
children.Add (b);
}
@@ -1662,9 +1542,9 @@ namespace Mono.CSharp {
EndLocation = loc;
}
- protected static void Error_158 (string name, Location loc)
+ protected void Error_158 (string name, Location loc)
{
- Report.Error (158, loc, "The label `{0}' shadows another label " +
+ Toplevel.Report.Error (158, loc, "The label `{0}' shadows another label " +
"by the same name in a contained scope", name);
}
@@ -1688,8 +1568,8 @@ namespace Mono.CSharp {
while (cur != null) {
LabeledStatement s = cur.DoLookupLabel (name);
if (s != null) {
- Report.SymbolRelatedToPreviousError (s.loc, s.Name);
- Report.Error (140, target.loc, "The label `{0}' is a duplicate", name);
+ Toplevel.Report.SymbolRelatedToPreviousError (s.loc, s.Name);
+ Toplevel.Report.Error (140, target.loc, "The label `{0}' is a duplicate", name);
return false;
}
@@ -1711,7 +1591,7 @@ namespace Mono.CSharp {
if (s == null)
continue;
- Report.SymbolRelatedToPreviousError (s.loc, s.Name);
+ Toplevel.Report.SymbolRelatedToPreviousError (s.loc, s.Name);
Error_158 (name, target.loc);
return false;
}
@@ -1723,7 +1603,7 @@ namespace Mono.CSharp {
Toplevel.CheckError158 (name, target.loc);
if (labels == null)
- labels = new HybridDictionary();
+ labels = new Dictionary ();
labels.Add (name, target);
return true;
@@ -1756,8 +1636,8 @@ namespace Mono.CSharp {
return switch_block.LookupLabel (name);
if (labels != null)
- if (labels.Contains (name))
- return ((LabeledStatement) labels [name]);
+ if (labels.ContainsKey (name))
+ return labels [name];
return null;
}
@@ -1783,8 +1663,8 @@ namespace Mono.CSharp {
// block, we violate the invariant meaning in a block.
//
if (b == this) {
- Report.SymbolRelatedToPreviousError (kvi.Location, name);
- Report.Error (135, loc, "`{0}' conflicts with a declaration in a child block", name);
+ Toplevel.Report.SymbolRelatedToPreviousError (kvi.Location, name);
+ Toplevel.Report.Error (135, loc, "`{0}' conflicts with a declaration in a child block", name);
return false;
}
@@ -1808,8 +1688,8 @@ namespace Mono.CSharp {
return true;
if (this is ToplevelBlock) {
- Report.SymbolRelatedToPreviousError (kvi.Location, name);
- e.Error_VariableIsUsedBeforeItIsDeclared (name);
+ Toplevel.Report.SymbolRelatedToPreviousError (kvi.Location, name);
+ e.Error_VariableIsUsedBeforeItIsDeclared (Toplevel.Report, name);
return false;
}
@@ -1817,16 +1697,16 @@ namespace Mono.CSharp {
// Even though we detected the error when the name is used, we
// treat it as if the variable declaration was in error.
//
- Report.SymbolRelatedToPreviousError (loc, name);
+ Toplevel.Report.SymbolRelatedToPreviousError (loc, name);
Error_AlreadyDeclared (kvi.Location, name, "parent or current");
return false;
}
- protected virtual bool CheckParentConflictName (ToplevelBlock block, string name, Location l)
+ protected bool CheckParentConflictName (ToplevelBlock block, string name, Location l)
{
LocalInfo vi = GetLocalInfo (name);
if (vi != null) {
- Report.SymbolRelatedToPreviousError (vi.Location, name);
+ block.Report.SymbolRelatedToPreviousError (vi.Location, name);
if (Explicit == vi.Block.Explicit) {
Error_AlreadyDeclared (l, name, null);
} else {
@@ -1837,13 +1717,13 @@ namespace Mono.CSharp {
}
if (block != null) {
- Expression e = block.GetParameterReference (name, Location.Null);
- if (e != null) {
- ParameterReference pr = e as ParameterReference;
- if (this is Linq.QueryBlock && (pr != null && pr.Parameter is Linq.QueryBlock.ImplicitQueryParameter || e is MemberAccess))
+ var tblock = block.CheckParameterNameConflict (name);
+ if (tblock != null) {
+ if (block == tblock && block is Linq.QueryBlock)
Error_AlreadyDeclared (loc, name);
else
Error_AlreadyDeclared (loc, name, "parent or current");
+
return false;
}
}
@@ -1856,19 +1736,9 @@ namespace Mono.CSharp {
if (!CheckParentConflictName (Toplevel, name, l))
return null;
- if (Toplevel.GenericMethod != null) {
- foreach (TypeParameter tp in Toplevel.GenericMethod.CurrentTypeParameters) {
- if (tp.Name == name) {
- Report.SymbolRelatedToPreviousError (tp);
- Error_AlreadyDeclaredTypeParameter (loc, name, "local variable");
- return null;
- }
- }
- }
-
IKnownVariable kvi = Explicit.GetKnownVariable (name);
if (kvi != null) {
- Report.SymbolRelatedToPreviousError (kvi.Location, name);
+ Toplevel.Report.SymbolRelatedToPreviousError (kvi.Location, name);
Error_AlreadyDeclared (l, name, "child");
return null;
}
@@ -1895,7 +1765,7 @@ namespace Mono.CSharp {
return;
}
- Report.Error (136, loc, "A local variable named `{0}' cannot be declared " +
+ Toplevel.Report.Error (136, loc, "A local variable named `{0}' cannot be declared " +
"in this scope because it would give a different meaning " +
"to `{0}', which is already used in a `{1}' scope " +
"to denote something else", var, reason);
@@ -1903,13 +1773,13 @@ namespace Mono.CSharp {
protected virtual void Error_AlreadyDeclared (Location loc, string name)
{
- Report.Error (128, loc,
+ Toplevel.Report.Error (128, loc,
"A local variable named `{0}' is already defined in this scope", name);
}
public virtual void Error_AlreadyDeclaredTypeParameter (Location loc, string name, string conflict)
{
- Report.Error (412, loc, "The type parameter name `{0}' is the same as `{1}'",
+ Toplevel.Report.Error (412, loc, "The type parameter name `{0}' is the same as `{1}'",
name, conflict);
}
@@ -1919,7 +1789,7 @@ namespace Mono.CSharp {
return false;
if (constants == null)
- constants = new HybridDictionary();
+ constants = new Dictionary ();
constants.Add (name, value);
@@ -1935,7 +1805,7 @@ namespace Mono.CSharp {
Report.Debug (64, "ADD TEMPORARY", this, Toplevel, loc);
if (temporary_variables == null)
- temporary_variables = new ArrayList ();
+ temporary_variables = new List ();
int id = ++next_temp_id;
string name = "$s_" + id.ToString ();
@@ -1950,10 +1820,8 @@ namespace Mono.CSharp {
{
LocalInfo ret;
for (Block b = this; b != null; b = b.Parent) {
- if (b.variables != null) {
- ret = (LocalInfo) b.variables [name];
- if (ret != null)
- return ret;
+ if (b.variables != null && b.variables.TryGetValue (name, out ret)) {
+ return ret;
}
}
@@ -1968,10 +1836,10 @@ namespace Mono.CSharp {
public Expression GetConstantExpression (string name)
{
+ Expression ret;
for (Block b = this; b != null; b = b.Parent) {
if (b.constants != null) {
- Expression ret = b.constants [name] as Expression;
- if (ret != null)
+ if (b.constants.TryGetValue (name, out ret))
return ret;
}
}
@@ -1985,9 +1853,20 @@ namespace Mono.CSharp {
public void AddScopeStatement (Statement s)
{
if (scope_initializers == null)
- scope_initializers = new ArrayList ();
+ scope_initializers = new List ();
- scope_initializers.Add (s);
+ //
+ // Simple recursive helper, when resolve scope initializer another
+ // new scope initializer can be added, this ensures it's initialized
+ // before existing one. For now this can happen with expression trees
+ // in base ctor initializer only
+ //
+ if (resolving_init_idx.HasValue) {
+ scope_initializers.Insert (resolving_init_idx.Value, s);
+ ++resolving_init_idx;
+ } else {
+ scope_initializers.Add (s);
+ }
}
public void AddStatement (Statement s)
@@ -2018,19 +1897,19 @@ namespace Mono.CSharp {
}
}
- public ArrayList AnonymousChildren {
+ public IList AnonymousChildren {
get { return anonymous_children; }
}
public void AddAnonymousChild (ToplevelBlock b)
{
if (anonymous_children == null)
- anonymous_children = new ArrayList ();
+ anonymous_children = new List ();
anonymous_children.Add (b);
}
- void DoResolveConstants (EmitContext ec)
+ void DoResolveConstants (BlockContext ec)
{
if (constants == null)
return;
@@ -2038,20 +1917,20 @@ namespace Mono.CSharp {
if (variables == null)
throw new InternalErrorException ("cannot happen");
- foreach (DictionaryEntry de in variables) {
- string name = (string) de.Key;
- LocalInfo vi = (LocalInfo) de.Value;
- Type variable_type = vi.VariableType;
+ foreach (var de in variables) {
+ string name = de.Key;
+ LocalInfo vi = de.Value;
+ TypeSpec variable_type = vi.VariableType;
if (variable_type == null) {
if (vi.Type is VarExpr)
- Report.Error (822, vi.Type.Location, "An implicitly typed local variable cannot be a constant");
+ ec.Report.Error (822, vi.Type.Location, "An implicitly typed local variable cannot be a constant");
continue;
}
- Expression cv = (Expression) constants [name];
- if (cv == null)
+ Expression cv;
+ if (!constants.TryGetValue (name, out cv))
continue;
// Don't let 'const int Foo = Foo;' succeed.
@@ -2059,14 +1938,14 @@ namespace Mono.CSharp {
// which in turn causes the 'must be constant' error to be triggered.
constants.Remove (name);
- if (!Const.IsConstantTypeValid (variable_type)) {
- Const.Error_InvalidConstantType (variable_type, loc);
+ if (!variable_type.IsConstantCompatible) {
+ Const.Error_InvalidConstantType (variable_type, loc, ec.Report);
continue;
}
ec.CurrentBlock = this;
Expression e;
- using (ec.With (EmitContext.Flags.ConstantCheckState, (flags & Flags.Unchecked) == 0)) {
+ using (ec.With (ResolveContext.Options.ConstantCheckState, (flags & Flags.Unchecked) == 0)) {
e = cv.Resolve (ec);
}
if (e == null)
@@ -2074,14 +1953,14 @@ namespace Mono.CSharp {
Constant ce = e as Constant;
if (ce == null) {
- Const.Error_ExpressionMustBeConstant (vi.Location, name);
+ e.Error_ExpressionMustBeConstant (ec, vi.Location, name);
continue;
}
- e = ce.ConvertImplicitly (variable_type);
+ e = ce.ConvertImplicitly (ec, variable_type);
if (e == null) {
if (TypeManager.IsReferenceType (variable_type))
- Const.Error_ConstantCanBeInitializedWithNullOnly (variable_type, vi.Location, vi.Name);
+ ce.Error_ConstantCanBeInitializedWithNullOnly (ec, variable_type, vi.Location, vi.Name);
else
ce.Error_ValueCannotBeConverted (ec, vi.Location, variable_type, false);
continue;
@@ -2092,13 +1971,13 @@ namespace Mono.CSharp {
}
}
- protected void ResolveMeta (EmitContext ec, int offset)
+ protected void ResolveMeta (BlockContext ec, int offset)
{
Report.Debug (64, "BLOCK RESOLVE META", this, Parent);
// If some parent block was unsafe, we remain unsafe even if this block
// isn't explicitly marked as such.
- using (ec.With (EmitContext.Flags.InUnsafe, ec.InUnsafe | Unsafe)) {
+ using (ec.With (ResolveContext.Options.UnsafeScope, ec.IsUnsafe | Unsafe)) {
flags |= Flags.VariablesInitialized;
if (variables != null) {
@@ -2141,27 +2020,27 @@ namespace Mono.CSharp {
}
}
- void UsageWarning ()
+ void UsageWarning (BlockContext ec)
{
- if (variables == null || Report.WarningLevel < 3)
+ if (variables == null || ec.Report.WarningLevel < 3)
return;
- foreach (DictionaryEntry de in variables) {
- LocalInfo vi = (LocalInfo) de.Value;
+ foreach (var de in variables) {
+ LocalInfo vi = de.Value;
if (!vi.Used) {
- string name = (string) de.Key;
+ string name = de.Key;
// vi.VariableInfo can be null for 'catch' variables
if (vi.VariableInfo != null && vi.VariableInfo.IsEverAssigned)
- Report.Warning (219, 3, vi.Location, "The variable `{0}' is assigned but its value is never used", name);
+ ec.Report.Warning (219, 3, vi.Location, "The variable `{0}' is assigned but its value is never used", name);
else
- Report.Warning (168, 3, vi.Location, "The variable `{0}' is declared but never used", name);
+ ec.Report.Warning (168, 3, vi.Location, "The variable `{0}' is declared but never used", name);
}
}
}
- static void CheckPossibleMistakenEmptyStatement (Statement s)
+ static void CheckPossibleMistakenEmptyStatement (BlockContext ec, Statement s)
{
Statement body;
@@ -2190,21 +2069,32 @@ namespace Mono.CSharp {
return;
if (body == null || body is EmptyStatement)
- Report.Warning (642, 3, s.loc, "Possible mistaken empty statement");
+ ec.Report.Warning (642, 3, s.loc, "Possible mistaken empty statement");
}
- public override bool Resolve (EmitContext ec)
+ public override bool Resolve (BlockContext ec)
{
Block prev_block = ec.CurrentBlock;
bool ok = true;
- int errors = Report.Errors;
+ int errors = ec.Report.Errors;
ec.CurrentBlock = this;
ec.StartFlowBranching (this);
Report.Debug (4, "RESOLVE BLOCK", StartLocation, ec.CurrentBranching);
+ //
+ // Compiler generated scope statements
+ //
+ if (scope_initializers != null) {
+ for (resolving_init_idx = 0; resolving_init_idx < scope_initializers.Count; ++resolving_init_idx) {
+ scope_initializers[resolving_init_idx.Value].Resolve (ec);
+ }
+
+ resolving_init_idx = null;
+ }
+
//
// This flag is used to notate nested statements as unreachable from the beginning of this block.
// For the purposes of this resolution, it doesn't matter that the whole block is unreachable
@@ -2213,12 +2103,11 @@ namespace Mono.CSharp {
//
int statement_count = statements.Count;
for (int ix = 0; ix < statement_count; ix++){
- Statement s = (Statement) statements [ix];
+ Statement s = statements [ix];
// Check possible empty statement (CS0642)
- if (Report.WarningLevel >= 3 &&
- ix + 1 < statement_count &&
- statements [ix + 1] is ExplicitBlock)
- CheckPossibleMistakenEmptyStatement (s);
+ if (ix + 1 < statement_count && ec.Report.WarningLevel >= 3 &&
+ statements [ix + 1] is ExplicitBlock)
+ CheckPossibleMistakenEmptyStatement (ec, s);
//
// Warn if we detect unreachable code.
@@ -2228,7 +2117,7 @@ namespace Mono.CSharp {
continue;
if (!unreachable_shown && !(s is LabeledStatement)) {
- Report.Warning (162, 2, s.loc, "Unreachable code detected");
+ ec.Report.Warning (162, 2, s.loc, "Unreachable code detected");
unreachable_shown = true;
}
@@ -2250,12 +2139,12 @@ namespace Mono.CSharp {
if (ec.IsInProbingMode)
break;
- statements [ix] = EmptyStatement.Value;
+ statements [ix] = new EmptyStatement (s.loc);
continue;
}
if (unreachable && !(s is LabeledStatement) && !(s is Block))
- statements [ix] = EmptyStatement.Value;
+ statements [ix] = new EmptyStatement (s.loc);
unreachable = ec.CurrentBranching.CurrentUsageVector.IsUnreachable;
if (unreachable && s is LabeledStatement)
@@ -2280,25 +2169,25 @@ namespace Mono.CSharp {
if (this == Toplevel && !Toplevel.IsThisAssigned (ec) && !flow_unreachable)
ok = false;
- if ((labels != null) && (Report.WarningLevel >= 2)) {
+ if ((labels != null) && (ec.Report.WarningLevel >= 2)) {
foreach (LabeledStatement label in labels.Values)
if (!label.HasBeenReferenced)
- Report.Warning (164, 2, label.loc, "This label has not been referenced");
+ ec.Report.Warning (164, 2, label.loc, "This label has not been referenced");
}
- if (ok && errors == Report.Errors)
- UsageWarning ();
+ if (ok && errors == ec.Report.Errors)
+ UsageWarning (ec);
return ok;
}
- public override bool ResolveUnreachable (EmitContext ec, bool warn)
+ public override bool ResolveUnreachable (BlockContext ec, bool warn)
{
unreachable_shown = true;
unreachable = true;
if (warn)
- Report.Warning (162, 2, loc, "Unreachable code detected");
+ ec.Report.Warning (162, 2, loc, "Unreachable code detected");
ec.StartFlowBranching (FlowBranching.BranchingType.Block, loc);
bool ok = Resolve (ec);
@@ -2310,16 +2199,12 @@ namespace Mono.CSharp {
protected override void DoEmit (EmitContext ec)
{
for (int ix = 0; ix < statements.Count; ix++){
- Statement s = (Statement) statements [ix];
- s.Emit (ec);
+ statements [ix].Emit (ec);
}
}
public override void Emit (EmitContext ec)
{
- Block prev_block = ec.CurrentBlock;
- ec.CurrentBlock = this;
-
if (scope_initializers != null)
EmitScopeInitializers (ec);
@@ -2328,20 +2213,18 @@ namespace Mono.CSharp {
if (SymbolWriter.HasSymbolWriter)
EmitSymbolInfo (ec);
-
- ec.CurrentBlock = prev_block;
}
protected void EmitScopeInitializers (EmitContext ec)
{
- SymbolWriter.OpenCompilerGeneratedBlock (ec.ig);
+ SymbolWriter.OpenCompilerGeneratedBlock (ec);
- using (ec.Set (EmitContext.Flags.OmitDebuggingInfo)) {
+ using (ec.With (EmitContext.Options.OmitDebugInfo, true)) {
foreach (Statement s in scope_initializers)
s.Emit (ec);
}
- SymbolWriter.CloseCompilerGeneratedBlock (ec.ig);
+ SymbolWriter.CloseCompilerGeneratedBlock (ec);
}
protected virtual void EmitSymbolInfo (EmitContext ec)
@@ -2353,36 +2236,9 @@ namespace Mono.CSharp {
}
}
- public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
- {
- MutateVariables (storey);
-
- if (scope_initializers != null) {
- foreach (Statement s in scope_initializers)
- s.MutateHoistedGenericType (storey);
- }
-
- foreach (Statement s in statements)
- s.MutateHoistedGenericType (storey);
- }
-
- void MutateVariables (AnonymousMethodStorey storey)
- {
- if (variables != null) {
- foreach (LocalInfo vi in variables.Values) {
- vi.VariableType = storey.MutateType (vi.VariableType);
- }
- }
-
- if (temporary_variables != null) {
- foreach (LocalInfo vi in temporary_variables)
- vi.VariableType = storey.MutateType (vi.VariableType);
- }
- }
-
public override string ToString ()
{
- return String.Format ("{0} ({1}:{2})", GetType (),ID, StartLocation);
+ return String.Format ("{0} ({1}:{2})", GetType (), this_id, StartLocation);
}
protected override void CloneTo (CloneContext clonectx, Statement t)
@@ -2391,27 +2247,27 @@ namespace Mono.CSharp {
clonectx.AddBlockMap (this, target);
- //target.Toplevel = (ToplevelBlock) clonectx.LookupBlock (Toplevel);
+ target.Toplevel = (ToplevelBlock) clonectx.LookupBlock (Toplevel);
target.Explicit = (ExplicitBlock) clonectx.LookupBlock (Explicit);
if (Parent != null)
target.Parent = clonectx.RemapBlockCopy (Parent);
if (variables != null){
- target.variables = new Hashtable ();
+ target.variables = new Dictionary ();
- foreach (DictionaryEntry de in variables){
- LocalInfo newlocal = ((LocalInfo) de.Value).Clone (clonectx);
+ foreach (var de in variables){
+ LocalInfo newlocal = de.Value.Clone (clonectx);
target.variables [de.Key] = newlocal;
- clonectx.AddVariableMap ((LocalInfo) de.Value, newlocal);
+ clonectx.AddVariableMap (de.Value, newlocal);
}
}
- target.statements = new ArrayList (statements.Count);
+ target.statements = new List (statements.Count);
foreach (Statement s in statements)
target.statements.Add (s.Clone (clonectx));
if (target.children != null){
- target.children = new ArrayList (children.Count);
+ target.children = new List (children.Count);
foreach (Block b in children){
target.children.Add (clonectx.LookupBlock (b));
}
@@ -2423,8 +2279,9 @@ namespace Mono.CSharp {
}
}
- public class ExplicitBlock : Block {
- HybridDictionary known_variables;
+ public class ExplicitBlock : Block
+ {
+ Dictionary known_variables;
protected AnonymousMethodStorey am_storey;
public ExplicitBlock (Block parent, Location start, Location end)
@@ -2446,7 +2303,7 @@ namespace Mono.CSharp {
internal void AddKnownVariable (string name, IKnownVariable info)
{
if (known_variables == null)
- known_variables = new HybridDictionary();
+ known_variables = new Dictionary ();
known_variables [name] = info;
@@ -2461,7 +2318,7 @@ namespace Mono.CSharp {
//
// Creates anonymous method storey in current block
//
- public AnonymousMethodStorey CreateAnonymousMethodStorey (EmitContext ec)
+ public AnonymousMethodStorey CreateAnonymousMethodStorey (ResolveContext ec)
{
//
// When referencing a variable in iterator storey from children anonymous method
@@ -2477,13 +2334,13 @@ namespace Mono.CSharp {
return ec.CurrentIterator.Storey;
if (am_storey == null) {
- MemberBase mc = ec.ResolveContext as MemberBase;
+ MemberBase mc = ec.MemberContext as MemberBase;
GenericMethod gm = mc == null ? null : mc.GenericMethod;
//
// Creates anonymous method storey for this block
//
- am_storey = new AnonymousMethodStorey (this, ec.TypeContainer, mc, gm, "AnonStorey");
+ am_storey = new AnonymousMethodStorey (this, ec.CurrentMemberDefinition.Parent.PartialContainer, mc, gm, "AnonStorey");
}
return am_storey;
@@ -2523,23 +2380,30 @@ namespace Mono.CSharp {
while (parent.am_storey == null || parent.am_storey.Parent is AnonymousMethodStorey)
parent = parent.Parent.Explicit;
- am_storey.AddParentStoreyReference (parent.am_storey);
+ am_storey.AddParentStoreyReference (ec, parent.am_storey);
}
- am_storey.ChangeParentStorey (ec.CurrentAnonymousMethod.Storey);
+ am_storey.SetNestedStoryParent (ec.CurrentAnonymousMethod.Storey);
+
+ // TODO MemberCache: Review
+ am_storey.Mutator = ec.CurrentAnonymousMethod.Storey.Mutator;
}
+ am_storey.CreateType ();
+ if (am_storey.Mutator == null && ec.CurrentTypeParameters != null)
+ am_storey.Mutator = new TypeParameterMutator (ec.CurrentTypeParameters, am_storey.CurrentTypeParameters);
+
am_storey.DefineType ();
- am_storey.ResolveType ();
+ am_storey.ResolveTypeParameters ();
am_storey.Define ();
am_storey.Parent.PartialContainer.AddCompilerGeneratedClass (am_storey);
- ArrayList ref_blocks = am_storey.ReferencesFromChildrenBlock;
+ var ref_blocks = am_storey.ReferencesFromChildrenBlock;
if (ref_blocks != null) {
foreach (ExplicitBlock ref_block in ref_blocks) {
for (ExplicitBlock b = ref_block.Explicit; b != this; b = b.Parent.Explicit) {
if (b.am_storey != null) {
- b.am_storey.AddParentStoreyReference (am_storey);
+ b.am_storey.AddParentStoreyReference (ec, am_storey);
// Stop propagation inside same top block
if (b.Toplevel == Toplevel)
@@ -2556,9 +2420,14 @@ namespace Mono.CSharp {
base.EmitMeta (ec);
}
- internal IKnownVariable GetKnownVariable (string name)
+ public IKnownVariable GetKnownVariable (string name)
{
- return known_variables == null ? null : (IKnownVariable) known_variables [name];
+ if (known_variables == null)
+ return null;
+
+ IKnownVariable kw;
+ known_variables.TryGetValue (name, out kw);
+ return kw;
}
public bool HasCapturedThis
@@ -2593,7 +2462,7 @@ namespace Mono.CSharp {
get { return Block.Parameters [Index]; }
}
- public Type ParameterType {
+ public TypeSpec ParameterType {
get { return Block.Parameters.Types [Index]; }
}
@@ -2632,17 +2501,16 @@ namespace Mono.CSharp {
this.block = block;
}
- public override Expression CreateExpressionTree (EmitContext ec)
+ public override Expression CreateExpressionTree (ResolveContext ec)
{
throw new NotSupportedException ();
}
- public override Expression DoResolve (EmitContext ec)
+ protected override Expression DoResolve (ResolveContext ec)
{
if (child == null)
return null;
- block.ResolveMeta (ec, ParametersCompiled.EmptyReadOnlyParameters);
child = child.Resolve (ec);
if (child == null)
return null;
@@ -2658,23 +2526,23 @@ namespace Mono.CSharp {
block.EmitScopeInitializers (ec);
child.Emit (ec);
}
-
- public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
- {
- type = storey.MutateType (type);
- child.MutateHoistedGenericType (storey);
- block.MutateHoistedGenericType (storey);
- }
}
- GenericMethod generic;
- FlowBranchingToplevel top_level_branching;
protected ParametersCompiled parameters;
- ToplevelParameterInfo[] parameter_info;
+ protected ToplevelParameterInfo[] parameter_info;
LocalInfo this_variable;
+ bool resolved;
+ bool unreachable;
+ CompilerContext compiler;
public HoistedVariable HoistedThisVariable;
+ public bool Resolved {
+ get {
+ return resolved;
+ }
+ }
+
//
// The parameters for the block.
//
@@ -2682,40 +2550,35 @@ namespace Mono.CSharp {
get { return parameters; }
}
- public GenericMethod GenericMethod {
- get { return generic; }
+ public Report Report {
+ get { return compiler.Report; }
}
public ToplevelBlock Container {
get { return Parent == null ? null : Parent.Toplevel; }
}
- public ToplevelBlock (Block parent, ParametersCompiled parameters, Location start) :
- this (parent, (Flags) 0, parameters, start)
+ public ToplevelBlock (CompilerContext ctx, Block parent, ParametersCompiled parameters, Location start) :
+ this (ctx, parent, (Flags) 0, parameters, start)
{
}
- public ToplevelBlock (Block parent, ParametersCompiled parameters, GenericMethod generic, Location start) :
- this (parent, parameters, start)
- {
- this.generic = generic;
- }
-
- public ToplevelBlock (ParametersCompiled parameters, Location start) :
- this (null, (Flags) 0, parameters, start)
+ public ToplevelBlock (CompilerContext ctx, ParametersCompiled parameters, Location start) :
+ this (ctx, null, (Flags) 0, parameters, start)
{
}
- ToplevelBlock (Flags flags, ParametersCompiled parameters, Location start) :
- this (null, flags, parameters, start)
+ ToplevelBlock (CompilerContext ctx, Flags flags, ParametersCompiled parameters, Location start) :
+ this (ctx, null, flags, parameters, start)
{
}
// We use 'Parent' to hook up to the containing block, but don't want to register the current block as a child.
// So, we use a two-stage setup -- first pass a null parent to the base constructor, and then override 'Parent'.
- public ToplevelBlock (Block parent, Flags flags, ParametersCompiled parameters, Location start) :
+ public ToplevelBlock (CompilerContext ctx, Block parent, Flags flags, ParametersCompiled parameters, Location start) :
base (null, flags, start, Location.Null)
{
+ this.compiler = ctx;
this.Toplevel = this;
this.parameters = parameters;
@@ -2727,8 +2590,8 @@ namespace Mono.CSharp {
ProcessParameters ();
}
- public ToplevelBlock (Location loc)
- : this (null, (Flags) 0, ParametersCompiled.EmptyReadOnlyParameters, loc)
+ public ToplevelBlock (CompilerContext ctx, Location loc)
+ : this (ctx, null, (Flags) 0, ParametersCompiled.EmptyReadOnlyParameters, loc)
{
}
@@ -2737,10 +2600,11 @@ namespace Mono.CSharp {
ToplevelBlock target = (ToplevelBlock) t;
base.CloneTo (clonectx, t);
- if (parameters.Count != 0)
- target.parameter_info = new ToplevelParameterInfo [parameters.Count];
- for (int i = 0; i < parameters.Count; ++i)
- target.parameter_info [i] = new ToplevelParameterInfo (target, i);
+ if (parameters.Count != 0) {
+ target.parameter_info = new ToplevelParameterInfo[parameters.Count];
+ for (int i = 0; i < parameters.Count; ++i)
+ target.parameter_info[i] = new ToplevelParameterInfo (target, i);
+ }
}
public bool CheckError158 (string name, Location loc)
@@ -2794,7 +2658,7 @@ namespace Mono.CSharp {
return true;
}
- public override Expression CreateExpressionTree (EmitContext ec)
+ public override Expression CreateExpressionTree (ResolveContext ec)
{
if (statements.Count == 1) {
Expression expr = ((Statement) statements[0]).CreateExpressionTree (ec);
@@ -2817,7 +2681,7 @@ namespace Mono.CSharp {
// Creates block with original statements
AddStatement (new IteratorStatement (iterator, new Block (this, source)));
- source.statements = new ArrayList (1);
+ source.statements = new List (1);
source.AddStatement (new Return (iterator, iterator.Location));
source.IsIterator = false;
@@ -2826,10 +2690,6 @@ namespace Mono.CSharp {
return iterator_storey;
}
- public FlowBranchingToplevel TopLevelBranching {
- get { return top_level_branching; }
- }
-
//
// Returns a parameter reference expression for the given name,
// or null if there is no such parameter
@@ -2837,6 +2697,9 @@ namespace Mono.CSharp {
public Expression GetParameterReference (string name, Location loc)
{
for (ToplevelBlock t = this; t != null; t = t.Container) {
+ if (t.parameters.IsEmpty)
+ continue;
+
Expression expr = t.GetParameterReferenceExpression (name, loc);
if (expr != null)
return expr;
@@ -2852,6 +2715,21 @@ namespace Mono.CSharp {
null : new ParameterReference (parameter_info [idx], loc);
}
+ public ToplevelBlock CheckParameterNameConflict (string name)
+ {
+ for (ToplevelBlock t = this; t != null; t = t.Container) {
+ if (t.HasParameterWithName (name))
+ return t;
+ }
+
+ return null;
+ }
+
+ protected virtual bool HasParameterWithName (string name)
+ {
+ return parameters.GetParameterIndexByName (name) >= 0;
+ }
+
//
// Returns the "this" instance variable of this block.
// See AddThisVariable() for more information.
@@ -2867,7 +2745,7 @@ namespace Mono.CSharp {
// analysis code to ensure that it's been fully initialized before control
// leaves the constructor.
//
- public LocalInfo AddThisVariable (DeclSpace ds, Location l)
+ public LocalInfo AddThisVariable (TypeContainer ds, Location l)
{
if (this_variable == null) {
this_variable = new LocalInfo (ds, this, l);
@@ -2885,19 +2763,73 @@ namespace Mono.CSharp {
set { flags = value ? flags | Flags.IsIterator : flags & ~Flags.IsIterator; }
}
- public bool IsThisAssigned (EmitContext ec)
- {
- return this_variable == null || this_variable.IsThisAssigned (ec);
+ //
+ // Block has been converted to expression tree
+ //
+ public bool IsExpressionTree {
+ get { return (flags & Flags.IsExpressionTree) != 0; }
}
- public bool ResolveMeta (EmitContext ec, ParametersCompiled ip)
+ public bool IsThisAssigned (BlockContext ec)
{
- int errors = Report.Errors;
- int orig_count = parameters.Count;
+ return this_variable == null || this_variable.IsThisAssigned (ec, this);
+ }
- if (top_level_branching != null)
+ public bool Resolve (FlowBranching parent, BlockContext rc, ParametersCompiled ip, IMethodData md)
+ {
+ if (resolved)
return true;
+ resolved = true;
+
+ if (rc.HasSet (ResolveContext.Options.ExpressionTreeConversion))
+ flags |= Flags.IsExpressionTree;
+
+ try {
+ if (!ResolveMeta (rc, ip))
+ return false;
+
+ using (rc.With (ResolveContext.Options.DoFlowAnalysis, true)) {
+ FlowBranchingToplevel top_level = rc.StartFlowBranching (this, parent);
+
+ if (!Resolve (rc))
+ return false;
+
+ unreachable = top_level.End ();
+ }
+ } catch (Exception e) {
+ if (e is CompletionResult || rc.Report.IsDisabled)
+ throw;
+
+ if (rc.CurrentBlock != null) {
+ rc.Report.Error (584, rc.CurrentBlock.StartLocation, "Internal compiler error: {0}", e.Message);
+ } else {
+ rc.Report.Error (587, "Internal compiler error: {0}", e.Message);
+ }
+
+ if (Report.DebugFlags > 0)
+ throw;
+ }
+
+ if (rc.ReturnType != TypeManager.void_type && !unreachable) {
+ if (rc.CurrentAnonymousMethod == null) {
+ rc.Report.Error (161, md.Location, "`{0}': not all code paths return a value", md.GetSignatureForError ());
+ return false;
+ } else if (!rc.CurrentAnonymousMethod.IsIterator) {
+ rc.Report.Error (1643, rc.CurrentAnonymousMethod.Location, "Not all code paths return a value in anonymous method of type `{0}'",
+ rc.CurrentAnonymousMethod.GetSignatureForError ());
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ bool ResolveMeta (BlockContext ec, ParametersCompiled ip)
+ {
+ int errors = ec.Report.Errors;
+ int orig_count = parameters.Count;
+
if (ip != null)
parameters = ip;
@@ -2920,9 +2852,7 @@ namespace Mono.CSharp {
ResolveMeta (ec, offset);
- top_level_branching = ec.StartFlowBranching (this);
-
- return Report.Errors == errors;
+ return ec.Report.Errors == errors;
}
//
@@ -2949,10 +2879,63 @@ namespace Mono.CSharp {
}
}
- public override void EmitMeta (EmitContext ec)
+ public override void Emit (EmitContext ec)
{
- parameters.ResolveVariable ();
+ if (Report.Errors > 0)
+ return;
+
+#if PRODUCTION
+ try {
+#endif
+ EmitMeta (ec);
+
+ if (ec.HasReturnLabel)
+ ec.ReturnLabel = ec.DefineLabel ();
+
+ base.Emit (ec);
+
+ ec.Mark (EndLocation);
+
+ if (ec.HasReturnLabel)
+ ec.MarkLabel (ec.ReturnLabel);
+
+ if (ec.return_value != null) {
+ ec.Emit (OpCodes.Ldloc, ec.return_value);
+ ec.Emit (OpCodes.Ret);
+ } else {
+ //
+ // If `HasReturnLabel' is set, then we already emitted a
+ // jump to the end of the method, so we must emit a `ret'
+ // there.
+ //
+ // Unfortunately, System.Reflection.Emit automatically emits
+ // a leave to the end of a finally block. This is a problem
+ // if no code is following the try/finally block since we may
+ // jump to a point after the end of the method.
+ // As a workaround, we're always creating a return label in
+ // this case.
+ //
+ if (ec.HasReturnLabel || !unreachable) {
+ if (ec.ReturnType != TypeManager.void_type)
+ ec.Emit (OpCodes.Ldloc, ec.TemporaryReturn ());
+ ec.Emit (OpCodes.Ret);
+ }
+ }
+
+#if PRODUCTION
+ } catch (Exception e){
+ Console.WriteLine ("Exception caught by the compiler while emitting:");
+ Console.WriteLine (" Block that caused the problem begin at: " + block.loc);
+
+ Console.WriteLine (e.GetType ().FullName + ": " + e.Message);
+ throw;
+ }
+#endif
+ }
+
+ public override void EmitMeta (EmitContext ec)
+ {
// Avoid declaring an IL variable for this_variable since it is not accessed
// from the generated IL
if (this_variable != null)
@@ -2968,12 +2951,6 @@ namespace Mono.CSharp {
base.EmitSymbolInfo (ec);
}
-
- public override void Emit (EmitContext ec)
- {
- base.Emit (ec);
- ec.Mark (EndLocation);
- }
}
public class SwitchLabel {
@@ -3016,7 +2993,7 @@ namespace Mono.CSharp {
public Label GetILLabel (EmitContext ec)
{
if (!il_label_set){
- il_label = ec.ig.DefineLabel ();
+ il_label = ec.DefineLabel ();
il_label_set = true;
}
return il_label;
@@ -3025,7 +3002,7 @@ namespace Mono.CSharp {
public Label GetILLabelCode (EmitContext ec)
{
if (!il_label_code_set){
- il_label_code = ec.ig.DefineLabel ();
+ il_label_code = ec.DefineLabel ();
il_label_code_set = true;
}
return il_label_code;
@@ -3035,7 +3012,7 @@ namespace Mono.CSharp {
// Resolves the expression, reduces it to a literal if possible
// and then converts it to the requested type.
//
- public bool ResolveAndReduce (EmitContext ec, Type required_type, bool allow_nullable)
+ public bool ResolveAndReduce (ResolveContext ec, TypeSpec required_type, bool allow_nullable)
{
Expression e = label.Resolve (ec);
@@ -3044,7 +3021,7 @@ namespace Mono.CSharp {
Constant c = e as Constant;
if (c == null){
- Report.Error (150, loc, "A constant value is expected");
+ ec.Report.Error (150, loc, "A constant value is expected");
return false;
}
@@ -3066,7 +3043,7 @@ namespace Mono.CSharp {
return true;
}
- public void Error_AlreadyOccurs (Type switch_type, SwitchLabel collision_with)
+ public void Error_AlreadyOccurs (ResolveContext ec, TypeSpec switch_type, SwitchLabel collision_with)
{
string label;
if (converted == null)
@@ -3076,8 +3053,8 @@ namespace Mono.CSharp {
else
label = converted.ToString ();
- Report.SymbolRelatedToPreviousError (collision_with.loc, null);
- Report.Error (152, loc, "The label `case {0}:' already occurs in this switch statement", label);
+ ec.Report.SymbolRelatedToPreviousError (collision_with.loc, null);
+ ec.Report.Error (152, loc, "The label `case {0}:' already occurs in this switch statement", label);
}
public SwitchLabel Clone (CloneContext clonectx)
@@ -3088,10 +3065,10 @@ namespace Mono.CSharp {
public class SwitchSection {
// An array of SwitchLabels.
- public readonly ArrayList Labels;
+ public readonly List Labels;
public readonly Block Block;
- public SwitchSection (ArrayList labels, Block block)
+ public SwitchSection (List labels, Block block)
{
Labels = labels;
Block = block;
@@ -3099,7 +3076,7 @@ namespace Mono.CSharp {
public SwitchSection Clone (CloneContext clonectx)
{
- ArrayList cloned_labels = new ArrayList ();
+ var cloned_labels = new List ();
foreach (SwitchLabel sl in cloned_labels)
cloned_labels.Add (sl.Clone (clonectx));
@@ -3109,18 +3086,18 @@ namespace Mono.CSharp {
}
public class Switch : Statement {
- public ArrayList Sections;
+ public List Sections;
public Expression Expr;
///
/// Maps constants whose type type SwitchType to their SwitchLabels.
///
- public IDictionary Elements;
+ public IDictionary