mirror of https://github.com/icsharpcode/ILSpy.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
138 lines
4.8 KiB
138 lines
4.8 KiB
// Copyright (c) 2014 Daniel Grunwald |
|
// |
|
// Permission is hereby granted, free of charge, to any person obtaining a copy of this |
|
// software and associated documentation files (the "Software"), to deal in the Software |
|
// without restriction, including without limitation the rights to use, copy, modify, merge, |
|
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons |
|
// to whom the Software is furnished to do so, subject to the following conditions: |
|
// |
|
// The above copyright notice and this permission notice shall be included in all copies or |
|
// substantial portions of the Software. |
|
// |
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, |
|
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR |
|
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE |
|
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR |
|
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
|
// DEALINGS IN THE SOFTWARE. |
|
|
|
using ICSharpCode.Decompiler.IL; |
|
using ICSharpCode.NRefactory.CSharp; |
|
using ICSharpCode.NRefactory.TypeSystem; |
|
using System; |
|
using System.Collections.Generic; |
|
using System.Linq; |
|
using System.Text; |
|
using System.Threading.Tasks; |
|
|
|
namespace ICSharpCode.Decompiler.CSharp |
|
{ |
|
class StatementBuilder : ILVisitor<Statement> |
|
{ |
|
readonly ExpressionBuilder exprBuilder; |
|
|
|
public StatementBuilder(ICompilation compilation) |
|
{ |
|
this.exprBuilder = new ExpressionBuilder(compilation); |
|
} |
|
|
|
public Statement Convert(ILInstruction inst) |
|
{ |
|
return inst.AcceptVisitor(this); |
|
} |
|
|
|
public BlockStatement ConvertAsBlock(ILInstruction inst) |
|
{ |
|
Statement stmt = Convert(inst); |
|
return stmt as BlockStatement ?? new BlockStatement { stmt }; |
|
} |
|
|
|
protected override Statement Default(ILInstruction inst) |
|
{ |
|
return new ExpressionStatement(exprBuilder.Convert(inst)); |
|
} |
|
|
|
protected internal override Statement VisitIfInstruction(IfInstruction inst) |
|
{ |
|
var condition = exprBuilder.ConvertCondition(inst.Condition); |
|
var trueStatement = Convert(inst.TrueInst); |
|
var falseStatement = inst.FalseInst.OpCode == OpCode.Nop ? null : Convert(inst.FalseInst); |
|
return new IfElseStatement(condition, trueStatement, falseStatement); |
|
} |
|
|
|
protected internal override Statement VisitBranch(Branch inst) |
|
{ |
|
return new GotoStatement(inst.TargetLabel); |
|
} |
|
|
|
protected internal override Statement VisitThrow(Throw inst) |
|
{ |
|
return new ThrowStatement(exprBuilder.Convert(inst.Argument)); |
|
} |
|
|
|
protected internal override Statement VisitReturn(Return inst) |
|
{ |
|
if (inst.ReturnValue == null) |
|
return new ReturnStatement(); |
|
return new ReturnStatement(exprBuilder.Convert(inst.ReturnValue)); |
|
} |
|
|
|
TryCatchStatement MakeTryCatch(ILInstruction tryBlock) |
|
{ |
|
var tryBlockConverted = Convert(tryBlock); |
|
var tryCatch = tryBlockConverted as TryCatchStatement; |
|
if (tryCatch != null && tryCatch.FinallyBlock.IsNull) |
|
return tryCatch; // extend existing try-catch |
|
tryCatch = new TryCatchStatement(); |
|
tryCatch.TryBlock = tryBlockConverted as BlockStatement ?? new BlockStatement { tryBlockConverted }; |
|
return tryCatch; |
|
} |
|
|
|
protected internal override Statement VisitTryCatch(TryCatch inst) |
|
{ |
|
var tryCatch = new TryCatchStatement(); |
|
tryCatch.TryBlock = ConvertAsBlock(inst.TryBlock); |
|
foreach (var handler in inst.CatchHandlers) { |
|
var catchClause = new CatchClause(); |
|
if (handler.Variable != null) { |
|
catchClause.Type = exprBuilder.ConvertType(handler.Variable.Type); |
|
catchClause.VariableName = handler.Variable.Name; |
|
} |
|
catchClause.Condition = exprBuilder.ConvertCondition(handler.Filter); |
|
catchClause.Body = ConvertAsBlock(handler.Body); |
|
tryCatch.CatchClauses.Add(catchClause); |
|
} |
|
return tryCatch; |
|
} |
|
|
|
protected internal override Statement VisitTryFinally(TryFinally inst) |
|
{ |
|
var tryCatch = MakeTryCatch(inst.TryBlock); |
|
tryCatch.FinallyBlock = ConvertAsBlock(inst.FinallyBlock); |
|
return tryCatch; |
|
} |
|
|
|
protected internal override Statement VisitTryFault(TryFault inst) |
|
{ |
|
var tryCatch = new TryCatchStatement(); |
|
tryCatch.TryBlock = ConvertAsBlock(inst.TryBlock); |
|
var faultBlock = ConvertAsBlock(inst.FaultBlock); |
|
faultBlock.InsertChildAfter(null, new Comment("try-fault"), Roles.Comment); |
|
faultBlock.Add(new ThrowStatement()); |
|
tryCatch.CatchClauses.Add(new CatchClause { Body = faultBlock }); |
|
return tryCatch; |
|
} |
|
|
|
protected internal override Statement VisitBlockContainer(BlockContainer container) |
|
{ |
|
BlockStatement blockStatement = new BlockStatement(); |
|
foreach (var block in container.Blocks) { |
|
blockStatement.Add(new LabelStatement { Label = block.Label }); |
|
foreach (var inst in block.Instructions) { |
|
blockStatement.Add(Convert(inst)); |
|
} |
|
} |
|
return blockStatement; |
|
} |
|
} |
|
}
|
|
|