📄 statement.cs
字号:
//// statement.cs: Statement representation for the IL tree.//// Author:// Miguel de Icaza (miguel@ximian.com)// Martin Baulig (martin@ximian.com)//// (C) 2001, 2002, 2003 Ximian, Inc.// (C) 2003, 2004 Novell, Inc.//using System;using System.Text;using System.Reflection;using System.Reflection.Emit;using System.Diagnostics;using System.Collections;using System.Collections.Specialized;namespace Mono.CSharp { public abstract class Statement { public Location loc; /// <summary> /// Resolves the statement, true means that all sub-statements /// did resolve ok. // </summary> public virtual bool Resolve (EmitContext ec) { return true; } /// <summary> /// We already know that the statement is unreachable, but we still /// need to resolve it to catch errors. /// </summary> public virtual bool ResolveUnreachable (EmitContext ec, bool warn) { // // This conflicts with csc's way of doing this, but IMHO it's // the right thing to do. // // If something is unreachable, we still check whether it's // correct. This means that you cannot use unassigned variables // in unreachable code, for instance. // if (warn && (RootContext.WarningLevel >= 2)) Report.Warning (162, loc, "Unreachable code detected"); ec.StartFlowBranching (FlowBranching.BranchingType.Block, loc); bool ok = Resolve (ec); ec.KillFlowBranching (); return ok; } /// <summary> /// Return value indicates whether all code paths emitted return. /// </summary> protected abstract void DoEmit (EmitContext ec); /// <summary> /// Utility wrapper routine for Error, just to beautify the code /// </summary> 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); } /// <summary> /// Return value indicates whether all code paths emitted return. /// </summary> public virtual void Emit (EmitContext ec) { ec.Mark (loc, true); DoEmit (ec); } } public sealed class EmptyStatement : Statement { private EmptyStatement () {} public static readonly EmptyStatement Value = new EmptyStatement (); public override bool Resolve (EmitContext ec) { return true; } protected override void DoEmit (EmitContext ec) { } } public class If : Statement { Expression expr; public Statement TrueStatement; public Statement FalseStatement; bool is_true_ret; public If (Expression expr, Statement trueStatement, Location l) { this.expr = expr; TrueStatement = trueStatement; loc = l; } public If (Expression expr, Statement trueStatement, Statement falseStatement, Location l) { this.expr = expr; TrueStatement = trueStatement; FalseStatement = falseStatement; loc = l; } public override bool Resolve (EmitContext ec) { bool ok = true; Report.Debug (1, "START IF BLOCK", loc); expr = Expression.ResolveBoolean (ec, expr, loc); 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 = ?"); } // // Dead code elimination // if (expr is BoolConstant){ bool take = ((BoolConstant) expr).Value; 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.Resolve (ec)) return false; } return true; } skip: ec.StartFlowBranching (FlowBranching.BranchingType.Conditional, loc); ok &= TrueStatement.Resolve (ec); is_true_ret = ec.CurrentBranching.CurrentUsageVector.Reachability.IsUnreachable; ec.CurrentBranching.CreateSibling (); if (FalseStatement != null) ok &= FalseStatement.Resolve (ec); ec.EndFlowBranching (); Report.Debug (1, "END IF BLOCK", loc); return ok; } protected override void DoEmit (EmitContext ec) { ILGenerator ig = ec.ig; Label false_target = ig.DefineLabel (); Label end; // // If we're a boolean expression, Resolve() already // eliminated dead code for us. // if (expr is BoolConstant){ bool take = ((BoolConstant) expr).Value; if (take) TrueStatement.Emit (ec); else if (FalseStatement != null) FalseStatement.Emit (ec); return; } expr.EmitBranchable (ec, false_target, false); TrueStatement.Emit (ec); if (FalseStatement != null){ bool branch_emitted = false; end = ig.DefineLabel (); if (!is_true_ret){ ig.Emit (OpCodes.Br, end); branch_emitted = true; } ig.MarkLabel (false_target); FalseStatement.Emit (ec); if (branch_emitted) ig.MarkLabel (end); } else { ig.MarkLabel (false_target); } } } public class Do : Statement { public Expression expr; public readonly Statement EmbeddedStatement; bool infinite; public Do (Statement statement, Expression boolExpr, Location l) { expr = boolExpr; EmbeddedStatement = statement; loc = l; } public override bool Resolve (EmitContext ec) { bool ok = true; ec.StartFlowBranching (FlowBranching.BranchingType.Loop, loc); if (!EmbeddedStatement.Resolve (ec)) ok = false; expr = Expression.ResolveBoolean (ec, expr, loc); if (expr == null) ok = false; else if (expr is BoolConstant){ bool res = ((BoolConstant) expr).Value; if (res) infinite = true; } ec.CurrentBranching.Infinite = infinite; ec.EndFlowBranching (); return ok; } protected override void DoEmit (EmitContext ec) { ILGenerator ig = ec.ig; Label loop = ig.DefineLabel (); Label old_begin = ec.LoopBegin; Label old_end = ec.LoopEnd; ec.LoopBegin = ig.DefineLabel (); ec.LoopEnd = ig.DefineLabel (); ig.MarkLabel (loop); EmbeddedStatement.Emit (ec); ig.MarkLabel (ec.LoopBegin); // // Dead code elimination // if (expr is BoolConstant){ bool res = ((BoolConstant) expr).Value; if (res) ec.ig.Emit (OpCodes.Br, loop); } else expr.EmitBranchable (ec, loop, true); ig.MarkLabel (ec.LoopEnd); ec.LoopBegin = old_begin; ec.LoopEnd = old_end; } } public class While : Statement { public Expression expr; public readonly Statement Statement; bool infinite, empty; public While (Expression boolExpr, Statement statement, Location l) { this.expr = boolExpr; Statement = statement; loc = l; } public override bool Resolve (EmitContext ec) { bool ok = true; expr = Expression.ResolveBoolean (ec, expr, loc); if (expr == null) return false; // // Inform whether we are infinite or not // if (expr is BoolConstant){ BoolConstant bc = (BoolConstant) expr; if (bc.Value == false){ if (!Statement.ResolveUnreachable (ec, true)) return false; empty = true; return true; } else infinite = true; } ec.StartFlowBranching (FlowBranching.BranchingType.Loop, loc); if (!infinite) ec.CurrentBranching.CreateSibling (); if (!Statement.Resolve (ec)) ok = false; ec.CurrentBranching.Infinite = infinite; ec.EndFlowBranching (); return ok; } protected override void DoEmit (EmitContext ec) { if (empty) return; ILGenerator ig = ec.ig; Label old_begin = ec.LoopBegin; Label old_end = ec.LoopEnd; ec.LoopBegin = ig.DefineLabel (); ec.LoopEnd = ig.DefineLabel (); // // Inform whether we are infinite or not // if (expr is BoolConstant){ ig.MarkLabel (ec.LoopBegin); Statement.Emit (ec); ig.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); } else { Label while_loop = ig.DefineLabel (); ig.Emit (OpCodes.Br, ec.LoopBegin); ig.MarkLabel (while_loop); Statement.Emit (ec); ig.MarkLabel (ec.LoopBegin); expr.EmitBranchable (ec, while_loop, true); ig.MarkLabel (ec.LoopEnd); } ec.LoopBegin = old_begin; ec.LoopEnd = old_end; } } public class For : Statement { Expression Test; readonly Statement InitStatement; readonly Statement Increment; public readonly Statement Statement; bool infinite, empty; public For (Statement initStatement, Expression test, Statement increment, Statement statement, Location l) { InitStatement = initStatement; Test = test; Increment = increment; Statement = statement; loc = l; } public override bool Resolve (EmitContext ec) { bool ok = true; if (InitStatement != null){ if (!InitStatement.Resolve (ec)) ok = false; } if (Test != null){ Test = Expression.ResolveBoolean (ec, Test, loc); if (Test == null) ok = false; else if (Test is BoolConstant){ BoolConstant bc = (BoolConstant) Test; if (bc.Value == false){ if (!Statement.ResolveUnreachable (ec, true)) return false; if ((Increment != null) && !Increment.ResolveUnreachable (ec, false)) return false; empty = true; return true; } else infinite = true; } } else infinite = true; ec.StartFlowBranching (FlowBranching.BranchingType.Loop, loc); if (!infinite) ec.CurrentBranching.CreateSibling (); if (!Statement.Resolve (ec)) ok = false; if (Increment != null){ if (!Increment.Resolve (ec)) ok = false; } ec.CurrentBranching.Infinite = infinite; ec.EndFlowBranching (); return ok; } protected override void DoEmit (EmitContext ec) { if (empty) return; ILGenerator ig = ec.ig; Label old_begin = ec.LoopBegin; Label old_end = ec.LoopEnd; Label loop = ig.DefineLabel (); Label test = ig.DefineLabel (); if (InitStatement != null && InitStatement != EmptyStatement.Value) InitStatement.Emit (ec); ec.LoopBegin = ig.DefineLabel (); ec.LoopEnd = ig.DefineLabel (); ig.Emit (OpCodes.Br, test); ig.MarkLabel (loop); Statement.Emit (ec); ig.MarkLabel (ec.LoopBegin); if (Increment != EmptyStatement.Value) Increment.Emit (ec); ig.MarkLabel (test); // // If test is null, there is no test, and we are just // an infinite loop // if (Test != null){ // // The Resolve code already catches the case for // Test == BoolConstant (false) so we know that // this is true // if (Test is BoolConstant) ig.Emit (OpCodes.Br, loop); else Test.EmitBranchable (ec, loop, true); } else ig.Emit (OpCodes.Br, loop); ig.MarkLabel (ec.LoopEnd); ec.LoopBegin = old_begin; ec.LoopEnd = old_end; } } public class StatementExpression : Statement { ExpressionStatement expr; public StatementExpression (ExpressionStatement expr) { this.expr = expr; loc = expr.Location; } public override bool Resolve (EmitContext ec) { if (expr != null) expr = expr.ResolveStatement (ec); return expr != null; } protected override void DoEmit (EmitContext ec) { expr.EmitStatement (ec); } public override string ToString () { return "StatementExpression (" + expr + ")"; } } /// <summary> /// Implements the return statement /// </summary> public class Return : Statement { public Expression Expr;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -