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 virtual ICode VisitTry(StmtTry s)
        {
            this.ThrowOnNoOverride();
            var @try = this.Visit(s.Try);
            List <StmtTry.Catch> catches = null;

            if (s.Catches != null)
            {
                foreach (var @catch in s.Catches)
                {
                    var stmt  = (Stmt)this.Visit(@catch.Stmt);
                    var exObj = (ExprVar)this.Visit(@catch.ExceptionVar);
                    if ((stmt != @catch.Stmt || exObj != @catch.ExceptionVar) && catches == null)
                    {
                        catches = new List <StmtTry.Catch>(s.Catches.TakeWhile(x => x != @catch));
                    }
                    if (catches != null)
                    {
                        catches.Add(new StmtTry.Catch(stmt, exObj));
                    }
                }
            }
            var @finally = this.Visit(s.Finally);

            if (@try != s.Try || catches != null || @finally != s.Finally)
            {
                return(new StmtTry(s.Ctx, (Stmt)@try, catches ?? s.Catches, (Stmt)@finally));
            }
            else
            {
                return(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);
 }
Exemple #4
0
        protected override ICode VisitTry(StmtTry s)
        {
            // 'try' part ends unpredicably, so cannot use any information
            // 'catch' part is called unpredictably, so cannot use any information
            // 'finally' part is always run, so can use all information
            this.knownTrue.Push(new List <Expr>());
            var @try = (Stmt)this.Visit(s.Try);

            this.knownTrue.Pop();
            var catches = this.HandleList(s.Catches, x => {
                this.knownTrue.Push(new List <Expr>());
                var @catch = (Stmt)this.Visit(x.Stmt);
                this.knownTrue.Pop();
                if (@catch != x.Stmt)
                {
                    return(new StmtTry.Catch(@catch, x.ExceptionVar));
                }
                else
                {
                    return(x);
                }
            });
            var @finally = (Stmt)this.Visit(s.Finally);

            if (@try != s.Try || catches != null || @finally != s.Finally)
            {
                return(new StmtTry(s.Ctx, @try, catches ?? s.Catches, @finally));
            }
            else
            {
                return(s);
            }
        }
 protected override ICode VisitTry(StmtTry s)
 {
     return(this.Isolate(() => base.VisitTry(s)));
 }
Exemple #6
0
        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);
            }
        }
        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));
        }