private void GetInitialValueDependencies()
        {
            foreach (var pair in initialValueExpressions)
            {
                var variable   = pair.Key;
                var expression = pair.Value;

                var symbols   = expression.GetSubexpressionsRecursive(TokenType.Identifier);
                var variables = symbols.Select(token => Symbols.GetOrNull(token.Token.Value)).ToArray();
                if (variables.Contains(null))
                {
                    //error
                }
                variables = variables.Distinct().ToArray();

                if (variables.Length == 0)
                {
                    var initialValue = EvaluateConstExpression(expression, variable.DataType, false);
                    if (initialValue != null)
                    {
                        InitialValues.Set(variable, initialValue);
                    }
                    else
                    {
                    }
                }
                else
                {
                    var depsList = initialDependencies.GetOrAddNew(variable);
                    depsList.AddRange(variables);
                }
            }
        }
        public void GetInitialValues(List <TokenExpression> result)
        {
            //first do the constatns
            var constDeclarations    = result.TokensWhere(TokenType.ConstDeclaration);
            var variableDeclarations = result.TokensWhere(TokenType.VariableDeclaration);
            var globalGroups         = result.TokensWhere(TokenType.GlobalGroupDeclaration);

            foreach (var constDeclaration in constDeclarations)
            {
                var variableDeclaration = constDeclaration.GetFirstSubexpression(TokenType.VariableDeclaration);
                SetVariableInitialValue(variableDeclaration, true);
            }
            foreach (var classDefinitionToken in result.TokensWhere(TokenType.ClassDefinition))
            {
                string className = classDefinitionToken.Subexpressions.TokensWhere(TokenType.Identifier).FirstOrDefault().Token.Value;
                var    entries   = classDefinitionToken.Subexpressions.TokensWhere(TokenType.ClassDefinitionEntries).FirstOrDefault();
                foreach (var entry in entries.Subexpressions.TokensWhere(TokenType.ClassDefinitionEntry))
                {
                    foreach (var constDeclaration in entry.Subexpressions.TokensWhere(TokenType.ConstDeclaration))
                    {
                        var variableDeclaration = constDeclaration.GetFirstSubexpression(TokenType.VariableDeclaration);
                        SetVariableInitialValue(variableDeclaration, className, true);
                    }
                }
            }


            //then do the globals
            foreach (var globalDeclaration in variableDeclarations)
            {
                SetVariableInitialValue(globalDeclaration);
            }
            foreach (var globalGroup in globalGroups)
            {
                foreach (var globalDeclaration in globalGroup.Subexpressions.TokensWhere(TokenType.VariableDeclaration))
                {
                    SetVariableInitialValue(globalDeclaration);
                }
            }

            //then do the function parameters
            foreach (var pair in FunctionDeclarationTokens)
            {
                var function         = pair.Key;
                var declarationToken = pair.Value;
                var parameterList    = declarationToken.Subexpressions.TokensWhere(TokenType.FunctionParameterList).FirstOrDefault();
                if (parameterList != null)
                {
                    int i = 0;
                    foreach (var parameter in parameterList.Subexpressions.TokensWhere(TokenType.FunctionParameter))
                    {
                        var initialValueToken = parameter.Subexpressions.TokensWhere(TokenType.VariableInitialValue).FirstOrDefault();
                        if (initialValueToken != null)
                        {
                            var parameterVariable = function.GetNonVoidFunctionParameter(i);
                            SetVariableInitialValueToken(parameterVariable, initialValueToken);
                        }
                        i++;
                    }
                }
            }

            //get dependencies
            GetInitialValueDependencies();

            //resolve dependencies - O(n^2) method
            while (true)
            {
                var pairs = initialDependencies.ToArray();
                int count = pairs.Length;
                foreach (var pair in pairs)
                {
                    var  variable       = pair.Key;
                    var  dependencyList = pair.Value;
                    bool isSatisfied    = true;
                    foreach (var dep in dependencyList)
                    {
                        if (initialDependencies.ContainsKey(dep))
                        {
                            isSatisfied = false;
                        }
                    }
                    if (isSatisfied)
                    {
                        initialDependencies.Remove(variable);
                        var initialValueExpression = initialValueExpressions[variable];
                        var initialValue           = EvaluateConstExpression(initialValueExpression, variable.DataType, false);
                        InitialValues.Set(variable, initialValue);
                    }
                }
                if (initialDependencies.Count == 0)
                {
                    break;
                }
                if (count == initialDependencies.Count)
                {
                    //error - circular dependencies
                    break;
                }
            }

            //Set global initial values
            foreach (var pair in InitialValues)
            {
                var variable = pair.Key;
                var global   = variable as Global;
                if (global != null)
                {
                    var initialValue       = pair.Value;
                    var globalInitialValue = new GlobalInitialValue(initialValue);
                    globalInitialValue.Root        = ainFile;
                    globalInitialValue.GlobalIndex = global.Index;
                    ainFile.GlobalInitialValues.Add(globalInitialValue);
                }
            }
        }