// Copyright (c) 2011, David J. Pearce (djp@ecs.vuw.ac.nz) // All rights reserved. // // This software may be modified and distributed under the terms // of the BSD license. See the LICENSE file for details. package wyil.util; import java.util.Arrays; import java.util.BitSet; import wyil.lang.Bytecode; import wyil.lang.SyntaxTree.Location; /** * Helper functions for working with SyntaxTrees. * * @author David J. Pearce * */ public class SyntaxTrees { /** * Traverse a syntax tree from one or more roots looking for variable * accesses (uses). * * @param roots * @return */ public static int[] determineUsedVariables(Location<?>... roots) { BitSet usedVariables = new BitSet(); for(int i=0;i!=roots.length;++i) { determineUsedVariables(roots[i],usedVariables); } int[] vars = new int[usedVariables.cardinality()]; int index = 0; for (int i = usedVariables.nextSetBit(0); i >= 0; i = usedVariables.nextSetBit(i+1)) { vars[index++] = i; } return vars; } private static void determineUsedVariables(Location<?> root, BitSet usedVariables) { switch(root.getOpcode()) { case Bytecode.OPCODE_vardecl: case Bytecode.OPCODE_vardeclinit: case Bytecode.OPCODE_aliasdecl: usedVariables.set(root.getIndex()); return; } for(int i=0;i!=root.numberOfOperands();++i) { determineUsedVariables(root.getOperand(i),usedVariables); } for(int i=0;i!=root.numberOfOperandGroups();++i) { Location<?>[] group = root.getOperandGroup(i); for(int j=0;j!=group.length;++j) { determineUsedVariables(group[j],usedVariables); } } for(int i=0;i!=root.numberOfBlocks();++i) { determineUsedVariables(root.getBlock(i),usedVariables); } switch(root.getOpcode()) { case Bytecode.OPCODE_some: case Bytecode.OPCODE_all: { Bytecode.Quantifier qf = (Bytecode.Quantifier) root.getBytecode(); for(Bytecode.Range r : qf.ranges()) { // Make sure that no bound variables are captured usedVariables.set(r.variable(),false); } } } } }