/// <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> /// Inserts code to yield, bubbling effects of nested yields upwards and computing local yields /// at the given position, returns position after inserted operations /// </summary> private SearchProgramOperation insertYields( SearchProgramOperation insertionPoint, PatternGraph patternGraph, String matchObjectName, bool inlined) { // the match object is built now with our local elements // and the match objects of our children // now 1. copy all def entities we share with children to our local variables foreach(PatternGraphEmbedding patternEmbedding in patternGraph.embeddedGraphsPlusInlined) { // in the inlined pass only the elements which were inlined into this pattern, in the non-inlined pass the original elements bool wasInlined = patternEmbedding.originalEmbedding != null; if(inlined == wasInlined) { // if the pattern embedding does not contain a def entity it can't yield to us if(!((PatternGraph)patternEmbedding.EmbeddedGraph).isDefEntityExistingPlusInlined) continue; // skip inlined embeddings (will be handled in 3.) if(patternEmbedding.inlined) continue; // in inlined pass bubble up from the components of the inlined patterns to the elements resulting from of the inlined pattern // (read from submatches to local variables, compute in local variables, writing will happen later from local variables to matches) string inlinedMatchObjectName = null; string patternEmbeddingName = patternEmbedding.Name; if(patternEmbedding.originalEmbedding != null) { if(patternGraph.WasInlinedHere(patternEmbedding.originalSubpatternEmbedding)) inlinedMatchObjectName = "match_" + patternEmbedding.originalSubpatternEmbedding.Name; patternEmbeddingName = patternEmbedding.originalEmbedding.name; } LGSPMatchingPattern matchingPattern = patternEmbedding.matchingPatternOfEmbeddedGraph; String nestedMatchObjectName = (inlinedMatchObjectName ?? matchObjectName) + "._" + patternEmbeddingName; Debug.Assert(matchingPattern.defNames.Length == patternEmbedding.yields.Length); for(int i = 0; i < patternEmbedding.yields.Length; ++i) { BubbleUpYieldAssignment bubble = new BubbleUpYieldAssignment( toBubbleUpYieldAssignmentType(matchingPattern.defs[i]), patternEmbedding.yields[i], nestedMatchObjectName, matchingPattern.defNames[i] ); insertionPoint = insertionPoint.Append(bubble); } } } foreach(Iterated iterated in patternGraph.iteratedsPlusInlined) { // in the inlined pass only the elements which were inlined into this pattern, in the non-inlined pass the original elements bool wasInlined = iterated.originalIterated != null; if(inlined == wasInlined) { // if the iterated does not contain a non local def entity it can't yield to us if(!iterated.iteratedPattern.isNonLocalDefEntityExistingPlusInlined) continue; // in inlined pass bubble up from the components of the inlined patterns to the elements resulting from of the inlined pattern // (read from submatches to local variables, compute in local variables, writing will happen later from local variables to matches) string inlinedMatchObjectName = null; string iteratedName = iterated.iteratedPattern.Name; if(iterated.originalIterated != null) { if(patternGraph.WasInlinedHere(iterated.originalSubpatternEmbedding)) inlinedMatchObjectName = "match_" + iterated.originalSubpatternEmbedding.Name; iteratedName = iterated.originalIterated.iteratedPattern.name; } String nestedMatchObjectName = (inlinedMatchObjectName ?? matchObjectName) + "._" + iteratedName; BubbleUpYieldIterated bubbleUpIterated = new BubbleUpYieldIterated(nestedMatchObjectName); bubbleUpIterated.NestedOperationsList = new SearchProgramList(bubbleUpIterated); SearchProgramOperation continuationPoint = insertionPoint.Append(bubbleUpIterated); insertionPoint = bubbleUpIterated.NestedOperationsList; insertYieldAssignments(insertionPoint, patternGraph, nestedMatchObjectName + ".Root", iterated.iteratedPattern); insertionPoint = continuationPoint; } } foreach(Alternative alternative in patternGraph.alternativesPlusInlined) { // in the inlined pass only the elements which were inlined into this pattern, in the non-inlined pass the original elements bool wasInlined = alternative.originalAlternative != null; if(inlined == wasInlined) { bool first = true; foreach(PatternGraph alternativeCase in alternative.alternativeCases) { // if the alternative case does not contain a non local def entity it can't yield to us if(!alternativeCase.isNonLocalDefEntityExistingPlusInlined) continue; // in inlined pass bubble up from the components of the inlined patterns to the elements resulting from of the inlined pattern // (read from submatches to local variables, compute in local variables, writing will happen later from local variables to matches) string inlinedMatchObjectName = matchObjectName; string inlinedNestedMatchObjectName = "_" + alternative.name; string inlinedPatternClassName = rulePatternClassName; string patternElementType = patternGraph.pathPrefix + patternGraph.name + "_" + alternative.name + "_" + alternativeCase.name; if(alternative.originalAlternative != null) { if(patternGraph.WasInlinedHere(alternative.originalSubpatternEmbedding)) inlinedMatchObjectName = "match_" + alternative.originalSubpatternEmbedding.name; inlinedNestedMatchObjectName = "_" + alternative.originalAlternative.name; inlinedPatternClassName = alternative.originalSubpatternEmbedding.matchingPatternOfEmbeddedGraph.GetType().Name; patternElementType = alternative.originalAlternative.pathPrefix + alternative.originalAlternative.name + "_" + alternativeCase.originalPatternGraph.name; } BubbleUpYieldAlternativeCase bubbleUpAlternativeCase = new BubbleUpYieldAlternativeCase( inlinedMatchObjectName, inlinedNestedMatchObjectName, inlinedPatternClassName + ".Match_" + patternElementType, "altCaseMatch", first); bubbleUpAlternativeCase.NestedOperationsList = new SearchProgramList(bubbleUpAlternativeCase); SearchProgramOperation continuationPoint = insertionPoint.Append(bubbleUpAlternativeCase); insertionPoint = bubbleUpAlternativeCase.NestedOperationsList; first = false; insertYieldAssignments(insertionPoint, patternGraph, "altCaseMatch", alternativeCase); insertionPoint = continuationPoint; } } } foreach(PatternGraph independent in patternGraph.independentPatternGraphsPlusInlined) { // in the inlined pass only the elements which were inlined into this pattern, in the non-inlined pass the original elements bool wasInlined = independent.originalPatternGraph != null; if(inlined == wasInlined) { // if the independent does not contain a non local def entity it can't yield to us if(!independent.isNonLocalDefEntityExistingPlusInlined) continue; // in inlined pass bubble up from the components of the inlined patterns to the elements resulting from of the inlined pattern // (read from submatches to local variables, compute in local variables, writing will happen later from local variables to matches) string inlinedMatchObjectName = null; if(independent.originalPatternGraph != null && patternGraph.WasInlinedHere(independent.originalSubpatternEmbedding)) { inlinedMatchObjectName = "match_" + independent.originalSubpatternEmbedding.Name; } String nestedMatchObjectName = NamesOfEntities.MatchedIndependentVariable(independent.pathPrefix + independent.name); ; insertionPoint = insertYieldAssignments(insertionPoint, patternGraph, inlinedMatchObjectName ?? nestedMatchObjectName, independent); } } ////////////////////////////////////////////////////// // then 2. compute all local yields PatternYielding[] patternYieldings; if(patternGraph.parallelizedSchedule != null) // in case of parallelization we've to use the parallelized yieldings patternYieldings = patternGraph.parallelizedYieldings; else patternYieldings = patternGraph.YieldingsPlusInlined; foreach(PatternYielding patternYielding in patternYieldings) { // in the inlined pass only the elements which were inlined into this pattern, in the non-inlined pass the original elements bool wasInlined = patternYielding.originalYielding != null; if(inlined == wasInlined) { YieldingBlock yieldingBlock = new YieldingBlock(patternYielding.Name); yieldingBlock.NestedOperationsList = new SearchProgramList(yieldingBlock); SearchProgramOperation continuationPointOuter = insertionPoint.Append(yieldingBlock); insertionPoint = yieldingBlock.NestedOperationsList; foreach(Yielding yielding in patternYielding.ElementaryYieldings) { // iterated potentially matching more than once can't be bubbled up normally, // they need accumulation with a for loop into a variable of the nesting pattern, // that's done in/with the yield statements of the parent if(yielding is IteratedAccumulationYield) { IteratedAccumulationYield accumulationYield = (IteratedAccumulationYield)yielding; foreach(Iterated iterated in patternGraph.iteratedsPlusInlined) { // skip the iterateds we're not interested in if(accumulationYield.Iterated != iterated.iteratedPattern.Name) continue; // in inlined pass bubble up from the components of the inlined patterns to the elements resulting from of the inlined pattern // (read from submatches to local variables, compute in local variables, writing will happen later from local variables to matches) string inlinedMatchObjectName = null; if(iterated.originalIterated != null) { inlinedMatchObjectName = "match_" + iterated.originalSubpatternEmbedding.Name; } String nestedMatchObjectName = (inlinedMatchObjectName ?? matchObjectName) + "._" + iterated.iteratedPattern.Name; AccumulateUpYieldIterated accumulateUpIterated = new AccumulateUpYieldIterated( nestedMatchObjectName, rulePatternClassName + ".Match_" + patternGraph.pathPrefix + patternGraph.name + "_" + iterated.iteratedPattern.name, "iteratedMatch"); accumulateUpIterated.NestedOperationsList = new SearchProgramList(accumulateUpIterated); SearchProgramOperation continuationPoint = insertionPoint.Append(accumulateUpIterated); insertionPoint = accumulateUpIterated.NestedOperationsList; accumulationYield.IteratedMatchVariable = "iteratedMatch._" + NamesOfEntities.Variable(accumulationYield.UnprefixedVariable); accumulationYield.ReplaceVariableByIterationVariable(accumulationYield); SourceBuilder yieldAssignmentSource = new SourceBuilder(); accumulationYield.Emit(yieldAssignmentSource); LocalYielding yieldAssignment = new LocalYielding(yieldAssignmentSource.ToString()); insertionPoint = insertionPoint.Append(yieldAssignment); insertionPoint = continuationPoint; } } else { SourceBuilder yieldAssignmentSource = new SourceBuilder(); yielding.Emit(yieldAssignmentSource); LocalYielding yieldAssignment = new LocalYielding(yieldAssignmentSource.ToString()); insertionPoint = insertionPoint.Append(yieldAssignment); } } insertionPoint = continuationPointOuter; } } ////////////////////////////////////////////////////// // 3. at the end of the inlined pass: // assign the def parameters from a subpattern which was inlined to the arguments yielded to // we can't read from the match objects of the inlined subpatterns cause they are not written yet, but from the corresponding local variables if(inlined) { foreach(PatternGraphEmbedding patternEmbedding in patternGraph.embeddedGraphsPlusInlined) { // only inlined embeddings if(!patternEmbedding.inlined) continue; for(int i = 0; i < patternEmbedding.yields.Length; ++i) { String targetName = patternEmbedding.yields[i]; String sourceName = patternEmbedding.matchingPatternOfEmbeddedGraph.defNames[i]; IPatternElement elem = getInlinedElementByOriginalUnprefixedName(patternGraph, patternEmbedding, sourceName); // find the one which was originating from inlining patternEmbedding, because of same originator bool isVariable = patternEmbedding.matchingPatternOfEmbeddedGraph.defs[i] is VarType; YieldAssignment assignment = new YieldAssignment( targetName, isVariable, patternEmbedding.matchingPatternOfEmbeddedGraph.defs[i] is VarType ? TypesHelper.TypeName(patternEmbedding.matchingPatternOfEmbeddedGraph.defs[i]) : patternEmbedding.matchingPatternOfEmbeddedGraph.defs[i].IsNodeType ? "GRGEN_LGSP.LGSPNode" : "GRGEN_LGSP.LGSPEdge", isVariable ? (Expression)new VariableExpression(elem.Name) : (Expression)new GraphEntityExpression(elem.Name) ); SourceBuilder yieldAssignmentSource = new SourceBuilder(); assignment.Emit(yieldAssignmentSource); LocalYielding yieldAssignment = new LocalYielding(yieldAssignmentSource.ToString()); insertionPoint = insertionPoint.Append(yieldAssignment); } } } 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> /// 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> /// 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> /// 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 declarations for variables extracted from parameters /// </summary> private 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> /// 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> /// Inserts code to build the match object /// at the given position, returns position after inserted operations /// </summary> private SearchProgramOperation insertMatchObjectBuilding( SearchProgramOperation insertionPoint, PatternGraph patternGraph, MatchObjectType matchObjectType, bool defElements) { String matchObjectName; if(matchObjectType==MatchObjectType.Independent) { matchObjectName = NamesOfEntities.MatchedIndependentVariable(patternGraph.pathPrefix + patternGraph.name); } else if(matchObjectType==MatchObjectType.Patternpath) { matchObjectName = NamesOfEntities.PatternpathMatch(patternGraph.pathPrefix + patternGraph.name); } else { //if(matchObjectType==MatchObjectType.Normal) matchObjectName = "match"; } String enumPrefix = patternGraph.pathPrefix + patternGraph.name + "_"; for (int i = 0; i < patternGraph.nodesPlusInlined.Length; ++i) { // in defElements pass only def elements, in non defElements pass only non def elements if(defElements == patternGraph.nodesPlusInlined[i].defToBeYieldedTo) { string inlinedMatchObjectName = null; string unprefixedName = patternGraph.nodesPlusInlined[i].UnprefixedName; if(patternGraph.nodesPlusInlined[i].originalNode != null) { if(patternGraph.WasInlinedHere(patternGraph.nodesPlusInlined[i].originalSubpatternEmbedding)) inlinedMatchObjectName = "match_" + patternGraph.nodesPlusInlined[i].originalSubpatternEmbedding.Name; unprefixedName = patternGraph.nodesPlusInlined[i].originalElement.UnprefixedName; } BuildMatchObject buildMatch = new BuildMatchObject( BuildMatchObjectType.Node, patternGraph.nodesPlusInlined[i].typeName, unprefixedName, patternGraph.nodesPlusInlined[i].Name, rulePatternClassName, enumPrefix, inlinedMatchObjectName ?? matchObjectName, -1 ); insertionPoint = insertionPoint.Append(buildMatch); } } for (int i = 0; i < patternGraph.edgesPlusInlined.Length; ++i) { // in defElements pass only def elements, in non defElements pass only non def elements if(defElements == patternGraph.edgesPlusInlined[i].defToBeYieldedTo) { string inlinedMatchObjectName = null; string unprefixedName = patternGraph.edgesPlusInlined[i].UnprefixedName; if(patternGraph.edgesPlusInlined[i].originalEdge != null) { if(patternGraph.WasInlinedHere(patternGraph.edgesPlusInlined[i].originalSubpatternEmbedding)) inlinedMatchObjectName = "match_" + patternGraph.edgesPlusInlined[i].originalSubpatternEmbedding.Name; unprefixedName = patternGraph.edgesPlusInlined[i].originalElement.UnprefixedName; } BuildMatchObject buildMatch = new BuildMatchObject( BuildMatchObjectType.Edge, patternGraph.edgesPlusInlined[i].typeName, unprefixedName, patternGraph.edgesPlusInlined[i].Name, rulePatternClassName, enumPrefix, inlinedMatchObjectName ?? matchObjectName, -1 ); insertionPoint = insertionPoint.Append(buildMatch); } } // only nodes and edges for patternpath matches if (matchObjectType == MatchObjectType.Patternpath) { return insertionPoint; } foreach (PatternVariable var in patternGraph.variablesPlusInlined) { // in defElements pass only def elements, in non defElements pass only non def elements if(defElements == var.defToBeYieldedTo) { string inlinedMatchObjectName = null; string unprefixedName = var.UnprefixedName; if(var.originalVariable != null) { if(patternGraph.WasInlinedHere(var.originalSubpatternEmbedding)) inlinedMatchObjectName = "match_" + var.originalSubpatternEmbedding.Name; unprefixedName = var.originalVariable.UnprefixedName; } BuildMatchObject buildMatch = new BuildMatchObject( BuildMatchObjectType.Variable, TypesHelper.TypeName(var.type), unprefixedName, var.Name, rulePatternClassName, enumPrefix, inlinedMatchObjectName ?? matchObjectName, -1 ); insertionPoint = insertionPoint.Append(buildMatch); } } // only nodes, edges, variables in defElements pass if(defElements) { return insertionPoint; } for (int i = 0; i < patternGraph.embeddedGraphsPlusInlined.Length; ++i) { if(patternGraph.embeddedGraphsPlusInlined[i].inlined) { BuildMatchObject buildMatch = new BuildMatchObject( BuildMatchObjectType.InlinedSubpattern, "", patternGraph.embeddedGraphsPlusInlined[i].name, patternGraph.embeddedGraphsPlusInlined[i].name, "", "", matchObjectName, -1 ); insertionPoint = insertionPoint.Append(buildMatch); } else { string inlinedMatchObjectName = null; string unprefixedName = patternGraph.embeddedGraphsPlusInlined[i].name; if(patternGraph.embeddedGraphsPlusInlined[i].originalEmbedding != null) { if(patternGraph.WasInlinedHere(patternGraph.embeddedGraphsPlusInlined[i].originalSubpatternEmbedding)) inlinedMatchObjectName = "match_" + patternGraph.embeddedGraphsPlusInlined[i].originalSubpatternEmbedding.Name; unprefixedName = patternGraph.embeddedGraphsPlusInlined[i].originalEmbedding.name; } string subpatternContainingType = NamesOfEntities.RulePatternClassName(patternGraph.embeddedGraphsPlusInlined[i].EmbeddedGraph.Name, patternGraph.embeddedGraphsPlusInlined[i].EmbeddedGraph.Package, true); string subpatternType = NamesOfEntities.MatchClassName(patternGraph.embeddedGraphsPlusInlined[i].EmbeddedGraph.Name); BuildMatchObject buildMatch = new BuildMatchObject( BuildMatchObjectType.Subpattern, subpatternContainingType + "." + subpatternType, unprefixedName, patternGraph.embeddedGraphsPlusInlined[i].name, rulePatternClassName, enumPrefix, inlinedMatchObjectName ?? matchObjectName, -1 ); insertionPoint = insertionPoint.Append(buildMatch); } } for (int i = 0; i < patternGraph.iteratedsPlusInlined.Length; ++i) { string inlinedMatchObjectName = null; string unprefixedName = patternGraph.iteratedsPlusInlined[i].iteratedPattern.name; string inlinedPatternClassName = rulePatternClassName; string patternElementType = patternGraph.pathPrefix + patternGraph.name + "_" + patternGraph.iteratedsPlusInlined[i].iteratedPattern.name; if(patternGraph.iteratedsPlusInlined[i].originalIterated != null) { if(patternGraph.WasInlinedHere(patternGraph.iteratedsPlusInlined[i].originalSubpatternEmbedding)) inlinedMatchObjectName = "match_" + patternGraph.iteratedsPlusInlined[i].originalSubpatternEmbedding.Name; unprefixedName = patternGraph.iteratedsPlusInlined[i].originalIterated.iteratedPattern.Name; inlinedPatternClassName = patternGraph.iteratedsPlusInlined[i].originalSubpatternEmbedding.matchingPatternOfEmbeddedGraph.GetType().Name; patternElementType = patternGraph.iteratedsPlusInlined[i].originalIterated.iteratedPattern.pathPrefix + unprefixedName; } BuildMatchObject buildMatch = new BuildMatchObject( BuildMatchObjectType.Iteration, patternElementType, unprefixedName, patternGraph.iteratedsPlusInlined[i].iteratedPattern.name, inlinedPatternClassName, enumPrefix, inlinedMatchObjectName ?? matchObjectName, patternGraph.embeddedGraphsPlusInlined.Length ); insertionPoint = insertionPoint.Append(buildMatch); } for (int i = 0; i < patternGraph.alternativesPlusInlined.Length; ++i) { string inlinedMatchObjectName = null; string unprefixedName = patternGraph.alternativesPlusInlined[i].name; string inlinedPatternClassName = rulePatternClassName; string patternElementType = patternGraph.pathPrefix+patternGraph.name+"_"+patternGraph.alternativesPlusInlined[i].name; if(patternGraph.alternativesPlusInlined[i].originalAlternative != null) { if(patternGraph.WasInlinedHere(patternGraph.alternativesPlusInlined[i].originalSubpatternEmbedding)) inlinedMatchObjectName = "match_" + patternGraph.alternativesPlusInlined[i].originalSubpatternEmbedding.Name; unprefixedName = patternGraph.alternativesPlusInlined[i].originalAlternative.name; inlinedPatternClassName = patternGraph.alternativesPlusInlined[i].originalSubpatternEmbedding.matchingPatternOfEmbeddedGraph.GetType().Name; patternElementType = patternGraph.alternativesPlusInlined[i].originalAlternative.pathPrefix + unprefixedName; } BuildMatchObject buildMatch = new BuildMatchObject( BuildMatchObjectType.Alternative, patternElementType, unprefixedName, patternGraph.alternativesPlusInlined[i].name, inlinedPatternClassName, enumPrefix, inlinedMatchObjectName ?? matchObjectName, patternGraph.embeddedGraphsPlusInlined.Length ); insertionPoint = insertionPoint.Append(buildMatch); } if (patternGraph.nestedIndependents != null) { foreach (KeyValuePair<PatternGraph,PatternGraph> nestedIndependent in patternGraph.nestedIndependents) { string inlinedMatchObjectName = null; string unprefixedName = nestedIndependent.Key.name; string inlinedPatternClassName = rulePatternClassName; string matchClassName = nestedIndependent.Key.pathPrefix + nestedIndependent.Key.name; if(nestedIndependent.Key.originalPatternGraph != null) { if(patternGraph.WasInlinedHere(nestedIndependent.Key.originalSubpatternEmbedding)) inlinedMatchObjectName = "match_" + nestedIndependent.Key.originalSubpatternEmbedding.Name; unprefixedName = nestedIndependent.Key.originalPatternGraph.Name; inlinedPatternClassName = nestedIndependent.Key.originalSubpatternEmbedding.matchingPatternOfEmbeddedGraph.GetType().Name; matchClassName = nestedIndependent.Key.pathPrefix + unprefixedName; } BuildMatchObject buildMatch = new BuildMatchObject( BuildMatchObjectType.Independent, unprefixedName, nestedIndependent.Key.pathPrefix + nestedIndependent.Key.name, inlinedPatternClassName, inlinedMatchObjectName ?? matchObjectName, matchClassName ); insertionPoint = insertionPoint.Append(buildMatch); } } // we only have to take care of yielding in case of normal and independent matches // and if we contain a def entity (and if we are not in the defElements pass), or if we contain a ref entity (that may be yielded to instead) if(matchObjectType != MatchObjectType.Patternpath && (patternGraph.isDefEntityExistingPlusInlined || patternGraph.IsRefEntityExisting())) { // first compute the yieldings which were inlined from subpatterns to us insertionPoint = insertYields(insertionPoint, patternGraph, matchObjectName, true); // then the yieldings of the current pattern return insertYields(insertionPoint, patternGraph, matchObjectName, false); // in the def-elements pass the yieldings computed into local variables are written to the match } 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 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> /// Inserts code to create the match objects of the inlined subpatterns /// at the given position, returns position after inserted operations /// </summary> private SearchProgramOperation insertInlinedMatchObjectCreation( SearchProgramOperation insertionPoint, PatternGraph patternGraph, MatchObjectType matchObjectType) { String matchOfEnclosingPatternName; if(matchObjectType == MatchObjectType.Independent) { matchOfEnclosingPatternName = NamesOfEntities.MatchedIndependentVariable(patternGraph.pathPrefix + patternGraph.name); } else { //if(matchObjectType==MatchObjectType.Normal) matchOfEnclosingPatternName = "match"; } for(int i = 0; i < patternGraph.embeddedGraphsPlusInlined.Length; ++i) { if(patternGraph.embeddedGraphsPlusInlined[i].inlined) { LGSPMatchingPattern matchingPattern = patternGraph.embeddedGraphsPlusInlined[i].matchingPatternOfEmbeddedGraph; string inlinedPatternClassName = NamesOfEntities.RulePatternClassName(matchingPattern.name, matchingPattern.PatternGraph.Package, true); insertionPoint = insertionPoint.Append( new CreateInlinedSubpatternMatch( inlinedPatternClassName, matchingPattern.patternGraph.pathPrefix + matchingPattern.patternGraph.name, patternGraph.embeddedGraphsPlusInlined[i].Name, matchOfEnclosingPatternName) ); } } return insertionPoint; }
/// <summary> /// Inserts code to get an implicit node from an edge /// </summary> private SearchProgramOperation insertImplicitNodeFromEdge( SearchProgramOperation insertionPoint, SearchPlanEdgeNode edge, SearchPlanNodeNode currentNode, ImplicitNodeType nodeType, out SearchProgramOperation continuationPoint) { continuationPoint = null; GetCandidateByDrawing nodeFromEdge; if (nodeType == ImplicitNodeType.Source || nodeType == ImplicitNodeType.Target) { nodeFromEdge = new GetCandidateByDrawing( GetCandidateByDrawingType.NodeFromEdge, currentNode.PatternElement.Name, TypesHelper.XgrsTypeToCSharpTypeNodeEdge(model.NodeModel.Types[currentNode.PatternElement.TypeID].PackagePrefixedName), edge.PatternElement.Name, nodeType); insertionPoint = insertionPoint.Append(nodeFromEdge); } else { Debug.Assert(nodeType != ImplicitNodeType.TheOther); if (currentNodeIsSecondIncidentNodeOfEdge(currentNode, edge)) { nodeFromEdge = new GetCandidateByDrawing( GetCandidateByDrawingType.NodeFromEdge, currentNode.PatternElement.Name, TypesHelper.XgrsTypeToCSharpTypeNodeEdge(model.NodeModel.Types[currentNode.PatternElement.TypeID].PackagePrefixedName), edge.PatternElement.Name, edge.PatternEdgeSource == currentNode ? edge.PatternEdgeTarget.PatternElement.Name : edge.PatternEdgeSource.PatternElement.Name, ImplicitNodeType.TheOther); insertionPoint = insertionPoint.Append(nodeFromEdge); } else // edge connects to first incident node { if (edge.PatternEdgeSource == edge.PatternEdgeTarget) { // reflexive edge without direction iteration as we don't want 2 matches nodeFromEdge = new GetCandidateByDrawing( GetCandidateByDrawingType.NodeFromEdge, currentNode.PatternElement.Name, TypesHelper.XgrsTypeToCSharpTypeNodeEdge(model.NodeModel.Types[currentNode.PatternElement.TypeID].PackagePrefixedName), edge.PatternElement.Name, ImplicitNodeType.Source); insertionPoint = insertionPoint.Append(nodeFromEdge); } else { BothDirectionsIteration directionsIteration = new BothDirectionsIteration(edge.PatternElement.Name); directionsIteration.NestedOperationsList = new SearchProgramList(directionsIteration); continuationPoint = insertionPoint.Append(directionsIteration); insertionPoint = directionsIteration.NestedOperationsList; nodeFromEdge = new GetCandidateByDrawing( GetCandidateByDrawingType.NodeFromEdge, currentNode.PatternElement.Name, TypesHelper.XgrsTypeToCSharpTypeNodeEdge(model.NodeModel.Types[currentNode.PatternElement.TypeID].PackagePrefixedName), edge.PatternElement.Name, ImplicitNodeType.SourceOrTarget); insertionPoint = insertionPoint.Append(nodeFromEdge); } } } if (continuationPoint == null) continuationPoint = insertionPoint; return insertionPoint; }
/// <summary> /// Search program operations completing the matching process /// after all pattern elements have been found are created and inserted into the program /// </summary> private SearchProgramOperation buildMatchComplete( SearchProgramOperation insertionPoint) { PatternGraph patternGraph = patternGraphWithNestingPatterns.Peek(); string negativeIndependentNamePrefix = NegativeIndependentNamePrefix(patternGraph); // is subpattern gives information about type of top level enclosing pattern (action vs. subpattern) // contains subpatterns gives informations about current pattern graph (might be negative, independent itself, too) bool isSubpattern = programType == SearchProgramType.Subpattern || programType == SearchProgramType.AlternativeCase || programType == SearchProgramType.Iterated; bool existsNonInlinedSubpattern = false; foreach(PatternGraphEmbedding sub in patternGraph.embeddedGraphsPlusInlined) if(!sub.inlined) existsNonInlinedSubpattern = true; bool containsSubpatterns = existsNonInlinedSubpattern || patternGraph.alternativesPlusInlined.Length >= 1 || patternGraph.iteratedsPlusInlined.Length >= 1; // increase iterated matched counter if it is iterated if(programType==SearchProgramType.Iterated) { AcceptIterated acceptIterated = new AcceptIterated(); insertionPoint = insertionPoint.Append(acceptIterated); } // push subpattern tasks (in case there are some) if(containsSubpatterns) insertionPoint = insertPushSubpatternTasks(insertionPoint); // if this is a subpattern without subpatterns // it may be the last to be matched - handle that case if(!containsSubpatterns && isSubpattern && programType!=SearchProgramType.Iterated && negativeIndependentNamePrefix=="") insertionPoint = insertCheckForTasksLeft(insertionPoint); // if this is a subpattern or a top-level pattern which contains subpatterns if(containsSubpatterns || isSubpattern && negativeIndependentNamePrefix=="") { // we do the global accept of all candidate elements (write isomorphy information) insertionPoint = insertGlobalAccept(insertionPoint); // and execute the open subpattern matching tasks MatchSubpatterns matchSubpatterns = new MatchSubpatterns(negativeIndependentNamePrefix, parallelized); insertionPoint = insertionPoint.Append(matchSubpatterns); } // pop subpattern tasks (in case there are/were some) if(containsSubpatterns) insertionPoint = insertPopSubpatternTasks(insertionPoint); // handle matched or not matched subpatterns, matched local pattern if(negativeIndependentNamePrefix == "") { // subpattern or top-level pattern which contains subpatterns if(containsSubpatterns || isSubpattern) insertionPoint = insertCheckForSubpatternsFound(insertionPoint, false); else // top-level-pattern of action without subpatterns insertionPoint = insertPatternFound(insertionPoint); } else { // negative/independent contains subpatterns if(containsSubpatterns) insertionPoint = insertCheckForSubpatternsFoundNegativeIndependent(insertionPoint); else insertionPoint = insertPatternFoundNegativeIndependent(insertionPoint); } // global abandon of all accepted candidate elements (remove isomorphy information) if(containsSubpatterns || isSubpattern && negativeIndependentNamePrefix=="") insertionPoint = insertGlobalAbandon(insertionPoint); // decrease iterated matched counter again if it is iterated if(programType == SearchProgramType.Iterated) { AbandonIterated abandonIterated = new AbandonIterated(); insertionPoint = insertionPoint.Append(abandonIterated); } return insertionPoint; }
/// <summary> /// Search program operations implementing the /// parallelized Extend Incoming|Outgoing|IncomingOrOutgoing search plan operation /// are created and inserted into search program /// </summary> private SearchProgramOperation buildParallelIncident( SearchProgramOperation insertionPoint, int currentOperationIndex, SearchPlanNodeNode source, SearchPlanEdgeNode target, IsomorphyInformation isomorphy, IncidentEdgeType edgeType) { #if RANDOM_LOOKUP_LIST_START // insert list heads randomization, thus randomized extend RandomizeListHeads randomizeListHeads = new RandomizeListHeads( RandomizeListHeadsTypes.IncidentEdges, target.PatternElement.Name, source.PatternElement.Name, getIncoming); insertionPoint = insertionPoint.Append(randomizeListHeads); #endif // iterate available incident edges SearchPlanNodeNode node = source; SearchPlanEdgeNode currentEdge = target; IncidentEdgeType incidentType = edgeType; SearchProgramOperation continuationPoint; GetCandidateByIterationParallel incidentIteration; if(incidentType == IncidentEdgeType.Incoming || incidentType == IncidentEdgeType.Outgoing) { incidentIteration = new GetCandidateByIterationParallel( GetCandidateByIterationType.IncidentEdges, currentEdge.PatternElement.Name, node.PatternElement.Name, incidentType, emitProfiling, packagePrefixedActionName, !firstLoopPassed); firstLoopPassed = true; incidentIteration.NestedOperationsList = new SearchProgramList(incidentIteration); continuationPoint = insertionPoint.Append(incidentIteration); insertionPoint = incidentIteration.NestedOperationsList; } else // IncidentEdgeType.IncomingOrOutgoing { if(currentEdge.PatternEdgeSource == currentEdge.PatternEdgeTarget) { // reflexive edge without direction iteration as we don't want 2 matches incidentIteration = new GetCandidateByIterationParallel( GetCandidateByIterationType.IncidentEdges, currentEdge.PatternElement.Name, node.PatternElement.Name, IncidentEdgeType.Incoming, emitProfiling, packagePrefixedActionName, !firstLoopPassed); firstLoopPassed = true; incidentIteration.NestedOperationsList = new SearchProgramList(incidentIteration); continuationPoint = insertionPoint.Append(incidentIteration); insertionPoint = incidentIteration.NestedOperationsList; } else { incidentIteration = new GetCandidateByIterationParallel( GetCandidateByIterationType.IncidentEdges, currentEdge.PatternElement.Name, node.PatternElement.Name, IncidentEdgeType.IncomingOrOutgoing, emitProfiling, packagePrefixedActionName, !firstLoopPassed); firstLoopPassed = true; incidentIteration.NestedOperationsList = new SearchProgramList(incidentIteration); continuationPoint = insertionPoint.Append(incidentIteration); insertionPoint = incidentIteration.NestedOperationsList; } } // check type of candidate insertionPoint = decideOnAndInsertCheckType(insertionPoint, target); // check connectedness of candidate SearchProgramOperation continuationPointOfConnectednessCheck; insertionPoint = decideOnAndInsertCheckConnectednessOfIncidentEdgeFromNode( insertionPoint, target, source, edgeType == IncidentEdgeType.Incoming, out continuationPointOfConnectednessCheck); // check candidate for isomorphy string negativeIndependentNamePrefix = ""; if(isomorphy.CheckIsMatchedBit) { CheckCandidateForIsomorphy checkIsomorphy = new CheckCandidateForIsomorphy( target.PatternElement.Name, isomorphy.PatternElementsToCheckAgainstAsListOfStrings(), negativeIndependentNamePrefix, false, 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, false, 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, false, isoSpaceNeverAboveMaxIsoSpace, isomorphy.Parallel, isomorphy.LockForAllThreads); insertionPoint = insertionPoint.Append(abandonCandidate); } // everything nested within incident iteration built by now - // continue at the end of the list after incident edges iteration insertionPoint = continuationPoint; return insertionPoint; }
/// <summary> /// Search program operations implementing the /// setup parallelized Extend Incoming|Outgoing|IncomingOrOutgoing search plan operation /// are created and inserted into search program /// </summary> private SearchProgramOperation buildParallelIncidentSetup( SearchProgramOperation insertionPoint, SearchPlanNodeNode source, SearchPlanEdgeNode target, IncidentEdgeType edgeType) { // iterate available incident edges SearchPlanNodeNode node = source; SearchPlanEdgeNode currentEdge = target; IncidentEdgeType incidentType = edgeType; GetCandidateByIterationParallelSetup incidentIteration; PatternGraph patternGraph = patternGraphWithNestingPatterns.Peek(); if(incidentType == IncidentEdgeType.Incoming || incidentType == IncidentEdgeType.Outgoing) { incidentIteration = new GetCandidateByIterationParallelSetup( GetCandidateByIterationType.IncidentEdges, currentEdge.PatternElement.Name, node.PatternElement.Name, incidentType, rulePatternClassName, patternGraph.name, parameterNames, false, wasIndependentInlined(patternGraph, indexOfSchedule), emitProfiling, packagePrefixedActionName, !firstLoopPassed); return insertionPoint.Append(incidentIteration); } else // IncidentEdgeType.IncomingOrOutgoing { if(currentEdge.PatternEdgeSource == currentEdge.PatternEdgeTarget) { // reflexive edge without direction iteration as we don't want 2 matches incidentIteration = new GetCandidateByIterationParallelSetup( GetCandidateByIterationType.IncidentEdges, currentEdge.PatternElement.Name, node.PatternElement.Name, IncidentEdgeType.Incoming, rulePatternClassName, patternGraph.name, parameterNames, false, wasIndependentInlined(patternGraph, indexOfSchedule), emitProfiling, packagePrefixedActionName, !firstLoopPassed); return insertionPoint.Append(incidentIteration); } else { BothDirectionsIteration directionsIteration = new BothDirectionsIteration(currentEdge.PatternElement.Name); directionsIteration.NestedOperationsList = new SearchProgramList(directionsIteration); SearchProgramOperation continuationPoint = insertionPoint.Append(directionsIteration); insertionPoint = directionsIteration.NestedOperationsList; incidentIteration = new GetCandidateByIterationParallelSetup( GetCandidateByIterationType.IncidentEdges, currentEdge.PatternElement.Name, node.PatternElement.Name, IncidentEdgeType.IncomingOrOutgoing, rulePatternClassName, patternGraph.name, parameterNames, true, wasIndependentInlined(patternGraph, indexOfSchedule), emitProfiling, packagePrefixedActionName, !firstLoopPassed); return insertionPoint.Append(incidentIteration); } } }
/// <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 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; }
/// <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> /// 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> /// 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> /// 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> /// 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 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> /// 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 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> /// 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> /// 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> /// 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> /// 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> /// 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> /// 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> /// "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> /// 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> /// 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> /// 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 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> /// Search program operations implementing the /// parallelized PickFromIndex search plan operation /// are created and inserted into search program /// </summary> private SearchProgramOperation buildParallelPickFromIndex( SearchProgramOperation insertionPoint, int currentOperationIndex, SearchPlanNode target, IndexAccess index, IsomorphyInformation isomorphy) { bool isNode = target.NodeType == PlanNodeType.Node; string negativeIndependentNamePrefix = ""; string iterationType = TypesHelper.TypeName(index.Index is AttributeIndexDescription ? ((AttributeIndexDescription)index.Index).GraphElementType : ((IncidenceCountIndexDescription)index.Index).StartNodeType); string indexSetType = NamesOfEntities.IndexSetType(model.ModelName); // iterate available index elements GetCandidateByIterationParallel elementsIteration; if(index is IndexAccessEquality) { IndexAccessEquality indexEquality = (IndexAccessEquality)index; SourceBuilder equalityExpression = new SourceBuilder(); indexEquality.Expr.Emit(equalityExpression); elementsIteration = new GetCandidateByIterationParallel( GetCandidateByIterationType.IndexElements, target.PatternElement.Name, index.Index.Name, iterationType, indexSetType, IndexAccessType.Equality, equalityExpression.ToString(), isNode, emitProfiling, packagePrefixedActionName, !firstLoopPassed); } else if(index is IndexAccessAscending) { IndexAccessAscending indexAscending = (IndexAccessAscending)index; SourceBuilder fromExpression = new SourceBuilder(); if(indexAscending.From != null) indexAscending.From.Emit(fromExpression); SourceBuilder toExpression = new SourceBuilder(); if(indexAscending.To != null) indexAscending.To.Emit(toExpression); elementsIteration = new GetCandidateByIterationParallel( GetCandidateByIterationType.IndexElements, target.PatternElement.Name, index.Index.Name, iterationType, indexSetType, IndexAccessType.Ascending, indexAscending.From != null ? fromExpression.ToString() : null, indexAscending.IncludingFrom, indexAscending.To != null ? toExpression.ToString() : null, indexAscending.IncludingTo, isNode, emitProfiling, packagePrefixedActionName, !firstLoopPassed); } else //if(index is IndexAccessDescending) { IndexAccessDescending indexDescending = (IndexAccessDescending)index; SourceBuilder fromExpression = new SourceBuilder(); if(indexDescending.From != null) indexDescending.From.Emit(fromExpression); SourceBuilder toExpression = new SourceBuilder(); if(indexDescending.To != null) indexDescending.To.Emit(toExpression); elementsIteration = new GetCandidateByIterationParallel( GetCandidateByIterationType.IndexElements, target.PatternElement.Name, index.Index.Name, iterationType, indexSetType, IndexAccessType.Descending, indexDescending.From != null ? fromExpression.ToString() : null, indexDescending.IncludingFrom, indexDescending.To != null ? toExpression.ToString() : null, indexDescending.IncludingTo, isNode, emitProfiling, packagePrefixedActionName, !firstLoopPassed); } firstLoopPassed = true; SearchProgramOperation continuationPoint = insertionPoint.Append(elementsIteration); elementsIteration.NestedOperationsList = new SearchProgramList(elementsIteration); insertionPoint = elementsIteration.NestedOperationsList; // check type of candidate insertionPoint = decideOnAndInsertCheckType(insertionPoint, target); // check connectedness of candidate SearchProgramOperation continuationPointAfterConnectednessCheck; if(isNode) { insertionPoint = decideOnAndInsertCheckConnectednessOfNodeFromLookupOrPickOrMap( insertionPoint, (SearchPlanNodeNode)target, out continuationPointAfterConnectednessCheck); } else { insertionPoint = decideOnAndInsertCheckConnectednessOfEdgeFromLookupOrPickOrMap( insertionPoint, (SearchPlanEdgeNode)target, out continuationPointAfterConnectednessCheck); } // 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); } // everything nested within candidate iteration built by now - // continue at the end of the list after storage iteration insertionPoint = continuationPoint; return insertionPoint; }