/** * 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()); } }
private void determineTypesUpto(int end) { Type[] environment = environments[0]; for (int i = position; i < end; ++i) { Code code = stmts.get(i).code; if (code instanceof Code.Label) { Code.Label label = (Code.Label) code; Type[] nEnv = cache.get(label.label); environment = join(environment, nEnv); } else if (code instanceof Code.AbstractAssignable) { Code.AbstractAssignable c = (Code.AbstractAssignable) code; environment = Arrays.copyOf(environment, environment.length); environment[c.target] = c.assignedType(); } else if (code instanceof Code.Goto) { Code.Goto gto = (Code.Goto) code; cache.put(gto.target, environment); environment = null; } else if (code instanceof Code.If) { Code.If gto = (Code.If) code; cache.put(gto.target, environment); } else if (code instanceof Code.IfIs) { Code.IfIs gto = (Code.IfIs) code; Type[] trueEnv = Arrays.copyOf(environment, environment.length); trueEnv[gto.operand] = Type.intersect(trueEnv[gto.operand], gto.rightOperand); cache.put(gto.target, trueEnv); environment[gto.operand] = Type.intersect(trueEnv[gto.operand], Type.Negation(gto.rightOperand)); } else if (code instanceof Code.Switch) { Code.Switch sw = (Code.Switch) code; for (Pair<Constant, String> c : sw.branches) { cache.put(c.second(), environment); } cache.put(sw.defaultTarget, environment); } else if (code instanceof Code.ForAll) { // FIXME: what this need to do is update the type for the // index variable, and then invalidate it afterwards. throw new RuntimeException("need to implement for-all loop!"); } else if (code instanceof Code.Return || code instanceof Code.Throw) { environment = null; } environments[i] = environment; } }
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; }