package org.spoofax.terms.visitor;

import java.util.Stack;

import org.spoofax.interpreter.terms.IStrategoAppl;
import org.spoofax.interpreter.terms.IStrategoInt;
import org.spoofax.interpreter.terms.IStrategoList;
import org.spoofax.interpreter.terms.IStrategoPlaceholder;
import org.spoofax.interpreter.terms.IStrategoReal;
import org.spoofax.interpreter.terms.IStrategoRef;
import org.spoofax.interpreter.terms.IStrategoString;
import org.spoofax.interpreter.terms.IStrategoTerm;
import org.spoofax.interpreter.terms.IStrategoTuple;

public class StrategoTermVisitee {
    public static void accept(IStrategoTermVisitor visitor, IStrategoTerm initialTerm) {
        final Stack<IStrategoTerm> stack = new Stack<IStrategoTerm>();
        stack.push(initialTerm);
        while(!stack.empty()) {
            final IStrategoTerm term = stack.pop();
            if(!dispatch(visitor, term)) {
                continue;
            }
            for(int i = term.getSubtermCount() -1; i >= 0; --i) {
                stack.push(term.getSubterm(i));
            }
        }
    }

    private static boolean dispatch(IStrategoTermVisitor visitor, IStrategoTerm term) {
        switch(term.getTermType()) {
            case IStrategoTerm.APPL:
                return visitor.visit((IStrategoAppl) term);
            case IStrategoTerm.LIST:
                return visitor.visit((IStrategoList) term);
            case IStrategoTerm.TUPLE:
                return visitor.visit((IStrategoTuple) term);
            case IStrategoTerm.INT:
                visitor.visit((IStrategoInt) term);
                return false;
            case IStrategoTerm.REAL:
                visitor.visit((IStrategoReal) term);
                return false;
            case IStrategoTerm.STRING:
                visitor.visit((IStrategoString) term);
                return false;
            case IStrategoTerm.REF:
                visitor.visit((IStrategoRef) term);
                return false;
            case IStrategoTerm.PLACEHOLDER:
                return visitor.visit((IStrategoPlaceholder) term);
            default:
                return visitor.visit(term);
        }
    }
}

@@ -29,16 +29,64 @@
 sitor;%0A%0A
+import java.util.HashSet;%0Aimport java.util.Set;%0A
 import j
@@ -101,16 +101,16 @@
 .Stack;%0A
-
 %0Aimport 
@@ -641,14 +641,15 @@
 oid 
-accept
+topdown
 (ISt
@@ -1037,24 +1037,24 @@
 = 0; --i) %7B%0A
-
             
@@ -1118,16 +1118,782 @@
  %7D%0A    %7D
+%0A    %0A    public static void bottomup(IStrategoTermVisitor visitor, IStrategoTerm initialTerm) %7B%0A        final Stack%3CIStrategoTerm%3E stack = new Stack%3CIStrategoTerm%3E();%0A        final Set%3CIStrategoTerm%3E visited = new HashSet%3CIStrategoTerm%3E();%0A        stack.push(initialTerm);%0A        while(!stack.isEmpty()) %7B%0A            final IStrategoTerm term = stack.peek();%0A            if(term.getSubtermCount() == 0 %7C%7C visited.contains(term)) %7B%0A                dispatch(visitor, term);%0A                stack.pop();%0A                visited.remove(term);%0A            %7D else %7B%0A                visited.add(term);%0A                for(int i = term.getSubtermCount() -1; i %3E= 0; --i) %7B%0A                    stack.push(term.getSubterm(i));%0A                %7D%0A            %7D%0A        %7D%0A    %7D
 %0A%0A    pr

Add bottomup to term visitor.