mergeSingletons static method
- SingletonPredictionContext a,
- SingletonPredictionContext b,
- bool rootIsWildcard,
- Map<
Pair< ? mergeCache,PredictionContext, PredictionContext> , PredictionContext>
Merge two SingletonPredictionContext instances.
Stack tops equal, parents merge is same; return left graph.
Same stack top, parents differ; merge parents giving array node, then
remainders of those graphs. A new root node is created to point to the
merged parents.
Different stack tops pointing to same parent. Make array node for the
root where both element in the root point to the same (original)
parent.
Different stack tops pointing to different parents. Make array node for
the root where each element points to the corresponding original
parent.
@param a the first SingletonPredictionContext
@param b the second SingletonPredictionContext
@param rootIsWildcard true
if this is a local-context merge,
otherwise false to indicate a full-context merge
@param mergeCache
Implementation
static PredictionContext mergeSingletons(
SingletonPredictionContext a,
SingletonPredictionContext b,
bool rootIsWildcard,
Map<Pair<PredictionContext, PredictionContext>, PredictionContext>?
mergeCache,
) {
if (mergeCache != null) {
var previous = mergeCache[Pair(a, b)];
if (previous != null) return previous;
previous = mergeCache[Pair(b, a)];
if (previous != null) return previous;
}
final rootMerge = mergeRoot(a, b, rootIsWildcard);
if (rootMerge != null) {
if (mergeCache != null) mergeCache[Pair(a, b)] = rootMerge;
return rootMerge;
}
if (a.returnState == b.returnState) {
assert(a.parent != null &&
b.parent != null); // must be empty context, never null
// a == b
final parent = merge(a.parent!, b.parent!, rootIsWildcard, mergeCache);
// 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 == b.parent) return b; // ax + bx = bx, if a=b
// else: ax + ay = a'[x,y]
// merge parents x and y, giving array node with x,y then remainders
// of those graphs. dup a, a' points at merged array
// new joined parent so create new singleton pointing to it, a'
PredictionContext a_ =
SingletonPredictionContext.create(parent, a.returnState);
if (mergeCache != null) mergeCache[Pair(a, b)] = a_;
return a_;
} else {
// a != b payloads differ
// see if we can collapse parents due to $+x parents if local ctx
PredictionContext? singleParent;
if (a == b || (a.parent != null && a.parent == b.parent)) {
// ax + bx = [a,b]x
singleParent = a.parent;
}
if (singleParent != null) {
// parents are same
// sort payloads and use same parent
final payloads = <int>[a.returnState, b.returnState];
if (a.returnState > b.returnState) {
payloads[0] = b.returnState;
payloads[1] = a.returnState;
}
final parents = <PredictionContext>[singleParent, singleParent];
PredictionContext a_ = ArrayPredictionContext(parents, payloads);
if (mergeCache != null) mergeCache[Pair(a, b)] = a_;
return a_;
}
// parents differ and can't merge them. Just pack together
// into array; can't merge.
// ax + by = [ax,by]
final payloads = <int>[a.returnState, b.returnState];
var parents = <PredictionContext?>[a.parent, b.parent];
if (a.returnState > b.returnState) {
// sort by payload
payloads[0] = b.returnState;
payloads[1] = a.returnState;
parents = [b.parent, a.parent];
}
PredictionContext a_ = ArrayPredictionContext(parents, payloads);
if (mergeCache != null) mergeCache[Pair(a, b)] = a_;
return a_;
}
}