public Operand buildNext(final NextNode nextNode) { IRLoop currLoop = getCurrentLoop(); Operand rv = build(nextNode.getValueNode()); // If we have ensure blocks, have to run those first! if (!activeEnsureBlockStack.empty()) emitEnsureBlocks(currLoop); if (currLoop != null) { // If a regular loop, the next is simply a jump to the end of the iteration addInstr(new JumpInstr(currLoop.iterEndLabel)); } else { addInstr(new ThreadPollInstr(true)); // If a closure, the next is simply a return from the closure! if (scope instanceof IRClosure) { if (scope instanceof IREvalScript) { throwSyntaxError(nextNode, "Can't escape from eval with next"); } else { addInstr(new ReturnInstr(rv)); } } else { throwSyntaxError(nextNode, "Invalid next"); } } // Once the "next instruction" (closure-return) executes, control exits this scope return U_NIL; }
public Operand buildRedo(RedoNode redoNode) { // If we have ensure blocks, have to run those first! if (!activeEnsureBlockStack.empty()) { emitEnsureBlocks(getCurrentLoop()); } // If in a loop, a redo is a jump to the beginning of the loop. // If not, for closures, a redo is a jump to the beginning of the closure. // If not in a loop or a closure, it is a compile/syntax error IRLoop currLoop = getCurrentLoop(); if (currLoop != null) { addInstr(new JumpInstr(currLoop.iterStartLabel)); } else { if (scope instanceof IRClosure) { if (scope instanceof IREvalScript) { throwSyntaxError(redoNode, "Can't escape from eval with redo"); } else { addInstr(new ThreadPollInstr(true)); addInstr(new JumpInstr(((IRClosure) scope).startLabel)); } } else { throwSyntaxError(redoNode, "Invalid redo"); } } return manager.getNil(); }
public Operand buildRedo(RedoNode redoNode) { // If we have ensure blocks, have to run those first! if (!activeEnsureBlockStack.empty()) { emitEnsureBlocks(getCurrentLoop()); } // If in a loop, a redo is a jump to the beginning of the loop. // If not, for closures, a redo is a jump to the beginning of the closure. // If not in a loop or a closure, it is a compile/syntax error IRLoop currLoop = getCurrentLoop(); if (currLoop != null) { addInstr(new JumpInstr(currLoop.iterStartLabel)); } else { if (scope instanceof IRClosure) { if (scope instanceof IREvalScript) { throwSyntaxError(redoNode, "Can't escape from eval with redo"); } else { addInstr(new ThreadPollInstr(true)); addInstr(new JumpInstr(((IRClosure) scope).startLabel)); } } else { throwSyntaxError(redoNode, "Invalid redo"); } } return manager.getNil(); }
public Operand buildNext(final NextNode nextNode) { IRLoop currLoop = getCurrentLoop(); Operand rv = build(nextNode.getValueNode()); // If we have ensure blocks, have to run those first! if (!activeEnsureBlockStack.empty()) emitEnsureBlocks(currLoop); if (currLoop != null) { // If a regular loop, the next is simply a jump to the end of the iteration addInstr(new JumpInstr(currLoop.iterEndLabel)); } else { addInstr(new ThreadPollInstr(true)); // If a closure, the next is simply a return from the closure! if (scope instanceof IRClosure) { if (scope instanceof IREvalScript) { throwSyntaxError(nextNode, "Can't escape from eval with next"); } else { addInstr(new ReturnInstr(rv)); } } else { throwSyntaxError(nextNode, "Invalid next"); } } // Once the "next instruction" (closure-return) executes, control exits this scope return U_NIL; }
public Operand buildBreak(BreakNode breakNode) { IRLoop currLoop = getCurrentLoop(); if (currLoop != null) { // If we have ensure blocks, have to run those first! if (!activeEnsureBlockStack.empty()) emitEnsureBlocks(currLoop); addInstr(new CopyInstr(currLoop.loopResult, build(breakNode.getValueNode()))); addInstr(new JumpInstr(currLoop.loopEndLabel)); } else { if (scope instanceof IRClosure) { // This lexical scope value is only used (and valid) in regular block contexts. // If this instruction is executed in a Proc or Lambda context, the lexical scope value is useless. IRScope returnScope = scope.getLexicalParent(); if (scope instanceof IREvalScript || returnScope == null) { // We are not in a closure or a loop => bad break instr! throwSyntaxError(breakNode, "Can't escape from eval with redo"); } else { addInstr(new BreakInstr(build(breakNode.getValueNode()), returnScope.getName())); } } else { // We are not in a closure or a loop => bad break instr! throwSyntaxError(breakNode, "Invalid break"); } } // Once the break instruction executes, control exits this scope return U_NIL; }
public Operand buildBreak(BreakNode breakNode) { IRLoop currLoop = getCurrentLoop(); if (currLoop != null) { // If we have ensure blocks, have to run those first! if (!activeEnsureBlockStack.empty()) emitEnsureBlocks(currLoop); addInstr(new CopyInstr(currLoop.loopResult, build(breakNode.getValueNode()))); addInstr(new JumpInstr(currLoop.loopEndLabel)); } else { if (scope instanceof IRClosure) { // This lexical scope value is only used (and valid) in regular block contexts. // If this instruction is executed in a Proc or Lambda context, the lexical scope value is useless. IRScope returnScope = scope.getLexicalParent(); if (scope instanceof IREvalScript || returnScope == null) { // We are not in a closure or a loop => bad break instr! throwSyntaxError(breakNode, "Can't escape from eval with redo"); } else { addInstr(new BreakInstr(build(breakNode.getValueNode()), returnScope.getName())); } } else { // We are not in a closure or a loop => bad break instr! throwSyntaxError(breakNode, "Invalid break"); } } // Once the break instruction executes, control exits this scope return U_NIL; }
public Operand buildYield(YieldNode node, Variable result) { if (scope instanceof IRScriptBody) throwSyntaxError(node, "Invalid yield"); boolean unwrap = true; Node argNode = node.getArgsNode(); // Get rid of one level of array wrapping if (argNode != null && (argNode instanceof ArrayNode) && ((ArrayNode)argNode).size() == 1) { argNode = ((ArrayNode)argNode).getLast(); unwrap = false; } Variable ret = result == null ? createTemporaryVariable() : result; if (argNode instanceof ArrayNode && unwrap) { addInstr(new YieldInstr(ret, scope.getYieldClosureVariable(), buildArray((ArrayNode)argNode, true), unwrap)); } else { addInstr(new YieldInstr(ret, scope.getYieldClosureVariable(), build(argNode), unwrap)); } return ret; }
public Operand buildYield(YieldNode node, Variable result) { if (scope instanceof IRScriptBody) throwSyntaxError(node, "Invalid yield"); boolean unwrap = true; Node argNode = node.getArgsNode(); // Get rid of one level of array wrapping if (argNode != null && (argNode instanceof ArrayNode) && ((ArrayNode)argNode).size() == 1) { argNode = ((ArrayNode)argNode).getLast(); unwrap = false; } Variable ret = result == null ? createTemporaryVariable() : result; if (argNode instanceof ArrayNode && unwrap) { addInstr(new YieldInstr(ret, scope.getYieldClosureVariable(), buildArray((ArrayNode)argNode, true), unwrap)); } else { addInstr(new YieldInstr(ret, scope.getYieldClosureVariable(), build(argNode), unwrap)); } return ret; }