package org.rascalmpl.library.experiments.Compiler.RVM.Interpreter.traverse; import java.util.Iterator; import java.util.Stack; import org.rascalmpl.interpreter.matching.MapKeyValueIterator; import org.rascalmpl.interpreter.matching.TupleElementIterator; import org.rascalmpl.interpreter.types.DefaultRascalTypeVisitor; import org.rascalmpl.interpreter.types.NonTerminalType; import org.rascalmpl.interpreter.types.RascalType; import org.rascalmpl.value.IConstructor; import org.rascalmpl.value.IList; import org.rascalmpl.value.IMap; import org.rascalmpl.value.INode; import org.rascalmpl.value.ISet; import org.rascalmpl.value.ITuple; import org.rascalmpl.value.IValue; import org.rascalmpl.value.IWithKeywordParameters; import org.rascalmpl.value.type.Type; import org.rascalmpl.values.uptr.ITree; import org.rascalmpl.values.uptr.RascalValueFactory; import org.rascalmpl.values.uptr.SymbolAdapter; import org.rascalmpl.values.uptr.TreeAdapter; public class DescendantMatchIterator implements Iterator<IValue> { final Stack<Object> spine = new Stack<Object>(); private final boolean debug = false; private final DescendantDescriptor descriptor; private final boolean concreteMatch; // true when matching concrete patterns public DescendantMatchIterator(IValue val, DescendantDescriptor descriptor){ if (debug) { System.err.println("DescendantReader: " + val); } this.concreteMatch = descriptor.isConcreteMatch(); this.descriptor = descriptor; push(val); } public boolean hasNext() { while((spine.size() > 0) && (spine.peek() instanceof Iterator && !((Iterator<?>) spine.peek()).hasNext())){ spine.pop(); } return spine.size() > 0; } public IValue next() { if (spine.peek() instanceof Iterator) { Iterator<?> iter = (Iterator<?>) spine.peek(); if (!iter.hasNext()) { spine.pop(); return next(); } push((IValue) iter.next()); return next(); } return (IValue) spine.pop(); } private void push(final IValue v, final Iterator<IValue> children){ spine.push(v); spine.push(children); } private void push(final IValue v){ if(concreteMatch){ if(v.getType().isSubtypeOf(RascalValueFactory.Tree)){ pushConcreteSyntaxNode((ITree) v); } return; } if(descriptor.shouldDescentInAbstractValue(v).getValue()){ if(v.getType().accept(new DefaultRascalTypeVisitor<Boolean,RuntimeException>(false) { @Override public Boolean visitList(final Type type) throws RuntimeException { IList lst = (IList) v; int len = lst.length(); if(len == 0){ spine.push(lst); } else if(len == 1){ spine.push(lst); push(lst.get(0)); } else { push(lst, lst.iterator()); } return true; } @Override public Boolean visitSet(final Type type) throws RuntimeException { ISet set = (ISet) v; if(set.isEmpty()){ spine.push(set); } else { push(set, set.iterator()); } return true; } @Override public Boolean visitMap(final Type type) throws RuntimeException { IMap map = (IMap) v; if(map.isEmpty()){ spine.push(map); } else { push(map, new MapKeyValueIterator(map)); } return true; } @Override public Boolean visitTuple(final Type type) throws RuntimeException { push(v, new TupleElementIterator((ITuple) v)); return true; } @Override public Boolean visitNode(final Type type) throws RuntimeException { INode node = (INode) v; int arity = node.arity(); if(arity == 0){ spine.push(node); } else if(arity == 1){ spine.push(node); push(node.get(0)); } else { push(node, node.getChildren().iterator()); } if (node.mayHaveKeywordParameters()) { IWithKeywordParameters<? extends INode> nodeKW = node.asWithKeywordParameters(); for (String name : nodeKW.getParameterNames()) { push(nodeKW.getParameter(name)); } } return true; } @Override public Boolean visitConstructor(final Type type) throws RuntimeException { return visitNode(type); } @Override public Boolean visitAbstractData(final Type type) throws RuntimeException { return visitNode(type); } @Override public Boolean visitNonTerminal(final RascalType type) throws RuntimeException { return visitNode(type); } })){ return; } } spine.push(v); } private void pushConcreteSyntaxNode(final ITree tree){ if (debug) System.err.println("pushConcreteSyntaxNode: " + tree); if (TreeAdapter.isAmb(tree)) { // only recurse for (IValue alt : TreeAdapter.getAlternatives(tree)) { pushConcreteSyntaxNode((ITree) alt); } return; } if(descriptor.shouldDescentInConcreteValue(tree).getValue()){ NonTerminalType ctype = (NonTerminalType) tree.getType(); if (debug) System.err.println("ctype.getSymbol=" + ctype.getSymbol()); IConstructor sym = ctype.getSymbol(); if (SymbolAdapter.isAnyList(sym)) { spine.push(tree); int delta = SymbolAdapter.getListSkipDelta(sym); sym = SymbolAdapter.getSymbol(sym); IList listElems = (IList) tree.get(1); if (debug) { for (int i = 0; i < listElems.length(); i++){ System.err.println("#" + i + ": " + listElems.get(i)); } } for (int i = listElems.length() - 1; i >= 0 ; i -= delta){ if (debug) System.err.println("adding: " + listElems.get(i)); pushConcreteSyntaxNode((ITree)listElems.get(i)); } } else if (SymbolAdapter.isStartSort(sym)) { pushConcreteSyntaxNode(TreeAdapter.getStartTop(tree)); } else { if (debug) System.err.println("pushConcreteSyntaxNode: appl"); /* * appl(prod(...), [child0, layout0, child1, ...]) */ spine.push(tree); IList applArgs = (IList) tree.get(1); int delta = (SymbolAdapter.isLex(sym)) ? 1 : 2; // distance between elements for(int i = applArgs.length() - 1; i >= 0 ; i -= delta){ pushConcreteSyntaxNode((ITree) applArgs.get(i)); } } } else { spine.push(tree); } } public void remove() { throw new UnsupportedOperationException("remove from DescendantMatchIterator"); } }