/** * Set type <code>e</code> as <code>type</code> * * @param e * @param type */ void setType(ECR e, ValueType type) { ECR root = findRoot(e); root.setType(type); Collection<Pair<Size, ECR>> ccjoins = ImmutableList.copyOf(root.getCCjoins()); root.clearCCjoins(ccjoins); for (Pair<Size, ECR> cjoinPair : ccjoins) ccjoin(cjoinPair.fst(), root, cjoinPair.snd()); Collection<ECR> cjoins = ImmutableList.copyOf(root.getCjoins()); root.clearCjoins(cjoins); for (ECR joinECR : cjoins) cjoin(root, joinECR); }
/** * Collapse <code>structECR</code> by merge it with all its element ECRs, and set its type as the * cell type (simple type might with top size) * * @param structECR * @param structT * @param ECRCache avoid structure cycle * @return */ private ValueType collapseStruct(ECR structECR, StructType structT, Collection<ECR> ECRCache) { // Ensure collapsed type to be simple ValueType unionType = null; // join components Collection<ECR> elems = structT.getFieldMap().asMapOfRanges().values(); Collection<ECR> cjoins = Sets.newHashSet(); Collection<Pair<Size, ECR>> ccjoins = Sets.newHashSet(); for (ECR elem : elems) { ECR elemLoc = getLoc(elem); ValueType elemLocType = getType(elemLoc); Parent parent = elemLocType.getParent().removeECR(structECR); elemLocType.setParent(parent); if (!ECRCache.add(elemLoc)) continue; // ECRCache has elemLoc cjoins.addAll(getCjoins(elemLoc)); elemLoc.clearCCjoins(ccjoins); ccjoins.addAll(getCCjoins(elemLoc)); elemLoc.clearCCjoins(ccjoins); if (elemLocType.isStruct()) { elemLocType = collapseStruct(elemLoc, elemLocType.asStruct(), ECRCache); } union(structECR, elemLoc); unionType = unionType == null ? elemLocType : unify(unionType, elemLocType); } unionType = unionType == null ? ValueType.bottom() : unionType; setType(structECR, unionType); ECR root = findRoot(structECR); for (Pair<Size, ECR> cjoinPair : ccjoins) ccjoin(cjoinPair.fst(), root, cjoinPair.snd()); for (ECR joinECR : cjoins) cjoin(root, joinECR); return unionType; }
ECR join(ECR e1, ECR e2) { if (e1.equals(e2)) return e1; checkStructCollapse(e1, e2); ValueType t1 = getType(e1); ValueType t2 = getType(e2); Collection<Pair<Size, ECR>> ccjoins1 = ImmutableList.copyOf(getCCjoins(e1)); Collection<Pair<Size, ECR>> ccjoins2 = ImmutableList.copyOf(getCCjoins(e2)); Collection<ECR> cjoins1 = ImmutableList.copyOf(getCjoins(e1)); Collection<ECR> cjoins2 = ImmutableList.copyOf(getCjoins(e2)); ECR root = union(e1, e2); switch (t1.getKind()) { case BOTTOM: { switch (t2.getKind()) { case BOTTOM: { Collection<ECR> cjoins = Sets.newHashSet(); cjoins.addAll(cjoins1); cjoins.addAll(cjoins2); root.addCjoins(cjoins); Collection<Pair<Size, ECR>> ccjoins = Sets.newHashSet(); ccjoins.addAll(ccjoins1); ccjoins.addAll(ccjoins2); root.addCCjoins(ccjoins); break; } default: { root.setType(t2); root.clearCCjoins(ccjoins1); for (Pair<Size, ECR> pair : ccjoins1) ccjoin(pair.fst(), root, pair.snd()); root.clearCjoins(cjoins1); for (ECR cjoin : cjoins1) cjoin(root, cjoin); break; } } break; } default: { switch (t2.getKind()) { case BOTTOM: { root.setType(t1); root.clearCCjoins(ccjoins2); for (Pair<Size, ECR> pair : ccjoins2) ccjoin(pair.fst(), root, pair.snd()); root.clearCjoins(cjoins2); for (ECR cjoin : cjoins2) cjoin(root, cjoin); break; } default: { root.setType(t1); ValueType unionType = unify(t1, t2); ValueType freshType = getType(root); if (!freshType.equals(t1)) { unionType = resolveType(root, unionType, freshType); } root.setType(unionType); root.clearCCjoins(ccjoins1); root.clearCCjoins(ccjoins2); for (Pair<Size, ECR> pair : ccjoins1) ccjoin(pair.fst(), root, pair.snd()); for (Pair<Size, ECR> pair : ccjoins2) ccjoin(pair.fst(), root, pair.snd()); break; } } break; } } return root; }