private static void Update(AMethodDecl method, List <AMethodDecl> parsedMethods, ModifyData modifyData, Dictionary <AMethodDecl, List <AMethodDecl> > usedMethods, Dictionary <AMethodDecl, List <AFieldDecl> > readFields, Dictionary <AMethodDecl, List <AFieldDecl> > writtenFields)
        {
            if (parsedMethods.Contains(method))
            {
                return;
            }

            parsedMethods.Add(method);

            foreach (AFieldDecl fieldDecl in readFields[method])
            {
                modifyData.Add(fieldDecl, true, false);
            }
            foreach (AFieldDecl fieldDecl in writtenFields[method])
            {
                modifyData.Add(fieldDecl, false, true);
            }


            foreach (AMethodDecl usedMethod in usedMethods[method])
            {
                ModifyData data = GetModifyData(usedMethod);
                if (data == null)
                {
                    Update(usedMethod, parsedMethods, modifyData, usedMethods, readFields, writtenFields);
                }
                else
                {
                    modifyData.Union(data);
                }
            }
        }
        public static ModifyData GetLocalData(PExp expression, SharedData data)
        {
            if (expression == null)
            {
                return(new ModifyData());
            }

            AMethodDecl     method       = Util.GetAncestor <AMethodDecl>(expression);
            GetDependancies dependancies = new GetDependancies(data, method);

            expression.Apply(dependancies);
            ModifyData modifyData = new ModifyData();

            foreach (AFieldDecl fieldDecl in dependancies.ReadFields[method])
            {
                modifyData.Add(fieldDecl, true, false);
            }
            foreach (AFieldDecl fieldDecl in dependancies.WrittenFields[method])
            {
                modifyData.Add(fieldDecl, false, true);
            }
            foreach (AALocalDecl localDecl in dependancies.ReadLocals[method])
            {
                modifyData.Add(localDecl, true, false);
            }
            foreach (AALocalDecl localDecl in dependancies.WrittenLocals[method])
            {
                modifyData.Add(localDecl, false, true);
            }

            foreach (AMethodDecl usedMethod in dependancies.UsedMethods[method])
            {
                modifyData.Union(GetModifyData(usedMethod));
            }

            return(modifyData);
        }
        public static void CalculateMethodModify(AAProgram ast, SharedData data, out int methodCount)
        {
            //Calculate what global variables all methods might modify.
            methodData.Clear();


            GetDependancies dependancies = new GetDependancies(data);

            ast.Apply(dependancies);
            methodCount = dependancies.UsedMethods.Count;

            while (dependancies.UsedMethods.Count > 0)
            {
                LinkedList <AMethodDecl> modified = new LinkedList <AMethodDecl>();
                foreach (var pair in dependancies.UsedMethods)
                {
                    AMethodDecl        method      = pair.Key;
                    List <AMethodDecl> usedMethods = pair.Value;


                    ModifyData modifyData = new ModifyData();
                    foreach (AFieldDecl fieldDecl in dependancies.ReadFields[method])
                    {
                        modifyData.Add(fieldDecl, true, false);
                    }
                    foreach (AFieldDecl fieldDecl in dependancies.WrittenFields[method])
                    {
                        modifyData.Add(fieldDecl, false, true);
                    }
                    bool skip = false;
                    foreach (AMethodDecl usedMethod in usedMethods)
                    {
                        ModifyData usedData = GetModifyData(usedMethod);
                        if (usedData == null)
                        {
                            skip = true;
                            break;
                        }
                        modifyData.Union(usedData);
                    }
                    if (skip)
                    {
                        continue;
                    }
                    methodData[method] = modifyData;
                    modified.AddLast(method);
                }
                foreach (AMethodDecl decl in modified)
                {
                    dependancies.UsedMethods.Remove(decl);
                    dependancies.ReadFields.Remove(decl);
                    dependancies.WrittenFields.Remove(decl);
                }
                if (modified.Count == 0)
                {//The rest is in a circular dependancy
                    foreach (var pair in dependancies.UsedMethods)
                    {
                        AMethodDecl method = pair.Key;

                        ModifyData modifyData = new ModifyData();

                        Update(method, new List <AMethodDecl>(), modifyData, dependancies.UsedMethods, dependancies.ReadFields, dependancies.WrittenFields);

                        methodData[method] = modifyData;
                        modified.AddLast(method);
                    }
                    dependancies.UsedMethods.Clear();
                }
            }
        }
        public static ModifyData GetLocalData(PExp expression, SharedData data)
        {
            if (expression == null)
                return new ModifyData();

            AMethodDecl method = Util.GetAncestor<AMethodDecl>(expression);
            GetDependancies dependancies = new GetDependancies(data, method);
            expression.Apply(dependancies);
            ModifyData modifyData = new ModifyData();

            foreach (AFieldDecl fieldDecl in dependancies.ReadFields[method])
            {
                modifyData.Add(fieldDecl, true, false);
            }
            foreach (AFieldDecl fieldDecl in dependancies.WrittenFields[method])
            {
                modifyData.Add(fieldDecl, false, true);
            }
            foreach (AALocalDecl localDecl in dependancies.ReadLocals[method])
            {
                modifyData.Add(localDecl, true, false);
            }
            foreach (AALocalDecl localDecl in dependancies.WrittenLocals[method])
            {
                modifyData.Add(localDecl, false, true);
            }

            foreach (AMethodDecl usedMethod in dependancies.UsedMethods[method])
            {
                modifyData.Union(GetModifyData(usedMethod));
            }

            return modifyData;
        }
        public static void CalculateMethodModify(AAProgram ast, SharedData data, out int methodCount)
        {
            //Calculate what global variables all methods might modify.
            methodData.Clear();

            GetDependancies dependancies = new GetDependancies(data);
            ast.Apply(dependancies);
            methodCount = dependancies.UsedMethods.Count;

            while (dependancies.UsedMethods.Count > 0)
            {
                LinkedList<AMethodDecl> modified = new LinkedList<AMethodDecl>();
                foreach (var pair in dependancies.UsedMethods)
                {
                    AMethodDecl method = pair.Key;
                    List<AMethodDecl> usedMethods = pair.Value;

                    ModifyData modifyData = new ModifyData();
                    foreach (AFieldDecl fieldDecl in dependancies.ReadFields[method])
                    {
                        modifyData.Add(fieldDecl, true, false);
                    }
                    foreach (AFieldDecl fieldDecl in dependancies.WrittenFields[method])
                    {
                        modifyData.Add(fieldDecl, false, true);
                    }
                    bool skip = false;
                    foreach (AMethodDecl usedMethod in usedMethods)
                    {
                        ModifyData usedData = GetModifyData(usedMethod);
                        if (usedData == null)
                        {
                            skip = true;
                            break;
                        }
                        modifyData.Union(usedData);
                    }
                    if (skip)
                        continue;
                    methodData[method] = modifyData;
                    modified.AddLast(method);
                }
                foreach (AMethodDecl decl in modified)
                {
                    dependancies.UsedMethods.Remove(decl);
                    dependancies.ReadFields.Remove(decl);
                    dependancies.WrittenFields.Remove(decl);
                }
                if (modified.Count == 0)
                {//The rest is in a circular dependancy
                    foreach (var pair in dependancies.UsedMethods)
                    {
                        AMethodDecl method = pair.Key;

                        ModifyData modifyData = new ModifyData();

                        Update(method, new List<AMethodDecl>(), modifyData, dependancies.UsedMethods, dependancies.ReadFields, dependancies.WrittenFields);

                        methodData[method] = modifyData;
                        modified.AddLast(method);
                    }
                    dependancies.UsedMethods.Clear();
                }
            }
        }
        private static void Update(AMethodDecl method, List<AMethodDecl> parsedMethods, ModifyData modifyData, Dictionary<AMethodDecl, List<AMethodDecl>> usedMethods, Dictionary<AMethodDecl, List<AFieldDecl>> readFields, Dictionary<AMethodDecl, List<AFieldDecl>> writtenFields)
        {
            if (parsedMethods.Contains(method))
                return;

            parsedMethods.Add(method);

            foreach (AFieldDecl fieldDecl in readFields[method])
            {
                modifyData.Add(fieldDecl, true, false);
            }
            foreach (AFieldDecl fieldDecl in writtenFields[method])
            {
                modifyData.Add(fieldDecl, false, true);
            }

            foreach (AMethodDecl usedMethod in usedMethods[method])
            {
                ModifyData data = GetModifyData(usedMethod);
                if (data == null)
                {
                    Update(usedMethod, parsedMethods, modifyData, usedMethods, readFields, writtenFields);
                }
                else
                {
                    modifyData.Union(data);
                }
            }
        }