/// <summary>The method was already called in the stack.</summary>
        private IWorkshopTree RecursiveCall(ActionSet actionSet, MethodCall methodCall)
        {
            // Push new parameters.
            for (int i = 0; i < method.ParameterVars.Length; i++)
            {
                var varReference = actionSet.IndexAssigner[method.ParameterVars[i]];
                if (varReference is RecursiveIndexReference)
                {
                    actionSet.AddAction(((RecursiveIndexReference)varReference).Push(
                                            (Element)methodCall.ParameterValues[i]
                                            ));
                }
            }

            // Add to the continue skip array.
            V_Number skipLength = new V_Number();

            actionSet.AddAction(continueArray.ModifyVariable(
                                    Operation.AppendToArray,
                                    skipLength
                                    ));

            // Restart the method.
            SkipStartMarker resetSkip = new SkipStartMarker(actionSet);

            resetSkip.SetEndMarker(endOfMethod);
            actionSet.AddAction(resetSkip);

            SkipEndMarker continueAtMarker = new SkipEndMarker();

            actionSet.AddAction(continueAtMarker);
            skipLength.Value = continueAt.NumberOfActionsToMarker(continueAtMarker);

            return(returnHandler.GetReturnedValue());
        }
        private IWorkshopTree ParseNormal(ActionSet actionSet, MethodCall methodCall)
        {
            // Create the return handler.
            ReturnHandler returnHandler = methodCall.ReturnHandler ?? new ReturnHandler(actionSet, Name, multiplePaths);

            actionSet = actionSet.New(returnHandler);

            // Assign the parameters and translate the block.
            AssignParameters(actionSet, ParameterVars, methodCall.ParameterValues);
            block.Translate(actionSet);

            if (methodCall.ResolveReturnHandler)
            {
                returnHandler.ApplyReturnSkips();
            }
            return(returnHandler.GetReturnedValue());
        }
        override public IWorkshopTree Parse(ActionSet actionSet, IWorkshopTree[] parameterValues, object[] additionalParameterData)
        {
            actionSet = actionSet
                        .New(actionSet.IndexAssigner.CreateContained());

            if (IsRecursive)
            {
                return(ParseRecursive(actionSet, parameterValues));
            }

            ReturnHandler returnHandler = new ReturnHandler(actionSet, Name, multiplePaths);

            actionSet = actionSet.New(returnHandler);

            AssignParameters(actionSet, ParameterVars, parameterValues);
            block.Translate(actionSet);

            returnHandler.ApplyReturnSkips();
            return(returnHandler.GetReturnedValue());
        }
        /// <summary>Calls the method.</summary>
        private IWorkshopTree ParseCall(ActionSet actionSet, MethodCall methodCall)
        {
            // Create the array used for continuing after a recursive call.
            continueArray = actionSet.VarCollection.Assign("_" + method.Name + "_recursiveContinue", actionSet.IsGlobal, false);
            nextContinue  = actionSet.VarCollection.Assign("_" + method.Name + "_nextContinue", actionSet.IsGlobal, true);
            actionSet.InitialSet().AddAction(continueArray.SetVariable(new V_EmptyArray()));

            ReturnHandler returnHandler = methodCall.ReturnHandler ?? new ReturnHandler(actionSet, method.Name, method.multiplePaths);

            this.returnHandler = returnHandler;

            DefinedMethod.AssignParameters(actionSet, method.ParameterVars, methodCall.ParameterValues, true);

            actionSet.AddAction(Element.Part <A_While>(new V_True()));

            continueAt = new SkipStartMarker(actionSet);
            continueAt.SetSkipCount((Element)nextContinue.GetVariable());
            actionSet.AddAction(continueAt);

            method.block.Translate(actionSet);

            PopParameterStacks(actionSet);

            // Pop the continueArray.
            actionSet.AddAction(Element.Part <A_SkipIf>(new V_Compare(
                                                            Element.Part <V_CountOf>(continueArray.GetVariable()),
                                                            Operators.Equal,
                                                            new V_Number(0)
                                                            ), new V_Number(3)));

            actionSet.AddAction(nextContinue.SetVariable(Element.Part <V_LastOf>(continueArray.GetVariable())));
            actionSet.AddAction(continueArray.ModifyVariable(Operation.RemoveFromArrayByIndex, Element.Part <V_CountOf>(continueArray.GetVariable()) - 1));

            actionSet.AddAction(endOfMethod);
            actionSet.AddAction(new A_End());

            actionSet.AddAction(nextContinue.SetVariable(0));

            return(returnHandler.GetReturnedValue());
        }
        private IWorkshopTree ParseRecursive(ActionSet actionSet, IWorkshopTree[] parameterValues)
        {
            // Check the method stack to see if this method was already called.
            RecursiveMethodStack lastCall = actionSet.Translate.MethodStack.FirstOrDefault(ms => ms.Function == this) as RecursiveMethodStack;

            // If not, set up the stack and call the method.
            if (lastCall == null)
            {
                // Assign the parameters.
                AssignParameters(actionSet, ParameterVars, parameterValues, true);

                // Get the return handler if a value is returned.
                ReturnHandler returnHandler = new ReturnHandler(actionSet, Name, true);

                // Set up the condinue skip array.
                IndexReference continueSkipArray = actionSet.VarCollection.Assign("recursiveContinueArray", actionSet.IsGlobal, false);

                SkipEndMarker methodStart = new SkipEndMarker();
                actionSet.AddAction(methodStart);

                // Add the method to the stack.
                var stack = new RecursiveMethodStack(this, returnHandler, continueSkipArray, methodStart);
                actionSet.Translate.MethodStack.Add(stack);

                // Parse the method block.
                block.Translate(actionSet.New(returnHandler));

                // Apply the returns.
                if (returnHandler != null)
                {
                    returnHandler.ApplyReturnSkips();
                }

                // Pop the recursive parameters
                // TODO: Make this work with all sub scoped variables somehow
                for (int i = 0; i < ParameterVars.Length; i++)
                {
                    var pop = (actionSet.IndexAssigner[ParameterVars[i]] as RecursiveIndexReference)?.Pop();
                    if (pop != null)
                    {
                        actionSet.AddAction(pop);
                    }
                }

                // Setup the continue skip
                actionSet.ContinueSkip.Setup(actionSet);
                actionSet.ContinueSkip.SetSkipCount(actionSet, Element.Part <V_LastOf>(continueSkipArray.GetVariable()));

                // Remove the last recursive continue skip.
                actionSet.AddAction(continueSkipArray.SetVariable(
                                        // Pop
                                        Element.Part <V_ArraySlice>(
                                            continueSkipArray.GetVariable(),
                                            new V_Number(0),
                                            Element.Part <V_CountOf>(continueSkipArray.GetVariable()) - 1
                                            )
                                        ));

                // Loop if there are any values in the continue skip array.
                actionSet.AddAction(Element.Part <A_LoopIf>(
                                        Element.Part <V_CountOf>(continueSkipArray.GetVariable()) > 0
                                        ));

                // Reset the continue skip.
                actionSet.ContinueSkip.ResetSkipCount(actionSet);
                actionSet.AddAction(continueSkipArray.SetVariable(0));

                // Remove the method from the stack.
                actionSet.Translate.MethodStack.Remove(stack);

                return(returnHandler.GetReturnedValue());
            }
            // If it is, push the parameters to the stack.
            else
            {
                for (int i = 0; i < ParameterVars.Length; i++)
                {
                    var varReference = actionSet.IndexAssigner[ParameterVars[i]];
                    if (varReference is RecursiveIndexReference)
                    {
                        actionSet.AddAction(((RecursiveIndexReference)varReference).Push(
                                                (Element)parameterValues[i]
                                                ));
                    }
                }

                // Add to the continue skip array.
                V_Number skipLength = new V_Number();
                actionSet.AddAction(lastCall.ContinueSkipArray.SetVariable(
                                        Element.Part <V_Append>(lastCall.ContinueSkipArray.GetVariable(), skipLength)
                                        ));

                actionSet.ContinueSkip.Setup(actionSet);
                actionSet.ContinueSkip.SetSkipCount(actionSet, lastCall.MethodStart);
                actionSet.AddAction(new A_Loop());

                SkipEndMarker continueAt = new SkipEndMarker();
                actionSet.AddAction(continueAt);
                skipLength.Value = actionSet.ContinueSkip.GetSkipCount(continueAt).Value;

                return(lastCall.ReturnHandler.GetReturnedValue());
            }
        }