/// <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 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; }