/// <summary>Gets a variable or type from a VariableContext.</summary>
        /// <param name="scope">The scope the variable was called in.</param>
        /// <param name="getter">The getter scope.</param>
        /// <param name="variableContext">The context of the variable.</param>
        /// <param name="selfContained">Wether the variable was not called in an expression tree.</param>
        /// <returns>An IExpression created from the context.</returns>
        public IExpression GetVariable(Scope scope, Scope getter, DeltinScriptParser.VariableContext variableContext, bool selfContained)
        {
            // Get the variable name and range.
            string   variableName  = variableContext.PART().GetText();
            DocRange variableRange = DocRange.GetRange(variableContext.PART());

            // Get the variable.
            IVariable element = scope.GetVariable(variableName, getter, Script.Diagnostics, variableRange);

            if (element == null)
            {
                return(null);
            }

            // Additional syntax checking.
            return(new VariableApply(this).Apply(element, ExpressionIndexArray(getter, variableContext.array()), variableRange));
        }
        public static IExpression GetVariable(ParseInfo parseInfo, Scope scope, Scope getter, DeltinScriptParser.VariableContext variableContext, bool selfContained)
        {
            string   variableName  = variableContext.PART().GetText();
            DocRange variableRange = DocRange.GetRange(variableContext.PART());

            var type = parseInfo.TranslateInfo.GetCodeType(variableName, null, null);

            if (type != null)
            {
                if (selfContained)
                {
                    parseInfo.Script.Diagnostics.Error("Types can't be used as expressions.", variableRange);
                }

                if (variableContext.array() != null)
                {
                    parseInfo.Script.Diagnostics.Error("Indexers cannot be used with types.", DocRange.GetRange(variableContext.array()));
                }

                type.Call(parseInfo.Script, variableRange);
                return(type);
            }

            IScopeable element = scope.GetVariable(variableName, getter, parseInfo.Script.Diagnostics, variableRange);

            if (element == null)
            {
                return(null);
            }

            if (element is ICallable)
            {
                ((ICallable)element).Call(parseInfo.Script, variableRange);
            }

            if (element is IApplyBlock)
            {
                parseInfo.CurrentCallInfo?.Call((IApplyBlock)element, variableRange);
            }

            if (element is IIndexReferencer var)
            {
                IExpression[] index;
                if (variableContext.array() == null)
                {
                    index = new IExpression[0];
                }
                else
                {
                    index = new IExpression[variableContext.array().expr().Length];
                    for (int i = 0; i < index.Length; i++)
                    {
                        index[i] = GetExpression(parseInfo, getter, variableContext.array().expr(i));
                    }
                }

                return(new CallVariableAction(var, index));
            }
            else if (element is ScopedEnumMember)
            {
                return((ScopedEnumMember)element);
            }
            else if (element is DefinedEnumMember)
            {
                return((DefinedEnumMember)element);
            }
            else if (element is MacroVar)
            {
                return((MacroVar)element);
            }
            else
            {
                throw new NotImplementedException();
            }
        }
        /// <summary>Gets a variable or type from a VariableContext.</summary>
        /// <param name="scope">The scope the variable was called in.</param>
        /// <param name="getter">The getter scope.</param>
        /// <param name="variableContext">The context of the variable.</param>
        /// <param name="selfContained">Wether the variable was not called in an expression tree.</param>
        /// <returns>An IExpression created from the context.</returns>
        public IExpression GetVariable(Scope scope, Scope getter, DeltinScriptParser.VariableContext variableContext, bool selfContained)
        {
            string   variableName  = variableContext.PART().GetText();
            DocRange variableRange = DocRange.GetRange(variableContext.PART());

            var type = TranslateInfo.Types.GetCodeType(variableName, null, null);

            if (type != null)
            {
                if (selfContained)
                {
                    Script.Diagnostics.Error("Types can't be used as expressions.", variableRange);
                }

                if (variableContext.array() != null)
                {
                    Script.Diagnostics.Error("Indexers cannot be used with types.", DocRange.GetRange(variableContext.array()));
                }

                type.Call(this, variableRange);
                return(type);
            }

            IVariable element = scope.GetVariable(variableName, getter, Script.Diagnostics, variableRange);

            if (element == null)
            {
                return(null);
            }

            if (element is ICallable)
            {
                ((ICallable)element).Call(this, variableRange);
            }

            if (element is IApplyBlock)
            {
                CurrentCallInfo?.Call((IApplyBlock)element, variableRange);
            }

            IExpression[] index = null;
            if (variableContext.array() != null)
            {
                index = new IExpression[variableContext.array().expr().Length];
                for (int i = 0; i < index.Length; i++)
                {
                    index[i] = GetExpression(getter, variableContext.array().expr(i));
                }
            }

            if (element is IIndexReferencer referencer)
            {
                return(new CallVariableAction(referencer, index));
            }

            if (index != null)
            {
                if (!element.CanBeIndexed)
                {
                    Script.Diagnostics.Error("This variable type cannot be indexed.", variableRange);
                }
                else
                {
                    return(new ValueInArrayAction(this, (IExpression)element, index));
                }
            }

            return((IExpression)element);
        }