public static PredictionContext GetCachedContext(PredictionContext context, PredictionContextCache contextCache, PredictionContext.IdentityHashMap visited)
{
if (context.IsEmpty)
{
return(context);
}
PredictionContext existing = visited.Get(context);
if (existing != null)
{
return(existing);
}
existing = contextCache.Get(context);
if (existing != null)
{
visited.Put(context, existing);
return(existing);
}
bool changed = false;
PredictionContext[] parents = new PredictionContext[context.Size];
for (int i = 0; i < parents.Length; i++)
{
PredictionContext parent = GetCachedContext(context.GetParent(i), contextCache, visited);
if (changed || parent != context.GetParent(i))
{
if (!changed)
{
parents = new PredictionContext[context.Size];
for (int j = 0; j < context.Size; j++)
{
parents[j] = context.GetParent(j);
}
changed = true;
}
parents[i] = parent;
}
}
if (!changed)
{
contextCache.Add(context);
visited.Put(context, context);
return(context);
}
PredictionContext updated;
if (parents.Length == 0)
{
updated = EMPTY;
}
else if (parents.Length == 1)
{
updated = SingletonPredictionContext.Create(parents[0], context.GetReturnState(0));
}
else
{
ArrayPredictionContext arrayPredictionContext = (ArrayPredictionContext)context;
updated = new ArrayPredictionContext(parents, arrayPredictionContext.returnStates);
}
contextCache.Add(updated);
visited.Put(updated, updated);
visited.Put(context, updated);
return(updated);
}