abstract public Element Get(TranslateRule context, ScopeGroup scope, MethodNode methodNode, IWorkshopTree[] parameters);
        public Element Parse(TranslateRule context, bool needsToBeValue, ScopeGroup scope, MethodNode methodNode, IWorkshopTree[] parameters)
        {
            Element result = Get(context, scope, methodNode, parameters);

            if (!needsToBeValue)
            {
                result = null;
            }

            return(result);
        }
        override public Element Get(TranslateRule context, ScopeGroup scope, MethodNode methodNode, IWorkshopTree[] parameters)
        {
            Element result;

            if (!IsRecursive)
            {
                // Check the method stack if this method was already called.
                // Throw a syntax error if it was.
                if (context.MethodStackNotRecursive.Contains(this))
                {
                    throw SyntaxErrorException.RecursionNotAllowed(methodNode.Location);
                }

                var methodScope = scope.Root().Child();

                // Add the parameter variables to the scope.
                context.AssignParameterVariables(methodScope, Parameters, parameters, methodNode);

                // The variable that stores the return value.
                IndexedVar returns = null;
                if (DoesReturn)
                {
                    returns      = IndexedVar.AssignVar(context.VarCollection, scope, $"{methodNode.Name} return", context.IsGlobal, null);
                    returns.Type = Type;
                }

                // Add the method to the method stack
                context.MethodStackNotRecursive.Add(this);

                Block.RelatedScopeGroup = methodScope;

                // Parse the block of the method
                context.ParseBlock(methodScope, methodScope, Block, true, returns);

                // Take the method scope out of scope.
                methodScope.Out(context);

                // Remove the method from the stack.
                context.MethodStackNotRecursive.Remove(this);

                if (DoesReturn)
                {
                    result = returns.GetVariable();
                }
                else
                {
                    result = new V_Null();
                }
            }
            else
            {
                // Check the method stack if this method was already called. It will be null if it wasn't called.
                MethodStack lastMethod = context.MethodStackRecursive.FirstOrDefault(ms => ms.UserMethod == this);
                if (lastMethod != null)
                {
                    context.ContinueSkip.Setup();

                    // Re-push the paramaters.
                    for (int i = 0; i < lastMethod.ParameterVars.Length; i++)
                    {
                        if (lastMethod.ParameterVars[i] is RecursiveVar)
                        {
                            context.Actions.AddRange
                            (
                                ((RecursiveVar)lastMethod.ParameterVars[i]).InScope((Element)parameters[i])
                            );
                        }
                    }

                    // Add to the continue skip array.
                    context.Actions.AddRange(
                        lastMethod.ContinueSkipArray.SetVariable(
                            Element.Part <V_Append>(lastMethod.ContinueSkipArray.GetVariable(), new V_Number(context.ContinueSkip.GetSkipCount() + 3))
                            )
                        );

                    // Loop back to the start of the method.
                    context.ContinueSkip.SetSkipCount(lastMethod.ActionIndex);
                    context.Actions.Add(Element.Part <A_Loop>());

                    result = lastMethod.Return.GetVariable();
                }
                else
                {
                    var methodScope = scope.Root().Child(true);

                    // Add the parameter variables to the scope.
                    Var[] parameterVars = new Var[Parameters.Length];
                    for (int i = 0; i < parameterVars.Length; i++)
                    {
                        if (parameters[i] is Element)
                        {
                            // Create a new variable using the parameter input.
                            parameterVars[i] = (RecursiveVar)IndexedVar.AssignVar(context.VarCollection, methodScope, Parameters[i].Name, context.IsGlobal, methodNode);
                            ((RecursiveVar)parameterVars[i]).Type = ((Element)parameters[i]).SupportedType?.Type;
                            context.Actions.AddRange
                            (
                                ((RecursiveVar)parameterVars[i]).InScope((Element)parameters[i])
                            );
                        }
                        else if (parameters[i] is EnumMember)
                        {
                            parameterVars[i] = new ElementReferenceVar(Parameters[i].Name, methodScope, methodNode, parameters[i]);
                        }
                        else
                        {
                            throw new NotImplementedException();
                        }
                    }

                    var returns = IndexedVar.AssignInternalVarExt(context.VarCollection, null, $"{methodNode.Name}: return", context.IsGlobal);
                    returns.Type = Type;

                    // Setup the continue skip array.
                    IndexedVar continueSkipArray = IndexedVar.AssignInternalVar(context.VarCollection, null, $"{methodNode.Name} sca", context.IsGlobal);
                    var        stack             = new MethodStack(this, parameterVars, context.ContinueSkip.GetSkipCount(), returns, continueSkipArray);

                    // Add the method to the stack.
                    context.MethodStackRecursive.Add(stack);

                    Block.RelatedScopeGroup = methodScope;

                    // Parse the method block
                    context.ParseBlock(methodScope, methodScope, Block, true, returns);

                    // No return value if the method is being used as an action.
                    result = returns.GetVariable();

                    // Take the method out of scope.
                    //Actions.AddRange(methodScope.RecursiveMethodStackPop());
                    methodScope.Out(context);

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

                    // Remove the last continue skip.
                    context.Actions.AddRange(
                        continueSkipArray.SetVariable(
                            Element.Part <V_ArraySlice>(
                                continueSkipArray.GetVariable(),
                                new V_Number(0),
                                Element.Part <V_CountOf>(continueSkipArray.GetVariable()) - 1
                                )
                            )
                        );

                    // Loop if the method goes any deeper by checking the length of the continue skip array.
                    context.Actions.Add(
                        Element.Part <A_LoopIf>(
                            Element.Part <V_Compare>(
                                Element.Part <V_CountOf>(continueSkipArray.GetVariable()),
                                EnumData.GetEnumValue(Operators.NotEqual),
                                new V_Number(0)
                                )
                            )
                        );

                    // Reset the continue skip.
                    context.ContinueSkip.ResetSkip();
                    context.Actions.AddRange(continueSkipArray.SetVariable(0));

                    // Remove the method from the stack.
                    context.MethodStackRecursive.Remove(stack);
                }
            }

            return(result);
        }