public void EmitRewritingRuleCountAllCallOrRuleAllCallNonRandom(SourceBuilder source)
        {
            // iterate through matches, use Modify on each, fire the next match event after the first
            if (returnParameterDeclarations.Length != 0)
            {
                source.AppendFront(returnParameterDeclarationsAllCall + "\n");
            }
            String enumeratorName = "enum_" + ruleCallGen.seqRule.Id;

            source.AppendFront("IEnumerator<" + matchType + "> " + enumeratorName + " = " + matchesName + ".GetEnumeratorExact();\n");
            source.AppendFront("while(" + enumeratorName + ".MoveNext())\n");
            source.AppendFront("{\n");
            source.Indent();
            source.AppendFront(matchType + " " + matchName + " = " + enumeratorName + ".Current;\n");
            source.AppendFront("if(" + matchName + "!=" + matchesName + ".FirstExact) procEnv.RewritingNextMatch();\n");
            if (returnParameterDeclarations.Length != 0)
            {
                source.AppendFront(returnParameterDeclarations + "\n");
            }
            source.AppendFront(ruleCallGen.ruleName + ".Modify(procEnv, " + matchName + returnArguments + ");\n");
            if (returnAssignments.Length != 0)
            {
                source.AppendFront(intermediateReturnAssignmentsAllCall + "\n");
            }
            source.AppendFront("procEnv.PerformanceInfo.RewritesPerformed++;\n");
            source.Unindent();
            source.AppendFront("}\n");
            if (returnAssignments.Length != 0)
            {
                source.AppendFront(returnAssignmentsAllCall + "\n");
            }
        }
 public void Explain(SourceBuilder sb, IGraphModel model)
 {
     foreach (SearchOperation searchOp in Operations)
     {
         searchOp.Explain(sb, model);
     }
 }
        public override void Dump(SourceBuilder builder)
        {
            // first dump check
            builder.AppendFront("CheckCandidate ForType ");
            if (Type == CheckCandidateForTypeType.ByIsAllowedType)
            {
                builder.Append("ByIsAllowedType ");
                builder.AppendFormat("on {0} in {1} node:{2}\n",
                                     PatternElementName, RulePatternTypeName, IsNode);
            }
            else if (Type == CheckCandidateForTypeType.ByIsMyType)
            {
                builder.Append("ByIsMyType ");
                builder.AppendFormat("on {0} in {1} node:{2}\n",
                                     PatternElementName, TypeName, IsNode);
            }
            else // Type == CheckCandidateForTypeType.ByTypeID
            {
                builder.Append("ByTypeID ");
                builder.AppendFormat("on {0} ids:{1} node:{2}\n",
                                     PatternElementName, string.Join(",", TypeIDs), IsNode);
            }

            // then operations for case check failed
            if (CheckFailedOperations != null)
            {
                builder.Indent();
                CheckFailedOperations.Dump(builder);
                builder.Unindent();
            }
        }
 public static void Explain(ScheduledSearchPlan ssp, SourceBuilder sb, IGraphModel model)
 {
     foreach (SearchOperation searchOp in ssp.Operations)
     {
         Explain(searchOp, sb, model);
     }
 }
        public override void Emit(SourceBuilder sourceCode)
        {
            // emit initialization with element mapped from storage
            string variableContainingStorage       = NamesOfEntities.Variable(StorageName);
            string variableContainingSourceElement = NamesOfEntities.CandidateVariable(SourcePatternElementName);
            string tempVariableForMapResult        = NamesOfEntities.MapWithStorageTemporary(PatternElementName);

            sourceCode.AppendFrontFormat("if(!{0}.TryGetValue(({1}){2}, out {3})) ",
                                         variableContainingStorage, StorageKeyTypeName,
                                         variableContainingSourceElement, tempVariableForMapResult);

            // emit check failed code
            sourceCode.Append("{\n");
            sourceCode.Indent();
            CheckFailedOperations.Emit(sourceCode);
            sourceCode.Unindent();
            sourceCode.AppendFront("}\n");

            // assign the value to the candidate variable, cast it to the variable type
            string typeOfVariableContainingCandidate = "GRGEN_LGSP."
                                                       + (IsNode ? "LGSPNode" : "LGSPEdge");
            string variableContainingCandidate = NamesOfEntities.CandidateVariable(PatternElementName);

            sourceCode.AppendFrontFormat("{0} = ({1}){2};\n",
                                         variableContainingCandidate, typeOfVariableContainingCandidate, tempVariableForMapResult);
        }
        public override void Emit(SourceBuilder sourceCode)
        {
            // open decision whether to fail
            sourceCode.AppendFront("if(");

            // fail if graph element contained within candidate was already matched
            // (previously on the pattern derivation path to another pattern element)
            // as this would cause a inter-pattern-homomorphic match
            string variableContainingCandidate = NamesOfEntities.CandidateVariable(PatternElementName);
            string isMatchedBySomeBit          = "(uint)GRGEN_LGSP.LGSPElemFlags.IS_MATCHED_BY_SOME_ENCLOSING_PATTERN";

            if (!Always)
            {
                sourceCode.Append("searchPatternpath && ");
            }

            sourceCode.AppendFormat("({0}.lgspFlags & {1})=={1} && GRGEN_LGSP.PatternpathIsomorphyChecker.IsMatched({0}, {2})",
                                    variableContainingCandidate, isMatchedBySomeBit, LastMatchAtPreviousNestingLevel);

            sourceCode.Append(")\n");

            // emit check failed code
            sourceCode.AppendFront("{\n");
            sourceCode.Indent();
            CheckFailedOperations.Emit(sourceCode);
            sourceCode.Unindent();
            sourceCode.AppendFront("}\n");
        }
 public override void Dump(SourceBuilder builder)
 {
     // first dump check
     builder.AppendFront("CheckCandidate ForIsomorphy ");
     builder.AppendFormat("on {0} negNamePrefix:{1} node:{2} ",
                          PatternElementName, NegativeIndependentNamePrefix, IsNode);
     if (NamesOfPatternElementsToCheckAgainst != null)
     {
         builder.Append("against ");
         foreach (string name in NamesOfPatternElementsToCheckAgainst)
         {
             builder.AppendFormat("{0} ", name);
         }
     }
     builder.AppendFormat("parallel:{0} first for all:{1} ",
                          Parallel, LockForAllThreads);
     builder.Append("\n");
     // then operations for case check failed
     if (CheckFailedOperations != null)
     {
         builder.Indent();
         CheckFailedOperations.Dump(builder);
         builder.Unindent();
     }
 }
Exemple #8
0
        public bool GenerateExternalDefinedSequence(SourceBuilder source, ExternalDefinedSequenceInfo sequence)
        {
            // exact sequence definition compiled class
            source.Append("\n");
            source.AppendFront("public partial class Sequence_" + sequence.Name + " : GRGEN_LIBGR.SequenceDefinitionCompiled\n");
            source.AppendFront("{\n");
            source.Indent();

            GenerateSequenceDefinedSingleton(source, sequence);

            source.Append("\n");
            GenerateGenericMethodReturnValues(source, sequence);

            source.Append("\n");
            GenerateExactExternalDefinedSequenceApplicationMethod(source, sequence);

            source.Append("\n");
            GenerateGenericExternalDefinedSequenceApplicationMethod(source, sequence);

            // end of exact sequence definition compiled class
            source.Unindent();
            source.AppendFront("}\n");

            return(true);
        }
        private static void BuildInterpretationPlan(LGSPGraph graph)
        {
            graph.matchingState.patternGraph = BuildPatternGraph(graph);
            PlanGraph planGraph = PlanGraphGenerator.GeneratePlanGraph(graph.Model, graph.statistics, graph.matchingState.patternGraph,
                                                                       false, false, false, new Dictionary <PatternElement, SetValueType>());

            PlanGraphGenerator.MarkMinimumSpanningArborescence(planGraph, graph.matchingState.patternGraph.name, false);
            SearchPlanGraph     searchPlanGraph     = SearchPlanGraphGeneratorAndScheduler.GenerateSearchPlanGraph(planGraph);
            ScheduledSearchPlan scheduledSearchPlan = SearchPlanGraphGeneratorAndScheduler.ScheduleSearchPlan(
                searchPlanGraph, graph.matchingState.patternGraph, false, false);
            InterpretationPlanBuilder builder = new InterpretationPlanBuilder(scheduledSearchPlan, searchPlanGraph, graph.Model);

            graph.matchingState.interpretationPlan = builder.BuildInterpretationPlan("ComparisonMatcher_" + graph.GraphId);
            ++GraphMatchingState.numInterpretationPlans;
            graph.matchingState.changesCounterAtInterpretationPlanBuilding = graph.changesCounterAtLastAnalyze;
            Debug.Assert(graph.changesCounterAtLastAnalyze == graph.ChangesCounter);

#if LOG_ISOMORPHY_CHECKING
            SourceBuilder sb = new SourceBuilder();
            graph.matchingState.interpretationPlan.Dump(sb);
            writer.WriteLine();
            writer.WriteLine(sb.ToString());
            writer.WriteLine();
            writer.Flush();
#endif
        }
        public void EmitMatchingAndCloning(SourceBuilder source, String maxMatches)
        {
            String parameters = seqHelper.BuildParameters(seqRule, ArgumentExpressions, source);

            EmitMatching(source, parameters, maxMatches);
            EmitCloning(source);
        }
 public void EmitMatchedReset(SourceBuilder builder, bool parallel)
 {
     if(parallel)
         builder.AppendFrontFormat("flagsPerElement{0}[candidate{0}.uniqueId] &= (ushort)~GRGEN_LGSP.LGSPElemFlagsParallel.IS_MATCHED;\n", this.Id);
     else
         builder.AppendFrontFormat("candidate{0}.lgspFlags &= ~((uint)GRGEN_LGSP.LGSPElemFlags.IS_MATCHED);\n", this.Id);
 }
        public string ExtractEdgeType(SourceBuilder source, SequenceExpression typeExpr)
        {
            string incidentEdgeType = "graph.Model.EdgeModel.RootType";

            if (typeExpr != null)
            {
                if (typeExpr.Type(env) != "")
                {
                    if (typeExpr.Type(env) == "string")
                    {
                        incidentEdgeType = "graph.Model.EdgeModel.GetType((string)" + exprGen.GetSequenceExpression(typeExpr, source) + ")";
                    }
                    else
                    {
                        incidentEdgeType = "(GRGEN_LIBGR.EdgeType)" + exprGen.GetSequenceExpression(typeExpr, source);
                    }
                }
                else
                {
                    incidentEdgeType = exprGen.GetSequenceExpression(typeExpr, source) + " is string ? "
                                       + "graph.Model.EdgeModel.GetType((string)" + exprGen.GetSequenceExpression(typeExpr, source) + ")"
                                       + " : " + "(GRGEN_LIBGR.EdgeType)" + exprGen.GetSequenceExpression(typeExpr, source);
                }
            }
            return("(" + incidentEdgeType + ")");
        }
 public void EmitFiltering(SourceBuilder source)
 {
     for (int i = 0; i < seqRule.Filters.Count; ++i)
     {
         seqExprGen.EmitFilterCall(source, seqRule.Filters[i], patternName, matchesName, seqRule.PackagePrefixedName, false);
     }
 }
Exemple #14
0
 public void EmitCloning(SourceBuilder source, SequenceGenerator seqGen, String matchListName, String originalToCloneName)
 {
     source.AppendFront("if(" + matchesName + ".Count != 0) {\n");
     source.Indent();
     source.AppendFrontFormat("{0} = ({1}){0}.Clone({2});\n", matchesName, matchesType, originalToCloneName);
     source.Unindent();
     source.AppendFront("}\n");
 }
Exemple #15
0
 public override void Emit(SourceBuilder sourceCode)
 {
     sourceCode.Append(IsVar ? NamesOfEntities.Variable(Left) : NamesOfEntities.CandidateVariable(Left));
     sourceCode.Append(" = ");
     sourceCode.Append("(" + TargetType + ")");
     Right.Emit(sourceCode);
     sourceCode.Append(";\n");
 }
Exemple #16
0
 /// <summary>
 /// Emit variable declarations needed (only once for every variable)
 /// </summary>
 private void EmitVarIfNew(SequenceVariable var, SourceBuilder source)
 {
     if (!var.Visited)
     {
         var.Visited = true;
         source.AppendFront(seqHelper.DeclareVar(var));
     }
 }
 public void EmitAddRange(SourceBuilder source, String matchListName)
 {
     source.AppendFront("if(" + matchesName + ".Count != 0) {\n");
     source.Indent();
     source.AppendFrontFormat("{0}.AddRange({1});\n", matchListName, matchesName);
     source.Unindent();
     source.AppendFront("}\n");
 }
 public void EmitCloning(SourceBuilder source)
 {
     source.AppendFront("if(" + matchesName + ".Count != 0) {\n");
     source.Indent();
     source.AppendFront(matchesName + " = (" + matchesType + ")" + matchesName + ".Clone();\n");
     source.Unindent();
     source.AppendFront("}\n");
 }
        private void GenerateSequenceDefinedSingleton(SourceBuilder source, DefinedSequenceInfo sequence)
        {
            String className = "Sequence_" + sequence.Name;

            source.AppendFront("private static " + className + " instance = null;\n");

            source.AppendFront("public static " + className + " Instance { get { if(instance==null) instance = new " + className + "(); return instance; } }\n");

            source.AppendFront("private " + className + "() : base(\"" + sequence.PackagePrefixedName + "\", SequenceInfo_" + sequence.Name + ".Instance) { }\n");
        }
Exemple #20
0
        public override void Emit(SourceBuilder sourceCode)
        {
            sourceCode.AppendFront("{ // " + Name + "\n");

            sourceCode.Indent();
            NestedOperationsList.Emit(sourceCode);
            sourceCode.Unindent();

            sourceCode.AppendFront("}\n");
        }
Exemple #21
0
        public override void Emit(SourceBuilder sourceCode)
        {
            sourceCode.AppendFrontFormat("if({0}.Count>0) {{\n", NestedMatchObjectName);
            sourceCode.Indent();

            NestedOperationsList.Emit(sourceCode);

            sourceCode.Unindent();
            sourceCode.AppendFront("}\n");
        }
Exemple #22
0
 public override void Dump(SourceBuilder builder)
 {
     // first dump local content
     builder.AppendFront("FillPartialMatchForDuplicateChecking with ");
     foreach (string neededElement in NeededElements)
     {
         builder.AppendFormat("{0} ", neededElement);
     }
     builder.Append("\n");
 }
Exemple #23
0
        private static void DumpScheduledSearchPlan(ScheduledSearchPlan ssp, IGraphModel model, String dumpname)
        {
            StreamWriter  sw = new StreamWriter(dumpname + "-scheduledsp.txt", false);
            SourceBuilder sb = new SourceBuilder();

            ScheduleExplainer.Explain(ssp, sb, model);
            sb.Append("\n");
            sw.WriteLine(sb.ToString());
            sw.Close();
        }
Exemple #24
0
        public override void Emit(SourceBuilder sourceCode)
        {
            sourceCode.AppendFrontFormat("foreach({0} {1} in {2}) {{\n",
                                         IteratedMatchTypeName, HelperMatchName, NestedMatchObjectName);
            sourceCode.Indent();

            NestedOperationsList.Emit(sourceCode);

            sourceCode.Unindent();
            sourceCode.AppendFront("}\n");
        }
Exemple #25
0
        public void EmitRewriting(SourceBuilder source, SequenceGenerator seqGen, String matchListName, String enumeratorName,
                                  bool fireDebugEvents)
        {
            source.AppendFrontFormat("case \"{0}\":\n", plainRuleName);
            source.AppendFront("{\n");
            source.Indent();

            source.AppendFront(matchType + " " + matchName + " = (" + matchType + ")" + enumeratorName + ".Current;\n");

            String returnParameterDeclarations;
            String returnArguments;
            String returnAssignments;
            String returnParameterDeclarationsAllCall;
            String intermediateReturnAssignmentsAllCall;
            String returnAssignmentsAllCall;

            seqHelper.BuildReturnParameters(seqRule, ReturnVars,
                                            out returnParameterDeclarations, out returnArguments, out returnAssignments,
                                            out returnParameterDeclarationsAllCall, out intermediateReturnAssignmentsAllCall, out returnAssignmentsAllCall);

            // start a transaction
            if (fireDebugEvents)
            {
                source.AppendFront("procEnv.Matched(" + matchesName + ", " + matchName + ", " + specialStr + ");\n");
            }
            if (fireDebugEvents)
            {
                source.AppendFront("procEnv.Finishing(" + matchesName + ", " + specialStr + ");\n");
            }
            if (returnParameterDeclarations.Length != 0)
            {
                source.AppendFront(returnParameterDeclarations + "\n");
            }

            source.AppendFront(ruleName + ".Modify(procEnv, " + matchName + returnArguments + ");\n");
            if (returnAssignments.Length != 0)
            {
                source.AppendFront(returnAssignments + "\n");
            }
            source.AppendFront("++procEnv.PerformanceInfo.RewritesPerformed;\n");
            if (fireDebugEvents)
            {
                source.AppendFront("procEnv.Finished(" + matchesName + ", " + specialStr + ");\n");
            }

            // rule applied, now execute the sequence
            seqGen.EmitSequence(seqSeq, source);

            source.AppendFront(COMP_HELPER.SetResultVar(seqMulti, COMP_HELPER.GetResultVar(seqSeq)));

            source.AppendFront("break;\n");
            source.Unindent();
            source.AppendFront("}\n");
        }
 public override void Emit(SourceBuilder sourceCode)
 {
     sourceCode.AppendFrontFormat("// build match of {0} for patternpath checks\n",
                                  PatternGraphName);
     sourceCode.AppendFrontFormat("if({0}==null) {0} = new {1}.{2}();\n",
                                  NamesOfEntities.PatternpathMatch(PatternGraphName),
                                  RulePatternClassName,
                                  NamesOfEntities.MatchClassName(PatternGraphName));
     sourceCode.AppendFrontFormat("{0}._matchOfEnclosingPattern = {1};\n",
                                  NamesOfEntities.PatternpathMatch(PatternGraphName), MatchOfNestingPattern);
 }
        public void GenerateExternalDefinedSequencePlaceholder(SourceBuilder source, ExternalDefinedSequenceInfo sequence, String externalActionsExtensionFilename)
        {
            source.Append("\n");
            source.AppendFront("public partial class Sequence_" + sequence.Name + "\n");
            source.AppendFront("{\n");
            source.Indent();

            GenerateInternalDefinedSequenceApplicationMethodStub(source, sequence, externalActionsExtensionFilename);

            source.Unindent();
            source.AppendFront("}\n");
        }
Exemple #28
0
        public override void Emit(SourceBuilder sourceCode)
        {
            SearchProgramOperation currentOperation = Next;

            // depth first walk over nested search program lists
            // walk current list here, recursive descent within local Emit-methods
            while (currentOperation != null)
            {
                currentOperation.Emit(sourceCode);
                currentOperation = currentOperation.Next;
            }
        }
Exemple #29
0
        public override void Dump(SourceBuilder builder)
        {
            SearchProgramOperation currentOperation = Next;

            // depth first walk over nested search program lists
            // walk current list here, recursive descent within local dump-methods
            while (currentOperation != null)
            {
                currentOperation.Dump(builder);
                currentOperation = currentOperation.Next;
            }
        }
Exemple #30
0
 public override void Dump(SourceBuilder builder)
 {
     // first dump check
     builder.AppendFront("CheckCandidate Failed \n");
     // then operations for case check failed
     if (CheckFailedOperations != null)
     {
         builder.Indent();
         CheckFailedOperations.Dump(builder);
         builder.Unindent();
     }
 }
        public override void Emit(SourceBuilder sourceCode)
        {
            if (sourceCode.CommentSourceCode)
            {
                sourceCode.AppendFrontFormat("// Variable {0} assigned from expression {1} \n",
                                             VariableName, SourceExpression);
            }

            // emit declaration of variable initialized with expression
            sourceCode.AppendFrontFormat("{0} {1} = ({0}){2};\n",
                                         VariableType, NamesOfEntities.Variable(VariableName), SourceExpression);
        }
Exemple #32
0
 public override void Dump(SourceBuilder builder)
 {
     // first dump check
     builder.AppendFront("CheckPartialMatch ForSubpatternsFound\n");
     // then operations for case check failed
     if (CheckFailedOperations != null)
     {
         builder.Indent();
         CheckFailedOperations.Dump(builder);
         builder.Unindent();
     }
 }
 public void EmitMatchedCheckAndSet(SourceBuilder builder, bool parallel)
 {
     if(parallel)
     {
         builder.AppendFrontFormat("List<ushort> flagsPerElement{0} = graph.flagsPerThreadPerElement[threadId];\n", this.Id);
         builder.AppendFrontFormat("if((flagsPerElement{0}[candidate{0}.uniqueId] & (ushort)GRGEN_LGSP.LGSPElemFlagsParallel.IS_MATCHED) != 0)\n", this.Id);
         builder.AppendFront("\tcontinue;\n");
         builder.AppendFrontFormat("flagsPerElement{0}[candidate{0}.uniqueId] |= (ushort)GRGEN_LGSP.LGSPElemFlagsParallel.IS_MATCHED;\n", this.Id);
     }
     else
     {
         builder.AppendFrontFormat("if((candidate{0}.lgspFlags & (uint)GRGEN_LGSP.LGSPElemFlags.IS_MATCHED) != 0)\n", this.Id);
         builder.AppendFront("\tcontinue;\n");
         builder.AppendFrontFormat("candidate{0}.lgspFlags |= (uint)GRGEN_LGSP.LGSPElemFlags.IS_MATCHED;\n", this.Id);
     }
 }
        /// <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>
        /// 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");
        }
Exemple #36
0
        /// <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)");
        }
 public override string ToString()
 {
     String fromStr = "";
     SourceBuilder sbFrom = new SourceBuilder();
     if(From != null)
     {
         sbFrom.Append(Index.Name);
         if(IncludingFrom)
             sbFrom.Append("<=");
         else
             sbFrom.Append("<");
         From.Emit(sbFrom);
         fromStr = sbFrom.ToString();
     }
     String toStr = "";
     SourceBuilder sbTo = new SourceBuilder();
     if(To != null)
     {
         sbTo.Append(Index.Name);
         if(IncludingTo)
             sbTo.Append(">=");
         else
             sbTo.Append(">");
         To.Emit(sbTo);
         toStr = sbTo.ToString();
     }
     if(From == null && To == null)
         return "descending(" + Index.Name + ")";
     else
         return "descending(" + fromStr + " " + toStr + ")";
 }
        /// <summary>
        /// Generate new actions for the given actions, doing the same work, 
        /// but hopefully faster by taking graph analysis information into account
        /// </summary>
        public LGSPAction[] GenerateActions(LGSPGraph graph, String modelAssemblyName, String actionsAssemblyName, 
            params LGSPAction[] actions)
        {
            if(actions.Length == 0) throw new ArgumentException("No actions provided!");

            SourceBuilder sourceCode = new SourceBuilder(CommentSourceCode);
            GenerateFileHeaderForActionsFile(sourceCode, model.GetType().Namespace, actions[0].rulePattern.GetType().Namespace);

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

            // generate code for subpatterns
            foreach (KeyValuePair<LGSPMatchingPattern, LGSPMatchingPattern> subpatternMatchingPattern in subpatternMatchingPatterns)
            {
                LGSPMatchingPattern smp = subpatternMatchingPattern.Key;

                GenerateScheduledSearchPlans(smp.patternGraph, graph, 
                    true, false, null);

                MergeNegativeAndIndependentSchedulesIntoEnclosingSchedules(smp.patternGraph);

                ParallelizeAsNeeded(smp);

                GenerateActionAndMatcher(sourceCode, smp, false);
            }

            // generate code for actions
            foreach(LGSPAction action in actions)
            {
                GenerateScheduledSearchPlans(action.rulePattern.patternGraph, graph,
                    false, false, null);

                MergeNegativeAndIndependentSchedulesIntoEnclosingSchedules(action.rulePattern.patternGraph);

                ParallelizeAsNeeded(action.rulePattern);

                GenerateActionAndMatcher(sourceCode, action.rulePattern, false);
            }

            // close namespace
            sourceCode.Append("}");

            if(DumpDynSourceCode)
            {
                using(StreamWriter writer = new StreamWriter("dynamic_" + actions[0].Name + ".cs"))
                    writer.Write(sourceCode.ToString());
            }

            // set up compiler
            CSharpCodeProvider compiler = new CSharpCodeProvider();
            CompilerParameters compParams = GetDynCompilerSetup(modelAssemblyName, actionsAssemblyName);
 
            // compile generated code
            CompilerResults compResults = compiler.CompileAssemblyFromSource(compParams, sourceCode.ToString());
            if(compResults.Errors.HasErrors)
            {
                String errorMsg = compResults.Errors.Count + " Errors:";
                foreach(CompilerError error in compResults.Errors)
                    errorMsg += Environment.NewLine + "Line: " + error.Line + " - " + error.ErrorText;
                throw new ArgumentException("Internal error: Illegal dynamic C# source code produced: " + errorMsg);
            }

            // create action instances
            LGSPAction[] newActions = new LGSPAction[actions.Length];
            for(int i = 0; i < actions.Length; i++)
            {
                newActions[i] = (LGSPAction) compResults.CompiledAssembly.CreateInstance(
                    "de.unika.ipd.grGen.lgspActions.DynAction_" + actions[i].Name);
                if(newActions[i] == null)
                    throw new ArgumentException("Internal error: Generated assembly does not contain action '"
                        + actions[i].Name + "'!");
            }
            return newActions;
        }
Exemple #39
0
        public override void Emit(SourceBuilder sourceCode)
        {
            String id = fetchId().ToString();

            if(Function is Adjacent)
            {
                Adjacent adjacent = (Adjacent)Function;
                sourceCode.AppendFront("GRGEN_LIBGR.INode node_" + id + " = ");
                adjacent.Node.Emit(sourceCode);
                sourceCode.Append(";\n");
                if(!Profiling)
                {
                    sourceCode.AppendFrontFormat("foreach(GRGEN_LIBGR.IEdge edge_{0} in node_{0}.GetCompatibleIncident(", id);
                    adjacent.IncidentEdgeType.Emit(sourceCode);
                    sourceCode.Append("))\n");
                }
                else
                {
                    sourceCode.AppendFrontFormat("foreach(GRGEN_LIBGR.IEdge edge_{0} in node_{0}.Incident)\n", id);
                }
                sourceCode.AppendFront("{\n");
                sourceCode.Indent();

                if(Profiling)
                {
                    if(Parallel)
                        sourceCode.AppendFront("++actionEnv.PerformanceInfo.SearchStepsPerThread[threadId];\n");
                    else
                        sourceCode.AppendFront("++actionEnv.PerformanceInfo.SearchSteps;\n");
                    sourceCode.AppendFrontFormat("if(!edge_{0}.InstanceOf(", id);
                    adjacent.IncidentEdgeType.Emit(sourceCode);
                    sourceCode.Append("))\n");
                    sourceCode.AppendFront("\tcontinue;\n");
                }

                sourceCode.AppendFrontFormat("if(!edge_{0}.Opposite(node_{0}).InstanceOf(", id);
                adjacent.AdjacentNodeType.Emit(sourceCode);
                sourceCode.Append("))\n");
                sourceCode.AppendFront("\tcontinue;\n");
                sourceCode.AppendFrontFormat("{0} {1} = ({0})edge_{2}.Opposite(node_{2});\n", VariableType, NamesOfEntities.Variable(Variable), id);
            }
            else if(Function is AdjacentIncoming)
            {
                AdjacentIncoming adjacent = (AdjacentIncoming)Function;
                sourceCode.AppendFront("GRGEN_LIBGR.INode node_" + id + " = ");
                adjacent.Node.Emit(sourceCode);
                sourceCode.Append(";\n");
                if(!Profiling)
                {
                    sourceCode.AppendFrontFormat("foreach(GRGEN_LIBGR.IEdge edge_{0} in node_{0}.GetCompatibleIncoming(", id);
                    adjacent.IncidentEdgeType.Emit(sourceCode);
                    sourceCode.Append("))\n");
                }
                else
                {
                    sourceCode.AppendFrontFormat("foreach(GRGEN_LIBGR.IEdge edge_{0} in node_{0}.Incoming)\n", id);
                }
                sourceCode.AppendFront("{\n");
                sourceCode.Indent();

                if(Profiling)
                {
                    if(Parallel)
                        sourceCode.AppendFront("++actionEnv.PerformanceInfo.SearchStepsPerThread[threadId];\n");
                    else
                        sourceCode.AppendFront("++actionEnv.PerformanceInfo.SearchSteps;\n");
                    sourceCode.AppendFrontFormat("if(!edge_{0}.InstanceOf(", id);
                    adjacent.IncidentEdgeType.Emit(sourceCode);
                    sourceCode.Append("))\n");
                    sourceCode.AppendFront("\tcontinue;\n");
                }

                sourceCode.AppendFrontFormat("if(!edge_{0}.Source.InstanceOf(", id);
                adjacent.AdjacentNodeType.Emit(sourceCode);
                sourceCode.Append("))\n");
                sourceCode.AppendFront("\tcontinue;\n");
                sourceCode.AppendFrontFormat("{0} {1} = ({0})edge_{2}.Source;\n", VariableType, NamesOfEntities.Variable(Variable), id);
            }
            else if(Function is AdjacentOutgoing)
            {
                AdjacentOutgoing adjacent = (AdjacentOutgoing)Function;
                sourceCode.AppendFront("GRGEN_LIBGR.INode node_" + id + " = ");
                adjacent.Node.Emit(sourceCode);
                sourceCode.Append(";\n");
                if(!Profiling)
                {
                    sourceCode.AppendFrontFormat("foreach(GRGEN_LIBGR.IEdge edge_{0} in node_{0}.GetCompatibleOutgoing(", id);
                    adjacent.IncidentEdgeType.Emit(sourceCode);
                    sourceCode.Append("))\n");
                }
                else
                {
                    sourceCode.AppendFrontFormat("foreach(GRGEN_LIBGR.IEdge edge_{0} in node_{0}.Outgoing)\n", id);
                }
                sourceCode.AppendFront("{\n");
                sourceCode.Indent();

                if(Profiling)
                {
                    if(Parallel)
                        sourceCode.AppendFront("++actionEnv.PerformanceInfo.SearchStepsPerThread[threadId];\n");
                    else
                        sourceCode.AppendFront("++actionEnv.PerformanceInfo.SearchSteps;\n");
                    sourceCode.AppendFrontFormat("if(!edge_{0}.InstanceOf(", id);
                    adjacent.IncidentEdgeType.Emit(sourceCode);
                    sourceCode.Append("))\n");
                    sourceCode.AppendFront("\tcontinue;\n");
                }

                sourceCode.AppendFrontFormat("if(!edge_{0}.Target.InstanceOf(", id);
                adjacent.AdjacentNodeType.Emit(sourceCode);
                sourceCode.Append("))\n");
                sourceCode.AppendFront("\tcontinue;\n");
                sourceCode.AppendFrontFormat("{0} {1} = ({0})edge_{2}.Target;\n", VariableType, NamesOfEntities.Variable(Variable), id);
            }
            else if(Function is Incident)
            {
                Incident incident = (Incident)Function;
                sourceCode.AppendFront("GRGEN_LIBGR.INode node_" + id + " = ");
                incident.Node.Emit(sourceCode);
                sourceCode.Append(";\n");
                if(!Profiling)
                {
                    sourceCode.AppendFrontFormat("foreach(GRGEN_LIBGR.IEdge edge_{0} in node_{0}.GetCompatibleIncident(", id);
                    incident.IncidentEdgeType.Emit(sourceCode);
                    sourceCode.Append("))\n");
                }
                else
                {
                    sourceCode.AppendFrontFormat("foreach(GRGEN_LIBGR.IEdge edge_{0} in node_{0}.Incident)\n", id);
                }
                sourceCode.AppendFront("{\n");
                sourceCode.Indent();

                if(Profiling)
                {
                    if(Parallel)
                        sourceCode.AppendFront("++actionEnv.PerformanceInfo.SearchStepsPerThread[threadId];\n");
                    else
                        sourceCode.AppendFront("++actionEnv.PerformanceInfo.SearchSteps;\n");
                    sourceCode.AppendFrontFormat("if(!edge_{0}.InstanceOf(", id);
                    incident.IncidentEdgeType.Emit(sourceCode);
                    sourceCode.Append("))\n");
                    sourceCode.AppendFront("\tcontinue;\n");
                }

                sourceCode.AppendFrontFormat("if(!edge_{0}.Opposite(node_{0}).InstanceOf(", id);
                incident.AdjacentNodeType.Emit(sourceCode);
                sourceCode.Append("))\n");
                sourceCode.AppendFront("\tcontinue;\n");
                sourceCode.AppendFrontFormat("{0} {1} = ({0})edge_{2};\n", VariableType, NamesOfEntities.Variable(Variable), id);
            }
            else if(Function is Incoming)
            {
                Incoming incident = (Incoming)Function;
                sourceCode.AppendFront("GRGEN_LIBGR.INode node_" + id + " = ");
                incident.Node.Emit(sourceCode);
                sourceCode.Append(";\n");
                if(!Profiling)
                {
                    sourceCode.AppendFrontFormat("foreach(GRGEN_LIBGR.IEdge edge_{0} in node_{0}.GetCompatibleIncoming(", id);
                    incident.IncidentEdgeType.Emit(sourceCode);
                    sourceCode.Append("))\n");
                }
                else
                {
                    sourceCode.AppendFrontFormat("foreach(GRGEN_LIBGR.IEdge edge_{0} in node_{0}.Incoming)\n", id);
                }
                sourceCode.AppendFront("{\n");
                sourceCode.Indent();

                if(Profiling)
                {
                    if(Parallel)
                        sourceCode.AppendFront("++actionEnv.PerformanceInfo.SearchStepsPerThread[threadId];\n");
                    else
                        sourceCode.AppendFront("++actionEnv.PerformanceInfo.SearchSteps;\n");
                    sourceCode.AppendFrontFormat("if(!edge_{0}.InstanceOf(", id);
                    incident.IncidentEdgeType.Emit(sourceCode);
                    sourceCode.Append("))\n");
                    sourceCode.AppendFront("\tcontinue;\n");
                }

                sourceCode.AppendFrontFormat("if(!edge_{0}.Source.InstanceOf(", id);
                incident.AdjacentNodeType.Emit(sourceCode);
                sourceCode.Append("))\n");
                sourceCode.AppendFront("\tcontinue;\n");
                sourceCode.AppendFrontFormat("{0} {1} = ({0})edge_{2};\n", VariableType, NamesOfEntities.Variable(Variable), id);
            }
            else if(Function is Outgoing)
            {
                Outgoing incident = (Outgoing)Function;
                sourceCode.AppendFront("GRGEN_LIBGR.INode node_" + id + " = ");
                incident.Node.Emit(sourceCode);
                sourceCode.Append(";\n");
                if(!Profiling)
                {
                    sourceCode.AppendFrontFormat("foreach(GRGEN_LIBGR.IEdge edge_{0} in node_{0}.GetCompatibleOutgoing(", id);
                    incident.IncidentEdgeType.Emit(sourceCode);
                    sourceCode.Append("))\n");
                }
                else
                {
                    sourceCode.AppendFrontFormat("foreach(GRGEN_LIBGR.IEdge edge_{0} in node_{0}.Outgoing)\n", id);
                }
                sourceCode.AppendFront("{\n");
                sourceCode.Indent();

                if(Profiling)
                {
                    if(Parallel)
                        sourceCode.AppendFront("++actionEnv.PerformanceInfo.SearchStepsPerThread[threadId];\n");
                    else
                        sourceCode.AppendFront("++actionEnv.PerformanceInfo.SearchSteps;\n");
                    sourceCode.AppendFrontFormat("if(!edge_{0}.InstanceOf(", id);
                    incident.IncidentEdgeType.Emit(sourceCode);
                    sourceCode.Append("))\n");
                    sourceCode.AppendFront("\tcontinue;\n");
                }

                sourceCode.AppendFrontFormat("if(!edge_{0}.Target.InstanceOf(", id);
                incident.AdjacentNodeType.Emit(sourceCode);
                sourceCode.Append("))\n");
                sourceCode.AppendFront("\tcontinue;\n");
                sourceCode.AppendFrontFormat("{0} {1} = ({0})edge_{2};\n", VariableType, NamesOfEntities.Variable(Variable), id);
            }
            else if(Function is Reachable)
            {
                Reachable reachable = (Reachable)Function;
                sourceCode.AppendFront("GRGEN_LIBGR.INode node_" + id + " = ");
                reachable.Node.Emit(sourceCode);
                sourceCode.Append(";\n");
                sourceCode.AppendFrontFormat("foreach(GRGEN_LIBGR.INode iter_{0} in GRGEN_LIBGR.GraphHelper.Reachable(node_{0}, ", id);
                reachable.IncidentEdgeType.Emit(sourceCode);
                sourceCode.Append(", ");
                reachable.AdjacentNodeType.Emit(sourceCode);
                sourceCode.Append(", ");
                sourceCode.Append("graph");
                if(Profiling)
                    sourceCode.Append(", actionEnv");
                if(Parallel)
                    sourceCode.Append(", threadId"); 
                sourceCode.Append("))\n");
                sourceCode.AppendFront("{\n");
                sourceCode.Indent();

                sourceCode.AppendFrontFormat("{0} {1} = ({0})iter_{2};\n", VariableType, NamesOfEntities.Variable(Variable), id);
            }
            else if(Function is ReachableIncoming)
            {
                ReachableIncoming reachable = (ReachableIncoming)Function;
                sourceCode.AppendFront("GRGEN_LIBGR.INode node_" + id + " = ");
                reachable.Node.Emit(sourceCode);
                sourceCode.Append(";\n");
                sourceCode.AppendFrontFormat("foreach(GRGEN_LIBGR.INode iter_{0} in GRGEN_LIBGR.GraphHelper.ReachableIncoming(node_{0}, ", id);
                reachable.IncidentEdgeType.Emit(sourceCode);
                sourceCode.Append(", ");
                reachable.AdjacentNodeType.Emit(sourceCode);
                sourceCode.Append(", ");
                sourceCode.Append("graph");
                if(Profiling)
                    sourceCode.Append(", actionEnv");
                if(Parallel)
                    sourceCode.Append(", threadId");
                sourceCode.Append("))\n");
                sourceCode.AppendFront("{\n");
                sourceCode.Indent();

                sourceCode.AppendFrontFormat("{0} {1} = ({0})iter_{2};\n", VariableType, NamesOfEntities.Variable(Variable), id);
            }
            else if(Function is ReachableOutgoing)
            {
                ReachableOutgoing reachable = (ReachableOutgoing)Function;
                sourceCode.AppendFront("GRGEN_LIBGR.INode node_" + id + " = ");
                reachable.Node.Emit(sourceCode);
                sourceCode.Append(";\n");
                sourceCode.AppendFrontFormat("foreach(GRGEN_LIBGR.INode iter_{0} in GRGEN_LIBGR.GraphHelper.ReachableOutgoing(node_{0}, ", id);
                reachable.IncidentEdgeType.Emit(sourceCode);
                sourceCode.Append(", ");
                reachable.AdjacentNodeType.Emit(sourceCode);
                sourceCode.Append(", ");
                sourceCode.Append("graph");
                if(Profiling)
                    sourceCode.Append(", actionEnv");
                if(Parallel)
                    sourceCode.Append(", threadId");
                sourceCode.Append("))\n");
                sourceCode.AppendFront("{\n");
                sourceCode.Indent();

                sourceCode.AppendFrontFormat("{0} {1} = ({0})iter_{2};\n", VariableType, NamesOfEntities.Variable(Variable), id);
            }
            else if(Function is ReachableEdges)
            {
                ReachableEdges reachable = (ReachableEdges)Function;
                sourceCode.AppendFront("GRGEN_LIBGR.INode node_" + id + " = ");
                reachable.Node.Emit(sourceCode);
                sourceCode.Append(";\n");
                sourceCode.AppendFrontFormat("foreach(GRGEN_LIBGR.IEdge edge_{0} in GRGEN_LIBGR.GraphHelper.ReachableEdges(node_{0}, ", id);
                reachable.IncidentEdgeType.Emit(sourceCode);
                sourceCode.Append(", ");
                reachable.AdjacentNodeType.Emit(sourceCode);
                sourceCode.Append(", ");
                sourceCode.Append("graph");
                if(Profiling)
                    sourceCode.Append(", actionEnv");
                if(Parallel)
                    sourceCode.Append(", threadId");
                sourceCode.Append("))\n");
                sourceCode.AppendFront("{\n");
                sourceCode.Indent();

                sourceCode.AppendFrontFormat("{0} {1} = ({0})edge_{2};\n", VariableType, NamesOfEntities.Variable(Variable), id);
            }
            else if(Function is ReachableEdgesIncoming)
            {
                ReachableEdgesIncoming reachable = (ReachableEdgesIncoming)Function;
                sourceCode.AppendFront("GRGEN_LIBGR.INode node_" + id + " = ");
                reachable.Node.Emit(sourceCode);
                sourceCode.Append(";\n");
                sourceCode.AppendFrontFormat("foreach(GRGEN_LIBGR.IEdge edge_{0} in GRGEN_LIBGR.GraphHelper.ReachableEdgesIncoming(node_{0}, ", id);
                reachable.IncidentEdgeType.Emit(sourceCode);
                sourceCode.Append(", ");
                reachable.AdjacentNodeType.Emit(sourceCode);
                sourceCode.Append(", ");
                sourceCode.Append("graph");
                if(Profiling)
                    sourceCode.Append(", actionEnv");
                if(Parallel)
                    sourceCode.Append(", threadId");
                sourceCode.Append("))\n");
                sourceCode.AppendFront("{\n");
                sourceCode.Indent();

                sourceCode.AppendFrontFormat("{0} {1} = ({0})edge_{2};\n", VariableType, NamesOfEntities.Variable(Variable), id);
            }
            else if(Function is ReachableEdgesOutgoing)
            {
                ReachableEdgesOutgoing reachable = (ReachableEdgesOutgoing)Function;
                sourceCode.AppendFront("GRGEN_LIBGR.INode node_" + id + " = ");
                reachable.Node.Emit(sourceCode);
                sourceCode.Append(";\n");
                sourceCode.AppendFrontFormat("foreach(GRGEN_LIBGR.IEdge edge_{0} in GRGEN_LIBGR.GraphHelper.ReachableEdgesOutgoing(node_{0}, ", id);
                reachable.IncidentEdgeType.Emit(sourceCode);
                sourceCode.Append(", ");
                reachable.AdjacentNodeType.Emit(sourceCode);
                sourceCode.Append(", ");
                sourceCode.Append("graph");
                if(Profiling)
                    sourceCode.Append(", actionEnv");
                if(Parallel)
                    sourceCode.Append(", threadId");
                sourceCode.Append("))\n");
                sourceCode.AppendFront("{\n");
                sourceCode.Indent();

                sourceCode.AppendFrontFormat("{0} {1} = ({0})edge_{2};\n", VariableType, NamesOfEntities.Variable(Variable), id);
            }
            else if(Function is BoundedReachable)
            {
                BoundedReachable reachable = (BoundedReachable)Function;
                sourceCode.AppendFront("GRGEN_LIBGR.INode node_" + id + " = ");
                reachable.Node.Emit(sourceCode);
                sourceCode.Append(";\n");
                sourceCode.AppendFrontFormat("foreach(GRGEN_LIBGR.INode iter_{0} in GRGEN_LIBGR.GraphHelper.BoundedReachable(node_{0}, ", id);
                reachable.IncidentEdgeType.Emit(sourceCode);
                sourceCode.Append(", ");
                reachable.AdjacentNodeType.Emit(sourceCode);
                sourceCode.Append(", ");
                sourceCode.Append("graph");
                if(Profiling)
                    sourceCode.Append(", actionEnv");
                if(Parallel)
                    sourceCode.Append(", threadId");
                sourceCode.Append("))\n");
                sourceCode.AppendFront("{\n");
                sourceCode.Indent();

                sourceCode.AppendFrontFormat("{0} {1} = ({0})iter_{2};\n", VariableType, NamesOfEntities.Variable(Variable), id);
            }
            else if(Function is BoundedReachableIncoming)
            {
                BoundedReachableIncoming reachable = (BoundedReachableIncoming)Function;
                sourceCode.AppendFront("GRGEN_LIBGR.INode node_" + id + " = ");
                reachable.Node.Emit(sourceCode);
                sourceCode.Append(";\n");
                sourceCode.AppendFrontFormat("foreach(GRGEN_LIBGR.INode iter_{0} in GRGEN_LIBGR.GraphHelper.BoundedReachableIncoming(node_{0}, ", id);
                reachable.IncidentEdgeType.Emit(sourceCode);
                sourceCode.Append(", ");
                reachable.AdjacentNodeType.Emit(sourceCode);
                sourceCode.Append(", ");
                sourceCode.Append("graph");
                if(Profiling)
                    sourceCode.Append(", actionEnv");
                if(Parallel)
                    sourceCode.Append(", threadId");
                sourceCode.Append("))\n");
                sourceCode.AppendFront("{\n");
                sourceCode.Indent();

                sourceCode.AppendFrontFormat("{0} {1} = ({0})iter_{2};\n", VariableType, NamesOfEntities.Variable(Variable), id);
            }
            else if(Function is BoundedReachableOutgoing)
            {
                BoundedReachableOutgoing reachable = (BoundedReachableOutgoing)Function;
                sourceCode.AppendFront("GRGEN_LIBGR.INode node_" + id + " = ");
                reachable.Node.Emit(sourceCode);
                sourceCode.Append(";\n");
                sourceCode.AppendFrontFormat("foreach(GRGEN_LIBGR.INode iter_{0} in GRGEN_LIBGR.GraphHelper.BoundedReachableOutgoing(node_{0}, ", id);
                reachable.IncidentEdgeType.Emit(sourceCode);
                sourceCode.Append(", ");
                reachable.AdjacentNodeType.Emit(sourceCode);
                sourceCode.Append(", ");
                sourceCode.Append("graph");
                if(Profiling)
                    sourceCode.Append(", actionEnv");
                if(Parallel)
                    sourceCode.Append(", threadId");
                sourceCode.Append("))\n");
                sourceCode.AppendFront("{\n");
                sourceCode.Indent();

                sourceCode.AppendFrontFormat("{0} {1} = ({0})iter_{2};\n", VariableType, NamesOfEntities.Variable(Variable), id);
            }
            else if(Function is BoundedReachableEdges)
            {
                BoundedReachableEdges reachable = (BoundedReachableEdges)Function;
                sourceCode.AppendFront("GRGEN_LIBGR.INode node_" + id + " = ");
                reachable.Node.Emit(sourceCode);
                sourceCode.Append(";\n");
                sourceCode.AppendFrontFormat("foreach(GRGEN_LIBGR.IEdge edge_{0} in GRGEN_LIBGR.GraphHelper.BoundedReachableEdges(node_{0}, ", id);
                reachable.IncidentEdgeType.Emit(sourceCode);
                sourceCode.Append(", ");
                reachable.AdjacentNodeType.Emit(sourceCode);
                sourceCode.Append(", ");
                sourceCode.Append("graph");
                if(Profiling)
                    sourceCode.Append(", actionEnv");
                if(Parallel)
                    sourceCode.Append(", threadId");
                sourceCode.Append("))\n");
                sourceCode.AppendFront("{\n");
                sourceCode.Indent();

                sourceCode.AppendFrontFormat("{0} {1} = ({0})edge_{2};\n", VariableType, NamesOfEntities.Variable(Variable), id);
            }
            else if(Function is BoundedReachableEdgesIncoming)
            {
                BoundedReachableEdgesIncoming reachable = (BoundedReachableEdgesIncoming)Function;
                sourceCode.AppendFront("GRGEN_LIBGR.INode node_" + id + " = ");
                reachable.Node.Emit(sourceCode);
                sourceCode.Append(";\n");
                sourceCode.AppendFrontFormat("foreach(GRGEN_LIBGR.IEdge edge_{0} in GRGEN_LIBGR.GraphHelper.BoundedReachableEdgesIncoming(node_{0}, ", id);
                reachable.IncidentEdgeType.Emit(sourceCode);
                sourceCode.Append(", ");
                reachable.AdjacentNodeType.Emit(sourceCode);
                sourceCode.Append(", ");
                sourceCode.Append("graph");
                if(Profiling)
                    sourceCode.Append(", actionEnv");
                if(Parallel)
                    sourceCode.Append(", threadId");
                sourceCode.Append("))\n");
                sourceCode.AppendFront("{\n");
                sourceCode.Indent();

                sourceCode.AppendFrontFormat("{0} {1} = ({0})edge_{2};\n", VariableType, NamesOfEntities.Variable(Variable), id);
            }
            else if(Function is BoundedReachableEdgesOutgoing)
            {
                BoundedReachableEdgesOutgoing reachable = (BoundedReachableEdgesOutgoing)Function;
                sourceCode.AppendFront("GRGEN_LIBGR.INode node_" + id + " = ");
                reachable.Node.Emit(sourceCode);
                sourceCode.Append(";\n");
                sourceCode.AppendFrontFormat("foreach(GRGEN_LIBGR.IEdge edge_{0} in GRGEN_LIBGR.GraphHelper.BoundedReachableEdgesOutgoing(node_{0}, ", id);
                reachable.IncidentEdgeType.Emit(sourceCode);
                sourceCode.Append(", ");
                reachable.AdjacentNodeType.Emit(sourceCode);
                sourceCode.Append(", ");
                sourceCode.Append("graph");
                if(Profiling)
                    sourceCode.Append(", actionEnv");
                if(Parallel)
                    sourceCode.Append(", threadId");
                sourceCode.Append("))\n");
                sourceCode.AppendFront("{\n");
                sourceCode.Indent();

                sourceCode.AppendFrontFormat("{0} {1} = ({0})edge_{2};\n", VariableType, NamesOfEntities.Variable(Variable), id);
            }
            else if(Function is Nodes)
            {
                Nodes nodes = (Nodes)Function;
                sourceCode.AppendFrontFormat("foreach(GRGEN_LIBGR.INode node_{0} in graph.GetCompatibleNodes(", id);
                nodes.NodeType.Emit(sourceCode);
                sourceCode.Append("))\n");
                sourceCode.AppendFront("{\n");
                sourceCode.Indent();

                if(Profiling)
                {
                    if(Parallel)
                        sourceCode.AppendFront("++actionEnv.PerformanceInfo.SearchStepsPerThread[threadId];\n");
                    else
                        sourceCode.AppendFront("++actionEnv.PerformanceInfo.SearchSteps;\n");
                }

                sourceCode.AppendFront(VariableType + " " + NamesOfEntities.Variable(Variable) + " = (" + VariableType + ") node_" + id + ";\n");
            }
            else if(Function is Edges)
            {
                Edges edges = (Edges)Function;
                sourceCode.AppendFrontFormat("foreach(GRGEN_LIBGR.IEdge edge_{0} in graph.GetCompatibleEdges(", id);
                edges.EdgeType.Emit(sourceCode);
                sourceCode.Append("))\n");
                sourceCode.AppendFront("{\n");
                sourceCode.Indent();

                if(Profiling)
                {
                    if(Parallel)
                        sourceCode.AppendFront("++actionEnv.PerformanceInfo.SearchStepsPerThread[threadId];\n");
                    else
                        sourceCode.AppendFront("++actionEnv.PerformanceInfo.SearchSteps;\n");
                }

                sourceCode.AppendFront(VariableType + " " + NamesOfEntities.Variable(Variable) + " = (" + VariableType + ") edge_" + id + ";\n");
            }

            foreach(Yielding statement in Statements)
                statement.Emit(sourceCode);

            sourceCode.Unindent();
            sourceCode.AppendFront("}\n");
        }
        /// <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 matcher class tail source code
        /// </summary>
        public void GenerateMatcherClassTail(SourceBuilder sb, bool containedInPackage)
        {
            sb.Unindent();
            sb.AppendFront("}\n");

            if(containedInPackage)
            {
                sb.Unindent();
                sb.AppendFront("}\n");
            }

            sb.AppendFront("\n");
        }
        /// <summary>
        // generate implementation of the exact action interface,
        // delegate calls of the inexact action interface IAction to the exact action interface
        /// </summary>
        void GenerateActionImplementation(SourceBuilder sb, LGSPRulePattern matchingPattern)
        {
            StringBuilder sbInParameters = new StringBuilder();
            StringBuilder sbInArguments = new StringBuilder();
            StringBuilder sbInArgumentsFromArray = new StringBuilder();
            for(int i = 0; i < matchingPattern.Inputs.Length; ++i)
            {
                sbInParameters.Append(", ");
                sbInParameters.Append(TypesHelper.TypeName(matchingPattern.Inputs[i]));
                sbInParameters.Append(" ");
                sbInParameters.Append(matchingPattern.InputNames[i]);

                sbInArguments.Append(", ");
                sbInArguments.Append(matchingPattern.InputNames[i]);

                sbInArgumentsFromArray.Append(", (");
                sbInArgumentsFromArray.Append(TypesHelper.TypeName(matchingPattern.Inputs[i]));
                sbInArgumentsFromArray.Append(") parameters[");
                sbInArgumentsFromArray.Append(i);
                sbInArgumentsFromArray.Append("]");
            }
            String inParameters = sbInParameters.ToString();
            String inArguments = sbInArguments.ToString();
            String inArgumentsFromArray = sbInArgumentsFromArray.ToString();

            StringBuilder sbOutParameters = new StringBuilder();
            StringBuilder sbRefParameters = new StringBuilder();
            StringBuilder sbOutLocals = new StringBuilder();
            StringBuilder sbRefLocals = new StringBuilder();
            StringBuilder sbOutArguments = new StringBuilder();
            StringBuilder sbRefArguments = new StringBuilder();
            StringBuilder sbOutIntermediateLocalsAll = new StringBuilder();
            StringBuilder sbOutParametersAll = new StringBuilder();
            StringBuilder sbOutArgumentsAll = new StringBuilder();
            StringBuilder sbIntermediateLocalArgumentsAll = new StringBuilder();
            StringBuilder sbOutClassArgumentsAll = new StringBuilder();
            for(int i = 0; i < matchingPattern.Outputs.Length; ++i)
            {
                sbOutParameters.Append(", out ");
                sbOutParameters.Append(TypesHelper.TypeName(matchingPattern.Outputs[i]));
                sbOutParameters.Append(" output_");
                sbOutParameters.Append(i);

                sbRefParameters.Append(", ref ");
                sbRefParameters.Append(TypesHelper.TypeName(matchingPattern.Outputs[i]));
                sbRefParameters.Append(" output_");
                sbRefParameters.Append(i);

                sbOutLocals.Append(TypesHelper.TypeName(matchingPattern.Outputs[i]));
                sbOutLocals.Append(" output_");
                sbOutLocals.Append(i);
                sbOutLocals.Append("; ");

                sbRefLocals.Append(TypesHelper.TypeName(matchingPattern.Outputs[i]));
                sbRefLocals.Append(" output_");
                sbRefLocals.Append(i);
                sbRefLocals.Append(" = ");
                sbRefLocals.Append(TypesHelper.DefaultValueString(matchingPattern.Outputs[i].PackagePrefixedName, model));
                sbRefLocals.Append("; ");

                sbOutArguments.Append(", out output_");
                sbOutArguments.Append(i);

                sbRefArguments.Append(", ref output_");
                sbRefArguments.Append(i);

                sbOutIntermediateLocalsAll.Append(TypesHelper.TypeName(matchingPattern.Outputs[i]));
                sbOutIntermediateLocalsAll.Append(" output_local_");
                sbOutIntermediateLocalsAll.Append(i);
                sbOutIntermediateLocalsAll.Append("; ");

                sbOutParametersAll.Append(", List<");
                sbOutParametersAll.Append(TypesHelper.TypeName(matchingPattern.Outputs[i]));
                sbOutParametersAll.Append("> output_");
                sbOutParametersAll.Append(i);

                sbOutArgumentsAll.Append(", output_");
                sbOutArgumentsAll.Append(i);

                sbIntermediateLocalArgumentsAll.Append(", out output_local_");
                sbIntermediateLocalArgumentsAll.Append(i);

                sbOutClassArgumentsAll.Append(", output_list_");
                sbOutClassArgumentsAll.Append(i);
            }
            String outParameters = sbOutParameters.ToString();
            String refParameters = sbRefParameters.ToString();
            String outLocals = sbOutLocals.ToString();
            String refLocals = sbRefLocals.ToString();
            String outArguments = sbOutArguments.ToString();
            String refArguments = sbRefArguments.ToString();
            String outIntermediateLocalsAll = sbOutIntermediateLocalsAll.ToString();
            String outParametersAll = sbOutParametersAll.ToString();
            String outArgumentsAll = sbOutArgumentsAll.ToString();
            String intermediateLocalArgumentsAll = sbIntermediateLocalArgumentsAll.ToString();
            String outClassArgumentsAll = sbOutClassArgumentsAll.ToString();
 
            String matchingPatternClassName = matchingPattern.GetType().Name;
            String patternName = matchingPattern.name;
            String matchType = matchingPatternClassName + "." + NamesOfEntities.MatchInterfaceName(patternName);
            String matchesType = "GRGEN_LIBGR.IMatchesExact<" + matchType + ">";

            // implementation of exact action interface

            sb.AppendFront("/// <summary> Type of the matcher method (with parameters processing environment containing host graph, maximum number of matches to search for (zero=unlimited), and rule parameters; returning found matches). </summary>\n");
            sb.AppendFrontFormat("public delegate {0} MatchInvoker(GRGEN_LGSP.LGSPActionExecutionEnvironment actionEnv, int maxMatches{1});\n", matchesType, inParameters);

            sb.AppendFront("/// <summary> A delegate pointing to the current matcher program for this rule. </summary>\n");
            sb.AppendFront("public MatchInvoker DynamicMatch;\n");

            sb.AppendFront("/// <summary> The RulePattern object from which this LGSPAction object has been created. </summary>\n");
            sb.AppendFront("public GRGEN_LIBGR.IRulePattern RulePattern { get { return _rulePattern; } }\n");

            for(int i = 0; i < matchingPattern.Outputs.Length; ++i)
            {
                sb.AppendFront("List<");
                sb.Append(TypesHelper.TypeName(matchingPattern.Outputs[i]));
                sb.Append("> output_list_");
                sb.Append(i.ToString());
                sb.Append(" = new List<");
                sb.Append(TypesHelper.TypeName(matchingPattern.Outputs[i]));
                sb.Append(">();\n");
            }

            sb.AppendFrontFormat("public {0} Match(GRGEN_LIBGR.IActionExecutionEnvironment actionEnv, int maxMatches{1})\n", matchesType, inParameters);
            sb.AppendFront("{\n");
            sb.Indent();
            sb.AppendFrontFormat("return DynamicMatch((GRGEN_LGSP.LGSPActionExecutionEnvironment)actionEnv, maxMatches{0});\n", inArguments);
            sb.Unindent();
            sb.AppendFront("}\n");

            sb.AppendFrontFormat("public void Modify(GRGEN_LIBGR.IActionExecutionEnvironment actionEnv, {0} match{1})\n", matchType, outParameters);
            sb.AppendFront("{\n");
            sb.Indent();
            sb.AppendFrontFormat("_rulePattern.Modify((GRGEN_LGSP.LGSPActionExecutionEnvironment)actionEnv, match{0});\n", outArguments);
            sb.Unindent();
            sb.AppendFront("}\n");

            sb.AppendFrontFormat("public void ModifyAll(GRGEN_LIBGR.IActionExecutionEnvironment actionEnv, {0} matches{1})\n", matchesType, outParametersAll);
            sb.AppendFront("{\n");
            sb.Indent();
            sb.AppendFrontFormat("foreach({0} match in matches)\n", matchType);
            sb.AppendFront("{\n");
            sb.Indent();
            sb.AppendFrontFormat("{0}\n", outIntermediateLocalsAll);
            sb.AppendFrontFormat("_rulePattern.Modify((GRGEN_LGSP.LGSPActionExecutionEnvironment)actionEnv, match{0});\n", intermediateLocalArgumentsAll);
            for(int i = 0; i < matchingPattern.Outputs.Length; ++i) {
                sb.AppendFrontFormat("output_{0}.Add(output_local_{0});\n", i);
            }
            sb.Unindent();
            sb.AppendFront("}\n");
            sb.Unindent();
            sb.AppendFront("}\n");

            sb.AppendFrontFormat("public bool Apply(GRGEN_LIBGR.IActionExecutionEnvironment actionEnv{0}{1})\n", inParameters, refParameters);
            sb.AppendFront("{\n");
            sb.Indent();
            sb.AppendFrontFormat("{0} matches = DynamicMatch((GRGEN_LGSP.LGSPActionExecutionEnvironment)actionEnv, 1{1});\n", matchesType, inArguments);
            sb.AppendFront("if(matches.Count <= 0) return false;\n");
            sb.AppendFrontFormat("_rulePattern.Modify((GRGEN_LGSP.LGSPActionExecutionEnvironment)actionEnv, matches.First{0});\n", outArguments);
            sb.AppendFront("return true;\n");
            sb.Unindent();
            sb.AppendFront("}\n");

            sb.AppendFrontFormat("public int ApplyAll(int maxMatches, GRGEN_LIBGR.IActionExecutionEnvironment actionEnv{0}{1})\n", inParameters, outParametersAll);
            sb.AppendFront("{\n");
            sb.Indent();
            sb.AppendFrontFormat("{0} matches = DynamicMatch((GRGEN_LGSP.LGSPActionExecutionEnvironment)actionEnv, maxMatches{1});\n", matchesType, inArguments);
            sb.AppendFront("if(matches.Count <= 0) return 0;\n");
            sb.AppendFrontFormat("foreach({0} match in matches)\n", matchType);
            sb.AppendFront("{\n");
            sb.Indent();
            sb.AppendFrontFormat("{0}\n", outIntermediateLocalsAll);
            sb.AppendFrontFormat("_rulePattern.Modify((GRGEN_LGSP.LGSPActionExecutionEnvironment)actionEnv, match{0});\n", intermediateLocalArgumentsAll);
            for(int i = 0; i < matchingPattern.Outputs.Length; ++i) {
                sb.AppendFrontFormat("output_{0}.Add(output_local_{0});\n", i);
            }
            sb.Unindent();
            sb.AppendFront("}\n");
            sb.AppendFront("return matches.Count;\n");
            sb.Unindent();
            sb.AppendFront("}\n");

            sb.AppendFrontFormat("public bool ApplyStar(GRGEN_LIBGR.IActionExecutionEnvironment actionEnv{0})\n", inParameters);
            sb.AppendFront("{\n");
            sb.Indent();
            sb.AppendFrontFormat("{0} matches;\n", matchesType);
            sb.AppendFrontFormat("{0}\n", outLocals);

            sb.AppendFront("while(true)\n");
            sb.AppendFront("{\n");
            sb.Indent();
            sb.AppendFrontFormat("matches = DynamicMatch((GRGEN_LGSP.LGSPActionExecutionEnvironment)actionEnv, 1{0});\n", inArguments);
            sb.AppendFront("if(matches.Count <= 0) return true;\n");
            sb.AppendFrontFormat("_rulePattern.Modify((GRGEN_LGSP.LGSPActionExecutionEnvironment)actionEnv, matches.First{0});\n", outArguments);
            sb.Unindent();
            sb.AppendFront("}\n");
            sb.Unindent();
            sb.AppendFront("}\n");

            sb.AppendFrontFormat("public bool ApplyPlus(GRGEN_LIBGR.IActionExecutionEnvironment actionEnv{0})\n", inParameters);
            sb.AppendFront("{\n");
            sb.Indent();
            sb.AppendFrontFormat("{0} matches = DynamicMatch((GRGEN_LGSP.LGSPActionExecutionEnvironment)actionEnv, 1{1});\n", matchesType, inArguments);
            sb.AppendFront("if(matches.Count <= 0) return false;\n");
            sb.AppendFrontFormat("{0}\n", outLocals);
            sb.AppendFront("do\n");
            sb.AppendFront("{\n");
            sb.Indent();
            sb.AppendFrontFormat("_rulePattern.Modify((GRGEN_LGSP.LGSPActionExecutionEnvironment)actionEnv, matches.First{0});\n", outArguments);
            sb.AppendFrontFormat("matches = DynamicMatch((GRGEN_LGSP.LGSPActionExecutionEnvironment)actionEnv, 1{0});\n", inArguments);
            sb.Unindent();
            sb.AppendFront("}\n");
            sb.AppendFront("while(matches.Count > 0) ;\n");
            sb.AppendFront("return true;\n");
            sb.Unindent();
            sb.AppendFront("}\n");

            sb.AppendFrontFormat("public bool ApplyMinMax(GRGEN_LIBGR.IActionExecutionEnvironment actionEnv, int min, int max{0})\n", inParameters);
            sb.AppendFront("{\n");
            sb.Indent();
            sb.AppendFrontFormat("{0} matches;\n", matchesType);
            sb.AppendFrontFormat("{0}\n", outLocals);
            sb.AppendFront("for(int i = 0; i < max; i++)\n");
            sb.AppendFront("{\n");
            sb.Indent();
            sb.AppendFrontFormat("matches = DynamicMatch((GRGEN_LGSP.LGSPActionExecutionEnvironment)actionEnv, 1{0});\n", inArguments);
            sb.AppendFront("if(matches.Count <= 0) return i >= min;\n");
            sb.AppendFrontFormat("_rulePattern.Modify((GRGEN_LGSP.LGSPActionExecutionEnvironment)actionEnv, matches.First{0});\n", outArguments);
            sb.Unindent();
            sb.AppendFront("}\n");
            sb.AppendFront("return true;\n");
            sb.Unindent();
            sb.AppendFront("}\n");

            // implementation of inexact action interface by delegation to exact action interface
            sb.AppendFront("// implementation of inexact action interface by delegation to exact action interface\n");

            sb.AppendFront("public GRGEN_LIBGR.IMatches Match(GRGEN_LIBGR.IActionExecutionEnvironment actionEnv, int maxMatches, object[] parameters)\n");
            sb.AppendFront("{\n");
            sb.Indent();
            sb.AppendFrontFormat("return Match(actionEnv, maxMatches{0});\n", inArgumentsFromArray);
            sb.Unindent(); 
            sb.AppendFront("}\n");

            sb.AppendFront("public object[] Modify(GRGEN_LIBGR.IActionExecutionEnvironment actionEnv, GRGEN_LIBGR.IMatch match)\n");
            sb.AppendFront("{\n");
            sb.Indent();
            sb.AppendFrontFormat("{0}\n", outLocals);
            sb.AppendFrontFormat("Modify(actionEnv, ({0})match{1});\n", matchType, outArguments);
            for(int i = 0; i < matchingPattern.Outputs.Length; ++i) {
                sb.AppendFrontFormat("ReturnArray[{0}] = output_{0};\n", i);
            }
            sb.AppendFront("return ReturnArray;\n");
            sb.Unindent(); 
            sb.AppendFront("}\n");

            sb.AppendFront("public List<object[]> ModifyAll(GRGEN_LIBGR.IActionExecutionEnvironment actionEnv, GRGEN_LIBGR.IMatches matches)\n");
            sb.AppendFront("{\n");
            sb.Indent();

            for(int i = 0; i < matchingPattern.Outputs.Length; ++i)
            {
                sb.AppendFront("output_list_");
                sb.Append(i.ToString());
                sb.Append(".Clear();\n");
            }
            sb.AppendFrontFormat("ModifyAll(actionEnv, ({0})matches{1});\n", matchesType, outClassArgumentsAll);

            sb.AppendFront("while(AvailableReturnArrays.Count < matches.Count) AvailableReturnArrays.Add(new object[" + matchingPattern.Outputs.Length + "]);\n");
            sb.AppendFront("ReturnArrayListForAll.Clear();\n");
            sb.AppendFront("for(int i=0; i<matches.Count; ++i)\n");
            sb.AppendFront("{\n");
            sb.Indent();
            sb.AppendFront("ReturnArrayListForAll.Add(AvailableReturnArrays[i]);\n");
            for(int i = 0; i < matchingPattern.Outputs.Length; ++i) {
                sb.AppendFrontFormat("ReturnArrayListForAll[i][{0}] = output_list_{0}[i];\n", i);
            }
            sb.Unindent();
            sb.AppendFront("}\n");

            sb.AppendFront("return ReturnArrayListForAll;\n");
            sb.Unindent(); 
            sb.AppendFront("}\n");

            sb.AppendFront("object[] GRGEN_LIBGR.IAction.Apply(GRGEN_LIBGR.IActionExecutionEnvironment actionEnv)\n");
            sb.AppendFront("{\n");
            sb.Indent();
            if(matchingPattern.Inputs.Length == 0) {
                sb.AppendFrontFormat("{0}\n", refLocals);
                sb.AppendFrontFormat("if(Apply(actionEnv{0})) ", refArguments);
                sb.Append("{\n");
                sb.Indent();
                for(int i = 0; i < matchingPattern.Outputs.Length; ++i) {
                    sb.AppendFrontFormat("ReturnArray[{0}] = output_{0};\n", i);
                }
                sb.AppendFront("return ReturnArray;\n");
                sb.Unindent();
                sb.AppendFront("}\n");
                sb.AppendFront("else return null;\n");
            }
            else
                sb.AppendFront("throw new Exception();\n");
            sb.Unindent(); 
            sb.AppendFront("}\n");

            sb.AppendFront("object[] GRGEN_LIBGR.IAction.Apply(GRGEN_LIBGR.IActionExecutionEnvironment actionEnv, params object[] parameters)\n");
            sb.AppendFront("{\n");
            sb.Indent();
            sb.AppendFrontFormat("{0}\n", refLocals);
            sb.AppendFrontFormat("if(Apply(actionEnv{0}{1})) ", inArgumentsFromArray, refArguments);
            sb.Append("{\n");
            sb.Indent();
            for(int i = 0; i < matchingPattern.Outputs.Length; ++i) {
                sb.AppendFrontFormat("ReturnArray[{0}] = output_{0};\n", i);
            }
            sb.AppendFront("return ReturnArray;\n");
            sb.Unindent(); 
            sb.AppendFront("}\n");
            sb.AppendFront("else return null;\n");
            sb.Unindent();
            sb.AppendFront("}\n");

            sb.AppendFront("public List<object[]> Reserve(int numReturns)\n");
            sb.AppendFront("{\n");
            sb.Indent();
            sb.AppendFront("while(AvailableReturnArrays.Count < numReturns) AvailableReturnArrays.Add(new object[" + matchingPattern.Outputs.Length + "]);\n");
            sb.AppendFront("ReturnArrayListForAll.Clear();\n");
            sb.AppendFront("for(int i=0; i<numReturns; ++i)\n");
            sb.AppendFront("{\n");
            sb.Indent();
            sb.AppendFront("ReturnArrayListForAll.Add(AvailableReturnArrays[i]);\n");
            sb.Unindent();
            sb.AppendFront("}\n");
            sb.AppendFront("return ReturnArrayListForAll;\n");
            sb.Unindent();
            sb.AppendFront("}\n");

            sb.AppendFront("List<object[]> GRGEN_LIBGR.IAction.ApplyAll(int maxMatches, GRGEN_LIBGR.IActionExecutionEnvironment actionEnv)\n");
            sb.AppendFront("{\n");
            sb.Indent();
            if(matchingPattern.Inputs.Length == 0) {
                for(int i = 0; i < matchingPattern.Outputs.Length; ++i)
                {
                    sb.AppendFront("output_list_");
                    sb.Append(i.ToString());
                    sb.Append(".Clear();\n");
                }
                sb.AppendFrontFormat("int matchesCount = ApplyAll(maxMatches, actionEnv{0});\n", outClassArgumentsAll);
                sb.AppendFront("while(AvailableReturnArrays.Count < matchesCount) AvailableReturnArrays.Add(new object[" + matchingPattern.Outputs.Length + "]);\n");
                sb.AppendFront("ReturnArrayListForAll.Clear();\n");
                sb.AppendFront("for(int i=0; i<matchesCount; ++i)\n");
                sb.AppendFront("{\n");
                sb.Indent();
                sb.AppendFront("ReturnArrayListForAll.Add(AvailableReturnArrays[i]);\n");
                for(int i = 0; i < matchingPattern.Outputs.Length; ++i) {
                    sb.AppendFrontFormat("ReturnArrayListForAll[i][{0}] = output_list_{0}[i];\n", i);
                }
                sb.Unindent();
                sb.AppendFront("}\n");
                sb.AppendFront("return ReturnArrayListForAll;\n");
            }
            else
                sb.AppendFront("throw new Exception();\n");
            sb.Unindent(); 
            sb.AppendFront("}\n");

            sb.AppendFront("List<object[]> GRGEN_LIBGR.IAction.ApplyAll(int maxMatches, GRGEN_LIBGR.IActionExecutionEnvironment actionEnv, params object[] parameters)\n");
            sb.AppendFront("{\n");
            sb.Indent();
            for(int i = 0; i < matchingPattern.Outputs.Length; ++i)
            {
                sb.AppendFront("output_list_");
                sb.Append(i.ToString());
                sb.Append(".Clear();\n");
            }
            sb.AppendFrontFormat("int matchesCount = ApplyAll(maxMatches, actionEnv{0}{1});\n", inArgumentsFromArray, outClassArgumentsAll);
            sb.AppendFront("while(AvailableReturnArrays.Count < matchesCount) AvailableReturnArrays.Add(new object[" + matchingPattern.Outputs.Length + "]);\n");
            sb.AppendFront("ReturnArrayListForAll.Clear();\n");
            sb.AppendFront("for(int i=0; i<matchesCount; ++i)\n");
            sb.AppendFront("{\n");
            sb.Indent();
            sb.AppendFront("ReturnArrayListForAll.Add(AvailableReturnArrays[i]);\n");
            for(int i = 0; i < matchingPattern.Outputs.Length; ++i) {
                sb.AppendFrontFormat("ReturnArrayListForAll[i][{0}] = output_list_{0}[i];\n", i);
            }
            sb.Unindent();
            sb.AppendFront("}\n");
            sb.AppendFront("return ReturnArrayListForAll;\n");
            sb.Unindent();
            sb.AppendFront("}\n");

            sb.AppendFront("bool GRGEN_LIBGR.IAction.ApplyStar(GRGEN_LIBGR.IActionExecutionEnvironment actionEnv)\n");
            sb.AppendFront("{\n");
            sb.Indent();
            if(matchingPattern.Inputs.Length == 0)
                sb.AppendFront("return ApplyStar(actionEnv);\n");
            else
                sb.AppendFront("throw new Exception(); return false;\n");
            sb.Unindent(); 
            sb.AppendFront("}\n");

            sb.AppendFront("bool GRGEN_LIBGR.IAction.ApplyStar(GRGEN_LIBGR.IActionExecutionEnvironment actionEnv, params object[] parameters)\n");
            sb.AppendFront("{\n");
            sb.Indent();
            sb.AppendFrontFormat("return ApplyStar(actionEnv{0});\n", inArgumentsFromArray);
            sb.Unindent(); 
            sb.AppendFront("}\n");

            sb.AppendFront("bool GRGEN_LIBGR.IAction.ApplyPlus(GRGEN_LIBGR.IActionExecutionEnvironment actionEnv)\n");
            sb.AppendFront("{\n");
            sb.Indent();
            if(matchingPattern.Inputs.Length == 0)
                sb.AppendFront("return ApplyPlus(actionEnv);\n");
            else
                sb.AppendFront("throw new Exception(); return false;\n");
            sb.Unindent(); 
            sb.AppendFront("}\n");

            sb.AppendFront("bool GRGEN_LIBGR.IAction.ApplyPlus(GRGEN_LIBGR.IActionExecutionEnvironment actionEnv, params object[] parameters)\n");
            sb.AppendFront("{\n");
            sb.Indent();
            sb.AppendFrontFormat("return ApplyPlus(actionEnv{0});\n", inArgumentsFromArray);
            sb.Unindent(); 
            sb.AppendFront("}\n");

            sb.AppendFront("bool GRGEN_LIBGR.IAction.ApplyMinMax(GRGEN_LIBGR.IActionExecutionEnvironment actionEnv, int min, int max)\n");
            sb.AppendFront("{\n");
            sb.Indent();
            if(matchingPattern.Inputs.Length == 0)
                sb.AppendFront("return ApplyMinMax(actionEnv, min, max);\n");
            else 
                sb.AppendFront("throw new Exception(); return false;\n");
            sb.Unindent(); 
            sb.AppendFront("}\n");

            sb.AppendFront("bool GRGEN_LIBGR.IAction.ApplyMinMax(GRGEN_LIBGR.IActionExecutionEnvironment actionEnv, int min, int max, params object[] parameters)\n");
            sb.AppendFront("{\n");
            sb.Indent(); 
            sb.AppendFrontFormat("return ApplyMinMax(actionEnv, min, max{0});\n", inArgumentsFromArray);
            sb.Unindent(); 
            sb.AppendFront("}\n");

            sb.AppendFront("void GRGEN_LIBGR.IAction.Filter(GRGEN_LIBGR.IActionExecutionEnvironment actionEnv, GRGEN_LIBGR.IMatches matches, GRGEN_LIBGR.FilterCall filter)\n");
            sb.AppendFront("{\n");
            sb.Indent();
            sb.AppendFront("if(filter.IsAutoSupplied) {\n");
            sb.Indent();
            sb.AppendFront("switch(filter.Name) {\n");
            sb.Indent();
            sb.AppendFront("case \"keepFirst\": matches.FilterKeepFirst((int)(filter.ArgumentExpressions[0]!=null ? filter.ArgumentExpressions[0].Evaluate((GRGEN_LIBGR.IGraphProcessingEnvironment)actionEnv) : filter.Arguments[0])); break;\n");
            sb.AppendFront("case \"keepLast\": matches.FilterKeepLast((int)(filter.ArgumentExpressions[0]!=null ? filter.ArgumentExpressions[0].Evaluate((GRGEN_LIBGR.IGraphProcessingEnvironment)actionEnv) : filter.Arguments[0])); break;\n");
            sb.AppendFront("case \"keepFirstFraction\": matches.FilterKeepFirstFraction((double)(filter.ArgumentExpressions[0]!=null ? filter.ArgumentExpressions[0].Evaluate((GRGEN_LIBGR.IGraphProcessingEnvironment)actionEnv) : filter.Arguments[0])); break;\n");
            sb.AppendFront("case \"keepLastFraction\": matches.FilterKeepLastFraction((double)(filter.ArgumentExpressions[0]!=null ? filter.ArgumentExpressions[0].Evaluate((GRGEN_LIBGR.IGraphProcessingEnvironment)actionEnv) : filter.Arguments[0])); break;\n");
            sb.AppendFront("case \"removeFirst\": matches.FilterRemoveFirst((int)(filter.ArgumentExpressions[0]!=null ? filter.ArgumentExpressions[0].Evaluate((GRGEN_LIBGR.IGraphProcessingEnvironment)actionEnv) : filter.Arguments[0])); break;\n");
            sb.AppendFront("case \"removeLast\": matches.FilterRemoveLast((int)(filter.ArgumentExpressions[0]!=null ? filter.ArgumentExpressions[0].Evaluate((GRGEN_LIBGR.IGraphProcessingEnvironment)actionEnv) : filter.Arguments[0])); break;\n");
            sb.AppendFront("case \"removeFirstFraction\": matches.FilterRemoveFirstFraction((double)(filter.ArgumentExpressions[0]!=null ? filter.ArgumentExpressions[0].Evaluate((GRGEN_LIBGR.IGraphProcessingEnvironment)actionEnv) : filter.Arguments[0])); break;\n");
            sb.AppendFront("case \"removeLastFraction\": matches.FilterRemoveLastFraction((double)(filter.ArgumentExpressions[0]!=null ? filter.ArgumentExpressions[0].Evaluate((GRGEN_LIBGR.IGraphProcessingEnvironment)actionEnv) : filter.Arguments[0])); break;\n");
            sb.AppendFront("default: throw new Exception(\"Unknown auto supplied filter name!\");\n");
            sb.Unindent();
            sb.AppendFront("}\n");
            sb.AppendFront("return;\n");
            sb.Unindent();
            sb.AppendFront("}\n");
            sb.AppendFront("switch(filter.FullName) {\n");
            sb.Indent();
            foreach(IFilter filter in matchingPattern.Filters)
            {
                if(filter is IFilterAutoGenerated)
                {
                    if(((IFilterAutoGenerated)filter).Entity != null)
                    {
                        sb.AppendFrontFormat("case \"{1}<{2}>\": GRGEN_ACTIONS.{4}MatchFilters.Filter_{0}_{1}_{2}((GRGEN_LGSP.LGSPGraphProcessingEnvironment)actionEnv, ({3})matches); break;\n",
                            patternName, filter.Name, ((IFilterAutoGenerated)filter).Entity, matchesType, TypesHelper.GetPackagePrefixDot(filter.Package));
                        if(filter.Package != null)
                            sb.AppendFrontFormat("case \"{5}{1}<{2}>\": GRGEN_ACTIONS.{4}MatchFilters.Filter_{0}_{1}_{2}((GRGEN_LGSP.LGSPGraphProcessingEnvironment)actionEnv, ({3})matches); break;\n",
                                patternName, filter.Name, ((IFilterAutoGenerated)filter).Entity, matchesType, filter.Package + ".", filter.Package + "::");
                    }
                    else // auto
                    {
                        sb.AppendFrontFormat("case \"{1}\": GRGEN_ACTIONS.{3}MatchFilters.Filter_{0}_{1}((GRGEN_LGSP.LGSPGraphProcessingEnvironment)actionEnv, ({2})matches); break;\n",
                            patternName, filter.Name, matchesType, TypesHelper.GetPackagePrefixDot(filter.Package));
                        if(filter.Package != null)
                            sb.AppendFrontFormat("case \"{4}{1}\": GRGEN_ACTIONS.{3}MatchFilters.Filter_{0}_{1}((GRGEN_LGSP.LGSPGraphProcessingEnvironment)actionEnv, ({2})matches); break;\n",
                                patternName, filter.Name, matchesType, filter.Package + ".", filter.Package + "::");
                    }
                }
                else
                {
                    IFilterFunction filterFunction = (IFilterFunction)filter;
                    sb.AppendFrontFormat("case \"{0}\": GRGEN_ACTIONS.{1}MatchFilters.Filter_{2}((GRGEN_LGSP.LGSPGraphProcessingEnvironment)actionEnv, ({3})matches",
                        filterFunction.Name, TypesHelper.GetPackagePrefixDot(filterFunction.Package), filterFunction.Name, matchesType);
                    for(int i=0; i<filterFunction.Inputs.Length; ++i)
                    {
                        sb.AppendFormat(", ({0})(filter.ArgumentExpressions[{1}]!=null ? filter.ArgumentExpressions[{1}].Evaluate((GRGEN_LIBGR.IGraphProcessingEnvironment)actionEnv) : filter.Arguments[{1}])", 
                            TypesHelper.TypeName(filterFunction.Inputs[i]), i);
                    }
                    sb.Append("); break;\n");
                    if(filter.Package != null)
                    {
                        sb.AppendFrontFormat("case \"{4}{0}\": GRGEN_ACTIONS.{1}MatchFilters.Filter_{2}((GRGEN_LGSP.LGSPGraphProcessingEnvironment)actionEnv, ({3})matches",
                            filterFunction.Name, TypesHelper.GetPackagePrefixDot(filterFunction.Package), filterFunction.Name, matchesType, filter.Package + "::");
                        for(int i = 0; i < filterFunction.Inputs.Length; ++i)
                        {
                            sb.AppendFormat(", ({0})(filter.ArgumentExpressions[{1}]!=null ? filter.ArgumentExpressions[{1}].Evaluate((GRGEN_LIBGR.IGraphProcessingEnvironment)actionEnv) : filter.Arguments[{1}])",
                                TypesHelper.TypeName(filterFunction.Inputs[i]), i);
                        }
                        sb.Append("); break;\n");
                    }
                }
            }
            sb.AppendFront("default: throw new Exception(\"Unknown filter name!\");\n");
            sb.Unindent();
            sb.AppendFront("}\n");
            sb.Unindent();
            sb.AppendFront("}\n");
        }
        /// <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>
        // generate the exact action interface
        /// </summary>
        void GenerateActionInterface(SourceBuilder sb, LGSPRulePattern matchingPattern)
        {
            String actionInterfaceName = "IAction_"+matchingPattern.name;
            String outParameters = "";
            String refParameters = "";
            String allParameters = "";
            for(int i = 0; i < matchingPattern.Outputs.Length; ++i)
            {
                outParameters += ", out " + TypesHelper.TypeName(matchingPattern.Outputs[i]) + " output_"+i;
                refParameters += ", ref " + TypesHelper.TypeName(matchingPattern.Outputs[i]) + " output_"+i;
                allParameters += ", List<" + TypesHelper.TypeName(matchingPattern.Outputs[i]) + "> output_"+i;
            }
 
            String inParameters = "";
            for(int i=0; i<matchingPattern.Inputs.Length; ++i) {
                inParameters += ", " + TypesHelper.TypeName(matchingPattern.Inputs[i]) + " " + matchingPattern.InputNames[i];
            }
            String matchingPatternClassName = matchingPattern.GetType().Name;
            String patternName = matchingPattern.name;
            String matchType = matchingPatternClassName + "." + NamesOfEntities.MatchInterfaceName(patternName);
            String matchesType = "GRGEN_LIBGR.IMatchesExact<" + matchType + ">" ;

            if(matchingPattern.PatternGraph.Package != null)
            {
                sb.AppendFrontFormat("namespace {0}\n", matchingPattern.PatternGraph.Package);
                sb.AppendFront("{\n");
                sb.Indent();
            }

            sb.AppendFront("/// <summary>\n");
            sb.AppendFront("/// An object representing an executable rule - same as IAction, but with exact types and distinct parameters.\n");
            sb.AppendFront("/// </summary>\n");
            sb.AppendFrontFormat("public interface {0}\n", actionInterfaceName);
            sb.AppendFront("{\n");
            sb.Indent();
            sb.AppendFront("/// <summary> same as IAction.Match, but with exact types and distinct parameters. </summary>\n");
            sb.AppendFrontFormat("{0} Match(GRGEN_LIBGR.IActionExecutionEnvironment actionEnv, int maxMatches{1});\n", matchesType, inParameters);

            sb.AppendFront("/// <summary> same as IAction.Modify, but with exact types and distinct parameters. </summary>\n");
            sb.AppendFrontFormat("void Modify(GRGEN_LIBGR.IActionExecutionEnvironment actionEnv, {0} match{1});\n", matchType, outParameters);

            sb.AppendFront("/// <summary> same as IAction.ModifyAll, but with exact types and distinct parameters. </summary>\n");
            sb.AppendFrontFormat("void ModifyAll(GRGEN_LIBGR.IActionExecutionEnvironment actionEnv, {0} matches{1});\n", matchesType, allParameters);

            sb.AppendFront("/// <summary> same as IAction.Apply, but with exact types and distinct parameters; returns true if applied </summary>\n");
            sb.AppendFrontFormat("bool Apply(GRGEN_LIBGR.IActionExecutionEnvironment actionEnv{0}{1});\n", inParameters, refParameters);

            sb.AppendFront("/// <summary> same as IAction.ApplyAll, but with exact types and distinct parameters; returns the number of matches found/applied. </summary>\n");
            sb.AppendFrontFormat("int ApplyAll(int maxMatches, GRGEN_LIBGR.IActionExecutionEnvironment actionEnv{0}{1});\n", inParameters, allParameters);

            sb.AppendFront("/// <summary> same as IAction.ApplyStar, but with exact types and distinct parameters. </summary>\n");
            sb.AppendFrontFormat("bool ApplyStar(GRGEN_LIBGR.IActionExecutionEnvironment actionEnv{0});\n", inParameters);

            sb.AppendFront("/// <summary> same as IAction.ApplyPlus, but with exact types and distinct parameters. </summary>\n");
            sb.AppendFrontFormat("bool ApplyPlus(GRGEN_LIBGR.IActionExecutionEnvironment actionEnv{0});\n", inParameters);

            sb.AppendFront("/// <summary> same as IAction.ApplyMinMax, but with exact types and distinct parameters. </summary>\n");
            sb.AppendFrontFormat("bool ApplyMinMax(GRGEN_LIBGR.IActionExecutionEnvironment actionEnv, int min, int max{0});\n", inParameters);
            sb.Unindent();
            sb.AppendFront("}\n");
            
            if(matchingPattern.PatternGraph.Package != null)
            {
                sb.Unindent();
                sb.AppendFront("}\n");
            }

            sb.AppendFront("\n");
        }
        /// <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>
        /// 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 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>
        /// Generates memory pooling code for matching tasks of class given by it's name
        /// </summary>
        private void GenerateTasksMemoryPool(SourceBuilder sb, String className, bool isAlternative, bool isIterationBreaking, int branchingFactor)
        {
            // getNewTask method handing out new task from pool or creating task if pool is empty
            if(isAlternative)
                sb.AppendFront("public static " + className + " getNewTask(GRGEN_LGSP.LGSPActionExecutionEnvironment actionEnv_, "
                    + "Stack<GRGEN_LGSP.LGSPSubpatternAction> openTasks_, GRGEN_LGSP.PatternGraph[] patternGraphs_) {\n");
            else
                sb.AppendFront("public static " + className + " getNewTask(GRGEN_LGSP.LGSPActionExecutionEnvironment actionEnv_, "
                    + "Stack<GRGEN_LGSP.LGSPSubpatternAction> openTasks_) {\n");
            sb.Indent();
            sb.AppendFront(className + " newTask;\n");
            sb.AppendFront("if(numFreeTasks>0) {\n");
            sb.Indent();
            sb.AppendFront("newTask = freeListHead;\n"); 
            sb.AppendFront("newTask.actionEnv = actionEnv_; newTask.openTasks = openTasks_;\n");
            if(isAlternative)
                sb.AppendFront("newTask.patternGraphs = patternGraphs_;\n");
            else if(isIterationBreaking)
                sb.AppendFront("newTask.breakIteration = false;\n");
            sb.AppendFront("freeListHead = newTask.next;\n");
            sb.AppendFront("newTask.next = null;\n");
            sb.AppendFront("--numFreeTasks;\n");
            sb.Unindent();
            sb.AppendFront("} else {\n");
            sb.Indent();
            if(isAlternative)
                sb.AppendFront("newTask = new " + className + "(actionEnv_, openTasks_, patternGraphs_);\n");
            else
                sb.AppendFront("newTask = new " + className + "(actionEnv_, openTasks_);\n");
            sb.Unindent();
            sb.AppendFront("}\n");
            sb.AppendFront("return newTask;\n");
            sb.Unindent();
            sb.AppendFront("}\n\n");

            // releaseTask method recycling task into pool if pool is not full
            sb.AppendFront("public static void releaseTask(" + className + " oldTask) {\n");
            sb.Indent();
            sb.AppendFront("if(numFreeTasks<MAX_NUM_FREE_TASKS) {\n");
            sb.Indent();
            sb.AppendFront("oldTask.next = freeListHead;\n");
            sb.AppendFront("oldTask.actionEnv = null; oldTask.openTasks = null;\n");
            sb.AppendFront("freeListHead = oldTask;\n");
            sb.AppendFront("++numFreeTasks;\n");
            sb.Unindent();
            sb.AppendFront("}\n");
            sb.Unindent();
            sb.AppendFront("}\n\n");

            // tasks pool administration data
            sb.AppendFront("private static " + className + " freeListHead = null;\n");
            sb.AppendFront("private static int numFreeTasks = 0;\n");
            sb.AppendFront("private const int MAX_NUM_FREE_TASKS = 100;\n\n"); // todo: compute antiproportional to pattern size

            sb.AppendFront("private " + className + " next = null;\n\n");

            // for parallelized subpatterns/alternatives/iterateds we need a freelist per thread
            if(branchingFactor > 1)
            {
                // getNewTask method handing out new task from pool or creating task if pool is empty
                if(isAlternative)
                    sb.AppendFront("public static " + className + " getNewTask(GRGEN_LGSP.LGSPActionExecutionEnvironment actionEnv_, "
                        + "Stack<GRGEN_LGSP.LGSPSubpatternAction> openTasks_, GRGEN_LGSP.PatternGraph[] patternGraphs_, int threadId) {\n");
                else
                    sb.AppendFront("public static " + className + " getNewTask(GRGEN_LGSP.LGSPActionExecutionEnvironment actionEnv_, "
                        + "Stack<GRGEN_LGSP.LGSPSubpatternAction> openTasks_, int threadId) {\n");
                sb.Indent();
                sb.AppendFront(className + " newTask;\n");
                sb.AppendFront("if(numFreeTasks_perWorker[threadId]>0) {\n");
                sb.Indent();
                sb.AppendFront("newTask = freeListHead_perWorker[threadId];\n");
                sb.AppendFront("newTask.actionEnv = actionEnv_; newTask.openTasks = openTasks_;\n");
                if(isAlternative)
                    sb.AppendFront("newTask.patternGraphs = patternGraphs_;\n");
                else if(isIterationBreaking)
                    sb.AppendFront("newTask.breakIteration = false;\n");
                sb.AppendFront("freeListHead_perWorker[threadId] = newTask.next;\n");
                sb.AppendFront("newTask.next = null;\n");
                sb.AppendFront("--numFreeTasks_perWorker[threadId];\n");
                sb.Unindent();
                sb.AppendFront("} else {\n");
                sb.Indent();
                if(isAlternative)
                    sb.AppendFront("newTask = new " + className + "(actionEnv_, openTasks_, patternGraphs_);\n");
                else
                    sb.AppendFront("newTask = new " + className + "(actionEnv_, openTasks_);\n");
                sb.Unindent();
                sb.AppendFront("}\n");
                sb.AppendFront("return newTask;\n");
                sb.Unindent();
                sb.AppendFront("}\n\n");

                // releaseTask method recycling task into pool if pool is not full
                sb.AppendFront("public static void releaseTask(" + className + " oldTask, int threadId) {\n");
                sb.Indent();
                sb.AppendFront("if(numFreeTasks_perWorker[threadId]<MAX_NUM_FREE_TASKS/2) {\n");
                sb.Indent();
                sb.AppendFront("oldTask.next = freeListHead_perWorker[threadId];\n");
                sb.AppendFront("oldTask.actionEnv = null; oldTask.openTasks = null;\n");
                sb.AppendFront("freeListHead_perWorker[threadId] = oldTask;\n");
                sb.AppendFront("++numFreeTasks_perWorker[threadId];\n");
                sb.Unindent();
                sb.AppendFront("}\n");
                sb.Unindent();
                sb.AppendFront("}\n\n");

                // tasks pool administration data
                sb.AppendFront("private static " + className + "[] freeListHead_perWorker = new " + className + "[Math.Min(" + branchingFactor + ", Environment.ProcessorCount)];\n");
                sb.AppendFront("private static int[] numFreeTasks_perWorker = new int[Math.Min(" + branchingFactor + ", Environment.ProcessorCount)];\n");
            }
        }
 /// <summary>
 /// Generates file header for actions file into given source builer
 /// </summary>
 public void GenerateFileHeaderForActionsFile(SourceBuilder sb,
         String namespaceOfModel, String namespaceOfRulePatterns)
 {
     sb.AppendFront("using System;\n"
         + "using System.Collections.Generic;\n"
         + "using System.Collections;\n"
         + "using System.Text;\n"
         + "using System.Threading;\n"
         + "using GRGEN_LIBGR = de.unika.ipd.grGen.libGr;\n"
         + "using GRGEN_EXPR = de.unika.ipd.grGen.expression;\n"
         + "using GRGEN_LGSP = de.unika.ipd.grGen.lgsp;\n"
         + "using GRGEN_MODEL = " + namespaceOfModel + ";\n"
         + "using GRGEN_ACTIONS = " + namespaceOfRulePatterns + ";\n"
         + "using " + namespaceOfRulePatterns + ";\n\n");
     sb.AppendFront("namespace de.unika.ipd.grGen.lgspActions\n");
     sb.AppendFront("{\n");
     sb.Indent(); // namespace level
 }
        /// <summary>
        /// Generates an LGSPAction object for the given scheduled search plan.
        /// </summary>
        /// <param name="action">Needed for the rule pattern and the name</param>
        /// <param name="sourceOutputFilename">null if no output file needed</param>
        public LGSPAction GenerateAction(ScheduledSearchPlan scheduledSearchPlan, LGSPAction action,
            String modelAssemblyLocation, String actionAssemblyLocation, String sourceOutputFilename)
        {
            SourceBuilder sourceCode = new SourceBuilder(CommentSourceCode);
            GenerateFileHeaderForActionsFile(sourceCode, model.GetType().Namespace, action.rulePattern.GetType().Namespace);

            // can't generate new subpattern matchers due to missing scheduled search plans for them / missing graph analyze data
            Debug.Assert(action.rulePattern.patternGraph.embeddedGraphsPlusInlined.Length == 0);

            GenerateActionAndMatcher(sourceCode, action.rulePattern, false);

            // close namespace
            sourceCode.Append("}");

            // write generated source to file if requested
            if(sourceOutputFilename != null)
            {
                StreamWriter writer = new StreamWriter(sourceOutputFilename);
                writer.Write(sourceCode.ToString());
                writer.Close();
            }

            // set up compiler
            CSharpCodeProvider compiler = new CSharpCodeProvider();
            CompilerParameters compParams = GetDynCompilerSetup(modelAssemblyLocation, actionAssemblyLocation);

//            Stopwatch compilerWatch = Stopwatch.StartNew();

            // compile generated code
            CompilerResults compResults = compiler.CompileAssemblyFromSource(compParams, sourceCode.ToString());
            if(compResults.Errors.HasErrors)
            {
                String errorMsg = compResults.Errors.Count + " Errors:";
                foreach(CompilerError error in compResults.Errors)
                    errorMsg += Environment.NewLine + "Line: " + error.Line + " - " + error.ErrorText;
                throw new ArgumentException("Illegal dynamic C# source code produced for actions \"" + action.Name + "\": " + errorMsg);
            }

            // create action instance
            Object obj = compResults.CompiledAssembly.CreateInstance("de.unika.ipd.grGen.lgspActions.DynAction_" + action.Name);

//            long compSourceTicks = compilerWatch.ElapsedTicks;
//            Console.WriteLine("GenMatcher: Compile source: {0} us", compSourceTicks / (Stopwatch.Frequency / 1000000));
            return (LGSPAction) obj;
        }
        /// <summary>
        /// Generates matcher class head source code for the pattern 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>
        void GenerateMatcherClassHeadAction(SourceBuilder sb, LGSPRulePattern rulePattern, 
            bool isInitialStatic, SearchProgram searchProgram)
        {
            PatternGraph patternGraph = (PatternGraph)rulePattern.PatternGraph;
                
            String namePrefix = (isInitialStatic ? "" : "Dyn") + "Action_";
            String className = namePrefix + rulePattern.name;
            String rulePatternClassName = rulePattern.GetType().Name;
            String matchClassName = rulePatternClassName + "." + "Match_" + rulePattern.name;
            String matchInterfaceName = rulePatternClassName + "." + "IMatch_" + rulePattern.name;
            String actionInterfaceName = "IAction_" + rulePattern.name;

            if(patternGraph.Package != null)
            {
                sb.AppendFrontFormat("namespace {0}\n", patternGraph.Package);
                sb.AppendFront("{\n");
                sb.Indent();
            }

            sb.AppendFront("public class " + className + " : GRGEN_LGSP.LGSPAction, "
                + "GRGEN_LIBGR.IAction, " + actionInterfaceName + "\n");
            sb.AppendFront("{\n");
            sb.Indent(); // class level

            sb.AppendFront("public " + className + "() {\n");
            sb.Indent(); // method body level
            sb.AppendFront("_rulePattern = " + rulePatternClassName + ".Instance;\n");
            sb.AppendFront("patternGraph = _rulePattern.patternGraph;\n");
            if(rulePattern.patternGraph.branchingFactor < 2)
            {
                sb.AppendFront("DynamicMatch = myMatch;\n");
                if(!isInitialStatic)
                    sb.AppendFrontFormat("GRGEN_ACTIONS.Action_{0}.Instance.DynamicMatch = myMatch;\n", rulePattern.name);
            }
            else
            {
                sb.AppendFront("if(Environment.ProcessorCount == 1)\n");
                sb.AppendFront("{\n");
                sb.AppendFront("\tDynamicMatch = myMatch;\n");
                if(!isInitialStatic)
                    sb.AppendFrontFormat("\tGRGEN_ACTIONS.Action_{0}.Instance.DynamicMatch = myMatch;\n", rulePattern.name);
                sb.AppendFront("}\n");
                sb.AppendFront("else\n");
                sb.AppendFront("{\n");
                sb.Indent();
                sb.AppendFront("DynamicMatch = myMatch_parallelized;\n");
                if(!isInitialStatic)
                    sb.AppendFrontFormat("GRGEN_ACTIONS.Action_{0}.Instance.DynamicMatch = myMatch_parallelized;\n", rulePattern.name);
                sb.AppendFrontFormat("numWorkerThreads = GRGEN_LGSP.WorkerPool.EnsurePoolSize({0});\n", rulePattern.patternGraph.branchingFactor);
                sb.AppendFrontFormat("parallelTaskMatches = new GRGEN_LGSP.LGSPMatchesList<{0}, {1}>[numWorkerThreads];\n", matchClassName, matchInterfaceName);
                sb.AppendFront("moveHeadAfterNodes = new List<GRGEN_LGSP.LGSPNode>[numWorkerThreads];\n");
                sb.AppendFront("moveHeadAfterEdges = new List<GRGEN_LGSP.LGSPEdge>[numWorkerThreads];\n");
                sb.AppendFront("moveOutHeadAfter = new List<KeyValuePair<GRGEN_LGSP.LGSPNode, GRGEN_LGSP.LGSPEdge>>[numWorkerThreads];\n");
                sb.AppendFront("moveInHeadAfter = new List<KeyValuePair<GRGEN_LGSP.LGSPNode, GRGEN_LGSP.LGSPEdge>>[numWorkerThreads];\n");
                sb.AppendFront("for(int i=0; i<numWorkerThreads; ++i)\n");
                sb.AppendFront("{\n");
                sb.Indent();
                sb.AppendFront("moveHeadAfterNodes[i] = new List<GRGEN_LGSP.LGSPNode>();\n");
                sb.AppendFront("moveHeadAfterEdges[i] = new List<GRGEN_LGSP.LGSPEdge>();\n");
                sb.AppendFront("moveOutHeadAfter[i] = new List<KeyValuePair<GRGEN_LGSP.LGSPNode, GRGEN_LGSP.LGSPEdge>>();\n");
                sb.AppendFront("moveInHeadAfter[i] = new List<KeyValuePair<GRGEN_LGSP.LGSPNode, GRGEN_LGSP.LGSPEdge>>();\n");
                sb.Unindent();
                sb.AppendFront("}\n");

                sb.AppendFront("for(int i=0; i<parallelTaskMatches.Length; ++i)\n");
                sb.AppendFrontFormat("\tparallelTaskMatches[i] = new GRGEN_LGSP.LGSPMatchesList<{0}, {1}>(this);\n", matchClassName, matchInterfaceName);
                sb.Unindent();
                sb.AppendFront("}\n");
            }
            sb.AppendFrontFormat("ReturnArray = new object[{0}];\n", rulePattern.Outputs.Length);
            sb.AppendFront("matches = new GRGEN_LGSP.LGSPMatchesList<" + matchClassName +", " + matchInterfaceName + ">(this);\n");
            sb.Unindent(); // class level
            sb.AppendFront("}\n\n");

            sb.AppendFront("public " + rulePatternClassName + " _rulePattern;\n");
            sb.AppendFront("public override GRGEN_LGSP.LGSPRulePattern rulePattern { get { return _rulePattern; } }\n");
            sb.AppendFront("public override string Name { get { return \"" + rulePattern.name + "\"; } }\n");
            sb.AppendFront("private GRGEN_LGSP.LGSPMatchesList<" + matchClassName + ", " + matchInterfaceName + "> matches;\n\n");

            if (isInitialStatic)
            {
                sb.AppendFront("public static " + className + " Instance { get { return instance; } set { instance = value; } }\n");
                sb.AppendFront("private static " + className + " instance = new " + className + "();\n");
            }

            GenerateIndependentsMatchObjects(sb, rulePattern, patternGraph);

            sb.AppendFront("\n");

            GenerateParallelizationSetupAsNeeded(sb, rulePattern, searchProgram);
        }
Exemple #53
0
 public override void Emit(SourceBuilder sourceCode)
 {
     sourceCode.Append(NamesOfEntities.Variable(Left));
     sourceCode.Append("[");
     Index.Emit(sourceCode);
     sourceCode.Append("] = ");
     Right.Emit(sourceCode);
     sourceCode.Append(";\n");
 }
        void GenerateParallelizationSetupAsNeeded(SourceBuilder sb, LGSPRulePattern rulePattern, SearchProgram searchProgram)
        {
            if(rulePattern.patternGraph.branchingFactor < 2)
                return;

            foreach(SearchOperation so in rulePattern.patternGraph.parallelizedSchedule[0].Operations)
            {
                switch(so.Type)
                {
                    case SearchOperationType.WriteParallelPreset:
                        if(so.Element is SearchPlanNodeNode)
                            sb.AppendFrontFormat("GRGEN_LGSP.LGSPNode {0};\n", NamesOfEntities.IterationParallelizationParallelPresetCandidate(((SearchPlanNodeNode)so.Element).PatternElement.Name));
                        else //SearchPlanEdgeNode
                            sb.AppendFrontFormat("GRGEN_LGSP.LGSPEdge {0};\n", NamesOfEntities.IterationParallelizationParallelPresetCandidate(((SearchPlanEdgeNode)so.Element).PatternElement.Name));
                        break;
                    case SearchOperationType.WriteParallelPresetVar:
                        sb.AppendFrontFormat("{0} {1};\n",
                            TypesHelper.TypeName(((PatternVariable)so.Element).Type),
                            NamesOfEntities.IterationParallelizationParallelPresetCandidate(((PatternVariable)so.Element).Name));
                        break;
                    case SearchOperationType.SetupParallelLookup:
                        if(so.Element is SearchPlanNodeNode)
                        {
                            sb.AppendFrontFormat("GRGEN_LGSP.LGSPNode {0};\n", NamesOfEntities.IterationParallelizationListHead(((SearchPlanNodeNode)so.Element).PatternElement.Name));
                            sb.AppendFrontFormat("GRGEN_LGSP.LGSPNode {0};\n", NamesOfEntities.IterationParallelizationNextCandidate(((SearchPlanNodeNode)so.Element).PatternElement.Name));
                        }
                        else
                        {
                            sb.AppendFrontFormat("GRGEN_LGSP.LGSPEdge {0};\n", NamesOfEntities.IterationParallelizationListHead(((SearchPlanEdgeNode)so.Element).PatternElement.Name));
                            sb.AppendFrontFormat("GRGEN_LGSP.LGSPEdge {0};\n", NamesOfEntities.IterationParallelizationNextCandidate(((SearchPlanEdgeNode)so.Element).PatternElement.Name));
                        }
                        break;
                    case SearchOperationType.SetupParallelPickFromStorage:
                        if(TypesHelper.DotNetTypeToXgrsType(so.Storage.Variable.type).StartsWith("set") || TypesHelper.DotNetTypeToXgrsType(so.Storage.Variable.type).StartsWith("map"))
                        {
                            sb.AppendFrontFormat("IEnumerator<KeyValuePair<{0},{1}>> {2};\n",
                                TypesHelper.XgrsTypeToCSharpType(TypesHelper.ExtractSrc(TypesHelper.DotNetTypeToXgrsType(so.Storage.Variable.Type)), model),
                                TypesHelper.XgrsTypeToCSharpType(TypesHelper.ExtractDst(TypesHelper.DotNetTypeToXgrsType(so.Storage.Variable.Type)), model),
                                NamesOfEntities.IterationParallelizationIterator(((SearchPlanNode)so.Element).PatternElement.Name));
                        }
                        else
                        {
                            sb.AppendFrontFormat("IEnumerator<{0}> {1};\n",
                                TypesHelper.XgrsTypeToCSharpType(TypesHelper.ExtractSrc(TypesHelper.DotNetTypeToXgrsType(so.Storage.Variable.Type)), model),
                                NamesOfEntities.IterationParallelizationIterator(((SearchPlanNode)so.Element).PatternElement.Name));
                        }
                        break;
                    case SearchOperationType.SetupParallelPickFromStorageDependent:
                        if(TypesHelper.AttributeTypeToXgrsType(so.Storage.Attribute.Attribute).StartsWith("set") || TypesHelper.AttributeTypeToXgrsType(so.Storage.Attribute.Attribute).StartsWith("map"))
                        {
                            sb.AppendFrontFormat("IEnumerator<KeyValuePair<{0},{1}>> {2};\n",
                               TypesHelper.XgrsTypeToCSharpType(TypesHelper.ExtractSrc(TypesHelper.AttributeTypeToXgrsType(so.Storage.Attribute.Attribute)), model),
                               TypesHelper.XgrsTypeToCSharpType(TypesHelper.ExtractDst(TypesHelper.AttributeTypeToXgrsType(so.Storage.Attribute.Attribute)), model),
                               NamesOfEntities.IterationParallelizationIterator(((SearchPlanNode)so.Element).PatternElement.Name));
                        }
                        else
                        {
                            sb.AppendFrontFormat("IEnumerator<{0}> {1};\n",
                               TypesHelper.XgrsTypeToCSharpType(TypesHelper.ExtractSrc(TypesHelper.AttributeTypeToXgrsType(so.Storage.Attribute.Attribute)), model),
                               NamesOfEntities.IterationParallelizationIterator(((SearchPlanNode)so.Element).PatternElement.Name));
                        }
                        break;
                    case SearchOperationType.SetupParallelPickFromIndex:
                        sb.AppendFrontFormat("IEnumerator<{0}> {1};\n",
                           TypesHelper.TypeName(so.IndexAccess.Index is AttributeIndexDescription ?
                               ((AttributeIndexDescription)so.IndexAccess.Index).GraphElementType :
                               ((IncidenceCountIndexDescription)so.IndexAccess.Index).StartNodeType),
                           NamesOfEntities.IterationParallelizationIterator(((SearchPlanNode)so.Element).PatternElement.Name));
                        break;
                    case SearchOperationType.SetupParallelPickFromIndexDependent:
                        sb.AppendFrontFormat("IEnumerator<{0}> {1};\n",
                           TypesHelper.TypeName(so.IndexAccess.Index is AttributeIndexDescription ?
                               ((AttributeIndexDescription)so.IndexAccess.Index).GraphElementType :
                               ((IncidenceCountIndexDescription)so.IndexAccess.Index).StartNodeType),
                           NamesOfEntities.IterationParallelizationIterator(((SearchPlanNode)so.Element).PatternElement.Name));
                        break;
                    case SearchOperationType.SetupParallelIncoming:
                    case SearchOperationType.SetupParallelOutgoing:
                        sb.AppendFrontFormat("GRGEN_LGSP.LGSPEdge {0};\n", NamesOfEntities.IterationParallelizationListHead(((SearchPlanEdgeNode)so.Element).PatternElement.Name));
                        sb.AppendFrontFormat("GRGEN_LGSP.LGSPEdge {0};\n", NamesOfEntities.IterationParallelizationNextCandidate(((SearchPlanEdgeNode)so.Element).PatternElement.Name));
                        break;
                    case SearchOperationType.SetupParallelIncident:
                        sb.AppendFrontFormat("GRGEN_LGSP.LGSPEdge {0};\n", NamesOfEntities.IterationParallelizationListHead(((SearchPlanEdgeNode)so.Element).PatternElement.Name));
                        sb.AppendFrontFormat("GRGEN_LGSP.LGSPEdge {0};\n", NamesOfEntities.IterationParallelizationNextCandidate(((SearchPlanEdgeNode)so.Element).PatternElement.Name));
                        sb.AppendFrontFormat("int {0};\n", NamesOfEntities.IterationParallelizationDirectionRunCounterVariable(((SearchPlanEdgeNode)so.Element).PatternElement.Name));
                        break;
                }
            }
            sb.AppendFront("\n");

            String rulePatternClassName = rulePattern.GetType().Name;
            String matchClassName = rulePatternClassName + "." + "Match_" + rulePattern.name;
            String matchInterfaceName = rulePatternClassName + "." + "IMatch_" + rulePattern.name;
            sb.AppendFront("private static GRGEN_LGSP.LGSPMatchesList<" + matchClassName + ", " + matchInterfaceName + ">[] parallelTaskMatches;\n");
            sb.AppendFront("private static int numWorkerThreads;\n");
            sb.AppendFront("private static int iterationNumber;\n");
            sb.AppendFront("private static int iterationLock;\n");
            sb.AppendFront("[ThreadStatic] private static int currentIterationNumber;\n");
            sb.AppendFront("[ThreadStatic] private static int threadId;\n");
            sb.AppendFront("private static GRGEN_LGSP.LGSPActionExecutionEnvironment actionEnvParallel;\n");
            sb.AppendFront("private static int maxMatchesParallel;\n");
            sb.AppendFront("private static bool maxMatchesFound = false;\n");

            sb.AppendFront("private static List<GRGEN_LGSP.LGSPNode>[] moveHeadAfterNodes;\n");
            sb.AppendFront("private static List<GRGEN_LGSP.LGSPEdge>[] moveHeadAfterEdges;\n");
            sb.AppendFront("private static List<KeyValuePair<GRGEN_LGSP.LGSPNode, GRGEN_LGSP.LGSPEdge>>[] moveOutHeadAfter;\n");
            sb.AppendFront("private static List<KeyValuePair<GRGEN_LGSP.LGSPNode, GRGEN_LGSP.LGSPEdge>>[] moveInHeadAfter;\n");
            sb.AppendFront("\n");
        }
Exemple #55
0
        public override void Emit(SourceBuilder sourceCode)
        {
            String ascendingVar = "ascending_" + fetchId().ToString();
            String entryVar = "entry_" + fetchId().ToString();
            String limitVar = "limit_" + fetchId().ToString();
            sourceCode.AppendFront("int " + entryVar + " = (int)(");
            Left.Emit(sourceCode);
            sourceCode.AppendFront(");\n");
            sourceCode.AppendFront("int " + limitVar + " = (int)(");
            Right.Emit(sourceCode);
            sourceCode.AppendFront(");\n");
            sourceCode.AppendFront("bool " + ascendingVar + " = " + entryVar + " <= " + limitVar + ";\n");

            sourceCode.AppendFront("while(" + ascendingVar + " ? " + entryVar + " <= " + limitVar + " : " + entryVar + " >= " + limitVar + ")\n");
            sourceCode.AppendFront("{\n");
            sourceCode.Indent();

            sourceCode.AppendFront(VariableType + " " + NamesOfEntities.Variable(Variable) + " = " + entryVar + ";\n");

            foreach(Yielding statement in Statements)
                statement.Emit(sourceCode);

            sourceCode.AppendFront("if(" + ascendingVar + ") ++" + entryVar + "; else --" + entryVar + ";\n");

            sourceCode.Unindent();
            sourceCode.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");
        }
 public override string ToString()
 {
     SourceBuilder sb = new SourceBuilder();
     Expr.Emit(sb);
     return Index.Name + "==" + sb.ToString();
 }
        /// <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");
        }
 public override string ToString()
 {
     SourceBuilder sb = new SourceBuilder();
     Expr.Emit(sb);
     return "unique[" + sb.ToString() + "]";
 }
        private void DumpScheduledSearchPlan(ScheduledSearchPlan ssp, String dumpname)
        {
            StreamWriter sw = new StreamWriter(dumpname + "-scheduledsp.txt", false);
            SourceBuilder sb = new SourceBuilder();
            ssp.Explain(sb, model);
            sb.Append("\n");
            sw.WriteLine(sb.ToString());
            sw.Close();

/*            StreamWriter sw = new StreamWriter(dumpname + "-scheduledsp.vcg", false);

            sw.WriteLine("graph:{\ninfoname 1: \"Attributes\"\ndisplay_edge_labels: no\nport_sharing: no\nsplines: no\n"
                + "\nmanhattan_edges: no\nsmanhattan_edges: no\norientation: bottom_to_top\nedges: yes\nnodes: yes\nclassname 1: \"normal\"");
            sw.WriteLine("node:{title:\"root\" label:\"ROOT\"}\n");
            SearchPlanNode root = new SearchPlanNode("root");

            sw.WriteLine("graph:{{title:\"pattern\" label:\"{0}\" status:clustered color:lightgrey", dumpname);

            foreach(SearchOperation op in ssp.Operations)
            {
                switch(op.Type)
                {
                    case SearchOperationType.Lookup:
                    case SearchOperationType.Incoming:
                    case SearchOperationType.Outgoing:
                    case SearchOperationType.ImplicitSource:
                    case SearchOperationType.ImplicitTarget:
                    {
                        SearchPlanNode spnode = (SearchPlanNode) op.Element;
                        DumpNode(sw, spnode);
                        SearchPlanNode src;
                        switch(op.Type)
                        {
                            case SearchOperationType.Lookup:
                            case SearchOperationType.ActionPreset:
                            case SearchOperationType.NegPreset:
                                src = root;
                                break;
                            default:
                                src = op.SourceSPNode;
                                break;
                        }
                        DumpEdge(sw, op.Type, src, spnode, op.CostToEnd, false);
                        break;
                    }
                    case SearchOperationType.Condition:
                        sw.WriteLine("node:{title:\"Condition\" label:\"CONDITION\"}\n");
                        break;
                    case SearchOperationType.NegativePattern:
                        sw.WriteLine("node:{title:\"NAC\" label:\"NAC\"}\n");
                        break;
                }
            }*/
        }