/// <summary> /// Copy constructor helper. /// </summary> /// <param name="dataSource">The LGSPGraph object to get the data from</param> /// <param name="newName">Name of the copied graph.</param> /// <param name="oldToNewMap">A map of the old elements to the new elements after cloning, /// just forget about it if you don't need it.</param> private void Copy(LGSPGraph dataSource, String newName, out IDictionary<IGraphElement, IGraphElement> oldToNewMap) { model = dataSource.model; name = newName; InitializeGraph(); model.CreateAndBindIndexSet(this); if(dataSource.backend != null) { backend = dataSource.backend; modelAssemblyName = dataSource.modelAssemblyName; } oldToNewMap = new Dictionary<IGraphElement, IGraphElement>(); for(int i = 0; i < dataSource.nodesByTypeHeads.Length; i++) { for(LGSPNode head = dataSource.nodesByTypeHeads[i], node = head.lgspTypePrev; node != head; node = node.lgspTypePrev) { LGSPNode newNode = (LGSPNode) node.Clone(); AddNodeWithoutEvents(newNode, node.lgspType.TypeID); oldToNewMap[node] = newNode; } } for(int i = 0; i < dataSource.edgesByTypeHeads.Length; i++) { for(LGSPEdge head = dataSource.edgesByTypeHeads[i], edge = head.lgspTypePrev; edge != head; edge = edge.lgspTypePrev) { LGSPEdge newEdge = (LGSPEdge) edge.Clone((INode) oldToNewMap[edge.lgspSource], (INode) oldToNewMap[edge.lgspTarget]); AddEdgeWithoutEvents(newEdge, newEdge.lgspType.TypeID); oldToNewMap[edge] = newEdge; } } /* TODO: remove when cloning of graph variables was implemented * foreach(KeyValuePair<IGraphElement, LinkedList<Variable>> kvp in dataSource.ElementMap) { IGraphElement newElem = oldToNewMap[kvp.Key]; foreach(Variable var in kvp.Value) SetVariableValue(var.Name, newElem); }*/ model.FillIndexSetAsClone(this, dataSource, oldToNewMap); statistics = new LGSPGraphStatistics(this.Model); statistics.Copy(dataSource); }
/// <summary> /// Does action-backend dependent stuff. /// </summary> /// <param name="args">Any kind of parameters for the stuff to do</param> public override void Custom(params object[] args) { if(args.Length == 0) goto invalidCommand; switch((String) args[0]) { case "gen_searchplan": { if(graph.statistics.edgeCounts == null) throw new ArgumentException("Graph not analyzed yet!\nPlease execute 'custom graph analyze'!"); LGSPAction[] oldActions; if(args.Length == 1) { oldActions = new LGSPAction[actions.Count]; int i = 0; foreach(LGSPAction action in actions.Values) { oldActions[i] = action; ++i; } } else { oldActions = new LGSPAction[args.Length - 1]; for(int i = 0; i < oldActions.Length; i++) { oldActions[i] = (LGSPAction)GetAction((String)args[i + 1]); if(oldActions[i] == null) throw new ArgumentException("'" + (String)args[i + 1] + "' is not the name of an action!\n" + "Please use 'show actions' to get a list of the available names."); } } int startticks = Environment.TickCount; matcherGenerator.LazyNegativeIndependentConditionEvaluation = LazyNIC; matcherGenerator.InlineIndependents = InlineIndependents; matcherGenerator.Profile = Profile; LGSPAction[] newActions = matcherGenerator.GenerateActions(graph, modelAssemblyName, actionsAssemblyName, oldActions); int stopticks = Environment.TickCount; Console.Write("Searchplans for actions "); for(int i = 0; i < oldActions.Length; i++) { actions[oldActions[i].Name] = newActions[i]; if(i != 0) Console.Write(", "); Console.Write("'" + oldActions[i].Name + "'"); } Console.WriteLine(" generated in " + (stopticks - startticks) + " ms."); return; } case "dump_sourcecode": if(args.Length != 2) throw new ArgumentException("Usage: dump_sourcecode <bool>\n" + "If <bool> == true, C# files will be dumped for new searchplans."); if(!bool.TryParse((String) args[1], out matcherGenerator.DumpDynSourceCode)) throw new ArgumentException("Illegal bool value specified: \"" + (String) args[1] + "\""); return; case "dump_searchplan": if(args.Length != 2) throw new ArgumentException("Usage: dump_searchplan <bool>\n" + "If <bool> == true, VCG and TXT files will be dumped for new searchplans."); if(!bool.TryParse((String) args[1], out matcherGenerator.DumpSearchPlan)) throw new ArgumentException("Illegal bool value specified: \"" + (String) args[1] + "\""); return; case "explain": { if(args.Length != 2) throw new ArgumentException("Usage: explain <name>\n" + "Explains the searchplan of the given action."); LGSPAction action = (LGSPAction)GetAction((String)args[1]); if(action == null) throw new ArgumentException("'" + (String)args[1] + "' is not the name of an action!\n" + "Please use 'show actions' to get a list of the available names."); if(action.patternGraph.schedules[0] == null) { LGSPGraphStatistics graphStatistics = null; if(StatisticsPath != null) { Console.WriteLine("static search plans from " + StatisticsPath); graphStatistics = new LGSPGraphStatistics(graph.Model); graphStatistics.Parse(StatisticsPath); } else Console.WriteLine("static search plans"); LGSPMatcherGenerator matcherGen = new LGSPMatcherGenerator(graph.Model); matcherGen.FillInStaticSearchPlans(graphStatistics, InlineIndependents, action); } SourceBuilder sb = new SourceBuilder(); foreach(KeyValuePair<LGSPMatchingPattern, LGSPMatchingPattern> usedSubpattern in action.rulePattern.patternGraph.usedSubpatterns) { usedSubpattern.Key.patternGraph.Explain(sb, graph.Model); } action.patternGraph.Explain(sb, graph.Model); Console.WriteLine(sb.ToString()); return; } } invalidCommand: throw new ArgumentException("Possible commands:\n" + "- gen_searchplan: Generates a new searchplan for a given action\n" + " depending on a previous graph analysis\n" + "- explain: explains the searchplan in use for a given action\n" + "- dump_sourcecode: Sets dumping of C# files for new searchplans\n" + "- dump_searchplan: Sets dumping of VCG and TXT files of new\n" + " searchplans (with some intermediate steps)"); }
/// <summary> /// Constructs an LGSPGraph object without initializing it. /// </summary> /// <param name="grname">The name for the graph.</param> protected LGSPGraph(String grname) { graphID = graphIDSource; ++graphIDSource; name = grname; statistics = new LGSPGraphStatistics(this.Model); }
private static void CreatePlanNodeAndLookupPlanEdge(PatternEdge edge, int elemId, LGSPGraphStatistics graphStatistics, PatternGraph patternGraph, bool isNegativeOrIndependent, bool isSubpatternLike, PlanNode planRoot, float zeroCost, IDictionary<PatternNode, PatternNode> originalToInlinedIndependent, IDictionary<PatternElement, SetValueType> presetsFromIndependentInlining, out bool isPreset, out PlanNode planNode, out PlanEdge rootToNodePlanEdge) { float cost; SearchOperationType searchOperationType; if(edge.DefToBeYieldedTo) { cost = zeroCost; isPreset = true; searchOperationType = SearchOperationType.DefToBeYieldedTo; } else if(edge.PointOfDefinition == null) { cost = zeroCost; isPreset = true; searchOperationType = isSubpatternLike ? SearchOperationType.SubPreset : SearchOperationType.ActionPreset; } else if(edge.PointOfDefinition != patternGraph && edge.OriginalIndependentElement == null) { cost = zeroCost; isPreset = true; searchOperationType = isNegativeOrIndependent ? SearchOperationType.NegIdptPreset : SearchOperationType.SubPreset; } else if(presetsFromIndependentInlining.ContainsKey(edge)) { cost = zeroCost; isPreset = true; searchOperationType = SearchOperationType.NegIdptPreset; edge.PresetBecauseOfIndependentInlining = true; } else if(edge.Storage != null) { if(edge.GetPatternElementThisElementDependsOnOutsideOfGraphConnectedness() != null) { cost = zeroCost; isPreset = false; searchOperationType = SearchOperationType.Void; // the element we depend on is needed, so there is no lookup like operation } else { cost = zeroCost; isPreset = false; searchOperationType = SearchOperationType.PickFromStorage; // pick from storage instead of lookup from graph } } else if(edge.IndexAccess != null) { if(edge.GetPatternElementThisElementDependsOnOutsideOfGraphConnectedness() != null) { cost = zeroCost; isPreset = false; searchOperationType = SearchOperationType.Void; // the element we depend on is needed, so there is no lookup like operation } else { cost = zeroCost; isPreset = false; searchOperationType = SearchOperationType.PickFromIndex; // pick from index instead of lookup from graph } } else if(edge.NameLookup != null) { if(edge.GetPatternElementThisElementDependsOnOutsideOfGraphConnectedness() != null) { cost = zeroCost; isPreset = false; searchOperationType = SearchOperationType.Void; // the element we depend on is needed, so there is no lookup like operation } else { cost = zeroCost; isPreset = false; searchOperationType = SearchOperationType.PickByName; // pick by name instead of lookup from graph } } else if(edge.UniqueLookup != null) { if(edge.GetPatternElementThisElementDependsOnOutsideOfGraphConnectedness() != null) { cost = zeroCost; isPreset = false; searchOperationType = SearchOperationType.Void; // the element we depend on is needed, so there is no lookup like operation } else { cost = zeroCost; isPreset = false; searchOperationType = SearchOperationType.PickByUnique; // pick by unique instead of lookup from graph } } else if(edge.ElementBeforeCasting != null) { cost = zeroCost; isPreset = false; searchOperationType = SearchOperationType.Void; // the element before casting is needed, so there is no lookup like operation } else { cost = graphStatistics.edgeCounts[edge.TypeID]; cost = CostIncreaseForInlinedIndependent(edge, cost); isPreset = false; searchOperationType = SearchOperationType.Lookup; } PatternNode source = GetSourcePlusInlined(edge, patternGraph, originalToInlinedIndependent); PatternNode target = GetTargetPlusInlined(edge, patternGraph, originalToInlinedIndependent); planNode = new PlanNode(edge, elemId, isPreset, source != null ? source.TempPlanMapping : null, target != null ? target.TempPlanMapping : null); rootToNodePlanEdge = null; if(searchOperationType != SearchOperationType.Void) rootToNodePlanEdge = new PlanEdge(searchOperationType, planRoot, planNode, cost); }
private void CreateSourceTargetIncomingOutgoingPlanEdges(PatternEdge edge, PlanNode planNode, List<PlanEdge> planEdges, IDictionary<PatternNode, PatternNode> originalToInlinedIndependent, LGSPGraphStatistics graphStatistics, PatternGraph patternGraph, bool isPreset, float zeroCost) { // only add implicit source operation if edge source is needed and the edge source is // not a preset node and not a storage node and not an index node and not a cast node PatternNode source = GetSourcePlusInlined(edge, patternGraph, originalToInlinedIndependent); if(source != null && !source.TempPlanMapping.IsPreset && source.Storage == null && source.IndexAccess == null && source.NameLookup == null && source.UniqueLookup == null && source.ElementBeforeCasting == null) { SearchOperationType operation = edge.fixedDirection ? SearchOperationType.ImplicitSource : SearchOperationType.Implicit; PlanEdge implSrcPlanEdge = new PlanEdge(operation, planNode, source.TempPlanMapping, zeroCost); planEdges.Add(implSrcPlanEdge); source.TempPlanMapping.IncomingEdges.Add(implSrcPlanEdge); } // only add implicit target operation if edge target is needed and the edge target is // not a preset node and not a storage node and not an index node and not a cast node PatternNode target = GetTargetPlusInlined(edge, patternGraph, originalToInlinedIndependent); if(target != null && !target.TempPlanMapping.IsPreset && target.Storage == null && target.IndexAccess == null && target.NameLookup == null && target.UniqueLookup == null && target.ElementBeforeCasting == null) { SearchOperationType operation = edge.fixedDirection ? SearchOperationType.ImplicitTarget : SearchOperationType.Implicit; PlanEdge implTgtPlanEdge = new PlanEdge(operation, planNode, target.TempPlanMapping, zeroCost); planEdges.Add(implTgtPlanEdge); target.TempPlanMapping.IncomingEdges.Add(implTgtPlanEdge); } // edge must only be reachable from other nodes if it's not a preset and not storage determined and not index determined and not a cast if(!isPreset && edge.Storage == null && edge.IndexAccess == null && edge.NameLookup == null && edge.UniqueLookup == null && edge.ElementBeforeCasting == null) { // no outgoing on source node if no source if(source != null) { int targetTypeID; if(target != null) targetTypeID = target.TypeID; else targetTypeID = model.NodeModel.RootType.TypeID; // cost of walking along edge #if MONO_MULTIDIMARRAY_WORKAROUND float normCost = graphStatistics.vstructs[((source.TypeID * graphStatistics.dim1size + edge.TypeID) * graphStatistics.dim2size + targetTypeID) * 2 + (int)LGSPDirection.Out]; if(!edge.fixedDirection) { normCost += graphStatistics.vstructs[((source.TypeID * graphStatistics.dim1size + edge.TypeID) * graphStatistics.dim2size + targetTypeID) * 2 + (int)LGSPDirection.In]; } #else float normCost = graph.statistics.vstructs[source.TypeID, edge.TypeID, targetTypeID, (int) LGSPDirection.Out]; if (!edge.fixedDirection) { normCost += graph.statistics.vstructs[source.TypeID, edge.TypeID, targetTypeID, (int) LGSPDirection.In]; } #endif if(graphStatistics.nodeCounts[source.TypeID] != 0) normCost /= graphStatistics.nodeCounts[source.TypeID]; normCost = CostIncreaseForInlinedIndependent(edge, normCost); SearchOperationType operation = edge.fixedDirection ? SearchOperationType.Outgoing : SearchOperationType.Incident; PlanEdge outPlanEdge = new PlanEdge(operation, source.TempPlanMapping, planNode, normCost); planEdges.Add(outPlanEdge); planNode.IncomingEdges.Add(outPlanEdge); } // no incoming on target node if no target if(target != null) { int sourceTypeID; if(source != null) sourceTypeID = source.TypeID; else sourceTypeID = model.NodeModel.RootType.TypeID; // cost of walking in opposite direction of edge #if MONO_MULTIDIMARRAY_WORKAROUND float revCost = graphStatistics.vstructs[((target.TypeID * graphStatistics.dim1size + edge.TypeID) * graphStatistics.dim2size + sourceTypeID) * 2 + (int)LGSPDirection.In]; if(!edge.fixedDirection) { revCost += graphStatistics.vstructs[((target.TypeID * graphStatistics.dim1size + edge.TypeID) * graphStatistics.dim2size + sourceTypeID) * 2 + (int)LGSPDirection.Out]; } #else float revCost = graph.statistics.vstructs[target.TypeID, edge.TypeID, sourceTypeID, (int) LGSPDirection.In]; if (!edge.fixedDirection) { revCost += graph.statistics.vstructs[target.TypeID, edge.TypeID, sourceTypeID, (int) LGSPDirection.Out]; } #endif if(graphStatistics.nodeCounts[target.TypeID] != 0) revCost /= graphStatistics.nodeCounts[target.TypeID]; revCost = CostIncreaseForInlinedIndependent(edge, revCost); SearchOperationType operation = edge.fixedDirection ? SearchOperationType.Incoming : SearchOperationType.Incident; PlanEdge inPlanEdge = new PlanEdge(operation, target.TempPlanMapping, planNode, revCost); planEdges.Add(inPlanEdge); planNode.IncomingEdges.Add(inPlanEdge); } } }
/// <summary> /// Do the static search planning again so we can explain the search plan /// </summary> public void FillInStaticSearchPlans(LGSPGraphStatistics graphStatistics, bool inlineIndependents, params LGSPAction[] actions) { if(actions.Length == 0) throw new ArgumentException("No actions provided!"); // use domain of dictionary as set with rulepatterns of the subpatterns of the actions, get them from pattern graph Dictionary<LGSPMatchingPattern, LGSPMatchingPattern> subpatternMatchingPatterns = new Dictionary<LGSPMatchingPattern, LGSPMatchingPattern>(); foreach(LGSPAction action in actions) { foreach(KeyValuePair<LGSPMatchingPattern, LGSPMatchingPattern> usedSubpattern in action.rulePattern.patternGraph.usedSubpatterns) { subpatternMatchingPatterns[usedSubpattern.Key] = usedSubpattern.Value; } } // build search plans for the subpatterns foreach(KeyValuePair<LGSPMatchingPattern, LGSPMatchingPattern> subpatternMatchingPattern in subpatternMatchingPatterns) { LGSPMatchingPattern smp = subpatternMatchingPattern.Key; LGSPGrGen.GenerateScheduledSearchPlans(smp.patternGraph, graphStatistics, this, true, false, null); MergeNegativeAndIndependentSchedulesIntoEnclosingSchedules(smp.patternGraph); ParallelizeAsNeeded(smp); } // build search plans code for actions foreach(LGSPAction action in actions) { LGSPGrGen.GenerateScheduledSearchPlans(action.rulePattern.patternGraph, graphStatistics, this, false, false, null); MergeNegativeAndIndependentSchedulesIntoEnclosingSchedules(action.rulePattern.patternGraph); ParallelizeAsNeeded(action.rulePattern); } }
/// <summary> /// Generate plan graph for given pattern graph with costs from the analyzed host graph. /// Plan graph contains nodes representing the pattern elements (nodes and edges) /// and edges representing the matching operations to get the elements by. /// Edges in plan graph are given in the nodes by incoming list, as needed for MSA computation. /// </summary> public PlanGraph GeneratePlanGraph(LGSPGraphStatistics graphStatistics, PatternGraph patternGraph, bool isNegativeOrIndependent, bool isSubpatternLike, IDictionary<PatternElement, SetValueType> presetsFromIndependentInlining) { // // If you change this method, chances are high you also want to change GenerateStaticPlanGraph in LGSPGrGen // look there for version without ifdef junk // todo: unify it with GenerateStaticPlanGraph in LGSPGrGen // // Create root node // Create plan graph nodes for all pattern graph nodes and all pattern graph edges // Create "lookup" plan graph edge from root node to each plan graph node // Create "implicit source" plan graph edge from each plan graph node originating with a pattern edge // to the plan graph node created by the source node of the pattern graph edge // Create "implicit target" plan graph edge from each plan graph node originating with a pattern edge // to the plan graph node created by the target node of the pattern graph edge // Create "incoming" plan graph edge from each plan graph node originating with a pattern node // to a plan graph node created by one of the incoming edges of the pattern node // Create "outgoing" plan graph edge from each plan graph node originating with a pattern node // to a plan graph node created by one of the outgoing edges of the pattern node // Ensured: there's no plan graph edge with a preset element as target besides the lookup, // so presets are only search operation sources // Create "pick from storage" plan graph edge for plan graph nodes which are to be picked from a storage, // from root node on, instead of lookup, no other plan graph edge having this node as target // Create "pick from storage attribute" plan graph edge from storage attribute owner to storage picking result, // no lookup, no other plan graph edge having this node as target // Create "map" by storage plan graph edge from accessor to storage mapping result // no lookup, no other plan graph edge having this node as target // Create "pick from index" plan graph edge for plan graph nodes which are to be picked from an index, // from root node on, instead of lookup, no other plan graph edge having this node as target // Create "pick from index depending" plan graph edge from node the index expressions depend on, // no lookup, no other plan graph edge having this node as target // Create "cast" plan graph edge from element before casting to cast result, // no lookup, no other plan graph edge having this node as target int numNodes = patternGraph.nodesPlusInlined.Length; if(InlineIndependents && !isNegativeOrIndependent) numNodes += LGSPMatcherGenerator.NumNodesInIndependentsMatchedThere(patternGraph); int numEdges = patternGraph.edgesPlusInlined.Length; if(InlineIndependents && !isNegativeOrIndependent) numEdges += LGSPMatcherGenerator.NumEdgesInIndependentsMatchedThere(patternGraph); PlanNode[] planNodes = new PlanNode[numNodes + numEdges]; List<PlanEdge> planEdges = new List<PlanEdge>(numNodes + 5 * numEdges); // upper bound for num of edges (lookup nodes + lookup edges + impl. tgt + impl. src + incoming + outgoing) Dictionary<PatternNode, PatternNode> originalToInlinedIndependent = new Dictionary<PatternNode, PatternNode>(); int nodesIndex = 0; float zeroCost = 1; PlanNode planRoot = new PlanNode("root"); // create plan nodes and lookup plan edges for all pattern graph nodes for(int i = 0; i < patternGraph.nodesPlusInlined.Length; i++) { PatternNode node = patternGraph.nodesPlusInlined[i]; PlanNode planNode; PlanEdge rootToNodePlanEdge; CreatePlanNodeAndLookupPlanEdge(node, i + 1, graphStatistics, patternGraph, isNegativeOrIndependent, isSubpatternLike, planRoot, zeroCost, originalToInlinedIndependent, presetsFromIndependentInlining, out planNode, out rootToNodePlanEdge); planNodes[nodesIndex] = planNode; if(rootToNodePlanEdge != null) { planEdges.Add(rootToNodePlanEdge); planNode.IncomingEdges.Add(rootToNodePlanEdge); } node.TempPlanMapping = planNode; ++nodesIndex; } if(InlineIndependents && !isNegativeOrIndependent) // independent inlining only if not in negative/independent { foreach(PatternGraph independent in patternGraph.independentPatternGraphsPlusInlined) { foreach(PatternNode nodeOriginal in LGSPMatcherGenerator.NodesInIndependentMatchedThere(independent)) { PatternNode node = new PatternNode(nodeOriginal, "_inlined_" + independent.name); originalToInlinedIndependent.Add(nodeOriginal, node); PlanNode planNode; PlanEdge rootToNodePlanEdge; CreatePlanNodeAndLookupPlanEdge(node, -1, graphStatistics, patternGraph, isNegativeOrIndependent, isSubpatternLike, planRoot, zeroCost, originalToInlinedIndependent, presetsFromIndependentInlining, out planNode, out rootToNodePlanEdge); planNodes[nodesIndex] = planNode; if(rootToNodePlanEdge != null) { planEdges.Add(rootToNodePlanEdge); planNode.IncomingEdges.Add(rootToNodePlanEdge); } node.TempPlanMapping = planNode; ++nodesIndex; } } } // create plan nodes and lookup plus incidence handling plan edges for all pattern graph edges for(int i = 0; i < patternGraph.edgesPlusInlined.Length; ++i) { PatternEdge edge = patternGraph.edgesPlusInlined[i]; bool isPreset; PlanNode planNode; PlanEdge rootToNodePlanEdge; CreatePlanNodeAndLookupPlanEdge(edge, i + 1, graphStatistics, patternGraph, isNegativeOrIndependent, isSubpatternLike, planRoot, zeroCost, originalToInlinedIndependent, presetsFromIndependentInlining, out isPreset, out planNode, out rootToNodePlanEdge); planNodes[nodesIndex] = planNode; if(rootToNodePlanEdge != null) { planEdges.Add(rootToNodePlanEdge); planNode.IncomingEdges.Add(rootToNodePlanEdge); } CreateSourceTargetIncomingOutgoingPlanEdges(edge, planNode, planEdges, originalToInlinedIndependent, graphStatistics, patternGraph, isPreset, zeroCost); edge.TempPlanMapping = planNode; ++nodesIndex; } if(InlineIndependents && !isNegativeOrIndependent) // independent inlining only if not in negative/independent { foreach(PatternGraph independent in patternGraph.independentPatternGraphsPlusInlined) { foreach(PatternEdge edgeOriginal in LGSPMatcherGenerator.EdgesInIndependentMatchedThere(independent)) { PatternEdge edge = new PatternEdge(edgeOriginal, "_inlined_" + independent.name); bool isPreset; PlanNode planNode; PlanEdge rootToNodePlanEdge; CreatePlanNodeAndLookupPlanEdge(edge, -1, graphStatistics, patternGraph, isNegativeOrIndependent, isSubpatternLike, planRoot, zeroCost, originalToInlinedIndependent, presetsFromIndependentInlining, out isPreset, out planNode, out rootToNodePlanEdge); planNodes[nodesIndex] = planNode; if(rootToNodePlanEdge != null) { planEdges.Add(rootToNodePlanEdge); planNode.IncomingEdges.Add(rootToNodePlanEdge); } CreateSourceTargetIncomingOutgoingPlanEdges(edge, planNode, planEdges, originalToInlinedIndependent, graphStatistics, patternGraph, isPreset, zeroCost); edge.TempPlanMapping = planNode; ++nodesIndex; } } } //////////////////////////////////////////////////////////////////////////// // second run handling dependent storage and index picking (can't be done in first run due to dependencies between elements) // create map/pick/cast/assign plan edges for all pattern graph nodes for(int i = 0; i < patternGraph.nodesPlusInlined.Length; ++i) { PatternNode node = patternGraph.nodesPlusInlined[i]; if(node.PointOfDefinition == patternGraph && !presetsFromIndependentInlining.ContainsKey(node)) CreatePickMapCastAssignPlanEdges(node, planEdges, zeroCost); } // create map/pick/cast/assign plan edges for all pattern graph edges for(int i = 0; i < patternGraph.edgesPlusInlined.Length; ++i) { PatternEdge edge = patternGraph.edgesPlusInlined[i]; if(edge.PointOfDefinition == patternGraph && !presetsFromIndependentInlining.ContainsKey(edge)) CreatePickMapCastAssignPlanEdges(edge, planEdges, zeroCost); } return new PlanGraph(planRoot, planNodes, planEdges.ToArray()); }
/// <summary> /// Generates scheduled search plans needed for matcher code generation for action compilation /// out of static schedule information given by rulePattern elements, /// or out of statistics stemming from loading previously serialized statistics /// utilizing code of the lgsp matcher generator. /// The scheduled search plans are added to the main and the nested pattern graphs. /// </summary> internal static void GenerateScheduledSearchPlans(PatternGraph patternGraph, LGSPGraphStatistics graphStatistics, LGSPMatcherGenerator matcherGen, bool isSubpatternLike, bool isNegativeOrIndependent, ScheduledSearchPlan nestingScheduledSearchPlan) { for(int i=0; i<patternGraph.schedules.Length; ++i) { patternGraph.AdaptToMaybeNull(i); if(matcherGen.Profile) LGSPMatcherGenerator.SetNeedForProfiling(patternGraph); PlanGraph planGraph; if(graphStatistics != null) planGraph = matcherGen.GeneratePlanGraph(graphStatistics, patternGraph, isNegativeOrIndependent, isSubpatternLike, LGSPMatcherGenerator.ExtractOwnElements(nestingScheduledSearchPlan, patternGraph)); else planGraph = GenerateStaticPlanGraph(patternGraph, isNegativeOrIndependent, isSubpatternLike, matcherGen.InlineIndependents, LGSPMatcherGenerator.ExtractOwnElements(nestingScheduledSearchPlan, patternGraph)); matcherGen.MarkMinimumSpanningArborescence(planGraph, patternGraph.name); SearchPlanGraph searchPlanGraph = matcherGen.GenerateSearchPlanGraph(planGraph); ScheduledSearchPlan scheduledSearchPlan = matcherGen.ScheduleSearchPlan( searchPlanGraph, patternGraph, isNegativeOrIndependent); matcherGen.AppendHomomorphyInformation(scheduledSearchPlan); patternGraph.schedules[i] = scheduledSearchPlan; patternGraph.RevertMaybeNullAdaption(i); foreach(PatternGraph neg in patternGraph.negativePatternGraphsPlusInlined) { GenerateScheduledSearchPlans(neg, graphStatistics, matcherGen, isSubpatternLike, true, null); } foreach(PatternGraph idpt in patternGraph.independentPatternGraphsPlusInlined) { GenerateScheduledSearchPlans(idpt, graphStatistics, matcherGen, isSubpatternLike, true, patternGraph.schedules[i]); } foreach(Alternative alt in patternGraph.alternativesPlusInlined) { foreach(PatternGraph altCase in alt.alternativeCases) { GenerateScheduledSearchPlans(altCase, graphStatistics, matcherGen, true, false, null); } } foreach(Iterated iter in patternGraph.iteratedsPlusInlined) { GenerateScheduledSearchPlans(iter.iteratedPattern, graphStatistics, matcherGen, true, false, null); } } }
private void GenerateAndInsertMatcherSourceCode(IGraphModel model, String actionsName, String unitName, string externalActionsExtensionFilename, LGSPRuleAndMatchingPatterns ruleAndMatchingPatterns, LGSPSequenceGenerator seqGen, bool isAutoGeneratedFilterExisting, bool isExternalFilterFunctionExisting, LGSPGraphStatistics graphStatistics, string statisticsPath, SourceBuilder externalSource, SourceBuilder source) { // analyze the matching patterns, inline the subpatterns when expected to be benefitial // the analyzer must be run before the matcher generation AnalyzeAndInlineMatchingPatterns((flags & ProcessSpecFlags.Noinline) == 0, ruleAndMatchingPatterns); LGSPMatcherGenerator matcherGen = new LGSPMatcherGenerator(model); if((flags & ProcessSpecFlags.KeepGeneratedFiles) != 0) matcherGen.CommentSourceCode = true; if((flags & ProcessSpecFlags.LazyNIC) != 0) matcherGen.LazyNegativeIndependentConditionEvaluation = true; if((flags & ProcessSpecFlags.Noinline) != 0) matcherGen.InlineIndependents = false; if((flags & ProcessSpecFlags.Profile) != 0) matcherGen.Profile = true; foreach(LGSPMatchingPattern matchingPattern in ruleAndMatchingPatterns.RulesAndSubpatterns) { GenerateScheduledSearchPlans(matchingPattern.patternGraph, graphStatistics, matcherGen, !(matchingPattern is LGSPRulePattern), false, null); matcherGen.MergeNegativeAndIndependentSchedulesIntoEnclosingSchedules(matchingPattern.patternGraph); matcherGen.ParallelizeAsNeeded(matchingPattern); matcherGen.GenerateActionAndMatcher(source, matchingPattern, true); } GenerateDefinedSequencesAndFiltersAndFilterStubs(externalActionsExtensionFilename, isAutoGeneratedFilterExisting, isExternalFilterFunctionExisting, ruleAndMatchingPatterns, seqGen, externalSource, source); // the actions class referencing the generated stuff is generated now into // a source builder which is appended at the end of the other generated stuff SourceBuilder endSource = GenerateActionsClass(model, actionsName, unitName, statisticsPath, ruleAndMatchingPatterns, matcherGen.LazyNegativeIndependentConditionEvaluation, matcherGen.InlineIndependents, matcherGen.Profile); source.Append(endSource.ToString()); source.Append("}"); }
private ErrorType GenerateActionsSourceCode(CompileConfiguration cc, IGraphModel model, String statisticsPath, out String actionsOutputSource) { /////////////////////////////////////////////// // compile the intermediate action files generated by the java frontend // to gain access via reflection to their content needed for matcher code generation // and collect that content actionsOutputSource = null; Assembly initialAssembly; ErrorType result = CompileIntermediateActions(cc.modelAssemblyName, cc.actionsFilename, out initialAssembly); if(result != ErrorType.NoError) return result; Dictionary<String, Type> actionTypes; Dictionary<String, Type> proceduresTypes; LGSPRuleAndMatchingPatterns ruleAndMatchingPatterns; CollectActionTypes(initialAssembly, out actionTypes, out proceduresTypes, out ruleAndMatchingPatterns); Dictionary<String, List<IFilter>> rulesToFilters; Dictionary<String, List<String>> filterFunctionsToInputTypes; Dictionary<String, List<String>> rulesToInputTypes; Dictionary<String, List<String>> rulesToOutputTypes; Dictionary<String, List<String>> sequencesToInputTypes; Dictionary<String, List<String>> sequencesToOutputTypes; Dictionary<String, List<String>> proceduresToInputTypes; Dictionary<String, List<String>> proceduresToOutputTypes; Dictionary<String, bool> proceduresToIsExternal; Dictionary<String, List<String>> functionsToInputTypes; Dictionary<String, String> functionsToOutputType; Dictionary<String, bool> functionsToIsExternal; Dictionary<String, List<String>> rulesToTopLevelEntities; Dictionary<String, List<String>> rulesToTopLevelEntityTypes; CollectActionParameterTypes(ruleAndMatchingPatterns, model, out rulesToFilters, out filterFunctionsToInputTypes, out rulesToInputTypes, out rulesToOutputTypes, out rulesToTopLevelEntities, out rulesToTopLevelEntityTypes, out sequencesToInputTypes, out sequencesToOutputTypes, out proceduresToInputTypes, out proceduresToOutputTypes, out proceduresToIsExternal, out functionsToInputTypes, out functionsToOutputType, out functionsToIsExternal); LGSPSequenceGenerator seqGen = new LGSPSequenceGenerator(this, model, rulesToFilters, filterFunctionsToInputTypes, rulesToInputTypes, rulesToOutputTypes, rulesToTopLevelEntities, rulesToTopLevelEntityTypes, sequencesToInputTypes, sequencesToOutputTypes, proceduresToInputTypes, proceduresToOutputTypes, proceduresToIsExternal, functionsToInputTypes, functionsToOutputType, functionsToIsExternal); /////////////////////////////////////////////// // generate external extension source if needed (cause there are external action extension) bool isAutoGeneratedFilterExisting; bool isExternalFilterFunctionExisting; bool isExternalSequenceExisting; DetermineWhetherExternalActionsFileIsNeeded(ruleAndMatchingPatterns, out isAutoGeneratedFilterExisting, out isExternalFilterFunctionExisting, out isExternalSequenceExisting); SourceBuilder externalSource = null; if(isAutoGeneratedFilterExisting || isExternalFilterFunctionExisting || isExternalSequenceExisting) { EmitExternalActionsFileHeader(cc, model, isExternalFilterFunctionExisting || isExternalSequenceExisting, ref externalSource); } /////////////////////////////////////////////// // take action intermediate file until action insertion point as base for action file SourceBuilder source = new SourceBuilder((flags & ProcessSpecFlags.KeepGeneratedFiles) != 0); source.Indent(); source.Indent(); bool actionPointFound; String actionsNamespace; result = CopyIntermediateCodeInsertingSequencesCode(cc.actionsFilename, actionTypes, proceduresTypes, seqGen, source, out actionPointFound, out actionsNamespace); if(result != ErrorType.NoError) return result; if(!actionPointFound) { Console.Error.WriteLine("Illegal actions C# input source code: Actions insertion point not found!"); return ErrorType.GrGenJavaError; } source.Unindent(); source.Append("\n"); /////////////////////////////////////////////// // generate and insert the matcher source code into the action file // already filled with the content of the action intermediate file until the action insertion point String unitName; int lastDot = actionsNamespace.LastIndexOf("."); if(lastDot == -1) unitName = ""; else unitName = actionsNamespace.Substring(lastDot + 8); // skip ".Action_" LGSPGraphStatistics graphStatistics = null; if(statisticsPath != null) { Console.WriteLine("Reading graph statistics from {0}", statisticsPath); graphStatistics = new LGSPGraphStatistics(model); graphStatistics.Parse(statisticsPath); } GenerateAndInsertMatcherSourceCode(model, cc.actionsName, unitName, cc.externalActionsExtensionFilename, ruleAndMatchingPatterns, seqGen, isAutoGeneratedFilterExisting, isExternalFilterFunctionExisting, graphStatistics, statisticsPath, externalSource, source); actionsOutputSource = WriteSourceAndExternalSource(externalSource, source, cc.actionsOutputFilename, cc.externalActionsExtensionOutputFilename); return ErrorType.NoError; }