private ZTry VisitZTry(ZTry Try) { WriteStart("try"); this.VisitBlock(Try.Body); WriteLine("with"); WriteLine("{"); In(); for (int i = 0, n = Try.Catchers.Length; i < n; i++) this.VisitWith(Try.Catchers[i]); Out(); WriteLine("}"); return Try; }
private ZTry VisitZTry(ZTry Try) { Try.Body = this.VisitBlock(Try.Body); WithList newCatchers = new WithList(); for (int i = 0, n = Try.Catchers.Length; i < n; i++) newCatchers.Add(this.VisitWith(Try.Catchers[i])); Try.Catchers = newCatchers; return Try; }
private ZTry VisitZTry(ZTry Try) { BasicBlock testerChain = null; // // Build a sequence of basic blocks to test the thrown exception type // and dispatch it to the appropriate handler. Check first to see if // a default handler is provided. If not, we need to create one here // and fall through to it if no matching handler is found. // if (Try.Catchers.Length > 0 && Try.Catchers[Try.Catchers.Length - 1].Name != null) { // No default handler, so we need to put a default of our // own in place to rethrow the exception. If we have an // outer exception context in this method, then we can // simply transfer control there. Otherwise, we need to // emit a block to make the runtime pass it up the stack. BasicBlock defaultHandler = null; if (this.CurrentHandlerBlock != null) { // Empty block just transfers control to the outer handler defaultHandler = new BasicBlock(null, this.CurrentHandlerBlock); } else { defaultHandler = new BasicBlock(Templates.GetStatementTemplate("PropagateException")); defaultHandler.PropagatesException = true; } defaultHandler.MiddleOfTransition = true; defaultHandler.SkipNormalizer = true; AddBlock(defaultHandler); testerChain = defaultHandler; } // // We traverse the list of catchers in reverse order to make // sure the default "with" (if any) is handled first, as it's // guaranteed (by the parser) to be the last one in the list. // for (int i = Try.Catchers.Length - 1; i >= 0; i--) { With with = Try.Catchers[i]; this.PushContinuationStack(); this.Visit(with.Block); BasicBlock catchBody = this.PopContinuationStack(); if (!this.insideAtomicBlock) { // If we aren't inside an atomic block, then we need an extra block // between the tester and the body of the specific handler. All of // the blocks involved in testing the exception are connected in // an atomic way. If the handler isn't also going to be reached // atomically, then we need an extra block with a non-atomic link // to the body. BasicBlock bodyConnector = new BasicBlock(null, catchBody); AddBlock(bodyConnector); catchBody = bodyConnector; } BasicBlock catchTester = new BasicBlock(null); if (with.Name != null) { Expression catchTestExpr = Templates.GetExpressionTemplate("CatchTest"); Replacer.Replace(catchTestExpr, "_exception", (Expression)with.Name); catchTester.ConditionalExpression = catchTestExpr; catchTester.ConditionalTarget = catchBody; catchTester.UnconditionalTarget = testerChain; } else { // We're the default catch clause, so no test is necessary. catchTester.UnconditionalTarget = catchBody; } catchTester.SkipNormalizer = true; catchTester.MiddleOfTransition = true; AddBlock(catchTester); // We just linked the new tester to the front of the tester chain. // This tester becomes the new head. testerChain = catchTester; } // All of the catch handlers are in place. Add a statement to the first handler // to reset the current handler block. If there's an outer scope, we point there. // If not, we point to "None". if (testerChain == null) // could be null if all handlers had syntax errors return Try; testerChain.Statement = Templates.GetStatementTemplate("SetHandler"); if (CurrentHandlerBlock != null) { Replacer.Replace(testerChain.Statement, "_blockName", new Identifier(CurrentHandlerBlock.Name)); testerChain.handlerTarget = CurrentHandlerBlock; } else Replacer.Replace(testerChain.Statement, "_blockName", new Identifier("None")); // Now begin processing the body of the try block. Push the exception context // before starting. this.PushExceptionContext(testerChain); this.Visit(Try.Body); // Now create a basic block to establish the current handler as we enter the // body of the "try". Statement setHandlerStmt = Templates.GetStatementTemplate("SetHandler"); Replacer.Replace(setHandlerStmt, "_blockName", new Identifier(CurrentHandlerBlock.Name)); BasicBlock setHandler = new BasicBlock(setHandlerStmt, CurrentContinuation); setHandler.MiddleOfTransition = true; setHandler.SkipNormalizer = true; setHandler.handlerTarget = CurrentHandlerBlock; AddBlock(setHandler); CurrentContinuation = setHandler; this.PopExceptionContext(); return Try; }
private ZTry VisitZTry(ZTry Try) { if (Try == null) return null; ZTry result = (ZTry)Try.Clone(); result.Body = this.VisitBlock(Try.Body); result.Catchers = new WithList(); for (int i = 0, n = Try.Catchers.Length; i < n; i++) result.Catchers.Add(this.VisitWith(Try.Catchers[i])); return result; }
private ZTry VisitZTry(ZTry Try) { if (Try == null) return null; Try.Body = this.VisitBlock(Try.Body); for (int i = 0, n = Try.Catchers.Length; i < n; i++) Try.Catchers[i] = this.VisitWith(Try.Catchers[i]); return Try; }