rm transient context cache for closure computations; slight speed improvement maybe. less complex.

This commit is contained in:
Terence Parr 2012-07-28 10:51:07 -07:00
parent eda95f7478
commit 680df17280
7 changed files with 63 additions and 115 deletions

View File

@ -31,7 +31,6 @@ package org.antlr.v4.runtime.atn;
import org.antlr.v4.runtime.misc.Array2DHashSet; import org.antlr.v4.runtime.misc.Array2DHashSet;
import org.antlr.v4.runtime.misc.IntervalSet; import org.antlr.v4.runtime.misc.IntervalSet;
import org.antlr.v4.runtime.misc.Nullable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
@ -300,25 +299,20 @@ public class ATNConfigSet implements Set<ATNConfig> {
public ATNConfigSet(ATNConfigSet old, PredictionContextCache contextCache) { public ATNConfigSet(ATNConfigSet old, PredictionContextCache contextCache) {
this(old.fullCtx); this(old.fullCtx);
addAll(old, contextCache); addAll(old);
this.uniqueAlt = old.uniqueAlt; this.uniqueAlt = old.uniqueAlt;
this.conflictingAlts = old.conflictingAlts; this.conflictingAlts = old.conflictingAlts;
this.hasSemanticContext = old.hasSemanticContext; this.hasSemanticContext = old.hasSemanticContext;
this.dipsIntoOuterContext = old.dipsIntoOuterContext; this.dipsIntoOuterContext = old.dipsIntoOuterContext;
} }
@Override
public boolean add(ATNConfig e) {
return add(e, null);
}
/** Adding a new config means merging contexts with existing configs for /** Adding a new config means merging contexts with existing configs for
* (s, i, pi, _) * (s, i, pi, _)
* We use (s,i,pi) as key * We use (s,i,pi) as key
*/ */
public boolean add(ATNConfig config, @Nullable PredictionContextCache contextCache) { @Override
public boolean add(ATNConfig config) {
if ( readonly ) throw new IllegalStateException("This set is readonly"); if ( readonly ) throw new IllegalStateException("This set is readonly");
contextCache = null; // TODO: costs time to cache and saves essentially no RAM
if ( config.semanticContext!=SemanticContext.NONE ) { if ( config.semanticContext!=SemanticContext.NONE ) {
hasSemanticContext = true; hasSemanticContext = true;
} }
@ -330,11 +324,10 @@ public class ATNConfigSet implements Set<ATNConfig> {
// a previous (s,i,pi,_), merge with it and save result // a previous (s,i,pi,_), merge with it and save result
boolean rootIsWildcard = !fullCtx; boolean rootIsWildcard = !fullCtx;
PredictionContext merged = PredictionContext merged =
PredictionContext.merge(existing.context, config.context, contextCache, rootIsWildcard); PredictionContext.merge(existing.context, config.context, rootIsWildcard);
// no need to check for existing.context, config.context in cache // no need to check for existing.context, config.context in cache
// since only way to create new graphs is "call rule" and here. We // since only way to create new graphs is "call rule" and here. We
// cache at both places. // cache at both places.
if ( contextCache!=null ) merged = contextCache.add(merged);
existing.reachesIntoOuterContext = existing.reachesIntoOuterContext =
Math.max(existing.reachesIntoOuterContext, config.reachesIntoOuterContext); Math.max(existing.reachesIntoOuterContext, config.reachesIntoOuterContext);
existing.context = merged; // replace context; no need to alt mapping existing.context = merged; // replace context; no need to alt mapping
@ -384,17 +377,8 @@ public class ATNConfigSet implements Set<ATNConfig> {
} }
} }
@Override public boolean addAll(Collection<? extends ATNConfig> coll) {
public boolean addAll(Collection<? extends ATNConfig> c) { for (ATNConfig c : coll) add(c);
return addAll(c, null);
}
public boolean addAll(Collection<? extends ATNConfig> coll,
PredictionContextCache contextCache)
{
for (ATNConfig c : coll) {
add(c, contextCache);
}
return false; return false;
} }

View File

@ -50,28 +50,23 @@ public abstract class ATNSimulator {
* to use only cached nodes/graphs in addDFAState(). We don't want to * to use only cached nodes/graphs in addDFAState(). We don't want to
* fill this during closure() since there are lots of contexts that * fill this during closure() since there are lots of contexts that
* pop up but are not used ever again. It also greatly slows down closure(). * pop up but are not used ever again. It also greatly slows down closure().
*
* This cache makes a huge difference in memory and a little bit in speed.
* For the Java grammar on java.*, it dropped the memory requirements
* at the end from 25M to 16M. We don't store any of the full context
* graphs in the DFA because they are limited to local context only,
* but apparently there's a lot of repetition there as well. We optimize
* the config contexts before storing the config set in the DFA states
* by literally rebuilding them with cached subgraphs only.
*
* I tried a cache for use during closure operations, that was
* whacked after each adaptivePredict(). It cost a little bit
* more time I think and doesn't save on the overall footprint
* so it's not worth the complexity.
*/ */
protected final PredictionContextCache sharedContextCache = protected final PredictionContextCache sharedContextCache =
new PredictionContextCache("shared DFA state context cache"); new PredictionContextCache("shared DFA state context cache");
/** This context cache tracks all context graphs used during a single
* ATN-based prediction operation. There will be significant context graph
* sharing among ATNConfigSets because all sets are derived from the
* same starting context.
*
* This cache is blown away after each adaptivePredict()
* because we cache everything within ATNConfigSets that become DFA
* states in sharedContextCache. (Sam thinks of this as an analogy to
* the nursery in a generational GC; then, sharedContextCache would be
* the mature generation.)
*
* In Sam's version, this is a parameter passed down through all of
* the methods, but it gets pretty unwieldy as there are already
* a crapload of parameters. Consequently, I'm using a field as a
* "parameter" despite it being generally poor coding style.
*/
protected PredictionContextCache contextCache;
static { static {
ERROR = new DFAState(new ATNConfigSet()); ERROR = new DFAState(new ATNConfigSet());
ERROR.stateNumber = Integer.MAX_VALUE; ERROR.stateNumber = Integer.MAX_VALUE;

View File

@ -1,7 +1,5 @@
package org.antlr.v4.runtime.atn; package org.antlr.v4.runtime.atn;
import org.antlr.v4.runtime.misc.NotNull;
import java.util.Arrays; import java.util.Arrays;
import java.util.Iterator; import java.util.Iterator;
@ -126,7 +124,6 @@ public class ArrayPredictionContext extends PredictionContext {
*/ */
@Override @Override
public PredictionContext popAll(int invokingState, public PredictionContext popAll(int invokingState,
@NotNull PredictionContextCache contextCache,
boolean fullCtx) boolean fullCtx)
{ {
int index = Arrays.binarySearch(this.invokingStates, invokingState); int index = Arrays.binarySearch(this.invokingStates, invokingState);
@ -135,7 +132,7 @@ public class ArrayPredictionContext extends PredictionContext {
} }
PredictionContext newCtx = PredictionContext newCtx =
this.parents[index].popAll(invokingState, contextCache, fullCtx); this.parents[index].popAll(invokingState, fullCtx);
for (int i = 0; i < this.invokingStates.length; i++) { for (int i = 0; i < this.invokingStates.length; i++) {
if (i == index) continue; if (i == index) continue;
PredictionContext next; PredictionContext next;
@ -145,10 +142,9 @@ public class ArrayPredictionContext extends PredictionContext {
else { else {
next = new SingletonPredictionContext(this.parents[i], next = new SingletonPredictionContext(this.parents[i],
this.invokingStates[i]); this.invokingStates[i]);
if ( contextCache!=null ) next = contextCache.add(next);
} }
boolean rootIsWildcard = fullCtx; boolean rootIsWildcard = fullCtx;
newCtx = merge(newCtx, next, contextCache, rootIsWildcard); newCtx = merge(newCtx, next, rootIsWildcard);
} }
return newCtx; return newCtx;

View File

@ -235,7 +235,6 @@ public class ParserATNSimulator<Symbol extends Token> extends ATNSimulator {
throw nvae; throw nvae;
} }
finally { finally {
contextCache = null; // wack the cache
input.seek(index); input.seek(index);
input.release(m); input.release(m);
} }
@ -268,7 +267,6 @@ public class ParserATNSimulator<Symbol extends Token> extends ATNSimulator {
if ( dfa_debug ) System.out.println("ctx sensitive state "+outerContext+" in "+s); if ( dfa_debug ) System.out.println("ctx sensitive state "+outerContext+" in "+s);
boolean loopsSimulateTailRecursion = true; boolean loopsSimulateTailRecursion = true;
boolean fullCtx = true; boolean fullCtx = true;
// contextCache = new PredictionContextCache("predict ctx cache built in execDFA");
ATNConfigSet s0_closure = ATNConfigSet s0_closure =
computeStartState(dfa.atnStartState, outerContext, computeStartState(dfa.atnStartState, outerContext,
greedy, loopsSimulateTailRecursion, greedy, loopsSimulateTailRecursion,
@ -280,7 +278,6 @@ public class ParserATNSimulator<Symbol extends Token> extends ATNSimulator {
outerContext, outerContext,
ATN.INVALID_ALT_NUMBER, ATN.INVALID_ALT_NUMBER,
greedy); greedy);
contextCache = null;
return fullCtxSet.uniqueAlt; return fullCtxSet.uniqueAlt;
} }
if ( s.isAcceptState ) { if ( s.isAcceptState ) {
@ -312,9 +309,7 @@ public class ParserATNSimulator<Symbol extends Token> extends ATNSimulator {
" at DFA state "+s.stateNumber); " at DFA state "+s.stateNumber);
} }
// contextCache = new PredictionContextCache("predict ctx cache built in execDFA");
alt = execATN(dfa, s, input, startIndex, outerContext); alt = execATN(dfa, s, input, startIndex, outerContext);
contextCache = null;
// this adds edge even if next state is accept for // this adds edge even if next state is accept for
// same alt; e.g., s0-A->:s1=>2-B->:s2=>2 // same alt; e.g., s0-A->:s1=>2-B->:s2=>2
// TODO: This next stuff kills edge, but extra states remain. :( // TODO: This next stuff kills edge, but extra states remain. :(
@ -625,7 +620,7 @@ public class ParserATNSimulator<Symbol extends Token> extends ATNSimulator {
Transition trans = c.state.transition(ti); Transition trans = c.state.transition(ti);
ATNState target = getReachableTarget(trans, t); ATNState target = getReachableTarget(trans, t);
if ( target!=null ) { if ( target!=null ) {
intermediate.add(new ATNConfig(c, target), contextCache); intermediate.add(new ATNConfig(c, target));
} }
} }
} }
@ -873,7 +868,7 @@ public class ParserATNSimulator<Symbol extends Token> extends ATNSimulator {
// don't see past end of a rule for any nongreedy decision // don't see past end of a rule for any nongreedy decision
if ( debug ) System.out.println("NONGREEDY at stop state of "+ if ( debug ) System.out.println("NONGREEDY at stop state of "+
getRuleName(config.state.ruleIndex)); getRuleName(config.state.ruleIndex));
configs.add(config, contextCache); configs.add(config);
return; return;
} }
// We hit rule end. If we have context info, use it // We hit rule end. If we have context info, use it
@ -917,7 +912,6 @@ public class ParserATNSimulator<Symbol extends Token> extends ATNSimulator {
{ {
config.context = config.context =
new SingletonPredictionContext(config.context, config.state.stateNumber); new SingletonPredictionContext(config.context, config.state.stateNumber);
if ( contextCache!=null ) config.context = contextCache.add(config.context);
// alter config; it's ok, since all calls to closure pass in a fresh config for us to chase // alter config; it's ok, since all calls to closure pass in a fresh config for us to chase
if ( debug ) System.out.println("Loop back; push "+config.state.stateNumber+", stack="+config.context); if ( debug ) System.out.println("Loop back; push "+config.state.stateNumber+", stack="+config.context);
} }
@ -926,7 +920,6 @@ public class ParserATNSimulator<Symbol extends Token> extends ATNSimulator {
LoopEndState end = (LoopEndState)config.state; LoopEndState end = (LoopEndState)config.state;
// pop all the way back until we don't see the loopback state anymore // pop all the way back until we don't see the loopback state anymore
config.context = config.context.popAll(end.loopBackStateNumber, config.context = config.context.popAll(end.loopBackStateNumber,
contextCache,
configs.fullCtx); configs.fullCtx);
if ( debug ) System.out.println(" becomes "+config.context); if ( debug ) System.out.println(" becomes "+config.context);
} }
@ -949,7 +942,7 @@ public class ParserATNSimulator<Symbol extends Token> extends ATNSimulator {
ATNState p = config.state; ATNState p = config.state;
// optimization // optimization
if ( !p.onlyHasEpsilonTransitions() ) { if ( !p.onlyHasEpsilonTransitions() ) {
configs.add(config, contextCache); configs.add(config);
if ( config.semanticContext!=null && config.semanticContext!= SemanticContext.NONE ) { if ( config.semanticContext!=null && config.semanticContext!= SemanticContext.NONE ) {
configs.hasSemanticContext = true; configs.hasSemanticContext = true;
} }
@ -1086,7 +1079,6 @@ public class ParserATNSimulator<Symbol extends Token> extends ATNSimulator {
} }
PredictionContext newContext = PredictionContext newContext =
new SingletonPredictionContext(config.context, config.state.stateNumber); new SingletonPredictionContext(config.context, config.state.stateNumber);
if ( contextCache!=null ) newContext = contextCache.add(newContext);
return new ATNConfig(config, t.target, newContext); return new ATNConfig(config, t.target, newContext);
} }

View File

@ -72,7 +72,6 @@ public abstract class PredictionContext implements Iterable<SingletonPredictionC
} }
public abstract PredictionContext popAll(int invokingState, public abstract PredictionContext popAll(int invokingState,
@NotNull PredictionContextCache contextCache,
boolean fullCtx); boolean fullCtx);
@Override @Override
@ -119,7 +118,6 @@ public abstract class PredictionContext implements Iterable<SingletonPredictionC
// dispatch // dispatch
public static PredictionContext merge(PredictionContext a, PredictionContext b, public static PredictionContext merge(PredictionContext a, PredictionContext b,
@NotNull PredictionContextCache contextCache,
boolean rootIsWildcard) boolean rootIsWildcard)
{ {
if ( (a==null&&b==null) || a==b || a.equals(b) ) return a; // share same graph if both same if ( (a==null&&b==null) || a==b || a.equals(b) ) return a; // share same graph if both same
@ -127,7 +125,6 @@ public abstract class PredictionContext implements Iterable<SingletonPredictionC
if ( a instanceof SingletonPredictionContext && b instanceof SingletonPredictionContext) { if ( a instanceof SingletonPredictionContext && b instanceof SingletonPredictionContext) {
return mergeSingletons((SingletonPredictionContext)a, return mergeSingletons((SingletonPredictionContext)a,
(SingletonPredictionContext)b, (SingletonPredictionContext)b,
contextCache,
rootIsWildcard); rootIsWildcard);
} }
@ -146,21 +143,19 @@ public abstract class PredictionContext implements Iterable<SingletonPredictionC
b = new ArrayPredictionContext((SingletonPredictionContext)b); b = new ArrayPredictionContext((SingletonPredictionContext)b);
} }
return mergeArrays((ArrayPredictionContext) a, (ArrayPredictionContext) b, return mergeArrays((ArrayPredictionContext) a, (ArrayPredictionContext) b,
contextCache,
rootIsWildcard); rootIsWildcard);
} }
// http://www.antlr.org/wiki/download/attachments/32014352/singleton-merge.png // http://www.antlr.org/wiki/download/attachments/32014352/singleton-merge.png
public static PredictionContext mergeSingletons(SingletonPredictionContext a, public static PredictionContext mergeSingletons(SingletonPredictionContext a,
SingletonPredictionContext b, SingletonPredictionContext b,
@NotNull PredictionContextCache contextCache,
boolean rootIsWildcard) boolean rootIsWildcard)
{ {
PredictionContext rootMerge = mergeRoot(a, b, contextCache, rootIsWildcard); PredictionContext rootMerge = mergeRoot(a, b, rootIsWildcard);
if ( rootMerge!=null ) return rootMerge; if ( rootMerge!=null ) return rootMerge;
if ( a.invokingState==b.invokingState ) { // a == b if ( a.invokingState==b.invokingState ) { // a == b
PredictionContext parent = merge(a.parent, b.parent, contextCache, rootIsWildcard); PredictionContext parent = merge(a.parent, b.parent, rootIsWildcard);
// if parent is same as existing a or b parent or reduced to a parent, return it // if parent is same as existing a or b parent or reduced to a parent, return it
if ( parent == a.parent ) return a; // ax + bx = ax, if a=b if ( parent == a.parent ) return a; // ax + bx = ax, if a=b
if ( parent == b.parent ) return b; // ax + bx = bx, if a=b if ( parent == b.parent ) return b; // ax + bx = bx, if a=b
@ -169,7 +164,6 @@ public abstract class PredictionContext implements Iterable<SingletonPredictionC
// of those graphs. dup a, a' points at merged array // of those graphs. dup a, a' points at merged array
// new joined parent so create new singleton pointing to it, a' // new joined parent so create new singleton pointing to it, a'
PredictionContext a_ = new SingletonPredictionContext(parent, a.invokingState); PredictionContext a_ = new SingletonPredictionContext(parent, a.invokingState);
if ( contextCache!=null ) a_ = contextCache.add(a_);
return a_; return a_;
} }
else { // a != b payloads differ else { // a != b payloads differ
@ -191,7 +185,6 @@ public abstract class PredictionContext implements Iterable<SingletonPredictionC
} }
PredictionContext[] parents = {singleParent, singleParent}; PredictionContext[] parents = {singleParent, singleParent};
PredictionContext a_ = new ArrayPredictionContext(parents, payloads); PredictionContext a_ = new ArrayPredictionContext(parents, payloads);
if ( contextCache!=null ) a_ = contextCache.add(a_);
return a_; return a_;
} }
// parents differ and can't merge them. Just pack together // parents differ and can't merge them. Just pack together
@ -205,7 +198,6 @@ public abstract class PredictionContext implements Iterable<SingletonPredictionC
parents = new PredictionContext[] {b.parent, a.parent}; parents = new PredictionContext[] {b.parent, a.parent};
} }
PredictionContext a_ = new ArrayPredictionContext(parents, payloads); PredictionContext a_ = new ArrayPredictionContext(parents, payloads);
if ( contextCache!=null ) a_ = contextCache.add(a_);
return a_; return a_;
} }
} }
@ -215,7 +207,6 @@ public abstract class PredictionContext implements Iterable<SingletonPredictionC
/** Handle case where at least one of a or b is $ (EMPTY) */ /** Handle case where at least one of a or b is $ (EMPTY) */
public static PredictionContext mergeRoot(SingletonPredictionContext a, public static PredictionContext mergeRoot(SingletonPredictionContext a,
SingletonPredictionContext b, SingletonPredictionContext b,
@NotNull PredictionContextCache contextCache,
boolean rootIsWildcard) boolean rootIsWildcard)
{ {
if ( rootIsWildcard ) { if ( rootIsWildcard ) {
@ -229,7 +220,6 @@ public abstract class PredictionContext implements Iterable<SingletonPredictionC
PredictionContext[] parents = {null, b.parent}; PredictionContext[] parents = {null, b.parent};
PredictionContext joined = PredictionContext joined =
new ArrayPredictionContext(parents, payloads); new ArrayPredictionContext(parents, payloads);
if ( contextCache!=null ) joined = contextCache.add(joined);
return joined; return joined;
} }
if ( b == EMPTY ) { // x + $ = [$,x] ($ is always first if present) if ( b == EMPTY ) { // x + $ = [$,x] ($ is always first if present)
@ -237,7 +227,6 @@ public abstract class PredictionContext implements Iterable<SingletonPredictionC
PredictionContext[] parents = {null, a.parent}; PredictionContext[] parents = {null, a.parent};
PredictionContext joined = PredictionContext joined =
new ArrayPredictionContext(parents, payloads); new ArrayPredictionContext(parents, payloads);
if ( contextCache!=null ) joined = contextCache.add(joined);
return joined; return joined;
} }
} }
@ -247,7 +236,6 @@ public abstract class PredictionContext implements Iterable<SingletonPredictionC
// http://www.antlr.org/wiki/download/attachments/32014352/array-merge.png // http://www.antlr.org/wiki/download/attachments/32014352/array-merge.png
public static PredictionContext mergeArrays(ArrayPredictionContext a, public static PredictionContext mergeArrays(ArrayPredictionContext a,
ArrayPredictionContext b, ArrayPredictionContext b,
@NotNull PredictionContextCache contextCache,
boolean rootIsWildcard) boolean rootIsWildcard)
{ {
// merge sorted payloads a + b => M // merge sorted payloads a + b => M
@ -277,7 +265,7 @@ public abstract class PredictionContext implements Iterable<SingletonPredictionC
} }
else { // ax+ay -> a'[x,y] else { // ax+ay -> a'[x,y]
PredictionContext mergedParent = PredictionContext mergedParent =
merge(a_parent, b_parent, contextCache, rootIsWildcard); merge(a_parent, b_parent, rootIsWildcard);
mergedParents[k] = mergedParent; mergedParents[k] = mergedParent;
mergedInvokingStates[k] = payload; mergedInvokingStates[k] = payload;
} }
@ -325,7 +313,6 @@ public abstract class PredictionContext implements Iterable<SingletonPredictionC
if ( n == 1 ) { // for just one merged element, return singleton top if ( n == 1 ) { // for just one merged element, return singleton top
PredictionContext a_ = new SingletonPredictionContext(mergedParents[0], PredictionContext a_ = new SingletonPredictionContext(mergedParents[0],
mergedInvokingStates[0]); mergedInvokingStates[0]);
a_ = contextCache.add(a_);
return a_; return a_;
} }
mergedParents = Arrays.copyOf(mergedParents, n); mergedParents = Arrays.copyOf(mergedParents, n);
@ -335,7 +322,6 @@ public abstract class PredictionContext implements Iterable<SingletonPredictionC
PredictionContext M = PredictionContext M =
new ArrayPredictionContext(mergedParents, mergedInvokingStates); new ArrayPredictionContext(mergedParents, mergedInvokingStates);
if ( contextCache!=null ) M = contextCache.add(M);
// if we created same array as a or b, return that instead // if we created same array as a or b, return that instead
// TODO: track whether this is possible above during merge sort for speed // TODO: track whether this is possible above during merge sort for speed

View File

@ -1,7 +1,5 @@
package org.antlr.v4.runtime.atn; package org.antlr.v4.runtime.atn;
import org.antlr.v4.runtime.misc.NotNull;
import java.util.Iterator; import java.util.Iterator;
public class SingletonPredictionContext extends PredictionContext { public class SingletonPredictionContext extends PredictionContext {
@ -52,11 +50,10 @@ public class SingletonPredictionContext extends PredictionContext {
@Override @Override
public PredictionContext popAll(int invokingState, public PredictionContext popAll(int invokingState,
@NotNull PredictionContextCache contextCache,
boolean fullCtx) boolean fullCtx)
{ {
if ( invokingState == this.invokingState ) { if ( invokingState == this.invokingState ) {
return parent.popAll(invokingState, contextCache, fullCtx); return parent.popAll(invokingState, fullCtx);
} }
return this; return this;
} }

View File

@ -22,7 +22,6 @@ public class TestGraphNodes extends TestCase {
@Test public void test_$_$() { @Test public void test_$_$() {
PredictionContext r = PredictionContext.merge(PredictionContext.EMPTY, PredictionContext r = PredictionContext.merge(PredictionContext.EMPTY,
PredictionContext.EMPTY, PredictionContext.EMPTY,
contextCache,
rootIsWildcard()); rootIsWildcard());
System.out.println(PredictionContext.toDOTString(r)); System.out.println(PredictionContext.toDOTString(r));
String expecting = String expecting =
@ -36,7 +35,6 @@ public class TestGraphNodes extends TestCase {
@Test public void test_$_$_fullctx() { @Test public void test_$_$_fullctx() {
PredictionContext r = PredictionContext.merge(PredictionContext.EMPTY, PredictionContext r = PredictionContext.merge(PredictionContext.EMPTY,
PredictionContext.EMPTY, PredictionContext.EMPTY,
contextCache,
fullCtx()); fullCtx());
System.out.println(PredictionContext.toDOTString(r)); System.out.println(PredictionContext.toDOTString(r));
String expecting = String expecting =
@ -48,7 +46,7 @@ public class TestGraphNodes extends TestCase {
} }
@Test public void test_x_$() { @Test public void test_x_$() {
PredictionContext r = PredictionContext.merge(x(), PredictionContext.EMPTY, contextCache, rootIsWildcard()); PredictionContext r = PredictionContext.merge(x(), PredictionContext.EMPTY, rootIsWildcard());
System.out.println(PredictionContext.toDOTString(r)); System.out.println(PredictionContext.toDOTString(r));
String expecting = String expecting =
"digraph G {\n" + "digraph G {\n" +
@ -59,7 +57,7 @@ public class TestGraphNodes extends TestCase {
} }
@Test public void test_x_$_fullctx() { @Test public void test_x_$_fullctx() {
PredictionContext r = PredictionContext.merge(x(), PredictionContext.EMPTY, contextCache, fullCtx()); PredictionContext r = PredictionContext.merge(x(), PredictionContext.EMPTY, fullCtx());
System.out.println(PredictionContext.toDOTString(r)); System.out.println(PredictionContext.toDOTString(r));
String expecting = String expecting =
"digraph G {\n" + "digraph G {\n" +
@ -72,7 +70,7 @@ public class TestGraphNodes extends TestCase {
} }
@Test public void test_$_x() { @Test public void test_$_x() {
PredictionContext r = PredictionContext.merge(PredictionContext.EMPTY, x(), contextCache, rootIsWildcard()); PredictionContext r = PredictionContext.merge(PredictionContext.EMPTY, x(), rootIsWildcard());
System.out.println(PredictionContext.toDOTString(r)); System.out.println(PredictionContext.toDOTString(r));
String expecting = String expecting =
"digraph G {\n" + "digraph G {\n" +
@ -83,7 +81,7 @@ public class TestGraphNodes extends TestCase {
} }
@Test public void test_$_x_fullctx() { @Test public void test_$_x_fullctx() {
PredictionContext r = PredictionContext.merge(PredictionContext.EMPTY, x(), contextCache, fullCtx()); PredictionContext r = PredictionContext.merge(PredictionContext.EMPTY, x(), fullCtx());
System.out.println(PredictionContext.toDOTString(r)); System.out.println(PredictionContext.toDOTString(r));
String expecting = String expecting =
"digraph G {\n" + "digraph G {\n" +
@ -96,7 +94,7 @@ public class TestGraphNodes extends TestCase {
} }
@Test public void test_a_a() { @Test public void test_a_a() {
PredictionContext r = PredictionContext.merge(a(), a(), contextCache, rootIsWildcard()); PredictionContext r = PredictionContext.merge(a(), a(), rootIsWildcard());
System.out.println(PredictionContext.toDOTString(r)); System.out.println(PredictionContext.toDOTString(r));
String expecting = String expecting =
"digraph G {\n" + "digraph G {\n" +
@ -112,7 +110,7 @@ public class TestGraphNodes extends TestCase {
PredictionContext a1 = a(); PredictionContext a1 = a();
PredictionContext x = x(); PredictionContext x = x();
PredictionContext a2 = createSingleton(x, 1); PredictionContext a2 = createSingleton(x, 1);
PredictionContext r = PredictionContext.merge(a1, a2, contextCache, rootIsWildcard()); PredictionContext r = PredictionContext.merge(a1, a2, rootIsWildcard());
System.out.println(PredictionContext.toDOTString(r)); System.out.println(PredictionContext.toDOTString(r));
String expecting = String expecting =
"digraph G {\n" + "digraph G {\n" +
@ -128,7 +126,7 @@ public class TestGraphNodes extends TestCase {
PredictionContext a1 = a(); PredictionContext a1 = a();
PredictionContext x = x(); PredictionContext x = x();
PredictionContext a2 = createSingleton(x, 1); PredictionContext a2 = createSingleton(x, 1);
PredictionContext r = PredictionContext.merge(a1, a2, contextCache, fullCtx()); PredictionContext r = PredictionContext.merge(a1, a2, fullCtx());
System.out.println(PredictionContext.toDOTString(r)); System.out.println(PredictionContext.toDOTString(r));
String expecting = String expecting =
"digraph G {\n" + "digraph G {\n" +
@ -146,7 +144,7 @@ public class TestGraphNodes extends TestCase {
PredictionContext x = x(); PredictionContext x = x();
PredictionContext a1 = createSingleton(x, 1); PredictionContext a1 = createSingleton(x, 1);
PredictionContext a2 = a(); PredictionContext a2 = a();
PredictionContext r = PredictionContext.merge(a1, a2, contextCache, rootIsWildcard()); PredictionContext r = PredictionContext.merge(a1, a2, rootIsWildcard());
System.out.println(PredictionContext.toDOTString(r)); System.out.println(PredictionContext.toDOTString(r));
String expecting = String expecting =
"digraph G {\n" + "digraph G {\n" +
@ -162,7 +160,7 @@ public class TestGraphNodes extends TestCase {
PredictionContext x = x(); PredictionContext x = x();
PredictionContext a1 = createSingleton(x, 1); PredictionContext a1 = createSingleton(x, 1);
PredictionContext a2 = a(); PredictionContext a2 = a();
PredictionContext r = PredictionContext.merge(a1, a2, contextCache, fullCtx()); PredictionContext r = PredictionContext.merge(a1, a2, fullCtx());
System.out.println(PredictionContext.toDOTString(r)); System.out.println(PredictionContext.toDOTString(r));
String expecting = String expecting =
"digraph G {\n" + "digraph G {\n" +
@ -177,7 +175,7 @@ public class TestGraphNodes extends TestCase {
} }
@Test public void test_a_b() { @Test public void test_a_b() {
PredictionContext r = PredictionContext.merge(a(), b(), contextCache, rootIsWildcard()); PredictionContext r = PredictionContext.merge(a(), b(), rootIsWildcard());
System.out.println(PredictionContext.toDOTString(r)); System.out.println(PredictionContext.toDOTString(r));
String expecting = String expecting =
"digraph G {\n" + "digraph G {\n" +
@ -194,7 +192,7 @@ public class TestGraphNodes extends TestCase {
PredictionContext x = x(); PredictionContext x = x();
PredictionContext a1 = createSingleton(x, 1); PredictionContext a1 = createSingleton(x, 1);
PredictionContext a2 = createSingleton(x, 1); PredictionContext a2 = createSingleton(x, 1);
PredictionContext r = PredictionContext.merge(a1, a2, contextCache, rootIsWildcard()); PredictionContext r = PredictionContext.merge(a1, a2, rootIsWildcard());
System.out.println(PredictionContext.toDOTString(r)); System.out.println(PredictionContext.toDOTString(r));
String expecting = String expecting =
"digraph G {\n" + "digraph G {\n" +
@ -213,7 +211,7 @@ public class TestGraphNodes extends TestCase {
PredictionContext x2 = x(); PredictionContext x2 = x();
PredictionContext a1 = createSingleton(x1, 1); PredictionContext a1 = createSingleton(x1, 1);
PredictionContext a2 = createSingleton(x2, 1); PredictionContext a2 = createSingleton(x2, 1);
PredictionContext r = PredictionContext.merge(a1, a2, contextCache, rootIsWildcard()); PredictionContext r = PredictionContext.merge(a1, a2, rootIsWildcard());
System.out.println(PredictionContext.toDOTString(r)); System.out.println(PredictionContext.toDOTString(r));
String expecting = String expecting =
"digraph G {\n" + "digraph G {\n" +
@ -234,7 +232,7 @@ public class TestGraphNodes extends TestCase {
PredictionContext b2 = createSingleton(x2, 2); PredictionContext b2 = createSingleton(x2, 2);
PredictionContext a1 = createSingleton(b1, 1); PredictionContext a1 = createSingleton(b1, 1);
PredictionContext a2 = createSingleton(b2, 1); PredictionContext a2 = createSingleton(b2, 1);
PredictionContext r = PredictionContext.merge(a1, a2, contextCache, rootIsWildcard()); PredictionContext r = PredictionContext.merge(a1, a2, rootIsWildcard());
System.out.println(PredictionContext.toDOTString(r)); System.out.println(PredictionContext.toDOTString(r));
String expecting = String expecting =
"digraph G {\n" + "digraph G {\n" +
@ -257,7 +255,7 @@ public class TestGraphNodes extends TestCase {
PredictionContext c = createSingleton(x2, 3); PredictionContext c = createSingleton(x2, 3);
PredictionContext a1 = createSingleton(b, 1); PredictionContext a1 = createSingleton(b, 1);
PredictionContext a2 = createSingleton(c, 1); PredictionContext a2 = createSingleton(c, 1);
PredictionContext r = PredictionContext.merge(a1, a2, contextCache, rootIsWildcard()); PredictionContext r = PredictionContext.merge(a1, a2, rootIsWildcard());
System.out.println(PredictionContext.toDOTString(r)); System.out.println(PredictionContext.toDOTString(r));
String expecting = String expecting =
"digraph G {\n" + "digraph G {\n" +
@ -278,7 +276,7 @@ public class TestGraphNodes extends TestCase {
PredictionContext x = x(); PredictionContext x = x();
PredictionContext a = createSingleton(x, 1); PredictionContext a = createSingleton(x, 1);
PredictionContext b = createSingleton(x, 2); PredictionContext b = createSingleton(x, 2);
PredictionContext r = PredictionContext.merge(a, b, contextCache, rootIsWildcard()); PredictionContext r = PredictionContext.merge(a, b, rootIsWildcard());
System.out.println(PredictionContext.toDOTString(r)); System.out.println(PredictionContext.toDOTString(r));
String expecting = String expecting =
"digraph G {\n" + "digraph G {\n" +
@ -298,7 +296,7 @@ public class TestGraphNodes extends TestCase {
PredictionContext x2 = x(); PredictionContext x2 = x();
PredictionContext a = createSingleton(x1, 1); PredictionContext a = createSingleton(x1, 1);
PredictionContext b = createSingleton(x2, 2); PredictionContext b = createSingleton(x2, 2);
PredictionContext r = PredictionContext.merge(a, b, contextCache, rootIsWildcard()); PredictionContext r = PredictionContext.merge(a, b, rootIsWildcard());
System.out.println(PredictionContext.toDOTString(r)); System.out.println(PredictionContext.toDOTString(r));
String expecting = String expecting =
"digraph G {\n" + "digraph G {\n" +
@ -316,7 +314,7 @@ public class TestGraphNodes extends TestCase {
@Test public void test_ax_by() { @Test public void test_ax_by() {
PredictionContext a = createSingleton(x(), 1); PredictionContext a = createSingleton(x(), 1);
PredictionContext b = createSingleton(y(), 2); PredictionContext b = createSingleton(y(), 2);
PredictionContext r = PredictionContext.merge(a, b, contextCache, rootIsWildcard()); PredictionContext r = PredictionContext.merge(a, b, rootIsWildcard());
System.out.println(PredictionContext.toDOTString(r)); System.out.println(PredictionContext.toDOTString(r));
String expecting = String expecting =
"digraph G {\n" + "digraph G {\n" +
@ -337,7 +335,7 @@ public class TestGraphNodes extends TestCase {
PredictionContext x2 = x(); PredictionContext x2 = x();
PredictionContext a = a(); PredictionContext a = a();
PredictionContext b = createSingleton(x2, 2); PredictionContext b = createSingleton(x2, 2);
PredictionContext r = PredictionContext.merge(a, b, contextCache, rootIsWildcard()); PredictionContext r = PredictionContext.merge(a, b, rootIsWildcard());
System.out.println(PredictionContext.toDOTString(r)); System.out.println(PredictionContext.toDOTString(r));
String expecting = String expecting =
"digraph G {\n" + "digraph G {\n" +
@ -354,7 +352,7 @@ public class TestGraphNodes extends TestCase {
PredictionContext x2 = x(); PredictionContext x2 = x();
PredictionContext a = a(); PredictionContext a = a();
PredictionContext b = createSingleton(x2, 2); PredictionContext b = createSingleton(x2, 2);
PredictionContext r = PredictionContext.merge(a, b, contextCache, fullCtx()); PredictionContext r = PredictionContext.merge(a, b, fullCtx());
System.out.println(PredictionContext.toDOTString(r)); System.out.println(PredictionContext.toDOTString(r));
String expecting = String expecting =
"digraph G {\n" + "digraph G {\n" +
@ -376,7 +374,7 @@ public class TestGraphNodes extends TestCase {
PredictionContext f = createSingleton(x2, 6); PredictionContext f = createSingleton(x2, 6);
PredictionContext a = createSingleton(e, 1); PredictionContext a = createSingleton(e, 1);
PredictionContext b = createSingleton(f, 2); PredictionContext b = createSingleton(f, 2);
PredictionContext r = PredictionContext.merge(a, b, contextCache, rootIsWildcard()); PredictionContext r = PredictionContext.merge(a, b, rootIsWildcard());
System.out.println(PredictionContext.toDOTString(r)); System.out.println(PredictionContext.toDOTString(r));
String expecting = String expecting =
"digraph G {\n" + "digraph G {\n" +
@ -402,7 +400,7 @@ public class TestGraphNodes extends TestCase {
@Test public void test_A$_A$_fullctx() { @Test public void test_A$_A$_fullctx() {
ArrayPredictionContext A1 = array(PredictionContext.EMPTY); ArrayPredictionContext A1 = array(PredictionContext.EMPTY);
ArrayPredictionContext A2 = array(PredictionContext.EMPTY); ArrayPredictionContext A2 = array(PredictionContext.EMPTY);
PredictionContext r = PredictionContext.merge(A1, A2, contextCache, fullCtx()); PredictionContext r = PredictionContext.merge(A1, A2, fullCtx());
System.out.println(PredictionContext.toDOTString(r)); System.out.println(PredictionContext.toDOTString(r));
String expecting = String expecting =
"digraph G {\n" + "digraph G {\n" +
@ -418,7 +416,7 @@ public class TestGraphNodes extends TestCase {
SingletonPredictionContext c = c(); SingletonPredictionContext c = c();
ArrayPredictionContext A1 = array(a, b); ArrayPredictionContext A1 = array(a, b);
ArrayPredictionContext A2 = array(c); ArrayPredictionContext A2 = array(c);
PredictionContext r = PredictionContext.merge(A1, A2, contextCache, rootIsWildcard()); PredictionContext r = PredictionContext.merge(A1, A2, rootIsWildcard());
System.out.println(PredictionContext.toDOTString(r)); System.out.println(PredictionContext.toDOTString(r));
String expecting = String expecting =
"digraph G {\n" + "digraph G {\n" +
@ -437,7 +435,7 @@ public class TestGraphNodes extends TestCase {
SingletonPredictionContext a2 = a(); SingletonPredictionContext a2 = a();
ArrayPredictionContext A1 = array(a1); ArrayPredictionContext A1 = array(a1);
ArrayPredictionContext A2 = array(a2); ArrayPredictionContext A2 = array(a2);
PredictionContext r = PredictionContext.merge(A1, A2, contextCache, rootIsWildcard()); PredictionContext r = PredictionContext.merge(A1, A2, rootIsWildcard());
System.out.println(PredictionContext.toDOTString(r)); System.out.println(PredictionContext.toDOTString(r));
String expecting = String expecting =
"digraph G {\n" + "digraph G {\n" +
@ -455,7 +453,7 @@ public class TestGraphNodes extends TestCase {
SingletonPredictionContext c = c(); SingletonPredictionContext c = c();
ArrayPredictionContext A1 = array(a); ArrayPredictionContext A1 = array(a);
ArrayPredictionContext A2 = array(b, c); ArrayPredictionContext A2 = array(b, c);
PredictionContext r = PredictionContext.merge(A1, A2, contextCache, rootIsWildcard()); PredictionContext r = PredictionContext.merge(A1, A2, rootIsWildcard());
System.out.println(PredictionContext.toDOTString(r)); System.out.println(PredictionContext.toDOTString(r));
String expecting = String expecting =
"digraph G {\n" + "digraph G {\n" +
@ -475,7 +473,7 @@ public class TestGraphNodes extends TestCase {
SingletonPredictionContext c = c(); SingletonPredictionContext c = c();
ArrayPredictionContext A1 = array(a, c); ArrayPredictionContext A1 = array(a, c);
ArrayPredictionContext A2 = array(b); ArrayPredictionContext A2 = array(b);
PredictionContext r = PredictionContext.merge(A1, A2, contextCache, rootIsWildcard()); PredictionContext r = PredictionContext.merge(A1, A2, rootIsWildcard());
System.out.println(PredictionContext.toDOTString(r)); System.out.println(PredictionContext.toDOTString(r));
String expecting = String expecting =
"digraph G {\n" + "digraph G {\n" +
@ -492,7 +490,7 @@ public class TestGraphNodes extends TestCase {
@Test public void test_Aab_Aa() { // a,b + a @Test public void test_Aab_Aa() { // a,b + a
ArrayPredictionContext A1 = array(a(), b()); ArrayPredictionContext A1 = array(a(), b());
ArrayPredictionContext A2 = array(a()); ArrayPredictionContext A2 = array(a());
PredictionContext r = PredictionContext.merge(A1, A2, contextCache, rootIsWildcard()); PredictionContext r = PredictionContext.merge(A1, A2, rootIsWildcard());
System.out.println(PredictionContext.toDOTString(r)); System.out.println(PredictionContext.toDOTString(r));
String expecting = String expecting =
"digraph G {\n" + "digraph G {\n" +
@ -508,7 +506,7 @@ public class TestGraphNodes extends TestCase {
@Test public void test_Aab_Ab() { // a,b + b @Test public void test_Aab_Ab() { // a,b + b
ArrayPredictionContext A1 = array(a(), b()); ArrayPredictionContext A1 = array(a(), b());
ArrayPredictionContext A2 = array(b()); ArrayPredictionContext A2 = array(b());
PredictionContext r = PredictionContext.merge(A1, A2, contextCache, rootIsWildcard()); PredictionContext r = PredictionContext.merge(A1, A2, rootIsWildcard());
System.out.println(PredictionContext.toDOTString(r)); System.out.println(PredictionContext.toDOTString(r));
String expecting = String expecting =
"digraph G {\n" + "digraph G {\n" +
@ -526,7 +524,7 @@ public class TestGraphNodes extends TestCase {
SingletonPredictionContext b = createSingleton(y(), 2); SingletonPredictionContext b = createSingleton(y(), 2);
ArrayPredictionContext A1 = array(a); ArrayPredictionContext A1 = array(a);
ArrayPredictionContext A2 = array(b); ArrayPredictionContext A2 = array(b);
PredictionContext r = PredictionContext.merge(A1, A2, contextCache, rootIsWildcard()); PredictionContext r = PredictionContext.merge(A1, A2, rootIsWildcard());
System.out.println(PredictionContext.toDOTString(r)); System.out.println(PredictionContext.toDOTString(r));
String expecting = String expecting =
"digraph G {\n" + "digraph G {\n" +
@ -548,7 +546,7 @@ public class TestGraphNodes extends TestCase {
SingletonPredictionContext a2 = createSingleton(y(), 1); SingletonPredictionContext a2 = createSingleton(y(), 1);
ArrayPredictionContext A1 = array(a1); ArrayPredictionContext A1 = array(a1);
ArrayPredictionContext A2 = array(a2); ArrayPredictionContext A2 = array(a2);
PredictionContext r = PredictionContext.merge(A1, A2, contextCache, rootIsWildcard()); PredictionContext r = PredictionContext.merge(A1, A2, rootIsWildcard());
System.out.println(PredictionContext.toDOTString(r)); System.out.println(PredictionContext.toDOTString(r));
String expecting = String expecting =
"digraph G {\n" + "digraph G {\n" +
@ -568,7 +566,7 @@ public class TestGraphNodes extends TestCase {
SingletonPredictionContext a2 = createSingleton(y(), 1); SingletonPredictionContext a2 = createSingleton(y(), 1);
ArrayPredictionContext A1 = array(a1, c()); ArrayPredictionContext A1 = array(a1, c());
ArrayPredictionContext A2 = array(a2, d()); ArrayPredictionContext A2 = array(a2, d());
PredictionContext r = PredictionContext.merge(A1, A2, contextCache, rootIsWildcard()); PredictionContext r = PredictionContext.merge(A1, A2, rootIsWildcard());
System.out.println(PredictionContext.toDOTString(r)); System.out.println(PredictionContext.toDOTString(r));
String expecting = String expecting =
"digraph G {\n" + "digraph G {\n" +
@ -592,7 +590,7 @@ public class TestGraphNodes extends TestCase {
SingletonPredictionContext d = createSingleton(x(), 4); SingletonPredictionContext d = createSingleton(x(), 4);
ArrayPredictionContext A1 = array(a, b); ArrayPredictionContext A1 = array(a, b);
ArrayPredictionContext A2 = array(c, d); ArrayPredictionContext A2 = array(c, d);
PredictionContext r = PredictionContext.merge(A1, A2, contextCache, rootIsWildcard()); PredictionContext r = PredictionContext.merge(A1, A2, rootIsWildcard());
System.out.println(PredictionContext.toDOTString(r)); System.out.println(PredictionContext.toDOTString(r));
String expecting = String expecting =
"digraph G {\n" + "digraph G {\n" +
@ -622,7 +620,7 @@ public class TestGraphNodes extends TestCase {
SingletonPredictionContext d = createSingleton(x(), 4); SingletonPredictionContext d = createSingleton(x(), 4);
ArrayPredictionContext A1 = array(a, b1); ArrayPredictionContext A1 = array(a, b1);
ArrayPredictionContext A2 = array(b2, d); ArrayPredictionContext A2 = array(b2, d);
PredictionContext r = PredictionContext.merge(A1, A2, contextCache, rootIsWildcard()); PredictionContext r = PredictionContext.merge(A1, A2, rootIsWildcard());
System.out.println(PredictionContext.toDOTString(r)); System.out.println(PredictionContext.toDOTString(r));
String expecting = String expecting =
"digraph G {\n" + "digraph G {\n" +
@ -649,7 +647,7 @@ public class TestGraphNodes extends TestCase {
SingletonPredictionContext d = createSingleton(x(), 4); SingletonPredictionContext d = createSingleton(x(), 4);
ArrayPredictionContext A1 = array(a, b1); ArrayPredictionContext A1 = array(a, b1);
ArrayPredictionContext A2 = array(b2, d); ArrayPredictionContext A2 = array(b2, d);
PredictionContext r = PredictionContext.merge(A1, A2, contextCache, rootIsWildcard()); PredictionContext r = PredictionContext.merge(A1, A2, rootIsWildcard());
System.out.println(PredictionContext.toDOTString(r)); System.out.println(PredictionContext.toDOTString(r));
String expecting = String expecting =
"digraph G {\n" + "digraph G {\n" +
@ -677,7 +675,7 @@ public class TestGraphNodes extends TestCase {
SingletonPredictionContext d = createSingleton(u(), 4); SingletonPredictionContext d = createSingleton(u(), 4);
ArrayPredictionContext A1 = array(a, b1); ArrayPredictionContext A1 = array(a, b1);
ArrayPredictionContext A2 = array(b2, d); ArrayPredictionContext A2 = array(b2, d);
PredictionContext r = PredictionContext.merge(A1, A2, contextCache, rootIsWildcard()); PredictionContext r = PredictionContext.merge(A1, A2, rootIsWildcard());
System.out.println(PredictionContext.toDOTString(r)); System.out.println(PredictionContext.toDOTString(r));
String expecting = String expecting =
"digraph G {\n" + "digraph G {\n" +
@ -702,7 +700,7 @@ public class TestGraphNodes extends TestCase {
SingletonPredictionContext d = createSingleton(u(), 4); SingletonPredictionContext d = createSingleton(u(), 4);
ArrayPredictionContext A1 = array(a, b); ArrayPredictionContext A1 = array(a, b);
ArrayPredictionContext A2 = array(c, d); ArrayPredictionContext A2 = array(c, d);
PredictionContext r = PredictionContext.merge(A1, A2, contextCache, rootIsWildcard()); PredictionContext r = PredictionContext.merge(A1, A2, rootIsWildcard());
System.out.println(PredictionContext.toDOTString(r)); System.out.println(PredictionContext.toDOTString(r));
String expecting = String expecting =
"digraph G {\n" + "digraph G {\n" +