/// <summary> /// Parallelize the scheduled search plan for usage from a parallelized matcher /// (non- is-matched-flag-based isomorphy checking) /// </summary> public static void Parallelize(LGSPMatchingPattern matchingPattern) { Debug.Assert(matchingPattern.patternGraph.schedulesIncludingNegativesAndIndependents.Length == 1); ScheduledSearchPlan ssp = matchingPattern.patternGraph.schedulesIncludingNegativesAndIndependents[0]; matchingPattern.patternGraph.parallelizedSchedule = new ScheduledSearchPlan[1]; List <SearchOperation> operations = new List <SearchOperation>(ssp.Operations.Length); for (int i = 0; i < ssp.Operations.Length; ++i) { SearchOperation so = ssp.Operations[i]; SearchOperation clone = (SearchOperation)so.Clone(); clone.Isomorphy.Parallel = true; operations.Add(clone); if (clone.Element is PatternCondition) { SetNeedForParallelizedVersion((clone.Element as PatternCondition).ConditionExpression); } } ScheduledSearchPlan clonedSsp = new ScheduledSearchPlan( matchingPattern.patternGraph, operations.ToArray(), operations.Count > 0 ? operations[0].CostToEnd : 0); matchingPattern.patternGraph.parallelizedSchedule[0] = clonedSsp; ParallelizeNegativeIndependent(clonedSsp); ParallelizeAlternativeIterated(matchingPattern.patternGraph); ParallelizeYielding(matchingPattern.patternGraph); }
private static void ExtractNestedIndependents(List <String> matchingPatternClassTypeNames, List <Dictionary <PatternGraph, bool> > nestedIndependents, LGSPMatchingPattern matchingPattern, PatternGraph patternGraph) { matchingPatternClassTypeNames.Add(matchingPattern.GetType().Name); nestedIndependents.Add(patternGraph.nestedIndependents); foreach (PatternGraph idpt in patternGraph.independentPatternGraphsPlusInlined) { ExtractNestedIndependents(matchingPatternClassTypeNames, nestedIndependents, matchingPattern, idpt); } }
/// <summary> /// Parallelize the scheduled search plan if it is to be parallelized. /// An action to be parallelized is split at the first loop into a header part and a body part, /// all subpatterns and nested patterns to be parallelized are switched to non- is-matched-flag-based isomorphy checking. /// </summary> public static void ParallelizeAsNeeded(LGSPMatchingPattern matchingPattern) { if (matchingPattern.patternGraph.branchingFactor < 2) { return; } if (matchingPattern is LGSPRulePattern) { bool parallelizableLoopFound = false; foreach (SearchOperation so in matchingPattern.patternGraph.schedulesIncludingNegativesAndIndependents[0].Operations) { if (so.Type == SearchOperationType.Lookup || so.Type == SearchOperationType.Incident || so.Type == SearchOperationType.Incoming || so.Type == SearchOperationType.Outgoing || so.Type == SearchOperationType.PickFromStorage || so.Type == SearchOperationType.PickFromStorageDependent || so.Type == SearchOperationType.PickFromIndex || so.Type == SearchOperationType.PickFromIndexDependent) { parallelizableLoopFound = true; break; } } if (parallelizableLoopFound) { ParallelizeHeadBody((LGSPRulePattern)matchingPattern); } else { matchingPattern.patternGraph.branchingFactor = 1; Console.Error.WriteLine("Warning: " + matchingPattern.patternGraph.Name + " not parallelized as no parallelizable loop was found."); } } else { Parallelize(matchingPattern); } }
/// <summary> /// Generates the parallelized search program(s) for the pattern graph of the given rule /// </summary> SearchProgram GenerateParallelizedSearchProgramAsNeeded(LGSPMatchingPattern matchingPattern) { PatternGraph patternGraph = matchingPattern.patternGraph; if(patternGraph.parallelizedSchedule == null) return null; SearchProgram searchProgramRoot = null; SearchProgram searchProgramListEnd = null; for(int i = 0; i < patternGraph.parallelizedSchedule.Length; ++i) // 2 for actions, 1 for subpatterns { ScheduledSearchPlan scheduledSearchPlan = patternGraph.parallelizedSchedule[i]; #if DUMP_SCHEDULED_SEARCH_PLAN StreamWriter sspwriter = new StreamWriter(matchingPattern.name + (i==1 ? "_parallelized_body" : "_parallelized") + "_ssp_dump.txt"); float prevCostToEnd = scheduledSearchPlan.Operations.Length > 0 ? scheduledSearchPlan.Operations[0].CostToEnd : 0f; foreach(SearchOperation so in scheduledSearchPlan.Operations) { sspwriter.Write(SearchOpToString(so) + " ; " + so.CostToEnd + " (+" + (prevCostToEnd-so.CostToEnd) + ")" + "\n"); prevCostToEnd = so.CostToEnd; } sspwriter.Close(); #endif // build pass: build nested program from scheduled search plan SearchProgramBuilder searchProgramBuilder = new SearchProgramBuilder(); if(matchingPattern is LGSPRulePattern) { SearchProgram sp = searchProgramBuilder.BuildSearchProgram(model, (LGSPRulePattern)matchingPattern, i, null, true, Profile); if(i == 0) searchProgramRoot = searchProgramListEnd = sp; else searchProgramListEnd = (SearchProgram)searchProgramListEnd.Append(sp); } else { Debug.Assert(searchProgramRoot == null); searchProgramRoot = searchProgramListEnd = searchProgramBuilder.BuildSearchProgram(model, matchingPattern, true, Profile); } } #if DUMP_SEARCHPROGRAMS // dump built search program for debugging SourceBuilder builder = new SourceBuilder(CommentSourceCode); searchProgramRoot.Dump(builder); StreamWriter writer = new StreamWriter(matchingPattern.name + (i==1 ? "_parallelized_body" : "_parallelized") + "_" + searchProgramRoot.Name + "_built_dump.txt"); writer.Write(builder.ToString()); writer.Close(); #endif // complete pass: complete check operations in all search programs SearchProgramCompleter searchProgramCompleter = new SearchProgramCompleter(); searchProgramCompleter.CompleteCheckOperationsInAllSearchPrograms(searchProgramRoot); #if DUMP_SEARCHPROGRAMS // dump completed search program for debugging builder = new SourceBuilder(CommentSourceCode); searchProgramRoot.Dump(builder); writer = new StreamWriter(matchingPattern.name + (i==1 ? "_parallelized_body" : "_parallelized") + "_" + searchProgramRoot.Name + "_completed_dump.txt"); writer.Write(builder.ToString()); writer.Close(); #endif return searchProgramRoot; }
/// <summary> /// Generates the action interface plus action implementation including the matcher source code /// for the alternatives/iterateds nested within the given negative/independent pattern graph into the given source builder /// </summary> public void GenerateActionAndMatcherOfNestedPatterns(SourceBuilder sb, LGSPMatchingPattern matchingPattern, PatternGraph negOrIdpt, bool isInitialStatic) { // nothing to do locally .. // .. just move on to the nested alternatives or iterateds foreach (Alternative alt in negOrIdpt.alternativesPlusInlined) { GenerateActionAndMatcherOfAlternative(sb, matchingPattern, alt, isInitialStatic); } foreach (Iterated iter in negOrIdpt.iteratedsPlusInlined) { GenerateActionAndMatcherOfIterated(sb, matchingPattern, iter.iteratedPattern, isInitialStatic); } foreach (PatternGraph nestedNeg in negOrIdpt.negativePatternGraphsPlusInlined) { GenerateActionAndMatcherOfNestedPatterns(sb, matchingPattern, nestedNeg, isInitialStatic); } foreach (PatternGraph nestedIdpt in negOrIdpt.independentPatternGraphsPlusInlined) { GenerateActionAndMatcherOfNestedPatterns(sb, matchingPattern, nestedIdpt, isInitialStatic); } }
/// <summary> /// Generates the action interface plus action implementation including the matcher source code /// for the given iterated pattern into the given source builder /// </summary> public void GenerateActionAndMatcherOfIterated(SourceBuilder sb, LGSPMatchingPattern matchingPattern, PatternGraph iter, bool isInitialStatic) { // generate the search program out of the schedule within the pattern graph of the iterated pattern SearchProgram searchProgram = GenerateSearchProgramIterated(matchingPattern, iter); // generate the parallelized search program out of the parallelized schedule within the pattern graph of the iterated pattern SearchProgram searchProgramParallelized = GenerateParallelizedSearchProgramIteratedAsNeeded(matchingPattern, iter); // emit matcher class head, body, tail; body is source code representing search program GenerateMatcherClassHeadIterated(sb, matchingPattern, iter, isInitialStatic); searchProgram.Emit(sb); if(searchProgramParallelized != null) searchProgramParallelized.Emit(sb); GenerateMatcherClassTail(sb, matchingPattern.PatternGraph.Package != null); // finally generate matcher source for all the nested alternatives or iterateds of the iterated pattern graph // nested inside the alternatives,iterateds,negatives,independents foreach (Alternative alt in iter.alternativesPlusInlined) { GenerateActionAndMatcherOfAlternative(sb, matchingPattern, alt, isInitialStatic); } foreach (Iterated nestedIter in iter.iteratedsPlusInlined) { GenerateActionAndMatcherOfIterated(sb, matchingPattern, nestedIter.iteratedPattern, isInitialStatic); } foreach (PatternGraph neg in iter.negativePatternGraphsPlusInlined) { GenerateActionAndMatcherOfNestedPatterns(sb, matchingPattern, neg, isInitialStatic); } foreach (PatternGraph idpt in iter.independentPatternGraphsPlusInlined) { GenerateActionAndMatcherOfNestedPatterns(sb, matchingPattern, idpt, isInitialStatic); } }
/// <summary> /// Builds search program for alternative from scheduled search plans of the alternative cases /// </summary> public SearchProgram BuildSearchProgram( IGraphModel model, LGSPMatchingPattern matchingPattern, Alternative alternative, bool parallelized, bool emitProfiling) { programType = SearchProgramType.AlternativeCase; this.model = model; patternGraphWithNestingPatterns = new Stack<PatternGraph>(); this.parallelized = parallelized; this.alternative = alternative; rulePatternClassName = NamesOfEntities.RulePatternClassName(matchingPattern.name, matchingPattern.PatternGraph.Package, !(matchingPattern is LGSPRulePattern)); this.emitProfiling = emitProfiling; packagePrefixedActionName = null; firstLoopPassed = false; // build combined list of namesOfPatternGraphsOnPathToEnclosedPatternpath // from the namesOfPatternGraphsOnPathToEnclosedPatternpath of the alternative cases List<string> namesOfPatternGraphsOnPathToEnclosedPatternpath = new List<string>(); 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); } } // build outermost search program operation, create the list anchor starting its program SearchProgram searchProgram = new SearchProgramOfAlternative( rulePatternClassName, namesOfPatternGraphsOnPathToEnclosedPatternpath, "myMatch", 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; } GetPartialMatchOfAlternative matchAlternative = new GetPartialMatchOfAlternative( pathPrefixInInlinedPatternClass, unprefixedNameInInlinedPatternClass, inlinedPatternClassName, wasIndependentInlined(altCase, indexOfSchedule)); matchAlternative.OperationsList = new SearchProgramList(matchAlternative); SearchProgramOperation continuationPointAfterAltCase = insertionPoint.Append(matchAlternative); // at level of the current alt case insertionPoint = matchAlternative.OperationsList; insertionPoint = insertVariableDeclarations(insertionPoint, altCase); patternGraphWithNestingPatterns.Push(altCase); isoSpaceNeverAboveMaxIsoSpace = patternGraphWithNestingPatterns.Peek().maxIsoSpace < (int)LGSPElemFlags.MAX_ISO_SPACE; isNegative = false; isNestedInNegative = false; // start building with first operation in scheduled search plan indexOfSchedule = 0; 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); } patternGraphWithNestingPatterns.Pop(); } // finalize task/result-pushdown handling in subpattern matcher FinalizeSubpatternMatching finalize = new FinalizeSubpatternMatching(InitializeFinalizeSubpatternMatchingType.Normal); insertionPoint = insertionPoint.Append(finalize); return searchProgram; }
//////////////////////////////////////////////////////////////////////////// /// <summary> /// Constructs a PatternGraphEmbedding object. /// </summary> /// <param name="name">The name of the usage of the subpattern.</param> /// <param name="matchingPatternOfEmbeddedGraph">The embedded subpattern.</param> /// <param name="connections">An array with the expressions defining how the subpattern is connected /// to the containing pattern (graph elements and basic variables) .</param> /// <param name="yields">An array with the def elements and variables /// from the containing pattern yielded to from the subpattern.</param> /// <param name="neededNodes">An array with names of nodes needed by this embedding.</param> /// <param name="neededEdges">An array with names of edges needed by this embedding.</param> /// <param name="neededVariables">An array with names of variables needed by this embedding.</param> /// <param name="neededVariableTypes">An array with types of variables needed by this embedding.</param> public PatternGraphEmbedding(String name, LGSPMatchingPattern matchingPatternOfEmbeddedGraph, Expression[] connections, String[] yields, String[] neededNodes, String[] neededEdges, String[] neededVariables, VarType[] neededVariableTypes) { this.name = name; this.matchingPatternOfEmbeddedGraph = matchingPatternOfEmbeddedGraph; this.connections = connections; this.yields = yields; this.neededNodes = neededNodes; this.neededEdges = neededEdges; this.neededVariables = neededVariables; this.neededVariableTypes = neededVariableTypes; this.matchingPatternOfEmbeddedGraph.uses += 1; }
/// <summary> /// Generates matcher class head source code for the given iterated pattern into given source builder /// isInitialStatic tells whether the initial static version or a dynamic version after analyze is to be generated. /// </summary> public void GenerateMatcherClassHeadIterated(SourceBuilder sb, LGSPMatchingPattern matchingPattern, PatternGraph iter, bool isInitialStatic) { PatternGraph patternGraph = (PatternGraph)matchingPattern.PatternGraph; String namePrefix = (isInitialStatic ? "" : "Dyn") + "IteratedAction_"; String className = namePrefix + iter.pathPrefix + iter.name; String matchingPatternClassName = matchingPattern.GetType().Name; if(patternGraph.Package != null) { sb.AppendFrontFormat("namespace {0}\n", patternGraph.Package); sb.AppendFront("{\n"); sb.Indent(); } sb.AppendFront("public class " + className + " : GRGEN_LGSP.LGSPSubpatternAction\n"); sb.AppendFront("{\n"); sb.Indent(); // class level sb.AppendFront("private " + className + "(GRGEN_LGSP.LGSPActionExecutionEnvironment actionEnv_, Stack<GRGEN_LGSP.LGSPSubpatternAction> openTasks_) {\n"); sb.Indent(); // method body level sb.AppendFront("actionEnv = actionEnv_; openTasks = openTasks_;\n"); sb.AppendFront("patternGraph = " + matchingPatternClassName + ".Instance.patternGraph;\n"); int index = -1; for (int i=0; i<iter.embeddingGraph.iteratedsPlusInlined.Length; ++i) { if (iter.embeddingGraph.iteratedsPlusInlined[i].iteratedPattern == iter) index = i; } sb.AppendFrontFormat("minMatchesIter = {0};\n", iter.embeddingGraph.iteratedsPlusInlined[index].minMatches); sb.AppendFrontFormat("maxMatchesIter = {0};\n", iter.embeddingGraph.iteratedsPlusInlined[index].maxMatches); sb.AppendFront("numMatchesIter = 0;\n"); if(iter.isIterationBreaking) sb.AppendFront("breakIteration = false;\n"); sb.Unindent(); // class level sb.AppendFront("}\n\n"); sb.AppendFront("int minMatchesIter;\n"); sb.AppendFront("int maxMatchesIter;\n"); sb.AppendFront("int numMatchesIter;\n"); if(iter.isIterationBreaking) sb.AppendFront("bool breakIteration;\n"); sb.Append("\n"); GenerateTasksMemoryPool(sb, className, false, iter.isIterationBreaking, matchingPattern.patternGraph.branchingFactor); 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 (KeyValuePair<string, bool> neededNode in iter.neededNodes) neededNodes[neededNode.Key] = neededNode.Value; foreach (KeyValuePair<string, bool> neededEdge in iter.neededEdges) neededEdges[neededEdge.Key] = neededEdge.Value; foreach (KeyValuePair<string, GrGenType> neededVariable in iter.neededVariables) neededVariables[neededVariable.Key] = neededVariable.Value; foreach (KeyValuePair<string, bool> node in neededNodes) { sb.AppendFront("public GRGEN_LGSP.LGSPNode " + node.Key + ";\n"); } foreach (KeyValuePair<string, bool> edge in neededEdges) { sb.AppendFront("public GRGEN_LGSP.LGSPEdge " + edge.Key + ";\n"); } foreach (KeyValuePair<string, GrGenType> variable in neededVariables) { sb.AppendFront("public " + TypesHelper.TypeName(variable.Value) + " " + variable.Key + ";\n"); } GenerateIndependentsMatchObjects(sb, matchingPattern, iter); sb.AppendFront("\n"); }
/// <summary> /// Generates matcher class head source code for the subpattern of the rulePattern into given source builder /// isInitialStatic tells whether the initial static version or a dynamic version after analyze is to be generated. /// </summary> public void GenerateMatcherClassHeadSubpattern(SourceBuilder sb, LGSPMatchingPattern matchingPattern, bool isInitialStatic) { Debug.Assert(!(matchingPattern is LGSPRulePattern)); PatternGraph patternGraph = (PatternGraph)matchingPattern.PatternGraph; String namePrefix = (isInitialStatic ? "" : "Dyn") + "PatternAction_"; String className = namePrefix + matchingPattern.name; String matchingPatternClassName = matchingPattern.GetType().Name; if(patternGraph.Package != null) { sb.AppendFrontFormat("namespace {0}\n", patternGraph.Package); sb.AppendFront("{\n"); sb.Indent(); } sb.AppendFront("public class " + className + " : GRGEN_LGSP.LGSPSubpatternAction\n"); sb.AppendFront("{\n"); sb.Indent(); // class level sb.AppendFront("private " + className + "(GRGEN_LGSP.LGSPActionExecutionEnvironment actionEnv_, Stack<GRGEN_LGSP.LGSPSubpatternAction> openTasks_) {\n"); sb.Indent(); // method body level sb.AppendFront("actionEnv = actionEnv_; openTasks = openTasks_;\n"); sb.AppendFront("patternGraph = " + matchingPatternClassName + ".Instance.patternGraph;\n"); sb.Unindent(); // class level sb.AppendFront("}\n\n"); GenerateTasksMemoryPool(sb, className, false, false, matchingPattern.patternGraph.branchingFactor); for (int i = 0; i < patternGraph.nodesPlusInlined.Length; ++i) { PatternNode node = patternGraph.nodesPlusInlined[i]; if (node.PointOfDefinition == null) { sb.AppendFront("public GRGEN_LGSP.LGSPNode " + node.name + ";\n"); } } for (int i = 0; i < patternGraph.edgesPlusInlined.Length; ++i) { PatternEdge edge = patternGraph.edgesPlusInlined[i]; if (edge.PointOfDefinition == null) { sb.AppendFront("public GRGEN_LGSP.LGSPEdge " + edge.name + ";\n"); } } for (int i = 0; i < patternGraph.variablesPlusInlined.Length; ++i) { PatternVariable variable = patternGraph.variablesPlusInlined[i]; sb.AppendFront("public " +TypesHelper.TypeName(variable.type) + " " + variable.name + ";\n"); } GenerateIndependentsMatchObjects(sb, matchingPattern, patternGraph); sb.AppendFront("\n"); }
/// <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> /// Builds search program for alternative from scheduled search plans of the alternative cases /// </summary> public static SearchProgram BuildSearchProgram( IGraphModel model, LGSPMatchingPattern matchingPattern, Alternative alternative, bool parallelized, bool emitProfiling) { String rulePatternClassName = NamesOfEntities.RulePatternClassName(matchingPattern.name, matchingPattern.PatternGraph.Package, !(matchingPattern is LGSPRulePattern)); // build combined list of namesOfPatternGraphsOnPathToEnclosedPatternpath // from the namesOfPatternGraphsOnPathToEnclosedPatternpath of the alternative cases // also build combined lists of matching pattern class type names and nested independents List <string> namesOfPatternGraphsOnPathToEnclosedPatternpath = new List <string>(); List <string> matchingPatternClassTypeNames = new List <string>(); List <Dictionary <PatternGraph, bool> > nestedIndependents = new List <Dictionary <PatternGraph, bool> >(); for (int i = 0; i < alternative.alternativeCases.Length; ++i) { PatternGraph altCase = alternative.alternativeCases[i]; foreach (String name in altCase.patternGraphsOnPathToEnclosedPatternpath) { if (!namesOfPatternGraphsOnPathToEnclosedPatternpath.Contains(name)) { namesOfPatternGraphsOnPathToEnclosedPatternpath.Add(name); } } ExtractNestedIndependents(matchingPatternClassTypeNames, nestedIndependents, matchingPattern, altCase); } // build outermost search program operation, create the list anchor starting its program SearchProgram searchProgram = new SearchProgramOfAlternative( rulePatternClassName, namesOfPatternGraphsOnPathToEnclosedPatternpath, "myMatch", matchingPatternClassTypeNames, nestedIndependents, parallelized); searchProgram.OperationsList = new SearchProgramList(searchProgram); SearchProgramOperation insertionPoint = searchProgram.OperationsList; // initialize task/result-pushdown handling in subpattern matcher InitializeSubpatternMatching initialize = new InitializeSubpatternMatching(InitializeFinalizeSubpatternMatchingType.Normal); insertionPoint = insertionPoint.Append(initialize); // build alternative matching search programs, one per case for (int i = 0; i < alternative.alternativeCases.Length; ++i) { PatternGraph altCase = alternative.alternativeCases[i]; ScheduledSearchPlan scheduledSearchPlan = altCase.schedulesIncludingNegativesAndIndependents[0]; string inlinedPatternClassName = rulePatternClassName; string pathPrefixInInlinedPatternClass = scheduledSearchPlan.PatternGraph.pathPrefix; string unprefixedNameInInlinedPatternClass = scheduledSearchPlan.PatternGraph.name; if (alternative.originalAlternative != null) { inlinedPatternClassName = alternative.originalSubpatternEmbedding.matchingPatternOfEmbeddedGraph.GetType().Name; pathPrefixInInlinedPatternClass = alternative.originalAlternative.pathPrefix + alternative.originalAlternative.name + "_"; unprefixedNameInInlinedPatternClass = alternative.originalAlternative.alternativeCases[i].name; } SearchProgramBodyBuilder builder = new SearchProgramBodyBuilder( SearchProgramType.AlternativeCase, model, rulePatternClassName, null, null, null, altCase, emitProfiling, parallelized, 0 ); AlternativeCaseMatching alternativeCaseMatching = new AlternativeCaseMatching( pathPrefixInInlinedPatternClass, unprefixedNameInInlinedPatternClass, inlinedPatternClassName, builder.wasIndependentInlined(altCase, 0)); alternativeCaseMatching.OperationsList = new SearchProgramList(alternativeCaseMatching); SearchProgramOperation continuationPointAfterAltCase = insertionPoint.Append(alternativeCaseMatching); // at level of the current alt case insertionPoint = alternativeCaseMatching.OperationsList; insertionPoint = insertVariableDeclarations(insertionPoint, altCase); // start building with first operation in scheduled search plan builder.BuildScheduledSearchPlanOperationIntoSearchProgram( 0, insertionPoint); // back to level of alt cases insertionPoint = continuationPointAfterAltCase; // save matches found by alternative case to get clean start for matching next alternative case if (i < alternative.alternativeCases.Length - 1) { NewMatchesListForFollowingMatches newMatchesList = new NewMatchesListForFollowingMatches(true); insertionPoint = insertionPoint.Append(newMatchesList); } } // finalize task/result-pushdown handling in subpattern matcher FinalizeSubpatternMatching finalize = new FinalizeSubpatternMatching(InitializeFinalizeSubpatternMatchingType.Normal); insertionPoint = insertionPoint.Append(finalize); return(searchProgram); }
/// <summary> /// Builds search program from scheduled search plan in pattern graph of the subpattern rule pattern /// </summary> public static SearchProgram BuildSearchProgram( IGraphModel model, LGSPMatchingPattern matchingPattern, bool parallelized, bool emitProfiling) { Debug.Assert(!(matchingPattern is LGSPRulePattern)); PatternGraph patternGraph = matchingPattern.patternGraph; String rulePatternClassName = NamesOfEntities.RulePatternClassName(matchingPattern.name, matchingPattern.PatternGraph.Package, true); SearchProgramBodyBuilder builder = new SearchProgramBodyBuilder( SearchProgramType.Subpattern, model, rulePatternClassName, null, null, null, patternGraph, emitProfiling, parallelized, 0 ); List <String> matchingPatternClassTypeNames = new List <String>(); List <Dictionary <PatternGraph, bool> > nestedIndependents = new List <Dictionary <PatternGraph, bool> >(); ExtractNestedIndependents(matchingPatternClassTypeNames, nestedIndependents, matchingPattern, patternGraph); // build outermost search program operation, create the list anchor starting its program SearchProgram searchProgram = new SearchProgramOfSubpattern( rulePatternClassName, patternGraph.Name, matchingPattern.patternGraph.patternGraphsOnPathToEnclosedPatternpath, "myMatch", builder.wasIndependentInlined(patternGraph, 0), matchingPatternClassTypeNames, nestedIndependents, parallelized); searchProgram.OperationsList = new SearchProgramList(searchProgram); SearchProgramOperation insertionPoint = searchProgram.OperationsList; insertionPoint = insertVariableDeclarations(insertionPoint, patternGraph); // initialize task/result-pushdown handling in subpattern matcher InitializeSubpatternMatching initialize = new InitializeSubpatternMatching(InitializeFinalizeSubpatternMatchingType.Normal); insertionPoint = insertionPoint.Append(initialize); // start building with first operation in scheduled search plan insertionPoint = builder.BuildScheduledSearchPlanOperationIntoSearchProgram( 0, insertionPoint); // finalize task/result-pushdown handling in subpattern matcher FinalizeSubpatternMatching finalize = new FinalizeSubpatternMatching(InitializeFinalizeSubpatternMatchingType.Normal); insertionPoint = insertionPoint.Append(finalize); return(searchProgram); }
/// <summary> /// Builds search program for iterated from scheduled search plan of iterated pattern graph /// </summary> public SearchProgram BuildSearchProgram( IGraphModel model, LGSPMatchingPattern matchingPattern, PatternGraph iter, bool parallelized, bool emitProfiling) { programType = SearchProgramType.Iterated; this.model = model; patternGraphWithNestingPatterns = new Stack<PatternGraph>(); patternGraphWithNestingPatterns.Push(iter); this.parallelized = parallelized; isoSpaceNeverAboveMaxIsoSpace = patternGraphWithNestingPatterns.Peek().maxIsoSpace < (int)LGSPElemFlags.MAX_ISO_SPACE; isNegative = false; isNestedInNegative = false; rulePatternClassName = NamesOfEntities.RulePatternClassName(matchingPattern.name, matchingPattern.PatternGraph.Package, !(matchingPattern is LGSPRulePattern)); this.emitProfiling = emitProfiling; packagePrefixedActionName = null; firstLoopPassed = false; // 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", wasIndependentInlined(iter, indexOfSchedule), 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); ReturnPreventingDummyIteration dummyIteration = new ReturnPreventingDummyIteration(); SearchProgramOperation continuationPointAfterDummyIteration = insertionPoint.Append(dummyIteration); dummyIteration.NestedOperationsList = new SearchProgramList(dummyIteration); insertionPoint = dummyIteration.NestedOperationsList; // start building with first operation in scheduled search plan indexOfSchedule = 0; insertionPoint = BuildScheduledSearchPlanOperationIntoSearchProgram( 0, insertionPoint); insertionPoint = continuationPointAfterDummyIteration; // check whether iteration came to an end (pattern not found (again)) and handle it insertionPoint = insertEndOfIterationHandling(insertionPoint); // finalize task/result-pushdown handling in subpattern matcher for iteration FinalizeSubpatternMatching finalize = new FinalizeSubpatternMatching(InitializeFinalizeSubpatternMatchingType.Iteration); insertionPoint = insertionPoint.Append(finalize); patternGraphWithNestingPatterns.Pop(); return searchProgram; }
/// <summary> /// Generates the search program for the given alternative /// </summary> SearchProgram GenerateSearchProgramAlternative(LGSPMatchingPattern matchingPattern, Alternative alt) { // build pass: build nested program from scheduled search plans of the alternative cases SearchProgramBuilder searchProgramBuilder = new SearchProgramBuilder(); SearchProgram searchProgram = searchProgramBuilder.BuildSearchProgram(model, matchingPattern, alt, false, Profile); #if DUMP_SEARCHPROGRAMS // dump built search program for debugging SourceBuilder builder = new SourceBuilder(CommentSourceCode); searchProgram.Dump(builder); StreamWriter writer = new StreamWriter(matchingPattern.name + "_" + alt.name + "_" + searchProgram.Name + "_built_dump.txt"); writer.Write(builder.ToString()); writer.Close(); #endif // complete pass: complete check operations in all search programs SearchProgramCompleter searchProgramCompleter = new SearchProgramCompleter(); searchProgramCompleter.CompleteCheckOperationsInAllSearchPrograms(searchProgram); #if DUMP_SEARCHPROGRAMS // dump completed search program for debugging builder = new SourceBuilder(CommentSourceCode); searchProgram.Dump(builder); writer = new StreamWriter(matchingPattern.name + "_" + alt.name + "_" + searchProgram.Name + "_completed_dump.txt"); writer.Write(builder.ToString()); writer.Close(); #endif return searchProgram; }
/// <summary> /// Generates the parallelized search program for the given iterated pattern /// </summary> SearchProgram GenerateParallelizedSearchProgramIteratedAsNeeded(LGSPMatchingPattern matchingPattern, PatternGraph iter) { if(matchingPattern.patternGraph.parallelizedSchedule == null) return null; // build pass: build nested program from scheduled search plan of the all pattern SearchProgramBuilder searchProgramBuilder = new SearchProgramBuilder(); SearchProgram searchProgram = searchProgramBuilder.BuildSearchProgram(model, matchingPattern, iter, true, Profile); #if DUMP_SEARCHPROGRAMS // dump built search program for debugging SourceBuilder builder = new SourceBuilder(CommentSourceCode); searchProgram.Dump(builder); StreamWriter writer = new StreamWriter(matchingPattern.name + "_parallelized_" + iter.name + "_" + searchProgram.Name + "_built_dump.txt"); writer.Write(builder.ToString()); writer.Close(); #endif // complete pass: complete check operations in all search programs SearchProgramCompleter searchProgramCompleter = new SearchProgramCompleter(); searchProgramCompleter.CompleteCheckOperationsInAllSearchPrograms(searchProgram); #if DUMP_SEARCHPROGRAMS // dump completed search program for debugging builder = new SourceBuilder(CommentSourceCode); searchProgram.Dump(builder); writer = new StreamWriter(matchingPattern.name + "_parallelized_" + iter.name + "_" + searchProgram.Name + "_completed_dump.txt"); writer.Write(builder.ToString()); writer.Close(); #endif return searchProgram; }
/// <summary> /// Parallelize the scheduled search plan if it is to be parallelized. /// An action to be parallelized is split at the first loop into a header part and a body part, /// all subpatterns and nested patterns to be parallelized are switched to non- is-matched-flag-based isomorphy checking. /// </summary> public void ParallelizeAsNeeded(LGSPMatchingPattern matchingPattern) { if(matchingPattern.patternGraph.branchingFactor < 2) return; if(matchingPattern is LGSPRulePattern) { bool parallelizableLoopFound = false; foreach(SearchOperation so in matchingPattern.patternGraph.schedulesIncludingNegativesAndIndependents[0].Operations) { if(so.Type == SearchOperationType.Lookup || so.Type == SearchOperationType.Incident || so.Type == SearchOperationType.Incoming || so.Type == SearchOperationType.Outgoing || so.Type == SearchOperationType.PickFromStorage || so.Type == SearchOperationType.PickFromStorageDependent || so.Type == SearchOperationType.PickFromIndex || so.Type == SearchOperationType.PickFromIndexDependent) { parallelizableLoopFound = true; break; } } if(parallelizableLoopFound) ParallelizeHeadBody((LGSPRulePattern)matchingPattern); else { matchingPattern.patternGraph.branchingFactor = 1; Console.Error.WriteLine("Warning: " + matchingPattern.patternGraph.Name + " not parallelized as no parallelizable loop was found."); } } else { Parallelize(matchingPattern); } }
/// <summary> /// Generates matcher class head source code for the given alternative into given source builder /// isInitialStatic tells whether the initial static version or a dynamic version after analyze is to be generated. /// </summary> public void GenerateMatcherClassHeadAlternative(SourceBuilder sb, LGSPMatchingPattern matchingPattern, Alternative alternative, bool isInitialStatic) { PatternGraph patternGraph = (PatternGraph)matchingPattern.PatternGraph; String namePrefix = (isInitialStatic ? "" : "Dyn") + "AlternativeAction_"; String className = namePrefix + alternative.pathPrefix+alternative.name; if(patternGraph.Package != null) { sb.AppendFrontFormat("namespace {0}\n", patternGraph.Package); sb.AppendFront("{\n"); sb.Indent(); } sb.AppendFront("public class " + className + " : GRGEN_LGSP.LGSPSubpatternAction\n"); sb.AppendFront("{\n"); sb.Indent(); // class level sb.AppendFront("private " + className + "(GRGEN_LGSP.LGSPActionExecutionEnvironment actionEnv_, " + "Stack<GRGEN_LGSP.LGSPSubpatternAction> openTasks_, GRGEN_LGSP.PatternGraph[] patternGraphs_) {\n"); sb.Indent(); // method body level sb.AppendFront("actionEnv = actionEnv_; openTasks = openTasks_;\n"); // pfadausdruck gebraucht, da das alternative-objekt im pattern graph steckt sb.AppendFront("patternGraphs = patternGraphs_;\n"); sb.Unindent(); // class level sb.AppendFront("}\n\n"); GenerateTasksMemoryPool(sb, className, true, false, matchingPattern.patternGraph.branchingFactor); 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; } foreach (KeyValuePair<string, bool> node in neededNodes) { sb.AppendFront("public GRGEN_LGSP.LGSPNode " + node.Key + ";\n"); } foreach (KeyValuePair<string, bool> edge in neededEdges) { sb.AppendFront("public GRGEN_LGSP.LGSPEdge " + edge.Key + ";\n"); } foreach (KeyValuePair<string, GrGenType> variable in neededVariables) { sb.AppendFront("public " + TypesHelper.TypeName(variable.Value) + " " + variable.Key + ";\n"); } foreach (PatternGraph altCase in alternative.alternativeCases) { GenerateIndependentsMatchObjects(sb, matchingPattern, altCase); } sb.AppendFront("\n"); }
/// <summary> /// Parallelize the scheduled search plan for usage from a parallelized matcher /// (non- is-matched-flag-based isomorphy checking) /// </summary> public void Parallelize(LGSPMatchingPattern matchingPattern) { Debug.Assert(matchingPattern.patternGraph.schedulesIncludingNegativesAndIndependents.Length == 1); ScheduledSearchPlan ssp = matchingPattern.patternGraph.schedulesIncludingNegativesAndIndependents[0]; matchingPattern.patternGraph.parallelizedSchedule = new ScheduledSearchPlan[1]; List<SearchOperation> operations = new List<SearchOperation>(ssp.Operations.Length); for(int i = 0; i < ssp.Operations.Length; ++i) { SearchOperation so = ssp.Operations[i]; SearchOperation clone = (SearchOperation)so.Clone(); clone.Isomorphy.Parallel = true; operations.Add(clone); if(clone.Element is PatternCondition) SetNeedForParallelizedVersion((clone.Element as PatternCondition).ConditionExpression); } ScheduledSearchPlan clonedSsp = new ScheduledSearchPlan( matchingPattern.patternGraph, operations.ToArray(), operations.Count > 0 ? operations[0].CostToEnd : 0); matchingPattern.patternGraph.parallelizedSchedule[0] = clonedSsp; ParallelizeNegativeIndependent(clonedSsp); ParallelizeAlternativeIterated(matchingPattern.patternGraph); ParallelizeYielding(matchingPattern.patternGraph); }
/// <summary> /// Generates match objects of independents (one pre-allocated is part of action class) /// </summary> private void GenerateIndependentsMatchObjects(SourceBuilder sb, LGSPMatchingPattern matchingPatternClass, PatternGraph patternGraph) { if (patternGraph.nestedIndependents != null) { foreach (KeyValuePair<PatternGraph, PatternGraph> nestedIndependent in patternGraph.nestedIndependents) { if(nestedIndependent.Key.originalPatternGraph != null) { sb.AppendFrontFormat("private {0} {1} = new {0}();", nestedIndependent.Key.originalSubpatternEmbedding.matchingPatternOfEmbeddedGraph.GetType().Name + "." + NamesOfEntities.MatchClassName(nestedIndependent.Key.originalPatternGraph.pathPrefix + nestedIndependent.Key.originalPatternGraph.name), NamesOfEntities.MatchedIndependentVariable(nestedIndependent.Key.pathPrefix + nestedIndependent.Key.name)); } else { sb.AppendFrontFormat("private {0} {1} = new {0}();", matchingPatternClass.GetType().Name + "." + NamesOfEntities.MatchClassName(nestedIndependent.Key.pathPrefix + nestedIndependent.Key.name), NamesOfEntities.MatchedIndependentVariable(nestedIndependent.Key.pathPrefix + nestedIndependent.Key.name)); } } } foreach (PatternGraph idpt in patternGraph.independentPatternGraphsPlusInlined) { GenerateIndependentsMatchObjects(sb, matchingPatternClass, idpt); } }
/// <summary> /// Generates the action interface plus action implementation including the matcher source code /// for the given rule pattern into the given source builder /// </summary> public void GenerateActionAndMatcher(SourceBuilder sb, LGSPMatchingPattern matchingPattern, bool isInitialStatic) { // generate the search program out of the schedule(s) within the pattern graph of the rule SearchProgram searchProgram = GenerateSearchProgram(matchingPattern); // generate the parallelized search program out of the parallelized schedule(s) within the pattern graph of the rule SearchProgram searchProgramParallelized = GenerateParallelizedSearchProgramAsNeeded(matchingPattern); // emit matcher class head, body, tail; body is source code representing search program if(matchingPattern is LGSPRulePattern) { GenerateActionInterface(sb, (LGSPRulePattern)matchingPattern); // generate the exact action interface GenerateMatcherClassHeadAction(sb, (LGSPRulePattern)matchingPattern, isInitialStatic, searchProgram); searchProgram.Emit(sb); if(searchProgramParallelized != null) searchProgramParallelized.Emit(sb); GenerateActionImplementation(sb, (LGSPRulePattern)matchingPattern); GenerateMatcherClassTail(sb, matchingPattern.PatternGraph.Package != null); } else { GenerateMatcherClassHeadSubpattern(sb, matchingPattern, isInitialStatic); searchProgram.Emit(sb); if(searchProgramParallelized != null) searchProgramParallelized.Emit(sb); GenerateMatcherClassTail(sb, matchingPattern.PatternGraph.Package != null); } // finally generate matcher source for all the nested alternatives or iterateds of the pattern graph // nested inside the alternatives,iterateds,negatives,independents foreach(Alternative alt in matchingPattern.patternGraph.alternativesPlusInlined) { GenerateActionAndMatcherOfAlternative(sb, matchingPattern, alt, isInitialStatic); } foreach (Iterated iter in matchingPattern.patternGraph.iteratedsPlusInlined) { GenerateActionAndMatcherOfIterated(sb, matchingPattern, iter.iteratedPattern, isInitialStatic); } foreach (PatternGraph neg in matchingPattern.patternGraph.negativePatternGraphsPlusInlined) { GenerateActionAndMatcherOfNestedPatterns(sb, matchingPattern, neg, isInitialStatic); } foreach (PatternGraph idpt in matchingPattern.patternGraph.independentPatternGraphsPlusInlined) { GenerateActionAndMatcherOfNestedPatterns(sb, matchingPattern, idpt, isInitialStatic); } }
/// <summary> /// Instantiates a new pattern graph embedding object as a copy from an original embedding, used for inlining. /// </summary> /// <param name="original">The original embedding to be copy constructed.</param> /// <param name="inlinedSubpatternEmbedding">The embedding which just gets inlined.</param> /// <param name="newHost">The pattern graph the new embedding will be contained in.</param> /// <param name="nameSuffix">The suffix to be added to the name of the embedding (to avoid name collisions).</param> /// Elements were already copied in the containing pattern(s), their copies have to be reused here. public PatternGraphEmbedding(PatternGraphEmbedding original, PatternGraphEmbedding inlinedSubpatternEmbedding, PatternGraph newHost, String nameSuffix) { PointOfDefinition = newHost; name = original.name + nameSuffix; originalSubpatternEmbedding = inlinedSubpatternEmbedding; matchingPatternOfEmbeddedGraph = original.matchingPatternOfEmbeddedGraph; annotations = original.annotations; connections = new Expression[original.connections.Length]; for(int i = 0; i < original.connections.Length; ++i) { connections[i] = original.connections[i].Copy(nameSuffix); } yields = new String[original.yields.Length]; for(int i = 0; i < original.yields.Length; ++i) { yields[i] = original.yields[i] + nameSuffix; } neededNodes = new String[original.neededNodes.Length]; for(int i = 0; i < original.neededNodes.Length; ++i) { neededNodes[i] = original.neededNodes[i] + nameSuffix; } neededEdges = new String[original.neededEdges.Length]; for(int i = 0; i < original.neededEdges.Length; ++i) { neededEdges[i] = original.neededEdges[i] + nameSuffix; } neededVariables = new String[original.neededVariables.Length]; for(int i = 0; i < original.neededVariables.Length; ++i) { neededVariables[i] = original.neededVariables[i] + nameSuffix; } neededVariableTypes = (VarType[])original.neededVariableTypes.Clone(); originalEmbedding = original; }
/// <summary> /// Builds search program from scheduled search plan in pattern graph of the subpattern rule pattern /// </summary> public SearchProgram BuildSearchProgram( IGraphModel model, LGSPMatchingPattern matchingPattern, bool parallelized, bool emitProfiling) { Debug.Assert(!(matchingPattern is LGSPRulePattern)); PatternGraph patternGraph = matchingPattern.patternGraph; programType = SearchProgramType.Subpattern; this.model = model; patternGraphWithNestingPatterns = new Stack<PatternGraph>(); patternGraphWithNestingPatterns.Push(patternGraph); this.parallelized = parallelized; isoSpaceNeverAboveMaxIsoSpace = patternGraphWithNestingPatterns.Peek().maxIsoSpace < (int)LGSPElemFlags.MAX_ISO_SPACE; isNegative = false; isNestedInNegative = false; rulePatternClassName = NamesOfEntities.RulePatternClassName(matchingPattern.name, matchingPattern.PatternGraph.Package, true); this.emitProfiling = emitProfiling; packagePrefixedActionName = null; firstLoopPassed = false; // build outermost search program operation, create the list anchor starting its program SearchProgram searchProgram = new SearchProgramOfSubpattern( rulePatternClassName, patternGraph.Name, matchingPattern.patternGraph.patternGraphsOnPathToEnclosedPatternpath, "myMatch", wasIndependentInlined(patternGraph, indexOfSchedule), 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 indexOfSchedule = 0; insertionPoint = BuildScheduledSearchPlanOperationIntoSearchProgram( 0, insertionPoint); // finalize task/result-pushdown handling in subpattern matcher FinalizeSubpatternMatching finalize = new FinalizeSubpatternMatching(InitializeFinalizeSubpatternMatchingType.Normal); insertionPoint = insertionPoint.Append(finalize); patternGraphWithNestingPatterns.Pop(); return searchProgram; }