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); }