📄 statement.cs
字号:
public Return (Expression expr, Location l) { Expr = expr; loc = l; } bool in_exc; public override bool Resolve (EmitContext ec) { AnonymousContainer am = ec.CurrentAnonymousMethod; if ((am != null) && am.IsIterator && ec.InIterator) { 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"); return false; } if (ec.ReturnType == null){ if (Expr != null){ if (ec.CurrentAnonymousMethod != null){ Report.Error (1662, loc, "Cannot convert anonymous method block to delegate type `{0}' because some of the return types in the block are not implicitly convertible to the delegate return type", ec.CurrentAnonymousMethod.GetSignatureForError ()); } Error (127, "A return keyword must not be followed by any expression when method returns void"); return false; } } else { if (Expr == null){ Error (126, "An object of a type convertible to `{0}' is required " + "for the return statement", TypeManager.CSharpName (ec.ReturnType)); return false; } Expr = Expr.Resolve (ec); if (Expr == null) return false; if (Expr.Type != ec.ReturnType) { Expr = Convert.ImplicitConversionRequired ( ec, Expr, ec.ReturnType, loc); if (Expr == null) return false; } } FlowBranching.UsageVector vector = ec.CurrentBranching.CurrentUsageVector; if (ec.CurrentBranching.InTryOrCatch (true)) { ec.CurrentBranching.AddFinallyVector (vector); in_exc = true; } else if (ec.InFinally) { Error (157, "Control cannot leave the body of a finally clause"); return false; } else vector.CheckOutParameters (ec.CurrentBranching); if (in_exc) ec.NeedReturnLabel (); ec.CurrentBranching.CurrentUsageVector.Return (); return true; } protected override void DoEmit (EmitContext ec) { if (Expr != null) { Expr.Emit (ec); if (in_exc) ec.ig.Emit (OpCodes.Stloc, ec.TemporaryReturn ()); } if (in_exc) ec.ig.Emit (OpCodes.Leave, ec.ReturnLabel); else ec.ig.Emit (OpCodes.Ret); } } public class Goto : Statement { string target; LabeledStatement label; public override bool Resolve (EmitContext ec) { label = ec.CurrentBranching.LookupLabel (target, loc); if (label == null) return false; // If this is a forward goto. if (!label.IsDefined) label.AddUsageVector (ec.CurrentBranching.CurrentUsageVector); ec.CurrentBranching.CurrentUsageVector.Goto (); label.AddReference (); return true; } public Goto (string label, Location l) { loc = l; target = label; } public string Target { get { return target; } } protected override void DoEmit (EmitContext ec) { Label l = label.LabelTarget (ec); ec.ig.Emit (OpCodes.Br, l); } } public class LabeledStatement : Statement { bool defined; bool referenced; Label label; ILGenerator ig; FlowBranching.UsageVector vectors; public LabeledStatement (string label_name, Location l) { this.loc = l; } public Label LabelTarget (EmitContext ec) { if (defined) return label; ig = ec.ig; label = ec.ig.DefineLabel (); defined = true; return label; } public bool IsDefined { get { return defined; } } public bool HasBeenReferenced { get { return referenced; } } public void AddUsageVector (FlowBranching.UsageVector vector) { vector = vector.Clone (); vector.Next = vectors; vectors = vector; } public override bool Resolve (EmitContext ec) { ec.CurrentBranching.Label (vectors); return true; } protected override void DoEmit (EmitContext ec) { if (ig != null && ig != ec.ig) { // TODO: location is wrong Report.Error (1632, loc, "Control cannot leave the body of an anonymous method"); return; } LabelTarget (ec); ec.ig.MarkLabel (label); } public void AddReference () { referenced = true; } } /// <summary> /// `goto default' statement /// </summary> public class GotoDefault : Statement { public GotoDefault (Location l) { loc = l; } public override bool Resolve (EmitContext 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.GotDefault){ Report.Error (159, loc, "No such label `default:' within the scope of the goto statement"); return; } ec.ig.Emit (OpCodes.Br, ec.Switch.DefaultTarget); } } /// <summary> /// `goto case' statement /// </summary> public class GotoCase : Statement { Expression expr; SwitchLabel sl; public GotoCase (Expression e, Location l) { expr = e; loc = l; } public override bool Resolve (EmitContext ec) { if (ec.Switch == null){ Report.Error (153, loc, "A goto case is only valid inside a switch statement"); return false; } expr = expr.Resolve (ec); if (expr == null) return false; Constant c = expr as Constant; if (c == null) { Error (150, "A constant value is expected"); return false; } c = c.ToType (ec.Switch.SwitchType, loc); if (c == null) return false; object val = c.GetValue (); if (val == null) val = SwitchLabel.NullStringCase; sl = (SwitchLabel) ec.Switch.Elements [val]; if (sl == null){ Report.Error (159, loc, "No such label `case {0}:' within the scope of the goto statement", c.GetValue () == null ? "null" : val); return false; } ec.CurrentBranching.CurrentUsageVector.Goto (); return true; } protected override void DoEmit (EmitContext ec) { ec.ig.Emit (OpCodes.Br, sl.GetILLabelCode (ec)); } } public class Throw : Statement { Expression expr; public Throw (Expression expr, Location l) { this.expr = expr; loc = l; } public override bool Resolve (EmitContext ec) { ec.CurrentBranching.CurrentUsageVector.Throw (); if (expr != null){ expr = expr.Resolve (ec); if (expr == null) return false; ExprClass eclass = expr.eclass; if (!(eclass == ExprClass.Variable || eclass == ExprClass.PropertyAccess || eclass == ExprClass.Value || eclass == ExprClass.IndexerAccess)) { expr.Error_UnexpectedKind (ec, "value, variable, property or indexer access ", loc); return false; } Type t = expr.Type; if ((t != TypeManager.exception_type) && !t.IsSubclassOf (TypeManager.exception_type) && !(expr is NullLiteral)) { Error (155, "The type caught or thrown must be derived " + "from System.Exception"); return false; } return true; } if (!ec.InCatch) { Error (156, "A throw statement with no arguments is not allowed outside of a catch clause"); return false; } if (ec.InFinally) { Error (724, "A throw statement with no arguments is not allowed inside of a finally clause nested inside of the innermost catch clause"); return false; } return true; } protected override void DoEmit (EmitContext ec) { if (expr == null) ec.ig.Emit (OpCodes.Rethrow); else { expr.Emit (ec); ec.ig.Emit (OpCodes.Throw); } } } public class Break : Statement { public Break (Location l) { loc = l; } bool crossing_exc; public override bool Resolve (EmitContext ec) { if (!ec.CurrentBranching.InLoop () && !ec.CurrentBranching.InSwitch ()){ Error (139, "No enclosing loop out of which to break or continue"); return false; } else if (ec.InFinally && ec.CurrentBranching.BreakCrossesTryCatchBoundary()) { Error (157, "Control cannot leave the body of a finally clause"); return false; } else if (ec.CurrentBranching.InTryOrCatch (false)) ec.CurrentBranching.AddFinallyVector ( ec.CurrentBranching.CurrentUsageVector); else if (ec.CurrentBranching.InLoop () || ec.CurrentBranching.InSwitch ()) ec.CurrentBranching.AddBreakVector ( ec.CurrentBranching.CurrentUsageVector); crossing_exc = ec.CurrentBranching.BreakCrossesTryCatchBoundary (); if (!crossing_exc) ec.NeedReturnLabel (); ec.CurrentBranching.CurrentUsageVector.Break (); return true; } protected override void DoEmit (EmitContext ec) { ILGenerator ig = ec.ig; if (crossing_exc) ig.Emit (OpCodes.Leave, ec.LoopEnd); else { ig.Emit (OpCodes.Br, ec.LoopEnd); } } } public class Continue : Statement { public Continue (Location l) { loc = l; } bool crossing_exc; public override bool Resolve (EmitContext ec) { if (!ec.CurrentBranching.InLoop ()){ Error (139, "No enclosing loop out of which to break or continue"); return false; } else if (ec.InFinally) { Error (157, "Control cannot leave the body of a finally clause"); return false; } else if (ec.CurrentBranching.InTryOrCatch (false)) ec.CurrentBranching.AddFinallyVector (ec.CurrentBranching.CurrentUsageVector); crossing_exc = ec.CurrentBranching.BreakCrossesTryCatchBoundary (); ec.CurrentBranching.CurrentUsageVector.Goto (); return true; } protected override void DoEmit (EmitContext ec) { Label begin = ec.LoopBegin; if (crossing_exc) ec.ig.Emit (OpCodes.Leave, begin); else ec.ig.Emit (OpCodes.Br, begin); } } // // The information about a user-perceived local variable // public class LocalInfo { public Expression Type; // // Most of the time a variable will be stored in a LocalBuilder // // But sometimes, it will be stored in a field (variables that have been // hoisted by iterators or by anonymous methods). The context of the field will // be stored in the EmitContext // // public LocalBuilder LocalBuilder; public FieldBuilder FieldBuilder; public Type VariableType; public readonly string Name; public readonly Location Location; public readonly Block Block; public VariableInfo VariableInfo; enum Flags : byte { Used = 1, ReadOnly = 2, Pinned = 4, IsThis = 8, Captured = 16, AddressTaken = 32, CompilerGenerated = 64 } public enum ReadOnlyContext: byte { Using, Foreach, Fixed } Flags flags; ReadOnlyContext ro_context; public LocalInfo (Expression type, string name, Block block, Location l) { Type = type; Name = name; Block = block; Location = l; } public LocalInfo (TypeContainer tc, Block block, Location l) { VariableType = tc.TypeBuilder; Block = block; Location = l; } public bool IsThisAssigned (EmitContext ec, Location loc) { if (VariableInfo == null) throw new Exception (); if (!ec.DoFlowAnalysis || ec.CurrentBranching.IsAssigned (VariableInfo)) return true; return VariableInfo.TypeInfo.IsFullyInitialized (ec.CurrentBranching, VariableInfo, loc); } public bool IsAssigned (EmitContext ec) { if (VariableInfo == null) throw new Exception (); return !ec.DoFlowAnalysis || ec.CurrentBranching.IsAssigned (VariableInfo); } public bool Resolve (EmitContext ec) { if (VariableType == null) { TypeExpr texpr = Type.ResolveAsTypeTerminal (ec, false); if (texpr == null) return false; VariableType = texpr.ResolveType (ec); } if (VariableType == TypeManager.void_type) { Report.Error (1547, Location, "Keyword 'void' cannot be used in this context"); return false; } if (VariableType.IsAbstract && VariableType.IsSealed) { Report.Error (723, Location, "Cannot declare variable of static type `{0}'", TypeManager.CSharpName (VariableType)); return false; } if (VariableType.IsPointer && !ec.InUnsafe) Expression.UnsafeError (Location); return true; } public bool IsCaptured { get { return (flags & Flags.Captured) != 0; } set { flags |= Flags.Captured; } } public bool AddressTaken { get { return (flags & Flags.AddressTaken) != 0; } set { flags |= Flags.AddressTaken; } } public bool CompilerGenerated { get { return (flags & Flags.CompilerGenerated) != 0; } set { flags |= Flags.CompilerGenerated;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -