LinkedHashSet<UnorderedPair<EqClass>> getDistinctClassPairs() { if (myCachedDistinctClassPairs != null) return myCachedDistinctClassPairs; LinkedHashSet<UnorderedPair<EqClass>> result = ContainerUtil.newLinkedHashSet(); for (long encodedPair : myDistinctClasses.toArray()) { result.add( new UnorderedPair<>( myEqClasses.get(low(encodedPair)), myEqClasses.get(high(encodedPair)))); } return myCachedDistinctClassPairs = result; }
// look up and apply coarts for w to each sign in result @SuppressWarnings("unchecked") private void applyCoarts(Word w, SignHash result) throws LexException { List<Sign> inputSigns = new ArrayList<Sign>(result.asSignSet()); result.clear(); List<Sign> outputSigns = new ArrayList<Sign>(inputSigns.size()); // for each surface attr, lookup coarts and apply to input signs, storing results in output // signs for (Iterator<Pair<String, String>> it = w.getSurfaceAttrValPairs(); it.hasNext(); ) { Pair<String, String> p = it.next(); String attr = (String) p.a; if (!_indexedCoartAttrs.contains(attr)) continue; String val = (String) p.b; Word coartWord = Word.createWord(attr, val); SignHash coartResult = getSignsFromWord(coartWord, null, null, null); for (Iterator<Sign> it2 = coartResult.iterator(); it2.hasNext(); ) { Sign coartSign = it2.next(); // apply to each input for (int j = 0; j < inputSigns.size(); j++) { Sign sign = inputSigns.get(j); grammar.rules.applyCoart(sign, coartSign, outputSigns); } } // switch output to input for next iteration inputSigns.clear(); inputSigns.addAll(outputSigns); outputSigns.clear(); } // add results back result.addAll(inputSigns); }
// look up and apply coarts for given rels to each sign in result private void applyCoarts(List<String> coartRels, Collection<Sign> result) { List<Sign> inputSigns = new ArrayList<Sign>(result); result.clear(); List<Sign> outputSigns = new ArrayList<Sign>(inputSigns.size()); // for each rel, lookup coarts and apply to input signs, storing results in output signs for (Iterator<String> it = coartRels.iterator(); it.hasNext(); ) { String rel = it.next(); Collection<String> preds = (Collection<String>) _coartRelsToPreds.get(rel); if (preds == null) continue; // not expected Collection<Sign> coartResult = getSignsFromRelAndPreds(rel, preds); if (coartResult == null) continue; for (Iterator<Sign> it2 = coartResult.iterator(); it2.hasNext(); ) { Sign coartSign = it2.next(); // apply to each input for (int j = 0; j < inputSigns.size(); j++) { Sign sign = inputSigns.get(j); grammar.rules.applyCoart(sign, coartSign, outputSigns); } } // switch output to input for next iteration inputSigns.clear(); inputSigns.addAll(outputSigns); outputSigns.clear(); } // add results back result.addAll(inputSigns); }
private void applyChildrenChangeEvents(VirtualFile parent, List<VFileEvent> events) { final NewVirtualFileSystem delegate = getDelegate(parent); TIntArrayList childrenIdsUpdated = new TIntArrayList(); List<VirtualFile> childrenToBeUpdated = new SmartList<VirtualFile>(); assert parent != null && parent != mySuperRoot; final int parentId = getFileId(parent); assert parentId != 0; TIntHashSet parentChildrenIds = new TIntHashSet(FSRecords.list(parentId)); boolean hasRemovedChildren = false; for (VFileEvent event : events) { if (event instanceof VFileCreateEvent) { String name = ((VFileCreateEvent) event).getChildName(); final VirtualFile fake = new FakeVirtualFile(parent, name); final FileAttributes attributes = delegate.getAttributes(fake); if (attributes != null) { final int childId = createAndFillRecord(delegate, fake, parentId, attributes); assert parent instanceof VirtualDirectoryImpl : parent; final VirtualDirectoryImpl dir = (VirtualDirectoryImpl) parent; VirtualFileSystemEntry child = dir.createChild(name, childId, dir.getFileSystem()); childrenToBeUpdated.add(child); childrenIdsUpdated.add(childId); parentChildrenIds.add(childId); } } else if (event instanceof VFileDeleteEvent) { VirtualFile file = ((VFileDeleteEvent) event).getFile(); if (!file.exists()) { LOG.error("Deleting a file, which does not exist: " + file.getPath()); continue; } hasRemovedChildren = true; int id = getFileId(file); childrenToBeUpdated.add(file); childrenIdsUpdated.add(-id); parentChildrenIds.remove(id); } } FSRecords.updateList(parentId, parentChildrenIds.toArray()); if (hasRemovedChildren) clearIdCache(); VirtualDirectoryImpl parentImpl = (VirtualDirectoryImpl) parent; for (int i = 0, len = childrenIdsUpdated.size(); i < len; ++i) { final int childId = childrenIdsUpdated.get(i); final VirtualFile childFile = childrenToBeUpdated.get(i); if (childId > 0) { parentImpl.addChild((VirtualFileSystemEntry) childFile); } else { FSRecords.deleteRecordRecursively(-childId); parentImpl.removeChild(childFile); invalidateSubtree(childFile); } } }
@Override @Nullable public DfaConstValue getConstantValue(@NotNull DfaVariableValue value) { int index = getEqClassIndex(value); EqClass ec = index == -1 ? null : myEqClasses.get(index); return ec == null ? null : (DfaConstValue) unwrap(ec.findConstant(true)); }
@Nullable private Double getDoubleValue(int eqClassIndex) { EqClass ec = myEqClasses.get(eqClassIndex); DfaValue dfaConst = ec == null ? null : ec.findConstant(false); Object constValue = dfaConst instanceof DfaConstValue ? ((DfaConstValue) dfaConst).getValue() : null; return constValue instanceof Number ? ((Number) constValue).doubleValue() : null; }
@NotNull private static List<VFileEvent> validateEvents(@NotNull List<VFileEvent> events) { final List<EventWrapper> deletionEvents = ContainerUtil.newArrayList(); for (int i = 0, size = events.size(); i < size; i++) { final VFileEvent event = events.get(i); if (event instanceof VFileDeleteEvent && event.isValid()) { deletionEvents.add(new EventWrapper((VFileDeleteEvent) event, i)); } } final TIntHashSet invalidIDs; if (deletionEvents.isEmpty()) { invalidIDs = EmptyIntHashSet.INSTANCE; } else { ContainerUtil.quickSort(deletionEvents, DEPTH_COMPARATOR); invalidIDs = new TIntHashSet(deletionEvents.size()); final Set<VirtualFile> dirsToBeDeleted = new THashSet<VirtualFile>(deletionEvents.size()); nextEvent: for (EventWrapper wrapper : deletionEvents) { final VirtualFile candidate = wrapper.event.getFile(); VirtualFile parent = candidate; while (parent != null) { if (dirsToBeDeleted.contains(parent)) { invalidIDs.add(wrapper.id); continue nextEvent; } parent = parent.getParent(); } if (candidate.isDirectory()) { dirsToBeDeleted.add(candidate); } } } final List<VFileEvent> filtered = new ArrayList<VFileEvent>(events.size() - invalidIDs.size()); for (int i = 0, size = events.size(); i < size; i++) { final VFileEvent event = events.get(i); if (event.isValid() && !(event instanceof VFileDeleteEvent && invalidIDs.contains(i))) { filtered.add(event); } } return filtered; }
@NotNull List<DfaValue> getEquivalentValues(@NotNull DfaValue dfaValue) { int index = getEqClassIndex(dfaValue); EqClass set = index == -1 ? null : myEqClasses.get(index); if (set == null) { return Collections.emptyList(); } return set.getMemberValues(); }
private boolean applyRelation( @NotNull final DfaValue dfaLeft, @NotNull final DfaValue dfaRight, boolean isNegated) { if (isUnknownState(dfaLeft) || isUnknownState(dfaRight)) { return true; } // DfaConstValue || DfaVariableValue Integer c1Index = getOrCreateEqClassIndex(dfaLeft); Integer c2Index = getOrCreateEqClassIndex(dfaRight); if (c1Index == null || c2Index == null) { return true; } if (!isNegated) { // Equals if (c1Index.equals(c2Index) || areCompatibleConstants(c1Index, c2Index)) return true; if (!uniteClasses(c1Index, c2Index)) return false; for (long encodedPair : myDistinctClasses.toArray()) { EqClass c1 = myEqClasses.get(low(encodedPair)); EqClass c2 = myEqClasses.get(high(encodedPair)); DfaConstValue const1 = (DfaConstValue) c1.findConstant(false); DfaConstValue const2 = (DfaConstValue) c2.findConstant(false); if (const1 != null && const2 != null && !preserveConstantDistinction(const1.getValue(), const2.getValue())) { myDistinctClasses.remove(encodedPair); } } myCachedDistinctClassPairs = null; myCachedNonTrivialEqClasses = null; myCachedHash = null; } else { // Not Equals if (c1Index.equals(c2Index) || areCompatibleConstants(c1Index, c2Index)) return false; if (isNull(dfaLeft) && isPrimitive(dfaRight) || isNull(dfaRight) && isPrimitive(dfaLeft)) return true; makeClassesDistinct(c1Index, c2Index); myCachedDistinctClassPairs = null; myCachedHash = null; } return true; }
private int getEqClassIndex(@NotNull final DfaValue dfaValue) { final int id = unwrap(dfaValue).getID(); int[] classes = myIdToEqClassesIndices.get(id); int result = -1; if (classes != null) { for (int index : classes) { EqClass aClass = myEqClasses.get(index); if (!aClass.contains(dfaValue.getID())) continue; if (!canBeReused(dfaValue) && aClass.size() > 1) break; result = index; break; } } return result; }
private boolean shouldMarkUnknown(@NotNull DfaVariableValue value) { int eqClassIndex = getEqClassIndex(value); if (eqClassIndex < 0) return false; EqClass eqClass = myEqClasses.get(eqClassIndex); if (eqClass == null) return false; if (eqClass.findConstant(true) != null) return true; for (UnorderedPair<EqClass> pair : getDistinctClassPairs()) { if (pair.first == eqClass && pair.second.findConstant(true) != null || pair.second == eqClass && pair.first.findConstant(true) != null) { return true; } } return false; }
private boolean uniteClasses(int c1Index, int c2Index) { EqClass c1 = myEqClasses.get(c1Index); EqClass c2 = myEqClasses.get(c2Index); Set<DfaVariableValue> vars = ContainerUtil.newTroveSet(); Set<DfaVariableValue> negatedVars = ContainerUtil.newTroveSet(); int[] cs = new int[c1.size() + c2.size()]; c1.set(0, cs, 0, c1.size()); c2.set(0, cs, c1.size(), c2.size()); int nConst = 0; for (int c : cs) { DfaValue dfaValue = unwrap(myFactory.getValue(c)); if (dfaValue instanceof DfaConstValue) nConst++; if (dfaValue instanceof DfaVariableValue) { DfaVariableValue variableValue = (DfaVariableValue) dfaValue; if (variableValue.isNegated()) { negatedVars.add(variableValue.createNegated()); } else { vars.add(variableValue); } } if (nConst > 1) return false; } if (ContainerUtil.intersects(vars, negatedVars)) return false; TLongArrayList c2Pairs = new TLongArrayList(); long[] distincts = myDistinctClasses.toArray(); for (long distinct : distincts) { int pc1 = low(distinct); int pc2 = high(distinct); boolean addedToC1 = false; if (pc1 == c1Index || pc2 == c1Index) { addedToC1 = true; } if (pc1 == c2Index || pc2 == c2Index) { if (addedToC1) return false; c2Pairs.add(distinct); } } EqClass newClass = new EqClass(c1); myEqClasses.set(c1Index, newClass); for (int i = 0; i < c2.size(); i++) { int c = c2.get(i); newClass.add(c); removeFromMap(c, c2Index); addToMap(c, c1Index); } for (int i = 0; i < c2Pairs.size(); i++) { long c = c2Pairs.get(i); myDistinctClasses.remove(c); myDistinctClasses.add(createPair(c1Index, low(c) == c2Index ? high(c) : low(c))); } myEqClasses.set(c2Index, null); return true; }
void doFlush(@NotNull DfaVariableValue varPlain, boolean markUnknown) { DfaVariableValue varNegated = varPlain.getNegatedValue(); final int idPlain = varPlain.getID(); final int idNegated = varNegated == null ? -1 : varNegated.getID(); int[] classes = myIdToEqClassesIndices.get(idPlain); int[] negatedClasses = myIdToEqClassesIndices.get(idNegated); int[] result = ArrayUtil.mergeArrays( ObjectUtils.notNull(classes, ArrayUtil.EMPTY_INT_ARRAY), ObjectUtils.notNull(negatedClasses, ArrayUtil.EMPTY_INT_ARRAY)); int interruptCount = 0; for (int varClassIndex : result) { EqClass varClass = myEqClasses.get(varClassIndex); if ((++interruptCount & 0xf) == 0) { ProgressManager.checkCanceled(); } varClass = new EqClass(varClass); myEqClasses.set(varClassIndex, varClass); for (int id : varClass.toNativeArray()) { int idUnwrapped; if (id == idPlain || id == idNegated || (idUnwrapped = unwrap(myFactory.getValue(id)).getID()) == idPlain || idUnwrapped == idNegated) { varClass.removeValue(id); } } if (varClass.isEmpty()) { myEqClasses.set(varClassIndex, null); for (TLongIterator iterator = myDistinctClasses.iterator(); iterator.hasNext(); ) { long pair = iterator.next(); if (low(pair) == varClassIndex || high(pair) == varClassIndex) { iterator.remove(); } } } else if (varClass.containsConstantsOnly()) { for (TLongIterator iterator = myDistinctClasses.iterator(); iterator.hasNext(); ) { long pair = iterator.next(); if (low(pair) == varClassIndex && myEqClasses.get(high(pair)).containsConstantsOnly() || high(pair) == varClassIndex && myEqClasses.get(low(pair)).containsConstantsOnly()) { iterator.remove(); } } } } removeAllFromMap(idPlain); removeAllFromMap(idNegated); myVariableStates.remove(varPlain); if (varNegated != null) { myVariableStates.remove(varNegated); } if (markUnknown) { myUnknownVariables.add(varPlain); } myCachedNonTrivialEqClasses = null; myCachedDistinctClassPairs = null; myCachedHash = null; }