public Block(int numInputs, Collection<Entry> stmts) { this.stmts = new ArrayList<Entry>(); for (Entry s : stmts) { append(s.code, s.attributes()); } this.numInputs = numInputs; }
/** * Import an external block into this one, using a given <i>binding</i>. The binding indicates how * the input variables for the external block should be mapped into the variables of this block. * * <p> * * <p>Every input variable in the block must be bound to something in the binding. Otherwise, an * IllegalArgumentException is raised. In the case of an input bound to a slot >= numSlots(), then * the number of slots is increased automatically. <b>NOTE:</b> temporary variables used in the * external block will be mapped automatically to unused slots in this environment to prevent * collisions. Therefore, temporary variables should not be specified in the binding. */ public void importExternal(Block block, Map<Integer, Integer> binding) { int freeSlot = numSlots(); // First, sanity check that all input variables are bound HashMap<Integer, Integer> nbinding = new HashMap<Integer, Integer>(); for (int i = 0; i != block.numInputs; ++i) { Integer target = binding.get(i); if (target == null) { throw new IllegalArgumentException("Input not mapped by input"); } nbinding.put(i, target); freeSlot = Math.max(target + 1, freeSlot); } // Second, determine binding for temporary variables for (int i = block.numInputs; i != block.numSlots(); ++i) { nbinding.put(i, i + freeSlot); } // Third, determine relabelling HashMap<String, String> labels = new HashMap<String, String>(); for (Entry s : block) { if (s.code instanceof Code.Label) { Code.Label l = (Code.Label) s.code; labels.put(l.label, freshLabel()); } } // Finally, apply the binding and relabel any labels as well. for (Entry s : block) { Code ncode = s.code.remap(nbinding).relabel(labels); append(ncode, s.attributes()); } }
public Block relabel() { HashMap<String, String> labels = new HashMap<String, String>(); for (Entry s : this) { if (s.code instanceof Code.Label) { Code.Label l = (Code.Label) s.code; labels.put(l.label, freshLabel()); } } Block block = new Block(numInputs); // Finally, apply the binding and relabel any labels as well. for (Entry s : this) { Code ncode = s.code.relabel(labels); block.append(ncode, s.attributes()); } return block; }
/** * Insert a block at a given position in this block. It is assumed that the bytecode employs the * same environment as this block. The bytecode at the given position (and any after it) are * shifted one or more positions down. * * @param index --- position to insert block at. * @param block --- block to insert. */ public void insert(int index, Block block) { for (Entry s : block) { insert(index++, s.code, s.attributes()); } }
/** * Append another block onto the end of this block. It is assumed that the block in question * employs the same environment. * * <p><b>NOTE</b>In the case of the block being appended having more input variables, it is * assumed those additional ones correspond to temporaries in this block. * * @param block --- block to append */ public void append(Block block) { for (Entry s : block) { append(s.code, s.attributes()); } }