Mercurial > hg > openjdk > jigsaw > nashorn
view src/jdk/nashorn/internal/ir/LexicalContext.java @ 143:4be452026847
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
Reviewed-by: jlaskey, lagergren
author | attila |
---|---|
date | Sat, 23 Mar 2013 00:58:39 +0100 |
parents | |
children |
line wrap: on
line source
package jdk.nashorn.internal.ir; import java.util.ArrayDeque; import java.util.Deque; import java.util.Iterator; import java.util.NoSuchElementException; /** * A class that tracks the current lexical context of node visitation as a stack of {@link Block} nodes. Has special * methods to retrieve useful subsets of the context. */ public class LexicalContext implements Cloneable { private final Deque<Block> lexicalContext; /** * Creates a new empty lexical context. */ public LexicalContext() { lexicalContext = new ArrayDeque<>(); } /** * Pushes a new block on top of the context, making it the innermost open block. * @param block the new block */ public void push(Block block) { //new Exception(block.toString()).printStackTrace(); lexicalContext.push(block); } /** * Pops the innermost block off the context. * @param the block expected to be popped, used to detect unbalanced pushes/pops */ public void pop(Block block) { final Block popped = lexicalContext.pop(); assert popped == block; } /** * Returns an iterator over all blocks in the context, with the top block (innermost lexical context) first. * @return an iterator over all blocks in the context. */ public Iterator<Block> getBlocks() { return lexicalContext.iterator(); } /** * Returns an iterator over all functions in the context, with the top (innermost open) function first. * @return an iterator over all functions in the context. */ public Iterator<FunctionNode> getFunctions() { return new FunctionIterator(getBlocks()); } private static final class FunctionIterator implements Iterator<FunctionNode> { private final Iterator<Block> it; private FunctionNode next; FunctionIterator(Iterator<Block> it) { this.it = it; next = findNext(); } @Override public boolean hasNext() { return next != null; } @Override public FunctionNode next() { if(next == null) { throw new NoSuchElementException(); } FunctionNode lnext = next; next = findNext(); return lnext; } private FunctionNode findNext() { while(it.hasNext()) { final Block block = it.next(); if(block instanceof FunctionNode) { return ((FunctionNode)block); } } return null; } @Override public void remove() { throw new UnsupportedOperationException(); } } /** * Returns an iterator over all ancestors block of the given block, with its parent block first. * @param block the block whose ancestors are returned * @return an iterator over all ancestors block of the given block. */ public Iterator<Block> getAncestorBlocks(Block block) { final Iterator<Block> it = getBlocks(); while(it.hasNext()) { final Block b = it.next(); if(block == b) { return it; } } throw new AssertionError("Block is not on the current lexical context stack"); } /** * Returns an iterator over a block and all its ancestors blocks, with the block first. * @param block the block that is the starting point of the iteration. * @return an iterator over a block and all its ancestors. */ public Iterator<Block> getBlocks(final Block block) { final Iterator<Block> it = getAncestorBlocks(block); return new Iterator<Block>() { boolean blockReturned = false; @Override public boolean hasNext() { return it.hasNext() || !blockReturned; } @Override public Block next() { if(blockReturned) { return it.next(); } blockReturned = true; return block; } @Override public void remove() { throw new UnsupportedOperationException(); } }; } /** * Returns the closest function node to the block. If the block is itself a function, it is returned. * @param block the block * @return the function closest to the block. * @see #getParentFunction(Block) */ public FunctionNode getFunction(Block block) { if(block instanceof FunctionNode) { return (FunctionNode)block; } return getParentFunction(block); } /** * Returns the closest function node to the block and all its ancestor functions. If the block is itself a function, * it is returned too. * @param block the block * @return the closest function node to the block and all its ancestor functions. */ public Iterator<FunctionNode> getFunctions(final Block block) { return new FunctionIterator(getBlocks(block)); } /** * Returns the containing function of the block. If the block is itself a function, its parent function is returned. * @param block the block * @return the containing function of the block. * @see #getFunction(Block) */ public FunctionNode getParentFunction(Block block) { return getFirstFunction(getAncestorBlocks(block)); } private static FunctionNode getFirstFunction(Iterator<Block> it) { while(it.hasNext()) { final Block ancestor = it.next(); if(ancestor instanceof FunctionNode) { return (FunctionNode)ancestor; } } return null; } /** * Returns the innermost block in the context. * @return the innermost block in the context. */ public Block getCurrentBlock() { return lexicalContext.element(); } /** * Returns the innermost function in the context. * @return the innermost function in the context. */ public FunctionNode getCurrentFunction() { return getFirstFunction(getBlocks()); } }