Inheritance: Stmt, IInstructionMappable
 public DebugView(StmtTry s) {
     this.@try = s.@try;
     this.@catch = s.@catch;
     this.@finally = s.@finally;
     this.catchType = s.catchType;
     this.Try = s.Try;
     this.Catches = s.Catches;
     this.Finally = s.Finally;
 }
Exemple #2
0
 public DebugView(StmtTry s)
 {
     this.@try      = s.@try;
     this.@catch    = s.@catch;
     this.@finally  = s.@finally;
     this.catchType = s.catchType;
     this.Try       = s.Try;
     this.Catches   = s.Catches;
     this.Finally   = s.Finally;
 }
 protected override ICode VisitTry(StmtTry s) {
     var @try = this.RemoveContinuation(s.Try);
     if (@try != null) {
         if (s.Catches != null) {
             if (s.Catches.Count() != 1) {
                 throw new InvalidOperationException("Should only ever see 1 catch here");
             }
             var sCatch = s.Catches.First();
             var @catch = this.RemoveContinuation(sCatch.Stmt);
             if (@catch != null) {
                 if ((@try.Item2 == null || @catch.Item2 == null || @try.Item2 == @catch.Item2) && (@try.Item2 != null || @catch.Item2 != null)) {
                     var newTry = new StmtTry(s.Ctx, @try.Item1, new[] { new StmtTry.Catch(@catch.Item1, sCatch.ExceptionVar) }, null);
                     var newCont = new StmtContinuation(s.Ctx, @try.Item2 ?? @catch.Item2, false);
                     return new StmtBlock(s.Ctx, newTry, newCont);
                 }
             }
             // Special case
             // When 'leave' CIL branch to different instructions, allow specific code to be
             // moved inside the 'try' or 'catch' block. It should be impossible for this code to throw an exception
             var tryTos = VisitorFindContinuations.Get(@try.Item2);
             if (tryTos.Count() == 1 && tryTos.First().To == @catch.Item2 && @try.Item2.StmtType == Stmt.NodeType.Block) {
                 var try2Stmts = ((StmtBlock)@try.Item2).Statements.ToArray();
                 var s0 = try2Stmts.Take(try2Stmts.Length - 1);
                 if (s0.All(x => x.StmtType == Stmt.NodeType.Assignment)) {
                     var sN = try2Stmts.Last();
                     if (sN.StmtType == Stmt.NodeType.Continuation) {
                         var newTry = new StmtTry(s.Ctx,
                             new StmtBlock(s.Ctx, @try.Item1, new StmtBlock(s.Ctx, s0), new StmtContinuation(s.Ctx, ((StmtContinuation)sN).To, true)),
                             s.Catches, null);
                         return newTry;
                     }
                 }
             }
         }
         if (s.Finally != null) {
             var @finally = this.RemoveContinuation(s.Finally);
             if (@finally != null) {
                 if ((@try.Item2 == null || @finally.Item2 == null || @try.Item2 == @finally.Item2) && (@try.Item2 != null || @finally.Item2 != null)) {
                     var newTry = new StmtTry(s.Ctx, @try.Item1, null, @finally.Item1);
                     var newCont = new StmtContinuation(s.Ctx, @try.Item2 ?? @finally.Item2, false);
                     return new StmtBlock(s.Ctx, newTry, newCont);
                 }
             }
         }
         // TODO: This is a hack for badly handling fault handlers. They are ignored at the moment
         if (s.Catches == null && s.Finally == null) {
             var cont = @try.Item2 == null ? null : new StmtContinuation(s.Ctx, @try.Item2, false);
             return new StmtBlock(s.Ctx, @try.Item1, cont);
         }
     }
     return base.VisitTry(s);
 }
 protected override ICode VisitTry(StmtTry s) {
     this.NewLine();
     this.js.Append("try {");
     this.indent++;
     this.Visit(s.Try);
     this.indent--;
     foreach (var @catch in s.Catches.EmptyIfNull()) {
         // TODO: Implement full exception processing (need some runtime type information to be able to do this)
         if (!(@catch.ExceptionVar.Type.IsObject() || @catch.ExceptionVar.Type.IsException())) {
             throw new NotImplementedException("Cannot yet handle 'catch' of type: " + @catch.ExceptionVar.Type.Name);
         }
         this.NewLine();
         this.js.Append("} catch(");
         this.Visit(@catch.ExceptionVar);
         this.js.Append(") {");
         this.indent++;
         this.Visit(@catch.Stmt);
         this.indent--;
     }
     if (s.Finally != null) {
         this.NewLine();
         this.js.Append("} finally {");
         this.indent++;
         this.Visit(s.Finally);
         this.indent--;
     }
     this.NewLine();
     this.js.Append("}");
     return s;
 }
 protected override ICode VisitTry(StmtTry s) {
     return this.Isolate(() => base.VisitTry(s));
 }
 protected override ICode VisitTry(StmtTry s) {
     this.NewLine();
     this.code.Append("try {");
     this.indent++;
     this.Visit(s.Try);
     this.indent--;
     foreach (var @catch in s.Catches.EmptyIfNull()) {
         this.NewLine();
         this.code.Append("} catch (");
         this.Visit(@catch.ExceptionVar);
         this.code.Append(") {");
         this.indent++;
         this.Visit(@catch.Stmt);
         this.indent--;
     }
     if (s.Finally != null) {
         this.NewLine();
         this.code.Append("} finally {");
         this.indent++;
         this.Visit(s.Finally);
         this.indent--;
     }
     this.NewLine();
     this.code.Append("}");
     return s;
 }
 private void CreatePart(IEnumerable<Instruction> insts, IEnumerable<ExceptionHandler> exs) {
     var stmtStart = insts.First();
     var end = insts.Last();
     var inst = insts.First();
     for (; ; ) {
         // Get the outermost 'try' statement starting on this instruction, if there is one
         var ex = exs.Where(x => x.TryStart == inst).OrderByDescending(x => x.HandlerEnd.Offset).FirstOrDefault();
         if (ex != null) {
             if (inst != stmtStart) {
                 // Build preceding code block up until this 'try' statement
                 this.BuildBlock(stmtStart.GetRange(inst.Previous), end.Next);
             }
             // Build this 'try' statement
             var tryExs = exs.Where(x => x.TryStart.Offset >= ex.TryStart.Offset && x.TryEnd.Offset < ex.TryEnd.Offset).ToArray();
             this.CreatePart(ex.TryStart.GetRange(ex.TryEnd.Previous), tryExs);
             // Build the 'catch' or 'finally' handler statement
             var handlerExs = exs.Where(x => x.TryStart.Offset >= ex.HandlerStart.Offset && x.TryEnd.Offset < ex.HandlerEnd.Offset).ToArray();
             this.CreatePart(ex.HandlerStart.GetRange(ex.HandlerEnd.Previous), handlerExs);
             StmtTry tryStmt;
             switch (ex.HandlerType) {
             case ExceptionHandlerType.Catch:
                 tryStmt = new StmtTry(this.ctx, ex.TryStart, ex.HandlerStart, null, ex.CatchType);
                 break;
             case ExceptionHandlerType.Finally:
                 tryStmt = new StmtTry(this.ctx, ex.TryStart, null, ex.HandlerStart, null);
                 break;
             case ExceptionHandlerType.Fault: // TODO: Handle this properly, can emulate with 2 try statements
                 tryStmt = new StmtTry(this.ctx, ex.TryStart, null, null, null); // INCORRECT
                 break;
             default:
                 throw new NotImplementedException("Cannot handle handler-type: " + ex.HandlerType);
             }
             if (tryStmt != null) {
                 this.mappable.Add(tryStmt);
                 // Put all 'try' statements in outer-first order. CIL will be at the end of the list
                 this.blockMap[inst].Insert(0, tryStmt);
             }
             stmtStart = ex.HandlerEnd;
             inst = ex.HandlerEnd.Previous;
         }
         if (inst == null || inst == end) {
             break;
         }
         inst = inst.Next;
     }
     if (stmtStart.Offset <= end.Offset) {
         // Build the final statement
         this.BuildBlock(stmtStart.GetRange(end), end.Next);
     }
 }