package runtime;
/**
* COPYRIGHT WARNING: This code is taken from Jing!!!!!
*
* @author Kohsuke Kawaguchi (kk@kohsuke.org)
*/
final class StateFactory {
private static final int INIT_SIZE = 255;
private static final float LOAD_FACTOR = 0.3f;
// memoization table. one instance per one type
private final After after = new After();
private final Choice choice = new Choice();
private final Interleave interleave = new Interleave();
State makeAfter( State child, State then ) {
if( child==State.emptySet ) return child;
if( then==State.emptySet ) return then;
return after.create( child, then );
}
/**
* Creates a new State.Choice object.
*
* Caller needs to addRef two parameters.
*/
State makeChoice( State block, State primitive ) {
if(primitive instanceof State.Choice)
throw new InternalError("primitive is also a choice"); // a bug in the algorithm
if( block==State.emptySet )
return primitive;
if( primitive==State.emptySet )
return block;
if( block.contains(primitive) )
return block;
return choice.create(block,primitive);
}
/**
* Creates a new Interleave object.
*
* Caller needs to addRef two parameters.
*/
State makeInterleave( State lhs, State rhs, Transition.Interleave alphabet ) {
if(lhs==State.emptySet) return lhs;
if(rhs==State.emptySet) return rhs;
return interleave.create( lhs, rhs, alphabet );
}
/**
* Common base class for three slightly different table implementations.
*/
private abstract static class AbstractStateTable {
protected int used =0;
protected int usedLimit =(int) (INIT_SIZE * LOAD_FACTOR);
protected int tableSize =INIT_SIZE;
/** First-time hash function. */
protected abstract int firstIndex(State s);
/** Successive re-hash function. */
protected final int nextIndex(int h) {
return h==0 ? tableSize-1 : h-1;
}
/**
* rehash contenst of oldTable into newTable.
*/
protected final void rehash(State[] oldTable, State[] newTable) {
for (int i = oldTable.length; i > 0;) {
--i;
if (oldTable[i] != null) {
int j;
for (j = firstIndex(oldTable[i]);
newTable[j] != null;
j = nextIndex(j));
newTable[j] = oldTable[i];
}
}
usedLimit = (int) (newTable.length * LOAD_FACTOR);
tableSize = newTable.length;
}
}
/**
* Table for hash-consing. This table is used only for
* {@link State.After}.
*/
private final static class After extends AbstractStateTable {
private State.After[] table;
After() {
table = new State.After[INIT_SIZE];
}
private final int firstIndex( Object a, Object b ) {
return ( (a.hashCode()^b.hashCode())&0x7FFFFFFF )%tableSize;
}
protected int firstIndex(State s) {
State.After a = (State.After)s;
return firstIndex( a.child, a.then );
}
State.After create(State child, State then) {
int h;
for (h = firstIndex(child,then); table[h] != null; h = nextIndex(h)) {
State.After t = table[h];
if( t.child==child && t.then==then )
return t;
}
if (used >= usedLimit) {
State.After[] old = table;
table = new State.After[ old.length<<1 ];
rehash(old,table);
for (h = firstIndex(child,then); table[h] != null; h = nextIndex(h))
;
}
used++;
return table[h] = new State.After(child,then);
}
}
/**
* Table for hash-consing. This table is used only for
* {@link State.After}.
*/
private final static class Choice extends AbstractStateTable {
private State.Choice[] table;
Choice() {
table = new State.Choice[INIT_SIZE];
}
private final int firstIndex( Object a, Object b ) {
return ( a.hashCode()^b.hashCode()&0x7FFFFFFF )%tableSize;
}
protected int firstIndex(State s) {
State.Choice c = (State.Choice)s;
return firstIndex( c.lhs, c.rhs );
}
State.Choice create(State lhs, State rhs) {
int h;
for (h = firstIndex(lhs,rhs); table[h] != null; h = nextIndex(h)) {
State.Choice r = table[h];
if( r.lhs==lhs && r.rhs==rhs )
return r;
}
if (used >= usedLimit) {
State.Choice[] old = table;
table = new State.Choice[ old.length<<1 ];
rehash(old,table);
for (h = firstIndex(lhs,rhs); table[h] != null; h = nextIndex(h))
;
}
used++;
return table[h] = new State.Choice(lhs,rhs);
}
}
/**
* Table for hash-consing. This table is used only for
* {@link State.After}.
*/
private final static class Interleave extends AbstractStateTable {
private State.Interleave[] table;
Interleave() {
table = new State.Interleave[INIT_SIZE];
}
private final int firstIndex( Object a, Object b, Object c ) {
return ( (a.hashCode()^b.hashCode()^c.hashCode())&0x7FFFFFFF )%tableSize;
}
protected int firstIndex(State s) {
State.Interleave i = (State.Interleave)s;
return firstIndex( i.lhs, i.rhs, i.alphabet );
}
State.Interleave create(State lhs, State rhs, Transition.Interleave alpha ) {
int h;
for (h = firstIndex(lhs,rhs,alpha); table[h] != null; h = nextIndex(h)) {
State.Interleave r = table[h];
if( r.lhs==lhs && r.rhs==rhs && r.alphabet==alpha )
return r;
}
if (used >= usedLimit) {
State.Interleave[] old = table;
table = new State.Interleave[ old.length<<1 ];
rehash(old,table);
for (h = firstIndex(lhs,rhs,alpha); table[h] != null; h = nextIndex(h))
;
}
used++;
return table[h] = new State.Interleave(lhs,rhs,alpha);
}
}
}