public List<Errors.CompilerWarning> Optimize(program_node p) { try { foreach (common_namespace_node cnn in p.common_namespaces) { VisitCommonNamespaceHeader(cnn); } foreach (common_namespace_node cnn in p.common_namespaces) { VisitCommonNamespaceNode(cnn); } if (p.main_function != null) VisitStatement(p.main_function.function_code); foreach (common_namespace_node cnn in p.common_namespaces) { CollectInfoNamespaces(cnn); } return warns; } catch (Exception e) { return warns; } }
public void ClearAll() { _semantic_tree = null; PCUReader.CloseUnits(); PCUWriter.Clear(); RecompileList.Clear(); CycleUnits.Clear(); UnitTable.Clear(); UnitsSortedList.Clear(); //TreeRealization.PCUReturner.Clear(); BadNodesInSyntaxTree.Clear(); PCUReader.AllReaders.Clear(); project = null; StandarModules.Clear(); //SystemLibrary.SystemLibrary.RestoreStandartNames(); }
public string Compile() { try { //var timer = System.Diagnostics.Stopwatch.StartNew(); ////// if (Path.GetExtension(CompilerOptions.SourceFileName) == ".vb") { return CompileVB(); } if (Path.GetExtension(CompilerOptions.SourceFileName) == ".cs") { return CompileCS(); } OnChangeCompilerState(this, CompilerState.CompilationStarting, CompilerOptions.SourceFileName); Reset(); //Console.WriteLine(timer.ElapsedMilliseconds / 1000.0); ////// if (CompilerOptions.ProjectCompiled) { PrepareCompileOptionsForProject(); } Environment.CurrentDirectory = CompilerOptions.SourceFileDirectory; // нужно для подключения *.inc и *.resources Units = new PascalABCCompiler.TreeRealization.unit_node_list(); CurrentSyntaxUnit = new SyntaxTree.uses_unit_in(new SyntaxTree.string_const(CompilerOptions.SourceFileName)); CompileUnit(Units, CurrentSyntaxUnit); //Console.WriteLine(timer.ElapsedMilliseconds / 1000.0); ////// foreach (CompilationUnit CurrentUnit in UnitsToCompile) if (CurrentUnit.State != UnitState.Compiled) { CurrentCompilationUnit = CurrentUnit; string UnitName = GetUnitFileName(CurrentUnit.SyntaxUnitName); //if(CurrentUnit.State!=UnitState.InterfaceCompiled) //DEBUG //Console.WriteLine("ERROR! interface not compiled "+GetUnitFileName(CurrentUnit.SyntaxUnitName));//DEBUG System.Collections.Generic.List<SyntaxTree.unit_or_namespace> SyntaxUsesList = GetSyntaxImplementationUsesList(CurrentUnit.SyntaxTree); CurrentUnit.PossibleNamespaces.Clear(); if (SyntaxUsesList != null) { for (int i = SyntaxUsesList.Count - 1; i >= 0; i--) if (!IsPossibleNamespace(SyntaxUsesList[i], false)) { compilerOptions.UseDllForSystemUnits = false; break; } for (int i = SyntaxUsesList.Count - 1; i >= 0; i--) if (!IsPossibleNamespace(SyntaxUsesList[i], true)) CompileUnit(CurrentUnit.ImplementationUsedUnits, SyntaxUsesList[i]); else { CurrentUnit.ImplementationUsedUnits.AddElement(new TreeRealization.namespace_unit_node(GetNamespace(SyntaxUsesList[i]))); CurrentUnit.PossibleNamespaces.Add(SyntaxUsesList[i]); } } //Console.WriteLine("Compile Implementation "+UnitName);//DEBUG //TODO: Избавиться от преобразования типа. AddNamespaces(CurrentUnit.ImplementationUsingNamespaceList, CurrentUnit.PossibleNamespaces, true); #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, null, CompilerOptions.Debug, CompilerOptions.ForDebugging ); CheckErrors(); } CurrentUnit.State = UnitState.Compiled; OnChangeCompilerState(this, CompilerState.EndCompileFile, UnitName); //SavePCU(CurrentUnit, UnitName); CurrentUnit.UnitName = UnitName; } ClosePCUReadersAndWriters(); if (CompilerOptions.SaveDocumentation) SaveDocumentations(); compilerDirectives = GetCompilerDirectives(UnitsSortedList); TreeRealization.compiler_directive compilerDirective; //TODO сделать это понормальному!!!!! if (compilerDirectives.ContainsKey(TreeConverter.compiler_string_consts.compiler_directive_apptype)) { string directive = compilerDirectives[TreeConverter.compiler_string_consts.compiler_directive_apptype][0].directive; if (string.Compare(directive,"console",true)==0) CompilerOptions.OutputFileType = CompilerOptions.OutputType.ConsoleApplicaton; else if (string.Compare(directive,"windows",true)==0) CompilerOptions.OutputFileType = CompilerOptions.OutputType.WindowsApplication; else if (string.Compare(directive,"dll",true)==0) CompilerOptions.OutputFileType = CompilerOptions.OutputType.ClassLibrary; else if (string.Compare(directive,"pcu",true)==0) CompilerOptions.OutputFileType = CompilerOptions.OutputType.PascalCompiledUnit; } moveSystemUnitToForwardUnitSortedList(); PascalABCCompiler.TreeRealization.common_unit_node system_unit = null; if (UnitsSortedList.Count>0) system_unit = UnitsSortedList[0].SemanticTree as PascalABCCompiler.TreeRealization.common_unit_node; if (system_unit != null) system_unit.IsConsoleApplicationVariable = CompilerOptions.OutputFileType == CompilerOptions.OutputType.ConsoleApplicaton; TreeRealization.program_node pn = null; NETGenerator.CompilerOptions cdo = new NETGenerator.CompilerOptions(); List<TreeRealization.compiler_directive> cds; if (compilerDirectives.TryGetValue(TreeConverter.compiler_string_consts.compiler_directive_platformtarget, out cds)) { string plt = cds[0].directive.ToLower(); if (plt.Equals("x86")) cdo.platformtarget = NETGenerator.CompilerOptions.PlatformTarget.x86; else if (plt.Equals("x64")) cdo.platformtarget = NETGenerator.CompilerOptions.PlatformTarget.x64; else if (plt.Equals("anycpu")) cdo.platformtarget = NETGenerator.CompilerOptions.PlatformTarget.AnyCPU; } if (this.compilerOptions.Only32Bit) cdo.platformtarget = NETGenerator.CompilerOptions.PlatformTarget.x86; if (compilerDirectives.TryGetValue(TreeConverter.compiler_string_consts.product_string, out cds)) { cdo.Product = cds[0].directive; } if (compilerDirectives.TryGetValue(TreeConverter.compiler_string_consts.version_string, out cds)) { cdo.ProductVersion = cds[0].directive; } if (compilerDirectives.TryGetValue(TreeConverter.compiler_string_consts.company_string, out cds)) { cdo.Company = cds[0].directive; } if (compilerDirectives.TryGetValue(TreeConverter.compiler_string_consts.trademark_string, out cds)) { cdo.TradeMark = cds[0].directive; } if (compilerDirectives.TryGetValue(TreeConverter.compiler_string_consts.copyright_string, out cds)) { cdo.Copyright = cds[0].directive; } if (compilerDirectives.TryGetValue(TreeConverter.compiler_string_consts.main_resource_string, out cds)) { cdo.MainResourceFileName = cds[0].directive; if (!File.Exists(cdo.MainResourceFileName)) { ErrorsList.Add(new ResourceFileNotFound(cds[0].directive, cds[0].location)); } } List<string> ResourceFiles = null; if (compilerDirectives.ContainsKey(TreeConverter.compiler_string_consts.compiler_directive_resource)) { ResourceFiles = new List<string>(); List<TreeRealization.compiler_directive> ResourceDirectives = compilerDirectives[TreeConverter.compiler_string_consts.compiler_directive_resource]; foreach (TreeRealization.compiler_directive cd in ResourceDirectives) if (!File.Exists(cd.directive)) { string fileName = Path.Combine(cd.location.doc.file_name, cd.directive); if (File.Exists(fileName)) ResourceFiles.Add(fileName); else ErrorsList.Add(new ResourceFileNotFound(cd.directive, cd.location)); } else ResourceFiles.Add(cd.directive); } string res_file = null; if (project != null) { if (!(project.major_version == 0 && project.minor_version == 0 && project.build_version == 0 && project.revision_version == 0)) cdo.ProductVersion = project.major_version + "." + project.minor_version + "." + project.build_version + "." + project.revision_version; if (!string.IsNullOrEmpty(project.product)) cdo.Product = project.product; if (!string.IsNullOrEmpty(project.company)) cdo.Company = project.company; if (!string.IsNullOrEmpty(project.trademark)) cdo.TradeMark = project.trademark; if (!string.IsNullOrEmpty(project.copyright)) cdo.Copyright = project.copyright; if (!string.IsNullOrEmpty(project.app_icon) && false) { //cdo.MainResourceFileName = project.app_icon; string rc_file = Path.GetFileNameWithoutExtension(project.app_icon) + ".rc"; StreamWriter sw = File.CreateText(rc_file); sw.WriteLine("1 ICON \"" + project.app_icon.Replace("\\", "\\\\") + "\""); if (cdo.NeedDefineVersionInfo) { cdo.NeedDefineVersionInfo = false; sw.WriteLine("1 VERSIONINFO"); string ver = project.major_version + "," + project.minor_version + "," + project.build_version + "," + project.revision_version; sw.WriteLine("FILEVERSION " + ver); /*sw.WriteLine("FILEFLAGSMASK VS_FFI_FILEFLAGSMASK"); sw.WriteLine("FILEFLAGS VER_DEBUG"); sw.WriteLine("FILEOS VOS__WINDOWS32"); if (project.project_type != ProjectType.Library) sw.WriteLine("FILETYPE VFT_APP"); else sw.WriteLine("FILETYPE VFT_DLL"); sw.WriteLine("FILESUBTYPE VFT2_UNKNOWN");*/ sw.WriteLine("BEGIN \r\n BLOCK \"StringFileInfo\"\r\n BEGIN \r\n BLOCK \"041904E3\"\r\nBEGIN"); sw.WriteLine("VALUE \"ProductName\"," + "\"" + cdo.Product + "\""); sw.WriteLine("VALUE \"FileVersion\"," + "\"" + ver + "\""); sw.WriteLine("VALUE \"ProductVersion\"," + "\"" + ver + "\""); sw.WriteLine("VALUE \"FileDescription\"," + "\"" + "" + "\""); sw.WriteLine("VALUE \"OriginalFileName\"," + "\"" + Path.GetFileName(CompilerOptions.OutputFileName) + "\""); sw.WriteLine("VALUE \"InternalName\"," + "\"" + Path.GetFileNameWithoutExtension(CompilerOptions.OutputFileName) + "\""); sw.WriteLine("VALUE \"CompanyName\"," + "\"" + cdo.Company + "\""); sw.WriteLine("VALUE \"LegalTrademarks1\"," + "\"" + cdo.TradeMark + "\""); sw.WriteLine("VALUE \"LegalCopyright\"," + "\"" + cdo.Copyright + "\""); sw.WriteLine("END"); sw.WriteLine("END"); sw.WriteLine("BLOCK \"VarFileInfo\"\r\nBEGIN"); sw.WriteLine("VALUE \"Translation\", 0x0419, 1251"); sw.WriteLine("END"); sw.WriteLine("END"); } sw.Close(); System.Diagnostics.Process prc = new System.Diagnostics.Process(); prc.StartInfo.FileName = Path.Combine(this.CompilerOptions.SystemDirectory, "rc.exe"); prc.StartInfo.Arguments = Path.Combine(Path.GetDirectoryName(project.app_icon), Path.GetFileNameWithoutExtension(project.app_icon) + ".rc"); prc.StartInfo.CreateNoWindow = true; prc.StartInfo.UseShellExecute = false; prc.StartInfo.RedirectStandardOutput = true; prc.StartInfo.RedirectStandardError = true; prc.Start(); prc.WaitForExit(); res_file = Path.Combine(Path.GetDirectoryName(project.app_icon), Path.GetFileNameWithoutExtension(project.app_icon) + ".res"); if (File.Exists(res_file)) { cdo.MainResourceFileName = res_file; } File.Delete(rc_file); } } if (ErrorsList.Count == 0 && compilerOptions.GenerateCode) { cdo.ForRunningWithEnvironment = CompilerOptions.RunWithEnvironment; switch (CompilerOptions.OutputFileType) { case CompilerOptions.OutputType.ClassLibrary: cdo.target = NETGenerator.TargetType.Dll; break; case CompilerOptions.OutputType.ConsoleApplicaton: cdo.target = NETGenerator.TargetType.Exe; break; case CompilerOptions.OutputType.WindowsApplication: cdo.target = NETGenerator.TargetType.WinExe; break; } if (project != null && project.ProjectType == ProjectType.WindowsApp) cdo.target = PascalABCCompiler.NETGenerator.TargetType.WinExe; switch (CompilerOptions.Debug) { case true: cdo.dbg_attrs = NETGenerator.DebugAttributes.Debug; break; case false: cdo.dbg_attrs = NETGenerator.DebugAttributes.Release; break; } if (CompilerOptions.ForDebugging) cdo.dbg_attrs = NETGenerator.DebugAttributes.ForDebbuging; //TODO: Разобратся c location для program_node и правильно передавать main_function. Добавить генератор main_function в SyntaxTreeToSemanticTreeConverter. pn = new PascalABCCompiler.TreeRealization.program_node(null, null); for (int i = 0; i < UnitsSortedList.Count; i++) pn.units.AddElement(UnitsSortedList[i].SemanticTree as TreeRealization.common_unit_node); //(ssyy) Добавил в условие c_module if (FirstCompilationUnit.SyntaxTree is SyntaxTree.program_module || FirstCompilationUnit.SyntaxTree is SyntaxTree.c_module) { if ((cdo.target == NETGenerator.TargetType.Exe) || (cdo.target == NETGenerator.TargetType.WinExe)) { if (UnitsSortedList.Count > 0) { pn.main_function = ((PascalABCCompiler.TreeRealization.common_unit_node)UnitsSortedList[UnitsSortedList.Count - 1].SemanticTree).main_function; /***************************Ivan added*******************************/ if (pn.main_function.function_code.location != null) { bool flag = false; PascalABCCompiler.TreeRealization.common_namespace_node main_ns = pn.main_function.namespace_node; for (int i = 0; i < main_ns.variables.Count; i++) { PascalABCCompiler.TreeRealization.namespace_variable nv = main_ns.variables[i]; if (nv.inital_value != null && nv.inital_value.location != null && !(nv.inital_value is PascalABCCompiler.TreeRealization.constant_node) && !(nv.inital_value is PascalABCCompiler.TreeRealization.record_initializer) && !(nv.inital_value is PascalABCCompiler.TreeRealization.array_initializer)) { varBeginOffset = main_ns.variables[i].inital_value.location.begin_line_num; flag = true; break; } } beginOffset = pn.main_function.function_code.location.begin_line_num; } /*******************************************************************/ Dictionary<string, object> config_dic = new Dictionary<string, object>(); if (CompilerOptions.Locale != null && PascalABCCompiler.StringResourcesLanguage.GetLCIDByTwoLetterISO(CompilerOptions.Locale) != null) { config_dic["locale"] = CompilerOptions.Locale; config_dic["full_locale"] = PascalABCCompiler.StringResourcesLanguage.GetLCIDByTwoLetterISO(CompilerOptions.Locale); } pn.create_main_function(StandarModules.ToArray(), config_dic); } } } else if (FirstCompilationUnit.SyntaxTree is SyntaxTree.unit_module && cdo.target == NETGenerator.TargetType.Dll) { pn.create_main_function_as_in_module(); } pn = semanticTreeConvertersController.Convert(pn) as TreeRealization.program_node; _semantic_tree = pn; if (FirstCompilationUnit.SyntaxTree is SyntaxTree.unit_module && CompilerOptions.OutputFileType != CompilerOptions.OutputType.ClassLibrary) { //если мы комилируем PCU CompilerOptions.OutputFileType = CompilerOptions.OutputType.PascalCompiledUnit; } else { if( CompilerOptions.OutputFileType!= CompilerOptions.OutputType.SemanticTree) #if DEBUG if (InternalDebug.CodeGeneration) #endif { try { File.Create(CompilerOptions.OutputFileName).Close(); //File.Delete(CompilerOptions.OutputFileName); string pdb_file_name=Path.ChangeExtension(CompilerOptions.OutputFileName, ".pdb"); if (File.Exists(pdb_file_name)) File.Delete(pdb_file_name); } catch (Exception) { throw new UnauthorizedAccessToFile(CompilerOptions.OutputFileName); } OnChangeCompilerState(this, CompilerState.CodeGeneration, CompilerOptions.OutputFileName); string[] ResourceFilesArray = null; if (ResourceFiles != null) ResourceFilesArray = ResourceFiles.ToArray(); cds = null; /*if (compilerDirectives.TryGetValue("platform", out cds) && cds[0].directive.ToLower() == "native") { //LLVMCodeGeneratorsController.Compile(pn, CompilerOptions.OutputFileName, CompilerOptions.SourceFileName, ResourceFilesArray); PABCToCppCodeGeneratorsController.Compile(pn, CompilerOptions.OutputFileName, CompilerOptions.SourceFileName, ResourceFilesArray); } else*/ CodeGeneratorsController.Compile(pn, CompilerOptions.OutputFileName, CompilerOptions.SourceFileName, cdo, CompilerOptions.StandartDirectories, ResourceFilesArray); if (res_file != null) File.Delete(res_file); } } } } catch (TreeConverter.ParserError err) { //конвертор уткнулся в ошибку. ничего не делаем } catch (Errors.CompilerInternalError err) { if (ErrorsList.Count == 0) ErrorsList.Add(err); else { #if DEBUG if (!InternalDebug.SkipInternalErrorsIfSyntaxTreeIsCorrupt) ErrorsList.Add(err); #endif } } catch (Errors.Error err) { if (ErrorsList.Count == 0) ErrorsList.Add(err); else if (err != ErrorsList[0]) { if (err is SemanticError) { int pos = ErrorsList.Count; SourceLocation loc = (err as SemanticError).SourceLocation, loctmp; if (loc != null) for (int i = 0; i < ErrorsList.Count; i++) if (ErrorsList[i] is LocatedError) if ((loctmp = (ErrorsList[i] as LocatedError).SourceLocation) != null) if (loctmp > loc) { pos = i; break; } ErrorsList.Insert(pos, err); } else ErrorsList.Add(err); } } catch (Exception err) { string fn = "Compiler"; if (CurrentCompilationUnit != null && this.CurrentCompilationUnit.SyntaxTree != null) fn = Path.GetFileName(this.CurrentCompilationUnit.SyntaxTree.file_name); Errors.CompilerInternalError comp_err = new Errors.CompilerInternalError(string.Format("Compiler.Compile[{0}]", fn), err); if (ErrorsList.Count == 0) ErrorsList.Add(comp_err); else { #if DEBUG if (!InternalDebug.SkipInternalErrorsIfSyntaxTreeIsCorrupt) ErrorsList.Add(comp_err); #endif } } //удаляем лишние ошибки /*foreach(Error er in errorsList) { }*/ //на случай если мы вывалились по исключению но у нас есть откомпилированные модули try { ClosePCUReadersAndWriters(); } catch (Exception e) { ErrorsList.Add(new Errors.CompilerInternalError("Compiler.ClosePCUReadersAndWriters", e)); } bool need_recompiled = false; if (ErrorsList.Count > 0) { if (compilerOptions.UseDllForSystemUnits && !has_only_syntax_errors(ErrorsList) && compilerOptions.IgnoreRtlErrors) { compilerOptions.UseDllForSystemUnits = false; ErrorsList.Clear(); need_recompiled = true; } } OnChangeCompilerState(this, CompilerState.CompilationFinished, CompilerOptions.SourceFileName); if (ClearAfterCompilation) ClearAll(); OnChangeCompilerState(this, CompilerState.Ready, null); if (ErrorsList.Count > 0) { return null; } else if (need_recompiled) { //Compiler c = new Compiler(sourceFilesProvider,OnChangeCompilerState); //return c.Compile(this.compilerOptions); return Compile(); } else return CompilerOptions.OutputFileName; }