001: /*
002: * xtc - The eXTensible Compiler
003: * Copyright (C) 2007 New York University
004: *
005: * This program is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU General Public License
007: * version 2 as published by the Free Software Foundation.
008: *
009: * This program is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
012: * GNU General Public License for more details.
013: *
014: * You should have received a copy of the GNU General Public License
015: * along with this program; if not, write to the Free Software
016: * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
017: * USA.
018: */
019: package xtc.typical;
020:
021: import java.util.Set;
022: import java.util.HashSet;
023:
024: import java.util.List;
025: import java.util.ArrayList;
026:
027: import xtc.tree.Visitor;
028: import xtc.tree.GNode;
029: import xtc.tree.Node;
030:
031: /**
032: * Visitor to add all find all free identifiers in an guard expression.
033: * This might need some refinement and synchronisation with the symbol
034: * table.
035: *
036: * @author Anh Le, Laune Harris
037: * @version $Revision: 1.2 $
038: */
039: public class FreeVariableCollector extends Visitor {
040:
041: /* The list of identifiers. */
042: protected final Set<String> idlist;
043:
044: /**
045: * Create a new free variable collector.
046: *
047: * @param n The root of the expression.
048: */
049: public FreeVariableCollector(GNode n) {
050: idlist = new HashSet<String>();
051: dispatch(n);
052: }
053:
054: /**
055: * Create a new free variable collector.
056: *
057: * @param n The root of the expression.
058: * @param idlist The current idlist.
059: */
060: public FreeVariableCollector(GNode n, Set<String> idlist) {
061: this .idlist = idlist;
062: dispatch(n);
063: }
064:
065: /**
066: * Get the list of identifiers in this guard expression.
067: *
068: * @return The list of identifiers.
069: */
070: public Set<String> getIdentifiers() {
071: return idlist;
072: }
073:
074: /**
075: * Get the identifers in a guard expression.
076: *
077: * @param n The node.
078: */
079: public void visitGuardExpression(GNode n) {
080: dispatch(n.getGeneric(0));
081: }
082:
083: /**
084: * Get the identifiers in a tuple literal.
085: *
086: * @param n The node.
087: */
088: public void visitTupleLiteral(GNode n) {
089: for (int i = 0; i < n.size(); i++)
090: dispatch(n.getGeneric(i));
091: }
092:
093: /**
094: * Get the identifiers in a logical or expression.
095: *
096: * @param n The node.
097: */
098: public void visitLogicalOrExpression(GNode n) {
099: dispatch(n.getGeneric(0));
100: dispatch(n.getGeneric(2));
101: }
102:
103: /**
104: * Get the identifiers in a logical and expression.
105: *
106: * @param n The node.
107: */
108: public void visitLogicalAndExpression(GNode n) {
109: dispatch(n.getGeneric(0));
110: dispatch(n.getGeneric(2));
111: }
112:
113: /**
114: * Get the identifiers in an equality expression.
115: *
116: * @param n The node.
117: */
118: public void visitEqualityExpression(GNode n) {
119: dispatch(n.getGeneric(0));
120: dispatch(n.getGeneric(2));
121: }
122:
123: /**
124: * Get the identifiers in a relational expression.
125: *
126: * @param n The node.
127: */
128: public void visitRelationalExpression(GNode n) {
129: dispatch(n.getGeneric(0));
130: dispatch(n.getGeneric(2));
131: }
132:
133: /**
134: * Get the identifiers in an additive expression.
135: *
136: * @param n The node.
137: */
138: public void visitAdditiveExpression(GNode n) {
139: dispatch(n.getGeneric(0));
140: dispatch(n.getGeneric(2));
141: }
142:
143: /**
144: * Get the identifiers in an concatenation expression.
145: *
146: * @param n The node.
147: */
148: public void visitConcatenationExpression(GNode n) {
149: dispatch(n.getGeneric(0));
150: dispatch(n.getGeneric(2));
151: }
152:
153: /**
154: * Get the identifiers in a multiplicative expression.
155: *
156: * @param n The node.
157: */
158: public void visitMultiplicativeExpresion(GNode n) {
159: dispatch(n.getGeneric(0));
160: dispatch(n.getGeneric(2));
161: }
162:
163: /**
164: * Get the identifiers in a cons expression.
165: *
166: * @param n The node.
167: */
168: public void visitConsExpression(GNode n) {
169: dispatch(n.getGeneric(0));
170: dispatch(n.getGeneric(1));
171: }
172:
173: /**
174: * Get the identifers in a function application.
175: *
176: * @param n The node.
177: */
178: public void visitFunctionApplication(GNode n) {
179: int size = n.size();
180: if (3 == size)
181: dispatch(n.getGeneric(2));
182: else {
183: dispatch(n.getGeneric(0));
184: dispatch(n.getGeneric(1));
185: }
186: }
187:
188: /**
189: * Get the identifers in an argument list.
190: *
191: * @param n The node.
192: */
193: public void visitArguments(GNode n) {
194: for (int i = 0; i < n.size(); i++)
195: dispatch(n.getGeneric(i));
196: }
197:
198: /**
199: * Get the identifiers in a predicate expression.
200: *
201: * @param n The node.
202: */
203: public void visitPredicateExpression(GNode n) {
204: dispatch(n.getGeneric(1));
205: }
206:
207: /** Get the identifiers in a field expression. */
208: public void visitFieldExpression(GNode n) {
209: dispatch(n.getGeneric(0));
210: }
211:
212: /**
213: * Get the identifiers in a logicalnegation expression.
214: *
215: * @param n The node.
216: */
217: public void visitLogicalNegationExpression(GNode n) {
218: dispatch(n.getGeneric(0));
219: }
220:
221: /**
222: * Get the identifiers in a let expression.
223: *
224: * @param n The node.
225: */
226: public void visitLetExpression(GNode n) {
227: // Get id in the expression
228: Set<String> ids1 = new FreeVariableCollector(n.getGeneric(1))
229: .getIdentifiers();
230:
231: // Remove the bound ids
232: Set<String> ids2 = new FreeVariableCollector(n.getGeneric(0),
233: ids1).getIdentifiers();
234:
235: idlist.addAll(ids2);
236: }
237:
238: /**
239: * Get (bound) identifiers in let bindings.
240: *
241: * @param n The node.
242: */
243: public void visitLetBindings(GNode n) {
244: for (int i = 0; i < n.size(); i++) {
245: dispatch(n.getGeneric(i));
246: }
247: }
248:
249: /**
250: * Get bound identifier in a let binding.
251: *
252: * @param n The node.
253: */
254: public void visitLetBinding(GNode n) {
255: Node var = n.getGeneric(0);
256: if ("Variable".equals(var.getName()))
257: idlist.remove(var.getString(0));
258: }
259:
260: /**
261: * Get identifiers in a function expression.
262: *
263: * @param n The node.
264: */
265: public void visitFunctionExpression(GNode n) {
266: dispatch(n.getGeneric(0));
267: }
268:
269: /**
270: * Get identifiers in a match expression.
271: *
272: * @param n The node.
273: */
274: public void visitMatchExpression(GNode n) {
275: dispatch(n.getGeneric(0));
276:
277: // Process pattern matching
278: Node pmatching = n.getGeneric(1);
279: for (int i = 0; i < pmatching.size(); i++) {
280: Node pmatch = pmatching.getGeneric(i);
281:
282: // Get ids in the right hand side expression
283: Set<String> ids1 = new FreeVariableCollector(pmatch
284: .getGeneric(1)).getIdentifiers();
285:
286: // Remove bound ids
287: Set<String> ids2 = new FreeVariableCollector(pmatch
288: .getGeneric(0), ids1).getIdentifiers();
289:
290: idlist.addAll(ids2);
291: }
292: }
293:
294: /**
295: * Get (bound) identifiers in patterns.
296: *
297: * @param n The node.
298: */
299: public void visitPatterns(GNode n) {
300: // Because all patterns must have the same bound variables, it is
301: // sufficient to get variables from the first patterns
302: dispatch(n.getGeneric(0));
303: }
304:
305: /**
306: * Get (bound) identifiers in TuplePattern.
307: *
308: * @param n The node.
309: */
310: public void visitTuplePattern(GNode n) {
311: for (int i = 0; i < n.size(); i++) {
312: dispatch(n.getGeneric(i));
313: }
314: }
315:
316: /**
317: * Get (bound) identifiers in WhenPattern.
318: *
319: * @param n The node.
320: */
321: public void visitWhenPattern(GNode n) {
322: dispatch(n.getGeneric(0));
323: }
324:
325: /**
326: * Get (bound) identifiers in AsPattern.
327: *
328: * @param n The node.
329: */
330: public void visitAsPattern(GNode n) {
331: dispatch(n.getGeneric(0));
332: final String id = n.getString(1);
333: idlist.remove(id);
334: }
335:
336: /**
337: * Get (bound) identifiers in TypedPattern.
338: *
339: * @param n The node.
340: */
341: public void visitTypedPattern(GNode n) {
342: dispatch(n.getGeneric(0));
343: }
344:
345: /**
346: * Get (bound) identifiers in ConsPattern.
347: *
348: * @param n The node.
349: */
350: public void visitConsPattern(GNode n) {
351: dispatch(n.getGeneric(0));
352: dispatch(n.getGeneric(1));
353: }
354:
355: /**
356: * Get (bound) identifier in a Variable.
357: *
358: * @param n The node.
359: */
360: public void visitVariable(GNode n) {
361: idlist.remove(n.getString(0));
362: }
363:
364: /**
365: * Get (bound) identifiers in a TypeConstructorPattern.
366: *
367: * @param n The node.
368: */
369: public void visitTypeConstructorPattern(GNode n) {
370: for (int i = 1; i < n.size(); i++) {
371: dispatch(n.getGeneric(i));
372: }
373: }
374:
375: /**
376: * Get (bound) identifiers in PatternParameters.
377: *
378: * @param n The node.
379: */
380: public void visitPatternParameters(GNode n) {
381: for (int i = 0; i < n.size(); i++) {
382: dispatch(n.getGeneric(i));
383: }
384: }
385:
386: /**
387: * Get (bound) identifiers in a ListPattern.
388: *
389: * @param n The node.
390: */
391: public void visitListPattern(GNode n) {
392: for (int i = 0; i < n.size(); i++) {
393: dispatch(n.getGeneric(i));
394: }
395: }
396:
397: /**
398: * Get (bound) identifiers in a RecordPattern.
399: *
400: * @param n The node.
401: */
402: public void visitRecordPattern(GNode n) {
403: for (int i = 0; i < n.size(); i++) {
404: dispatch(n.getGeneric(i));
405: }
406: }
407:
408: /**
409: * Get (bound) identifiers in a FieldPattern.
410: *
411: * @param n The node.
412: */
413: public void visitFieldPattern(GNode n) {
414: dispatch(n.getGeneric(1));
415: }
416:
417: /**
418: * Get identifiers in a TupleConstructor.
419: *
420: * @param n The node.
421: */
422: public void visitTupleConstructor(GNode n) {
423: for (int i = 1; i < n.size(); i++) {
424: dispatch(n.getGeneric(i));
425: }
426: }
427:
428: /**
429: * Get identifiers in a RecordExpression.
430: *
431: * @param n The node.
432: */
433: public void visitRecordExpression(GNode n) {
434: for (int i = 0; i < n.size(); i++) {
435: dispatch(n.getGeneric(i));
436: }
437: }
438:
439: /**
440: * Get identifiers in a WithExpression.
441: *
442: * @param n The node.
443: */
444: public void visitWithExpression(GNode n) {
445: dispatch(n.getGeneric(0));
446: }
447:
448: /**
449: * Get identifiers in a FieldAssignment.
450: *
451: * @param n The node.
452: */
453: public void visitFieldAssignment(GNode n) {
454: dispatch(n.getGeneric(1));
455: }
456:
457: /**
458: * Get identifiers in a ListLiteral.
459: *
460: * @param n The node.
461: */
462: public void visitListLiteral(GNode n) {
463: for (int i = 0; i < n.size(); i++) {
464: dispatch(n.getGeneric(i));
465: }
466: }
467:
468: /**
469: * Get the identifers in a lower id.
470: *
471: * @param n The node.
472: */
473: public void visitLowerID(GNode n) {
474: idlist.add(n.getString(0));
475: }
476:
477: /**
478: * Get the identifiers in other nodes.
479: *
480: * @param n The node.
481: */
482: public void visit(GNode n) {
483: // do nothing
484: }
485:
486: }
|