39 40 /** 41 * IR representation for a list of statements. 42 */ 43 @Immutable 44 public class Block extends Node implements BreakableNode, Terminal, Flags<Block> { 45 private static final long serialVersionUID = 1L; 46 47 /** List of statements */ 48 protected final List<Statement> statements; 49 50 /** Symbol table - keys must be returned in the order they were put in. */ 51 protected final Map<String, Symbol> symbols; 52 53 /** Entry label. */ 54 private final Label entryLabel; 55 56 /** Break label. */ 57 private final Label breakLabel; 58 59 /** Does the block/function need a new scope? */ 60 protected final int flags; 61 62 /** 63 * @see JoinPredecessor 64 */ 65 private final LocalVariableConversion conversion; 66 67 /** Flag indicating that this block needs scope */ 68 public static final int NEEDS_SCOPE = 1 << 0; 69 70 /** 71 * Is this block tagged as terminal based on its contents 72 * (usually the last statement) 73 */ 74 public static final int IS_TERMINAL = 1 << 2; 75 76 /** 77 * Is this block the eager global scope - i.e. the original program. This isn't true for the 78 * outermost level of recompiles 79 */ 80 public static final int IS_GLOBAL_SCOPE = 1 << 3; 81 82 /** 83 * Constructor 84 * 85 * @param token The first token of the block 86 * @param finish The index of the last character 87 * @param flags The flags of the block 88 * @param statements All statements in the block 89 */ 90 public Block(final long token, final int finish, final int flags, final Statement... statements) { 91 super(token, finish); 92 93 this.statements = Arrays.asList(statements); 94 this.symbols = new LinkedHashMap<>(); 95 this.entryLabel = new Label("block_entry"); 96 this.breakLabel = new Label("block_break"); 97 final int len = statements.length; 98 final int terminalFlags = len > 0 && statements[len - 1].hasTerminalFlags() ? IS_TERMINAL : 0; 99 this.flags = terminalFlags | flags; 100 this.conversion = null; 101 } 102 103 /** 104 * Constructs a new block 105 * 106 * @param token The first token of the block 107 * @param finish The index of the last character 108 * @param statements All statements in the block 109 */ 110 public Block(final long token, final int finish, final Statement...statements){ 111 this(token, finish, 0, statements); 112 } 113 114 /** 115 * Constructs a new block 116 * 117 * @param token The first token of the block 118 * @param finish The index of the last character 119 * @param statements All statements in the block 120 */ 121 public Block(final long token, final int finish, final List<Statement> statements){ 122 this(token, finish, 0, statements); 123 } 124 125 /** 126 * Constructor 127 * 128 * @param token The first token of the block 129 * @param finish The index of the last character 130 * @param flags The flags of the block 131 * @param statements All statements in the block 132 */ 133 public Block(final long token, final int finish, final int flags, final List<Statement> statements) { 134 this(token, finish, flags, statements.toArray(new Statement[statements.size()])); 135 } 136 137 private Block(final Block block, final int finish, final List<Statement> statements, final int flags, final Map<String, Symbol> symbols, final LocalVariableConversion conversion) { 138 super(block, finish); 139 this.statements = statements; 140 this.flags = flags; 141 this.symbols = new LinkedHashMap<>(symbols); //todo - symbols have no dependencies on any IR node and can as far as we understand it be shallow copied now 142 this.entryLabel = new Label(block.entryLabel); 347 return Node.replaceInLexicalContext(lc, this, new Block(this, Math.max(finish, lastFinish), statements, flags, symbols, conversion)); 348 } 349 350 /** 351 * Add or overwrite an existing symbol in the block 352 * 353 * @param lc get lexical context 354 * @param symbol symbol 355 */ 356 public void putSymbol(final LexicalContext lc, final Symbol symbol) { 357 symbols.put(symbol.getName(), symbol); 358 } 359 360 /** 361 * Check whether scope is necessary for this Block 362 * 363 * @return true if this function needs a scope 364 */ 365 public boolean needsScope() { 366 return (flags & NEEDS_SCOPE) == NEEDS_SCOPE; 367 } 368 369 @Override 370 public Block setFlags(final LexicalContext lc, final int flags) { 371 if (this.flags == flags) { 372 return this; 373 } 374 return Node.replaceInLexicalContext(lc, this, new Block(this, finish, statements, flags, symbols, conversion)); 375 } 376 377 @Override 378 public Block clearFlag(final LexicalContext lc, final int flag) { 379 return setFlags(lc, flags & ~flag); 380 } 381 382 @Override 383 public Block setFlag(final LexicalContext lc, final int flag) { 384 return setFlags(lc, flags | flag); 385 } 386 | 39 40 /** 41 * IR representation for a list of statements. 42 */ 43 @Immutable 44 public class Block extends Node implements BreakableNode, Terminal, Flags<Block> { 45 private static final long serialVersionUID = 1L; 46 47 /** List of statements */ 48 protected final List<Statement> statements; 49 50 /** Symbol table - keys must be returned in the order they were put in. */ 51 protected final Map<String, Symbol> symbols; 52 53 /** Entry label. */ 54 private final Label entryLabel; 55 56 /** Break label. */ 57 private final Label breakLabel; 58 59 /** Does the block/function need a new scope? Is this synthetic? */ 60 protected final int flags; 61 62 /** 63 * @see JoinPredecessor 64 */ 65 private final LocalVariableConversion conversion; 66 67 /** Flag indicating that this block needs scope */ 68 public static final int NEEDS_SCOPE = 1 << 0; 69 70 /** 71 * Is this block tagged as terminal based on its contents 72 * (usually the last statement) 73 */ 74 public static final int IS_TERMINAL = 1 << 2; 75 76 /** 77 * Is this block the eager global scope - i.e. the original program. This isn't true for the 78 * outermost level of recompiles 79 */ 80 public static final int IS_GLOBAL_SCOPE = 1 << 3; 81 82 /** 83 * Is this block a synthetic one introduced by Parser? 84 */ 85 public static final int IS_SYNTHETIC = 1 << 4; 86 87 /** 88 * Constructor 89 * 90 * @param token The first token of the block 91 * @param finish The index of the last character 92 * @param flags The flags of the block 93 * @param statements All statements in the block 94 */ 95 public Block(final long token, final int finish, final int flags, final Statement... statements) { 96 super(token, finish); 97 98 this.statements = Arrays.asList(statements); 99 this.symbols = new LinkedHashMap<>(); 100 this.entryLabel = new Label("block_entry"); 101 this.breakLabel = new Label("block_break"); 102 final int len = statements.length; 103 final int terminalFlags = len > 0 && statements[len - 1].hasTerminalFlags() ? IS_TERMINAL : 0; 104 this.flags = terminalFlags | flags; 105 this.conversion = null; 106 } 107 108 /** 109 * Constructs a new block 110 * 111 * @param token The first token of the block 112 * @param finish The index of the last character 113 * @param statements All statements in the block 114 */ 115 public Block(final long token, final int finish, final Statement...statements){ 116 this(token, finish, IS_SYNTHETIC, statements); 117 } 118 119 /** 120 * Constructs a new block 121 * 122 * @param token The first token of the block 123 * @param finish The index of the last character 124 * @param statements All statements in the block 125 */ 126 public Block(final long token, final int finish, final List<Statement> statements){ 127 this(token, finish, IS_SYNTHETIC, statements); 128 } 129 130 /** 131 * Constructor 132 * 133 * @param token The first token of the block 134 * @param finish The index of the last character 135 * @param flags The flags of the block 136 * @param statements All statements in the block 137 */ 138 public Block(final long token, final int finish, final int flags, final List<Statement> statements) { 139 this(token, finish, flags, statements.toArray(new Statement[statements.size()])); 140 } 141 142 private Block(final Block block, final int finish, final List<Statement> statements, final int flags, final Map<String, Symbol> symbols, final LocalVariableConversion conversion) { 143 super(block, finish); 144 this.statements = statements; 145 this.flags = flags; 146 this.symbols = new LinkedHashMap<>(symbols); //todo - symbols have no dependencies on any IR node and can as far as we understand it be shallow copied now 147 this.entryLabel = new Label(block.entryLabel); 352 return Node.replaceInLexicalContext(lc, this, new Block(this, Math.max(finish, lastFinish), statements, flags, symbols, conversion)); 353 } 354 355 /** 356 * Add or overwrite an existing symbol in the block 357 * 358 * @param lc get lexical context 359 * @param symbol symbol 360 */ 361 public void putSymbol(final LexicalContext lc, final Symbol symbol) { 362 symbols.put(symbol.getName(), symbol); 363 } 364 365 /** 366 * Check whether scope is necessary for this Block 367 * 368 * @return true if this function needs a scope 369 */ 370 public boolean needsScope() { 371 return (flags & NEEDS_SCOPE) == NEEDS_SCOPE; 372 } 373 374 /** 375 * Check whether this block is synthetic or not. 376 * 377 * @return true if this is a synthetic block 378 */ 379 public boolean isSynthetic() { 380 return (flags & IS_SYNTHETIC) == IS_SYNTHETIC; 381 } 382 383 @Override 384 public Block setFlags(final LexicalContext lc, final int flags) { 385 if (this.flags == flags) { 386 return this; 387 } 388 return Node.replaceInLexicalContext(lc, this, new Block(this, finish, statements, flags, symbols, conversion)); 389 } 390 391 @Override 392 public Block clearFlag(final LexicalContext lc, final int flag) { 393 return setFlags(lc, flags & ~flag); 394 } 395 396 @Override 397 public Block setFlag(final LexicalContext lc, final int flag) { 398 return setFlags(lc, flags | flag); 399 } 400 |