/// <summary> /// Appends the given element to the search program operations list /// whose closing element until now was this element. /// Returns the new closing element - the given element. /// </summary> public SearchProgramOperation Append(SearchProgramOperation newElement) { Debug.Assert(Next == null, "Append only at end of list"); Debug.Assert(newElement.Previous == null, "Append only of element without predecessor"); Next = newElement; newElement.Previous = this; return newElement; }
/// <summary> /// Insert the given element into the search program operations list /// between this and the succeeding element. /// Returns the element after this - the given element. /// </summary> public SearchProgramOperation Insert(SearchProgramOperation newElement) { Debug.Assert(newElement.Previous == null, "Insert only of single unconnected element (previous)"); Debug.Assert(newElement.Next == null, "Insert only of single unconnected element (next)"); if (Next == null) { return Append(newElement); } SearchProgramOperation Successor = Next; Next = newElement; newElement.Next = Successor; Successor.Previous = newElement; newElement.Previous = this; return newElement; }
/// <summary> /// Inserts declarations for variables extracted from parameters /// </summary> private static SearchProgramOperation insertVariableDeclarations(SearchProgramOperation insertionPoint, PatternGraph patternGraph) { foreach (PatternVariable var in patternGraph.variablesPlusInlined) { if (!var.defToBeYieldedTo) // def variables are handled with the schedule, must come after the presets { // inlined variables are handled later, cause they may depend on elements matched if (var.originalVariable == null || !patternGraph.WasInlinedHere(var.originalSubpatternEmbedding)) { insertionPoint = insertionPoint.Append( new ExtractVariable(TypesHelper.TypeName(var.type), var.Name) ); } } } return(insertionPoint); }
/// <summary> /// move outwards from check succeeded operation until check partial match by independent is found /// appending restore isomorphy for isomorphy written on the way /// and final jump to operation right after the independent failed operation of the check partial match by independent /// </summary> private static void MoveRightAfterCorrespondingIndependentFailedAppendingRemoveIsomorphyAndJump( CheckContinueMatchingOfIndependentSucceeded checkSucceeded, CheckPartialMatchByIndependent enclosingIndependent, SearchProgram topLevelSearchProgram) { // insertion point for candidate failed operations SearchProgramOperation insertionPoint = checkSucceeded.CheckFailedOperations; while (insertionPoint.Next != null) // needed? { insertionPoint = insertionPoint.Next; } // move outwards, append remove isomorphy string[] neededElements = new string[0]; SearchProgramOperation continuationPoint = MoveOutwardsAppendingRemoveIsomorphy( checkSucceeded, ref insertionPoint, neededElements, enclosingIndependent, topLevelSearchProgram); // move to check failed operation of check independent operation while (!(continuationPoint is CheckContinueMatchingOfIndependentFailed)) { continuationPoint = continuationPoint.Next; } CheckContinueMatchingOfIndependentFailed checkFailed = (CheckContinueMatchingOfIndependentFailed)continuationPoint; // insert label right thereafter, append jump there at insertion point GotoLabel gotoLabel = new GotoLabel(); checkFailed.Insert(gotoLabel); ContinueOperation continueByGoto = new ContinueOperation( ContinueOperationType.ByGoto, gotoLabel.LabelName); insertionPoint.Append(continueByGoto); }
/// <summary> /// Builds search program for alternative from scheduled search plans of the alternative cases /// </summary> public static SearchProgram BuildSearchProgram( IGraphModel model, LGSPMatchingPattern matchingPattern, Alternative alternative, bool parallelized, bool emitProfiling) { String rulePatternClassName = NamesOfEntities.RulePatternClassName(matchingPattern.name, matchingPattern.PatternGraph.Package, !(matchingPattern is LGSPRulePattern)); // build combined list of namesOfPatternGraphsOnPathToEnclosedPatternpath // from the namesOfPatternGraphsOnPathToEnclosedPatternpath of the alternative cases // also build combined lists of matching pattern class type names and nested independents List <string> namesOfPatternGraphsOnPathToEnclosedPatternpath = new List <string>(); List <string> matchingPatternClassTypeNames = new List <string>(); List <Dictionary <PatternGraph, bool> > nestedIndependents = new List <Dictionary <PatternGraph, bool> >(); for (int i = 0; i < alternative.alternativeCases.Length; ++i) { PatternGraph altCase = alternative.alternativeCases[i]; foreach (String name in altCase.patternGraphsOnPathToEnclosedPatternpath) { if (!namesOfPatternGraphsOnPathToEnclosedPatternpath.Contains(name)) { namesOfPatternGraphsOnPathToEnclosedPatternpath.Add(name); } } ExtractNestedIndependents(matchingPatternClassTypeNames, nestedIndependents, matchingPattern, altCase); } // build outermost search program operation, create the list anchor starting its program SearchProgram searchProgram = new SearchProgramOfAlternative( rulePatternClassName, namesOfPatternGraphsOnPathToEnclosedPatternpath, "myMatch", matchingPatternClassTypeNames, nestedIndependents, parallelized); searchProgram.OperationsList = new SearchProgramList(searchProgram); SearchProgramOperation insertionPoint = searchProgram.OperationsList; // initialize task/result-pushdown handling in subpattern matcher InitializeSubpatternMatching initialize = new InitializeSubpatternMatching(InitializeFinalizeSubpatternMatchingType.Normal); insertionPoint = insertionPoint.Append(initialize); // build alternative matching search programs, one per case for (int i = 0; i < alternative.alternativeCases.Length; ++i) { PatternGraph altCase = alternative.alternativeCases[i]; ScheduledSearchPlan scheduledSearchPlan = altCase.schedulesIncludingNegativesAndIndependents[0]; string inlinedPatternClassName = rulePatternClassName; string pathPrefixInInlinedPatternClass = scheduledSearchPlan.PatternGraph.pathPrefix; string unprefixedNameInInlinedPatternClass = scheduledSearchPlan.PatternGraph.name; if (alternative.originalAlternative != null) { inlinedPatternClassName = alternative.originalSubpatternEmbedding.matchingPatternOfEmbeddedGraph.GetType().Name; pathPrefixInInlinedPatternClass = alternative.originalAlternative.pathPrefix + alternative.originalAlternative.name + "_"; unprefixedNameInInlinedPatternClass = alternative.originalAlternative.alternativeCases[i].name; } SearchProgramBodyBuilder builder = new SearchProgramBodyBuilder( SearchProgramType.AlternativeCase, model, rulePatternClassName, null, null, null, altCase, emitProfiling, parallelized, 0 ); AlternativeCaseMatching alternativeCaseMatching = new AlternativeCaseMatching( pathPrefixInInlinedPatternClass, unprefixedNameInInlinedPatternClass, inlinedPatternClassName, builder.wasIndependentInlined(altCase, 0)); alternativeCaseMatching.OperationsList = new SearchProgramList(alternativeCaseMatching); SearchProgramOperation continuationPointAfterAltCase = insertionPoint.Append(alternativeCaseMatching); // at level of the current alt case insertionPoint = alternativeCaseMatching.OperationsList; insertionPoint = insertVariableDeclarations(insertionPoint, altCase); // start building with first operation in scheduled search plan builder.BuildScheduledSearchPlanOperationIntoSearchProgram( 0, insertionPoint); // back to level of alt cases insertionPoint = continuationPointAfterAltCase; // save matches found by alternative case to get clean start for matching next alternative case if (i < alternative.alternativeCases.Length - 1) { NewMatchesListForFollowingMatches newMatchesList = new NewMatchesListForFollowingMatches(true); insertionPoint = insertionPoint.Append(newMatchesList); } } // finalize task/result-pushdown handling in subpattern matcher FinalizeSubpatternMatching finalize = new FinalizeSubpatternMatching(InitializeFinalizeSubpatternMatchingType.Normal); insertionPoint = insertionPoint.Append(finalize); return(searchProgram); }
/// <summary> /// Builds search program from scheduled search plan in pattern graph of the subpattern rule pattern /// </summary> public static SearchProgram BuildSearchProgram( IGraphModel model, LGSPMatchingPattern matchingPattern, bool parallelized, bool emitProfiling) { Debug.Assert(!(matchingPattern is LGSPRulePattern)); PatternGraph patternGraph = matchingPattern.patternGraph; String rulePatternClassName = NamesOfEntities.RulePatternClassName(matchingPattern.name, matchingPattern.PatternGraph.Package, true); SearchProgramBodyBuilder builder = new SearchProgramBodyBuilder( SearchProgramType.Subpattern, model, rulePatternClassName, null, null, null, patternGraph, emitProfiling, parallelized, 0 ); List <String> matchingPatternClassTypeNames = new List <String>(); List <Dictionary <PatternGraph, bool> > nestedIndependents = new List <Dictionary <PatternGraph, bool> >(); ExtractNestedIndependents(matchingPatternClassTypeNames, nestedIndependents, matchingPattern, patternGraph); // build outermost search program operation, create the list anchor starting its program SearchProgram searchProgram = new SearchProgramOfSubpattern( rulePatternClassName, patternGraph.Name, matchingPattern.patternGraph.patternGraphsOnPathToEnclosedPatternpath, "myMatch", builder.wasIndependentInlined(patternGraph, 0), matchingPatternClassTypeNames, nestedIndependents, parallelized); searchProgram.OperationsList = new SearchProgramList(searchProgram); SearchProgramOperation insertionPoint = searchProgram.OperationsList; insertionPoint = insertVariableDeclarations(insertionPoint, patternGraph); // initialize task/result-pushdown handling in subpattern matcher InitializeSubpatternMatching initialize = new InitializeSubpatternMatching(InitializeFinalizeSubpatternMatchingType.Normal); insertionPoint = insertionPoint.Append(initialize); // start building with first operation in scheduled search plan insertionPoint = builder.BuildScheduledSearchPlanOperationIntoSearchProgram( 0, insertionPoint); // finalize task/result-pushdown handling in subpattern matcher FinalizeSubpatternMatching finalize = new FinalizeSubpatternMatching(InitializeFinalizeSubpatternMatchingType.Normal); insertionPoint = insertionPoint.Append(finalize); return(searchProgram); }
/////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Completes check operations in search program from given currentOperation on /// (taking borderlines set by enclosing search program and check negative into account) /// Completion: /// - determine continuation point /// - insert remove isomorphy opertions needed for continuing there /// - insert continuing operation itself /// </summary> private void CompleteCheckOperations( SearchProgramOperation currentOperation, SearchProgramOperation enclosingSearchProgram, // might be a negative/independent in case these are nested GetPartialMatchOfAlternative enclosingAlternative, CheckPartialMatchByNegativeOrIndependent enclosingCheckNegativeOrIndependent, SearchProgram topLevelSearchProgram) { // mainly dispatching and iteration method, traverses search program // real completion done in MoveOutwardsAppendingRemoveIsomorphyAndJump // outermost operation for that function is computed here, regarding negative patterns // program nesting structure: search program - [alternative] - [negative|independent]* // complete check operations by inserting failure code // find them in depth first search of search program while (currentOperation != null) { ////////////////////////////////////////////////////////// if (currentOperation is CheckCandidate) ////////////////////////////////////////////////////////// { CheckCandidate checkCandidate = (CheckCandidate)currentOperation; checkCandidate.CheckFailedOperations = new SearchProgramList(checkCandidate); string[] neededElementsForCheckOperation = new string[1]; neededElementsForCheckOperation[0] = checkCandidate.PatternElementName; MoveOutwardsAppendingRemoveIsomorphyAndJump( checkCandidate, neededElementsForCheckOperation, enclosingCheckNegativeOrIndependent ?? (enclosingAlternative ?? enclosingSearchProgram), topLevelSearchProgram); } ////////////////////////////////////////////////////////// else if (currentOperation is CheckPartialMatch) ////////////////////////////////////////////////////////// { if (currentOperation is CheckPartialMatchByCondition) { CheckPartialMatchByCondition checkCondition = (CheckPartialMatchByCondition)currentOperation; checkCondition.CheckFailedOperations = new SearchProgramList(checkCondition); MoveOutwardsAppendingRemoveIsomorphyAndJump( checkCondition, checkCondition.NeededElements, enclosingCheckNegativeOrIndependent ?? (enclosingAlternative ?? enclosingSearchProgram), topLevelSearchProgram); } else if(currentOperation is CheckPartialMatchForDuplicate) { CheckPartialMatchForDuplicate checkDuplicateMatch = (CheckPartialMatchForDuplicate)currentOperation; checkDuplicateMatch.CheckFailedOperations = new SearchProgramList(checkDuplicateMatch); MoveOutwardsAppendingRemoveIsomorphyAndJump( checkDuplicateMatch, checkDuplicateMatch.NeededElements, enclosingCheckNegativeOrIndependent ?? (enclosingAlternative ?? enclosingSearchProgram), topLevelSearchProgram); } else if(currentOperation is CheckPartialMatchByNegativeOrIndependent) { CheckPartialMatchByNegativeOrIndependent checkNegativeOrIndependent = (CheckPartialMatchByNegativeOrIndependent)currentOperation; // ByNegative/ByIndependent is handled in CheckContinueMatchingFailed // of the negative/independent case - enter negative/independent case CompleteCheckOperations( checkNegativeOrIndependent.NestedOperationsList, enclosingCheckNegativeOrIndependent ?? enclosingSearchProgram, enclosingCheckNegativeOrIndependent!=null ? null : enclosingAlternative, checkNegativeOrIndependent, topLevelSearchProgram); } else if (currentOperation is CheckPartialMatchForSubpatternsFound) { CheckPartialMatchForSubpatternsFound checkSubpatternsFound = (CheckPartialMatchForSubpatternsFound)currentOperation; if (enclosingCheckNegativeOrIndependent == null) { // determine insertion point within check failed operations // to append the nested check maximum matches SearchProgramOperation insertionPoint = checkSubpatternsFound.CheckFailedOperations; while (insertionPoint.Next != null) { insertionPoint = insertionPoint.Next; } // append nested check maximum matches CheckMaximumMatchesType checkMaxMatchesType = CheckMaximumMatchesType.Action; if(enclosingSearchProgram is SearchProgramOfSubpattern || enclosingSearchProgram is SearchProgramOfAlternative) { checkMaxMatchesType = CheckMaximumMatchesType.Subpattern; } else if(enclosingSearchProgram is SearchProgramOfIterated) { checkMaxMatchesType = CheckMaximumMatchesType.Iterated; } CheckContinueMatchingMaximumMatchesReached checkMaximumMatches = new CheckContinueMatchingMaximumMatchesReached(checkMaxMatchesType, false, enclosingSearchProgram is SearchProgramOfActionParallelizationBody); insertionPoint.Append(checkMaximumMatches); MoveOutwardsAppendingRemoveIsomorphyAndJump( checkSubpatternsFound, null, enclosingCheckNegativeOrIndependent ?? (enclosingAlternative ?? enclosingSearchProgram), topLevelSearchProgram); } // check subpatterns found has a further check maximum matches // or check continue matching of negative failed nested within check failed code // give it its special bit of attention here CompleteCheckOperations( checkSubpatternsFound.CheckFailedOperations, enclosingSearchProgram, enclosingAlternative, enclosingCheckNegativeOrIndependent, topLevelSearchProgram); } else { Debug.Assert(false, "unknown check partial match operation"); } } ////////////////////////////////////////////////////////// else if (currentOperation is CheckContinueMatching) ////////////////////////////////////////////////////////// { if (currentOperation is CheckContinueMatchingMaximumMatchesReached) { CheckContinueMatchingMaximumMatchesReached checkMaximumMatches = (CheckContinueMatchingMaximumMatchesReached)currentOperation; checkMaximumMatches.CheckFailedOperations = new SearchProgramList(checkMaximumMatches); if (checkMaximumMatches.ListHeadAdjustment) { MoveOutwardsAppendingListHeadAdjustment(checkMaximumMatches, checkMaximumMatches.InParallelizedBody); } string[] neededElementsForCheckOperation = new string[0]; MoveOutwardsAppendingRemoveIsomorphyAndJump( checkMaximumMatches, neededElementsForCheckOperation, enclosingSearchProgram, topLevelSearchProgram); } else if (currentOperation is CheckContinueMatchingOfNegativeFailed) { CheckContinueMatchingOfNegativeFailed checkFailed = (CheckContinueMatchingOfNegativeFailed)currentOperation; checkFailed.CheckFailedOperations = new SearchProgramList(checkFailed); if(checkFailed.IsIterationBreaking) { string[] neededElementsForCheckOperation = new string[0]; MoveOutwardsAppendingRemoveIsomorphyAndJump( checkFailed, neededElementsForCheckOperation, enclosingSearchProgram, topLevelSearchProgram); } else { MoveOutwardsAppendingRemoveIsomorphyAndJump( checkFailed, enclosingCheckNegativeOrIndependent.NeededElements, enclosingAlternative ?? enclosingSearchProgram, topLevelSearchProgram); } } else if (currentOperation is CheckContinueMatchingOfIndependentSucceeded) { CheckContinueMatchingOfIndependentSucceeded checkSucceeded = (CheckContinueMatchingOfIndependentSucceeded)currentOperation; checkSucceeded.CheckFailedOperations = // yep, rotten wording new SearchProgramList(checkSucceeded); MoveRightAfterCorrespondingIndependentFailedAppendingRemoveIsomorphyAndJump( checkSucceeded, (CheckPartialMatchByIndependent)enclosingCheckNegativeOrIndependent, topLevelSearchProgram); } else if (currentOperation is CheckContinueMatchingOfIndependentFailed) { CheckContinueMatchingOfIndependentFailed checkFailed = (CheckContinueMatchingOfIndependentFailed)currentOperation; checkFailed.CheckFailedOperations = new SearchProgramList(checkFailed); if(checkFailed.IsIterationBreaking) { string[] neededElementsForCheckOperation = new string[0]; MoveOutwardsAppendingRemoveIsomorphyAndJump( checkFailed, neededElementsForCheckOperation, enclosingSearchProgram, topLevelSearchProgram); } else { MoveOutwardsAppendingRemoveIsomorphyAndJump( checkFailed, checkFailed.CheckIndependent.NeededElements, enclosingAlternative ?? enclosingSearchProgram, topLevelSearchProgram); } } else if (currentOperation is CheckContinueMatchingTasksLeft) { CheckContinueMatchingTasksLeft tasksLeft = (CheckContinueMatchingTasksLeft)currentOperation; // determine insertion point within check failed operations // to append the nested check maximum matches SearchProgramOperation insertionPoint = tasksLeft.CheckFailedOperations; while (insertionPoint.Next != null) { insertionPoint = insertionPoint.Next; } // append nested check maximum matches CheckContinueMatchingMaximumMatchesReached checkMaximumMatches = new CheckContinueMatchingMaximumMatchesReached( enclosingSearchProgram is SearchProgramOfIterated ? CheckMaximumMatchesType.Iterated : CheckMaximumMatchesType.Subpattern, false, topLevelSearchProgram is SearchProgramOfActionParallelizationBody); insertionPoint.Append(checkMaximumMatches); MoveOutwardsAppendingRemoveIsomorphyAndJump( tasksLeft, null, enclosingCheckNegativeOrIndependent ?? (enclosingAlternative ?? enclosingSearchProgram), topLevelSearchProgram); // check tasks left has a further check maximum matches nested within check failed code // give it its special bit of attention here CompleteCheckOperations( tasksLeft.CheckFailedOperations, enclosingSearchProgram, enclosingAlternative, enclosingCheckNegativeOrIndependent, topLevelSearchProgram); } else if (currentOperation is CheckContinueMatchingIteratedPatternNonNullMatchFound) { // was built completely, nothing to complete } else { Debug.Assert(false, "unknown check abort matching operation"); } } ////////////////////////////////////////////////////////// else if (currentOperation is GetPartialMatchOfAlternative) ////////////////////////////////////////////////////////// { // depth first CompleteCheckOperations( currentOperation.GetNestedSearchOperationsList(), enclosingSearchProgram, (GetPartialMatchOfAlternative)currentOperation, null, topLevelSearchProgram); } ////////////////////////////////////////////////////////// else if (currentOperation.IsSearchNestingOperation()) ////////////////////////////////////////////////////////// { // depth first CompleteCheckOperations( currentOperation.GetNestedSearchOperationsList(), enclosingSearchProgram, enclosingAlternative, enclosingCheckNegativeOrIndependent, topLevelSearchProgram); } // breadth currentOperation = currentOperation.Next; } }
/// <summary> /// Search program operations implementing the /// ActionPreset search plan operation /// are created and inserted into search program /// </summary> private SearchProgramOperation buildActionPreset( SearchProgramOperation insertionPoint, int currentOperationIndex, SearchPlanNode target, IsomorphyInformation isomorphy) { bool isNode = target.NodeType == PlanNodeType.Node; string negativeIndependentNamePrefix = NegativeIndependentNamePrefix(patternGraphWithNestingPatterns.Peek()); Debug.Assert(negativeIndependentNamePrefix == "", "Top-level maybe preset in negative/independent search plan"); Debug.Assert(programType != SearchProgramType.Subpattern, "Maybe preset in subpattern"); Debug.Assert(programType != SearchProgramType.AlternativeCase, "Maybe preset in alternative"); Debug.Assert(programType != SearchProgramType.Iterated, "Maybe preset in iterated"); // get candidate from inputs GetCandidateByDrawing fromInputs = new GetCandidateByDrawing( GetCandidateByDrawingType.FromInputs, target.PatternElement.Name, isNode); insertionPoint = insertionPoint.Append(fromInputs); // check type of candidate insertionPoint = decideOnAndInsertCheckType(insertionPoint, target); // check candidate for isomorphy if (isomorphy.CheckIsMatchedBit) { CheckCandidateForIsomorphy checkIsomorphy = new CheckCandidateForIsomorphy( target.PatternElement.Name, isomorphy.PatternElementsToCheckAgainstAsListOfStrings(), negativeIndependentNamePrefix, isNode, isoSpaceNeverAboveMaxIsoSpace, isomorphy.Parallel, isomorphy.LockForAllThreads); insertionPoint = insertionPoint.Append(checkIsomorphy); } // accept candidate (write isomorphy information) if (isomorphy.SetIsMatchedBit) { AcceptCandidate acceptCandidate = new AcceptCandidate( target.PatternElement.Name, negativeIndependentNamePrefix, isNode, isoSpaceNeverAboveMaxIsoSpace, isomorphy.Parallel, isomorphy.LockForAllThreads); insertionPoint = insertionPoint.Append(acceptCandidate); } // mark element as visited target.Visited = true; //--------------------------------------------------------------------------- // build next operation insertionPoint = BuildScheduledSearchPlanOperationIntoSearchProgram( currentOperationIndex + 1, insertionPoint); //--------------------------------------------------------------------------- // unmark element for possibly following run target.Visited = false; // abandon candidate (restore isomorphy information) if (isomorphy.SetIsMatchedBit) { // only if isomorphy information was previously written AbandonCandidate abandonCandidate = new AbandonCandidate( target.PatternElement.Name, negativeIndependentNamePrefix, isNode, isoSpaceNeverAboveMaxIsoSpace, isomorphy.Parallel, isomorphy.LockForAllThreads); insertionPoint = insertionPoint.Append(abandonCandidate); } return insertionPoint; }
/// <summary> /// Decides which check connectedness operations are needed for the given edge of fixed direction /// and inserts them into the search program /// </summary> private SearchProgramOperation decideOnAndInsertCheckConnectednessOfEdgeFixedDirection( SearchProgramOperation insertionPoint, SearchPlanEdgeNode edge, CheckCandidateForConnectednessType connectednessType) { // check whether source/target-nodes of the candidate edge // are the same as the already found nodes to which the edge must be incident // don't need to, if that node is not matched by now (signaled by visited) SearchPlanNodeNode nodeRequiringCheck = connectednessType == CheckCandidateForConnectednessType.Source ? edge.PatternEdgeSource : edge.PatternEdgeTarget; if (nodeRequiringCheck.Visited) { CheckCandidateForConnectedness checkConnectedness = new CheckCandidateForConnectedness( edge.PatternElement.Name, nodeRequiringCheck.PatternElement.Name, edge.PatternElement.Name, connectednessType); insertionPoint = insertionPoint.Append(checkConnectedness); } return insertionPoint; }
/// <summary> /// Inserts code for bubbling yield assignments /// at the given position, returns position after inserted operations /// </summary> private SearchProgramOperation insertYieldAssignments( SearchProgramOperation insertionPoint, PatternGraph patternGraph, String nestedMatchObjectName, PatternGraph nestedPatternGraph) { foreach(PatternNode node in patternGraph.nodesPlusInlined) { if(!node.DefToBeYieldedTo) continue; foreach(PatternNode nestedNode in nestedPatternGraph.nodesPlusInlined) { if(nestedNode == node) { BubbleUpYieldAssignment bubble = new BubbleUpYieldAssignment( EntityType.Node, node.Name, nestedMatchObjectName, nestedNode.originalNode!=null && patternGraph.WasInlinedHere(nestedNode.originalSubpatternEmbedding) ? nestedNode.originalNode.UnprefixedName : nestedNode.UnprefixedName ); insertionPoint = insertionPoint.Append(bubble); } } } foreach(PatternEdge edge in patternGraph.edgesPlusInlined) { if(!edge.DefToBeYieldedTo) continue; foreach(PatternEdge nestedEdge in nestedPatternGraph.edgesPlusInlined) { if(nestedEdge == edge) { BubbleUpYieldAssignment bubble = new BubbleUpYieldAssignment( EntityType.Edge, edge.Name, nestedMatchObjectName, nestedEdge.originalElement!=null ? nestedEdge.originalEdge.UnprefixedName : nestedEdge.UnprefixedName ); insertionPoint = insertionPoint.Append(bubble); } } } foreach(PatternVariable var in patternGraph.variablesPlusInlined) { if(!var.DefToBeYieldedTo) continue; foreach(PatternVariable nestedVar in nestedPatternGraph.variablesPlusInlined) { if(nestedVar == var) { BubbleUpYieldAssignment bubble = new BubbleUpYieldAssignment( EntityType.Variable, var.Name, nestedMatchObjectName, nestedVar.originalVariable!=null ? nestedVar.originalVariable.UnprefixedName : nestedVar.UnprefixedName ); insertionPoint = insertionPoint.Append(bubble); } } } return insertionPoint; }
/// <summary> /// Inserts code to accept the matched elements for patternpath checks /// at the given position, returns position after inserted operations /// </summary> private SearchProgramOperation insertPatternpathAccept(SearchProgramOperation insertionPoint, PatternGraph patternGraph) { bool isAction = programType == SearchProgramType.Action; string negativeIndependentNamePrefix = NegativeIndependentNamePrefix(patternGraph); for (int i = 0; i < patternGraph.nodesPlusInlined.Length; ++i) { if (patternGraph.nodesPlusInlined[i].PointOfDefinition == patternGraph || patternGraph.nodesPlusInlined[i].PointOfDefinition == null && isAction) { if(!patternGraph.nodesPlusInlined[i].defToBeYieldedTo) { AcceptCandidatePatternpath acceptPatternpath = new AcceptCandidatePatternpath(patternGraph.nodesPlusInlined[i].name, negativeIndependentNamePrefix, true); insertionPoint = insertionPoint.Append(acceptPatternpath); } } } for (int i = 0; i < patternGraph.edgesPlusInlined.Length; ++i) { if (patternGraph.edgesPlusInlined[i].PointOfDefinition == patternGraph || patternGraph.edgesPlusInlined[i].PointOfDefinition == null && isAction) { if(!patternGraph.edgesPlusInlined[i].defToBeYieldedTo) { AcceptCandidatePatternpath acceptPatternpath = new AcceptCandidatePatternpath(patternGraph.edgesPlusInlined[i].name, negativeIndependentNamePrefix, false); insertionPoint = insertionPoint.Append(acceptPatternpath); } } } return insertionPoint; }
/// <summary> /// Inserts code to insert the local match into a set used for duplicate checking /// at the given position, returns position after inserted operations. /// Duplicates may arise after independent inlining, when the non-inlined part was already matched with exactly the same elements. /// </summary> private SearchProgramOperation insertFillForDuplicateMatchChecking(SearchProgramOperation insertionPoint) { PatternGraph patternGraph = patternGraphWithNestingPatterns.Peek(); List<String> namesOfPatternElements = new List<String>(); List<String> unprefixedNamesOfPatternElements = new List<String>(); List<bool> patternElementIsNode = new List<bool>(); foreach(PatternElement elementFromInlinedIndependent in patternElementsMatchedThere(patternGraph)) { namesOfPatternElements.Add(elementFromInlinedIndependent.Name); unprefixedNamesOfPatternElements.Add(elementFromInlinedIndependent.UnprefixedName); patternElementIsNode.Add(elementFromInlinedIndependent is PatternNode); } FillPartialMatchForDuplicateChecking checkDuplicateMatch = new FillPartialMatchForDuplicateChecking(rulePatternClassName, patternGraph.pathPrefix + patternGraph.Name, namesOfPatternElements.ToArray(), unprefixedNamesOfPatternElements.ToArray(), patternElementIsNode.ToArray(), parallelized && programType == SearchProgramType.Action); insertionPoint = insertionPoint.Append(checkDuplicateMatch); return insertionPoint; }
/// <summary> /// Inserts code to check whether there are open tasks to handle left and code for case there are none /// at the given position, returns position after inserted operations /// </summary> private SearchProgramOperation insertCheckForTasksLeft(SearchProgramOperation insertionPoint) { PatternGraph patternGraph = patternGraphWithNestingPatterns.Peek(); CheckContinueMatchingTasksLeft tasksLeft = new CheckContinueMatchingTasksLeft(); SearchProgramOperation continuationPointAfterTasksLeft = insertionPoint.Append(tasksLeft); tasksLeft.CheckFailedOperations = new SearchProgramList(tasksLeft); insertionPoint = tasksLeft.CheckFailedOperations; // ---- check failed, no tasks left, leaf subpattern was matched string inlinedPatternClassName = rulePatternClassName; string pathPrefixInInlinedPatternClass = patternGraph.pathPrefix; string unprefixedNameInInlinedPatternClass = patternGraph.name; if(patternGraph.originalPatternGraph != null) { inlinedPatternClassName = patternGraph.originalSubpatternEmbedding.matchingPatternOfEmbeddedGraph.GetType().Name; pathPrefixInInlinedPatternClass = patternGraph.originalPatternGraph.pathPrefix; unprefixedNameInInlinedPatternClass = patternGraph.originalPatternGraph.name; } LeafSubpatternMatched leafMatched = new LeafSubpatternMatched( inlinedPatternClassName, pathPrefixInInlinedPatternClass+unprefixedNameInInlinedPatternClass, false); SearchProgramOperation continuationPointAfterLeafMatched = insertionPoint.Append(leafMatched); leafMatched.MatchBuildingOperations = new SearchProgramList(leafMatched); insertionPoint = leafMatched.MatchBuildingOperations; // ---- ---- fill the match object with the candidates // ---- ---- which have passed all the checks for being a match insertionPoint = insertInlinedMatchObjectCreation(insertionPoint, patternGraph, MatchObjectType.Normal); insertionPoint = insertMatchObjectBuilding(insertionPoint, patternGraph, MatchObjectType.Normal, false); insertionPoint = insertMatchObjectBuilding(insertionPoint, patternGraph, MatchObjectType.Normal, true); // if an independent was inlined, we have to insert the local match into a set used for duplicate checking if(wasIndependentInlined(patternGraph, indexOfSchedule)) insertionPoint = insertFillForDuplicateMatchChecking(insertionPoint); // ---- nesting level up insertionPoint = continuationPointAfterLeafMatched; // ---- check max matches reached will be inserted here by completion pass // nesting level up insertionPoint = continuationPointAfterTasksLeft; return insertionPoint; }
/// <summary> /// Inserts code to pop the subpattern tasks from the open tasks stack /// at the given position, returns position after inserted operations /// </summary> private SearchProgramOperation insertPopSubpatternTasks(SearchProgramOperation insertionPoint) { PatternGraph patternGraph = patternGraphWithNestingPatterns.Peek(); string negativeIndependentNamePrefix = NegativeIndependentNamePrefix(patternGraph); foreach (PatternGraphEmbedding subpattern in patternGraph.embeddedGraphsPlusInlined) { if(subpattern.inlined) continue; PopSubpatternTask popTask = new PopSubpatternTask( negativeIndependentNamePrefix, PushAndPopSubpatternTaskTypes.Subpattern, subpattern.matchingPatternOfEmbeddedGraph.name, subpattern.name, parallelized ); insertionPoint = insertionPoint.Append(popTask); } foreach (Iterated iterated in patternGraph.iteratedsPlusInlined) { PopSubpatternTask popTask = new PopSubpatternTask( negativeIndependentNamePrefix, PushAndPopSubpatternTaskTypes.Iterated, iterated.iteratedPattern.name, iterated.iteratedPattern.pathPrefix, parallelized ); insertionPoint = insertionPoint.Append(popTask); } foreach (Alternative alternative in patternGraph.alternativesPlusInlined) { PopSubpatternTask popTask = new PopSubpatternTask( negativeIndependentNamePrefix, PushAndPopSubpatternTaskTypes.Alternative, alternative.name, alternative.pathPrefix, parallelized ); insertionPoint = insertionPoint.Append(popTask); } return insertionPoint; }
/////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Builds search program operations from scheduled search plan operation. /// Decides which specialized build procedure is to be called. /// The specialized build procedure then calls this procedure again, /// in order to process the next search plan operation. /// </summary> private SearchProgramOperation BuildScheduledSearchPlanOperationIntoSearchProgram( int indexOfScheduledSearchPlanOperationToBuild, SearchProgramOperation insertionPointWithinSearchProgram) { PatternGraph patternGraph = patternGraphWithNestingPatterns.Peek(); SearchOperation op; if(parallelized) { if(indexOfScheduledSearchPlanOperationToBuild >= patternGraph.parallelizedSchedule[indexOfSchedule].Operations.Length) { // end of scheduled search plan reached, stop recursive iteration (of body, the head ends with a parallel setup operation) return buildMatchComplete(insertionPointWithinSearchProgram); } op = patternGraph.parallelizedSchedule[indexOfSchedule]. Operations[indexOfScheduledSearchPlanOperationToBuild]; } else { if(indexOfScheduledSearchPlanOperationToBuild >= patternGraph.schedulesIncludingNegativesAndIndependents[indexOfSchedule].Operations.Length) { // end of scheduled search plan reached, stop recursive iteration return buildMatchComplete(insertionPointWithinSearchProgram); } op = patternGraph.schedulesIncludingNegativesAndIndependents[indexOfSchedule]. Operations[indexOfScheduledSearchPlanOperationToBuild]; } // for current scheduled search plan operation // insert corresponding search program operations into search program switch(op.Type) { case SearchOperationType.Void: return BuildScheduledSearchPlanOperationIntoSearchProgram( indexOfScheduledSearchPlanOperationToBuild + 1, insertionPointWithinSearchProgram); case SearchOperationType.ActionPreset: return buildActionPreset(insertionPointWithinSearchProgram, indexOfScheduledSearchPlanOperationToBuild, (SearchPlanNode)op.Element, op.Isomorphy); case SearchOperationType.NegIdptPreset: return buildNegIdptPreset(insertionPointWithinSearchProgram, indexOfScheduledSearchPlanOperationToBuild, (SearchPlanNode)op.Element, op.Isomorphy); case SearchOperationType.SubPreset: return buildSubPreset(insertionPointWithinSearchProgram, indexOfScheduledSearchPlanOperationToBuild, (SearchPlanNode)op.Element, op.Isomorphy); case SearchOperationType.DefToBeYieldedTo: return buildDefToBeYieldedTo(insertionPointWithinSearchProgram, indexOfScheduledSearchPlanOperationToBuild, op.Element); case SearchOperationType.Lookup: return buildLookup(insertionPointWithinSearchProgram, indexOfScheduledSearchPlanOperationToBuild, (SearchPlanNode)op.Element, op.Isomorphy); case SearchOperationType.PickFromStorage: return buildPickFromStorage(insertionPointWithinSearchProgram, indexOfScheduledSearchPlanOperationToBuild, (SearchPlanNode)op.Element, op.Storage, op.Isomorphy); case SearchOperationType.PickFromStorageDependent: return buildPickFromStorageDependent(insertionPointWithinSearchProgram, indexOfScheduledSearchPlanOperationToBuild, op.SourceSPNode, (SearchPlanNode)op.Element, op.Storage, op.Isomorphy); case SearchOperationType.PickFromIndex: return buildPickFromIndex(insertionPointWithinSearchProgram, indexOfScheduledSearchPlanOperationToBuild, (SearchPlanNode)op.Element, op.IndexAccess, op.Isomorphy); case SearchOperationType.PickFromIndexDependent: return buildPickFromIndex(insertionPointWithinSearchProgram, indexOfScheduledSearchPlanOperationToBuild, //op.SourceSPNode, (SearchPlanNode)op.Element, op.IndexAccess, op.Isomorphy); case SearchOperationType.PickByName: return buildPickByName(insertionPointWithinSearchProgram, indexOfScheduledSearchPlanOperationToBuild, (SearchPlanNode)op.Element, op.NameLookup, op.Isomorphy); case SearchOperationType.PickByNameDependent: return buildPickByName(insertionPointWithinSearchProgram, indexOfScheduledSearchPlanOperationToBuild, //op.SourceSPNode, (SearchPlanNode)op.Element, op.NameLookup, op.Isomorphy); case SearchOperationType.PickByUnique: return buildPickByUnique(insertionPointWithinSearchProgram, indexOfScheduledSearchPlanOperationToBuild, (SearchPlanNode)op.Element, op.UniqueLookup, op.Isomorphy); case SearchOperationType.PickByUniqueDependent: return buildPickByUnique(insertionPointWithinSearchProgram, indexOfScheduledSearchPlanOperationToBuild, //op.SourceSPNode, (SearchPlanNode)op.Element, op.UniqueLookup, op.Isomorphy); case SearchOperationType.Cast: return buildCast(insertionPointWithinSearchProgram, indexOfScheduledSearchPlanOperationToBuild, op.SourceSPNode, (SearchPlanNode)op.Element, op.Isomorphy); case SearchOperationType.Assign: return buildAssign(insertionPointWithinSearchProgram, indexOfScheduledSearchPlanOperationToBuild, op.SourceSPNode, (SearchPlanNode)op.Element, op.Isomorphy); case SearchOperationType.Identity: return buildIdentity(insertionPointWithinSearchProgram, indexOfScheduledSearchPlanOperationToBuild, op.SourceSPNode, (SearchPlanNode)op.Element, op.Isomorphy); case SearchOperationType.AssignVar: return buildAssignVar(insertionPointWithinSearchProgram, indexOfScheduledSearchPlanOperationToBuild, (PatternVariable)op.Element, op.Expression); case SearchOperationType.MapWithStorage: return buildMapWithStorage(insertionPointWithinSearchProgram, indexOfScheduledSearchPlanOperationToBuild, (SearchPlanNode)op.Element, op.Storage, op.StorageIndex, op.Isomorphy); case SearchOperationType.MapWithStorageDependent: return buildMapWithStorageDependent(insertionPointWithinSearchProgram, indexOfScheduledSearchPlanOperationToBuild, op.SourceSPNode, (SearchPlanNode)op.Element, op.Storage, op.StorageIndex, op.Isomorphy); case SearchOperationType.ImplicitSource: return buildImplicit(insertionPointWithinSearchProgram, indexOfScheduledSearchPlanOperationToBuild, (SearchPlanEdgeNode)op.SourceSPNode, (SearchPlanNodeNode)op.Element, op.Isomorphy, ImplicitNodeType.Source); case SearchOperationType.ImplicitTarget: return buildImplicit(insertionPointWithinSearchProgram, indexOfScheduledSearchPlanOperationToBuild, (SearchPlanEdgeNode)op.SourceSPNode, (SearchPlanNodeNode)op.Element, op.Isomorphy, ImplicitNodeType.Target); case SearchOperationType.Implicit: return buildImplicit(insertionPointWithinSearchProgram, indexOfScheduledSearchPlanOperationToBuild, (SearchPlanEdgeNode)op.SourceSPNode, (SearchPlanNodeNode)op.Element, op.Isomorphy, ImplicitNodeType.SourceOrTarget); case SearchOperationType.Incoming: return buildIncident(insertionPointWithinSearchProgram, indexOfScheduledSearchPlanOperationToBuild, (SearchPlanNodeNode)op.SourceSPNode, (SearchPlanEdgeNode)op.Element, op.Isomorphy, IncidentEdgeType.Incoming); case SearchOperationType.Outgoing: return buildIncident(insertionPointWithinSearchProgram, indexOfScheduledSearchPlanOperationToBuild, (SearchPlanNodeNode)op.SourceSPNode, (SearchPlanEdgeNode)op.Element, op.Isomorphy, IncidentEdgeType.Outgoing); case SearchOperationType.Incident: return buildIncident(insertionPointWithinSearchProgram, indexOfScheduledSearchPlanOperationToBuild, (SearchPlanNodeNode)op.SourceSPNode, (SearchPlanEdgeNode)op.Element, op.Isomorphy, IncidentEdgeType.IncomingOrOutgoing); case SearchOperationType.Condition: return buildCondition(insertionPointWithinSearchProgram, indexOfScheduledSearchPlanOperationToBuild, (PatternCondition)op.Element); case SearchOperationType.LockLocalElementsForPatternpath: return buildLockLocalElementsForPatternpath(insertionPointWithinSearchProgram, indexOfScheduledSearchPlanOperationToBuild); case SearchOperationType.NegativePattern: return buildNegative(insertionPointWithinSearchProgram, indexOfScheduledSearchPlanOperationToBuild, ((ScheduledSearchPlan)op.Element).PatternGraph); case SearchOperationType.IndependentPattern: return buildIndependent(insertionPointWithinSearchProgram, indexOfScheduledSearchPlanOperationToBuild, ((ScheduledSearchPlan)op.Element).PatternGraph); case SearchOperationType.InlinedIndependentCheckForDuplicateMatch: return buildInlinedIndependentCheckForDuplicateMatch(insertionPointWithinSearchProgram, indexOfScheduledSearchPlanOperationToBuild); case SearchOperationType.WriteParallelPreset: return buildWriteParallelPreset(insertionPointWithinSearchProgram, indexOfScheduledSearchPlanOperationToBuild, (SearchPlanNode)op.Element); case SearchOperationType.WriteParallelPresetVar: return buildWriteParallelPresetVar(insertionPointWithinSearchProgram, indexOfScheduledSearchPlanOperationToBuild, (PatternVariable)op.Element); case SearchOperationType.ParallelPreset: return buildParallelPreset(insertionPointWithinSearchProgram, indexOfScheduledSearchPlanOperationToBuild, (SearchPlanNode)op.Element); case SearchOperationType.ParallelPresetVar: return buildParallelPresetVar(insertionPointWithinSearchProgram, indexOfScheduledSearchPlanOperationToBuild, (PatternVariable)op.Element); case SearchOperationType.SetupParallelLookup: Debug.Assert(indexOfScheduledSearchPlanOperationToBuild >= patternGraph.parallelizedSchedule[indexOfSchedule].Operations.Length - 1, "Setup parallel must be last operation in schedule"); return buildParallelLookupSetup(insertionPointWithinSearchProgram, (SearchPlanNode)op.Element); case SearchOperationType.ParallelLookup: return buildParallelLookup(insertionPointWithinSearchProgram, indexOfScheduledSearchPlanOperationToBuild, (SearchPlanNode)op.Element, op.Isomorphy); case SearchOperationType.SetupParallelPickFromStorage: Debug.Assert(indexOfScheduledSearchPlanOperationToBuild >= patternGraph.parallelizedSchedule[indexOfSchedule].Operations.Length - 1, "Setup parallel must be last operation in schedule"); return buildParallelPickFromStorageSetup(insertionPointWithinSearchProgram, (SearchPlanNode)op.Element, op.Storage); case SearchOperationType.ParallelPickFromStorage: return buildParallelPickFromStorage(insertionPointWithinSearchProgram, indexOfScheduledSearchPlanOperationToBuild, (SearchPlanNode)op.Element, op.Storage, op.Isomorphy); case SearchOperationType.SetupParallelPickFromStorageDependent: Debug.Assert(indexOfScheduledSearchPlanOperationToBuild >= patternGraph.parallelizedSchedule[indexOfSchedule].Operations.Length - 1, "Setup parallel must be last operation in schedule"); return buildParallelPickFromStorageDependentSetup(insertionPointWithinSearchProgram, op.SourceSPNode, (SearchPlanNode)op.Element, op.Storage); case SearchOperationType.ParallelPickFromStorageDependent: return buildParallelPickFromStorageDependent(insertionPointWithinSearchProgram, indexOfScheduledSearchPlanOperationToBuild, op.SourceSPNode, (SearchPlanNode)op.Element, op.Storage, op.Isomorphy); case SearchOperationType.SetupParallelPickFromIndex: Debug.Assert(indexOfScheduledSearchPlanOperationToBuild >= patternGraph.parallelizedSchedule[indexOfSchedule].Operations.Length - 1, "Setup parallel must be last operation in schedule"); return buildParallelPickFromIndexSetup(insertionPointWithinSearchProgram, (SearchPlanNode)op.Element, op.IndexAccess); case SearchOperationType.ParallelPickFromIndex: return buildParallelPickFromIndex(insertionPointWithinSearchProgram, indexOfScheduledSearchPlanOperationToBuild, (SearchPlanNode)op.Element, op.IndexAccess, op.Isomorphy); case SearchOperationType.SetupParallelPickFromIndexDependent: Debug.Assert(indexOfScheduledSearchPlanOperationToBuild >= patternGraph.parallelizedSchedule[indexOfSchedule].Operations.Length - 1, "Setup parallel must be last operation in schedule"); return buildParallelPickFromIndexSetup(insertionPointWithinSearchProgram, //op.SourceSPNode, (SearchPlanNode)op.Element, op.IndexAccess); case SearchOperationType.ParallelPickFromIndexDependent: return buildParallelPickFromIndex(insertionPointWithinSearchProgram, indexOfScheduledSearchPlanOperationToBuild, //op.SourceSPNode, (SearchPlanNode)op.Element, op.IndexAccess, op.Isomorphy); case SearchOperationType.SetupParallelOutgoing: Debug.Assert(indexOfScheduledSearchPlanOperationToBuild >= patternGraph.parallelizedSchedule[indexOfSchedule].Operations.Length - 1, "Setup parallel must be last operation in schedule"); return buildParallelIncidentSetup(insertionPointWithinSearchProgram, (SearchPlanNodeNode)op.SourceSPNode, (SearchPlanEdgeNode)op.Element, IncidentEdgeType.Outgoing); case SearchOperationType.ParallelOutgoing: return buildParallelIncident(insertionPointWithinSearchProgram, indexOfScheduledSearchPlanOperationToBuild, (SearchPlanNodeNode)op.SourceSPNode, (SearchPlanEdgeNode)op.Element, op.Isomorphy, IncidentEdgeType.Outgoing); case SearchOperationType.SetupParallelIncoming: Debug.Assert(indexOfScheduledSearchPlanOperationToBuild >= patternGraph.parallelizedSchedule[indexOfSchedule].Operations.Length - 1, "Setup parallel must be last operation in schedule"); return buildParallelIncidentSetup(insertionPointWithinSearchProgram, (SearchPlanNodeNode)op.SourceSPNode, (SearchPlanEdgeNode)op.Element, IncidentEdgeType.Incoming); case SearchOperationType.ParallelIncoming: return buildParallelIncident(insertionPointWithinSearchProgram, indexOfScheduledSearchPlanOperationToBuild, (SearchPlanNodeNode)op.SourceSPNode, (SearchPlanEdgeNode)op.Element, op.Isomorphy, IncidentEdgeType.Incoming); case SearchOperationType.SetupParallelIncident: Debug.Assert(indexOfScheduledSearchPlanOperationToBuild >= patternGraph.parallelizedSchedule[indexOfSchedule].Operations.Length - 1, "Setup parallel must be last operation in schedule"); return buildParallelIncidentSetup(insertionPointWithinSearchProgram, (SearchPlanNodeNode)op.SourceSPNode, (SearchPlanEdgeNode)op.Element, IncidentEdgeType.IncomingOrOutgoing); case SearchOperationType.ParallelIncident: return buildParallelIncident(insertionPointWithinSearchProgram, indexOfScheduledSearchPlanOperationToBuild, (SearchPlanNodeNode)op.SourceSPNode, (SearchPlanEdgeNode)op.Element, op.Isomorphy, IncidentEdgeType.IncomingOrOutgoing); default: Debug.Assert(false, "Unknown search operation"); return insertionPointWithinSearchProgram; } }
/// <summary> /// Inserts code to push the subpattern tasks to the open tasks stack /// at the given position, returns position after inserted operations /// </summary> private SearchProgramOperation insertPushSubpatternTasks(SearchProgramOperation insertionPoint) { PatternGraph patternGraph = patternGraphWithNestingPatterns.Peek(); string negativeIndependentNamePrefix = NegativeIndependentNamePrefix(patternGraph); string searchPatternpath = "false"; string matchOfNestingPattern = "null"; string lastMatchAtPreviousNestingLevel = "null"; if(patternGraph.patternGraphsOnPathToEnclosedPatternpath.Count > 0) { if(patternGraph.isPatternpathLocked) searchPatternpath = "true"; if((programType == SearchProgramType.Subpattern || programType == SearchProgramType.AlternativeCase || programType == SearchProgramType.Iterated) && patternGraphWithNestingPatterns.Count == 1) { searchPatternpath = "searchPatternpath"; } matchOfNestingPattern = NamesOfEntities.PatternpathMatch(patternGraph.pathPrefix + patternGraph.name); lastMatchAtPreviousNestingLevel = getCurrentLastMatchAtPreviousNestingLevel(); } // first alternatives, so that they get processed last // to handle subpatterns in linear order we've to push them in reverse order on the stack for (int i = patternGraph.alternativesPlusInlined.Length - 1; i >= 0; --i) { Alternative alternative = patternGraph.alternativesPlusInlined[i]; Dictionary<string, bool> neededNodes = new Dictionary<string, bool>(); Dictionary<string, bool> neededEdges = new Dictionary<string, bool>(); Dictionary<string, GrGenType> neededVariables = new Dictionary<string, GrGenType>(); foreach(PatternGraph altCase in alternative.alternativeCases) { foreach (KeyValuePair<string, bool> neededNode in altCase.neededNodes) neededNodes[neededNode.Key] = neededNode.Value; foreach (KeyValuePair<string, bool> neededEdge in altCase.neededEdges) neededEdges[neededEdge.Key] = neededEdge.Value; foreach(KeyValuePair<string, GrGenType> neededVariable in altCase.neededVariables) neededVariables[neededVariable.Key] = neededVariable.Value; } int numElements = neededNodes.Count + neededEdges.Count + neededVariables.Count; string[] connectionName = new string[numElements]; string[] argumentExpressions = new string[numElements]; int j = 0; foreach (KeyValuePair<string, bool> node in neededNodes) { connectionName[j] = node.Key; SourceBuilder argumentExpression = new SourceBuilder(); (new GraphEntityExpression(node.Key)).Emit(argumentExpression); argumentExpressions[j] = argumentExpression.ToString(); ++j; } foreach (KeyValuePair<string, bool> edge in neededEdges) { connectionName[j] = edge.Key; SourceBuilder argumentExpression = new SourceBuilder(); (new GraphEntityExpression(edge.Key)).Emit(argumentExpression); argumentExpressions[j] = argumentExpression.ToString(); ++j; } foreach(KeyValuePair<string, GrGenType> variable in neededVariables) { connectionName[j] = variable.Key; SourceBuilder argumentExpression = new SourceBuilder(); (new VariableExpression(variable.Key)).Emit(argumentExpression); argumentExpressions[j] = argumentExpression.ToString(); ++j; } string inlinedPatternClassName = rulePatternClassName; string pathPrefixInInlinedPatternClass = alternative.pathPrefix; string unprefixedNameInInlinedPatternClass = alternative.name; if(alternative.originalAlternative != null) { inlinedPatternClassName = alternative.originalSubpatternEmbedding.matchingPatternOfEmbeddedGraph.GetType().Name; pathPrefixInInlinedPatternClass = alternative.originalAlternative.pathPrefix; unprefixedNameInInlinedPatternClass = alternative.originalAlternative.name; } PushSubpatternTask pushTask = new PushSubpatternTask( PushAndPopSubpatternTaskTypes.Alternative, alternative.pathPrefix, alternative.name, inlinedPatternClassName, pathPrefixInInlinedPatternClass, unprefixedNameInInlinedPatternClass, connectionName, argumentExpressions, negativeIndependentNamePrefix, searchPatternpath, matchOfNestingPattern, lastMatchAtPreviousNestingLevel, parallelized ); insertionPoint = insertionPoint.Append(pushTask); } // then iterated patterns of the pattern // to handle iterated in linear order we've to push them in reverse order on the stack for (int i = patternGraph.iteratedsPlusInlined.Length - 1; i >= 0; --i) { PatternGraph iter = patternGraph.iteratedsPlusInlined[i].iteratedPattern; int numElements = iter.neededNodes.Count + iter.neededEdges.Count + iter.neededVariables.Count; string[] connectionName = new string[numElements]; string[] argumentExpressions = new string[numElements]; int j = 0; foreach (KeyValuePair<string, bool> node in iter.neededNodes) { connectionName[j] = node.Key; SourceBuilder argumentExpression = new SourceBuilder(); (new GraphEntityExpression(node.Key)).Emit(argumentExpression); argumentExpressions[j] = argumentExpression.ToString(); ++j; } foreach (KeyValuePair<string, bool> edge in iter.neededEdges) { connectionName[j] = edge.Key; SourceBuilder argumentExpression = new SourceBuilder(); (new GraphEntityExpression(edge.Key)).Emit(argumentExpression); argumentExpressions[j] = argumentExpression.ToString(); ++j; } foreach(KeyValuePair<string, GrGenType> variable in iter.neededVariables) { connectionName[j] = variable.Key; SourceBuilder argumentExpression = new SourceBuilder(); (new VariableExpression(variable.Key)).Emit(argumentExpression); argumentExpressions[j] = argumentExpression.ToString(); ++j; } PushSubpatternTask pushTask = new PushSubpatternTask( PushAndPopSubpatternTaskTypes.Iterated, iter.pathPrefix, iter.name, rulePatternClassName, "", "", connectionName, argumentExpressions, negativeIndependentNamePrefix, searchPatternpath, matchOfNestingPattern, lastMatchAtPreviousNestingLevel, parallelized ); insertionPoint = insertionPoint.Append(pushTask); } // and finally subpatterns of the pattern // to handle subpatterns in linear order we've to push them in reverse order on the stack for (int i = patternGraph.embeddedGraphsPlusInlined.Length - 1; i >= 0; --i) { PatternGraphEmbedding subpattern = patternGraph.embeddedGraphsPlusInlined[i]; if(subpattern.inlined) continue; Debug.Assert(subpattern.matchingPatternOfEmbeddedGraph.inputNames.Length == subpattern.connections.Length); string[] connectionName = subpattern.matchingPatternOfEmbeddedGraph.inputNames; string[] argumentExpressions = new string[subpattern.connections.Length]; for (int j = 0; j < subpattern.connections.Length; ++j) { SourceBuilder argumentExpression = new SourceBuilder(); subpattern.connections[j].Emit(argumentExpression); argumentExpressions[j] = argumentExpression.ToString(); } PushSubpatternTask pushTask = new PushSubpatternTask( PushAndPopSubpatternTaskTypes.Subpattern, subpattern.matchingPatternOfEmbeddedGraph.name, subpattern.name, connectionName, argumentExpressions, negativeIndependentNamePrefix, searchPatternpath, matchOfNestingPattern, lastMatchAtPreviousNestingLevel, parallelized ); insertionPoint = insertionPoint.Append(pushTask); } return insertionPoint; }
public SearchProgramList(SearchProgramOperation enclosingOperation) { Previous = enclosingOperation; }
/// <summary> /// move outwards from check operation until operation to continue at is found /// appending restore isomorphy for isomorphy written on the way /// and final jump to operation to continue at /// </summary> private static void MoveOutwardsAppendingRemoveIsomorphyAndJump( CheckOperation checkOperation, string[] neededElementsForCheckOperation, SearchProgramOperation outermostOperation, SearchProgram topLevelSearchProgram) { // insertion point for candidate failed operations SearchProgramOperation insertionPoint = checkOperation.CheckFailedOperations; while (insertionPoint.Next != null) { insertionPoint = insertionPoint.Next; } // set outermost to iterated matching dummy loop if iterated if (outermostOperation is SearchProgramOfIterated) { SearchProgramOperation cur = checkOperation; while (!(cur is IteratedMatchingDummyLoop)) { cur = cur.Previous; } outermostOperation = cur; } SearchProgramOperation continuationPoint = MoveOutwardsAppendingRemoveIsomorphy( checkOperation, ref insertionPoint, neededElementsForCheckOperation, outermostOperation, topLevelSearchProgram); // decide on type of continuing operation, then insert it // continue at top nesting level -> return SearchProgramOperation op = continuationPoint; while (!(op is SearchProgram)) { op = op.Previous; } SearchProgram searchProgramRoot = op as SearchProgram; if (continuationPoint == searchProgramRoot) { ContinueOperation continueByReturn = new ContinueOperation( ContinueOperationType.ByReturn, searchProgramRoot is SearchProgramOfAction || searchProgramRoot is SearchProgramOfActionParallelizationHead, searchProgramRoot is SearchProgramOfActionParallelizationBody ); insertionPoint.Append(continueByReturn); return; } // continue at directly enclosing nesting level -> continue op = checkOperation; do { op = op.Previous; }while(!op.IsSearchNestingOperation()); SearchProgramOperation directlyEnclosingOperation = op; if (continuationPoint == directlyEnclosingOperation // (check negative/independent is enclosing, but not a loop, thus continue wouldn't work) && !(directlyEnclosingOperation is CheckPartialMatchByNegative) && !(directlyEnclosingOperation is CheckPartialMatchByIndependent) // (check partial match for duplicate contains an internal loop in checking, thus continue wouldn't work) && !(checkOperation is CheckPartialMatchForDuplicate)) { ContinueOperation continueByContinue = new ContinueOperation(ContinueOperationType.ByContinue, directlyEnclosingOperation is GetCandidateByIterationParallel); insertionPoint.Append(continueByContinue); return; } // otherwise -> goto label string gotoLabelName; // if our continuation point is a candidate iteration // -> append label at the end of the loop body of the candidate iteration loop if (continuationPoint is GetCandidateByIteration) { GetCandidateByIteration candidateIteration = continuationPoint as GetCandidateByIteration; op = candidateIteration.NestedOperationsList; while (op.Next != null) { op = op.Next; } GotoLabel gotoLabel = new GotoLabel(); op.Append(gotoLabel); gotoLabelName = gotoLabel.LabelName; } // if our continuation point is a candidate iteration parallel // -> append label at the end of the loop body of the candidate iteration loop else if (continuationPoint is GetCandidateByIterationParallel) { GetCandidateByIterationParallel candidateIteration = continuationPoint as GetCandidateByIterationParallel; op = candidateIteration.NestedOperationsList; while (op.Next != null) { op = op.Next; } GotoLabel gotoLabel = new GotoLabel(); op.Append(gotoLabel); gotoLabelName = gotoLabel.LabelName; } // if our continuation point is a both directions iteration // -> append label at the end of the loop body of the both directions iteration loop else if (continuationPoint is BothDirectionsIteration) { BothDirectionsIteration bothDirections = continuationPoint as BothDirectionsIteration; op = bothDirections.NestedOperationsList; while (op.Next != null) { op = op.Next; } GotoLabel gotoLabel = new GotoLabel(); op.Append(gotoLabel); gotoLabelName = gotoLabel.LabelName; } // if our continuation point is an alternative case // -> append label at the end of the alternative case operations else if (continuationPoint is AlternativeCaseMatching) { AlternativeCaseMatching alternativeCase = continuationPoint as AlternativeCaseMatching; op = alternativeCase.OperationsList; while (op.Next != null) { op = op.Next; } GotoLabel gotoLabel = new GotoLabel(); op.Append(gotoLabel); gotoLabelName = gotoLabel.LabelName; } // if our continuation point is the dummy loop of an iterated operation // -> we just jump to the label maxMatchesIterReached directly after the loop else if (continuationPoint is IteratedMatchingDummyLoop) { gotoLabelName = "maxMatchesIterReached"; } // otherwise our continuation point is a check negative/independent operation // -> insert label directly after the check negative/independent operation else { CheckPartialMatchByNegativeOrIndependent checkNegativeIndependent = continuationPoint as CheckPartialMatchByNegativeOrIndependent; GotoLabel gotoLabel = new GotoLabel(); checkNegativeIndependent.Insert(gotoLabel); gotoLabelName = gotoLabel.LabelName; } ContinueOperation continueByGoto = new ContinueOperation( ContinueOperationType.ByGoto, gotoLabelName); // ByGoto due to parameters insertionPoint.Append(continueByGoto); }
/// <summary> /// Decides which check connectedness operations are needed for the given node and edge of fixed direction /// and inserts them into the search program /// </summary> private SearchProgramOperation decideOnAndInsertCheckConnectednessOfNodeFixedDirection( SearchProgramOperation insertionPoint, SearchPlanNodeNode currentNode, SearchPlanEdgeNode edge, CheckCandidateForConnectednessType connectednessType) { Debug.Assert(connectednessType == CheckCandidateForConnectednessType.Source || connectednessType == CheckCandidateForConnectednessType.Target); // check whether the pattern edges which must be incident to the candidate node (according to the pattern) // are really incident to it // only if edge is already matched by now (signaled by visited) if (edge.Visited) { CheckCandidateForConnectedness checkConnectedness = new CheckCandidateForConnectedness( currentNode.PatternElement.Name, currentNode.PatternElement.Name, edge.PatternElement.Name, connectednessType); insertionPoint = insertionPoint.Append(checkConnectedness); } return insertionPoint; }
/// <summary> /// Inserts code to abandon the matched elements globally /// at the given position, returns position after inserted operations /// </summary> private SearchProgramOperation insertGlobalAbandon(SearchProgramOperation insertionPoint) { bool isAction = programType == SearchProgramType.Action; PatternGraph patternGraph = patternGraphWithNestingPatterns.Peek(); string negativeIndependentNamePrefix = NegativeIndependentNamePrefix(patternGraph); // global abandon of all candidate elements (remove isomorphy information) for (int i = 0; i < patternGraph.nodesPlusInlined.Length; ++i) { if (patternGraph.nodesPlusInlined[i].PointOfDefinition == patternGraph || patternGraph.nodesPlusInlined[i].PointOfDefinition == null && isAction) { if(!patternGraph.nodesPlusInlined[i].defToBeYieldedTo && !patternGraph.totallyHomomorphicNodes[i] && patternGraph.nodesPlusInlined[i].AssignmentSource==null) { AbandonCandidateGlobal abandonGlobal = new AbandonCandidateGlobal(patternGraph.nodesPlusInlined[i].name, negativeIndependentNamePrefix, true, isoSpaceNeverAboveMaxIsoSpace, parallelized); insertionPoint = insertionPoint.Append(abandonGlobal); } } } for (int i = 0; i < patternGraph.edgesPlusInlined.Length; ++i) { if (patternGraph.edgesPlusInlined[i].PointOfDefinition == patternGraph || patternGraph.edgesPlusInlined[i].PointOfDefinition == null && isAction) { if(!patternGraph.edgesPlusInlined[i].defToBeYieldedTo && !patternGraph.totallyHomomorphicEdges[i] && patternGraph.edgesPlusInlined[i].AssignmentSource==null) { AbandonCandidateGlobal abandonGlobal = new AbandonCandidateGlobal(patternGraph.edgesPlusInlined[i].name, negativeIndependentNamePrefix, false, isoSpaceNeverAboveMaxIsoSpace, parallelized); insertionPoint = insertionPoint.Append(abandonGlobal); } } } return insertionPoint; }
/// <summary> /// Decides which check connectedness operations are needed for the given edge determined by lookup /// and inserts them into the search program /// returns new insertion point and continuation point /// for continuing buildup after the stuff nested within both directions iteration was built /// if no direction iteration was needed, insertion point == continuation point /// </summary> private SearchProgramOperation decideOnAndInsertCheckConnectednessOfEdgeFromLookupOrPickOrMap( SearchProgramOperation insertionPoint, SearchPlanEdgeNode edge, out SearchProgramOperation continuationPoint) { continuationPoint = null; if (((PatternEdge)edge.PatternElement).fixedDirection) { // don't need to check if the edge is not required by the pattern to be incident to some given node if (edge.PatternEdgeSource != null) { insertionPoint = decideOnAndInsertCheckConnectednessOfEdgeFixedDirection( insertionPoint, edge, CheckCandidateForConnectednessType.Source); } if (edge.PatternEdgeTarget != null) { insertionPoint = decideOnAndInsertCheckConnectednessOfEdgeFixedDirection( insertionPoint, edge, CheckCandidateForConnectednessType.Target); } } else { insertionPoint = decideOnAndInsertCheckConnectednessOfEdgeBothDirections( insertionPoint, edge, false, out continuationPoint); } if (continuationPoint == null) continuationPoint = insertionPoint; return insertionPoint; }
/// <summary> /// Decides which check connectedness operations are needed for the given node and edge in both directions /// and inserts them into the search program /// returns new insertion point and continuation point /// for continuing buildup after the stuff nested within both directions iteration was built /// if no direction iteration was needed, insertion point == continuation point /// </summary> private SearchProgramOperation decideOnAndInsertCheckConnectednessOfNodeBothDirections( SearchProgramOperation insertionPoint, SearchPlanNodeNode currentNode, SearchPlanEdgeNode edge, out SearchProgramOperation continuationPoint) { Debug.Assert(edge.PatternEdgeSource != edge.PatternEdgeTarget); continuationPoint = null; // check whether the pattern edges which must be incident to the candidate node (according to the pattern) // are really incident to it if (currentNodeIsFirstIncidentNodeOfEdge(currentNode, edge)) { BothDirectionsIteration directionsIteration = new BothDirectionsIteration(edge.PatternElement.Name); directionsIteration.NestedOperationsList = new SearchProgramList(directionsIteration); continuationPoint = insertionPoint.Append(directionsIteration); CheckCandidateForConnectedness checkConnectedness = new CheckCandidateForConnectedness( currentNode.PatternElement.Name, currentNode.PatternElement.Name, edge.PatternElement.Name, CheckCandidateForConnectednessType.SourceOrTarget); insertionPoint = directionsIteration.NestedOperationsList.Append(checkConnectedness); } if (currentNodeIsSecondIncidentNodeOfEdge(currentNode, edge)) { CheckCandidateForConnectedness checkConnectedness = new CheckCandidateForConnectedness( currentNode.PatternElement.Name, currentNode.PatternElement.Name, edge.PatternElement.Name, edge.PatternEdgeSource == currentNode ? edge.PatternEdgeTarget.PatternElement.Name : edge.PatternEdgeSource.PatternElement.Name, CheckCandidateForConnectednessType.TheOther); insertionPoint = insertionPoint.Append(checkConnectedness); } if (continuationPoint == null) continuationPoint = insertionPoint; return insertionPoint; }
/// <summary> /// Inserts code to abandon the matched elements for patternpath check /// at the given position, returns position after inserted operations /// </summary> private SearchProgramOperation insertPatternpathAbandon(SearchProgramOperation insertionPoint, PatternGraph patternGraph) { bool isAction = programType == SearchProgramType.Action; string negativeIndependentNamePrefix = NegativeIndependentNamePrefix(patternGraph); // patternpath abandon of all candidate elements (remove isomorphy information) for (int i = 0; i < patternGraph.nodesPlusInlined.Length; ++i) { if (patternGraph.nodesPlusInlined[i].PointOfDefinition == patternGraph || patternGraph.nodesPlusInlined[i].PointOfDefinition == null && isAction) { if(!patternGraph.nodesPlusInlined[i].defToBeYieldedTo) { AbandonCandidatePatternpath abandonPatternpath = new AbandonCandidatePatternpath(patternGraph.nodesPlusInlined[i].name, negativeIndependentNamePrefix, true); insertionPoint = insertionPoint.Append(abandonPatternpath); } } } for (int i = 0; i < patternGraph.edgesPlusInlined.Length; ++i) { if (patternGraph.edgesPlusInlined[i].PointOfDefinition == patternGraph || patternGraph.edgesPlusInlined[i].PointOfDefinition == null && isAction) { if(!patternGraph.edgesPlusInlined[i].defToBeYieldedTo) { AbandonCandidatePatternpath abandonPatternpath = new AbandonCandidatePatternpath(patternGraph.edgesPlusInlined[i].name, negativeIndependentNamePrefix, false); insertionPoint = insertionPoint.Append(abandonPatternpath); } } } return insertionPoint; }
/// <summary> /// Decides which check connectedness operations are needed for the given edge determined from incident node /// and inserts them into the search program /// </summary> private SearchProgramOperation decideOnAndInsertCheckConnectednessOfIncidentEdgeFromNode( SearchProgramOperation insertionPoint, SearchPlanEdgeNode edge, SearchPlanNodeNode originatingNode, bool edgeIncomingAtOriginatingNode, out SearchProgramOperation continuationPoint) { continuationPoint = null; if (((PatternEdge)edge.PatternElement).fixedDirection) { // don't need to check if the edge is not required by the pattern to be incident to some given node // or if the edge was taken from the given originating node if (edge.PatternEdgeSource != null) { if (!(!edgeIncomingAtOriginatingNode && edge.PatternEdgeSource == originatingNode)) { insertionPoint = decideOnAndInsertCheckConnectednessOfEdgeFixedDirection( insertionPoint, edge, CheckCandidateForConnectednessType.Source); } } if (edge.PatternEdgeTarget != null) { if (!(edgeIncomingAtOriginatingNode && edge.PatternEdgeTarget == originatingNode)) { insertionPoint = decideOnAndInsertCheckConnectednessOfEdgeFixedDirection( insertionPoint, edge, CheckCandidateForConnectednessType.Target); } } } else { insertionPoint = decideOnAndInsertCheckConnectednessOfEdgeBothDirections( insertionPoint, edge, true, out continuationPoint); } if (continuationPoint == null) continuationPoint = insertionPoint; return insertionPoint; }
/// <summary> /// Inserts code to check whether the subpatterns were found and code for case there were some /// at the given position, returns position after inserted operations /// </summary> private SearchProgramOperation insertCheckForSubpatternsFound(SearchProgramOperation insertionPoint, bool isIteratedNullMatch) { PatternGraph patternGraph = patternGraphWithNestingPatterns.Peek(); string negativeIndependentNamePrefix = NegativeIndependentNamePrefix(patternGraph); // check whether there were no subpattern matches found CheckPartialMatchForSubpatternsFound checkSubpatternsFound = new CheckPartialMatchForSubpatternsFound(negativeIndependentNamePrefix); SearchProgramOperation continuationPointAfterSubpatternsFound = insertionPoint.Append(checkSubpatternsFound); checkSubpatternsFound.CheckFailedOperations = new SearchProgramList(checkSubpatternsFound); insertionPoint = checkSubpatternsFound.CheckFailedOperations; // ---- check failed, some subpattern matches found, pattern and subpatterns were matched PatternAndSubpatternsMatchedType type = PatternAndSubpatternsMatchedType.SubpatternOrAlternative; if (programType == SearchProgramType.Action) { type = PatternAndSubpatternsMatchedType.Action; } else if (programType == SearchProgramType.Iterated) { if (isIteratedNullMatch) type = PatternAndSubpatternsMatchedType.IteratedNullMatch; else type = PatternAndSubpatternsMatchedType.Iterated; } Debug.Assert(!isIteratedNullMatch || programType == SearchProgramType.Iterated); string inlinedPatternClassName = rulePatternClassName; string pathPrefixInInlinedPatternClass = patternGraph.pathPrefix; string unprefixedNameInInlinedPatternClass = patternGraph.name; if(patternGraph.originalPatternGraph != null) { inlinedPatternClassName = patternGraph.originalSubpatternEmbedding.matchingPatternOfEmbeddedGraph.GetType().Name; pathPrefixInInlinedPatternClass = patternGraph.originalPatternGraph.pathPrefix; unprefixedNameInInlinedPatternClass = patternGraph.originalPatternGraph.name; } PatternAndSubpatternsMatched patternAndSubpatternsMatched = new PatternAndSubpatternsMatched( inlinedPatternClassName, pathPrefixInInlinedPatternClass + unprefixedNameInInlinedPatternClass, parallelized && indexOfSchedule == 1, type); SearchProgramOperation continuationPointAfterPatternAndSubpatternsMatched = insertionPoint.Append(patternAndSubpatternsMatched); patternAndSubpatternsMatched.MatchBuildingOperations = new SearchProgramList(patternAndSubpatternsMatched); insertionPoint = patternAndSubpatternsMatched.MatchBuildingOperations; // ---- ---- fill the match object with the candidates // ---- ---- which have passed all the checks for being a match if (!isIteratedNullMatch) { insertionPoint = insertInlinedMatchObjectCreation(insertionPoint, patternGraph, MatchObjectType.Normal); insertionPoint = insertMatchObjectBuilding(insertionPoint, patternGraph, MatchObjectType.Normal, false); insertionPoint = insertMatchObjectBuilding(insertionPoint, patternGraph, MatchObjectType.Normal, true); // if an independent was inlined, we have to insert the local match into a set used for duplicate checking if(wasIndependentInlined(patternGraph, indexOfSchedule)) insertionPoint = insertFillForDuplicateMatchChecking(insertionPoint); } // ---- nesting level up insertionPoint = continuationPointAfterPatternAndSubpatternsMatched; // ---- create new matches list to search on or copy found matches into own matches list if (programType==SearchProgramType.Subpattern || programType==SearchProgramType.AlternativeCase) { // not needed for iterated, because if match was found, that's it NewMatchesListForFollowingMatches newMatchesList = new NewMatchesListForFollowingMatches(false); insertionPoint = insertionPoint.Append(newMatchesList); } // ---- check max matches reached will be inserted here by completion pass // (not for iterated, but not needed in that case, too) // nesting level up insertionPoint = continuationPointAfterSubpatternsFound; return insertionPoint; }
/// <summary> /// Decides which check connectedness operations are needed for the given edge in both directions /// and inserts them into the search program /// returns new insertion point and continuation point /// for continuing buildup after the stuff nested within both directions iteration was built /// todo: if no direction iteration was needed, insertion point == continuation point ? /// </summary> private SearchProgramOperation decideOnAndInsertCheckConnectednessOfEdgeBothDirections( SearchProgramOperation insertionPoint, SearchPlanEdgeNode edge, bool edgeDeterminationContainsFirstNodeLoop, out SearchProgramOperation continuationPoint) { continuationPoint = null; // check whether source/target-nodes of the candidate edge // are the same as the already found nodes to which the edge must be incident if (!edgeDeterminationContainsFirstNodeLoop && currentEdgeConnectsToFirstIncidentNode(edge)) { // due to currentEdgeConnectsToFirstIncidentNode: at least on incident node available if (edge.PatternEdgeSource == edge.PatternEdgeTarget) { // reflexive edge without direction iteration as we don't want 2 matches SearchPlanNodeNode nodeRequiringFirstNodeLoop = edge.PatternEdgeSource != null ? edge.PatternEdgeSource : edge.PatternEdgeTarget; CheckCandidateForConnectedness checkConnectedness = new CheckCandidateForConnectedness( edge.PatternElement.Name, nodeRequiringFirstNodeLoop.PatternElement.Name, edge.PatternElement.Name, CheckCandidateForConnectednessType.Source); // might be Target as well insertionPoint = insertionPoint.Append(checkConnectedness); } else { BothDirectionsIteration directionsIteration = new BothDirectionsIteration(edge.PatternElement.Name); directionsIteration.NestedOperationsList = new SearchProgramList(directionsIteration); continuationPoint = insertionPoint.Append(directionsIteration); insertionPoint = directionsIteration.NestedOperationsList; SearchPlanNodeNode nodeRequiringFirstNodeLoop = edge.PatternEdgeSource != null ? edge.PatternEdgeSource : edge.PatternEdgeTarget; CheckCandidateForConnectedness checkConnectedness = new CheckCandidateForConnectedness( edge.PatternElement.Name, nodeRequiringFirstNodeLoop.PatternElement.Name, edge.PatternElement.Name, CheckCandidateForConnectednessType.SourceOrTarget); insertionPoint = insertionPoint.Append(checkConnectedness); } } if (currentEdgeConnectsToSecondIncidentNode(edge)) { // due to currentEdgeConnectsToSecondIncidentNode: both incident node available CheckCandidateForConnectedness checkConnectedness = new CheckCandidateForConnectedness( edge.PatternElement.Name, edge.PatternEdgeTarget.PatternElement.Name, edge.PatternElement.Name, edge.PatternEdgeSource.PatternElement.Name, CheckCandidateForConnectednessType.TheOther); insertionPoint = insertionPoint.Append(checkConnectedness); } return insertionPoint; }
/// <summary> /// Inserts code to check whether the subpatterns were found and code for case there were some /// at the given position, returns position after inserted operations /// </summary> private SearchProgramOperation insertCheckForSubpatternsFoundNegativeIndependent(SearchProgramOperation insertionPoint) { PatternGraph patternGraph = patternGraphWithNestingPatterns.Peek(); string negativeIndependentNamePrefix = NegativeIndependentNamePrefix(patternGraph); // check whether there were no subpattern matches found CheckPartialMatchForSubpatternsFound checkSubpatternsFound = new CheckPartialMatchForSubpatternsFound(negativeIndependentNamePrefix); SearchProgramOperation continuationPointAfterSubpatternsFound = insertionPoint.Append(checkSubpatternsFound); checkSubpatternsFound.CheckFailedOperations = new SearchProgramList(checkSubpatternsFound); insertionPoint = checkSubpatternsFound.CheckFailedOperations; if (isNegative) { // ---- check failed, some subpattern matches found, negative pattern and subpatterns were matched // build the negative pattern was matched operation NegativePatternMatched patternMatched = new NegativePatternMatched( NegativeIndependentPatternMatchedType.ContainingSubpatterns, negativeIndependentNamePrefix); insertionPoint = insertionPoint.Append(patternMatched); // ---- abort the matching process CheckContinueMatchingOfNegativeFailed abortMatching = new CheckContinueMatchingOfNegativeFailed(patternGraph.isIterationBreaking); insertionPoint = insertionPoint.Append(abortMatching); } else { // ---- check failed, some subpattern matches found, independent pattern and subpatterns were matched // build the independent pattern was matched operation IndependentPatternMatched patternMatched = new IndependentPatternMatched( NegativeIndependentPatternMatchedType.ContainingSubpatterns, negativeIndependentNamePrefix); insertionPoint = insertionPoint.Append(patternMatched); if (!isNestedInNegative) // no match object needed(/available) if independent is part of negative { // ---- fill the match object with the candidates // ---- which have passed all the checks for being a match insertionPoint = insertInlinedMatchObjectCreation(insertionPoint, patternGraph, MatchObjectType.Independent); insertionPoint = insertMatchObjectBuilding(insertionPoint, patternGraph, MatchObjectType.Independent, false); insertionPoint = insertMatchObjectBuilding(insertionPoint, patternGraph, MatchObjectType.Independent, true); // if an independent was inlined, we have to insert the local match into a set used for duplicate checking if(wasIndependentInlined(patternGraph, indexOfSchedule)) insertionPoint = insertFillForDuplicateMatchChecking(insertionPoint); } // ---- continue the matching process outside CheckContinueMatchingOfIndependentSucceeded continueMatching = new CheckContinueMatchingOfIndependentSucceeded(); insertionPoint = insertionPoint.Append(continueMatching); } // nesting level up insertionPoint = continuationPointAfterSubpatternsFound; return insertionPoint; }
/// <summary> /// move outwards from check operation until operation to continue at is found /// appending restore isomorphy for isomorphy written on the way /// and final jump to operation to continue at /// </summary> private void MoveOutwardsAppendingRemoveIsomorphyAndJump( CheckOperation checkOperation, string[] neededElementsForCheckOperation, SearchProgramOperation outermostOperation, SearchProgram topLevelSearchProgram) { // insertion point for candidate failed operations SearchProgramOperation insertionPoint = checkOperation.CheckFailedOperations; while (insertionPoint.Next != null) { insertionPoint = insertionPoint.Next; } // set outermost to iterated dummy iteration if iterated if (outermostOperation is SearchProgramOfIterated) { SearchProgramOperation cur = checkOperation; while (!(cur is ReturnPreventingDummyIteration)) { cur = cur.Previous; } outermostOperation = cur; } SearchProgramOperation continuationPoint = MoveOutwardsAppendingRemoveIsomorphy( checkOperation, ref insertionPoint, neededElementsForCheckOperation, outermostOperation, topLevelSearchProgram); // decide on type of continuing operation, then insert it // continue at top nesting level -> return SearchProgramOperation op = continuationPoint; while (!(op is SearchProgram)) { op = op.Previous; } SearchProgram searchProgramRoot = op as SearchProgram; if (continuationPoint == searchProgramRoot) { ContinueOperation continueByReturn = new ContinueOperation( ContinueOperationType.ByReturn, searchProgramRoot is SearchProgramOfAction || searchProgramRoot is SearchProgramOfActionParallelizationHead, searchProgramRoot is SearchProgramOfActionParallelizationBody ); insertionPoint.Append(continueByReturn); return; } // continue at directly enclosing nesting level -> continue op = checkOperation; do { op = op.Previous; } while (!op.IsSearchNestingOperation()); SearchProgramOperation directlyEnclosingOperation = op; if (continuationPoint == directlyEnclosingOperation // (check negative/independent is enclosing, but not a loop, thus continue wouldn't work) && !(directlyEnclosingOperation is CheckPartialMatchByNegative) && !(directlyEnclosingOperation is CheckPartialMatchByIndependent) // (check partial match for duplicate contains an internal loop in checking, thus continue wouldn't work) && !(checkOperation is CheckPartialMatchForDuplicate)) { ContinueOperation continueByContinue = new ContinueOperation(ContinueOperationType.ByContinue, directlyEnclosingOperation is GetCandidateByIterationParallel); insertionPoint.Append(continueByContinue); return; } // otherwise -> goto label string gotoLabelName; // if our continuation point is a candidate iteration // -> append label at the end of the loop body of the candidate iteration loop if (continuationPoint is GetCandidateByIteration) { GetCandidateByIteration candidateIteration = continuationPoint as GetCandidateByIteration; op = candidateIteration.NestedOperationsList; while (op.Next != null) { op = op.Next; } GotoLabel gotoLabel = new GotoLabel(); op.Append(gotoLabel); gotoLabelName = gotoLabel.LabelName; } // if our continuation point is a candidate iteration parallel // -> append label at the end of the loop body of the candidate iteration loop else if (continuationPoint is GetCandidateByIterationParallel) { GetCandidateByIterationParallel candidateIteration = continuationPoint as GetCandidateByIterationParallel; op = candidateIteration.NestedOperationsList; while(op.Next != null) { op = op.Next; } GotoLabel gotoLabel = new GotoLabel(); op.Append(gotoLabel); gotoLabelName = gotoLabel.LabelName; } // if our continuation point is a both directions iteration // -> append label at the end of the loop body of the both directions iteration loop else if (continuationPoint is BothDirectionsIteration) { BothDirectionsIteration bothDirections = continuationPoint as BothDirectionsIteration; op = bothDirections.NestedOperationsList; while (op.Next != null) { op = op.Next; } GotoLabel gotoLabel = new GotoLabel(); op.Append(gotoLabel); gotoLabelName = gotoLabel.LabelName; } // if our continuation point is an alternative // -> append label at the end of the alternative operations else if (continuationPoint is GetPartialMatchOfAlternative) { GetPartialMatchOfAlternative getAlternative = continuationPoint as GetPartialMatchOfAlternative; op = getAlternative.OperationsList; while (op.Next != null) { op = op.Next; } GotoLabel gotoLabel = new GotoLabel(); op.Append(gotoLabel); gotoLabelName = gotoLabel.LabelName; } // if our continuation point is the dummy loop of an iterated operation // -> we just jump to the label maxMatchesIterReached directly after the loop else if (continuationPoint is ReturnPreventingDummyIteration) { gotoLabelName = "maxMatchesIterReached"; } // otherwise our continuation point is a check negative/independent operation // -> insert label directly after the check negative/independent operation else { CheckPartialMatchByNegativeOrIndependent checkNegativeIndependent = continuationPoint as CheckPartialMatchByNegativeOrIndependent; GotoLabel gotoLabel = new GotoLabel(); checkNegativeIndependent.Insert(gotoLabel); gotoLabelName = gotoLabel.LabelName; } ContinueOperation continueByGoto = new ContinueOperation( ContinueOperationType.ByGoto, gotoLabelName); // ByGoto due to parameters insertionPoint.Append(continueByGoto); }
/// <summary> /// Inserts code to handle case top level pattern of action was found /// at the given position, returns position after inserted operations /// </summary> private SearchProgramOperation insertPatternFound(SearchProgramOperation insertionPoint) { PatternGraph patternGraph = patternGraphWithNestingPatterns.Peek(); // build the pattern was matched operation PositivePatternWithoutSubpatternsMatched patternMatched = new PositivePatternWithoutSubpatternsMatched(rulePatternClassName, patternGraph.name, parallelized && indexOfSchedule == 1); SearchProgramOperation continuationPoint = insertionPoint.Append(patternMatched); patternMatched.MatchBuildingOperations = new SearchProgramList(patternMatched); insertionPoint = patternMatched.MatchBuildingOperations; // ---- fill the match object with the candidates // ---- which have passed all the checks for being a match insertionPoint = insertInlinedMatchObjectCreation(insertionPoint, patternGraph, MatchObjectType.Normal); insertionPoint = insertMatchObjectBuilding(insertionPoint, patternGraph, MatchObjectType.Normal, false); insertionPoint = insertMatchObjectBuilding(insertionPoint, patternGraph, MatchObjectType.Normal, true); // if an independent was inlined, we have to insert the local match into a set used for duplicate checking if(wasIndependentInlined(patternGraph, indexOfSchedule)) insertionPoint = insertFillForDuplicateMatchChecking(insertionPoint); // ---- nesting level up insertionPoint = continuationPoint; // check whether to continue the matching process // or abort because the maximum desired number of maches was reached CheckContinueMatchingMaximumMatchesReached checkMaximumMatches = #if NO_ADJUST_LIST_HEADS new CheckContinueMatchingMaximumMatchesReached( CheckMaximumMatchesType.Action, false, parallelized && indexOfSchedule == 1, emitProfiling, actionName, firstLoopPassed); #else new CheckContinueMatchingMaximumMatchesReached( CheckMaximumMatchesType.Action, true, parallelized && indexOfSchedule == 1, emitProfiling, packagePrefixedActionName, firstLoopPassed); #endif insertionPoint = insertionPoint.Append(checkMaximumMatches); return insertionPoint; }
/// <summary> /// move outwards from starting point on until operation to continue at is found /// appending restore isomorphy at insertion point for isomorphy written on the way /// returns operation to continue at /// </summary> private SearchProgramOperation MoveOutwardsAppendingRemoveIsomorphy( SearchProgramOperation startingPoint, ref SearchProgramOperation insertionPoint, string[] neededElementsForCheckOperation, SearchProgramOperation outermostOperation, SearchProgram topLevelSearchProgram) { // currently focused operation on our way outwards SearchProgramOperation op = startingPoint; // move outwards until operation to continue at is found bool creationPointOfDominatingElementFound = false; bool iterationReached = false; do { op = op.Previous; // insert code to clean up isomorphy information written by candidate acceptance // in between the operation to continue and the check operation if (op is AcceptCandidate) { AcceptCandidate writeIsomorphy = op as AcceptCandidate; AbandonCandidate restoreIsomorphy = new AbandonCandidate( writeIsomorphy.PatternElementName, writeIsomorphy.NegativeIndependentNamePrefix, writeIsomorphy.IsNode, writeIsomorphy.NeverAboveMaxIsoSpace, writeIsomorphy.Parallel, writeIsomorphy.LockForAllThreads); insertionPoint = insertionPoint.Append(restoreIsomorphy); } // insert code to clean up isomorphy information written by global candidate acceptance // in between the operation to continue and the check operation if (op is AcceptCandidateGlobal) { AcceptCandidateGlobal writeIsomorphy = op as AcceptCandidateGlobal; AbandonCandidateGlobal removeIsomorphy = new AbandonCandidateGlobal( writeIsomorphy.PatternElementName, writeIsomorphy.NegativeIndependentNamePrefix, writeIsomorphy.IsNode, writeIsomorphy.NeverAboveMaxIsoSpace, writeIsomorphy.Parallel); insertionPoint = insertionPoint.Append(removeIsomorphy); } // insert code to clean up isomorphy information written by patternpath candidate acceptance // in between the operation to continue and the check operation if (op is AcceptCandidatePatternpath) { AcceptCandidatePatternpath writeIsomorphy = op as AcceptCandidatePatternpath; AbandonCandidatePatternpath removeIsomorphy = new AbandonCandidatePatternpath( writeIsomorphy.PatternElementName, writeIsomorphy.NegativeIndependentNamePrefix, writeIsomorphy.IsNode); insertionPoint = insertionPoint.Append(removeIsomorphy); } // insert code to remove iterated pattern acceptance if (op is AcceptIterated) { AcceptIterated acceptIterated = op as AcceptIterated; AbandonIterated abandonIterated = new AbandonIterated(); insertionPoint = insertionPoint.Append(abandonIterated); } // insert code to undo subpattern matching initialization if we leave the subpattern matching method if (op is InitializeSubpatternMatching) { InitializeSubpatternMatching initialize = op as InitializeSubpatternMatching; FinalizeSubpatternMatching finalize = new FinalizeSubpatternMatching(initialize.Type); insertionPoint = insertionPoint.Append(finalize); } // insert code to undo negative/independent matching initialization if we leave the negative/independent matching method if (op is InitializeNegativeIndependentMatching) { InitializeNegativeIndependentMatching initialize = op as InitializeNegativeIndependentMatching; FinalizeNegativeIndependentMatching finalize = new FinalizeNegativeIndependentMatching(initialize.NeverAboveMaxIsoSpace, initialize.Parallel); insertionPoint = insertionPoint.Append(finalize); } // determine operation to continue at // found by looking at the graph elements // the check operation depends on / is dominated by // its the first element iteration on our way outwards the search program // after or at the point of a get element operation // of some dominating element the check depends on // (or the outermost operation if no iteration is found until it is reached) if (op is GetCandidate || op is BothDirectionsIteration) { if (creationPointOfDominatingElementFound == false) { if (neededElementsForCheckOperation != null) { foreach (string dominating in neededElementsForCheckOperation) { GetCandidate getCandidate = op as GetCandidate; BothDirectionsIteration bothDirections = op as BothDirectionsIteration; if (getCandidate!=null && getCandidate.PatternElementName == dominating || bothDirections!=null && bothDirections.PatternElementName == dominating) { creationPointOfDominatingElementFound = true; iterationReached = false; break; } } } else { // needed elements == null means everything fits, // take first element iteration on our way outwards the search program // (or the outermost operation if no iteration is found until it is reached) creationPointOfDominatingElementFound = true; iterationReached = false; } } if (op is GetCandidateByIteration || op is GetCandidateByIterationParallel || op is BothDirectionsIteration) { iterationReached = true; } } } while (!(creationPointOfDominatingElementFound && iterationReached) && op != outermostOperation); return op; }
/// <summary> /// Inserts code to handle case negative/independent pattern was found /// at the given position, returns position after inserted operations /// </summary> private SearchProgramOperation insertPatternFoundNegativeIndependent(SearchProgramOperation insertionPoint) { PatternGraph patternGraph = patternGraphWithNestingPatterns.Peek(); string negativeIndependentNamePrefix = NegativeIndependentNamePrefix(patternGraph); if (isNegative) { // build the negative pattern was matched operation NegativePatternMatched patternMatched = new NegativePatternMatched( NegativeIndependentPatternMatchedType.WithoutSubpatterns, negativeIndependentNamePrefix); insertionPoint = insertionPoint.Append(patternMatched); // abort the matching process CheckContinueMatchingOfNegativeFailed abortMatching = new CheckContinueMatchingOfNegativeFailed(patternGraph.isIterationBreaking); insertionPoint = insertionPoint.Append(abortMatching); } else { // build the independent pattern was matched operation IndependentPatternMatched patternMatched = new IndependentPatternMatched( NegativeIndependentPatternMatchedType.WithoutSubpatterns, negativeIndependentNamePrefix); insertionPoint = insertionPoint.Append(patternMatched); if (!isNestedInNegative) // no match object needed(/available) if independent is part of negative { // fill the match object with the candidates // which have passed all the checks for being a match insertionPoint = insertInlinedMatchObjectCreation(insertionPoint, patternGraph, MatchObjectType.Independent); insertionPoint = insertMatchObjectBuilding(insertionPoint, patternGraph, MatchObjectType.Independent, false); insertionPoint = insertMatchObjectBuilding(insertionPoint, patternGraph, MatchObjectType.Independent, true); // if an independent was inlined, we have to insert the local match into a set used for duplicate checking if(wasIndependentInlined(patternGraph, indexOfSchedule)) insertionPoint = insertFillForDuplicateMatchChecking(insertionPoint); } // continue the matching process outside CheckContinueMatchingOfIndependentSucceeded continueMatching = new CheckContinueMatchingOfIndependentSucceeded(); insertionPoint = insertionPoint.Append(continueMatching); } return insertionPoint; }
/// <summary> /// Builds search program from scheduled search plan at given index in pattern graph of the action rule pattern /// </summary> public static SearchProgram BuildSearchProgram( IGraphModel model, LGSPRulePattern rulePattern, int index, string nameOfSearchProgram, bool parallelized, bool emitProfiling) { PatternGraph patternGraph = rulePattern.patternGraph; String rulePatternClassName = NamesOfEntities.RulePatternClassName(rulePattern.name, rulePattern.PatternGraph.Package, false); // filter out parameters which are implemented by lookup due to maybe null unfolding // and suffix matcher method name by missing parameters which get computed by lookup here string[] parameterTypes; string[] parameterNames; String name; GetFilteredParametersAndSuffixedMatcherName( rulePattern, patternGraph, parallelized ? 0 : index, out parameterTypes, out parameterNames, out name); SearchProgramBodyBuilder builder = new SearchProgramBodyBuilder( SearchProgramType.Action, model, rulePatternClassName, rulePattern.patternGraph.Package != null ? rulePattern.patternGraph.Package + "::" + rulePattern.name : rulePattern.name, parameterNames, parameterTypes, patternGraph, emitProfiling, parallelized, index ); // this is the all presets available method (index 0) and there are presets which may be null? // -> collect data for missing preset calls List <String[]> paramTypesList = null; List <String[]> paramNamesList = null; List <String> suffixedMatcherNameList = null; if (patternGraph.schedules.Length > 1 && index == 0) { paramTypesList = new List <String[]>(); paramNamesList = new List <String[]>(); suffixedMatcherNameList = new List <String>(); for (int i = 0; i < patternGraph.schedules.Length; ++i) { String[] paramTypes; String[] paramNames; String suffixedMatcherName; GetFilteredParametersAndSuffixedMatcherName( rulePattern, patternGraph, i, out paramTypes, out paramNames, out suffixedMatcherName); paramTypesList.Add(paramTypes); paramNamesList.Add(paramNames); suffixedMatcherNameList.Add(suffixedMatcherName); } } // build outermost search program operation, create the list anchor starting its program bool containsSubpatterns = patternGraph.embeddedGraphsPlusInlined.Length > 0 || patternGraph.iteratedsPlusInlined.Length > 0 || patternGraph.alternativesPlusInlined.Length > 0; SearchProgram searchProgram; if (parallelized) { if (index == 1) { List <String> matchingPatternClassTypeNames = new List <String>(); List <Dictionary <PatternGraph, bool> > nestedIndependents = new List <Dictionary <PatternGraph, bool> >(); ExtractNestedIndependents(matchingPatternClassTypeNames, nestedIndependents, rulePattern, patternGraph); searchProgram = new SearchProgramOfActionParallelizationBody( rulePatternClassName, patternGraph.name, name + "_parallelized_body", rulePattern.patternGraph.patternGraphsOnPathToEnclosedPatternpath, containsSubpatterns, builder.wasIndependentInlined(patternGraph, index), matchingPatternClassTypeNames, nestedIndependents, emitProfiling, patternGraph.PackagePrefixedName); } else // index == 0 { searchProgram = new SearchProgramOfActionParallelizationHead( rulePatternClassName, patternGraph.name, parameterTypes, parameterNames, name + "_parallelized", emitProfiling, patternGraph.PackagePrefixedName); } } else { List <String> matchingPatternClassTypeNames = new List <String>(); List <Dictionary <PatternGraph, bool> > nestedIndependents = new List <Dictionary <PatternGraph, bool> >(); ExtractNestedIndependents(matchingPatternClassTypeNames, nestedIndependents, rulePattern, patternGraph); searchProgram = new SearchProgramOfAction( rulePatternClassName, patternGraph.name, parameterTypes, parameterNames, name, rulePattern.patternGraph.patternGraphsOnPathToEnclosedPatternpath, containsSubpatterns, builder.wasIndependentInlined(patternGraph, 0), matchingPatternClassTypeNames, nestedIndependents, emitProfiling, patternGraph.PackagePrefixedName, patternGraph.maybeNullElementNames, suffixedMatcherNameList, paramNamesList); } searchProgram.OperationsList = new SearchProgramList(searchProgram); SearchProgramOperation insertionPoint = searchProgram.OperationsList; if (!parallelized || index == 0) { insertionPoint = insertVariableDeclarations(insertionPoint, patternGraph); } // start building with first operation in scheduled search plan insertionPoint = builder.BuildScheduledSearchPlanOperationIntoSearchProgram( 0, insertionPoint); return(searchProgram); }
/// <summary> /// Inserts code to check whether iteration came to an end (pattern not found (again)) /// and code to handle that case /// </summary> private SearchProgramOperation insertEndOfIterationHandling(SearchProgramOperation insertionPoint) { Debug.Assert(NegativeIndependentNamePrefix(patternGraphWithNestingPatterns.Peek()) == ""); PatternGraph patternGraph = patternGraphWithNestingPatterns.Peek(); // check whether the pattern was not found / the null match was found // if yes the iteration came to an end, handle that case CheckContinueMatchingIteratedPatternNonNullMatchFound iteratedPatternFound = new CheckContinueMatchingIteratedPatternNonNullMatchFound(patternGraph.isIterationBreaking); SearchProgramOperation continuationPoint = insertionPoint.Append(iteratedPatternFound); iteratedPatternFound.CheckFailedOperations = new SearchProgramList(iteratedPatternFound); insertionPoint = iteratedPatternFound.CheckFailedOperations; // ---- initialize task/result-pushdown handling in subpattern matcher for end of iteration InitializeSubpatternMatching initialize = new InitializeSubpatternMatching(InitializeFinalizeSubpatternMatchingType.EndOfIteration); insertionPoint = insertionPoint.Append(initialize); // ---- ---- iteration pattern may be the last to be matched - handle that case CheckContinueMatchingTasksLeft tasksLeft = new CheckContinueMatchingTasksLeft(); SearchProgramOperation continuationPointAfterTasksLeft = insertionPoint.Append(tasksLeft); tasksLeft.CheckFailedOperations = new SearchProgramList(tasksLeft); insertionPoint = tasksLeft.CheckFailedOperations; // ---- ---- check failed, no tasks left, leaf subpattern was matched string inlinedPatternClassName = rulePatternClassName; string pathPrefixInInlinedPatternClass = patternGraph.pathPrefix; string unprefixedNameInInlinedPatternClass = patternGraph.name; if(patternGraph.originalPatternGraph != null) { inlinedPatternClassName = patternGraph.originalSubpatternEmbedding.matchingPatternOfEmbeddedGraph.GetType().Name; pathPrefixInInlinedPatternClass = patternGraph.originalPatternGraph.pathPrefix; unprefixedNameInInlinedPatternClass = patternGraph.originalPatternGraph.name; } LeafSubpatternMatched leafMatched = new LeafSubpatternMatched( inlinedPatternClassName, pathPrefixInInlinedPatternClass + unprefixedNameInInlinedPatternClass, true); insertionPoint = insertionPoint.Append(leafMatched); leafMatched.MatchBuildingOperations = new SearchProgramList(leafMatched); // empty, no match object // ---- ---- finalize task/result-pushdown handling in subpattern matcher for end of iteration FinalizeSubpatternMatching finalize = new FinalizeSubpatternMatching(InitializeFinalizeSubpatternMatchingType.EndOfIteration); insertionPoint = insertionPoint.Append(finalize); FinalizeSubpatternMatching finalizeIteration = new FinalizeSubpatternMatching(InitializeFinalizeSubpatternMatchingType.Iteration); insertionPoint = insertionPoint.Append(finalizeIteration); ContinueOperation leave = new ContinueOperation(ContinueOperationType.ByReturn, false, parallelized && indexOfSchedule == 1); insertionPoint = insertionPoint.Append(leave); // ---- nesting level up insertionPoint = continuationPointAfterTasksLeft; // ---- we execute the open subpattern matching tasks MatchSubpatterns matchSubpatterns = new MatchSubpatterns("", parallelized); insertionPoint = insertionPoint.Append(matchSubpatterns); // ---- check whether the open subpattern matching task succeeded, with null match building insertionPoint = insertCheckForSubpatternsFound(insertionPoint, true); // ---- finalize task/result-pushdown handling in subpattern matcher for end of iteration finalize = new FinalizeSubpatternMatching(InitializeFinalizeSubpatternMatchingType.EndOfIteration); insertionPoint = insertionPoint.Append(finalize); finalizeIteration = new FinalizeSubpatternMatching(InitializeFinalizeSubpatternMatchingType.Iteration); insertionPoint = insertionPoint.Append(finalizeIteration); leave = new ContinueOperation(ContinueOperationType.ByReturn, false, parallelized && indexOfSchedule == 1); insertionPoint = insertionPoint.Append(leave); // ---- nesting level up insertionPoint = continuationPoint; return insertionPoint; }
/// <summary> /// Builds search program for iterated from scheduled search plan of iterated pattern graph /// </summary> public static SearchProgram BuildSearchProgram( IGraphModel model, LGSPMatchingPattern matchingPattern, PatternGraph iter, bool parallelized, bool emitProfiling) { String rulePatternClassName = NamesOfEntities.RulePatternClassName(matchingPattern.name, matchingPattern.PatternGraph.Package, !(matchingPattern is LGSPRulePattern)); SearchProgramBodyBuilder builder = new SearchProgramBodyBuilder( SearchProgramType.Iterated, model, rulePatternClassName, null, null, null, iter, emitProfiling, parallelized, 0 ); List <String> matchingPatternClassTypeNames = new List <String>(); List <Dictionary <PatternGraph, bool> > nestedIndependents = new List <Dictionary <PatternGraph, bool> >(); ExtractNestedIndependents(matchingPatternClassTypeNames, nestedIndependents, matchingPattern, iter); // build outermost search program operation, create the list anchor starting its program SearchProgram searchProgram = new SearchProgramOfIterated( rulePatternClassName, matchingPattern.patternGraph.Name, iter.Name, iter.pathPrefix, matchingPattern.patternGraph.patternGraphsOnPathToEnclosedPatternpath, "myMatch", builder.wasIndependentInlined(iter, 0), matchingPatternClassTypeNames, nestedIndependents, parallelized); searchProgram.OperationsList = new SearchProgramList(searchProgram); SearchProgramOperation insertionPoint = searchProgram.OperationsList; insertionPoint = insertVariableDeclarations(insertionPoint, iter); // initialize task/result-pushdown handling in subpattern matcher for iteration InitializeSubpatternMatching initialize = new InitializeSubpatternMatching(InitializeFinalizeSubpatternMatchingType.Iteration); insertionPoint = insertionPoint.Append(initialize); IteratedMatchingDummyLoop iteratedMatchingDummyLoop = new IteratedMatchingDummyLoop(); SearchProgramOperation continuationPointAfterIteratedMatching = insertionPoint.Append(iteratedMatchingDummyLoop); iteratedMatchingDummyLoop.NestedOperationsList = new SearchProgramList(iteratedMatchingDummyLoop); insertionPoint = iteratedMatchingDummyLoop.NestedOperationsList; // start building with first operation in scheduled search plan insertionPoint = builder.BuildScheduledSearchPlanOperationIntoSearchProgram( 0, insertionPoint); insertionPoint = continuationPointAfterIteratedMatching; // check whether iteration came to an end (pattern not found (again)) and handle it insertionPoint = builder.insertEndOfIterationHandling(insertionPoint); // finalize task/result-pushdown handling in subpattern matcher for iteration FinalizeSubpatternMatching finalize = new FinalizeSubpatternMatching(InitializeFinalizeSubpatternMatchingType.Iteration); insertionPoint = insertionPoint.Append(finalize); return(searchProgram); }
/// <summary> /// Decides which get type operation to use and inserts it /// returns new insertion point and continuation point /// for continuing buildup after the stuff nested within type iteration was built /// if type drawing was sufficient, insertion point == continuation point /// </summary> private SearchProgramOperation decideOnAndInsertGetType( SearchProgramOperation insertionPoint, SearchPlanNode target, out SearchProgramOperation continuationPoint) { bool isNode = target.NodeType == PlanNodeType.Node; ITypeModel typeModel = isNode ? (ITypeModel)model.NodeModel : (ITypeModel)model.EdgeModel; if (target.PatternElement.AllowedTypes == null) { // the pattern element type and all subtypes are allowed if (typeModel.Types[target.PatternElement.TypeID].HasSubTypes) { // more than the type itself -> we've to iterate them GetTypeByIteration typeIteration = new GetTypeByIteration( GetTypeByIterationType.AllCompatible, target.PatternElement.Name, TypesHelper.PrefixedTypeFromType(typeModel.TypeTypes[target.PatternElement.TypeID]), isNode); continuationPoint = insertionPoint.Append(typeIteration); typeIteration.NestedOperationsList = new SearchProgramList(typeIteration); insertionPoint = typeIteration.NestedOperationsList; } else { // only the type itself -> no iteration needed GetTypeByDrawing typeDrawing = new GetTypeByDrawing( target.PatternElement.Name, target.PatternElement.TypeID.ToString(), isNode); insertionPoint = insertionPoint.Append(typeDrawing); continuationPoint = insertionPoint; } } else //(target.PatternElement.AllowedTypes != null) { // the allowed types are given explicitely if (target.PatternElement.AllowedTypes.Length != 1) { // more than one allowed type -> we've to iterate them GetTypeByIteration typeIteration = new GetTypeByIteration( GetTypeByIterationType.ExplicitelyGiven, target.PatternElement.Name, rulePatternClassName, isNode); continuationPoint = insertionPoint.Append(typeIteration); typeIteration.NestedOperationsList = new SearchProgramList(typeIteration); insertionPoint = typeIteration.NestedOperationsList; } else { // only one allowed type -> no iteration needed GetTypeByDrawing typeDrawing = new GetTypeByDrawing( target.PatternElement.Name, target.PatternElement.AllowedTypes[0].TypeID.ToString(), isNode); insertionPoint = insertionPoint.Append(typeDrawing); continuationPoint = insertionPoint; } } return insertionPoint; }
/// <summary> /// "listentrick": append search program operations to adjust list heads /// i.e. set list entry point to element after last found, /// so that next searching starts there - performance optimization /// (leave graph in the state of our last visit (searching it)) /// </summary> private static void MoveOutwardsAppendingListHeadAdjustment( CheckContinueMatchingMaximumMatchesReached checkMaximumMatches, bool inParallelizedBody) { // todo: avoid adjusting list heads twice for lookups of same type // insertion point for candidate failed operations SearchProgramOperation insertionPoint = checkMaximumMatches.CheckFailedOperations; SearchProgramOperation op = checkMaximumMatches; do { if (op is GetCandidateByIteration) { GetCandidateByIteration candidateByIteration = op as GetCandidateByIteration; if (candidateByIteration.Type == GetCandidateByIterationType.GraphElements) { AdjustListHeads adjustElements = new AdjustListHeads( AdjustListHeadsTypes.GraphElements, candidateByIteration.PatternElementName, candidateByIteration.IsNode, inParallelizedBody); insertionPoint = insertionPoint.Append(adjustElements); } else if (candidateByIteration.Type == GetCandidateByIterationType.IncidentEdges) { AdjustListHeads adjustIncident = new AdjustListHeads( AdjustListHeadsTypes.IncidentEdges, candidateByIteration.PatternElementName, candidateByIteration.StartingPointNodeName, candidateByIteration.EdgeType, inParallelizedBody); insertionPoint = insertionPoint.Append(adjustIncident); } } else if (op is GetCandidateByIterationParallel) { GetCandidateByIterationParallel candidateByIteration = op as GetCandidateByIterationParallel; if (candidateByIteration.Type == GetCandidateByIterationType.GraphElements) { AdjustListHeads adjustElements = new AdjustListHeads( AdjustListHeadsTypes.GraphElements, candidateByIteration.PatternElementName, candidateByIteration.IsNode, inParallelizedBody); insertionPoint = insertionPoint.Append(adjustElements); } else if (candidateByIteration.Type == GetCandidateByIterationType.IncidentEdges) { AdjustListHeads adjustIncident = new AdjustListHeads( AdjustListHeadsTypes.IncidentEdges, candidateByIteration.PatternElementName, candidateByIteration.StartingPointNodeName, candidateByIteration.EdgeType, inParallelizedBody); insertionPoint = insertionPoint.Append(adjustIncident); } } op = op.Previous; }while(op != null); }
/// <summary> /// Decides which check type operation to build and inserts it into search program /// </summary> private SearchProgramOperation decideOnAndInsertCheckType( SearchProgramOperation insertionPoint, SearchPlanNode target) { bool isNode = target.NodeType == PlanNodeType.Node; ITypeModel typeModel = isNode ? (ITypeModel)model.NodeModel : (ITypeModel)model.EdgeModel; if (target.PatternElement.IsAllowedType != null) { // the allowed types are given by an array for checking against them Debug.Assert(target.PatternElement.AllowedTypes != null); if (target.PatternElement.AllowedTypes.Length <= MAXIMUM_NUMBER_OF_TYPES_TO_CHECK_BY_TYPE_ID) { string[] typeIDs = new string[target.PatternElement.AllowedTypes.Length]; for (int i = 0; i < target.PatternElement.AllowedTypes.Length; ++i) { typeIDs[i] = target.PatternElement.AllowedTypes[i].TypeID.ToString(); } CheckCandidateForType checkType = new CheckCandidateForType( CheckCandidateForTypeType.ByTypeID, target.PatternElement.Name, typeIDs, isNode); insertionPoint = insertionPoint.Append(checkType); } else { string inlinedPatternClassName = null; string inlinedPatternElementName = null; if(target.PatternElement.originalElement != null) { inlinedPatternClassName = target.PatternElement.originalSubpatternEmbedding.matchingPatternOfEmbeddedGraph.GetType().Name; inlinedPatternElementName = target.PatternElement.originalElement.name; } CheckCandidateForType checkType = new CheckCandidateForType( CheckCandidateForTypeType.ByIsAllowedType, target.PatternElement.Name, inlinedPatternClassName ?? rulePatternClassName, inlinedPatternElementName ?? target.PatternElement.Name, isNode); insertionPoint = insertionPoint.Append(checkType); } return insertionPoint; } if (target.PatternElement.AllowedTypes == null) { // the pattern element type and all subtypes are allowed GrGenType targetType = typeModel.Types[target.PatternElement.TypeID]; if (targetType == typeModel.RootType) { // every type matches the root type == element type -> no check needed return insertionPoint; } if (targetType.subOrSameGrGenTypes.Length <= MAXIMUM_NUMBER_OF_TYPES_TO_CHECK_BY_TYPE_ID) { // the target type has no sub types, it must be exactly this type string[] typeIDs = new string[targetType.subOrSameGrGenTypes.Length]; for (int i = 0; i < targetType.subOrSameGrGenTypes.Length; ++i) { typeIDs[i] = targetType.subOrSameGrGenTypes[i].TypeID.ToString(); } CheckCandidateForType checkType = new CheckCandidateForType( CheckCandidateForTypeType.ByTypeID, target.PatternElement.Name, typeIDs, isNode); insertionPoint = insertionPoint.Append(checkType); } else { CheckCandidateForType checkType = new CheckCandidateForType( CheckCandidateForTypeType.ByIsMyType, target.PatternElement.Name, TypesHelper.PrefixedTypeFromType(typeModel.TypeTypes[target.PatternElement.TypeID]), isNode); insertionPoint = insertionPoint.Append(checkType); } return insertionPoint; } // the allowed types are given by allowed types array // if there are multiple ones, is allowed types must have been not null before Debug.Assert(target.PatternElement.AllowedTypes.Length > 1, "More than one allowed type"); if (target.PatternElement.AllowedTypes.Length == 0) { // no type allowed CheckCandidateFailed checkFailed = new CheckCandidateFailed(); insertionPoint = insertionPoint.Append(checkFailed); } else // (target.PatternElement.AllowedTypes.Length == 1) { // only one type allowed string[] typeIDs = new string[1]; typeIDs[0] = target.PatternElement.AllowedTypes[0].TypeID.ToString(); CheckCandidateForType checkType = new CheckCandidateForType( CheckCandidateForTypeType.ByTypeID, target.PatternElement.Name, typeIDs, isNode); insertionPoint = insertionPoint.Append(checkType); } return insertionPoint; }
/////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Completes check operations in search program from given currentOperation on /// (taking borderlines set by enclosing search program and check negative into account) /// Completion: /// - determine continuation point /// - insert remove isomorphy opertions needed for continuing there /// - insert continuing operation itself /// </summary> private static void CompleteCheckOperations( SearchProgramOperation currentOperation, SearchProgramOperation enclosingSearchProgram, // might be a negative/independent in case these are nested AlternativeCaseMatching enclosingAlternativeCase, CheckPartialMatchByNegativeOrIndependent enclosingCheckNegativeOrIndependent, SearchProgram topLevelSearchProgram) { // mainly dispatching and iteration method, traverses search program // real completion done in MoveOutwardsAppendingRemoveIsomorphyAndJump // outermost operation for that function is computed here, regarding negative patterns // program nesting structure: search program - [alternative] - [negative|independent]* // complete check operations by inserting failure code // find them in depth first search of search program while (currentOperation != null) { ////////////////////////////////////////////////////////// if (currentOperation is CheckCandidate) ////////////////////////////////////////////////////////// { CheckCandidate checkCandidate = (CheckCandidate)currentOperation; checkCandidate.CheckFailedOperations = new SearchProgramList(checkCandidate); string[] neededElementsForCheckOperation = new string[1]; neededElementsForCheckOperation[0] = checkCandidate.PatternElementName; MoveOutwardsAppendingRemoveIsomorphyAndJump( checkCandidate, neededElementsForCheckOperation, enclosingCheckNegativeOrIndependent ?? (enclosingAlternativeCase ?? enclosingSearchProgram), topLevelSearchProgram); } ////////////////////////////////////////////////////////// else if (currentOperation is CheckPartialMatch) ////////////////////////////////////////////////////////// { if (currentOperation is CheckPartialMatchByCondition) { CheckPartialMatchByCondition checkCondition = (CheckPartialMatchByCondition)currentOperation; checkCondition.CheckFailedOperations = new SearchProgramList(checkCondition); MoveOutwardsAppendingRemoveIsomorphyAndJump( checkCondition, checkCondition.NeededElements, enclosingCheckNegativeOrIndependent ?? (enclosingAlternativeCase ?? enclosingSearchProgram), topLevelSearchProgram); } else if (currentOperation is CheckPartialMatchForDuplicate) { CheckPartialMatchForDuplicate checkDuplicateMatch = (CheckPartialMatchForDuplicate)currentOperation; checkDuplicateMatch.CheckFailedOperations = new SearchProgramList(checkDuplicateMatch); MoveOutwardsAppendingRemoveIsomorphyAndJump( checkDuplicateMatch, checkDuplicateMatch.NeededElements, enclosingCheckNegativeOrIndependent ?? (enclosingAlternativeCase ?? enclosingSearchProgram), topLevelSearchProgram); } else if (currentOperation is CheckPartialMatchByNegativeOrIndependent) { CheckPartialMatchByNegativeOrIndependent checkNegativeOrIndependent = (CheckPartialMatchByNegativeOrIndependent)currentOperation; // ByNegative/ByIndependent is handled in CheckContinueMatchingFailed // of the negative/independent case - enter negative/independent case CompleteCheckOperations( checkNegativeOrIndependent.NestedOperationsList, enclosingCheckNegativeOrIndependent ?? enclosingSearchProgram, enclosingCheckNegativeOrIndependent != null ? null : enclosingAlternativeCase, checkNegativeOrIndependent, topLevelSearchProgram); } else if (currentOperation is CheckPartialMatchForSubpatternsFound) { CheckPartialMatchForSubpatternsFound checkSubpatternsFound = (CheckPartialMatchForSubpatternsFound)currentOperation; if (enclosingCheckNegativeOrIndependent == null) { // determine insertion point within check failed operations // to append the nested check maximum matches SearchProgramOperation insertionPoint = checkSubpatternsFound.CheckFailedOperations; while (insertionPoint.Next != null) { insertionPoint = insertionPoint.Next; } // append nested check maximum matches CheckMaximumMatchesType checkMaxMatchesType = CheckMaximumMatchesType.Action; if (enclosingSearchProgram is SearchProgramOfSubpattern || enclosingSearchProgram is SearchProgramOfAlternative) { checkMaxMatchesType = CheckMaximumMatchesType.Subpattern; } else if (enclosingSearchProgram is SearchProgramOfIterated) { checkMaxMatchesType = CheckMaximumMatchesType.Iterated; } CheckContinueMatchingMaximumMatchesReached checkMaximumMatches = new CheckContinueMatchingMaximumMatchesReached(checkMaxMatchesType, false, enclosingSearchProgram is SearchProgramOfActionParallelizationBody); insertionPoint.Append(checkMaximumMatches); MoveOutwardsAppendingRemoveIsomorphyAndJump( checkSubpatternsFound, null, enclosingCheckNegativeOrIndependent ?? (enclosingAlternativeCase ?? enclosingSearchProgram), topLevelSearchProgram); } // check subpatterns found has a further check maximum matches // or check continue matching of negative failed nested within check failed code // give it its special bit of attention here CompleteCheckOperations( checkSubpatternsFound.CheckFailedOperations, enclosingSearchProgram, enclosingAlternativeCase, enclosingCheckNegativeOrIndependent, topLevelSearchProgram); } else { Debug.Assert(false, "unknown check partial match operation"); } } ////////////////////////////////////////////////////////// else if (currentOperation is CheckContinueMatching) ////////////////////////////////////////////////////////// { if (currentOperation is CheckContinueMatchingMaximumMatchesReached) { CheckContinueMatchingMaximumMatchesReached checkMaximumMatches = (CheckContinueMatchingMaximumMatchesReached)currentOperation; checkMaximumMatches.CheckFailedOperations = new SearchProgramList(checkMaximumMatches); if (checkMaximumMatches.ListHeadAdjustment) { MoveOutwardsAppendingListHeadAdjustment(checkMaximumMatches, checkMaximumMatches.InParallelizedBody); } string[] neededElementsForCheckOperation = new string[0]; MoveOutwardsAppendingRemoveIsomorphyAndJump( checkMaximumMatches, neededElementsForCheckOperation, enclosingSearchProgram, topLevelSearchProgram); } else if (currentOperation is CheckContinueMatchingOfNegativeFailed) { CheckContinueMatchingOfNegativeFailed checkFailed = (CheckContinueMatchingOfNegativeFailed)currentOperation; checkFailed.CheckFailedOperations = new SearchProgramList(checkFailed); if (checkFailed.IsIterationBreaking) { string[] neededElementsForCheckOperation = new string[0]; MoveOutwardsAppendingRemoveIsomorphyAndJump( checkFailed, neededElementsForCheckOperation, enclosingSearchProgram, topLevelSearchProgram); } else { MoveOutwardsAppendingRemoveIsomorphyAndJump( checkFailed, enclosingCheckNegativeOrIndependent.NeededElements, enclosingAlternativeCase ?? enclosingSearchProgram, topLevelSearchProgram); } } else if (currentOperation is CheckContinueMatchingOfIndependentSucceeded) { CheckContinueMatchingOfIndependentSucceeded checkSucceeded = (CheckContinueMatchingOfIndependentSucceeded)currentOperation; checkSucceeded.CheckFailedOperations = // yep, rotten wording new SearchProgramList(checkSucceeded); MoveRightAfterCorrespondingIndependentFailedAppendingRemoveIsomorphyAndJump( checkSucceeded, (CheckPartialMatchByIndependent)enclosingCheckNegativeOrIndependent, topLevelSearchProgram); } else if (currentOperation is CheckContinueMatchingOfIndependentFailed) { CheckContinueMatchingOfIndependentFailed checkFailed = (CheckContinueMatchingOfIndependentFailed)currentOperation; checkFailed.CheckFailedOperations = new SearchProgramList(checkFailed); if (checkFailed.IsIterationBreaking) { string[] neededElementsForCheckOperation = new string[0]; MoveOutwardsAppendingRemoveIsomorphyAndJump( checkFailed, neededElementsForCheckOperation, enclosingSearchProgram, topLevelSearchProgram); } else { MoveOutwardsAppendingRemoveIsomorphyAndJump( checkFailed, checkFailed.CheckIndependent.NeededElements, enclosingAlternativeCase ?? enclosingSearchProgram, topLevelSearchProgram); } } else if (currentOperation is CheckContinueMatchingTasksLeft) { CheckContinueMatchingTasksLeft tasksLeft = (CheckContinueMatchingTasksLeft)currentOperation; // determine insertion point within check failed operations // to append the nested check maximum matches SearchProgramOperation insertionPoint = tasksLeft.CheckFailedOperations; while (insertionPoint.Next != null) { insertionPoint = insertionPoint.Next; } // append nested check maximum matches CheckContinueMatchingMaximumMatchesReached checkMaximumMatches = new CheckContinueMatchingMaximumMatchesReached( enclosingSearchProgram is SearchProgramOfIterated ? CheckMaximumMatchesType.Iterated : CheckMaximumMatchesType.Subpattern, false, topLevelSearchProgram is SearchProgramOfActionParallelizationBody); insertionPoint.Append(checkMaximumMatches); MoveOutwardsAppendingRemoveIsomorphyAndJump( tasksLeft, null, enclosingCheckNegativeOrIndependent ?? (enclosingAlternativeCase ?? enclosingSearchProgram), topLevelSearchProgram); // check tasks left has a further check maximum matches nested within check failed code // give it its special bit of attention here CompleteCheckOperations( tasksLeft.CheckFailedOperations, enclosingSearchProgram, enclosingAlternativeCase, enclosingCheckNegativeOrIndependent, topLevelSearchProgram); } else if (currentOperation is CheckContinueMatchingIteratedPatternNonNullMatchFound) { // was built completely, nothing to complete } else { Debug.Assert(false, "unknown check abort matching operation"); } } ////////////////////////////////////////////////////////// else if (currentOperation is AlternativeCaseMatching) ////////////////////////////////////////////////////////// { // depth first CompleteCheckOperations( currentOperation.GetNestedSearchOperationsList(), enclosingSearchProgram, (AlternativeCaseMatching)currentOperation, null, topLevelSearchProgram); } ////////////////////////////////////////////////////////// else if (currentOperation.IsSearchNestingOperation()) ////////////////////////////////////////////////////////// { // depth first CompleteCheckOperations( currentOperation.GetNestedSearchOperationsList(), enclosingSearchProgram, enclosingAlternativeCase, enclosingCheckNegativeOrIndependent, topLevelSearchProgram); } // breadth currentOperation = currentOperation.Next; } }
/// <summary> /// Decides which check connectedness operations are needed for the given node just determined by lookup /// and inserts them into the search program /// returns new insertion point and continuation point /// for continuing buildup after the stuff nested within both directions iteration was built /// if no direction iteration was needed, insertion point == continuation point /// </summary> private SearchProgramOperation decideOnAndInsertCheckConnectednessOfNodeFromLookupOrPickOrMap( SearchProgramOperation insertionPoint, SearchPlanNodeNode node, out SearchProgramOperation continuationPoint) { continuationPoint = null; SearchProgramOperation localContinuationPoint; // check for edges required by the pattern to be incident to the given node foreach (SearchPlanEdgeNode edge in node.OutgoingPatternEdges) { if (((PatternEdge)edge.PatternElement).fixedDirection || edge.PatternEdgeSource == edge.PatternEdgeTarget) { insertionPoint = decideOnAndInsertCheckConnectednessOfNodeFixedDirection( insertionPoint, node, edge, CheckCandidateForConnectednessType.Source); } else { insertionPoint = decideOnAndInsertCheckConnectednessOfNodeBothDirections( insertionPoint, node, edge, out localContinuationPoint); if (localContinuationPoint != insertionPoint && continuationPoint == null) continuationPoint = localContinuationPoint; } } foreach (SearchPlanEdgeNode edge in node.IncomingPatternEdges) { if (((PatternEdge)edge.PatternElement).fixedDirection || edge.PatternEdgeSource == edge.PatternEdgeTarget) { insertionPoint = decideOnAndInsertCheckConnectednessOfNodeFixedDirection( insertionPoint, node, edge, CheckCandidateForConnectednessType.Target); } else { insertionPoint = decideOnAndInsertCheckConnectednessOfNodeBothDirections( insertionPoint, node, edge, out localContinuationPoint); if (localContinuationPoint != insertionPoint && continuationPoint == null) continuationPoint = localContinuationPoint; } } if (continuationPoint == null) continuationPoint = insertionPoint; return insertionPoint; }
/// <summary> /// move outwards from starting point on until operation to continue at is found /// appending restore isomorphy at insertion point for isomorphy written on the way /// returns operation to continue at /// </summary> private static SearchProgramOperation MoveOutwardsAppendingRemoveIsomorphy( SearchProgramOperation startingPoint, ref SearchProgramOperation insertionPoint, string[] neededElementsForCheckOperation, SearchProgramOperation outermostOperation, SearchProgram topLevelSearchProgram) { // currently focused operation on our way outwards SearchProgramOperation op = startingPoint; // move outwards until operation to continue at is found bool creationPointOfDominatingElementFound = false; bool iterationReached = false; do { op = op.Previous; // insert code to clean up isomorphy information written by candidate acceptance // in between the operation to continue and the check operation if (op is AcceptCandidate) { AcceptCandidate writeIsomorphy = op as AcceptCandidate; AbandonCandidate restoreIsomorphy = new AbandonCandidate( writeIsomorphy.PatternElementName, writeIsomorphy.NegativeIndependentNamePrefix, writeIsomorphy.IsNode, writeIsomorphy.NeverAboveMaxIsoSpace, writeIsomorphy.Parallel, writeIsomorphy.LockForAllThreads); insertionPoint = insertionPoint.Append(restoreIsomorphy); } // insert code to clean up isomorphy information written by global candidate acceptance // in between the operation to continue and the check operation if (op is AcceptCandidateGlobal) { AcceptCandidateGlobal writeIsomorphy = op as AcceptCandidateGlobal; AbandonCandidateGlobal removeIsomorphy = new AbandonCandidateGlobal( writeIsomorphy.PatternElementName, writeIsomorphy.NegativeIndependentNamePrefix, writeIsomorphy.IsNode, writeIsomorphy.NeverAboveMaxIsoSpace, writeIsomorphy.Parallel); insertionPoint = insertionPoint.Append(removeIsomorphy); } // insert code to clean up isomorphy information written by patternpath candidate acceptance // in between the operation to continue and the check operation if (op is AcceptCandidatePatternpath) { AcceptCandidatePatternpath writeIsomorphy = op as AcceptCandidatePatternpath; AbandonCandidatePatternpath removeIsomorphy = new AbandonCandidatePatternpath( writeIsomorphy.PatternElementName, writeIsomorphy.NegativeIndependentNamePrefix, writeIsomorphy.IsNode); insertionPoint = insertionPoint.Append(removeIsomorphy); } // insert code to remove iterated pattern acceptance if (op is AcceptIterated) { AcceptIterated acceptIterated = op as AcceptIterated; AbandonIterated abandonIterated = new AbandonIterated(); insertionPoint = insertionPoint.Append(abandonIterated); } // insert code to undo subpattern matching initialization if we leave the subpattern matching method if (op is InitializeSubpatternMatching) { InitializeSubpatternMatching initialize = op as InitializeSubpatternMatching; FinalizeSubpatternMatching finalize = new FinalizeSubpatternMatching(initialize.Type); insertionPoint = insertionPoint.Append(finalize); } // insert code to undo negative/independent matching initialization if we leave the negative/independent matching method if (op is InitializeNegativeIndependentMatching) { InitializeNegativeIndependentMatching initialize = op as InitializeNegativeIndependentMatching; FinalizeNegativeIndependentMatching finalize = new FinalizeNegativeIndependentMatching(initialize.NeverAboveMaxIsoSpace, initialize.Parallel); insertionPoint = insertionPoint.Append(finalize); } // determine operation to continue at // found by looking at the graph elements // the check operation depends on / is dominated by // its the first element iteration on our way outwards the search program // after or at the point of a get element operation // of some dominating element the check depends on // (or the outermost operation if no iteration is found until it is reached) if (op is GetCandidate || op is BothDirectionsIteration) { if (creationPointOfDominatingElementFound == false) { if (neededElementsForCheckOperation != null) { foreach (string dominating in neededElementsForCheckOperation) { GetCandidate getCandidate = op as GetCandidate; BothDirectionsIteration bothDirections = op as BothDirectionsIteration; if (getCandidate != null && getCandidate.PatternElementName == dominating || bothDirections != null && bothDirections.PatternElementName == dominating) { creationPointOfDominatingElementFound = true; iterationReached = false; break; } } } else { // needed elements == null means everything fits, // take first element iteration on our way outwards the search program // (or the outermost operation if no iteration is found until it is reached) creationPointOfDominatingElementFound = true; iterationReached = false; } } if (op is GetCandidateByIteration || op is GetCandidateByIterationParallel || op is BothDirectionsIteration) { iterationReached = true; } } }while(!(creationPointOfDominatingElementFound && iterationReached) && op != outermostOperation); return(op); }
/// <summary> /// Decides which check connectedness operations are needed for the given node just drawn from edge /// and inserts them into the search program /// returns new insertion point and continuation point /// for continuing buildup after the stuff nested within both directions iteration was built /// if no direction iteration was needed, insertion point == continuation point /// </summary> private SearchProgramOperation decideOnAndInsertCheckConnectednessOfImplicitNodeFromEdge( SearchProgramOperation insertionPoint, SearchPlanNodeNode node, SearchPlanEdgeNode originatingEdge, SearchPlanNodeNode otherNodeOfOriginatingEdge, out SearchProgramOperation continuationPoint) { continuationPoint = null; SearchProgramOperation localContinuationPoint; // check for edges required by the pattern to be incident to the given node // only if the node was not taken from the given originating edge // with the exception of reflexive edges, as these won't get checked thereafter foreach (SearchPlanEdgeNode edge in node.OutgoingPatternEdges) { if (((PatternEdge)edge.PatternElement).fixedDirection || edge.PatternEdgeSource == edge.PatternEdgeTarget) { if (edge != originatingEdge || node == otherNodeOfOriginatingEdge) { insertionPoint = decideOnAndInsertCheckConnectednessOfNodeFixedDirection( insertionPoint, node, edge, CheckCandidateForConnectednessType.Source); } } else { if (edge != originatingEdge || node == otherNodeOfOriginatingEdge) { insertionPoint = decideOnAndInsertCheckConnectednessOfNodeBothDirections( insertionPoint, node, edge, out localContinuationPoint); if (localContinuationPoint != insertionPoint && continuationPoint == null) continuationPoint = localContinuationPoint; } } } foreach (SearchPlanEdgeNode edge in node.IncomingPatternEdges) { if (((PatternEdge)edge.PatternElement).fixedDirection || edge.PatternEdgeSource == edge.PatternEdgeTarget) { if (edge != originatingEdge || node == otherNodeOfOriginatingEdge) { insertionPoint = decideOnAndInsertCheckConnectednessOfNodeFixedDirection( insertionPoint, node, edge, CheckCandidateForConnectednessType.Target); } } else { if (edge != originatingEdge || node == otherNodeOfOriginatingEdge) { insertionPoint = decideOnAndInsertCheckConnectednessOfNodeBothDirections( insertionPoint, node, edge, out localContinuationPoint); if (localContinuationPoint != insertionPoint && continuationPoint == null) continuationPoint = localContinuationPoint; } } } if (continuationPoint == null) continuationPoint = insertionPoint; return insertionPoint; }