///////////////////////////////////////////////////////////////////////////////////
        ///////////////////////////////////////////////////////////////////////////////////

        /// <summary>
        /// Completes check operations in search program from given currentOperation on
        /// (taking borderlines set by enclosing search program and check negative into account)
        /// Completion:
        /// - determine continuation point
        /// - insert remove isomorphy opertions needed for continuing there
        /// - insert continuing operation itself
        /// </summary>
        private void CompleteCheckOperations(
            SearchProgramOperation currentOperation,
            SearchProgramOperation enclosingSearchProgram, // might be a negative/independent in case these are nested
            GetPartialMatchOfAlternative enclosingAlternative,
            CheckPartialMatchByNegativeOrIndependent enclosingCheckNegativeOrIndependent,
            SearchProgram topLevelSearchProgram)
        {
            // mainly dispatching and iteration method, traverses search program
            // real completion done in MoveOutwardsAppendingRemoveIsomorphyAndJump
            // outermost operation for that function is computed here, regarding negative patterns
            // program nesting structure: search program - [alternative] - [negative|independent]*

            // complete check operations by inserting failure code
            // find them in depth first search of search program
            while (currentOperation != null)
            {
                //////////////////////////////////////////////////////////
                if (currentOperation is CheckCandidate)
                //////////////////////////////////////////////////////////
                {
                    CheckCandidate checkCandidate =
                        (CheckCandidate)currentOperation;
                    checkCandidate.CheckFailedOperations =
                        new SearchProgramList(checkCandidate);
                    string[] neededElementsForCheckOperation = new string[1];
                    neededElementsForCheckOperation[0] = checkCandidate.PatternElementName;
                    MoveOutwardsAppendingRemoveIsomorphyAndJump(
                        checkCandidate,
                        neededElementsForCheckOperation,
                        enclosingCheckNegativeOrIndependent ?? (enclosingAlternative ?? enclosingSearchProgram),
                        topLevelSearchProgram);
                }
                //////////////////////////////////////////////////////////
                else if (currentOperation is CheckPartialMatch)
                //////////////////////////////////////////////////////////
                {
                    if (currentOperation is CheckPartialMatchByCondition)
                    {
                        CheckPartialMatchByCondition checkCondition =
                            (CheckPartialMatchByCondition)currentOperation;
                        checkCondition.CheckFailedOperations =
                            new SearchProgramList(checkCondition);
                        MoveOutwardsAppendingRemoveIsomorphyAndJump(
                            checkCondition,
                            checkCondition.NeededElements,
                            enclosingCheckNegativeOrIndependent ?? (enclosingAlternative ?? enclosingSearchProgram),
                            topLevelSearchProgram);
                    }
                    else if(currentOperation is CheckPartialMatchForDuplicate)
                    {
                        CheckPartialMatchForDuplicate checkDuplicateMatch =
                            (CheckPartialMatchForDuplicate)currentOperation;
                        checkDuplicateMatch.CheckFailedOperations =
                            new SearchProgramList(checkDuplicateMatch);
                        MoveOutwardsAppendingRemoveIsomorphyAndJump(
                            checkDuplicateMatch,
                            checkDuplicateMatch.NeededElements,
                            enclosingCheckNegativeOrIndependent ?? (enclosingAlternative ?? enclosingSearchProgram),
                            topLevelSearchProgram);
                    }
                    else if(currentOperation is CheckPartialMatchByNegativeOrIndependent)
                    {
                        CheckPartialMatchByNegativeOrIndependent checkNegativeOrIndependent =
                            (CheckPartialMatchByNegativeOrIndependent)currentOperation;

                        // ByNegative/ByIndependent is handled in CheckContinueMatchingFailed
                        // of the negative/independent case - enter negative/independent case
                        CompleteCheckOperations(
                            checkNegativeOrIndependent.NestedOperationsList,
                            enclosingCheckNegativeOrIndependent ?? enclosingSearchProgram,
                            enclosingCheckNegativeOrIndependent!=null ? null : enclosingAlternative,
                            checkNegativeOrIndependent,
                            topLevelSearchProgram);
                    }
                    else if (currentOperation is CheckPartialMatchForSubpatternsFound)
                    {
                        CheckPartialMatchForSubpatternsFound checkSubpatternsFound =
                            (CheckPartialMatchForSubpatternsFound)currentOperation;

                        if (enclosingCheckNegativeOrIndependent == null)
                        {
                            // determine insertion point within check failed operations
                            // to append the nested check maximum matches
                            SearchProgramOperation insertionPoint =
                                checkSubpatternsFound.CheckFailedOperations;
                            while (insertionPoint.Next != null)
                            {
                                insertionPoint = insertionPoint.Next;
                            }

                            // append nested check maximum matches
                            CheckMaximumMatchesType checkMaxMatchesType = CheckMaximumMatchesType.Action;
                            if(enclosingSearchProgram is SearchProgramOfSubpattern
                                || enclosingSearchProgram is SearchProgramOfAlternative) {
                                checkMaxMatchesType = CheckMaximumMatchesType.Subpattern;
                            } else if(enclosingSearchProgram is SearchProgramOfIterated) {
                                checkMaxMatchesType = CheckMaximumMatchesType.Iterated;
                            }
                            CheckContinueMatchingMaximumMatchesReached checkMaximumMatches =
                                new CheckContinueMatchingMaximumMatchesReached(checkMaxMatchesType, false, 
                                    enclosingSearchProgram is SearchProgramOfActionParallelizationBody);
                            insertionPoint.Append(checkMaximumMatches);

                            MoveOutwardsAppendingRemoveIsomorphyAndJump(
                                checkSubpatternsFound,
                                null,
                                enclosingCheckNegativeOrIndependent ?? (enclosingAlternative ?? enclosingSearchProgram),
                                topLevelSearchProgram);
                        }

                        // check subpatterns found has a further check maximum matches
                        // or check continue matching of negative failed nested within check failed code
                        // give it its special bit of attention here
                        CompleteCheckOperations(
                            checkSubpatternsFound.CheckFailedOperations,
                            enclosingSearchProgram,
                            enclosingAlternative,
                            enclosingCheckNegativeOrIndependent,
                            topLevelSearchProgram);
                    }
                    else
                    {
                        Debug.Assert(false, "unknown check partial match operation");
                    }

                }
                //////////////////////////////////////////////////////////
                else if (currentOperation is CheckContinueMatching)
                //////////////////////////////////////////////////////////
                {
                    if (currentOperation is CheckContinueMatchingMaximumMatchesReached)
                    {
                        CheckContinueMatchingMaximumMatchesReached checkMaximumMatches =
                            (CheckContinueMatchingMaximumMatchesReached)currentOperation;
                        checkMaximumMatches.CheckFailedOperations =
                            new SearchProgramList(checkMaximumMatches);

                        if (checkMaximumMatches.ListHeadAdjustment)
                        {
                            MoveOutwardsAppendingListHeadAdjustment(checkMaximumMatches, checkMaximumMatches.InParallelizedBody);
                        }

                        string[] neededElementsForCheckOperation = new string[0];
                        MoveOutwardsAppendingRemoveIsomorphyAndJump(
                            checkMaximumMatches,
                            neededElementsForCheckOperation,
                            enclosingSearchProgram,
                            topLevelSearchProgram);
                    }
                    else if (currentOperation is CheckContinueMatchingOfNegativeFailed)
                    {
                        CheckContinueMatchingOfNegativeFailed checkFailed =
                            (CheckContinueMatchingOfNegativeFailed)currentOperation;
                        checkFailed.CheckFailedOperations =
                            new SearchProgramList(checkFailed);
                        if(checkFailed.IsIterationBreaking)
                        {
                            string[] neededElementsForCheckOperation = new string[0];
                            MoveOutwardsAppendingRemoveIsomorphyAndJump(
                                checkFailed,
                                neededElementsForCheckOperation,
                                enclosingSearchProgram,
                                topLevelSearchProgram);
                        }
                        else
                        {
                            MoveOutwardsAppendingRemoveIsomorphyAndJump(
                                checkFailed,
                                enclosingCheckNegativeOrIndependent.NeededElements,
                                enclosingAlternative ?? enclosingSearchProgram,
                                topLevelSearchProgram);
                        }
                    }
                    else if (currentOperation is CheckContinueMatchingOfIndependentSucceeded)
                    {
                        CheckContinueMatchingOfIndependentSucceeded checkSucceeded =
                            (CheckContinueMatchingOfIndependentSucceeded)currentOperation;
                        checkSucceeded.CheckFailedOperations = // yep, rotten wording
                            new SearchProgramList(checkSucceeded);
                        MoveRightAfterCorrespondingIndependentFailedAppendingRemoveIsomorphyAndJump(
                            checkSucceeded,
                            (CheckPartialMatchByIndependent)enclosingCheckNegativeOrIndependent,
                            topLevelSearchProgram);
                    }
                    else if (currentOperation is CheckContinueMatchingOfIndependentFailed)
                    {
                        CheckContinueMatchingOfIndependentFailed checkFailed =
                            (CheckContinueMatchingOfIndependentFailed)currentOperation;
                        checkFailed.CheckFailedOperations =
                            new SearchProgramList(checkFailed);
                        if(checkFailed.IsIterationBreaking)
                        {
                            string[] neededElementsForCheckOperation = new string[0];
                            MoveOutwardsAppendingRemoveIsomorphyAndJump(
                                checkFailed,
                                neededElementsForCheckOperation,
                                enclosingSearchProgram,
                                topLevelSearchProgram);
                        }
                        else
                        {
                            MoveOutwardsAppendingRemoveIsomorphyAndJump(
                                checkFailed,
                                checkFailed.CheckIndependent.NeededElements,
                                enclosingAlternative ?? enclosingSearchProgram,
                                topLevelSearchProgram);
                        }
                    }
                    else if (currentOperation is CheckContinueMatchingTasksLeft)
                    {
                        CheckContinueMatchingTasksLeft tasksLeft =
                            (CheckContinueMatchingTasksLeft)currentOperation;

                        // determine insertion point within check failed operations
                        // to append the nested check maximum matches
                        SearchProgramOperation insertionPoint =
                            tasksLeft.CheckFailedOperations;
                        while (insertionPoint.Next != null)
                        {
                            insertionPoint = insertionPoint.Next;
                        }

                        // append nested check maximum matches
                        CheckContinueMatchingMaximumMatchesReached checkMaximumMatches =
                            new CheckContinueMatchingMaximumMatchesReached(
                                enclosingSearchProgram is SearchProgramOfIterated ? CheckMaximumMatchesType.Iterated : CheckMaximumMatchesType.Subpattern,
                                false, topLevelSearchProgram is SearchProgramOfActionParallelizationBody);
                        insertionPoint.Append(checkMaximumMatches);

                        MoveOutwardsAppendingRemoveIsomorphyAndJump(
                            tasksLeft,
                            null,
                            enclosingCheckNegativeOrIndependent ?? (enclosingAlternative ?? enclosingSearchProgram),
                            topLevelSearchProgram);

                        // check tasks left has a further check maximum matches nested within check failed code
                        // give it its special bit of attention here
                        CompleteCheckOperations(
                            tasksLeft.CheckFailedOperations,
                            enclosingSearchProgram,
                            enclosingAlternative,
                            enclosingCheckNegativeOrIndependent,
                            topLevelSearchProgram);
                    }
                    else if (currentOperation is CheckContinueMatchingIteratedPatternNonNullMatchFound)
                    {
                        // was built completely, nothing to complete
                    }
                    else
                    {
                        Debug.Assert(false, "unknown check abort matching operation");
                    }
                }
                //////////////////////////////////////////////////////////
                else if (currentOperation is GetPartialMatchOfAlternative)
                //////////////////////////////////////////////////////////
                {
                    // depth first
                    CompleteCheckOperations(
                        currentOperation.GetNestedSearchOperationsList(),
                        enclosingSearchProgram,
                        (GetPartialMatchOfAlternative)currentOperation,
                        null,
                        topLevelSearchProgram);
                }
                //////////////////////////////////////////////////////////
                else if (currentOperation.IsSearchNestingOperation())
                //////////////////////////////////////////////////////////
                {
                    // depth first
                    CompleteCheckOperations(
                        currentOperation.GetNestedSearchOperationsList(),
                        enclosingSearchProgram,
                        enclosingAlternative,
                        enclosingCheckNegativeOrIndependent,
                        topLevelSearchProgram);
                }

                // breadth
                currentOperation = currentOperation.Next;
            }
        }
        /// <summary>
        /// Builds search program for alternative from scheduled search plans of the alternative cases
        /// </summary>
        public SearchProgram BuildSearchProgram(
            IGraphModel model,
            LGSPMatchingPattern matchingPattern,
            Alternative alternative,
            bool parallelized,
            bool emitProfiling)
        {
            programType = SearchProgramType.AlternativeCase;
            this.model = model;
            patternGraphWithNestingPatterns = new Stack<PatternGraph>();
            this.parallelized = parallelized;
            this.alternative = alternative;
            rulePatternClassName = NamesOfEntities.RulePatternClassName(matchingPattern.name, matchingPattern.PatternGraph.Package, !(matchingPattern is LGSPRulePattern));
            this.emitProfiling = emitProfiling;
            packagePrefixedActionName = null;
            firstLoopPassed = false;

            // build combined list of namesOfPatternGraphsOnPathToEnclosedPatternpath
            // from the namesOfPatternGraphsOnPathToEnclosedPatternpath of the alternative cases
            List<string> namesOfPatternGraphsOnPathToEnclosedPatternpath = new List<string>();
            for (int i = 0; i < alternative.alternativeCases.Length; ++i)
            {
                PatternGraph altCase = alternative.alternativeCases[i];
                foreach (String name in altCase.patternGraphsOnPathToEnclosedPatternpath)
                {
                    if(!namesOfPatternGraphsOnPathToEnclosedPatternpath.Contains(name))
                        namesOfPatternGraphsOnPathToEnclosedPatternpath.Add(name);
                }
            }

            // build outermost search program operation, create the list anchor starting its program
            SearchProgram searchProgram = new SearchProgramOfAlternative(
                rulePatternClassName,
                namesOfPatternGraphsOnPathToEnclosedPatternpath,
                "myMatch",
                parallelized);
            searchProgram.OperationsList = new SearchProgramList(searchProgram);
            SearchProgramOperation insertionPoint = searchProgram.OperationsList;

            // initialize task/result-pushdown handling in subpattern matcher
            InitializeSubpatternMatching initialize = 
                new InitializeSubpatternMatching(InitializeFinalizeSubpatternMatchingType.Normal);
            insertionPoint = insertionPoint.Append(initialize);

            // build alternative matching search programs, one per case
            for (int i=0; i<alternative.alternativeCases.Length; ++i)
            {
                PatternGraph altCase = alternative.alternativeCases[i];
                ScheduledSearchPlan scheduledSearchPlan = altCase.schedulesIncludingNegativesAndIndependents[0];

                string inlinedPatternClassName = rulePatternClassName;
                string pathPrefixInInlinedPatternClass = scheduledSearchPlan.PatternGraph.pathPrefix;
                string unprefixedNameInInlinedPatternClass = scheduledSearchPlan.PatternGraph.name;
                if(alternative.originalAlternative != null)
                {
                    inlinedPatternClassName = alternative.originalSubpatternEmbedding.matchingPatternOfEmbeddedGraph.GetType().Name;
                    pathPrefixInInlinedPatternClass = alternative.originalAlternative.pathPrefix + alternative.originalAlternative.name + "_";
                    unprefixedNameInInlinedPatternClass = alternative.originalAlternative.alternativeCases[i].name;
                }

                GetPartialMatchOfAlternative matchAlternative = new GetPartialMatchOfAlternative(
                    pathPrefixInInlinedPatternClass, 
                    unprefixedNameInInlinedPatternClass,
                    inlinedPatternClassName,
                    wasIndependentInlined(altCase, indexOfSchedule));
                matchAlternative.OperationsList = new SearchProgramList(matchAlternative);
                SearchProgramOperation continuationPointAfterAltCase = insertionPoint.Append(matchAlternative);
                
                // at level of the current alt case
                insertionPoint = matchAlternative.OperationsList;
                insertionPoint = insertVariableDeclarations(insertionPoint, altCase);

                patternGraphWithNestingPatterns.Push(altCase);
                isoSpaceNeverAboveMaxIsoSpace = patternGraphWithNestingPatterns.Peek().maxIsoSpace < (int)LGSPElemFlags.MAX_ISO_SPACE;
                isNegative = false;
                isNestedInNegative = false;

                // start building with first operation in scheduled search plan

                indexOfSchedule = 0;
                BuildScheduledSearchPlanOperationIntoSearchProgram(
                    0,
                    insertionPoint);

                // back to level of alt cases
                insertionPoint = continuationPointAfterAltCase;

                // save matches found by alternative case to get clean start for matching next alternative case
                if(i<alternative.alternativeCases.Length-1)
                {
                    NewMatchesListForFollowingMatches newMatchesList =
                        new NewMatchesListForFollowingMatches(true);
                    insertionPoint = insertionPoint.Append(newMatchesList);
                }

                patternGraphWithNestingPatterns.Pop();
            }

            // finalize task/result-pushdown handling in subpattern matcher
            FinalizeSubpatternMatching finalize =
                new FinalizeSubpatternMatching(InitializeFinalizeSubpatternMatchingType.Normal);
            insertionPoint = insertionPoint.Append(finalize);

            return searchProgram;
        }