package org.rascalmpl.library.experiments.Compiler.RVM.Interpreter.traverse; import org.rascalmpl.value.IValue; import org.rascalmpl.value.IValueFactory; import org.rascalmpl.value.type.Type; import org.rascalmpl.values.uptr.ITree; public abstract class TraverseOnce { protected final IValueFactory vf; public TraverseOnce(IValueFactory vf) { this.vf = vf; } /* * traverseTop: traverse the outermost symbol of the subject. */ public IValue traverseTop(IValue subject, final TraversalState tr) { IValue res = tr.execute(subject); if(tr.isLeavingVisit()){ throw new ReturnFromTraversalException(res); } return res; } /* * Datatype specific traverse functions that will be implemented by * rebuilding or non-rebuilding versions. */ abstract IValue traverseStringOnce(IValue subject, final TraversalState tr); abstract IValue traverseTupleOnce(IValue subject, final TraversalState tr); abstract IValue traverseADTOnce(IValue subject, final TraversalState tr); abstract IValue traverseConcreteTreeOnce(IValue subject, final TraversalState tr); abstract IValue traverseMapOnce(IValue subject, final TraversalState tr); abstract IValue traverseSetOnce(IValue subject, final TraversalState tr); abstract IValue traverseListOnce(IValue subject, final TraversalState tr); abstract IValue traverseNodeOnce(IValue subject, final TraversalState tr); /* * Here are 16 specializations of the traverseOnce function for the following variants: * - BottomUp or TopDown * - Continuing or Breaking * - FixedPoint or NoFixedPoint * - Concrete or Abstract * * The unspecialized version of the code is given at the bottom of this file. */ public IValue traverseOnceBottomUpContinuingFixedPointConcrete(IValue subject, final TraversalState tr){ IValue result = subject; boolean hasMatched = false; boolean hasChanged = false; if(tr.shouldDescentInConcreteValue((ITree)subject)){ result = traverseConcreteTreeOnce(subject, tr); } hasMatched = tr.hasMatched(); hasChanged = tr.hasChanged(); tr.setMatchedAndChanged(false, false); result = traverseTop(result, tr); if (tr.hasChanged()) { do { tr.setMatchedAndChanged(false, false); result = traverseTop(result, tr); } while (tr.hasChanged()); tr.setMatchedAndChanged(true, true); } tr.setMatchedAndChanged(tr.hasMatched() | hasMatched, tr.hasChanged() | hasChanged); return result; } public IValue traverseOnceBottomUpContinuingFixedPointAbstract(IValue subject, final TraversalState tr){ Type subjectType = subject.getType(); IValue result = subject; boolean hasMatched = false; boolean hasChanged = false; if(tr.shouldDescentInAbstractValue(subject)){ if (subjectType.isAbstractData()){ result = traverseADTOnce(subject,tr); } else if (subjectType.isNode()){ result = traverseNodeOnce(subject, tr); } else if(subjectType.isList()){ result = traverseListOnce(subject, tr); } else if(subjectType.isSet()){ result = traverseSetOnce(subject, tr); } else if (subjectType.isMap()) { result = traverseMapOnce(subject, tr); } else if(subjectType.isTuple()){ result = traverseTupleOnce(subject, tr); } else { result = subject; } } hasMatched = tr.hasMatched(); hasChanged = tr.hasChanged(); tr.setMatchedAndChanged(false, false); result = traverseTop(result, tr); if (tr.hasChanged()) { do { tr.setMatchedAndChanged(false, false); result = traverseTop(result, tr); } while (tr.hasChanged()); tr.setMatchedAndChanged(true, true); } tr.setMatchedAndChanged(tr.hasMatched() | hasMatched, tr.hasChanged() | hasChanged); return result; } public IValue traverseOnceBottomUpContinuingNoFixedPointConcrete(IValue subject, final TraversalState tr){ IValue result = subject; boolean hasMatched = false; boolean hasChanged = false; if(tr.shouldDescentInConcreteValue((ITree)subject)){ result = traverseConcreteTreeOnce(subject, tr); } hasMatched = tr.hasMatched(); hasChanged = tr.hasChanged(); tr.setMatchedAndChanged(false, false); result = traverseTop(result, tr); tr.setMatchedAndChanged(tr.hasMatched() | hasMatched, tr.hasChanged() | hasChanged); return result; } public IValue traverseOnceBottomUpContinuingNoFixedPointAbstract(IValue subject, final TraversalState tr){ Type subjectType = subject.getType(); IValue result = subject; boolean hasMatched = false; boolean hasChanged = false; if(tr.shouldDescentInAbstractValue(subject)){ if (subjectType.isAbstractData()){ result = traverseADTOnce(subject,tr); } else if (subjectType.isNode()){ result = traverseNodeOnce(subject, tr); } else if(subjectType.isList()){ result = traverseListOnce(subject, tr); } else if(subjectType.isSet()){ result = traverseSetOnce(subject, tr); } else if (subjectType.isMap()) { result = traverseMapOnce(subject, tr); } else if(subjectType.isTuple()){ result = traverseTupleOnce(subject, tr); } else { result = subject; } } hasMatched = tr.hasMatched(); hasChanged = tr.hasChanged(); tr.setMatchedAndChanged(false, false); result = traverseTop(result, tr); tr.setMatchedAndChanged(tr.hasMatched() | hasMatched, tr.hasChanged() | hasChanged); return result; } public IValue traverseOnceBottomUpBreakingFixedPointConcrete(IValue subject, final TraversalState tr){ IValue result = subject; boolean hasMatched = false; boolean hasChanged = false; if(tr.shouldDescentInConcreteValue((ITree)subject)){ result = traverseConcreteTreeOnce(subject, tr); } if (tr.hasMatched()) { return result; } hasMatched = tr.hasMatched(); hasChanged = tr.hasChanged(); tr.setMatchedAndChanged(false, false); result = traverseTop(result, tr); if (tr.hasChanged()) { do { tr.setMatchedAndChanged(false, false); result = traverseTop(result, tr); } while (tr.hasChanged()); tr.setMatchedAndChanged(true, true); } tr.setMatchedAndChanged(tr.hasMatched() | hasMatched, tr.hasChanged() | hasChanged); return result; } public IValue traverseOnceBottomUpBreakingFixedPointAbstract(IValue subject, final TraversalState tr){ Type subjectType = subject.getType(); IValue result = subject; boolean hasMatched = false; boolean hasChanged = false; if(tr.shouldDescentInAbstractValue(subject)){ if (subjectType.isAbstractData()){ result = traverseADTOnce(subject,tr); } else if (subjectType.isNode()){ result = traverseNodeOnce(subject, tr); } else if(subjectType.isList()){ result = traverseListOnce(subject, tr); } else if(subjectType.isSet()){ result = traverseSetOnce(subject, tr); } else if (subjectType.isMap()) { result = traverseMapOnce(subject, tr); } else if(subjectType.isTuple()){ result = traverseTupleOnce(subject, tr); } else { result = subject; } } if (tr.hasMatched()) { return result; } hasMatched = tr.hasMatched(); hasChanged = tr.hasChanged(); tr.setMatchedAndChanged(false, false); result = traverseTop(result, tr); if (tr.hasChanged()) { do { tr.setMatchedAndChanged(false, false); result = traverseTop(result, tr); } while (tr.hasChanged()); tr.setMatchedAndChanged(true, true); } tr.setMatchedAndChanged(tr.hasMatched() | hasMatched, tr.hasChanged() | hasChanged); return result; } public IValue traverseOnceBottomUpBreakingNoFixedPointConcrete(IValue subject, final TraversalState tr){ IValue result = subject; boolean hasMatched = false; boolean hasChanged = false; if(tr.shouldDescentInConcreteValue((ITree)subject)){ result = traverseConcreteTreeOnce(subject, tr); } if (tr.hasMatched()) { return result; } hasMatched = tr.hasMatched(); hasChanged = tr.hasChanged(); tr.setMatchedAndChanged(false, false); result = traverseTop(result, tr); tr.setMatchedAndChanged(tr.hasMatched() | hasMatched, tr.hasChanged() | hasChanged); return result; } public IValue traverseOnceBottomUpBreakingNoFixedPointAbstract(IValue subject, final TraversalState tr){ Type subjectType = subject.getType(); IValue result = subject; boolean hasMatched = false; boolean hasChanged = false; if(tr.shouldDescentInAbstractValue(subject)){ if (subjectType.isAbstractData()){ result = traverseADTOnce(subject,tr); } else if (subjectType.isNode()){ result = traverseNodeOnce(subject, tr); } else if(subjectType.isList()){ result = traverseListOnce(subject, tr); } else if(subjectType.isSet()){ result = traverseSetOnce(subject, tr); } else if (subjectType.isMap()) { result = traverseMapOnce(subject, tr); } else if(subjectType.isTuple()){ result = traverseTupleOnce(subject, tr); } else { result = subject; } } if (tr.hasMatched()) { return result; } hasMatched = tr.hasMatched(); hasChanged = tr.hasChanged(); tr.setMatchedAndChanged(false, false); result = traverseTop(result, tr); tr.setMatchedAndChanged(tr.hasMatched() | hasMatched, tr.hasChanged() | hasChanged); return result; } public IValue traverseOnceTopDownContinuingFixedPointConcrete(IValue subject, final TraversalState tr){ IValue result = subject; boolean hasMatched = false; boolean hasChanged = false; IValue newTop = traverseTop(subject, tr); if (tr.hasChanged()) { do { tr.setChanged(false); newTop = traverseTop(newTop, tr); } while (tr.hasChanged()); tr.setChanged(true); subject = newTop; } else { subject = newTop; } hasMatched = tr.hasMatched(); hasChanged = tr.hasChanged(); if(tr.shouldDescentInConcreteValue((ITree)subject)){ result = traverseConcreteTreeOnce(subject, tr); } tr.setMatchedAndChanged(tr.hasMatched() | hasMatched, tr.hasChanged() | hasChanged); return result; } public IValue traverseOnceTopDownContinuingFixedPointAbstract(IValue subject, final TraversalState tr){ Type subjectType = subject.getType(); IValue result = subject; boolean hasMatched = false; boolean hasChanged = false; IValue newTop = traverseTop(subject, tr); if (tr.hasChanged()) { do { tr.setChanged(false); newTop = traverseTop(newTop, tr); } while (tr.hasChanged()); tr.setChanged(true); subject = newTop; } else { subject = newTop; } hasMatched = tr.hasMatched(); hasChanged = tr.hasChanged(); if(tr.shouldDescentInAbstractValue(subject)){ if (subjectType.isAbstractData()){ result = traverseADTOnce(subject,tr); } else if (subjectType.isNode()){ result = traverseNodeOnce(subject, tr); } else if(subjectType.isList()){ result = traverseListOnce(subject, tr); } else if(subjectType.isSet()){ result = traverseSetOnce(subject, tr); } else if (subjectType.isMap()) { result = traverseMapOnce(subject, tr); } else if(subjectType.isTuple()){ result = traverseTupleOnce(subject, tr); } else { result = subject; } } tr.setMatchedAndChanged(tr.hasMatched() | hasMatched, tr.hasChanged() | hasChanged); return result; } public IValue traverseOnceTopDownContinuingNoFixedPointConcrete(IValue subject, final TraversalState tr){ IValue result = subject; boolean hasMatched = false; boolean hasChanged = false; subject = traverseTop(subject, tr); hasMatched = tr.hasMatched(); hasChanged = tr.hasChanged(); if(tr.shouldDescentInConcreteValue((ITree)subject)){ result = traverseConcreteTreeOnce(subject, tr); } tr.setMatchedAndChanged(tr.hasMatched() | hasMatched, tr.hasChanged() | hasChanged); return result; } public IValue traverseOnceTopDownContinuingNoFixedPointAbstract(IValue subject, final TraversalState tr){ Type subjectType = subject.getType(); IValue result = subject; boolean hasMatched = false; boolean hasChanged = false; subject = traverseTop(subject, tr); hasMatched = tr.hasMatched(); hasChanged = tr.hasChanged(); if(tr.shouldDescentInAbstractValue(subject)){ if (subjectType.isAbstractData()){ result = traverseADTOnce(subject,tr); } else if (subjectType.isNode()){ result = traverseNodeOnce(subject, tr); } else if(subjectType.isList()){ result = traverseListOnce(subject, tr); } else if(subjectType.isSet()){ result = traverseSetOnce(subject, tr); } else if (subjectType.isMap()) { result = traverseMapOnce(subject, tr); } else if(subjectType.isTuple()){ result = traverseTupleOnce(subject, tr); } else { result = subject; } } tr.setMatchedAndChanged(tr.hasMatched() | hasMatched, tr.hasChanged() | hasChanged); return result; } public IValue traverseOnceTopDownBreakingFixedPointConcrete(IValue subject, final TraversalState tr){ IValue result = subject; boolean hasMatched = false; boolean hasChanged = false; IValue newTop = traverseTop(subject, tr); if (tr.hasMatched()) { return newTop; } else if (tr.hasChanged()) { do { tr.setChanged(false); newTop = traverseTop(newTop, tr); } while (tr.hasChanged()); tr.setChanged(true); subject = newTop; } else { subject = newTop; } hasMatched = tr.hasMatched(); hasChanged = tr.hasChanged(); if(tr.shouldDescentInConcreteValue((ITree)subject)){ result = traverseConcreteTreeOnce(subject, tr); } tr.setMatchedAndChanged(tr.hasMatched() | hasMatched, tr.hasChanged() | hasChanged); return result; } public IValue traverseOnceTopDownBreakingFixedPointAbstract(IValue subject, final TraversalState tr){ Type subjectType = subject.getType(); IValue result = subject; boolean hasMatched = false; boolean hasChanged = false; IValue newTop = traverseTop(subject, tr); if (tr.hasMatched()) { return newTop; } else if (tr.hasChanged()) { do { tr.setChanged(false); newTop = traverseTop(newTop, tr); } while (tr.hasChanged()); tr.setChanged(true); subject = newTop; } else { subject = newTop; } hasMatched = tr.hasMatched(); hasChanged = tr.hasChanged(); if(tr.shouldDescentInAbstractValue(subject)){ if (subjectType.isAbstractData()){ result = traverseADTOnce(subject,tr); } else if (subjectType.isNode()){ result = traverseNodeOnce(subject, tr); } else if(subjectType.isList()){ result = traverseListOnce(subject, tr); } else if(subjectType.isSet()){ result = traverseSetOnce(subject, tr); } else if (subjectType.isMap()) { result = traverseMapOnce(subject, tr); } else if(subjectType.isTuple()){ result = traverseTupleOnce(subject, tr); } else { result = subject; } } tr.setMatchedAndChanged(tr.hasMatched() | hasMatched, tr.hasChanged() | hasChanged); return result; } public IValue traverseOnceTopDownBreakingNoFixedPointConcrete(IValue subject, final TraversalState tr){ IValue result = subject; boolean hasMatched = false; boolean hasChanged = false; IValue newTop = traverseTop(subject, tr); if (tr.hasMatched()) { return newTop; } else { subject = newTop; } hasMatched = tr.hasMatched(); hasChanged = tr.hasChanged(); if(tr.shouldDescentInConcreteValue((ITree)subject)){ result = traverseConcreteTreeOnce(subject, tr); } tr.setMatchedAndChanged(tr.hasMatched() | hasMatched, tr.hasChanged() | hasChanged); return result; } public IValue traverseOnceTopDownBreakingNoFixedPointAbstract(IValue subject, final TraversalState tr){ Type subjectType = subject.getType(); IValue result = subject; boolean hasMatched = false; boolean hasChanged = false; IValue newTop = traverseTop(subject, tr); if (tr.hasMatched()) { return newTop; } else { subject = newTop; } hasMatched = tr.hasMatched(); hasChanged = tr.hasChanged(); if(tr.shouldDescentInAbstractValue(subject)){ if (subjectType.isAbstractData()){ result = traverseADTOnce(subject,tr); } else if (subjectType.isNode()){ result = traverseNodeOnce(subject, tr); } else if(subjectType.isList()){ result = traverseListOnce(subject, tr); } else if(subjectType.isSet()){ result = traverseSetOnce(subject, tr); } else if (subjectType.isMap()) { result = traverseMapOnce(subject, tr); } else if(subjectType.isTuple()){ result = traverseTupleOnce(subject, tr); } else { result = subject; } } tr.setMatchedAndChanged(tr.hasMatched() | hasMatched, tr.hasChanged() | hasChanged); return result; } /* * The original version of traverseOnce from which the above specialization have been derived IValue traverseOnce(IValue subject, final TraversalState tr){ Type subjectType = subject.getType(); IValue result = subject; boolean hasMatched = false; boolean hasChanged = false; if (tr.isTopDown()){ IValue newTop = traverseTop(subject, tr); if (tr.isBreaking() && tr.hasMatched()) { return newTop; } else if (tr.isFixedPoint() && tr.hasChanged()) { do { tr.setChanged(false); newTop = traverseTop(newTop, tr); } while (tr.hasChanged()); tr.setChanged(true); subject = newTop; } else { subject = newTop; } hasMatched = tr.hasMatched(); hasChanged = tr.hasChanged(); } if(tr.isConcreteMatch()){ if(tr.shouldDescentInConcreteValue((ITree)subject)){ result = traverseConcreteTreeOnce(subject, tr); } } else { if(tr.shouldDescentInAbstractValue(subject)){ if (subjectType.isAbstractData()){ result = traverseADTOnce(subject,tr); } else if (subjectType.isNode()){ result = traverseNodeOnce(subject, tr); } else if(subjectType.isList()){ result = traverseListOnce(subject, tr); } else if(subjectType.isSet()){ result = traverseSetOnce(subject, tr); } else if (subjectType.isMap()) { result = traverseMapOnce(subject, tr); } else if(subjectType.isTuple()){ result = traverseTupleOnce(subject, tr); } else { result = subject; } } } if (tr.isTopDown()) { tr.setMatchedAndChanged(tr.hasMatched() | hasMatched, tr.hasChanged() | hasChanged); } if (tr.isBottomUp()) { if ((tr.isBreaking() && tr.hasMatched())) { return result; } hasMatched = tr.hasMatched(); hasChanged = tr.hasChanged(); tr.setMatchedAndChanged(false, false); result = traverseTop(result, tr); if (tr.hasChanged() && tr.isFixedPoint()) { do { tr.setMatchedAndChanged(false, false); result = traverseTop(result, tr); } while (tr.hasChanged()); tr.setMatchedAndChanged(true, true); } tr.setMatchedAndChanged(tr.hasMatched() | hasMatched, tr.hasChanged() | hasChanged); } return result; } */ }