public Operand buildNext(final NextNode nextNode, IRScope s) { IRLoop currLoop = getCurrentLoop(); Operand rv = (nextNode.getValueNode() == null) ? manager.getNil() : build(nextNode.getValueNode(), s); // If we have ensure blocks, have to run those first! if (!_ensureBlockStack.empty()) EnsureBlockInfo.emitJumpChain(s, _ensureBlockStack, currLoop); else if (!_rescueBlockStack.empty()) _rescueBlockStack.peek().restoreException(s, currLoop); if (currLoop != null) { // If a regular loop, the next is simply a jump to the end of the iteration s.addInstr(new JumpInstr(currLoop.iterEndLabel)); } else { s.addInstr(new ThreadPollInstr(true)); // If a closure, the next is simply a return from the closure! if (s instanceof IRClosure) s.addInstr(new ReturnInstr(rv)); else s.addInstr(new ThrowExceptionInstr(IRException.NEXT_LocalJumpError)); } // Once the "next instruction" (closure-return) executes, control exits this scope return UnexecutableNil.U_NIL; }
public Operand buildNext(final NextNode nextNode, IRScope s) { IRLoop currLoop = getCurrentLoop(); Operand rv = (nextNode.getValueNode() == null) ? manager.getNil() : build(nextNode.getValueNode(), s); // If we have ensure blocks, have to run those first! if (!_ensureBlockStack.empty()) EnsureBlockInfo.emitJumpChain(s, _ensureBlockStack, currLoop); else if (!_rescueBlockStack.empty()) _rescueBlockStack.peek().restoreException(s, currLoop); if (currLoop != null) { // If a regular loop, the next is simply a jump to the end of the iteration s.addInstr(new JumpInstr(currLoop.iterEndLabel)); } else { s.addInstr(new ThreadPollInstr(true)); // If a closure, the next is simply a return from the closure! if (s instanceof IRClosure) s.addInstr(new ReturnInstr(rv)); else s.addInstr(new ThrowExceptionInstr(IRException.NEXT_LocalJumpError)); } // Once the "next instruction" (closure-return) executes, control exits this scope return UnexecutableNil.U_NIL; }
if (!_ensureBlockStack.empty()) EnsureBlockInfo.emitJumpChain(s, _ensureBlockStack, currLoop); else if (!_rescueBlockStack.empty()) _rescueBlockStack.peek().restoreException(s, currLoop);
if (!_ensureBlockStack.empty()) EnsureBlockInfo.emitJumpChain(s, _ensureBlockStack, currLoop); else if (!_rescueBlockStack.empty()) _rescueBlockStack.peek().restoreException(s, currLoop);
public Operand buildReturn(ReturnNode returnNode, IRScope s) { Operand retVal = (returnNode.getValueNode() == null) ? manager.getNil() : build(returnNode.getValueNode(), s); // Before we return, // - have to go execute all the ensure blocks if there are any. // this code also takes care of resetting "$!" // - if we dont have any ensure blocks, we have to clear "$!" if (!_ensureBlockStack.empty()) EnsureBlockInfo.emitJumpChain(s, _ensureBlockStack, null); else if (!_rescueBlockStack.empty()) s.addInstr(new PutGlobalVarInstr("$!", manager.getNil())); if (s instanceof IRClosure) { // If 'm' is a block scope, a return returns from the closest enclosing method. // If this happens to be a module body, the runtime throws a local jump error if // the closure is a proc. If the closure is a lambda, then this is just a normal // return and the static methodToReturnFrom value is ignored s.addInstr(new NonlocalReturnInstr(retVal, s.getNearestMethod())); } else if (s.isModuleBody()) { IRMethod sm = s.getNearestMethod(); // Cannot return from top-level module bodies! if (sm == null) s.addInstr(new ThrowExceptionInstr(IRException.RETURN_LocalJumpError)); else s.addInstr(new NonlocalReturnInstr(retVal, sm)); } else { s.addInstr(new ReturnInstr(retVal)); } // The value of the return itself in the containing expression can never be used because of control-flow reasons. // The expression that uses this result can never be executed beyond the return and hence the value itself is just // a placeholder operand. return UnexecutableNil.U_NIL; }
public Operand buildReturn(ReturnNode returnNode, IRScope s) { Operand retVal = (returnNode.getValueNode() == null) ? manager.getNil() : build(returnNode.getValueNode(), s); // Before we return, // - have to go execute all the ensure blocks if there are any. // this code also takes care of resetting "$!" // - if we dont have any ensure blocks, we have to clear "$!" if (!_ensureBlockStack.empty()) EnsureBlockInfo.emitJumpChain(s, _ensureBlockStack, null); else if (!_rescueBlockStack.empty()) s.addInstr(new PutGlobalVarInstr("$!", manager.getNil())); if (s instanceof IRClosure) { // If 'm' is a block scope, a return returns from the closest enclosing method. // If this happens to be a module body, the runtime throws a local jump error if // the closure is a proc. If the closure is a lambda, then this is just a normal // return and the static methodToReturnFrom value is ignored s.addInstr(new NonlocalReturnInstr(retVal, s.getNearestMethod())); } else if (s.isModuleBody()) { IRMethod sm = s.getNearestMethod(); // Cannot return from top-level module bodies! if (sm == null) s.addInstr(new ThrowExceptionInstr(IRException.RETURN_LocalJumpError)); else s.addInstr(new NonlocalReturnInstr(retVal, sm)); } else { s.addInstr(new ReturnInstr(retVal)); } // The value of the return itself in the containing expression can never be used because of control-flow reasons. // The expression that uses this result can never be executed beyond the return and hence the value itself is just // a placeholder operand. return UnexecutableNil.U_NIL; }