/* * xtc - The eXTensible Compiler * Copyright (C) 2007 New York University * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ package xtc.typical; import java.util.Set; import java.util.HashSet; import java.util.List; import java.util.ArrayList; import xtc.tree.Visitor; import xtc.tree.GNode; import xtc.tree.Node; /** * Visitor to add all find all free identifiers in an guard expression. * This might need some refinement and synchronisation with the symbol * table. * * @author Anh Le, Laune Harris * @version $Revision: 1.2 $ */ public class FreeVariableCollector extends Visitor { /* The list of identifiers. */ protected final Set<String> idlist; /** * Create a new free variable collector. * * @param n The root of the expression. */ public FreeVariableCollector(GNode n) { idlist = new HashSet<String>(); dispatch(n); } /** * Create a new free variable collector. * * @param n The root of the expression. * @param idlist The current idlist. */ public FreeVariableCollector(GNode n, Set<String> idlist) { this.idlist = idlist; dispatch(n); } /** * Get the list of identifiers in this guard expression. * * @return The list of identifiers. */ public Set<String> getIdentifiers() { return idlist; } /** * Get the identifers in a guard expression. * * @param n The node. */ public void visitGuardExpression(GNode n) { dispatch(n.getGeneric(0)); } /** * Get the identifiers in a tuple literal. * * @param n The node. */ public void visitTupleLiteral(GNode n) { for (int i = 0; i < n.size(); i++) dispatch(n.getGeneric(i)); } /** * Get the identifiers in a logical or expression. * * @param n The node. */ public void visitLogicalOrExpression(GNode n) { dispatch(n.getGeneric(0)); dispatch(n.getGeneric(2)); } /** * Get the identifiers in a logical and expression. * * @param n The node. */ public void visitLogicalAndExpression(GNode n) { dispatch(n.getGeneric(0)); dispatch(n.getGeneric(2)); } /** * Get the identifiers in an equality expression. * * @param n The node. */ public void visitEqualityExpression(GNode n) { dispatch(n.getGeneric(0)); dispatch(n.getGeneric(2)); } /** * Get the identifiers in a relational expression. * * @param n The node. */ public void visitRelationalExpression(GNode n) { dispatch(n.getGeneric(0)); dispatch(n.getGeneric(2)); } /** * Get the identifiers in an additive expression. * * @param n The node. */ public void visitAdditiveExpression(GNode n) { dispatch(n.getGeneric(0)); dispatch(n.getGeneric(2)); } /** * Get the identifiers in an concatenation expression. * * @param n The node. */ public void visitConcatenationExpression(GNode n) { dispatch(n.getGeneric(0)); dispatch(n.getGeneric(2)); } /** * Get the identifiers in a multiplicative expression. * * @param n The node. */ public void visitMultiplicativeExpresion(GNode n) { dispatch(n.getGeneric(0)); dispatch(n.getGeneric(2)); } /** * Get the identifiers in a cons expression. * * @param n The node. */ public void visitConsExpression(GNode n) { dispatch(n.getGeneric(0)); dispatch(n.getGeneric(1)); } /** * Get the identifers in a function application. * * @param n The node. */ public void visitFunctionApplication(GNode n) { int size = n.size(); if (3 == size) dispatch(n.getGeneric(2)); else { dispatch(n.getGeneric(0)); dispatch(n.getGeneric(1)); } } /** * Get the identifers in an argument list. * * @param n The node. */ public void visitArguments(GNode n) { for (int i = 0; i < n.size(); i++) dispatch(n.getGeneric(i)); } /** * Get the identifiers in a predicate expression. * * @param n The node. */ public void visitPredicateExpression(GNode n) { dispatch(n.getGeneric(1)); } /** Get the identifiers in a field expression. */ public void visitFieldExpression(GNode n) { dispatch(n.getGeneric(0)); } /** * Get the identifiers in a logicalnegation expression. * * @param n The node. */ public void visitLogicalNegationExpression(GNode n) { dispatch(n.getGeneric(0)); } /** * Get the identifiers in a let expression. * * @param n The node. */ public void visitLetExpression(GNode n) { // Get id in the expression Set<String> ids1 = new FreeVariableCollector(n.getGeneric(1)).getIdentifiers(); // Remove the bound ids Set<String> ids2 = new FreeVariableCollector(n.getGeneric(0),ids1).getIdentifiers(); idlist.addAll(ids2); } /** * Get (bound) identifiers in let bindings. * * @param n The node. */ public void visitLetBindings(GNode n) { for (int i = 0; i < n.size(); i++) { dispatch(n.getGeneric(i)); } } /** * Get bound identifier in a let binding. * * @param n The node. */ public void visitLetBinding(GNode n) { Node var = n.getGeneric(0); if ("Variable".equals(var.getName())) idlist.remove(var.getString(0)); } /** * Get identifiers in a function expression. * * @param n The node. */ public void visitFunctionExpression(GNode n) { dispatch(n.getGeneric(0)); } /** * Get identifiers in a match expression. * * @param n The node. */ public void visitMatchExpression(GNode n) { dispatch(n.getGeneric(0)); // Process pattern matching Node pmatching = n.getGeneric(1); for (int i = 0; i < pmatching.size(); i++) { Node pmatch = pmatching.getGeneric(i); // Get ids in the right hand side expression Set<String> ids1 = new FreeVariableCollector(pmatch.getGeneric(1)).getIdentifiers(); // Remove bound ids Set<String> ids2 = new FreeVariableCollector(pmatch.getGeneric(0), ids1).getIdentifiers(); idlist.addAll(ids2); } } /** * Get (bound) identifiers in patterns. * * @param n The node. */ public void visitPatterns(GNode n) { // Because all patterns must have the same bound variables, it is // sufficient to get variables from the first patterns dispatch(n.getGeneric(0)); } /** * Get (bound) identifiers in TuplePattern. * * @param n The node. */ public void visitTuplePattern(GNode n) { for (int i = 0; i < n.size(); i ++) { dispatch(n.getGeneric(i)); } } /** * Get (bound) identifiers in WhenPattern. * * @param n The node. */ public void visitWhenPattern(GNode n) { dispatch(n.getGeneric(0)); } /** * Get (bound) identifiers in AsPattern. * * @param n The node. */ public void visitAsPattern(GNode n) { dispatch(n.getGeneric(0)); final String id = n.getString(1); idlist.remove(id); } /** * Get (bound) identifiers in TypedPattern. * * @param n The node. */ public void visitTypedPattern(GNode n) { dispatch(n.getGeneric(0)); } /** * Get (bound) identifiers in ConsPattern. * * @param n The node. */ public void visitConsPattern(GNode n) { dispatch(n.getGeneric(0)); dispatch(n.getGeneric(1)); } /** * Get (bound) identifier in a Variable. * * @param n The node. */ public void visitVariable(GNode n) { idlist.remove(n.getString(0)); } /** * Get (bound) identifiers in a TypeConstructorPattern. * * @param n The node. */ public void visitTypeConstructorPattern(GNode n) { for (int i = 1; i < n.size(); i++) { dispatch(n.getGeneric(i)); } } /** * Get (bound) identifiers in PatternParameters. * * @param n The node. */ public void visitPatternParameters(GNode n) { for (int i = 0; i < n.size(); i++) { dispatch(n.getGeneric(i)); } } /** * Get (bound) identifiers in a ListPattern. * * @param n The node. */ public void visitListPattern(GNode n) { for (int i = 0; i < n.size(); i++) { dispatch(n.getGeneric(i)); } } /** * Get (bound) identifiers in a RecordPattern. * * @param n The node. */ public void visitRecordPattern(GNode n) { for (int i = 0; i < n.size(); i++) { dispatch(n.getGeneric(i)); } } /** * Get (bound) identifiers in a FieldPattern. * * @param n The node. */ public void visitFieldPattern(GNode n) { dispatch(n.getGeneric(1)); } /** * Get identifiers in a TupleConstructor. * * @param n The node. */ public void visitTupleConstructor(GNode n) { for (int i = 1; i < n.size(); i++) { dispatch(n.getGeneric(i)); } } /** * Get identifiers in a RecordExpression. * * @param n The node. */ public void visitRecordExpression(GNode n) { for (int i = 0; i < n.size(); i++) { dispatch(n.getGeneric(i)); } } /** * Get identifiers in a WithExpression. * * @param n The node. */ public void visitWithExpression(GNode n) { dispatch(n.getGeneric(0)); } /** * Get identifiers in a FieldAssignment. * * @param n The node. */ public void visitFieldAssignment(GNode n) { dispatch(n.getGeneric(1)); } /** * Get identifiers in a ListLiteral. * * @param n The node. */ public void visitListLiteral(GNode n) { for (int i = 0; i < n.size(); i++) { dispatch(n.getGeneric(i)); } } /** * Get the identifers in a lower id. * * @param n The node. */ public void visitLowerID(GNode n) { idlist.add(n.getString(0)); } /** * Get the identifiers in other nodes. * * @param n The node. */ public void visit(GNode n) { // do nothing } }