/** * 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()); } }