Rhino.Ast.Jump.SetFinally C# (CSharp) Method

SetFinally() public method

public SetFinally ( Node finallyTarget ) : void
finallyTarget Node
return void
		public virtual void SetFinally(Node finallyTarget)
		{
			if (type != Token.TRY)
			{
				CodeBug();
			}
			if (finallyTarget.GetType() != Token.TARGET)
			{
				CodeBug();
			}
			if (target2 != null)
			{
				CodeBug();
			}
			//only once
			target2 = finallyTarget;
		}

Usage Example

Example #1
0
		/// <summary>
		/// Try/Catch/Finally
		/// The IRFactory tries to express as much as possible in the tree;
		/// the responsibilities remaining for Codegen are to add the Java
		/// handlers: (Either (but not both) of TARGET and FINALLY might not
		/// be defined)
		/// - a catch handler for javascript exceptions that unwraps the
		/// exception onto the stack and GOTOes to the catch target
		/// - a finally handler
		/// ...
		/// </summary>
		/// <remarks>
		/// Try/Catch/Finally
		/// The IRFactory tries to express as much as possible in the tree;
		/// the responsibilities remaining for Codegen are to add the Java
		/// handlers: (Either (but not both) of TARGET and FINALLY might not
		/// be defined)
		/// - a catch handler for javascript exceptions that unwraps the
		/// exception onto the stack and GOTOes to the catch target
		/// - a finally handler
		/// ... and a goto to GOTO around these handlers.
		/// </remarks>
		private Node CreateTryCatchFinally(Node tryBlock, Node catchBlocks, Node finallyBlock, int lineno)
		{
			bool hasFinally = (finallyBlock != null) && (finallyBlock.GetType() != Token.BLOCK || finallyBlock.HasChildren());
			// short circuit
			if (tryBlock.GetType() == Token.BLOCK && !tryBlock.HasChildren() && !hasFinally)
			{
				return tryBlock;
			}
			bool hasCatch = catchBlocks.HasChildren();
			// short circuit
			if (!hasFinally && !hasCatch)
			{
				// bc finally might be an empty block...
				return tryBlock;
			}
			Node handlerBlock = new Node(Token.LOCAL_BLOCK);
			Jump pn = new Jump(Token.TRY, tryBlock, lineno);
			pn.PutProp(Node.LOCAL_BLOCK_PROP, handlerBlock);
			if (hasCatch)
			{
				// jump around catch code
				Node endCatch = Node.NewTarget();
				pn.AddChildToBack(MakeJump(Token.GOTO, endCatch));
				// make a TARGET for the catch that the tcf node knows about
				Node catchTarget = Node.NewTarget();
				pn.target = catchTarget;
				// mark it
				pn.AddChildToBack(catchTarget);
				//
				//  Given
				//
				//   try {
				//       tryBlock;
				//   } catch (e if condition1) {
				//       something1;
				//   ...
				//
				//   } catch (e if conditionN) {
				//       somethingN;
				//   } catch (e) {
				//       somethingDefault;
				//   }
				//
				//  rewrite as
				//
				//   try {
				//       tryBlock;
				//       goto after_catch:
				//   } catch (x) {
				//       with (newCatchScope(e, x)) {
				//           if (condition1) {
				//               something1;
				//               goto after_catch;
				//           }
				//       }
				//   ...
				//       with (newCatchScope(e, x)) {
				//           if (conditionN) {
				//               somethingN;
				//               goto after_catch;
				//           }
				//       }
				//       with (newCatchScope(e, x)) {
				//           somethingDefault;
				//           goto after_catch;
				//       }
				//   }
				// after_catch:
				//
				// If there is no default catch, then the last with block
				// arround  "somethingDefault;" is replaced by "rethrow;"
				// It is assumed that catch handler generation will store
				// exeception object in handlerBlock register
				// Block with local for exception scope objects
				Node catchScopeBlock = new Node(Token.LOCAL_BLOCK);
				// expects catchblocks children to be (cond block) pairs.
				Node cb = catchBlocks.GetFirstChild();
				bool hasDefault = false;
				int scopeIndex = 0;
				while (cb != null)
				{
					int catchLineNo = cb.GetLineno();
					Node name = cb.GetFirstChild();
					Node cond = name.GetNext();
					Node catchStatement = cond.GetNext();
					cb.RemoveChild(name);
					cb.RemoveChild(cond);
					cb.RemoveChild(catchStatement);
					// Add goto to the catch statement to jump out of catch
					// but prefix it with LEAVEWITH since try..catch produces
					// "with"code in order to limit the scope of the exception
					// object.
					catchStatement.AddChildToBack(new Node(Token.LEAVEWITH));
					catchStatement.AddChildToBack(MakeJump(Token.GOTO, endCatch));
					// Create condition "if" when present
					Node condStmt;
					if (cond.GetType() == Token.EMPTY)
					{
						condStmt = catchStatement;
						hasDefault = true;
					}
					else
					{
						condStmt = CreateIf(cond, catchStatement, null, catchLineNo);
					}
					// Generate code to create the scope object and store
					// it in catchScopeBlock register
					Node catchScope = new Node(Token.CATCH_SCOPE, name, CreateUseLocal(handlerBlock));
					catchScope.PutProp(Node.LOCAL_BLOCK_PROP, catchScopeBlock);
					catchScope.PutIntProp(Node.CATCH_SCOPE_PROP, scopeIndex);
					catchScopeBlock.AddChildToBack(catchScope);
					// Add with statement based on catch scope object
					catchScopeBlock.AddChildToBack(CreateWith(CreateUseLocal(catchScopeBlock), condStmt, catchLineNo));
					// move to next cb
					cb = cb.GetNext();
					++scopeIndex;
				}
				pn.AddChildToBack(catchScopeBlock);
				if (!hasDefault)
				{
					// Generate code to rethrow if no catch clause was executed
					Node rethrow = new Node(Token.RETHROW);
					rethrow.PutProp(Node.LOCAL_BLOCK_PROP, handlerBlock);
					pn.AddChildToBack(rethrow);
				}
				pn.AddChildToBack(endCatch);
			}
			if (hasFinally)
			{
				Node finallyTarget = Node.NewTarget();
				pn.SetFinally(finallyTarget);
				// add jsr finally to the try block
				pn.AddChildToBack(MakeJump(Token.JSR, finallyTarget));
				// jump around finally code
				Node finallyEnd = Node.NewTarget();
				pn.AddChildToBack(MakeJump(Token.GOTO, finallyEnd));
				pn.AddChildToBack(finallyTarget);
				Node fBlock = new Node(Token.FINALLY, finallyBlock);
				fBlock.PutProp(Node.LOCAL_BLOCK_PROP, handlerBlock);
				pn.AddChildToBack(fBlock);
				pn.AddChildToBack(finallyEnd);
			}
			handlerBlock.AddChildToBack(pn);
			return handlerBlock;
		}