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) { sourceCode.AppendFrontFormat("{0}.{1} match_{2} = new {0}.{1}();\n", RulePatternClassName, NamesOfEntities.MatchClassName(PatternName), MatchName); sourceCode.AppendFrontFormat("match_{0}.SetMatchOfEnclosingPattern({1});\n", MatchName, MatchOfEnclosingPatternName); }
/// <summary> /// Generates match objects of independents /// </summary> protected void GenerateIndependentsMatchObjects(SourceBuilder sourceCode) { for (int i = 0; i < MatchingPatternClassTypeName.Count; ++i) { if (NestedIndependents[i] == null) { continue; } foreach (KeyValuePair <PatternGraph, bool> nestedIndependent in NestedIndependents[i]) { if (nestedIndependent.Value == false) { continue; // if independent is not nested in iterated with potentially more than one match then matcher-class-based match variables are sufficient, only one match is living at a time } if (nestedIndependent.Key.originalPatternGraph != null) { sourceCode.AppendFrontFormat("{0} {1} = new {0}();\n", 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 { sourceCode.AppendFrontFormat("{0} {1} = new {0}();\n", MatchingPatternClassTypeName[i] + "." + NamesOfEntities.MatchClassName(nestedIndependent.Key.pathPrefix + nestedIndependent.Key.name), NamesOfEntities.MatchedIndependentVariable(nestedIndependent.Key.pathPrefix + nestedIndependent.Key.name)); } } } }
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 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 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); }
public SequenceRuleCallMatcherGenerator(SequenceRuleCall seqRule, SequenceExpressionGenerator seqExprGen, SequenceGeneratorHelper seqHelper) { this.seqRule = seqRule; this.seqExprGen = seqExprGen; this.seqHelper = seqHelper; ArgumentExpressions = seqRule.ArgumentExpressions; String matchingPatternClassName = "GRGEN_ACTIONS." + TypesHelper.GetPackagePrefixDot(seqRule.Package) + "Rule_" + seqRule.Name; patternName = seqRule.Name; ruleName = "rule_" + TypesHelper.PackagePrefixedNameUnderscore(seqRule.Package, seqRule.Name); matchType = matchingPatternClassName + "." + NamesOfEntities.MatchInterfaceName(patternName); matchesType = "GRGEN_LIBGR.IMatchesExact<" + matchType + ">"; matchesName = "matches_" + seqRule.Id; }
public override void Emit(SourceBuilder sourceCode) { if (Type == EntityType.Node) { sourceCode.AppendFront(TypeOfEntity + " " + NamesOfEntities.CandidateVariable(NameOfEntity) + " = (" + TypeOfEntity + ")" + Initialization + ";\n"); } else if (Type == EntityType.Edge) { sourceCode.AppendFront(TypeOfEntity + " " + NamesOfEntities.CandidateVariable(NameOfEntity) + " = (" + TypeOfEntity + ")" + Initialization + ";\n"); } else //if(Type == EntityType.Variable) { sourceCode.AppendFront(TypeOfEntity + " " + NamesOfEntities.Variable(NameOfEntity) + " = (" + TypeOfEntity + ")" + Initialization + ";\n"); } }
void EmitHashComputation(SourceBuilder sourceCode, int i) { if (i < 0) { sourceCode.Append("23"); } else { sourceCode.Append("("); EmitHashComputation(sourceCode, i - 1); sourceCode.AppendFormat("*17 + {0}.GetHashCode()", NamesOfEntities.CandidateVariable(NeededElements[i])); sourceCode.Append(")"); } }
public override void Emit(SourceBuilder sourceCode) { sourceCode.AppendFrontFormat("if({0} != null)\n", NamesOfEntities.FoundMatchesForFilteringVariable()); sourceCode.AppendFront("{\n"); sourceCode.Indent(); // emit check whether hash is contained in found matches hash map sourceCode.AppendFrontFormat("if(!{0}.ContainsKey({1}))\n", NamesOfEntities.FoundMatchesForFilteringVariable(), NamesOfEntities.DuplicateMatchHashVariable()); sourceCode.AppendFront("{\n"); sourceCode.Indent(); // if not, just insert it sourceCode.AppendFrontFormat("{0}[{1}] = match;\n", NamesOfEntities.FoundMatchesForFilteringVariable(), NamesOfEntities.DuplicateMatchHashVariable()); sourceCode.Unindent(); sourceCode.AppendFront("}\n"); sourceCode.AppendFront("else\n"); sourceCode.AppendFront("{\n"); sourceCode.Indent(); // otherwise loop till end of collision list of the hash set, insert there sourceCode.AppendFrontFormat("{0} {1} = {2}[{3}];\n", RulePatternClassName + "." + NamesOfEntities.MatchClassName(PatternName), NamesOfEntities.DuplicateMatchCandidateVariable(), NamesOfEntities.FoundMatchesForFilteringVariable(), NamesOfEntities.DuplicateMatchHashVariable()); sourceCode.AppendFrontFormat("while({0}.nextWithSameHash != null) {0} = {0}.nextWithSameHash;\n", NamesOfEntities.DuplicateMatchCandidateVariable()); sourceCode.AppendFrontFormat("{0}.nextWithSameHash = match;\n", NamesOfEntities.DuplicateMatchCandidateVariable()); sourceCode.Unindent(); sourceCode.AppendFront("}\n"); if (ParallelizedAction) { sourceCode.AppendFrontFormat("match.{0} = {0};\n", NamesOfEntities.DuplicateMatchHashVariable()); } sourceCode.Unindent(); sourceCode.AppendFront("}\n"); }
public override void Emit(SourceBuilder sourceCode) { // emit check decision string variableContainingCandidate = NamesOfEntities.CandidateVariable(PatternElementName); string variableContainingOtherElement = NamesOfEntities.CandidateVariable(OtherPatternElementName); sourceCode.AppendFrontFormat("if({0}!={1}) ", variableContainingCandidate, variableContainingOtherElement); // emit check failed code sourceCode.Append("{\n"); sourceCode.Indent(); CheckFailedOperations.Emit(sourceCode); sourceCode.Unindent(); sourceCode.AppendFront("}\n"); }
public override void Emit(SourceBuilder sourceCode) { string targetPatternElement = Type == EntityType.Variable ? NamesOfEntities.Variable(TargetPatternElementName) : NamesOfEntities.CandidateVariable(TargetPatternElementName); if (SourcePatternElementUnprefixedName != null) { string sourcePatternElement = NamesOfEntities.MatchName(SourcePatternElementUnprefixedName, Type); sourceCode.AppendFrontFormat("{0} = {1}._{2}; // bubble up (from match)\n", targetPatternElement, NestedMatchOrTaskObjectName, sourcePatternElement); } else { sourceCode.AppendFrontFormat("{0} = {1}.{0}; // bubble up (from task)\n", targetPatternElement, NestedMatchOrTaskObjectName); } }
public SequenceSomeRuleCallRewritingGenerator(SequenceSomeFromSet seqSome, SequenceRuleCall seqRule, SequenceExpressionGenerator seqExprGen, SequenceGeneratorHelper seqHelper) { this.seqSome = seqSome; // parent this.seqExprGen = seqExprGen; this.seqHelper = seqHelper; this.seqRule = seqRule; specialStr = seqRule.Special ? "true" : "false"; matchingPatternClassName = "GRGEN_ACTIONS." + TypesHelper.GetPackagePrefixDot(seqRule.Package) + "Rule_" + seqRule.Name; patternName = seqRule.Name; ruleName = "rule_" + TypesHelper.PackagePrefixedNameUnderscore(seqRule.Package, seqRule.Name); matchType = matchingPatternClassName + "." + NamesOfEntities.MatchInterfaceName(patternName); matchName = "match_" + seqRule.Id; matchesType = "GRGEN_LIBGR.IMatchesExact<" + matchType + ">"; matchesName = "matches_" + seqRule.Id; }
public override void Emit(SourceBuilder sourceCode) { // emit check decision string variableContainingCandidate = NamesOfEntities.CandidateVariable(PatternElementName); if (Type == CheckCandidateForTypeType.ByIsAllowedType) { string isAllowedTypeArrayMemberOfRulePattern = IsAllowedArrayName + "_IsAllowedType"; sourceCode.AppendFrontFormat("if(!{0}.{1}[{2}.lgspType.TypeID]) ", RulePatternTypeName, isAllowedTypeArrayMemberOfRulePattern, variableContainingCandidate); } else if (Type == CheckCandidateForTypeType.ByIsMyType) { sourceCode.AppendFrontFormat("if(!{0}.isMyType[{1}.lgspType.TypeID]) ", TypeName, variableContainingCandidate); } else // Type == CheckCandidateForTypeType.ByTypeID) { sourceCode.AppendFront("if("); bool first = true; foreach (string typeID in TypeIDs) { if (first) { first = false; } else { sourceCode.Append(" && "); } sourceCode.AppendFormat("{0}.lgspType.TypeID!={1}", variableContainingCandidate, typeID); } sourceCode.Append(") "); } // emit check failed code sourceCode.Append("{\n"); sourceCode.Indent(); CheckFailedOperations.Emit(sourceCode); sourceCode.Unindent(); sourceCode.AppendFront("}\n"); }
public SequenceBacktrackGenerator(SequenceBacktrack seq, SequenceExpressionGenerator seqExprGen, SequenceGeneratorHelper seqHelper) { this.seq = seq; this.seqExprGen = seqExprGen; this.seqHelper = seqHelper; seqRule = seq.Rule; ArgumentExpressions = seqRule.ArgumentExpressions; ReturnVars = seqRule.ReturnVars; specialStr = seqRule.Special ? "true" : "false"; matchingPatternClassName = "GRGEN_ACTIONS." + TypesHelper.GetPackagePrefixDot(seqRule.Package) + "Rule_" + seqRule.Name; patternName = seqRule.Name; ruleName = "rule_" + TypesHelper.PackagePrefixedNameUnderscore(seqRule.Package, seqRule.Name); matchType = matchingPatternClassName + "." + NamesOfEntities.MatchInterfaceName(patternName); matchName = "match_" + seq.Id; matchesType = "GRGEN_LIBGR.IMatchesExact<" + matchType + ">"; matchesName = "matches_" + seq.Id; }
/// <summary> /// Emits the matcher source code for the search program /// head, search program operations list in depth first walk over search program operations list, tail /// </summary> public override void Emit(SourceBuilder sourceCode) { #if RANDOM_LOOKUP_LIST_START sourceCode.AppendFront("private Random random = new Random(13795661);\n"); #endif if (Parallel) { sourceCode.AppendFront("public override void " + Name + "_parallelized" + "(List<Stack<GRGEN_LIBGR.IMatch>> foundPartialMatches, " + "int maxMatches, int isoSpace, int threadId)\n"); } else { sourceCode.AppendFront("public override void " + Name + "(List<Stack<GRGEN_LIBGR.IMatch>> foundPartialMatches, " + "int maxMatches, int isoSpace)\n"); } sourceCode.AppendFront("{\n"); sourceCode.Indent(); sourceCode.AppendFront("GRGEN_LGSP.LGSPGraph graph = actionEnv.graph;\n"); if (Parallel) { sourceCode.AppendFront("List<ushort> flagsPerElement = graph.flagsPerThreadPerElement[threadId];\n"); sourceCode.AppendFront("List<ushort> flagsPerElement0 = graph.flagsPerThreadPerElement[0];\n"); sourceCode.AppendFront("List<ushort> flagsPerElementGlobal = graph.flagsPerThreadPerElement[threadId];\n"); } foreach (string graphsOnPath in NamesOfPatternGraphsOnPathToEnclosedPatternpath) { sourceCode.AppendFrontFormat("{0}.{1} {2} = null;\n", RulePatternClassName, NamesOfEntities.MatchClassName(graphsOnPath), NamesOfEntities.PatternpathMatch(graphsOnPath)); } GenerateIndependentsMatchObjects(sourceCode); OperationsList.Emit(sourceCode); sourceCode.AppendFront("return;\n"); sourceCode.Unindent(); sourceCode.AppendFront("}\n"); }
public override void Emit(SourceBuilder sourceCode) { if (sourceCode.CommentSourceCode) { if (Type == PushAndPopSubpatternTaskTypes.Subpattern) { sourceCode.AppendFrontFormat("// Pop subpattern matching task for {0}\n", SubpatternElementName); } else if (Type == PushAndPopSubpatternTaskTypes.Alternative) { sourceCode.AppendFrontFormat("// Pop alternative matching task for {0}\n", PathPrefix + AlternativeOrIteratedName); } else // if(Type==PushAndPopSubpatternTaskTypes.Iterated) { sourceCode.AppendFrontFormat("// Pop iterated matching task for {0}\n", PathPrefix + AlternativeOrIteratedName); } } sourceCode.AppendFrontFormat("{0}openTasks.Pop();\n", NegativeIndependentNamePrefix); string variableContainingTask; string typeOfVariableContainingTask; if (Type == PushAndPopSubpatternTaskTypes.Subpattern) { variableContainingTask = NamesOfEntities.TaskVariable(SubpatternElementName, NegativeIndependentNamePrefix); typeOfVariableContainingTask = NamesOfEntities.TypeOfTaskVariable(SubpatternName, false, false); } else if (Type == PushAndPopSubpatternTaskTypes.Alternative) { variableContainingTask = NamesOfEntities.TaskVariable(AlternativeOrIteratedName, NegativeIndependentNamePrefix); typeOfVariableContainingTask = NamesOfEntities.TypeOfTaskVariable(PathPrefix + AlternativeOrIteratedName, true, false); } else // if(Type==PushAndPopSubpatternTaskTypes.Iterated) { variableContainingTask = NamesOfEntities.TaskVariable(AlternativeOrIteratedName, NegativeIndependentNamePrefix); typeOfVariableContainingTask = NamesOfEntities.TypeOfTaskVariable(PathPrefix + AlternativeOrIteratedName, false, true); } string parallelizationThreadId = Parallel ? ", threadId" : ""; sourceCode.AppendFrontFormat("{0}.releaseTask({1}{2});\n", typeOfVariableContainingTask, variableContainingTask, parallelizationThreadId); }
public SequenceMultiBacktrackRuleRewritingGenerator(SequenceMultiBacktrack seqMulti, SequenceRuleCall seqRule, SequenceExpressionGenerator seqExprGen, SequenceGeneratorHelper seqHelper) { this.seqMulti = seqMulti; this.seqExprGen = seqExprGen; this.seqHelper = seqHelper; this.seqRule = seqRule; ReturnVars = seqRule.ReturnVars; specialStr = seqRule.Special ? "true" : "false"; matchingPatternClassName = "GRGEN_ACTIONS." + TypesHelper.GetPackagePrefixDot(seqRule.Package) + "Rule_" + seqRule.Name; patternName = seqRule.Name; plainRuleName = TypesHelper.PackagePrefixedNameDoubleColon(seqRule.Package, seqRule.Name); ruleName = "rule_" + TypesHelper.PackagePrefixedNameUnderscore(seqRule.Package, seqRule.Name); matchType = matchingPatternClassName + "." + NamesOfEntities.MatchInterfaceName(patternName); matchName = "match_" + seqRule.Id; matchesType = "GRGEN_LIBGR.IMatchesExact<" + matchType + ">"; matchesName = "matches_" + seqRule.Id; }
public override void Emit(SourceBuilder sourceCode) { if (ConnectednessType == CheckCandidateForConnectednessType.Source) { // emit check decision for is candidate connected to already found partial match, i.e. edge source equals node sourceCode.AppendFrontFormat("if({0}.lgspSource != {1}) ", NamesOfEntities.CandidateVariable(PatternEdgeName), NamesOfEntities.CandidateVariable(PatternNodeName)); } else if (ConnectednessType == CheckCandidateForConnectednessType.Target) { // emit check decision for is candidate connected to already found partial match, i.e. edge target equals node sourceCode.AppendFrontFormat("if({0}.lgspTarget != {1}) ", NamesOfEntities.CandidateVariable(PatternEdgeName), NamesOfEntities.CandidateVariable(PatternNodeName)); } else if (ConnectednessType == CheckCandidateForConnectednessType.SourceOrTarget) { // we've to check both node positions of the edge, we do so by checking source or target dependent on the direction run sourceCode.AppendFrontFormat("if( ({0}==0 ? {1}.lgspSource : {1}.lgspTarget) != {2}) ", NamesOfEntities.DirectionRunCounterVariable(PatternEdgeName), NamesOfEntities.CandidateVariable(PatternEdgeName), NamesOfEntities.CandidateVariable(PatternNodeName)); } else //ConnectednessType == CheckCandidateForConnectednessType.TheOther { // we've to check the node position of the edge the first node is not assigned to sourceCode.AppendFrontFormat("if( ({0}=={1}.lgspSource ? {1}.lgspTarget : {1}.lgspSource) != {2}) ", NamesOfEntities.CandidateVariable(TheOtherPatternNodeName), NamesOfEntities.CandidateVariable(PatternEdgeName), NamesOfEntities.CandidateVariable(PatternNodeName)); } // emit check failed code sourceCode.Append("{\n"); sourceCode.Indent(); CheckFailedOperations.Emit(sourceCode); sourceCode.Unindent(); sourceCode.AppendFront("}\n"); }
public SequenceMultiRuleAllCallGenerator(SequenceMultiRuleAllCall seqMulti, SequenceRuleCall seqRule, SequenceExpressionGenerator seqExprGen, SequenceGeneratorHelper seqHelper) { this.seqMulti = seqMulti; // parent this.seqRule = seqRule; this.seqExprGen = seqExprGen; this.seqHelper = seqHelper; ArgumentExpressions = seqRule.ArgumentExpressions; specialStr = seqRule.Special ? "true" : "false"; matchingPatternClassName = "GRGEN_ACTIONS." + TypesHelper.GetPackagePrefixDot(seqRule.Package) + "Rule_" + seqRule.Name; patternName = seqRule.Name; plainRuleName = TypesHelper.PackagePrefixedNameDoubleColon(seqRule.Package, seqRule.Name); ruleName = "rule_" + TypesHelper.PackagePrefixedNameUnderscore(seqRule.Package, seqRule.Name); matchType = matchingPatternClassName + "." + NamesOfEntities.MatchInterfaceName(patternName); matchName = "match_" + seqRule.Id; matchesType = "GRGEN_LIBGR.IMatchesExact<" + matchType + ">"; matchesName = "matches_" + seqRule.Id; seqHelper.BuildReturnParameters(seqRule, seqRule.ReturnVars, out returnParameterDeclarations, out returnArguments, out returnAssignments, out returnParameterDeclarationsAllCall, out intermediateReturnAssignmentsAllCall, out returnAssignmentsAllCall); }
public override void Emit(SourceBuilder sourceCode) { // emit initialization with element mapped from unique index string tempVariableForUniqueResult = NamesOfEntities.MapByUniqueTemporary(PatternElementName); sourceCode.AppendFrontFormat("if({0}==null || !({0} is {1}))", tempVariableForUniqueResult, IsNode ? "GRGEN_LIBGR.INode" : "GRGEN_LIBGR.IEdge"); // 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, tempVariableForUniqueResult); }
/// <summary> /// Emits the matcher source code for all search programs /// first head of matching function of the current search program /// then the search program operations list in depth first walk over search program operations list /// then tail of matching function of the current search program /// and finally continues in missing preset search program list by emitting following search program /// </summary> public override void Emit(SourceBuilder sourceCode) { string matchType = RulePatternClassName + "." + NamesOfEntities.MatchInterfaceName(PatternName); string matchesType = "GRGEN_LIBGR.IMatchesExact<" + matchType + ">"; sourceCode.AppendFront("\n"); sourceCode.AppendFrontFormat("private void {0}()\n", Name); sourceCode.AppendFront("{\n"); sourceCode.Indent(); sourceCode.AppendFront("threadId = GRGEN_LGSP.WorkerPool.ThreadId;\n"); //sourceCode.AppendFrontFormat("Console.WriteLine(\"start work for {0} at threadId \" + threadId);\n", PatternName); sourceCode.AppendFront("GRGEN_LGSP.LGSPActionExecutionEnvironment actionEnv = actionEnvParallel;\n"); sourceCode.AppendFront("int maxMatches = maxMatchesParallel;\n"); sourceCode.AppendFront("GRGEN_LGSP.LGSPGraph graph = actionEnv.graph;\n"); sourceCode.AppendFront("List<ushort> flagsPerElement = graph.flagsPerThreadPerElement[threadId];\n"); sourceCode.AppendFront("List<ushort> flagsPerElement0 = graph.flagsPerThreadPerElement[0];\n"); sourceCode.AppendFront("List<ushort> flagsPerElementGlobal = graph.flagsPerThreadPerElement[threadId];\n"); sourceCode.AppendFront("int isoSpace = 0;\n"); if (NamesOfPatternGraphsOnPathToEnclosedPatternpath.Count > 0) { sourceCode.AppendFront("bool searchPatternpath = false;\n"); } foreach (string graphsOnPath in NamesOfPatternGraphsOnPathToEnclosedPatternpath) { sourceCode.AppendFrontFormat("{0}.{1} {2} = null;\n", RulePatternClassName, NamesOfEntities.MatchClassName(graphsOnPath), NamesOfEntities.PatternpathMatch(graphsOnPath)); } if (SetupSubpatternMatching) { sourceCode.AppendFront("Stack<GRGEN_LGSP.LGSPSubpatternAction> openTasks = new Stack<" + "GRGEN_LGSP.LGSPSubpatternAction>();\n"); sourceCode.AppendFront("List<Stack<GRGEN_LIBGR.IMatch>> foundPartialMatches = new List<Stack<" + "GRGEN_LIBGR.IMatch>>();\n"); sourceCode.AppendFront("List<Stack<GRGEN_LIBGR.IMatch>> matchesList = foundPartialMatches;\n"); } GenerateIndependentsMatchObjects(sourceCode); if (WasIndependentInlined) { sourceCode.AppendFrontFormat("Dictionary<int, {0}> {1} = null;\n", RulePatternClassName + "." + NamesOfEntities.MatchClassName(PatternName), NamesOfEntities.FoundMatchesForFilteringVariable()); } if (EmitProfiling) { sourceCode.AppendFront("long searchStepsAtLoopStepBegin;\n"); } OperationsList.Emit(sourceCode); //sourceCode.AppendFrontFormat("Console.WriteLine(\"work done for {0} at threadId \" + threadId);\n", PatternName); if (EmitProfiling) { sourceCode.AppendFrontFormat("if(maxMatches==1) actionEnv.PerformanceInfo.ActionProfiles[\"{0}\"].averagesPerThread[threadId].searchStepsSingle.Add(actionEnv.PerformanceInfo.SearchStepsPerThread[threadId]);\n", PackagePrefixedPatternName); sourceCode.AppendFrontFormat("else actionEnv.PerformanceInfo.ActionProfiles[\"{0}\"].averagesPerThread[threadId].searchStepsMultiple.Add(actionEnv.PerformanceInfo.SearchStepsPerThread[threadId]);\n", PackagePrefixedPatternName); sourceCode.AppendFrontFormat("if(maxMatches==1) actionEnv.PerformanceInfo.ActionProfiles[\"{0}\"].averagesPerThread[threadId].loopStepsSingle.Add(actionEnv.PerformanceInfo.LoopStepsPerThread[threadId]);\n", PackagePrefixedPatternName); sourceCode.AppendFrontFormat("else actionEnv.PerformanceInfo.ActionProfiles[\"{0}\"].averagesPerThread[threadId].loopStepsMultiple.Add(actionEnv.PerformanceInfo.LoopStepsPerThread[threadId]);\n", PackagePrefixedPatternName); sourceCode.AppendFrontFormat("if(maxMatches==1) actionEnv.PerformanceInfo.ActionProfiles[\"{0}\"].averagesPerThread[threadId].searchStepsPerLoopStepSingle.Add(actionEnv.PerformanceInfo.SearchStepsPerThread[threadId] - searchStepsAtLoopStepBegin);\n", PackagePrefixedPatternName); sourceCode.AppendFrontFormat("else actionEnv.PerformanceInfo.ActionProfiles[\"{0}\"].averagesPerThread[threadId].searchStepsPerLoopStepMultiple.Add(actionEnv.PerformanceInfo.SearchStepsPerThread[threadId] - searchStepsAtLoopStepBegin);\n", PackagePrefixedPatternName); } if (WasIndependentInlined) { sourceCode.AppendFrontFormat("if({0} != null)\n", NamesOfEntities.FoundMatchesForFilteringVariable()); sourceCode.AppendFront("{\n"); sourceCode.Indent(); sourceCode.AppendFrontFormat("foreach({0} toClean in {1}.Values) toClean.CleanNextWithSameHash();\n", RulePatternClassName + "." + NamesOfEntities.MatchClassName(PatternName), NamesOfEntities.FoundMatchesForFilteringVariable()); sourceCode.Unindent(); sourceCode.AppendFront("}\n"); } sourceCode.AppendFront("return;\n"); sourceCode.Unindent(); sourceCode.AppendFront("}\n"); Debug.Assert(Next == null); }
public override void Emit(SourceBuilder sourceCode) { // open decision whether to fail sourceCode.AppendFront("if("); // fail if graph element contained within candidate was already matched // (in another subpattern to another pattern element) // as this would cause a inter-pattern-homomorphic match string variableContainingCandidate = NamesOfEntities.CandidateVariable(PatternElementName); if (Parallel) { if (!NeverAboveMaxIsoSpace) { sourceCode.Append("(isoSpace < (int) GRGEN_LGSP.LGSPElemFlagsParallel.MAX_ISO_SPACE ? "); } string isMatchedBit = "(uint)GRGEN_LGSP.LGSPElemFlagsParallel.IS_MATCHED_BY_ENCLOSING_PATTERN << isoSpace"; sourceCode.AppendFormat("( flagsPerElementGlobal[{0}.uniqueId] & {1} ) == {1}", variableContainingCandidate, isMatchedBit); if (!NeverAboveMaxIsoSpace) { sourceCode.Append(" : "); sourceCode.AppendFormat("graph.perThreadInIsoSpaceMatchedElementsGlobal[threadId][isoSpace - (int)" + "GRGEN_LGSP.LGSPElemFlagsParallel.MAX_ISO_SPACE]" + ".ContainsKey({0}))", variableContainingCandidate); } } else { if (!NeverAboveMaxIsoSpace) { sourceCode.Append("(isoSpace < (int) GRGEN_LGSP.LGSPElemFlags.MAX_ISO_SPACE ? "); } string isMatchedBit = "(uint)GRGEN_LGSP.LGSPElemFlags.IS_MATCHED_BY_ENCLOSING_PATTERN << isoSpace"; sourceCode.AppendFormat("({0}.lgspFlags & {1})=={1}", variableContainingCandidate, isMatchedBit); if (!NeverAboveMaxIsoSpace) { sourceCode.Append(" : "); sourceCode.AppendFormat("graph.inIsoSpaceMatchedElementsGlobal[isoSpace - (int)" + "GRGEN_LGSP.LGSPElemFlags.MAX_ISO_SPACE]" + ".ContainsKey({0}))", variableContainingCandidate); } } if (GloballyHomomorphElements != null) { // don't fail if candidate was globally matched by an element // it is allowed to be globally homomorph to // (element from alternative case declared to be non-isomorph to element from enclosing pattern) foreach (string name in GloballyHomomorphElements) { sourceCode.AppendFormat(" && {0}!={1}", variableContainingCandidate, NamesOfEntities.CandidateVariable(name)); } } sourceCode.Append(")\n"); // emit check failed code sourceCode.AppendFront("{\n"); sourceCode.Indent(); CheckFailedOperations.Emit(sourceCode); sourceCode.Unindent(); sourceCode.AppendFront("}\n"); }
public override void Emit(SourceBuilder sourceCode) { // open decision whether to fail sourceCode.AppendFront("if("); // fail if graph element contained within candidate was already matched // (to another pattern element) // as this would cause a homomorphic match string variableContainingCandidate = NamesOfEntities.CandidateVariable(PatternElementName); if (Parallel) { if (!NeverAboveMaxIsoSpace) { sourceCode.Append("(isoSpace < (int) GRGEN_LGSP.LGSPElemFlagsParallel.MAX_ISO_SPACE ? "); } string isMatchedBit = "(uint)GRGEN_LGSP.LGSPElemFlagsParallel.IS_MATCHED << isoSpace"; if (LockForAllThreads) { sourceCode.AppendFormat("( flagsPerElement0[{0}.uniqueId] & {1} ) != 0", variableContainingCandidate, isMatchedBit); } else { sourceCode.AppendFormat("( flagsPerElement[{0}.uniqueId] & {1} ) != 0", variableContainingCandidate, isMatchedBit); } if (!NeverAboveMaxIsoSpace) { sourceCode.Append(" : "); sourceCode.AppendFormat("graph.perThreadInIsoSpaceMatchedElements[{0}][isoSpace - (int)" + "GRGEN_LGSP.LGSPElemFlagsParallel.MAX_ISO_SPACE]" + ".ContainsKey({1}))", LockForAllThreads ? "0" : "threadId", variableContainingCandidate); } } else { if (!NeverAboveMaxIsoSpace) { sourceCode.Append("(isoSpace < (int) GRGEN_LGSP.LGSPElemFlags.MAX_ISO_SPACE ? "); } string isMatchedBit = "(uint)GRGEN_LGSP.LGSPElemFlags.IS_MATCHED << isoSpace"; sourceCode.AppendFormat("({0}.lgspFlags & {1}) != 0", variableContainingCandidate, isMatchedBit); if (!NeverAboveMaxIsoSpace) { sourceCode.Append(" : "); sourceCode.AppendFormat("graph.inIsoSpaceMatchedElements[isoSpace - (int)" + "GRGEN_LGSP.LGSPElemFlags.MAX_ISO_SPACE]" + ".ContainsKey({0}))", variableContainingCandidate); } } // but only if isomorphy is demanded (NamesOfPatternElementsToCheckAgainst empty) // otherwise homomorphy to certain elements is allowed, // so we only fail if the graph element is matched to one of the not allowed elements, // given in NamesOfPatternElementsToCheckAgainst if (NamesOfPatternElementsToCheckAgainst != null) { Debug.Assert(NamesOfPatternElementsToCheckAgainst.Count > 0); sourceCode.Append("\n"); sourceCode.Indent(); if (NamesOfPatternElementsToCheckAgainst.Count == 1) { string name = NamesOfPatternElementsToCheckAgainst[0]; sourceCode.AppendFrontFormat("&& {0}=={1}\n", variableContainingCandidate, NamesOfEntities.CandidateVariable(name)); } else { bool first = true; foreach (string name in NamesOfPatternElementsToCheckAgainst) { if (first) { sourceCode.AppendFrontFormat("&& ({0}=={1}\n", variableContainingCandidate, NamesOfEntities.CandidateVariable(name)); sourceCode.Indent(); first = false; } else { sourceCode.AppendFrontFormat("|| {0}=={1}\n", variableContainingCandidate, NamesOfEntities.CandidateVariable(name)); } } sourceCode.AppendFront(")\n"); sourceCode.Unindent(); } // close decision sourceCode.AppendFront(")\n"); sourceCode.Unindent(); } else { // close decision sourceCode.Append(")\n"); } // emit check failed code sourceCode.AppendFront("{\n"); sourceCode.Indent(); CheckFailedOperations.Emit(sourceCode); sourceCode.Unindent(); sourceCode.AppendFront("}\n"); }
/// <summary> /// Emits the matcher source code for the search program /// head, search program operations list in depth first walk over search program operations list, tail /// </summary> public override void Emit(SourceBuilder sourceCode) { #if RANDOM_LOOKUP_LIST_START sourceCode.AppendFront("private Random random = new Random(13795661);\n"); #endif if (Parallel) { sourceCode.AppendFront("public override void " + Name + "_parallelized" + "(List<Stack<GRGEN_LIBGR.IMatch>> foundPartialMatches, " + "int maxMatches, int isoSpace, int threadId)\n"); } else { sourceCode.AppendFront("public override void " + Name + "(List<Stack<GRGEN_LIBGR.IMatch>> foundPartialMatches, " + "int maxMatches, int isoSpace)\n"); } sourceCode.AppendFront("{\n"); sourceCode.Indent(); sourceCode.AppendFront("bool patternFound = false;\n"); sourceCode.AppendFront("GRGEN_LGSP.LGSPGraph graph = actionEnv.graph;\n"); if (Parallel) { sourceCode.AppendFront("List<ushort> flagsPerElement = graph.flagsPerThreadPerElement[threadId];\n"); sourceCode.AppendFront("List<ushort> flagsPerElement0 = graph.flagsPerThreadPerElement[0];\n"); sourceCode.AppendFront("List<ushort> flagsPerElementGlobal = graph.flagsPerThreadPerElement[threadId];\n"); } foreach (string graphsOnPath in NamesOfPatternGraphsOnPathToEnclosedPatternpath) { sourceCode.AppendFrontFormat("{0}.{1} {2} = null;\n", RulePatternClassName, NamesOfEntities.MatchClassName(graphsOnPath), NamesOfEntities.PatternpathMatch(graphsOnPath)); } GenerateIndependentsMatchObjects(sourceCode); if (WasIndependentInlined) { sourceCode.AppendFrontFormat("Dictionary<int, {0}> {1} = null;\n", RulePatternClassName + "." + NamesOfEntities.MatchClassName(IterPathPrefix + IterPatternName), NamesOfEntities.FoundMatchesForFilteringVariable()); } OperationsList.Emit(sourceCode); if (WasIndependentInlined) { sourceCode.AppendFrontFormat("if({0} != null)\n", NamesOfEntities.FoundMatchesForFilteringVariable()); sourceCode.AppendFront("{\n"); sourceCode.Indent(); sourceCode.AppendFrontFormat("foreach({0} toClean in {1}.Values) toClean.CleanNextWithSameHash();\n", RulePatternClassName + "." + NamesOfEntities.MatchClassName(IterPathPrefix + IterPatternName), NamesOfEntities.FoundMatchesForFilteringVariable()); sourceCode.Unindent(); sourceCode.AppendFront("}\n"); } sourceCode.AppendFront("return;\n"); sourceCode.Unindent(); sourceCode.AppendFront("}\n"); }
public override void Emit(SourceBuilder sourceCode) { if (sourceCode.CommentSourceCode) { sourceCode.AppendFront("// Check whether a duplicate match to be purged was found or will be found\n"); } // emit hash variable declaration sourceCode.AppendFrontFormat("int {0} = 0;\n", NamesOfEntities.DuplicateMatchHashVariable()); // only do the rest if more than one match is requested sourceCode.AppendFront("if(maxMatches!=1) {\n"); sourceCode.Indent(); // emit found matches hash map initialization as needed sourceCode.AppendFrontFormat("if({0}==null) {0} = new Dictionary<int, {1}>();\n", NamesOfEntities.FoundMatchesForFilteringVariable(), RulePatternClassName + "." + NamesOfEntities.MatchClassName(PatternName)); // emit hash variable initialization with result of hash computation sourceCode.AppendFrontFormat("{0} = unchecked(", NamesOfEntities.DuplicateMatchHashVariable()); EmitHashComputation(sourceCode, NeededElements.Length - 1); sourceCode.Append(");\n"); // emit check whether hash is contained in found matches hash map sourceCode.AppendFrontFormat("if({0}.ContainsKey({1}))\n", NamesOfEntities.FoundMatchesForFilteringVariable(), NamesOfEntities.DuplicateMatchHashVariable()); sourceCode.AppendFront("{\n"); sourceCode.Indent(); // emit check whether one of the matches in the hash map with same hash is equal to the locally matched elements sourceCode.AppendFrontFormat("{0} {1} = {2}[{3}];\n", RulePatternClassName + "." + NamesOfEntities.MatchClassName(PatternName), NamesOfEntities.DuplicateMatchCandidateVariable(), NamesOfEntities.FoundMatchesForFilteringVariable(), NamesOfEntities.DuplicateMatchHashVariable()); sourceCode.AppendFront("do {\n"); sourceCode.Indent(); // emit check for same elements sourceCode.AppendFront("if("); for (int i = 0; i < NeededElements.Length; ++i) { if (i != 0) { sourceCode.Append(" && "); } sourceCode.AppendFormat("{0}._{1} == {2}", NamesOfEntities.DuplicateMatchCandidateVariable() + MatchObjectPaths[i], NamesOfEntities.MatchName(NeededElementsUnprefixedName[i], NeededElementsIsNode[i] ? BuildMatchObjectType.Node : BuildMatchObjectType.Edge), NamesOfEntities.CandidateVariable(NeededElements[i])); } sourceCode.Append(")\n"); // emit check failed code, i.e. the current local match is equivalent to one of the already found ones, a duplicate sourceCode.AppendFront("{\n"); sourceCode.Indent(); CheckFailedOperations.Emit(sourceCode); sourceCode.Unindent(); sourceCode.AppendFront("}\n"); // close "emit check whether one of the matches in the hash map with same hash is equal to the locally matched elements" // switching to next match with the same hash, if available sourceCode.Unindent(); sourceCode.AppendFront("} "); sourceCode.AppendFormat("while(({0} = {0}.nextWithSameHash) != null);\n", NamesOfEntities.DuplicateMatchCandidateVariable()); // close "emit check whether hash is contained in found matches hash map" sourceCode.Unindent(); sourceCode.AppendFront("}\n"); // close "only do the rest if more than one match is requested" sourceCode.Unindent(); sourceCode.AppendFront("}\n"); }
public override void Emit(SourceBuilder sourceCode) { if (Type == AdjustListHeadsTypes.GraphElements) { if (Parallel) { if (IsNode) { sourceCode.AppendFrontFormat("moveHeadAfterNodes[threadId].Add({0});\n", NamesOfEntities.CandidateVariable(PatternElementName)); } else { sourceCode.AppendFrontFormat("moveHeadAfterEdges[threadId].Add({0});\n", NamesOfEntities.CandidateVariable(PatternElementName)); } } else { sourceCode.AppendFrontFormat("graph.MoveHeadAfter({0});\n", NamesOfEntities.CandidateVariable(PatternElementName)); } } else //Type == AdjustListHeadsTypes.IncidentEdges { if (IncidentType == IncidentEdgeType.Incoming) { if (Parallel) { sourceCode.AppendFrontFormat("moveInHeadAfter[threadId].Add(new KeyValuePair<GRGEN_LGSP.LGSPNode, GRGEN_LGSP.LGSPEdge>({0}, {1}));\n", NamesOfEntities.CandidateVariable(StartingPointNodeName), NamesOfEntities.CandidateVariable(PatternElementName)); } else { sourceCode.AppendFrontFormat("{0}.MoveInHeadAfter({1});\n", NamesOfEntities.CandidateVariable(StartingPointNodeName), NamesOfEntities.CandidateVariable(PatternElementName)); } } else if (IncidentType == IncidentEdgeType.Outgoing) { if (Parallel) { sourceCode.AppendFrontFormat("moveOutHeadAfter[threadId].Add(new KeyValuePair<GRGEN_LGSP.LGSPNode, GRGEN_LGSP.LGSPEdge>({0}, {1}));\n", NamesOfEntities.CandidateVariable(StartingPointNodeName), NamesOfEntities.CandidateVariable(PatternElementName)); } else { sourceCode.AppendFrontFormat("{0}.MoveOutHeadAfter({1});\n", NamesOfEntities.CandidateVariable(StartingPointNodeName), NamesOfEntities.CandidateVariable(PatternElementName)); } } else // IncidentType == IncidentEdgeType.IncomingOrOutgoing { sourceCode.AppendFrontFormat("if({0}==0)", NamesOfEntities.DirectionRunCounterVariable(PatternElementName)); sourceCode.Append(" {\n"); sourceCode.Indent(); if (Parallel) { sourceCode.AppendFrontFormat("moveInHeadAfter[threadId].Add(new KeyValuePair<GRGEN_LGSP.LGSPNode, GRGEN_LGSP.LGSPEdge>({0}, {1}));\n", NamesOfEntities.CandidateVariable(StartingPointNodeName), NamesOfEntities.CandidateVariable(PatternElementName)); } else { sourceCode.AppendFrontFormat("{0}.MoveInHeadAfter({1});\n", NamesOfEntities.CandidateVariable(StartingPointNodeName), NamesOfEntities.CandidateVariable(PatternElementName)); } sourceCode.Unindent(); sourceCode.AppendFront("} else {\n"); sourceCode.Indent(); if (Parallel) { sourceCode.AppendFrontFormat("moveOutHeadAfter[threadId].Add(new KeyValuePair<GRGEN_LGSP.LGSPNode, GRGEN_LGSP.LGSPEdge>({0}, {1}));\n", NamesOfEntities.CandidateVariable(StartingPointNodeName), NamesOfEntities.CandidateVariable(PatternElementName)); } else { sourceCode.AppendFrontFormat("{0}.MoveOutHeadAfter({1});\n", NamesOfEntities.CandidateVariable(StartingPointNodeName), NamesOfEntities.CandidateVariable(PatternElementName)); } sourceCode.Unindent(); sourceCode.AppendFront("}\n"); } } }
public override void Dump(SourceBuilder builder) { builder.AppendFront("Declare def " + NamesOfEntities.ToString(Type) + " " + NameOfEntity + ":" + TypeOfEntity + " = " + Initialization + "\n"); }
public override void Emit(SourceBuilder sourceCode) { sourceCode.AppendFront(VarType + " " + NamesOfEntities.Variable(VarName) + " = (" + VarType + ")" + VarName + ";\n"); }
public override void Emit(SourceBuilder sourceCode) { // --- move list head from current position to random position --- if (Type == RandomizeListHeadsTypes.GraphElements) { // emit declaration of variable containing random position to move list head to string variableContainingRandomPosition = "random_position_" + PatternElementName; sourceCode.AppendFormat("int {0}", variableContainingRandomPosition); // emit initialization with ramdom position string graphMemberContainingElementListCountsByType = IsNode ? "nodesByTypeCounts" : "edgesByTypeCounts"; string variableContainingTypeIDForCandidate = NamesOfEntities.TypeIdForCandidateVariable(PatternElementName); sourceCode.AppendFormat(" = random.Next(graph.{0}[{1}]);\n", graphMemberContainingElementListCountsByType, variableContainingTypeIDForCandidate); // emit declaration of variable containing element at random position string typeOfVariableContainingElementAtRandomPosition = "GRGEN_LGSP." + (IsNode ? "LGSPNode" : "LGSPEdge"); string variableContainingElementAtRandomPosition = "random_element_" + PatternElementName; sourceCode.AppendFrontFormat("{0} {1}", typeOfVariableContainingElementAtRandomPosition, variableContainingElementAtRandomPosition); // emit initialization with element list head string graphMemberContainingElementListHeadByType = IsNode ? "nodesByTypeHeads" : "edgesByTypeHeads"; sourceCode.AppendFormat(" = graph.{0}[{1}];\n", graphMemberContainingElementListHeadByType, variableContainingTypeIDForCandidate); // emit iteration to get element at random position sourceCode.AppendFrontFormat( "for(int i = 0; i < {0}; ++i) {1} = {1}.Next;\n", variableContainingRandomPosition, variableContainingElementAtRandomPosition); // iteration left, element is the one at the requested random position // move list head after element at random position, sourceCode.AppendFrontFormat("graph.MoveHeadAfter({0});\n", variableContainingElementAtRandomPosition); // effect is new random starting point for following iteration } else //Type == RandomizeListHeadsTypes.IncidentEdges { // emit "randomization only if list is not empty" string variableContainingStartingPointNode = NamesOfEntities.CandidateVariable(StartingPointNodeName); string memberOfNodeContainingListHead = IsIncoming ? "lgspInhead" : "lgspOuthead"; sourceCode.AppendFrontFormat("if({0}.{1}!=null)\n", variableContainingStartingPointNode, memberOfNodeContainingListHead); sourceCode.AppendFront("{\n"); sourceCode.Indent(); // emit declaration of variable containing random position to move list head to, initialize it to 0 string variableContainingRandomPosition = "random_position_" + PatternElementName; sourceCode.AppendFrontFormat("int {0} = 0;", variableContainingRandomPosition); // misuse variable to store length of list which is computed within the follwing iteration string memberOfEdgeContainingNextEdge = IsIncoming ? "lgspInNext" : "lgspOutNext"; sourceCode.AppendFrontFormat("for(GRGEN_LGSP.LGSPEdge edge = {0}.{1}; edge!={0}.{1}; edge=edge.{2}) ++{3};\n", variableContainingStartingPointNode, memberOfNodeContainingListHead, memberOfEdgeContainingNextEdge, variableContainingRandomPosition); // emit initialization of variable containing ramdom position // now that the necessary length of the list is known after the iteration // given in the variable itself sourceCode.AppendFrontFormat("{0} = random.Next({0});\n", variableContainingRandomPosition); // emit declaration of variable containing edge at random position string variableContainingEdgeAtRandomPosition = "random_element_" + PatternElementName; sourceCode.AppendFrontFormat("GRGEN_LGSP.LGSPEdge {0}", variableContainingEdgeAtRandomPosition); // emit initialization with edge list head sourceCode.AppendFormat(" = {0}.{1};\n", variableContainingStartingPointNode, memberOfNodeContainingListHead); // emit iteration to get edge at random position sourceCode.AppendFrontFormat( "for(int i = 0; i < {0}; ++i) {1} = {1}.{2};\n", variableContainingRandomPosition, variableContainingEdgeAtRandomPosition, memberOfEdgeContainingNextEdge); // iteration left, edge is the one at the requested random position // move list head after edge at random position, if (IsIncoming) { sourceCode.AppendFrontFormat("{0}.MoveInHeadAfter({1});\n", variableContainingStartingPointNode, variableContainingEdgeAtRandomPosition); } else { sourceCode.AppendFrontFormat("{0}.MoveOutHeadAfter({1});\n", variableContainingStartingPointNode, variableContainingEdgeAtRandomPosition); } // close list is not empty check sourceCode.Unindent(); sourceCode.AppendFront("}\n"); // effect is new random starting point for following iteration } }