/// <summary>
        /// Used to analyze scriptbloct, functionmemberast or functiondefinitionast
        /// </summary>
        /// <param name="ast"></param>
        /// <returns></returns>
        public void AnalyzeImpl(Ast ast, VariableAnalysis outerAnalysis)
        {
            if (!(ast is ScriptBlockAst || ast is FunctionMemberAst || ast is FunctionDefinitionAst))
            {
                return;
            }

            _variables = FindAllVariablesVisitor.Visit(ast);

            Init();

            if (ast is FunctionMemberAst || ast is FunctionDefinitionAst)
            {
                IEnumerable <ParameterAst> parameters = FindParameters(ast, ast.GetType());
                if (parameters != null)
                {
                    ProcessParameters(parameters);
                }
            }
            else
            {
                ScriptBlockAst sbAst = ast as ScriptBlockAst;
                if (sbAst != null && sbAst.ParamBlock != null && sbAst.ParamBlock.Parameters != null)
                {
                    ProcessParameters(sbAst.ParamBlock.Parameters);
                }
            }

            if (ast is FunctionMemberAst)
            {
                (ast as FunctionMemberAst).Body.Visit(this.Decorator);
            }
            else if (ast is FunctionDefinitionAst)
            {
                (ast as FunctionDefinitionAst).Body.Visit(this.Decorator);
            }
            else
            {
                ast.Visit(this.Decorator);
            }

            Ast parent = ast;

            while (parent.Parent != null)
            {
                parent = parent.Parent;
            }

            List <TypeDefinitionAst> classes = parent.FindAll(item =>
                                                              item is TypeDefinitionAst && (item as TypeDefinitionAst).IsClass, true)
                                               .Cast <TypeDefinitionAst>().ToList();

            if (outerAnalysis != null)
            {
                // Initialize the variables from outside
                var outerDictionary = outerAnalysis.InternalVariablesDictionary;
                foreach (var details in outerDictionary.Values)
                {
                    if (details.DefinedBlock != null)
                    {
                        var assignTarget = new AssignmentTarget(details.RealName, details.Type);
                        assignTarget.Constant = details.Constant;
                        if (!_variables.ContainsKey(assignTarget.Name))
                        {
                            _variables.Add(assignTarget.Name, new VariableAnalysisDetails
                            {
                                Name     = assignTarget.Name,
                                RealName = assignTarget.Name,
                                Type     = assignTarget.Type
                            });
                        }
                        Entry.AddFirstAst(assignTarget);
                    }
                }

                foreach (var key in _variables.Keys)
                {
                    if (outerDictionary.ContainsKey(key))
                    {
                        var outerItem = outerDictionary[key];
                        var innerItem = _variables[key];
                        innerItem.Constant = outerItem.Constant;
                        innerItem.Name     = outerItem.Name;
                        innerItem.RealName = outerItem.RealName;
                        innerItem.Type     = outerItem.Type;
                    }
                }
            }

            var dictionaries = Block.SparseSimpleConstants(_variables, Entry, classes);

            VariablesDictionary         = dictionaries.Item1;
            InternalVariablesDictionary = new Dictionary <string, VariableAnalysisDetails>(StringComparer.OrdinalIgnoreCase);

            foreach (var KVP in dictionaries.Item2)
            {
                var analysis = KVP.Value;
                if (analysis == null)
                {
                    continue;
                }

                if (!InternalVariablesDictionary.ContainsKey(analysis.RealName))
                {
                    InternalVariablesDictionary.Add(analysis.RealName, analysis);
                }
                else
                {
                    InternalVariablesDictionary[analysis.RealName] = analysis;
                }
            }
        }