private SNode searchInSuperTypes(SNode subType, CoercionMatcher superType, boolean isWeak) { StructuralNodeSet<?> frontier = new StructuralNodeSet(); StructuralNodeSet<?> newFrontier = new StructuralNodeSet(); StructuralNodeSet<?> yetPassed = new StructuralNodeSet(); frontier.add(subType); while (!frontier.isEmpty()) { Set<SNode> yetPassedRaw = new THashSet<SNode>(); // collecting a set of frontier's ancestors StructuralNodeSet<?> ancestors = new StructuralNodeSet(); for (SNode node : frontier) { mySubTyping.collectImmediateSuperTypes(node, isWeak, ancestors, null); yetPassedRaw.add(node); } ArrayList<SNode> ancestorsSorted; ancestorsSorted = new ArrayList<SNode>(ancestors); Collections.sort( ancestorsSorted, new Comparator<SNode>() { public int compare(SNode o1, SNode o2) { return TypesUtil.depth(o2) - TypesUtil.depth(o1); } }); List<SNode> results = new ArrayList<SNode>(); for (SNode ancestor : ancestorsSorted) { if (superType.matchesWith(ancestor)) { results.add(ancestor); } } if (!results.isEmpty()) { if (results.size() > 1) { results = mySubTyping.eliminateSuperTypes(results); } if (!results.isEmpty()) { return results.get(0); } } for (SNode passedNodeRaw : yetPassedRaw) { yetPassed.add(passedNodeRaw); } for (SNode passedNode : yetPassed) { ancestors.removeStructurally(passedNode); } for (SNode ancestor : ancestors) { Pair<Boolean, SNode> answer = getCoerceCacheAnswer(ancestor, superType.getMatchingPattern(), isWeak); if (answer != null) { if (answer.o1 && answer.o2 == null) { // System.out.println("coerce optimized"); continue; } } newFrontier.addStructurally(ancestor); yetPassed.addStructurally(ancestor); } frontier = newFrontier; newFrontier = new StructuralNodeSet(); } return null; }
public SNode coerceSubTypingNew( final SNode subtype, final IMatchingPattern pattern, final boolean isWeak, final State state) { if (subtype == null) return null; if (pattern.match(subtype)) return subtype; if (!CoerceUtil.canBeCoerced(subtype, pattern.getConceptFQName())) return null; if ("jetbrains.mps.lang.typesystem.structure.MeetType".equals(subtype.getConceptFqName())) { List<SNode> children = subtype.getChildren("argument"); for (SNode child : children) { SNode result = coerceSubTypingNew(child, pattern, isWeak, state); if (result != null) return result; } return null; } final TypeCheckingContextNew typeCheckingContext = state == null ? null : state.getTypeCheckingContext(); if ("jetbrains.mps.lang.typesystem.structure.JoinType".equals(subtype.getConceptFqName())) { List<SNode> children = subtype.getChildren("argument"); SNode lcs = mySubTyping.createLCS(children, typeCheckingContext); return coerceSubTypingNew(lcs, pattern, isWeak, state); } // asking the cache return NodeReadAccessCasterInEditor.runReadTransparentAction( new Computable<SNode>() { public SNode compute() { Pair<Boolean, SNode> answer = getCoerceCacheAnswer(subtype, pattern, isWeak); if (answer != null && answer.o1) { return answer.o2; } CoercionMatcher coercionMatcher = new CoercionMatcher(pattern); SNode result = searchInSuperTypes(subtype, coercionMatcher, isWeak); // writing to the cache SubtypingCache subtypingCache = myTypeChecker.getSubtypingCache(); if (subtypingCache != null) { subtypingCache.cacheCoerce(subtype, pattern, result, isWeak); } subtypingCache = myTypeChecker.getGlobalSubtypingCache(); if (subtypingCache != null) { subtypingCache.cacheCoerce(subtype, pattern, result, isWeak); } return result; } }); }