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);
        }
            public ParseExpressionTree(TranslateRule translator, ScopeGroup getter, ScopeGroup scope, Node root)
            {
                if (root is VariableNode)
                {
                    VariableNode variableNode = (VariableNode)root;

                    Var var = scope.GetVar(getter, ((VariableNode)root).Name, root.Location);
                    ResultingVariable = var;

                    //if (!ResultingVariable.Gettable()) throw SyntaxErrorException.CantReadVariable(ResultingVariable.Name, root.Location);

                    if (ResultingVariable.Gettable())
                    {
                        ResultingElement = var.GetVariable();
                    }

                    VariableIndex = new Element[variableNode.Index.Length];
                    for (int i = 0; i < VariableIndex.Length; i++)
                    {
                        VariableIndex[i] = translator.ParseExpression(getter, scope, variableNode.Index[i]);
                    }

                    for (int i = 0; i < VariableIndex.Length; i++)
                    {
                        if (!ResultingVariable.Gettable())
                        {
                            throw SyntaxErrorException.CantReadVariable(ResultingVariable.Name, root.Location);
                        }
                        ResultingElement = Element.Part <V_ValueInArray>(ResultingElement, VariableIndex[i]);
                    }

                    return;
                }

                if (root is ExpressionTreeNode == false)
                {
                    throw new SyntaxErrorException("Error", root.Location);
                }

                List <Node> nodes        = flatten((ExpressionTreeNode)root);
                ScopeGroup  currentScope = scope;

                Element nodeResult = null;

                for (int index = 0; index < nodes.Count; index++)
                {
                    if (nodes[index] is RootNode)
                    {
                        currentScope = translator.ParserData.Root;
                        nodeResult   = new V_Null();
                    }
                    // If the node is a variable node, get the value.
                    else if (nodes[index] is VariableNode)
                    {
                        VariableNode variableNode = (VariableNode)nodes[index];
                        Var          var          = currentScope.GetVar(getter, variableNode.Name, variableNode.Location);

                        // If this is the last node, set the resulting var.
                        if (index == nodes.Count - 1)
                        {
                            ResultingVariable = var;
                        }

                        // Get the variable index
                        VariableIndex = new Element[variableNode.Index.Length];
                        for (int i = 0; i < VariableIndex.Length; i++)
                        {
                            VariableIndex[i] = translator.ParseExpression(getter, scope, variableNode.Index[i]);
                        }

                        // Set the nodeResult.
                        nodeResult = var.GetVariable(Target);

                        // Apply the index
                        for (int i = 0; i < VariableIndex.Length; i++)
                        {
                            nodeResult = Element.Part <V_ValueInArray>(nodeResult, VariableIndex[i]);
                        }
                    }
                    // If not, parse the node as an expression.
                    else
                    {
                        nodeResult = translator.ParseExpression(getter, currentScope, nodes[index]);
                    }

                    // SupportedType will equal null if the element is not a defined type.
                    if (nodeResult.SupportedType == null)
                    {
                        // If there is no supported type, assume the element or variable is containing a player.
                        // Reset the scope.
                        //currentScope = scope;
                        currentScope = translator.ParserData.Root;

                        // If this isn't the last node, set the target and reset the nodeResult.
                        if (index < nodes.Count - 1)
                        {
                            Target     = nodeResult;
                            nodeResult = null;
                        }
                    }
                    else
                    {
                        // Set the target scope to the type.
                        currentScope = nodeResult.SupportedType.Type.GetRootScope(nodeResult, nodeResult.SupportedType, translator.ParserData, Target);
                    }
                }
                ResultingElement = nodeResult;
            }