public CompilationUnit CompileUnit(PascalABCCompiler.TreeRealization.unit_node_list Units, SyntaxTree.unit_or_namespace SyntaxUsesUnit)
        {
            string UnitName = GetUnitFileName(SyntaxUsesUnit);
            //if (UnitName == null) throw new UnitNotFound(SyntaxUsesUnit.name,
            CompilationUnit CurrentUnit = UnitTable[UnitName];
            string name = Path.GetFileNameWithoutExtension(UnitName);
            if (Path.GetExtension(UnitName).ToLower() == CompilerOptions.CompiledUnitExtension)
            {
                string sfn = FindSourceFileName(Path.GetFileNameWithoutExtension(UnitName));
                if (sfn != null && UnitTable[sfn] != null)
                    CurrentUnit = UnitTable[sfn];
            }

            if (CurrentUnit != null)
                if (CurrentUnit.State != UnitState.BeginCompilation || CurrentUnit.SemanticTree != null)  //ИЗБАВИТЬСЯ ОТ ВТОРОГО УСЛОВИЯ
                {
                    Units.AddElement(CurrentUnit.SemanticTree);
                    Units.AddRange(GetReferences(CurrentUnit));
                    return CurrentUnit;
                }

            if (UnitName.ToLower().LastIndexOf(".dll") >= 0 || UnitName.ToLower().LastIndexOf(".exe") >= 0)
                if (File.Exists(UnitName))
                {
                    if (UnitTable.Count == 0) throw new ProgramModuleExpected(UnitName, null);
                    if ((CurrentUnit = ReadDLL(UnitName)) != null)
                    {
                        Units.AddElement(CurrentUnit.SemanticTree);
                        UnitTable[UnitName] = CurrentUnit;
                        return CurrentUnit;
                    }
                    else
                        //throw new DLLReadingError(UnitName);
                        throw new AssemblyReadingError(CurrentCompilationUnit.SyntaxTree.file_name, UnitName, SyntaxUsesUnit.source_context);
                }
            if (Path.GetExtension(UnitName).ToLower() == CompilerOptions.CompiledUnitExtension)
                if (File.Exists(UnitName))
                {
                    if (UnitTable.Count == 0) throw new ProgramModuleExpected(UnitName, null);
                    string SourceFileName = FindSourceFileName(Path.Combine(Path.GetDirectoryName(UnitName), Path.GetFileNameWithoutExtension(UnitName)));
                    try
                    {
                        //TODO: подумать как это нормально сделать
                        /*if (CompilerOptions.Debug)
                        {
                            PCUReader.PCUFileHeadState PCUFileHeadState = PCUReader.GetPCUFileHeadState(UnitName);
                            if (PCUFileHeadState.IsPCUFile && 
                                PCUFileHeadState.SupportedVersion && 
                                !PCUFileHeadState.IncludetDebugInfo && 
                                SourceFileName != null)
                            {
                                //перекомпилируем файл для получения отладочной информации
                                throw new Exception("");
                            }
                        }*/
                        if ((CurrentUnit = ReadPCU(UnitName)) != null)
                        {
                            Units.AddElement(CurrentUnit.SemanticTree);
                            Units.AddRange(GetReferences(CurrentUnit));
                            UnitTable[UnitName] = CurrentUnit;
                            return CurrentUnit;
                        }
                    }
                    catch (InvalidPCUFule)
                    {
                        //Перекомпилируем....
                    }
                    catch (Error)
                    {
                        throw;
                    }
                    catch (Exception e)
                    {
                        OnChangeCompilerState(this, CompilerState.PCUReadingError, UnitName);
#if DEBUG
                        if (!InternalDebug.SkipPCUErrors)
                            throw new Errors.CompilerInternalError("PCUReader", e);
#endif
                    }
                    if (SourceFileName == null)
                        throw new ReadPCUError(UnitName);
                    else
                        UnitName = SourceFileName;
                }
            string SourceText = null;
            Dictionary<SyntaxTree.syntax_tree_node, string> docs = null;
            if (CurrentUnit == null)
            {

                CurrentUnit = new CompilationUnit();
                if (FirstCompilationUnit == null)
                    FirstCompilationUnit = CurrentUnit;
                OnChangeCompilerState(this, CompilerState.BeginCompileFile, UnitName);
                SourceText = GetSourceFileText(UnitName);
                if (SourceText == null)
                    if (CurrentUnit == FirstCompilationUnit)
                        throw new SourceFileNotFound(UnitName);
                    else
                        throw new UnitNotFound(CurrentCompilationUnit.SyntaxTree.file_name, UnitName, SyntaxUsesUnit.source_context);

                CurrentUnit.SyntaxTree = InternalParseText(UnitName, SourceText, errorsList);

                if (errorsList.Count == 0) // SSM 2/05/16 - для преобразования синтаксических деревьев извне
                {
                    CurrentUnit.SyntaxTree = syntaxTreeConvertersController.Convert(CurrentUnit.SyntaxTree) as SyntaxTree.compilation_unit;
                }

                if (errorsList.Count == 0 && need_gen_doc(CurrentUnit.SyntaxTree))
                {
                    if (SourceText != null)
                    {
                        docs = AddDocumentationToNodes(CurrentUnit.SyntaxTree, SourceText);
                        if (docs != null)
                            CurrentUnit.Documented = true;
                    }
                }
                if (CurrentUnit.SyntaxTree is SyntaxTree.unit_module)
                    compilerOptions.UseDllForSystemUnits = false;
                if (is_dll(CurrentUnit.SyntaxTree))
                    compilerOptions.OutputFileType = PascalABCCompiler.CompilerOptions.OutputType.ClassLibrary;
                CurrentUnit.CaseSensitive = ParsersController.LastParser.CaseSensitive;
                CurrentCompilationUnit = CurrentUnit;

                CurrentUnit.SyntaxUnitName = SyntaxUsesUnit;

                //BadNodesInSyntaxTree.Clear();
                if (errorsList.Count > 0)
                {
                    CurrentUnit.syntax_error = errorsList[0] as PascalABCCompiler.Errors.SyntaxError;
                    foreach (Errors.Error er in errorsList)
                        if (er is SyntaxError && (er as SyntaxError).bad_node != null)
                            BadNodesInSyntaxTree[(er as SyntaxError).bad_node] = er;
                }

                //if (CurrentUnit.SyntaxTree == null)
                if (errorsList.Count > 0)
                {
                    //if (errorsList.Count == 0)
                    //    throw new Errors.SyntaxError("Internal parser error: Parser not create syntax tree", UnitName,null,null);
                    throw errorsList[0];
                }

                UnitTable[UnitName] = CurrentUnit;

                if (UnitTable.Count > 1)//если это не главный модуль
                    if (CurrentUnit.SyntaxTree is SyntaxTree.program_module)
                        throw new UnitModuleExpected(UnitName, CurrentUnit.SyntaxTree.source_context.LeftSourceContext);
                    else if (is_dll(CurrentUnit.SyntaxTree))
                        throw new UnitModuleExpectedLibraryFound(UnitName, CurrentUnit.SyntaxTree.source_context.LeftSourceContext);
                //здесь в начало uses добавляем стандартные модули
#if DEBUG
                if (InternalDebug.AddStandartUnits)
#endif
                    AddStandartUnitsToUsesSection(CurrentUnit.SyntaxTree);

            }
            CurrentSyntaxUnit = SyntaxUsesUnit;
            CurrentCompilationUnit = CurrentUnit;

            CurrentUnit.PossibleNamespaces.Clear();

            //TODO переделать, слишком сложно, некоторый код дублируется
            

            System.Collections.Generic.List<SyntaxTree.unit_or_namespace> SyntaxUsesList;
            SyntaxUsesList = GetSyntaxInterfaceUsesList(CurrentUnit.SyntaxTree);

            if (SyntaxUsesList != null)
            {
                for (int i = SyntaxUsesList.Count - 1 - CurrentUnit.InterfaceUsedUnits.Count; i >= 0; i--)
                {
                    if (!IsPossibleNamespace(SyntaxUsesList[i], false))
                    {
                        compilerOptions.UseDllForSystemUnits = false;
                        break;
                    }
                }
            }
            TreeRealization.unit_node_list References = GetReferences(CurrentUnit);

            if (SyntaxUsesList != null)
            {
                
                for (int i = SyntaxUsesList.Count - 1 - CurrentUnit.InterfaceUsedUnits.Count; i >= 0; i--)
                {
                    if (IsPossibleNamespace(SyntaxUsesList[i], true))
                    {
                        CurrentUnit.InterfaceUsedUnits.AddElement(new TreeRealization.namespace_unit_node(GetNamespace(SyntaxUsesList[i])));
                        CurrentUnit.PossibleNamespaces.Add(SyntaxUsesList[i]);
                    }
                    else
                    {
                        string CurrentSyntaxUnitName = GetUnitFileName(SyntaxUsesList[i]);
                        CurrentUnit.CurrentUsesUnit = CurrentSyntaxUnitName;
                        if (UnitTable[CurrentSyntaxUnitName] != null)
                            if (UnitTable[CurrentSyntaxUnitName].State == UnitState.BeginCompilation)
                            {
                                string CurrentSyntaxUnitNameCurrentUsesUnit = UnitTable[CurrentSyntaxUnitName].CurrentUsesUnit;
                                if (CurrentSyntaxUnitNameCurrentUsesUnit != null)
                                {
                                    //если сначало взали pcu а потом решили его перекомпилировать, поэтому в таблице его нет
                                    if (UnitTable[CurrentSyntaxUnitNameCurrentUsesUnit] == null)
                                        UnitTable[CurrentSyntaxUnitName].CurrentUsesUnit = FindSourceFileName(Path.GetFileNameWithoutExtension(CurrentSyntaxUnitNameCurrentUsesUnit));
                                    //далее финальная поверка на зацикливание
                                    if (UnitTable[CurrentSyntaxUnitName].CurrentUsesUnit != null && UnitTable[UnitTable[CurrentSyntaxUnitName].CurrentUsesUnit].State == UnitState.BeginCompilation)
                                        throw new CycleUnitReference(UnitName, SyntaxUsesList[i]);
                                }
                            }
                        CompileUnit(CurrentUnit.InterfaceUsedUnits, SyntaxUsesList[i]);
                        if (CurrentUnit.State == UnitState.Compiled)
                        {
                            Units.AddElement(CurrentUnit.SemanticTree);
                            Units.AddRange(References);
                            return CurrentUnit;
                        }
                    }

                }
            }

            CurrentCompilationUnit = CurrentUnit;

            CurrentUnit.InterfaceUsedUnits.AddRange(References);

            AddNamespaces(CurrentUnit.InterfaceUsingNamespaceList, CurrentUnit.PossibleNamespaces, true);
            AddNamespaces(CurrentUnit.InterfaceUsingNamespaceList, GetInterfaceSyntaxUsingList(CurrentUnit.SyntaxTree));

            //Console.WriteLine("Compile Interface "+UnitName);//DEBUG
#if DEBUG
            if (InternalDebug.SemanticAnalysis)
#endif
            {
                OnChangeCompilerState(this, CompilerState.CompileInterface, UnitName);
                PascalABCCompiler.TreeConverter.SemanticRules.SymbolTableCaseSensitive = CurrentUnit.CaseSensitive;
                CurrentUnit.SemanticTree = SyntaxTreeToSemanticTreeConverter.CompileInterface(
                    CurrentUnit.SyntaxTree,
                    CurrentUnit.InterfaceUsedUnits,
                    ErrorsList, Warnings,
                    CurrentUnit.syntax_error,
                    BadNodesInSyntaxTree,
                    CurrentUnit.InterfaceUsingNamespaceList,
                    docs,
                    CompilerOptions.Debug,
                    CompilerOptions.ForDebugging
                    );
                CheckErrors();
            }
            TreeRealization.common_unit_node cun = CurrentUnit.SemanticTree as TreeRealization.common_unit_node;
            /*if (cun != null)
            {
            	if (!UnitsSortedList.Contains(CurrentUnit))//vnimanie zdes inogda pri silnoj zavisimosti modulej moduli popadajut neskolko raz
            	UnitsSortedList.Add(CurrentUnit);
            }*/
            CurrentUnit.State = UnitState.InterfaceCompiled;
            if (Units != null)
            {
                Units.AddElement(CurrentUnit.SemanticTree);
                Units.AddRange(References);
            }
            SyntaxUsesList = GetSyntaxImplementationUsesList(CurrentUnit.SyntaxTree);
            CompilationUnit cu = null; bool interfcompile = true;
            CurrentUnit.ImplementationUsedUnits.clear();
            CurrentUnit.PossibleNamespaces.Clear();
            if (SyntaxUsesList != null)
            {
                for (int i = SyntaxUsesList.Count - 1; i >= 0; i--)
                    if (!IsPossibleNamespace(SyntaxUsesList[i], true))
                    {
                        cu = UnitTable[GetUnitFileName(SyntaxUsesList[i])];
                        if (cu != null && cu.State == UnitState.BeginCompilation)
                        {
                            UnitsToCompile.Add(cu);
                            interfcompile = false;
#if DEBUG
                            //                            Console.WriteLine("[DEBUGINFO]Send compile to end " + Path.GetFileName(GetUnitFileName(SyntaxUsesList[i])));//DEBUG
#endif
                        }
                        else
                            CompileUnit(CurrentUnit.ImplementationUsedUnits, SyntaxUsesList[i]);
                    }
                    else
                    {
                        CurrentUnit.ImplementationUsedUnits.AddElement(new TreeRealization.namespace_unit_node(GetNamespace(SyntaxUsesList[i])));
                        CurrentUnit.PossibleNamespaces.Add(SyntaxUsesList[i]);
                    }
            }

            CurrentCompilationUnit = CurrentUnit;

            AddNamespaces(CurrentUnit.ImplementationUsingNamespaceList, CurrentUnit.PossibleNamespaces, true);
            AddNamespaces(CurrentUnit.ImplementationUsingNamespaceList, GetImplementationSyntaxUsingList(CurrentUnit.SyntaxTree));

            if (!interfcompile)
            {
                UnitsToCompile.Add(CurrentUnit);
                if (cun != null)
                {
                    if (!UnitsSortedList.Contains(CurrentUnit))//vnimanie zdes inogda pri silnoj zavisimosti modulej moduli popadajut neskolko raz
                        UnitsSortedList.Add(CurrentUnit);
                }
                //Console.WriteLine("Send compile to end "+UnitName);//DEBUG
                return CurrentUnit;
            }

            //Console.WriteLine("Compile Implementation "+UnitName);//DEBUG
            if (CurrentUnit.SyntaxTree is SyntaxTree.unit_module)
            {
#if DEBUG
                if (InternalDebug.SemanticAnalysis)
#endif
                {
                    OnChangeCompilerState(this, CompilerState.CompileImplementation, UnitName);
                    PascalABCCompiler.TreeConverter.SemanticRules.SymbolTableCaseSensitive = CurrentUnit.CaseSensitive;
                    SyntaxTreeToSemanticTreeConverter.CompileImplementation(
                        (PascalABCCompiler.TreeRealization.common_unit_node)CurrentUnit.SemanticTree,
                        CurrentUnit.SyntaxTree,
                        buildImplementationUsesList(CurrentUnit),
                        ErrorsList, Warnings,
                        CurrentUnit.syntax_error,
                        BadNodesInSyntaxTree,
                        CurrentUnit.InterfaceUsingNamespaceList,
                        CurrentUnit.ImplementationUsingNamespaceList,
                        docs,
                        CompilerOptions.Debug,
                        CompilerOptions.ForDebugging
                        );
                    CheckErrors();
                }
            }
            CurrentUnit.State = UnitState.Compiled;
            if (cun != null)
            {
                if (!UnitsSortedList.Contains(CurrentUnit))//vnimanie zdes inogda pri silnoj zavisimosti modulej moduli popadajut neskolko raz
                    UnitsSortedList.Add(CurrentUnit);
            }
            OnChangeCompilerState(this, CompilerState.EndCompileFile, UnitName);
            //SavePCU(CurrentUnit, UnitName);
            CurrentUnit.UnitName = UnitName;
            return CurrentUnit;
            /*if(CurrentUnit.State!=UnitState.Compiled)
            { 
                //Console.WriteLine("Compile Interface "+UnitName);//DEBUG
                CurrentUnit.SemanticTree=SyntaxTreeToSemanticTreeConverter.CompileInterface(CurrentUnit.SyntaxTree,
                    CurrentUnit.InterfaceUsedUnits,CurrentUnit.syntax_error);
                CurrentUnit.State=UnitState.InterfaceCompiled;
                SyntaxUsesList=GetSemanticImplementationUsesList(CurrentUnit.SyntaxTree);
                if(SyntaxUsesList!=null)
                    for(int i=SyntaxUsesList.Count-1;i>=0;i--)
                        CompileUnit(CurrentUnit.ImplementationUsedUnits,SyntaxUsesList[i]);        
                //Console.WriteLine("Compile Implementation "+UnitName);//DEBUG
                if (CurrentUnit.SyntaxTree is SyntaxTree.unit_module)
                {
                    SyntaxTreeToSemanticTreeConverter.CompileImplementation(CurrentUnit.SemanticTree,
                        CurrentUnit.SyntaxTree,CurrentUnit.ImplementationUsedUnits,CurrentUnit.syntax_error);
                }
                CurrentUnit.State=UnitState.Compiled;
                Units.Add(CurrentUnit.SemanticTree);
                SaveSemanticTreeToFile(CurrentUnit,UnitName);
            }*/
        }
 private CompilationUnit CompileReference(PascalABCCompiler.TreeRealization.unit_node_list Units, TreeRealization.compiler_directive cd)
 {
     TreeRealization.location loc = cd.location;
     SyntaxTree.SourceContext sc = null;
     if (loc!=null)
         sc = new SyntaxTree.SourceContext(loc.begin_line_num,loc.begin_column_num,loc.end_line_num,loc.end_column_num,0,0);
     string UnitName = null;
     try
     {
         UnitName = GetReferenceFileName(cd.directive, sc);
     }
     catch (AssemblyNotFound ex)
     {
         throw;
     }
     catch(Exception ex)
     {
         throw new InvalidAssemblyPathError(CurrentCompilationUnit.SyntaxTree.file_name, sc);
     }
     CompilationUnit CurrentUnit = null;
     if (UnitTable.Count == 0) throw new ProgramModuleExpected(UnitName, null);
     if ((CurrentUnit = ReadDLL(UnitName)) != null)
     {
         Units.AddElement(CurrentUnit.SemanticTree);
         UnitTable[UnitName] = CurrentUnit;
         return CurrentUnit;
     }
     else
         //throw new DLLReadingError(UnitName);
     	throw new AssemblyReadingError(CurrentCompilationUnit.SyntaxTree.file_name,UnitName,sc);
 }