2020-07-09 05:54:55 +03:00
// Copyright (c) Ivan Bondarev, Stanislav Mikhalkovich (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* У п р а в л я ю щ и й б л о к к о м п и л я т о р а , а л г о р и т м к о м п и л я ц и и м о д у л е й
* З а в и с и т о т Errors , SyntaxTree , SemanticTree , Parsers , TreeConvertor ,
* CodeGenerators
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
//TODO разобраться с ToLower()!!!
#region algorithm
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Р е к у р с и в н ы й а л г о р и т м к о м п и л я ц и и м о д у л е й
* в е р с и я 1.4
*
* CompileUnit ( И м я Ф а й л а )
* 1. CompileUnit ( new С п и с о к М о д у л е й , И м я Ф а й л а )
* 2. Д о к о м п и л и р о в а т ь м о д у л и и з С п и с о к О т л о ж е н о й К о м п и л я ц и и ;
*
* CompileUnit ( С п и с о к М о д у л е й , И м я Ф а й л а )
* 1. Т е к у щ и й М о д у л ь = Т а б л и ц а М о д у л е й [ И м я Ф а й л а ] ;
* Е с л и ( Т е к у щ и й М о д у л ь ! = 0 ) т о
* Е с л и ( Т е к у щ и й М о д у л ь . С о с т о я н и е = = BeginCompilation )
* С п и с о к М о д у л е й . Д о б а в и т ь ( Т е к у щ и й М о д у л ь ) ;
* В ы х о д ;
* и н а ч е п е р е й т и к п у н к т у 5
*
* 2. Е с л и Э т о Ф а й л DLL ( И м я Ф а й л а ) т о
* Е с л и ( ( Т е к у щ и й М о д у л ь = С ч и т а т ь DLL ( И м я Ф а й л а ) ) ! = 0 ) т о
* С п и с о к М о д у л е й . Д о б а в и т ь ( Т е к у щ и й М о д у л ь ) ;
* Т а б л и ц а М о д у л е й . Д о б а в и т ь ( Т е к у щ и й М о д у л ь ) ;
* В ы х о д ;
* и н а ч е
* О ш и б к а ( "Н е могу подключить сборку" ) ;
* В ы х о д ;
*
* 3. Е с л и Э т о Ф а й л PCU ( И м я Ф а й л а ) т о
* Е с л и ( ( Т е к у щ и й М о д у л ь = С ч и т а т ь PCU ( И м я Ф а й л а ) ) ! = 0 ) т о
* С п и с о к М о д у л е й . Д о б а в и т ь ( Т е к у щ и й М о д у л ь ) ;
* Т а б л и ц а М о д у л е й . Д о б а в и т ь ( Т е к у щ и й М о д у л ь ) ;
* В ы х о д ;
* и н а ч е
* и н а ч е п е р е й т и к п у н к т у 4 ;
*
* 4. Т е к у щ и й М о д у л ь = н о в ы й М о д у л ь ( ) ;
* Т е к у щ и й М о д у л ь . С и н т а к с и ч е с к о е Д е р е в о = П а р а с е р ы . П а р с и т ь ( И м я Ф а й л а , Т е к у щ и й М о д у л ь . С п и с о к О ш и б о к ) ;
* Е с л и ( Т е к у щ и й М о д у л ь . С и н т а к с и ч е с к о е Д е р е в о = = 0 ) т о
* Е с л и ( Т е к у щ и й М о д у л ь . С п и с о к О ш и б о к . К о л и ч е с т в о = = 0 ) т о
* О ш и б к а ( "Модуль не неайден" ) ;
* и н а ч е
* О ш и б к а ( Т е к у щ и й М о д у л ь . С п и с о к О ш и б о к [ 0 ] ) ;
* Т а б л и ц а М о д у л е й [ И м я Ф а й л а ] = Т е к у щ и й М о д у л ь ;
* Т е к у щ и й М о д у л ь . С о с т о я н и е = BeginCompilation ;
*
* 5. С и н т а к с и ч е с к и й С п и с о к М о д у л е й = Т е к у щ и й М о д у л ь . С и н т а к с и ч е с к о е Д е р е в о . Interface . UsesList ;
* Д л я ( i = С и н т а к с и ч е с к и й С п и с о к М о д у л е й . К о л и ч е с т в о - 1 - Т е к у щ и й М о д у л ь . К о м п и л и р о в а н ы е В Interface . К о л и ч е с т в о ; i > = 0 ; i - - )
* Т е к у ш и й М о д у л ь . Т е к у щ и й UsesМ о ду ль = С и н т а к с и ч е с к и й С п и с о к М о д у л е й [ i ] . И м я Ф а й л а ;
* И м я UsesФа йла = С и н т а к с и ч е с к и й С п и с о к М о д у л е й [ i ] . И м я Ф а й л а ;
* Е с л и ( Т а б л и ц а М о д у л е й [ И м я UsesФа йла ] ! = 0 )
* Е с л и ( Т а б л и ц а М о д у л е й [ И м я UsesФа йла ] . С о с т о я н и е = = BeginCompilation )
* Е с л и ( Т а б л и ц а М о д у л е й [ Т а б л и ц а М о д у л е й [ И м я UsesФа йла ] . Т е к у щ и й UsesМ о ду ль ] . С о с т о я н и е = BeginCompilation )
* О ш и б к а ( "Циклическая связь модулей" ) ;
* CompileUnit ( Т е к у щ и й М о д у л ь . К о м п и л и р о в а н ы е В Interface , И м я UsesФа йла ) ;
* Е с л и ( Т е к у ш и й М о д у л ь . С о с т о я н и е = = Compiled ) т о
* С п и с о к М о д у л е й . Д о б а в и т ь ( Т е к у ш и й М о д у л ь ) ;
* В ы х о д ;
*
* 6. Т е к у щ и й М о д у л ь . С е м а н т и ч е с к о е Д е р е в о = К о н в е р т о р Д е р е в а . К о н в е р т и р о в а т ь InterfaceЧа с ть (
* Т е к у щ и й М о д у л ь . С и н т а к с и ч е с к о е Д е р е в о ,
* Т е к у щ и й М о д у л ь . К о м п и л и р о в а н ы е В Interface ,
* Т е к у щ и й М о д у л ь . С п и с о к О ш и б о к ) ;
* С п и с о к М о д у л е й . Д о б а в и т ь ( Т е к у щ и й М о д у л ь ) ;
* С и н т а к с и ч е с к и й С п и с о к М о д у л е й = Т е к у щ и й М о д у л ь . С и н т а к с и ч е с к о е Д е р е в о . Implementation . UsesList ;
* Д л я ( i = С и н т а к с и ч е с к и й С п и с о к М о д у л е й . К о л и ч е с т в о - 1 ; i > = 0 ; i - - )
* Е с л и ( Т а б л и ц а М о д у л е й [ С и н т а к с и ч е с к и й С п и с о к М о д у л е й [ i ] . И м я Ф а й л а ] . С о с т о я н и е = BeginCompilation )
* С п и с о к О т л о ж е н о й К о м п и л я ц и и . Д о б а в и т ь ( Т а б л и ц а М о д у л е й [ С и н т а к с и ч е с к и й С п и с о к М о д у л е й [ i ] . И м я Ф а й л а ] ) ;
* и н а ч е
* CompileUnit ( Т е к у щ и й М о д у л ь . К о м п и л и р о в а н ы е В Implementation , С и н т а к с и ч е с к и й С п и с о к М о д у л е й [ i ] . И м я Ф а й л а ) ;
* Е с л и ( Д о б а в л я л и Х о т я б ы О д и н В С п и с о к О т л о ж е н о й К о м п и л я ц и и )
* С п и с о к О т л о ж е н о й К о м п и л я ц и и . Д о б а в и т ь ( Т е к у щ и й М о д у л ь ) ;
* в ы х о д ;
* и н а ч е
* К о н в е р т о р Д е р е в а . К о н в е р т и р о в а т ь ImplementationЧа с ть (
* Т е к у щ и й М о д у л ь . С и н т а к с и ч е с к о е Д е р е в о ,
* Т е к у щ и й М о д у л ь . С е м а н т и ч е с к о е Д е р е в о ,
* Т е к у щ и й М о д у л ь . К о м п и л и р о в а н ы е В Implementation
* Т е к у щ и й М о д у л ь . С п и с о к О ш и б о к ) ;
* Т е к у щ и й М о д у л ь . С о с т о я н и е = Compiled ;
* С о х р а н и т ь PCU ( Т е к у щ и й М о д у л ь ) ;
*
*
*
* [ к р а т к а я в е р cия а л г о р и т м а к о м п и л я ц и и м о д у л е й ]
* CompileUnit ( И м я Ф а й л а )
* 1. CompileUnit ( new С п и с о к М о д у л е й , И м я Ф а й л а )
* 2. Д о к о м п и л и р о в а т ь м о д у л и и з С п и с о к О т л о ж е н о й К о м п и л я ц и и ;
*
* CompileUnit ( С п и с о к М о д у л е й , И м я Ф а й л а ) ;
* 1. Е с л и у э т о г о м о д у л я о т к о м п и л и р о в а н х о т я б ы и н т е р ф е й с т о
* д о б а в и т ь е г о в С п и с о к М о д у л е й
* в ы х о д
* 2. Е с л и э т о DLL т о
* с ч и т а т ь
* д о б а в и т ь е г о в С п и с о к М о д у л е й
* в ы х о д
* 3. Е с л и э т о PCU т о
* с ч и т а т ь
* д о б а в и т ь е г о в С п и с о к М о д у л е й
* в ы х о д
* 4. с о з д а т ь н о в ы й к о м п и л и р у е м ы й М о д у л ь
* Р а с п а р с и т ь Т е к с т ( И м я Ф а й л а )
* С о с т о я н и е к о м п и л и р у е м о г о М о д у л я у с т а н о в и т ь н а BeginCompilation
* 5. Д л я в с е х м о д у л е й и з Interface ч а с т и к о м п и л и р у е м о г о М о д у л я с п р а в а н а л е в о
* Е с л и м ы у ж е н а ч а и н а л и к о м п и л и р о в а т ь э т о т м о д у л ь
* Е с л и с о с т о я н и е м о д у л я BeginCompilation
* Е с л и с о с т о я н и е п о с л е д н е г о к о м п и л и р у е м о г о и м м о д у л я BeginCompilation
* о ш и б к а ( "Циклическая связь модулей" )
* в ы х о д
* CompileUnit ( С п и с о к и з Interface ч а с т и к о м п и л и р у е м о г о М о д у л я , м о д у л ь . и м я )
* Е с л и к о м п и л и р у е м ы й М о д у л ь . С о с т о я н и е Compiled т о
* д о б а в и т ь е г о в С п и с о к М о д у л е й
* в ы х о д
* 6. О т к о м п и л и р о в а т ь Interface ч а с т ь к о м п и л и р у е м о г о М о д у л я
* Д л я в с е х м о д у л е й и з Implementation ч а с т и к о м п и л и р у е м о г о М о д у л я с п р а в а н а л е в о
* Е с л и с о с т о я н и е о ч е р е д н о г о м о д у л я BeginCompilation т о
* д о б а в и т ь е г о в с п и с о к о т л о ж е н о й к о м п и л я ц и и ;
* и н а ч е
* CompileUnit ( С п и с о к и з Implementation ч а с т и к о м п и л и р у е м о г о М о д у л я , м о д у л ь . и м я )
* Е с л и Д о б а в л я л и Х о т я б ы О д и н В С п и с о к О т л о ж е н о й К о м п и л я ц и и т о
* д о б а в и т ь к о м п и л и р у е м ы й М о д у л ь в с п и с о к о т л о ж е н о й к о м п и л я ц и и
* в ы х о д
* О т к о м п и л и р о в а т ь Implementation ч а с т ь к о м п и л и р у е м о г о М о д у л я
* С о с т о я н и е к о м п и л и р у е м о г о М о д у л я у с т а н о в и т ь н а Compiled
* д о б а в и т ь е г о в С п и с о к М о д у л е й
* С о х р а н и т ь к о м п и л и р у е м ы й М о д у л ь в в и д е PCU ф а й л а н а д и с к
*
*
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
#endregion
#define DEBUG
//#undef DEBUG
using System ;
using System.IO ;
using System.Collections ;
using System.Collections.Generic ;
using System.Xml ;
using PascalABCCompiler.Errors ;
using PascalABCCompiler.PCU ;
using PascalABCCompiler.SemanticTreeConverters ;
using ICSharpCode.NRefactory ;
using ICSharpCode.NRefactory.Parser.VB ;
using System.CodeDom.Compiler ;
//using IronPython.Hosting;
using Microsoft.Scripting.Hosting ;
using Microsoft.Scripting ;
using System.Reflection ;
//using SyntaxTreeChanger;
using PascalABCCompiler.SyntaxTreeConverters ;
2020-07-13 06:23:13 +03:00
using System.Text ;
2020-10-11 21:20:44 +03:00
using PascalABCCompiler.TreeRealization ;
2020-07-17 07:02:36 +03:00
using System.Linq ;
2020-07-09 05:54:55 +03:00
namespace PascalABCCompiler
{
public class CompilerCompilationError : LocatedError
{
public CompilerCompilationError ( string message )
: base ( message )
{
}
public CompilerCompilationError ( string message , string FileName )
: base ( message , FileName )
{
}
public override string ToString ( )
{
return Message ;
}
}
public class ReadPCUError : CompilerCompilationError
{
public ReadPCUError ( string FileName )
: base ( string . Format ( StringResources . Get ( "COMPILATIONERROR_READ_PCU{0}_ERROR" ) , FileName ) )
{
}
}
public class NamespaceCannotHaveInSection : CompilerCompilationError
{
public NamespaceCannotHaveInSection ( SyntaxTree . SourceContext sc )
: base ( string . Format ( StringResources . Get ( "COMPILATIONERROR_NAMESPACE_CANNOT_HAVE_IN_SECTION" ) ) )
{
this . source_context = sc ;
}
}
public class ProgramModuleExpected : CompilerCompilationError
{
public ProgramModuleExpected ( string FileName , SyntaxTree . SourceContext sc )
: base ( StringResources . Get ( "COMPILATIONERROR_PROGRAM_MODULE_EXPECTED" ) , FileName )
{
this . source_context = sc ;
}
}
public class UnitModuleExpected : CompilerCompilationError
{
public UnitModuleExpected ( string FileName , SyntaxTree . SourceContext sc )
: base ( StringResources . Get ( "COMPILATIONERROR_UNIT_MODULE_EXPECTED" ) , FileName )
{
this . source_context = sc ;
}
}
public class AppTypeDllIsAllowedOnlyForLibraries : CompilerCompilationError
{
public AppTypeDllIsAllowedOnlyForLibraries ( string FileName , SyntaxTree . SourceContext sc )
: base ( StringResources . Get ( "COMPILATIONERROR_APPTYPE_DLL_IS_ALLOWED_ONLY_FOR_LIBRARIES" ) , FileName )
{
this . source_context = sc ;
}
}
public class UnitModuleExpectedLibraryFound : CompilerCompilationError
{
public UnitModuleExpectedLibraryFound ( string FileName , SyntaxTree . SourceContext sc )
: base ( StringResources . Get ( "COMPILATIONERROR_UNIT_MODULE_EXPECTED_LIBRARY_FOUND" ) , FileName )
{
this . source_context = sc ;
}
}
public class AssemblyNotFound : CompilerCompilationError
{
public string AssemblyFileName ;
public AssemblyNotFound ( string FileName , string AssemblyFileName , SyntaxTree . SourceContext sc )
: base ( string . Format ( StringResources . Get ( "COMPILATIONERROR_ASSEMBLY_{0}_NOT_FOUND" ) , AssemblyFileName ) , FileName )
{
this . AssemblyFileName = AssemblyFileName ;
this . source_context = sc ;
}
}
public class AssemblyReadingError : CompilerCompilationError
{
public string AssemblyFileName ;
public AssemblyReadingError ( string FileName , string AssemblyFileName , SyntaxTree . SourceContext sc )
: base ( string . Format ( StringResources . Get ( "COMPILATIONERROR_ASSEMBLY_{0}_READING_ERROR" ) , AssemblyFileName ) , FileName )
{
this . AssemblyFileName = AssemblyFileName ;
this . source_context = sc ;
}
}
public class InvalidAssemblyPathError : CompilerCompilationError
{
public InvalidAssemblyPathError ( string FileName , SyntaxTree . SourceContext sc )
: base ( string . Format ( StringResources . Get ( "COMPILATIONERROR_INVALID_ASSEMBLY_PATH" ) ) , FileName )
{
this . source_context = sc ;
}
}
public class ResourceFileNotFound : CompilerCompilationError
{
public ResourceFileNotFound ( string ResFileName , TreeRealization . location sl )
: base ( string . Format ( StringResources . Get ( "COMPILATIONERROR_RESOURCEFILE_{0}_NOT_FOUND" ) , ResFileName ) , sl . doc . file_name )
{
this . sourceLocation = new SourceLocation ( sl . doc . file_name , sl . begin_line_num , sl . begin_column_num , sl . end_line_num , sl . end_column_num ) ;
}
public ResourceFileNotFound ( string ResFileName )
: base ( string . Format ( StringResources . Get ( "COMPILATIONERROR_RESOURCEFILE_{0}_NOT_FOUND" ) , ResFileName ) , null )
{
//this.sourceLocation = new SourceLocation(sl.doc.file_name, sl.begin_line_num, sl.begin_column_num, sl.end_line_num, sl.end_column_num);
}
}
public class IncludeNamespaceInUnit : CompilerCompilationError
{
public IncludeNamespaceInUnit ( string FileName , SyntaxTree . SourceContext sc )
: base ( string . Format ( StringResources . Get ( "COMPILATIONERROR_INCLUDE_NAMESPACE_IN_UNIT" ) ) , FileName )
{
this . source_context = sc ;
}
}
public class NamespaceModuleExpected : CompilerCompilationError
{
public NamespaceModuleExpected ( SyntaxTree . SourceContext sc )
: base ( string . Format ( StringResources . Get ( "COMPILATIONERROR_NAMESPACE_MODULE_EXPECTED" ) ) )
{
this . source_context = sc ;
}
}
public class MainResourceNotAllowed : CompilerCompilationError
{
public MainResourceNotAllowed ( TreeRealization . location sl )
: base ( string . Format ( StringResources . Get ( "COMPILATIONERROR_MAINRESOURCE_NOT_ALLOWED" ) ) , sl . doc . file_name )
{
this . sourceLocation = new SourceLocation ( sl . doc . file_name , sl . begin_line_num , sl . begin_column_num , sl . end_line_num , sl . end_column_num ) ;
}
}
public class DuplicateUsesUnit : CompilerCompilationError
{
public string UnitName ;
public DuplicateUsesUnit ( string FileName , string UnitName , SyntaxTree . SourceContext sc )
: base ( string . Format ( StringResources . Get ( "COMPILATIONERROR_DUPLICATE_USES_UNIT{0}" ) , UnitName ) , FileName )
{
this . UnitName = UnitName ;
this . source_context = sc ;
}
}
public class DuplicateDirective : CompilerCompilationError
{
public string DirectiveName ;
public DuplicateDirective ( string FileName , string DirectiveName , SyntaxTree . SourceContext sc )
: base ( string . Format ( StringResources . Get ( "COMPILATIONERROR_DUPLICATE_DIRECTIVE{0}" ) , DirectiveName ) , FileName )
{
this . DirectiveName = DirectiveName ;
this . source_context = sc ;
}
}
public class NamespacesCanBeCompiledOnlyInProjects : CompilerCompilationError
{
public NamespacesCanBeCompiledOnlyInProjects ( SyntaxTree . SourceContext sc )
: base ( StringResources . Get ( "COMPILATIONERROR_NAMESPACE_CAN_BE_COMPILED_ONLY_IN_PROJECTS" ) )
{
this . source_context = sc ;
}
}
public class UnitNotFound : CompilerCompilationError
{
public string UnitName ;
public UnitNotFound ( string FileName , string UnitName , SyntaxTree . SourceContext sc )
: base ( string . Format ( StringResources . Get ( "COMPILATIONERROR_UNIT_{0}_NOT_FOUND" ) , UnitName ) , FileName )
{
this . UnitName = UnitName ;
this . source_context = sc ;
}
}
public class UsesInWrongName : CompilerCompilationError
{
public string UnitName1 ;
public string UnitName2 ;
public UsesInWrongName ( string FileName , string UnitName1 , string UnitName2 , SyntaxTree . SourceContext sc )
: base ( string . Format ( StringResources . Get ( "COMPILATIONERROR_USES_IN_WRONG_NAME" ) , UnitName1 , UnitName2 ) , FileName )
{
this . UnitName1 = UnitName1 ;
this . UnitName2 = UnitName2 ;
this . source_context = sc ;
}
}
public class SourceFileNotFound : CompilerCompilationError
{
public SourceFileNotFound ( string FileName )
: base ( string . Format ( StringResources . Get ( "COMPILATIONERROR_SOURCE_FILE_{0}_NOT_FOUND" ) , FileName ) )
{
}
}
public class UnauthorizedAccessToFile : CompilerCompilationError
{
public UnauthorizedAccessToFile ( string FileName )
: base ( string . Format ( StringResources . Get ( "COMPILATIONERROR_NO_ACCESS_TO_FILE{0}" ) , FileName ) )
{
}
}
public class CycleUnitReference : CompilerCompilationError
{
public SyntaxTree . unit_or_namespace SyntaxUsesUnit ;
public CycleUnitReference ( string FileName , SyntaxTree . unit_or_namespace SyntaxUsesUnit )
: base ( string . Format ( StringResources . Get ( "COMPILATIONERROR_CYCLIC_UNIT_REFERENCE_WITH_UNIT_{0}" ) , SyntaxTree . Utils . IdentListToString ( SyntaxUsesUnit . name . idents , "." ) ) , FileName )
{
this . SyntaxUsesUnit = SyntaxUsesUnit ;
this . source_context = SyntaxUsesUnit . source_context ;
}
}
public enum UnitState { BeginCompilation , InterfaceCompiled , Compiled }
public class CompilationUnit
{
internal bool CaseSensitive = false ;
2021-01-06 00:47:18 +03:00
public string CurrentUsesUnitId ;
2020-07-09 05:54:55 +03:00
public PascalABCCompiler . Errors . SyntaxError syntax_error ;
2021-01-06 00:47:18 +03:00
public string UnitFileName ;
2020-07-09 05:54:55 +03:00
public List < Errors . Error > ErrorList = new List < Errors . Error > ( ) ;
public bool Documented ;
internal List < SyntaxTree . unit_or_namespace > PossibleNamespaces = new List < PascalABCCompiler . SyntaxTree . unit_or_namespace > ( ) ;
//internal List<CompilationUnit> AssemblyReferences = new List<CompilationUnit>();
2020-10-11 21:20:44 +03:00
//private SemanticTree.compilation_unitArrayList _interfaceUsedUnits=new SemanticTree.compilation_unitArrayList();
2020-07-09 05:54:55 +03:00
2020-10-11 21:20:44 +03:00
public Dictionary < unit_node , CompilationUnit > DirectInterfaceCompilationUnits { get ; } = new Dictionary < unit_node , CompilationUnit > ( ) ;
2020-07-13 06:23:13 +03:00
public PascalABCCompiler . TreeRealization . unit_node_list InterfaceUsedUnits { get ; } = new PascalABCCompiler . TreeRealization . unit_node_list ( ) ;
2020-07-09 05:54:55 +03:00
2020-10-11 21:20:44 +03:00
public Dictionary < unit_node , CompilationUnit > DirectImplementationCompilationUnits { get ; } = new Dictionary < unit_node , CompilationUnit > ( ) ;
2020-07-13 06:23:13 +03:00
public PascalABCCompiler . TreeRealization . unit_node_list ImplementationUsedUnits { get ; } = new PascalABCCompiler . TreeRealization . unit_node_list ( ) ;
2020-07-09 05:54:55 +03:00
2020-07-13 06:23:13 +03:00
private SyntaxTree . compilation_unit _syntaxTree = null ;
2020-07-09 05:54:55 +03:00
public SyntaxTree . compilation_unit SyntaxTree
{
get { return _syntaxTree ; }
set { _syntaxTree = value ; }
}
private PascalABCCompiler . TreeRealization . unit_node _semanticTree = null ;
public PascalABCCompiler . TreeRealization . unit_node SemanticTree
{
get { return _semanticTree ; }
set { _semanticTree = value ; }
}
private SyntaxTree . unit_or_namespace _syntaxUnitName = null ;
public SyntaxTree . unit_or_namespace SyntaxUnitName
{
get { return _syntaxUnitName ; }
set { _syntaxUnitName = value ; }
}
private TreeRealization . using_namespace_list _interface_using_namespace_list = new TreeRealization . using_namespace_list ( ) ;
public TreeRealization . using_namespace_list InterfaceUsingNamespaceList
{
get { return _interface_using_namespace_list ; }
set { _interface_using_namespace_list = value ; }
}
private TreeRealization . using_namespace_list _implementation_using_namespace_list = new TreeRealization . using_namespace_list ( ) ;
public TreeRealization . using_namespace_list ImplementationUsingNamespaceList
{
get { return _implementation_using_namespace_list ; }
set { _implementation_using_namespace_list = value ; }
}
public UnitState State = UnitState . BeginCompilation ;
}
public class CompilationUnitHashTable : Hashtable
{
public CompilationUnitHashTable ( )
//DarkStar: fixed error in test_standartuses.pas at rebuild
: base ( StringComparer . InvariantCultureIgnoreCase )
{
}
public CompilationUnit this [ string key ]
{
get
{
if ( key ! = null )
return ( base [ key ] as CompilationUnit ) ;
return null ;
}
set
{
base [ key ] = value ;
}
}
}
/// <summary>
/// Опции компиляции
/// </summary>
//[Serializable()]
public class CompilerOptions : MarshalByRefObject
{
public enum OutputType { ClassLibrary = 0 , ConsoleApplicaton = 1 , WindowsApplication = 2 , PascalCompiledUnit = 3 , SemanticTree = 4 }
public bool Debug = false ;
public bool ForDebugging = false ;
2021-09-06 21:37:31 +03:00
public bool ForIntellisense = false ;
2020-07-09 05:54:55 +03:00
public bool Rebuild = false ;
public bool Optimise = false ;
public bool SavePCUInThreadPull = false ;
public bool RunWithEnvironment = false ;
public string CompiledUnitExtension = ".pcu" ;
public bool ProjectCompiled = false ;
public IProjectInfo CurrentProject = null ;
public OutputType OutputFileType = OutputType . ConsoleApplicaton ;
public bool GenerateCode = true ;
public bool SaveDocumentation = true ;
public bool SavePCU = true ;
public bool IgnoreRtlErrors = true ;
public bool Only32Bit = false ;
public string Locale = "ru" ;
2021-09-06 21:37:31 +03:00
public SyntaxTree . compilation_unit UnitSyntaxTree = null ;
2020-07-09 05:54:55 +03:00
private string sourceFileName = null ;
///имя исходного файла
///при измененнии меняется OutputFileName,OutputDirectory,SourceFileDirectory
public string SourceFileName
{
get { return sourceFileName ; }
set
{
sourceFileName = value ;
OutputFileName = value ;
sourceFileDirectory = Path . GetDirectoryName ( value ) ;
if ( sourceFileDirectory = = "" ) sourceFileDirectory = Environment . CurrentDirectory ;
outputDirectory = SourceFileDirectory ;
useOutputDirectory = false ;
}
}
private string sourceFileDirectory = null ;
public string SourceFileDirectory
{
get { return sourceFileDirectory ; }
}
private string outputFileName = null ;
//имя выходного файла без расширения
//ели имя указано без пути то в качестве пути используетя OutputDirectory
public string OutputFileName
{
get
{
string FileName = outputFileName ;
switch ( OutputFileType )
{
case OutputType . ConsoleApplicaton :
case OutputType . WindowsApplication : FileName = FileName + ".exe" ; break ;
case OutputType . ClassLibrary : FileName = FileName + ".dll" ; break ;
case OutputType . PascalCompiledUnit : FileName = FileName + CompiledUnitExtension ; break ;
}
if ( Path . GetDirectoryName ( FileName ) = = "" ) FileName = Path . Combine ( OutputDirectory , FileName ) ;
return FileName ;
}
set
{
outputFileName = Path . GetFileNameWithoutExtension ( value ) ;
}
}
//
public string SystemDirectory ;
2021-11-17 17:10:37 +03:00
public List < string > ForceDefines = new List < string > ( ) ;
2020-07-17 07:02:36 +03:00
public List < string > SearchDirectory ;
2020-07-09 05:54:55 +03:00
private bool useDllForSystemUnits = false ;
public bool UseDllForSystemUnits
{
get
{
return useDllForSystemUnits ;
}
set
{
useDllForSystemUnits = value ;
PascalABCCompiler . NetHelper . NetHelper . UsePABCRtl = value ;
}
}
public string [ ] ParserSearchPatchs ;
public enum StandartModuleAddMethod { LeftToAll , RightToMain } ;
[Serializable()]
public class StandartModule : MarshalByRefObject
{
public string Name = null ;
public StandartModuleAddMethod AddMethod = StandartModuleAddMethod . LeftToAll ;
public SyntaxTree . LanguageId AddToLanguages = SyntaxTree . LanguageId . PascalABCNET ;
public StandartModule ( string Name , StandartModuleAddMethod AddMethod )
{
this . Name = Name ;
this . AddMethod = AddMethod ;
}
public StandartModule ( string Name , StandartModuleAddMethod AddMethod , SyntaxTree . LanguageId AddToLanguages )
{
this . Name = Name ;
this . AddToLanguages = AddToLanguages ;
this . AddMethod = AddMethod ;
}
public StandartModule ( string Name )
{
this . Name = Name ;
}
public StandartModule ( string Name , SyntaxTree . LanguageId AddToLanguages )
{
this . AddToLanguages = AddToLanguages ;
this . Name = Name ;
}
}
/// <summary>
/// Module at index 0 is System module
/// </summary>
public List < StandartModule > StandartModules ;
public void RemoveStandartModule ( string Name )
{
StandartModule module_to_del = null ;
foreach ( StandartModule module in StandartModules )
if ( module . Name = = Name )
{
module_to_del = module ;
break ;
}
if ( module_to_del ! = null )
StandartModules . Remove ( module_to_del ) ;
}
public void RemoveStandartModuleAtIndex ( int index )
{
if ( index < StandartModules . Count )
StandartModules . RemoveAt ( index ) ;
}
internal string outputDirectory = null ;
internal bool useOutputDirectory = false ;
//для поиска pcu во вторую очередь
//для сохранения сюда .exe, .dll и .pdb файлов
public string OutputDirectory
{
get
{
return outputDirectory ;
}
set
{
outputDirectory = value ;
useOutputDirectory = outputDirectory ! = null ;
}
}
//для поиска pcu в третью очередь исп. путь к pas файлу
public Hashtable StandartDirectories ;
private void SetStandartModules ( )
{
StandartModules = new List < StandartModule > ( ) ;
StandartModules . Add ( new StandartModule ( "PABCSystem" , SyntaxTree . LanguageId . PascalABCNET | SyntaxTree . LanguageId . C ) ) ;
StandartModules . Add ( new StandartModule ( "PABCExtensions" , SyntaxTree . LanguageId . PascalABCNET | SyntaxTree . LanguageId . C ) ) ;
}
private void SetDirectories ( )
{
2020-07-17 07:02:36 +03:00
SystemDirectory = Path . GetDirectoryName ( Assembly . GetExecutingAssembly ( ) . ManifestModule . FullyQualifiedName ) ;
2020-07-09 05:54:55 +03:00
StandartDirectories = new Hashtable ( StringComparer . InvariantCultureIgnoreCase ) ;
StandartDirectories . Add ( "%PABCSYSTEM%" , SystemDirectory ) ;
2020-07-17 07:02:36 +03:00
ParserSearchPatchs = new string [ ] { Path . Combine ( SystemDirectory , "Lib" ) } ;
SearchDirectory = ParserSearchPatchs . ToList ( ) ;
2020-07-09 05:54:55 +03:00
}
public CompilerOptions ( )
{
SetDirectories ( ) ;
SetStandartModules ( ) ;
}
public CompilerOptions ( string SourceFileName , OutputType OutputFileType )
{
SetDirectories ( ) ;
SetStandartModules ( ) ;
this . SourceFileName = SourceFileName ;
this . OutputFileType = OutputFileType ;
}
}
public enum CompilerState
{
Ready , CompilationStarting , Reloading , ParserConnected ,
BeginCompileFile , BeginParsingFile , EndParsingFile , CompileInterface , CompileImplementation , EndCompileFile ,
ReadDLL , ReadPCUFile , SavePCUFile , CodeGeneration , CompilationFinished , PCUReadingError , PCUWritingError ,
SemanticTreeConverterConnected , SemanticTreeConversion , SyntaxTreeConversion , SyntaxTreeConverterConnected
}
[Serializable()]
public class CompilerInternalDebug
{
public bool CodeGeneration = true ;
public bool SemanticAnalysis = true ;
public bool PCUGenerate = true ;
public bool AddStandartUnits = true ;
public bool SkipPCUErrors = true ;
public bool IncludeDebugInfoInPCU = true ;
public bool AlwaysGenerateXMLDoc = false ;
public bool SkipInternalErrorsIfSyntaxTreeIsCorrupt = true ;
public bool UseStandarParserForIntellisense = true ;
public bool RunOnMono = false ;
public List < string > DocumentedUnits = new List < string > ( ) ;
#if DEBUG
public bool DebugVersion
{
get { return true ; }
}
#elif ! DEBUG
public bool DebugVersion
{
get { return false ; }
}
#endif
}
public class SupportedSourceFile
{
private string [ ] extensions ;
public string [ ] Extensions
{
get { return extensions ; }
}
private string languageName ;
public string LanguageName
{
get { return languageName ; }
}
public SupportedSourceFile ( string [ ] extensions , string lname )
{
this . extensions = extensions ; languageName = lname ;
}
public static SupportedSourceFile Make ( Parsers . IParser parser )
{
List < string > ext = new List < string > ( ) ;
foreach ( string ex in parser . FilesExtensions )
if ( ex [ ex . Length - 1 ] ! = Parsers . Controller . HideParserExtensionPostfixChar )
ext . Add ( ex ) ;
if ( ext . Count > 0 )
return new SupportedSourceFile ( ext . ToArray ( ) , parser . Name ) ;
return null ;
}
public override string ToString ( )
{
return string . Format ( "{0} ({1})" , LanguageName , FormatTools . ExtensionsToString ( Extensions , "*" , ";" ) ) ;
}
}
public delegate void ChangeCompilerStateEventDelegate ( ICompiler sender , CompilerState State , string FileName ) ;
public class Compiler : MarshalByRefObject , ICompiler
{
//public ISyntaxTreeChanger SyntaxTreeChanger = null; // SSM 17/08/15 - для операций над синтаксическим деревом после е г о построения
2020-09-19 23:45:19 +03:00
int pABCCodeHealth = 0 ;
public int PABCCodeHealth { get { return pABCCodeHealth ; } }
2020-07-09 05:54:55 +03:00
public static string Version
{
get
{
return RevisionClass . FullVersion ;
}
}
public static string ShortVersion
{
get
{
if ( RevisionClass . Build = = "0" )
return RevisionClass . MainVersion ;
else return RevisionClass . MainVersion + "." + RevisionClass . Build ;
}
}
public static DateTime VersionDateTime
{
get
{
return File . GetLastWriteTime ( System . Reflection . Assembly . GetExecutingAssembly ( ) . ManifestModule . FullyQualifiedName ) ;
}
}
public static string Banner
{
get
{
return "PascalABCCompiler.Core v" + Version ;
}
}
public override string ToString ( )
{
return Banner ;
}
private SyntaxTreeConvertersController syntaxTreeConvertersController = null ;
public SyntaxTreeConvertersController SyntaxTreeConvertersController
{
get
{
return syntaxTreeConvertersController ;
}
}
private SemanticTreeConvertersController semanticTreeConvertersController = null ;
public SemanticTreeConvertersController SemanticTreeConvertersController
{
get
{
return semanticTreeConvertersController ;
}
}
private Hashtable BadNodesInSyntaxTree = new Hashtable ( ) ;
TreeRealization . program_node _semantic_tree = null ;
public SemanticTree . IProgramNode SemanticTree
{
get
{
return _semantic_tree ;
}
}
2021-09-06 21:37:31 +03:00
public program_node semantic_tree
{
get
{
return _semantic_tree ;
}
}
public List < var_definition_node > CompiledVariables = new List < var_definition_node > ( ) ;
2020-07-09 05:54:55 +03:00
private Dictionary < string , List < TreeRealization . compiler_directive > > compilerDirectives = null ;
//public Hashtable CompilerDirectives
//{
// get { return compilerDirectives; }
//}
private uint linesCompiled ;
public uint LinesCompiled
{
get { return linesCompiled ; }
}
private CompilerInternalDebug internalDebug ;
public CompilerInternalDebug InternalDebug
{
get
{
return internalDebug ;
}
set
{
internalDebug = value ;
}
}
private CompilerState state = CompilerState . Ready ;
public CompilerState State
{
get { return state ; }
}
private void SetSupportedSourceFiles ( )
{
List < SupportedSourceFile > supportedSourceFilesList = new List < SupportedSourceFile > ( ) ;
for ( int i = 0 ; i < ParsersController . Parsers . Count ; i + + )
{
SupportedSourceFile sf = SupportedSourceFile . Make ( ParsersController . Parsers [ i ] ) ;
if ( sf ! = null )
supportedSourceFilesList . Add ( sf ) ;
}
supportedSourceFiles = supportedSourceFilesList . ToArray ( ) ;
}
private void SetSupportedProjectFiles ( )
{
List < SupportedSourceFile > supportedProjectFilesList = new List < SupportedSourceFile > ( ) ;
/ * for ( int i = 0 ; i < ParsersController . Parsers . Count ; i + + )
{
SupportedSourceFile sf = SupportedSourceFile . Make ( ParsersController . Parsers [ i ] ) ;
if ( sf ! = null )
supportedSourceFilesList . Add ( sf ) ;
} * /
//vremenno
supportedProjectFilesList . Add ( new SupportedSourceFile ( new string [ 1 ] { ".pabcproj" } , "PascalABC.NET" ) ) ;
supportedProjectFiles = supportedProjectFilesList . ToArray ( ) ;
}
2020-10-11 21:20:44 +03:00
2020-07-09 05:54:55 +03:00
private SupportedSourceFile [ ] supportedSourceFiles = null ;
public SupportedSourceFile [ ] SupportedSourceFiles
{
get { return supportedSourceFiles ; }
set { supportedSourceFiles = value ; }
}
private SupportedSourceFile [ ] supportedProjectFiles = null ;
public SupportedSourceFile [ ] SupportedProjectFiles
{
get { return supportedProjectFiles ; }
}
private CompilationUnitHashTable unitTable = new CompilationUnitHashTable ( ) ;
public CompilationUnitHashTable UnitTable { get { return unitTable ; } }
public List < CompilationUnit > UnitsSortedList = new List < CompilationUnit > ( ) ;
private List < string > StandarModules = new List < string > ( ) ;
private CompilerOptions compilerOptions = new CompilerOptions ( ) ;
public CompilerOptions CompilerOptions
{
get
{
return compilerOptions ;
}
set
{
compilerOptions = value ;
}
}
2021-11-15 22:07:20 +03:00
internal Dictionary < string , CompilationUnit > DLLCache = new Dictionary < string , CompilationUnit > ( ) ;
2020-07-09 05:54:55 +03:00
private Parsers . Controller parsersController = null ;
public Parsers . Controller ParsersController
{
get
{
return parsersController ;
}
set
{
parsersController = value ;
}
}
public TreeConverter . SyntaxTreeToSemanticTreeConverter SyntaxTreeToSemanticTreeConverter = null ;
public CodeGenerators . Controller CodeGeneratorsController = null ;
//public LLVMConverter.Controller LLVMCodeGeneratorsController = null;
//public PascalToCppConverter.Controller PABCToCppCodeGeneratorsController = null;
2020-09-14 21:14:08 +03:00
public SyntaxTree . unit_or_namespace CurrentSyntaxUnit ;
2020-07-09 05:54:55 +03:00
private List < CompilationUnit > UnitsToCompile = new List < CompilationUnit > ( ) ;
public Hashtable RecompileList = new Hashtable ( StringComparer . OrdinalIgnoreCase ) ;
private Hashtable CycleUnits = new Hashtable ( ) ;
2020-09-14 21:14:08 +03:00
public CompilationUnit CurrentCompilationUnit = null ;
2020-07-09 05:54:55 +03:00
private CompilationUnit FirstCompilationUnit = null ;
private bool PCUReadersAndWritersClosed ;
public int beginOffset ;
public int varBeginOffset ;
private bool _clear_after_compilation = true ;
2021-11-15 22:07:20 +03:00
private static Dictionary < string , CompilationUnit > pcuCompilationUnits = new Dictionary < string , CompilationUnit > ( ) ;
2020-07-09 05:54:55 +03:00
public bool ClearAfterCompilation
{
get
{
return _clear_after_compilation ;
}
set
{
_clear_after_compilation = value ;
}
}
public int BeginOffset
{
get
{
return beginOffset ;
}
}
public int VarBeginOffset
{
get
{
return varBeginOffset ;
}
}
private List < CompilerWarning > warnings = new List < CompilerWarning > ( ) ;
public List < CompilerWarning > Warnings
{
get
{
return warnings ;
}
}
2020-07-17 01:58:34 +03:00
public Dictionary < Tuple < string , string > , Tuple < string , int > > SourceFileNamesDictionary { get ; } = new Dictionary < Tuple < string , string > , Tuple < string , int > > ( ) ;
2020-07-09 05:54:55 +03:00
2020-07-17 01:58:34 +03:00
public Dictionary < Tuple < string , string > , Tuple < string , int > > PCUFileNamesDictionary { get ; } = new Dictionary < Tuple < string , string > , Tuple < string , int > > ( ) ;
public Dictionary < Tuple < string , string > , string > GetUnitFileNameCache { get ; } = new Dictionary < Tuple < string , string > , string > ( ) ;
2020-07-09 05:54:55 +03:00
public void AddWarnings ( List < CompilerWarning > WarningList )
{
foreach ( CompilerWarning cw in WarningList )
warnings . Add ( cw ) ;
}
public event ChangeCompilerStateEventDelegate OnChangeCompilerState ;
private void ChangeCompilerStateEvent ( ICompiler sender , CompilerState State , string FileName )
{
this . state = State ;
}
private bool SourceFileExists ( string FileName )
{
if ( FileName = = null ) return false ;
return ( bool ) SourceFilesProvider ( FileName , SourceFileOperation . Exists ) ;
}
private DateTime SourceFileGetLastWriteTime ( string FileName )
{
return ( DateTime ) SourceFilesProvider ( FileName , SourceFileOperation . GetLastWriteTime ) ;
}
private SourceFilesProviderDelegate sourceFilesProvider = SourceFilesProviders . DefaultSourceFilesProvider ;
public SourceFilesProviderDelegate SourceFilesProvider
{
get
{
return sourceFilesProvider ;
}
}
private List < Errors . Error > errorsList = new List < Errors . Error > ( ) ;
public List < Errors . Error > ErrorsList
{
get { return errorsList ; }
}
public Compiler ( )
{
//SyntaxTreeChanger = new SyntaxTreeChanger.SyntaxTreeChange();
OnChangeCompilerState + = ChangeCompilerStateEvent ;
Reload ( ) ;
}
public Compiler ( ICompiler comp , SourceFilesProviderDelegate SourceFilesProvider , ChangeCompilerStateEventDelegate ChangeCompilerState )
{
//SyntaxTreeChanger = new SyntaxTreeChanger.SyntaxTreeChange(); // SSM 01/05/16 - подключение изменяльщика синтаксического дерева
this . ParsersController = comp . ParsersController ;
this . internalDebug = comp . InternalDebug ;
OnChangeCompilerState + = ChangeCompilerStateEvent ;
if ( SourceFilesProvider ! = null )
this . sourceFilesProvider = SourceFilesProvider ;
if ( ChangeCompilerState ! = null )
OnChangeCompilerState + = ChangeCompilerState ;
this . supportedSourceFiles = comp . SupportedSourceFiles ;
this . supportedProjectFiles = comp . SupportedProjectFiles ;
}
public Compiler ( SourceFilesProviderDelegate SourceFilesProvider , ChangeCompilerStateEventDelegate ChangeCompilerState )
{
//SyntaxTreeChanger = new SyntaxTreeChanger.SyntaxTreeChange(); // SSM 01/05/16 - подключение изменяльщика синтаксического дерева
OnChangeCompilerState + = ChangeCompilerStateEvent ;
if ( SourceFilesProvider ! = null )
this . sourceFilesProvider = SourceFilesProvider ;
if ( ChangeCompilerState ! = null )
OnChangeCompilerState + = ChangeCompilerState ;
Reload ( ) ;
}
public void Reload ( )
{
OnChangeCompilerState ( this , CompilerState . Reloading , null ) ;
2020-09-19 23:45:19 +03:00
pABCCodeHealth = 0 ;
2020-07-09 05:54:55 +03:00
//А это что?
TreeRealization . type_node tn = SystemLibrary . SystemLibrary . void_type ;
ClearAll ( ) ;
errorsList . Clear ( ) ;
Warnings . Clear ( ) ;
InternalDebug = new CompilerInternalDebug ( ) ;
ParsersController = new Parsers . Controller ( ) ;
ParsersController . ParserConnected + = new PascalABCCompiler . Parsers . Controller . ParserConnectedDeleagte ( ParsersController_ParserConnected ) ;
ParsersController . SourceFilesProvider = sourceFilesProvider ;
ParsersController . Reload ( ) ;
SyntaxTreeToSemanticTreeConverter = new TreeConverter . SyntaxTreeToSemanticTreeConverter ( ) ;
CodeGeneratorsController = new CodeGenerators . Controller ( ) ;
//PABCToCppCodeGeneratorsController = new PascalToCppConverter.Controller();
SetSupportedSourceFiles ( ) ;
SetSupportedProjectFiles ( ) ;
syntaxTreeConvertersController = new SyntaxTreeConvertersController ( this ) ;
syntaxTreeConvertersController . ChangeState + = syntaxTreeConvertersController_ChangeState ;
syntaxTreeConvertersController . AddConverters ( ) ;
semanticTreeConvertersController = new SemanticTreeConvertersController ( this ) ;
semanticTreeConvertersController . ChangeState + = semanticTreeConvertersController_ChangeState ;
semanticTreeConvertersController . AddConverters ( ) ;
OnChangeCompilerState ( this , CompilerState . Ready , null ) ;
}
void ParsersController_ParserConnected ( PascalABCCompiler . Parsers . IParser Parser )
{
if ( OnChangeCompilerState ! = null )
OnChangeCompilerState ( this , CompilerState . ParserConnected , Parser . GetType ( ) . Assembly . ManifestModule . FullyQualifiedName ) ;
}
void syntaxTreeConvertersController_ChangeState ( SyntaxTreeConvertersController . State State , ISyntaxTreeConverter SyntaxTreeConverter )
{
switch ( State )
{
case SyntaxTreeConvertersController . State . Convert :
OnChangeCompilerState ( this , CompilerState . SyntaxTreeConversion , SyntaxTreeConverter . Name ) ;
break ;
case SyntaxTreeConvertersController . State . ConnectConverter :
OnChangeCompilerState ( this , CompilerState . SyntaxTreeConverterConnected , SyntaxTreeConverter . Name ) ;
break ;
}
}
void semanticTreeConvertersController_ChangeState ( SemanticTreeConvertersController . State State , ISemanticTreeConverter SemanticTreeConverter )
{
switch ( State )
{
case SemanticTreeConvertersController . State . Convert :
OnChangeCompilerState ( this , CompilerState . SemanticTreeConversion , SemanticTreeConverter . Name ) ;
break ;
case SemanticTreeConvertersController . State . ConnectConverter :
OnChangeCompilerState ( this , CompilerState . SemanticTreeConverterConnected , SemanticTreeConverter . Name ) ;
break ;
}
}
private Dictionary < string , List < TreeRealization . compiler_directive > > GetCompilerDirectives ( List < CompilationUnit > Units )
{
Dictionary < string , List < TreeRealization . compiler_directive > > Directives = new Dictionary < string , List < TreeRealization . compiler_directive > > ( StringComparer . CurrentCultureIgnoreCase ) ;
for ( int i = 0 ; i < Units . Count ; i + + )
{
TreeRealization . common_unit_node cun = Units [ i ] . SemanticTree as TreeRealization . common_unit_node ;
if ( cun ! = null )
foreach ( TreeRealization . compiler_directive cd in cun . compiler_directives )
{
if ( ! Directives . ContainsKey ( cd . name ) )
Directives . Add ( cd . name , new List < TreeRealization . compiler_directive > ( ) ) ;
else if ( string . Compare ( cd . name , "mainresource" , true ) = = 0 )
throw new DuplicateDirective ( cd . location . doc . file_name , "mainresource" , cd . location ) ;
Directives [ cd . name ] . Insert ( 0 , cd ) ;
}
}
return Directives ;
}
private Hashtable GetCompilerDirectives ( CompilationUnit Unit )
{
Hashtable Directives = new Hashtable ( StringComparer . CurrentCultureIgnoreCase ) ;
TreeRealization . common_unit_node cun = Unit . SemanticTree as TreeRealization . common_unit_node ;
if ( cun ! = null )
foreach ( TreeRealization . compiler_directive cd in cun . compiler_directives )
Directives [ cd . name ] = cd ;
return Directives ;
}
private TreeRealization . location get_location_from_treenode ( SyntaxTree . syntax_tree_node tn , string FileName )
{
if ( tn . source_context = = null )
{
return null ;
}
return new TreeRealization . location ( tn . source_context . begin_position . line_num , tn . source_context . begin_position . column_num ,
tn . source_context . end_position . line_num , tn . source_context . end_position . column_num , new TreeRealization . document ( FileName ) ) ;
}
private System . Collections . Generic . List < TreeRealization . compiler_directive > ConvertDirectives ( SyntaxTree . compilation_unit cu )
{
System . Collections . Generic . List < TreeRealization . compiler_directive > list = new System . Collections . Generic . List < TreeRealization . compiler_directive > ( ) ;
foreach ( SyntaxTree . compiler_directive sncd in cu . compiler_directives )
{
list . Add ( new TreeRealization . compiler_directive ( sncd . Name . text , sncd . Directive ! = null ? sncd . Directive . text : "" , get_location_from_treenode ( sncd , cu . file_name ) , cu . file_name ) ) ;
}
return list ;
}
void syncStartCompile ( )
{
Compile ( ) ;
}
public void StartCompile ( )
{
System . Threading . Thread th = new System . Threading . Thread ( syncStartCompile ) ;
th . SetApartmentState ( System . Threading . ApartmentState . STA ) ;
th . Start ( ) ;
}
public string Compile ( CompilerOptions CompilerOptions )
{
this . CompilerOptions = CompilerOptions ;
return Compile ( ) ;
}
internal void Reset ( )
{
SourceFileNamesDictionary . Clear ( ) ;
PCUFileNamesDictionary . Clear ( ) ;
2020-07-17 04:13:17 +03:00
GetUnitFileNameCache . Clear ( ) ;
Warnings . Clear ( ) ;
2020-07-09 05:54:55 +03:00
errorsList . Clear ( ) ;
//if (!File.Exists(CompilerOptions.SourceFileName)) throw new SourceFileNotFound(CompilerOptions.SourceFileName);
CurrentCompilationUnit = null ;
FirstCompilationUnit = null ;
linesCompiled = 0 ;
2020-09-19 23:45:19 +03:00
pABCCodeHealth = 0 ;
2020-07-09 05:54:55 +03:00
PCUReadersAndWritersClosed = false ;
ParsersController . Reset ( ) ;
SyntaxTreeToSemanticTreeConverter . Reset ( ) ;
CodeGeneratorsController . Reset ( ) ;
//PABCToCppCodeGeneratorsController.Reset();
UnitsToCompile . Clear ( ) ;
2021-11-15 22:07:20 +03:00
DLLCache . Clear ( ) ;
2020-07-09 05:54:55 +03:00
project = null ;
}
void CheckErrors ( )
{
2021-11-15 22:07:20 +03:00
if ( compilerOptions . ForIntellisense )
return ;
2020-07-09 05:54:55 +03:00
if ( ErrorsList . Count > 0 )
throw ErrorsList [ 0 ] ;
}
private void moveSystemUnitToForwardUnitSortedList ( )
{
if ( CompilerOptions . StandartModules . Count = = 0 )
return ;
CompilationUnit system_unit = null ;
foreach ( CompilationUnit cu in UnitsSortedList )
if ( cu . SemanticTree ! = null & & cu . SemanticTree is PascalABCCompiler . TreeRealization . common_unit_node )
if ( ( cu . SemanticTree as PascalABCCompiler . TreeRealization . common_unit_node ) . unit_name = = CompilerOptions . StandartModules [ 0 ] . Name )
{
system_unit = cu ;
break ;
}
if ( system_unit ! = null & & system_unit ! = UnitsSortedList [ 0 ] )
{
UnitsSortedList . Remove ( system_unit ) ;
UnitsSortedList . Insert ( 0 , system_unit ) ;
}
}
private uint get_compiled_lines ( string FileName )
{
StreamReader sr = File . OpenText ( FileName ) ;
uint line = 0 ;
while ( ! sr . EndOfStream )
{
sr . ReadLine ( ) ;
line + + ;
}
sr . Close ( ) ;
return line ;
}
class ProgInfo
{
public string entry_module ;
public int entry_method_name_pos ;
public int entry_method_line ;
public int using_pos = - 1 ;
public List < string > modules = new List < string > ( ) ;
public List < string > addit_imports = new List < string > ( ) ;
public List < string > addit_project_files = new List < string > ( ) ;
}
private void add_import_info ( ProgInfo info , List < string > imports )
{
Hashtable ht = new Hashtable ( StringComparer . CurrentCultureIgnoreCase ) ;
ht [ "GraphABC" ] = "GraphABC" ;
ht [ "GraphABCHelper" ] = "GraphABCHelper" ;
ht [ "ABCObjects" ] = "ABCObjects" ;
ht [ "Robot" ] = "Robot" ;
ht [ "Drawman" ] = "Drawman" ;
ht [ "DrawManField" ] = "DrawManField" ;
foreach ( string s in imports )
{
string low_s = s . ToLower ( ) ;
//string mod_file = FindSourceFileInDirectories(s+".mod",Path.Combine(this.CompilerOptions.SystemDirectory,"lib"));
if ( ht [ s ] ! = null )
{
string name = ht [ s ] as string ;
if ( ! info . modules . Contains ( name ) )
{
info . modules . Add ( name ) ;
info . addit_imports . Add ( name + "." + name ) ;
}
}
/ * if ( ! string . IsNullOrEmpty ( mod_file ) )
{
switch ( low_s )
{
case "graphabc" :
if ( ! info . modules . Contains ( "GraphABC" ) & & ! info . modules . Contains ( "ABCObjects" ) & & ! info . modules . Contains ( "ABCButtons" ) & & ! info . modules . Contains ( "ABCHouse" )
& & ! info . modules . Contains ( "ABCSprites" ) & & ! info . modules . Contains ( "RobotField" ) )
{
info . modules . Add ( "GraphABC" ) ;
info . addit_imports . Add ( "GraphABC.GraphABC" ) ;
}
else if ( ! info . addit_imports . Contains ( "GraphABC.GraphABC" ) )
{
info . addit_imports . Add ( "GraphABC.GraphABC" ) ;
}
break ;
case "abcobjects" :
if ( ! info . modules . Contains ( "ABCObjects" ) & & ! info . modules . Contains ( "ABCButtons" ) & & ! info . modules . Contains ( "ABCHouse" )
& & ! info . modules . Contains ( "ABCSprites" ) & & ! info . modules . Contains ( "RobotField" ) )
{
info . modules . Add ( "ABCObjects" ) ;
info . addit_imports . Add ( "ABCObjects.ABCObjects" ) ;
if ( info . modules . Contains ( "GraphABC" ) )
{
info . modules . Remove ( "GraphABC" ) ;
//info.addit_imports.Remove("GraphABC.GraphABC");
}
}
break ;
default :
if ( ! info . modules . Contains ( s ) )
{
info . modules . Add ( s ) ;
info . addit_imports . Add ( s + "." + s ) ;
}
break ;
}
} * /
else
{
string source_file = FindFileInDirs ( s + ".vb" , Path . GetDirectoryName ( CompilerOptions . SourceFileName ) , Path . Combine ( this . CompilerOptions . SystemDirectory , "lib" ) ,
Path . Combine ( this . CompilerOptions . SystemDirectory , "LibSource" ) ) ;
if ( ! string . IsNullOrEmpty ( source_file ) )
{
if ( ! info . addit_project_files . Contains ( source_file ) )
{
info . addit_project_files . Add ( source_file ) ;
}
}
}
}
/ * List < string > mods = new List < string > ( ) ;
List < int > inds = new List < int > ( ) ;
for ( int i = 0 ; i < info . modules . Count ; i + + )
{
switch ( info . modules [ i ] )
{
case "GraphABCHelper" : inds . Add ( 0 ) ; break ;
case "GraphABC" : inds . Add ( 1 ) ; break ;
case "ABCObjects" : inds . Add ( 2 ) ; break ;
case "ABCHouse" : inds . Add ( 3 ) ; break ;
case "ABCSprites" : inds . Add ( 3 ) ; break ;
case "ABCButtons" : inds . Add ( 3 ) ; break ;
case "DMCollect" : inds . Add ( 0 ) ; break ;
case "DrawManField" : inds . Add ( 2 ) ; break ;
case "DMZadan" : inds . Add ( 4 ) ; break ;
case "DMTaskMaker" : inds . Add ( 3 ) ; break ;
case "RobotField" : inds . Add ( 2 ) ; break ;
case "RobotTaskMaker" : inds . Add ( 3 ) ; break ;
case "RobotZadan" : inds . Add ( 4 ) ; break ;
case "Robot" : inds . Add ( 5 ) ; break ;
}
} * /
}
private int find_pos ( string s , int line , int col , bool search_main )
{
int ind_ln = 1 ;
int ind_col = 1 ;
int pos = 0 ;
for ( int i = 0 ; i < s . Length ; i + + )
{
if ( ind_col = = col & & ind_ln = = line )
{
if ( search_main )
{
pos + = 3 ;
while ( s [ pos ] ! = 'M' & & s [ pos ] ! = 'm' )
pos + + ;
}
return pos ;
}
if ( s [ i ] = = '\n' )
{
ind_col = 1 ;
ind_ln + + ;
}
else
{
ind_col + + ;
}
pos + + ;
}
return - 1 ;
}
private ProgInfo get_programm_info ( ICSharpCode . NRefactory . Ast . CompilationUnit cu , string source )
{
ProgInfo info = new ProgInfo ( ) ;
List < string > usings = new List < string > ( ) ;
foreach ( ICSharpCode . NRefactory . Ast . INode node in cu . Children )
{
if ( node is ICSharpCode . NRefactory . Ast . TypeDeclaration )
{
ICSharpCode . NRefactory . Ast . TypeDeclaration td = node as ICSharpCode . NRefactory . Ast . TypeDeclaration ;
if ( td . Type = = ICSharpCode . NRefactory . Ast . ClassType . Module )
{
foreach ( ICSharpCode . NRefactory . Ast . INode node2 in td . Children )
{
if ( node2 is ICSharpCode . NRefactory . Ast . MethodDeclaration )
{
ICSharpCode . NRefactory . Ast . MethodDeclaration meth = node2 as ICSharpCode . NRefactory . Ast . MethodDeclaration ;
if ( string . Compare ( meth . Name , "Main" , true ) = = 0 & & ( meth . Parameters = = null | | meth . Parameters . Count = = 0 ) )
{
//info = new ProgInfo();
info . entry_module = ( meth . Parent as ICSharpCode . NRefactory . Ast . TypeDeclaration ) . Name ;
//info.entry_method_name_line = meth.StartLocation.Line;
//info.entry_method_name_col = meth.StartLocation.Column;
info . entry_method_name_pos = find_pos ( source , meth . StartLocation . Line , meth . StartLocation . Column , true ) ;
if ( meth . Body . Children . Count > 0 )
{
for ( int i = 0 ; i < meth . Body . Children . Count ; i + + )
{
if ( ! ( meth . Body . Children [ i ] is ICSharpCode . NRefactory . Ast . LocalVariableDeclaration ) )
{
info . entry_method_line = meth . Body . Children [ i ] . StartLocation . Line ;
break ;
}
}
}
else
info . entry_method_line = meth . Body . EndLocation . Line ;
}
}
}
}
}
else if ( node is ICSharpCode . NRefactory . Ast . UsingDeclaration )
{
ICSharpCode . NRefactory . Ast . UsingDeclaration using_node = node as ICSharpCode . NRefactory . Ast . UsingDeclaration ;
foreach ( ICSharpCode . NRefactory . Ast . Using us in using_node . Usings )
if ( ! string . IsNullOrEmpty ( us . Name ) )
usings . Add ( us . Name ) ;
if ( info . using_pos = = - 1 )
info . using_pos = find_pos ( source , using_node . EndLocation . Line , using_node . EndLocation . Column , false ) ;
}
}
if ( info . entry_module ! = null )
{
add_import_info ( info , usings ) ;
return info ;
}
return null ;
}
public string CompileWithProvider ( string [ ] sources , System . CodeDom . Compiler . CodeDomProvider cp , params string [ ] RefAssemblies )
{
OnChangeCompilerState ( this , CompilerState . CompilationStarting , CompilerOptions . SourceFileName ) ;
OnChangeCompilerState ( this , CompilerState . BeginCompileFile , CompilerOptions . SourceFileName ) ;
Reset ( ) ;
//var cscp = new Microsoft.CSharp.CSharpCodeProvider();
var comp_opt = new CompilerParameters ( ) ;
comp_opt . IncludeDebugInformation = CompilerOptions . Debug ;
comp_opt . GenerateExecutable = true ;
comp_opt . WarningLevel = 3 ;
comp_opt . CompilerOptions = "/platform:x86 " ;
comp_opt . OutputAssembly = CompilerOptions . OutputFileName ;
if ( RefAssemblies ! = null )
comp_opt . ReferencedAssemblies . AddRange ( RefAssemblies ) ;
//string source = GetSourceFileText(CompilerOptions.SourceFileName);
var res = cp . CompileAssemblyFromSource ( comp_opt , sources ) ;
if ( res . Errors . Count > 0 )
{
for ( int i = 0 ; i < res . Errors . Count ; i + + )
{
if ( ! res . Errors [ i ] . IsWarning & & errorsList . Count = = 0 /*&& res.Errors[i].FileName != redirect_fname*/ )
{
if ( File . Exists ( res . Errors [ i ] . FileName ) )
errorsList . Add ( new Errors . CommonCompilerError ( res . Errors [ i ] . ErrorText , res . Errors [ i ] . FileName , res . Errors [ i ] . Line ! = 0 ? res . Errors [ i ] . Line : 1 , res . Errors [ i ] . Column ! = 0 ? res . Errors [ i ] . Column : 1 ) ) ;
else
errorsList . Add ( new Errors . CommonCompilerError ( res . Errors [ i ] . ErrorText , CompilerOptions . SourceFileName , res . Errors [ i ] . Line ! = 0 ? res . Errors [ i ] . Line : 1 , res . Errors [ i ] . Column ! = 0 ? res . Errors [ i ] . Column : 1 ) ) ;
}
else if ( res . Errors [ i ] . IsWarning )
{
warnings . Add ( new Errors . CommonWarning ( res . Errors [ i ] . ErrorText , res . Errors [ i ] . FileName , res . Errors [ i ] . Line , res . Errors [ i ] . Column ) ) ;
}
}
}
//linesCompiled = get_compiled_lines(CompilerOptions.SourceFileName);
OnChangeCompilerState ( this , CompilerState . CompilationFinished , CompilerOptions . SourceFileName ) ;
ClearAll ( ) ;
OnChangeCompilerState ( this , CompilerState . Ready , null ) ;
if ( errorsList . Count > 0 )
return null ;
else
return res . PathToAssembly ;
}
class PyErrorHandler : ErrorListener
{
Compiler c ;
public PyErrorHandler ( Compiler cc ) { c = cc ; }
public override void ErrorReported ( ScriptSource source , string message , SourceSpan span , int errorCode , Severity severity )
{
if ( severity = = Severity . Warning )
c . warnings . Add ( new Errors . CommonWarning ( message , c . compilerOptions . SourceFileName , span . Start . Line , span . Start . Column ) ) ;
else
c . errorsList . Add ( new Errors . CommonCompilerError ( message , c . compilerOptions . SourceFileName , span . Start . Line , span . Start . Column ) ) ;
}
}
private Assembly IronPythonAssembly ;
private MethodInfo PythonCreateEngineMethod ;
public string CompilePy ( )
{
OnChangeCompilerState ( this , CompilerState . CompilationStarting , CompilerOptions . SourceFileName ) ;
OnChangeCompilerState ( this , CompilerState . BeginCompileFile , CompilerOptions . SourceFileName ) ;
Reset ( ) ;
if ( IronPythonAssembly = = null )
{
IronPythonAssembly = Assembly . LoadFrom ( "IronPython.dll" ) ;
PythonCreateEngineMethod = IronPythonAssembly . GetType ( "IronPython.Hosting.Python" ) . GetMethod ( "CreateEngine" ) ;
}
string source = GetSourceFileText ( CompilerOptions . SourceFileName ) ;
ScriptEngine pyEngine = ( ScriptEngine ) PythonCreateEngineMethod . Invoke ( null , new object [ 0 ] ) ; ;
ScriptSource src = pyEngine . CreateScriptSourceFromString ( source ) ;
CompiledCode compiled = src . Compile ( new PyErrorHandler ( this ) ) ;
if ( compiled ! = null )
compiled . Execute ( ) ;
linesCompiled = get_compiled_lines ( CompilerOptions . SourceFileName ) ;
OnChangeCompilerState ( this , CompilerState . CompilationFinished , CompilerOptions . SourceFileName ) ;
ClearAll ( ) ;
OnChangeCompilerState ( this , CompilerState . Ready , null ) ;
//if (errorsList.Count > 0)
return null ;
//else return res.PathToAssembly;
}
public string CompileCS ( )
{
OnChangeCompilerState ( this , CompilerState . CompilationStarting , CompilerOptions . SourceFileName ) ;
OnChangeCompilerState ( this , CompilerState . BeginCompileFile , CompilerOptions . SourceFileName ) ;
Reset ( ) ;
var d = new Dictionary < string , string > ( ) ;
d [ "CompilerVersion" ] = "v4.0" ;
var cscp = new Microsoft . CSharp . CSharpCodeProvider ( d ) ;
//var cscp = new Microsoft.CSharp.CSharpCodeProvider();
var comp_opt = new CompilerParameters ( ) ;
comp_opt . IncludeDebugInformation = CompilerOptions . Debug ;
comp_opt . GenerateExecutable = true ;
comp_opt . WarningLevel = 3 ;
comp_opt . OutputAssembly = CompilerOptions . OutputFileName ;
//comp_opt.ReferencedAssemblies.Add()
string source = GetSourceFileText ( CompilerOptions . SourceFileName ) ;
using ( StringReader sr = new StringReader ( source ) )
{
do
{
var s = sr . ReadLine ( ) ;
if ( s = = null )
break ;
if ( s . ToLower ( ) . StartsWith ( "//#reference " ) )
{
s = s . Remove ( 0 , 13 ) ;
s = s . Trim ( ) ;
comp_opt . ReferencedAssemblies . Add ( s ) ;
}
else break ;
} while ( true ) ;
}
var res = cscp . CompileAssemblyFromSource ( comp_opt , source ) ;
if ( res . Errors . Count > 0 )
{
for ( int i = 0 ; i < res . Errors . Count ; i + + )
{
if ( ! res . Errors [ i ] . IsWarning & & errorsList . Count = = 0 /*&& res.Errors[i].FileName != redirect_fname*/ )
{
if ( File . Exists ( res . Errors [ i ] . FileName ) )
errorsList . Add ( new Errors . CommonCompilerError ( res . Errors [ i ] . ErrorText , res . Errors [ i ] . FileName , res . Errors [ i ] . Line ! = 0 ? res . Errors [ i ] . Line : 1 , res . Errors [ i ] . Column ! = 0 ? res . Errors [ i ] . Column : 1 ) ) ;
else
errorsList . Add ( new Errors . CommonCompilerError ( res . Errors [ i ] . ErrorText , CompilerOptions . SourceFileName , res . Errors [ i ] . Line ! = 0 ? res . Errors [ i ] . Line : 1 , res . Errors [ i ] . Column ! = 0 ? res . Errors [ i ] . Column : 1 ) ) ;
}
else if ( res . Errors [ i ] . IsWarning )
{
warnings . Add ( new Errors . CommonWarning ( res . Errors [ i ] . ErrorText , res . Errors [ i ] . FileName , res . Errors [ i ] . Line , res . Errors [ i ] . Column ) ) ;
}
}
}
linesCompiled = get_compiled_lines ( CompilerOptions . SourceFileName ) ;
OnChangeCompilerState ( this , CompilerState . CompilationFinished , CompilerOptions . SourceFileName ) ;
ClearAll ( ) ;
OnChangeCompilerState ( this , CompilerState . Ready , null ) ;
if ( errorsList . Count > 0 )
return null ;
else
return res . PathToAssembly ;
}
public string CompileVB ( )
{
OnChangeCompilerState ( this , CompilerState . CompilationStarting , CompilerOptions . SourceFileName ) ;
OnChangeCompilerState ( this , CompilerState . BeginCompileFile , CompilerOptions . SourceFileName ) ;
Reset ( ) ;
Microsoft . VisualBasic . VBCodeProvider vbcp = new Microsoft . VisualBasic . VBCodeProvider ( ) ;
List < string > sources = new List < string > ( ) ;
sources . Add ( CompilerOptions . SourceFileName ) ;
System . CodeDom . Compiler . CompilerParameters comp_opt = new System . CodeDom . Compiler . CompilerParameters ( ) ;
comp_opt . OutputAssembly = CompilerOptions . OutputFileName ;
comp_opt . WarningLevel = 3 ;
comp_opt . ReferencedAssemblies . Add ( "System.Windows.Forms.dll" ) ;
comp_opt . ReferencedAssemblies . Add ( "System.Drawing.dll" ) ;
comp_opt . ReferencedAssemblies . Add ( "Microsoft.VisualBasic.dll" ) ;
comp_opt . IncludeDebugInformation = CompilerOptions . Debug ;
comp_opt . GenerateExecutable = true ;
string fname = Path . Combine ( Path . GetDirectoryName ( CompilerOptions . SourceFileName ) , "_temp$" + Path . GetFileName ( CompilerOptions . SourceFileName ) ) ;
File . Copy ( CompilerOptions . SourceFileName , fname , true ) ;
string source = GetSourceFileText ( CompilerOptions . SourceFileName ) ;
IParser parser = ICSharpCode . NRefactory . ParserFactory . CreateParser ( ICSharpCode . NRefactory . SupportedLanguage . VBNet , new StringReader ( source ) ) ;
parser . Parse ( ) ;
ProgInfo info = get_programm_info ( parser . CompilationUnit , source ) ;
parser . Dispose ( ) ;
if ( info ! = null )
sources . AddRange ( info . addit_project_files ) ;
string redirect_base_fname = FindFileInDirs ( "__RedirectIOMode.vb" , Path . Combine ( this . CompilerOptions . SystemDirectory , "Lib" ) , Path . Combine ( this . CompilerOptions . SystemDirectory , "LibSource" ) ) ;
string system_unit_name = FindFileInDirs ( "VBSystem.vb" , Path . Combine ( this . CompilerOptions . SystemDirectory , "lib" ) , Path . Combine ( this . CompilerOptions . SystemDirectory , "LibSource" ) ) ;
string redirect_fname = Path . Combine ( Path . GetDirectoryName ( CompilerOptions . SourceFileName ) , "_RedirectIOMode.vb" ) ;
StreamReader sr = File . OpenText ( redirect_base_fname ) ;
string redirect_module = sr . ReadToEnd ( ) ;
sr . Close ( ) ;
if ( info ! = null )
{
System . Text . StringBuilder tmp_sb = new System . Text . StringBuilder ( ) ;
if ( info . modules . Count > 0 )
{
tmp_sb . AppendLine ( "GetType(Fictive.Fictive).Assembly.GetType(\"PABCSystem_implementation$.PABCSystem_implementation$\").GetMethod(\"$Initialization\").Invoke(Nothing,Nothing)" ) ;
}
for ( int i = 0 ; i < info . modules . Count ; i + + )
{
tmp_sb . AppendLine ( "GetType(Fictive.Fictive).Assembly.GetType(\"" + info . modules [ i ] + "_implementation$." + info . modules [ i ] +
"_implementation$\").GetMethod(\"$Initialization\").Invoke(Nothing,Nothing)" ) ;
}
tmp_sb . AppendLine ( info . entry_module + "." + "___Main()" ) ;
for ( int i = 0 ; i < info . modules . Count ; i + + )
{
tmp_sb . AppendLine ( "GetType(Fictive.Fictive).Assembly.GetType(\"" + info . modules [ i ] + "_implementation$." + info . modules [ i ] +
"_implementation$\").GetMethod(\"$Finalization\").Invoke(Nothing,Nothing)" ) ;
}
redirect_module = redirect_module . Replace ( "%MAIN%" , tmp_sb . ToString ( ) ) ;
}
StreamWriter sw = new StreamWriter ( redirect_fname , false ) ;
if ( info ! = null )
{
sw . WriteLine ( redirect_module ) ;
}
else
{
sw . WriteLine ( "Module _RedirectIOMode" ) ;
sw . WriteLine ( "End Module" ) ;
}
sw . Close ( ) ;
sw = new StreamWriter ( CompilerOptions . SourceFileName , false ) ;
if ( info ! = null & & info . entry_method_name_pos ! = - 1 )
{
System . Text . StringBuilder sb = new System . Text . StringBuilder ( ) ;
int start_pos = 0 ;
if ( info . using_pos ! = - 1 )
{
start_pos = info . using_pos ;
sb . Append ( source . Substring ( 0 , info . using_pos ) ) ;
for ( int i = 0 ; i < info . addit_imports . Count ; i + + )
{
sb . Append ( "," + info . addit_imports [ i ] ) ;
}
sb . Append ( ",System.Collections.Generic" ) ;
sb . Append ( ",Microsoft.VisualBasic.Strings" ) ;
sb . Append ( ",Microsoft.VisualBasic.Constants" ) ;
sb . Append ( ",Microsoft.VisualBasic.VBMath" ) ;
sb . Append ( ",Microsoft.VisualBasic.Information" ) ;
sb . Append ( ",Microsoft.VisualBasic.Interaction" ) ;
sb . Append ( ",Microsoft.VisualBasic.FileSystem" ) ;
sb . Append ( ",Microsoft.VisualBasic.Financial" ) ;
sb . Append ( ",Microsoft.VisualBasic.DateAndTime" ) ;
}
else
{
start_pos = 0 ;
sb . Append ( "Imports System" ) ;
sb . Append ( ",System.Collections.Generic" ) ;
sb . Append ( ",Microsoft.VisualBasic.Strings" ) ;
sb . Append ( ",Microsoft.VisualBasic.Constants" ) ;
sb . Append ( ",Microsoft.VisualBasic.VBMath" ) ;
sb . Append ( ",Microsoft.VisualBasic.Information" ) ;
sb . Append ( ",Microsoft.VisualBasic.Interaction" ) ;
sb . Append ( ",Microsoft.VisualBasic.FileSystem" ) ;
sb . Append ( ",Microsoft.VisualBasic.Financial" ) ;
sb . Append ( ",Microsoft.VisualBasic.DateAndTime" ) ;
sb . Append ( ":" ) ;
}
sb . Append ( source . Substring ( start_pos , info . entry_method_name_pos - start_pos ) ) ;
sb . Append ( "___" ) ;
sb . Append ( source . Substring ( info . entry_method_name_pos ) ) ;
sw . Write ( sb . ToString ( ) ) ;
}
else
{
sw . Write ( source ) ;
}
sw . Close ( ) ;
if ( info ! = null & & info . modules . Count > 0 )
{
comp_opt . ReferencedAssemblies . Add ( Path . Combine ( Path . GetDirectoryName ( CompilerOptions . SourceFileName ) , PascalABCCompiler . TreeConverter . compiler_string_consts . pabc_rtl_dll_name ) ) ;
string mod_file_name = FindFileInDirs ( "PABCRtl.dll" , Path . Combine ( this . CompilerOptions . SystemDirectory , "Lib" ) ) ;
File . Copy ( mod_file_name , Path . Combine ( Path . GetDirectoryName ( CompilerOptions . SourceFileName ) , "PABCRtl.dll" ) , true ) ;
/ * foreach ( string mod in info . modules )
{
comp_opt . ReferencedAssemblies . Add ( Path . Combine ( Path . GetDirectoryName ( CompilerOptions . SourceFileName ) , mod + ".dll" ) ) ;
string mod_file_name = FindSourceFileInDirectories ( mod + ".mod" , Path . Combine ( this . CompilerOptions . SystemDirectory , "lib" ) ) ;
File . Copy ( mod_file_name , Path . Combine ( Path . GetDirectoryName ( CompilerOptions . SourceFileName ) , mod + ".dll" ) , true ) ;
} * /
}
sources . Add ( redirect_fname ) ;
sources . Add ( system_unit_name ) ;
System . CodeDom . Compiler . CompilerResults res = vbcp . CompileAssemblyFromFile ( comp_opt , sources . ToArray ( ) ) ;
if ( res . Errors . Count > 0 )
{
for ( int i = 0 ; i < res . Errors . Count ; i + + )
{
if ( ! res . Errors [ i ] . IsWarning & & errorsList . Count = = 0 /*&& res.Errors[i].FileName != redirect_fname*/ )
{
if ( File . Exists ( res . Errors [ i ] . FileName ) )
errorsList . Add ( new Errors . CommonCompilerError ( res . Errors [ i ] . ErrorText , res . Errors [ i ] . FileName , res . Errors [ i ] . Line ! = 0 ? res . Errors [ i ] . Line : 1 , 1 ) ) ;
else
errorsList . Add ( new Errors . CommonCompilerError ( res . Errors [ i ] . ErrorText , CompilerOptions . SourceFileName , res . Errors [ i ] . Line ! = 0 ? res . Errors [ i ] . Line : 1 , 1 ) ) ;
}
else if ( res . Errors [ i ] . IsWarning )
{
warnings . Add ( new Errors . CommonWarning ( res . Errors [ i ] . ErrorText , res . Errors [ i ] . FileName , res . Errors [ i ] . Line , 1 ) ) ;
}
}
}
linesCompiled = get_compiled_lines ( CompilerOptions . SourceFileName ) ;
if ( info ! = null )
{
beginOffset = info . entry_method_line ;
//if (info.using_pos == -1)
// beginOffset -= 1;
}
OnChangeCompilerState ( this , CompilerState . CompilationFinished , CompilerOptions . SourceFileName ) ;
ClearAll ( ) ;
File . Copy ( fname , CompilerOptions . SourceFileName , true ) ;
File . Delete ( fname ) ;
File . Delete ( redirect_fname ) ;
OnChangeCompilerState ( this , CompilerState . Ready , null ) ;
if ( errorsList . Count > 0 )
return null ;
else
return res . PathToAssembly ;
}
private ProjectInfo project ;
private void PrepareCompileOptionsForProject ( )
{
project = new ProjectInfo ( ) ;
project . Load ( CompilerOptions . SourceFileName ) ;
//LoadProject(CompilerOptions.SourceFileName);
switch ( project . ProjectType )
{
case ProjectType . ConsoleApp : CompilerOptions . OutputFileType = CompilerOptions . OutputType . ConsoleApplicaton ; break ;
case ProjectType . WindowsApp : CompilerOptions . OutputFileType = CompilerOptions . OutputType . WindowsApplication ; break ;
case ProjectType . Library : CompilerOptions . OutputFileType = CompilerOptions . OutputType . ClassLibrary ; break ;
}
CompilerOptions . SourceFileName = project . main_file ;
CompilerOptions . Debug = project . include_debug_info ;
CompilerOptions . OutputFileName = project . output_file_name ;
CompilerOptions . OutputDirectory = project . output_directory ;
}
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 ( ) ;
}
CurrentSyntaxUnit = new SyntaxTree . uses_unit_in ( null , new SyntaxTree . string_const ( Path . GetFullPath ( CompilerOptions . SourceFileName ) ) ) ;
2020-10-11 21:20:44 +03:00
CompileUnit (
new PascalABCCompiler . TreeRealization . unit_node_list ( ) ,
new Dictionary < unit_node , CompilationUnit > ( ) ,
CurrentSyntaxUnit , null ) ;
2020-07-09 05:54:55 +03:00
//Console.WriteLine(timer.ElapsedMilliseconds / 1000.0); //////
foreach ( CompilationUnit CurrentUnit in UnitsToCompile )
if ( CurrentUnit . State ! = UnitState . Compiled )
{
CurrentCompilationUnit = CurrentUnit ;
string UnitName = CurrentCompilationUnit . SyntaxTree . file_name ;
//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 ( HasIncludeNamespacesDirective ( CurrentUnit ) )
compilerOptions . UseDllForSystemUnits = false ;
if ( SyntaxUsesList ! = null )
{
for ( int i = SyntaxUsesList . Count - 1 ; i > = 0 ; i - - )
if ( ! IsPossibleNamespace ( SyntaxUsesList [ i ] , false , Path . GetDirectoryName ( UnitName ) ) )
{
compilerOptions . UseDllForSystemUnits = false ;
break ;
}
for ( int i = SyntaxUsesList . Count - 1 ; i > = 0 ; i - - )
if ( ! IsPossibleNamespace ( SyntaxUsesList [ i ] , true , Path . GetDirectoryName ( UnitName ) ) )
{
2020-10-11 21:20:44 +03:00
CompileUnit ( CurrentUnit . ImplementationUsedUnits , CurrentUnit . DirectImplementationCompilationUnits , SyntaxUsesList [ i ] , Path . GetDirectoryName ( UnitName ) ) ;
2020-07-09 05:54:55 +03:00
}
else
{
2020-10-11 21:20:44 +03:00
CurrentUnit . ImplementationUsedUnits . AddElement ( new TreeRealization . namespace_unit_node ( GetNamespace ( SyntaxUsesList [ i ] ) ) , null ) ;
2020-07-09 05:54:55 +03:00
CurrentUnit . PossibleNamespaces . Add ( SyntaxUsesList [ i ] ) ;
}
}
//Console.WriteLine("Compile Implementation "+UnitName);//DEBUG
//TODO: Избавиться от преобразования типа.
AddNamespaces ( CurrentUnit . ImplementationUsingNamespaceList , CurrentUnit . PossibleNamespaces , true , null ) ;
#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 ,
2021-09-06 21:37:31 +03:00
CompilerOptions . ForDebugging ,
CompilerOptions . ForIntellisense ,
CompiledVariables
2020-07-09 05:54:55 +03:00
) ;
CheckErrors ( ) ;
}
CurrentUnit . State = UnitState . Compiled ;
OnChangeCompilerState ( this , CompilerState . EndCompileFile , UnitName ) ;
//SavePCU(CurrentUnit, UnitName);
2021-01-06 00:47:18 +03:00
CurrentUnit . UnitFileName = UnitName ;
2020-07-09 05:54:55 +03:00
}
ClosePCUReadersAndWriters ( ) ;
if ( CompilerOptions . SaveDocumentation )
SaveDocumentations ( ) ;
compilerDirectives = GetCompilerDirectives ( UnitsSortedList ) ;
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 ;
2020-12-24 17:07:20 +03:00
else if ( plt . Equals ( "dotnet5win" ) )
cdo . platformtarget = NETGenerator . CompilerOptions . PlatformTarget . dotnet5win ;
else if ( plt . Equals ( "dotnet5linux" ) )
cdo . platformtarget = NETGenerator . CompilerOptions . PlatformTarget . dotnet5linux ;
else if ( plt . Equals ( "dotnet5macos" ) )
cdo . platformtarget = NETGenerator . CompilerOptions . PlatformTarget . dotnet5macos ;
2022-11-17 22:53:12 +03:00
else if ( plt . Equals ( "native" ) )
{
if ( Environment . OSVersion . Platform = = PlatformID . Unix )
cdo . platformtarget = NETGenerator . CompilerOptions . PlatformTarget . dotnetlinuxnative ;
else if ( Environment . OSVersion . Platform = = PlatformID . MacOSX )
cdo . platformtarget = NETGenerator . CompilerOptions . PlatformTarget . dotnetmacosnative ;
else
cdo . platformtarget = NETGenerator . CompilerOptions . PlatformTarget . dotnetwinnative ;
}
2020-07-09 05:54:55 +03:00
}
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 . title_string , out cds ) )
{
cdo . Title = cds [ 0 ] . directive ;
}
if ( compilerDirectives . TryGetValue ( TreeConverter . compiler_string_consts . description_string , out cds ) )
{
cdo . Description = cds [ 0 ] . directive ;
}
if ( compilerDirectives . TryGetValue ( TreeConverter . compiler_string_consts . main_resource_string , out cds ) )
{
if ( compilerDirectives . ContainsKey ( TreeConverter . compiler_string_consts . product_string ) | |
compilerDirectives . ContainsKey ( TreeConverter . compiler_string_consts . version_string ) | |
compilerDirectives . ContainsKey ( TreeConverter . compiler_string_consts . company_string ) | |
compilerDirectives . ContainsKey ( TreeConverter . compiler_string_consts . trademark_string ) | |
compilerDirectives . ContainsKey ( TreeConverter . compiler_string_consts . title_string ) | |
2023-02-18 12:31:48 +03:00
compilerDirectives . ContainsKey ( TreeConverter . compiler_string_consts . description_string ) | |
compilerDirectives . ContainsKey ( TreeConverter . compiler_string_consts . copyright_string ) )
2020-07-09 05:54:55 +03:00
{
ErrorsList . Add ( new MainResourceNotAllowed ( cds [ 0 ] . location ) ) ;
}
2021-12-12 14:17:30 +03:00
cdo . MainResourceFileName = Path . Combine ( Path . GetDirectoryName ( cds [ 0 ] . source_file ) , cds [ 0 ] . directive ) ;
2020-07-09 05:54:55 +03:00
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 )
{
var resource_fname = Path . Combine ( Path . GetDirectoryName ( cd . source_file ) , cd . directive ) ;
if ( File . Exists ( resource_fname ) )
ResourceFiles . Add ( resource_fname ) ;
else
ErrorsList . Add ( new ResourceFileNotFound ( cd . directive , cd . location ) ) ;
2020-11-22 22:10:26 +03:00
}
2020-07-09 05:54:55 +03:00
}
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 . title ) )
cdo . Title = project . title ;
if ( ! string . IsNullOrEmpty ( project . description ) )
cdo . Description = project . description ;
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\"," + "\"" + cdo . Description + "\"" ) ;
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 ) ;
}
}
2021-09-06 21:37:31 +03:00
if ( ErrorsList . Count = = 0 )
2020-07-09 05:54:55 +03:00
{
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 . ForDebugging ;
//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 ( ) ;
}
2021-09-06 21:37:31 +03:00
if ( compilerOptions . GenerateCode )
pn = semanticTreeConvertersController . Convert ( pn ) as TreeRealization . program_node ;
2020-07-09 05:54:55 +03:00
_semantic_tree = pn ;
if ( FirstCompilationUnit . SyntaxTree is SyntaxTree . unit_module & & CompilerOptions . OutputFileType ! = CompilerOptions . OutputType . ClassLibrary )
{
//если мы комилируем PCU
CompilerOptions . OutputFileType = CompilerOptions . OutputType . PascalCompiledUnit ;
}
2021-09-06 21:37:31 +03:00
else if ( compilerOptions . GenerateCode )
2020-07-09 05:54:55 +03:00
{
if ( CompilerOptions . OutputFileType ! = CompilerOptions . OutputType . SemanticTree )
#if DEBUG
if ( InternalDebug . CodeGeneration )
#endif
{
int n = 1 ;
try
{
n = 2 ;
var fs = File . Create ( CompilerOptions . OutputFileName ) ;
n = 3 ;
fs . Close ( ) ;
n = 4 ;
///////File.Delete(CompilerOptions.OutputFileName);
string pdb_file_name = Path . ChangeExtension ( CompilerOptions . OutputFileName , ".pdb" ) ;
if ( File . Exists ( pdb_file_name ) )
File . Delete ( pdb_file_name ) ;
2022-01-28 11:55:37 +03:00
n = 5 ; // PVS 01/2022
2020-07-09 05:54:55 +03:00
}
catch ( Exception e )
{
throw new UnauthorizedAccessToFile ( CompilerOptions . OutputFileName + " -- " + n + " " + e . ToString ( ) ) ;
//throw e;
}
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 * /
if ( compilerOptions . UseDllForSystemUnits )
cdo . RtlPABCSystemType = NetHelper . NetHelper . FindRtlType ( "PABCSystem.PABCSystem" ) ;
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 ( ) ;
2020-10-31 23:07:04 +03:00
if ( ! need_recompiled )
OnChangeCompilerState ( this , CompilerState . Ready , null ) ;
2020-07-09 05:54:55 +03:00
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 ;
}
private bool has_only_syntax_errors ( List < Error > errors )
{
foreach ( Error err in errors )
{
if ( ! ( err is SyntaxError ) )
return false ;
}
return true ;
}
private void SaveDocumentations ( )
{
DocXmlManager dxm = new DocXmlManager ( ) ;
foreach ( CompilationUnit cu in UnitsSortedList )
{
if ( cu . Documented )
dxm . SaveXml ( cu ) ;
}
}
private void ClosePCUReadersAndWriters ( )
{
if ( PCUReadersAndWritersClosed )
return ;
PCUReadersAndWritersClosed = true ;
bool all_restored = false ;
while ( ! all_restored )
{
foreach ( PCUReader p in PCUReader . AllReaders )
{
p . AddInitFinalMethods ( ) ;
SystemLibrary . SystemLibInitializer . RestoreStandardFunctions ( ) ;
p . ProcessWaitedToRestoreFields ( ) ;
2022-01-23 14:10:05 +03:00
p . RestoreWaitedMethodCodes ( ) ;
2020-07-09 05:54:55 +03:00
}
bool rest = true ;
for ( int i = 0 ; i < PCUReader . AllReaders . Count ; i + + )
if ( PCUReader . AllReaders [ i ] . waited_types_to_restore_fields . Count ! = 0 )
{
rest = false ;
break ;
}
all_restored = rest ;
}
PCUReader . AddUsedMembersInAllUnits ( ) ;
if ( CompilerOptions . SavePCUInThreadPull )
AsyncClosePCUWriters ( ) ;
else
ClosePCUWriters ( ) ;
}
void WaitCallback_ClosePCUWriters ( object state )
{
ClosePCUWriters ( ) ;
}
private void AsyncClosePCUWriters ( )
{
System . Threading . ThreadPool . QueueUserWorkItem ( WaitCallback_ClosePCUWriters ) ;
}
private void ClosePCUWriters ( )
{
foreach ( CompilationUnit cu in UnitsSortedList )
{
2020-07-17 06:22:30 +03:00
SavePCU ( cu ) ;
2020-07-09 05:54:55 +03:00
}
foreach ( PCUWriter pw in PCUWriter . AllWriters )
{
pw . CloseWriter ( ) ;
}
}
void checkDuplicateUsesUnit ( List < SyntaxTree . unit_or_namespace > usesList )
{
if ( usesList = = null )
return ;
List < string > names = new List < string > ( ) ;
foreach ( SyntaxTree . unit_or_namespace un in usesList )
{
string name = SyntaxTree . Utils . IdentListToString ( un . name . idents , "." ) . ToLower ( ) ;
if ( un . source_context ! = null )
{
if ( names . Contains ( name ) )
throw new DuplicateUsesUnit ( CurrentCompilationUnit . SyntaxTree . file_name , name , un . source_context ) ;
else
names . Add ( name ) ;
}
}
}
public List < SyntaxTree . unit_or_namespace > GetSyntaxInterfaceUsesList ( SyntaxTree . compilation_unit CurrentSyntaxUnit )
{
List < SyntaxTree . unit_or_namespace > result = null ;
if ( CurrentSyntaxUnit is SyntaxTree . unit_module )
{
SyntaxTree . interface_node intp = ( CurrentSyntaxUnit as SyntaxTree . unit_module ) . interface_part ;
if ( intp . uses_modules = = null )
if ( CompilerOptions . StandartModules . Count > 0 ) //если есть стандартые модули то создать список
{
intp . uses_modules = new SyntaxTree . uses_list ( ) ;
intp . uses_modules . source_context = new SyntaxTree . SourceContext ( 1 , 1 , 1 , 1 , 1 , 1 ) ;
}
else
return null ;
result = intp . uses_modules . units ;
}
if ( CurrentSyntaxUnit is SyntaxTree . program_module )
{
SyntaxTree . program_module pm = ( CurrentSyntaxUnit as SyntaxTree . program_module ) ;
if ( pm . used_units = = null )
if ( CompilerOptions . StandartModules . Count > 0 ) //если есть стандартые модули то создать список
{
pm . used_units = new SyntaxTree . uses_list ( ) ;
pm . used_units . source_context = new SyntaxTree . SourceContext ( 1 , 1 , 1 , 1 , 1 , 1 ) ;
}
else
return null ;
result = pm . used_units . units ;
}
if ( CurrentSyntaxUnit is SyntaxTree . c_module )
{
SyntaxTree . c_module pm = ( CurrentSyntaxUnit as SyntaxTree . c_module ) ;
if ( pm . used_units = = null )
if ( CompilerOptions . StandartModules . Count > 0 ) //если есть стандартые модули то создать список
{
pm . used_units = new SyntaxTree . uses_list ( ) ;
pm . used_units . source_context = new SyntaxTree . SourceContext ( 1 , 1 , 1 , 1 , 1 , 1 ) ;
}
else
return null ;
result = pm . used_units . units ;
}
checkDuplicateUsesUnit ( result ) ;
return result ;
}
private List < SyntaxTree . unit_or_namespace > GetSyntaxImplementationUsesList ( SyntaxTree . compilation_unit CurrentSyntaxUnit )
{
List < SyntaxTree . unit_or_namespace > result = null ;
if ( CurrentSyntaxUnit is SyntaxTree . unit_module )
if ( ( CurrentSyntaxUnit as SyntaxTree . unit_module ) . implementation_part ! = null )
if ( ( CurrentSyntaxUnit as SyntaxTree . unit_module ) . implementation_part . uses_modules ! = null )
{
result = ( CurrentSyntaxUnit as SyntaxTree . unit_module ) . implementation_part . uses_modules . units ;
checkDuplicateUsesUnit ( result ) ;
return result ;
}
if ( CurrentSyntaxUnit is SyntaxTree . program_module )
return null ;
return null ;
}
2020-07-17 01:58:34 +03:00
public string FindPCUFileName ( string fname , string curr_path , out int folder_priority )
2020-07-09 05:54:55 +03:00
{
2020-07-14 07:31:18 +03:00
if ( string . IsNullOrEmpty ( Path . GetExtension ( fname ) ) )
2020-07-09 05:54:55 +03:00
fname + = CompilerOptions . CompiledUnitExtension ;
2020-07-17 04:13:17 +03:00
var cache_key = Tuple . Create ( fname . ToLower ( ) , curr_path ? . ToLower ( ) ) ;
2020-07-09 05:54:55 +03:00
2020-07-17 01:58:34 +03:00
if ( ! PCUFileNamesDictionary . TryGetValue ( cache_key , out var res ) )
{
2020-07-09 05:54:55 +03:00
2020-07-17 01:58:34 +03:00
if ( FindFileInDirs ( fname , curr_path ) is string res_s1 )
res = Tuple . Create ( res_s1 , 1 ) ;
else if ( FindFileInDirs ( Path . GetFileName ( fname ) , CompilerOptions . OutputDirectory ) is string res_s2 )
res = Tuple . Create ( res_s2 , 2 ) ;
2020-07-17 07:02:36 +03:00
else if ( FindFileInDirs ( fname , CompilerOptions . SearchDirectory . ToArray ( ) ) is string res_s3 )
2020-07-17 01:58:34 +03:00
res = Tuple . Create ( res_s3 , 3 ) ;
else
res = null ;
2020-07-09 05:54:55 +03:00
2020-07-17 01:58:34 +03:00
PCUFileNamesDictionary [ cache_key ] = res ;
}
folder_priority = res = = null ? 0 : res . Item2 ;
return res ? . Item1 ;
2020-07-09 05:54:55 +03:00
}
2020-07-17 01:58:34 +03:00
public string FindSourceFileName ( string fname , string curr_path , out int folder_priority )
2020-07-09 05:54:55 +03:00
{
2020-07-17 04:13:17 +03:00
var cache_key = Tuple . Create ( fname . ToLower ( ) , curr_path ? . ToLower ( ) ) ;
2020-07-09 05:54:55 +03:00
2020-07-17 01:58:34 +03:00
if ( ! SourceFileNamesDictionary . TryGetValue ( cache_key , out var res ) )
{
2020-07-09 05:54:55 +03:00
2020-07-17 01:58:34 +03:00
if ( FindSourceFileNameInDirs ( fname , curr_path ) is string res_s1 )
res = Tuple . Create ( res_s1 , 1 ) ;
2020-07-17 07:02:36 +03:00
else if ( FindSourceFileNameInDirs ( fname , CompilerOptions . SearchDirectory . ToArray ( ) ) is string res_s3 )
2020-07-17 01:58:34 +03:00
res = Tuple . Create ( res_s3 , 3 ) ;
else
res = null ;
2020-07-09 05:54:55 +03:00
2020-07-17 01:58:34 +03:00
SourceFileNamesDictionary [ cache_key ] = res ;
}
folder_priority = res = = null ? 0 : res . Item2 ;
return res ? . Item1 ;
2020-07-09 05:54:55 +03:00
}
public string FindSourceFileNameInDirs ( string fname , params string [ ] Dirs )
{
var fname_ext = Path . GetExtension ( fname ) ;
var need_ext = string . IsNullOrEmpty ( fname_ext ) ;
foreach ( SupportedSourceFile sf in SupportedSourceFiles )
foreach ( string ext in sf . Extensions )
if ( need_ext | | fname_ext = = ext )
{
var res = FindFileInDirs ( need_ext ? fname + ext : fname , Dirs ) ;
//if (!(CompilerOptions.UseDllForSystemUnits && Path.GetDirectoryName(res) == CompilerOptions.SearchDirectory))
if ( res ! = null )
return res ;
}
return null ;
}
2020-07-13 06:23:13 +03:00
public static string CombinePath ( string dir , string path )
2020-07-09 05:54:55 +03:00
{
if ( Path . IsPathRooted ( path ) ) return path ;
int i = 0 ;
2020-10-19 14:42:03 +03:00
for ( ; dir ! = "" & & i < path . Length & & path [ i ] = = '.' & & path [ i + 1 ] = = '.' ; )
2020-07-09 05:54:55 +03:00
{
2021-10-12 12:04:31 +03:00
if ( Path . GetFileName ( dir ) = = ".." ) break ;
2020-07-09 05:54:55 +03:00
dir = Path . GetDirectoryName ( dir ) ;
2021-10-18 10:09:09 +03:00
if ( dir = = null ) return null ; // Path.GetDirectoryName("C:\") возвращает null
2020-07-09 05:54:55 +03:00
i + = 2 ;
if ( path [ i ] = = Path . DirectorySeparatorChar | | path [ i ] = = Path . AltDirectorySeparatorChar ) i + = 1 ;
}
return Path . Combine ( dir , path . Substring ( i ) ) ;
}
2020-10-11 21:20:44 +03:00
public static string GetUnitPath ( CompilationUnit u1 , CompilationUnit u2 )
{
if ( u1 = = null ) throw new ArgumentException ( nameof ( u1 ) ) ;
if ( u2 = = null ) throw new ArgumentException ( nameof ( u2 ) ) ;
if ( u1 . DirectInterfaceCompilationUnits . Values . Contains ( u2 ) ) return u1 . InterfaceUsedUnits . unit_uses_paths [ u2 . SemanticTree ] ;
if ( u1 . DirectImplementationCompilationUnits . Values . Contains ( u2 ) ) return u1 . ImplementationUsedUnits . unit_uses_paths [ u2 . SemanticTree ] ;
var last = new Dictionary < CompilationUnit , string > ( ) ;
var done = new HashSet < CompilationUnit > ( ) ;
foreach ( var u in u1 . DirectInterfaceCompilationUnits . Values . Concat ( u1 . DirectImplementationCompilationUnits . Values ) )
{
last . Add ( u , u1 . InterfaceUsedUnits . unit_uses_paths [ u . SemanticTree ] ) ;
done . Add ( u ) ;
}
while ( last . Count ! = 0 )
{
var next = new Dictionary < CompilationUnit , string > ( ) ;
foreach ( var u in last . Keys )
2020-10-19 15:09:46 +03:00
{
foreach ( var used_u in u . DirectInterfaceCompilationUnits . Values )
2020-10-11 21:20:44 +03:00
{
if ( ! done . Add ( used_u ) ) continue ;
var path = CombinePath ( Path . GetDirectoryName ( last [ u ] ) , u . InterfaceUsedUnits . unit_uses_paths [ used_u . SemanticTree ] ) ;
if ( used_u = = u2 ) return path ;
next . Add ( used_u , path ) ;
}
2020-10-19 15:09:46 +03:00
foreach ( var used_u in u . DirectImplementationCompilationUnits . Values )
{
if ( ! done . Add ( used_u ) ) continue ;
var path = CombinePath ( Path . GetDirectoryName ( last [ u ] ) , u . ImplementationUsedUnits . unit_uses_paths [ used_u . SemanticTree ] ) ;
if ( used_u = = u2 ) return path ;
next . Add ( used_u , path ) ;
}
}
2020-10-11 21:20:44 +03:00
last = next ;
}
2021-01-06 00:47:18 +03:00
throw new InvalidOperationException ( $"Could not find path to \" { u2 . UnitFileName } \ " relative to \"{u1.UnitFileName}\"" ) ;
2020-10-11 21:20:44 +03:00
}
2020-07-09 05:54:55 +03:00
private string FindFileInDirs ( string FileName , params string [ ] Dirs )
{
foreach ( string Dir in Dirs )
{
var res = CombinePath ( Dir , FileName ) ;
if ( File . Exists ( res ) )
return res ;
}
return null ;
}
2021-12-19 14:13:59 +03:00
public static string GetReferenceFileName ( string FileName , string curr_path = null )
2020-07-09 05:54:55 +03:00
{
// Вначале - кешированные стандартные dll
if ( standart_assembly_dict . ContainsKey ( FileName ) )
return standart_assembly_dict [ FileName ] ;
2021-12-19 14:13:59 +03:00
if ( curr_path ! = null & & System . IO . File . Exists ( Path . Combine ( curr_path , FileName ) ) )
return Path . Combine ( curr_path , FileName ) ;
2020-07-09 05:54:55 +03:00
if ( System . IO . File . Exists ( FileName ) )
{
return FileName ; //.ToLower();//? а надо ли tolover?
}
else
{
return get_assembly_path ( FileName , false ) ;
}
}
private string GetReferenceFileName ( string FileName , SyntaxTree . SourceContext sc , string curr_path )
{
if ( standart_assembly_dict . ContainsKey ( FileName ) )
return standart_assembly_dict [ FileName ] ;
// Наверное, этот код MikhailoMMX лишний
//MikhailoMMX PABCRtl.dll будем искать сначала в GAC, а потом в папке с программой
if ( FileName = = TreeConverter . compiler_string_consts . pabc_rtl_dll_name )
{
string name = get_assembly_path ( FileName , true ) ;
if ( ( name ! = null ) & & ( File . Exists ( name ) ) )
return name ;
}
//\MikhailoMMX
var FullFileName = Path . Combine ( curr_path , FileName ) ;
2020-11-22 22:10:26 +03:00
if ( System . IO . File . Exists ( FullFileName ) )
2020-07-09 05:54:55 +03:00
{
var NewFileName = Path . Combine ( compilerOptions . OutputDirectory , Path . GetFileName ( FullFileName ) ) ;
if ( FullFileName ! = NewFileName ) File . Copy ( FullFileName , NewFileName , true ) ;
return NewFileName ;
}
else
{
string name = get_assembly_path ( FileName , false ) ; //? а надо ли tolover?
if ( name = = null )
throw new AssemblyNotFound ( this . CurrentCompilationUnit . SyntaxTree . file_name , FileName , sc ) ;
else
if ( File . Exists ( name ) )
return name ;
else
throw new AssemblyNotFound ( this . CurrentCompilationUnit . SyntaxTree . file_name , FileName , sc ) ;
}
}
public string GetUnitFileName ( SyntaxTree . unit_or_namespace SyntaxUsesUnit , string curr_path )
{
//ToDo В корневом Compile() создаётся uses_unit_in без name. Выглядит как костыль
if ( SyntaxUsesUnit is SyntaxTree . uses_unit_in & & ( SyntaxUsesUnit as SyntaxTree . uses_unit_in ) . name = = null ) return ( SyntaxUsesUnit as SyntaxTree . uses_unit_in ) . in_file . Value ;
2021-10-18 10:09:09 +03:00
if ( curr_path = = null ) throw new InvalidOperationException ( SyntaxUsesUnit . UsesPath ( ) ) ;
2020-07-17 01:58:34 +03:00
var UnitName = SyntaxUsesUnit . name . idents [ 0 ] . name ;
2020-07-09 05:54:55 +03:00
if ( SyntaxUsesUnit is SyntaxTree . uses_unit_in uui )
{
2020-07-17 01:58:34 +03:00
if ( UnitName . ToLower ( ) ! = Path . GetFileNameWithoutExtension ( uui . in_file . Value ) . ToLower ( ) )
throw new UsesInWrongName ( CurrentCompilationUnit . SyntaxTree . file_name , UnitName , Path . GetFileNameWithoutExtension ( uui . in_file . Value ) , uui . in_file . source_context ) ;
2020-07-09 05:54:55 +03:00
}
2020-07-17 01:58:34 +03:00
return GetUnitFileName ( UnitName , SyntaxUsesUnit . UsesPath ( ) , curr_path , SyntaxUsesUnit . source_context ) ;
}
public string GetUnitFileName ( string UnitName , string path , string curr_path , SyntaxTree . SourceContext source_context )
{
2020-07-17 04:13:17 +03:00
var cache_key = Tuple . Create ( path . ToLower ( ) , curr_path ? . ToLower ( ) ) ;
2020-07-17 01:58:34 +03:00
string res ;
if ( GetUnitFileNameCache . TryGetValue ( cache_key , out res ) )
return res ;
2020-07-09 05:54:55 +03:00
2020-07-17 01:58:34 +03:00
// число приоритета меньше = более важная папка
// может выглядеть задом-наперёд, но так должно быть проще в будущем добавлять папки...
var SourceFileName = FindSourceFileName ( path , curr_path , out var SourceFilePriority ) ;
var PCUFileName = FindPCUFileName ( path , curr_path , out var PCUFilePriority ) ;
2020-07-09 05:54:55 +03:00
2020-07-14 07:31:18 +03:00
var SourceFileExists = SourceFileName ! = null ;
2020-07-17 01:58:34 +03:00
//ToDo то есть Rebuild режим игнорирует .pcu, даже если нет .pas файла?
// а ещё ниже стоит ещё 1 проверка Rebuild...
2022-10-23 13:09:03 +03:00
var PCUFileExists = ( ! CompilerOptions . Rebuild | | ! SourceFileExists ) & & PCUFileName ! = null ;
2020-07-09 05:54:55 +03:00
if ( ! PCUFileExists & & ! SourceFileExists )
2020-07-17 01:58:34 +03:00
if ( UnitName = = null )
// вызов с "UnitName == null" должен быть только там, где уже известно что хотя бы какой то файл есть
// если где то ещё будет исопльзоваться UnitName или source_context - надо будет добавить такую же проверку
throw new InvalidOperationException ( nameof ( UnitName ) ) ;
else
throw new UnitNotFound ( CurrentCompilationUnit . SyntaxTree . file_name , UnitName , source_context ) ;
2020-07-09 05:54:55 +03:00
if ( PCUFileExists & & SourceFileExists )
{
2020-07-17 01:58:34 +03:00
//ToDo из за проверки Rebuild выше - тут всегда будет false
// но я не понимаю какая из этих 2 проверок правильная
2020-07-14 07:31:18 +03:00
if ( CompilerOptions . Rebuild & & ! RecompileList . ContainsKey ( PCUFileName ) )
2020-07-09 05:54:55 +03:00
PCUFileExists = false ;
2020-07-17 01:58:34 +03:00
else if ( SourceFilePriority ! = PCUFilePriority )
{
if ( SourceFilePriority < PCUFilePriority )
PCUFileExists = false ;
else
SourceFileExists = false ;
}
2020-07-09 05:54:55 +03:00
else if ( Path . GetDirectoryName ( SourceFileName ) ! = Path . GetDirectoryName ( PCUFileName ) )
2020-07-17 01:58:34 +03:00
throw new InvalidOperationException ( "priority" ) ; // не должно происходить, раз приоритет одинаковый
else if ( File . GetLastWriteTime ( PCUFileName ) < File . GetLastWriteTime ( SourceFileName ) )
2020-07-09 05:54:55 +03:00
PCUFileExists = false ;
}
if ( PCUFileExists )
2020-07-17 01:58:34 +03:00
res = Path . Combine ( curr_path , PCUFileName ) ;
else if ( SourceFileExists )
res = Path . Combine ( curr_path , SourceFileName ) ;
2020-07-09 05:54:55 +03:00
else
2020-07-17 01:58:34 +03:00
throw new InvalidOperationException ( nameof ( SourceFileExists ) ) ; // тело "if (PCUFileExists && SourceFileExists)" не должно присваивать false обоим переменным
GetUnitFileNameCache [ cache_key ] = res ;
return res ;
}
2020-07-09 05:54:55 +03:00
public void AddStandartUnitsToUsesSection ( SyntaxTree . compilation_unit cu )
{
//if (FileInSearchDirectory(cu.file_name)) return;
string ModuleName = null ;
SyntaxTree . uses_unit_in uses_unit_in = null ;
SyntaxTree . unit_or_namespace uses_unit = null ;
List < SyntaxTree . unit_or_namespace > UsesList = GetSyntaxInterfaceUsesList ( cu ) ;
if ( UsesList = = null )
return ;
string cu_module_name = Path . GetFileNameWithoutExtension ( cu . file_name ) . ToLower ( ) ;
foreach ( CompilerOptions . StandartModule Module in CompilerOptions . StandartModules )
{
//Я стандартный??
ModuleName = Path . GetFileNameWithoutExtension ( Module . Name ) ;
if ( ModuleName . ToLower ( ) = = cu_module_name )
return ;
}
foreach ( CompilerOptions . StandartModule Module in CompilerOptions . StandartModules )
{
if ( ( Module . AddToLanguages & FirstCompilationUnit . SyntaxTree . Language ) ! = FirstCompilationUnit . SyntaxTree . Language
& & ( Module . AddToLanguages & CurrentCompilationUnit . SyntaxTree . Language ) ! = CurrentCompilationUnit . SyntaxTree . Language )
continue ;
ModuleName = Path . GetFileNameWithoutExtension ( Module . Name ) ;
if ( Module . AddMethod = = CompilerOptions . StandartModuleAddMethod . RightToMain & & CurrentCompilationUnit ! = FirstCompilationUnit )
continue ;
foreach ( SyntaxTree . unit_or_namespace curunit in UsesList )
{
if ( curunit . name . idents . Count = = 1 & & curunit . name . idents [ 0 ] . name . ToLower ( ) = = ModuleName . ToLower ( ) )
continue ;
}
PascalABCCompiler . SyntaxTree . unit_or_namespace to_add ;
if ( Path . GetExtension ( Module . Name ) ! = "" /*&& Path.GetExtension(ModuleFileName).ToLower() != ".dll"*/ )
{
uses_unit_in = new SyntaxTree . uses_unit_in (
_name : new SyntaxTree . ident_list ( new SyntaxTree . ident ( ModuleName ) ) ,
_in_file : new SyntaxTree . string_const ( Module . Name ) ) ;
//uses_unit_in.source_context = uses_unit_in.in_file.source_context = uses_unit_in.name.source_context = new SyntaxTree.SourceContext(1, 1, 1, 1);
to_add = uses_unit_in ;
}
else
{
uses_unit = new SyntaxTree . unit_or_namespace ( new SyntaxTree . ident_list ( new SyntaxTree . ident ( ModuleName ) ) ) ;
//uses_unit.source_context = uses_unit.name.source_context = new SyntaxTree.SourceContext(1, 1, 1, 1);
to_add = uses_unit ;
}
switch ( Module . AddMethod )
{
case CompilerOptions . StandartModuleAddMethod . RightToMain :
UsesList . Add ( to_add ) ;
break ;
case CompilerOptions . StandartModuleAddMethod . LeftToAll :
UsesList . Insert ( 0 , to_add ) ;
break ;
}
}
}
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
{
2020-11-22 22:10:26 +03:00
UnitName = GetReferenceFileName ( cd . directive , sc , Path . GetDirectoryName ( cd . source_file ) ) ;
2020-07-09 05:54:55 +03:00
}
catch ( AssemblyNotFound ex )
{
throw ;
}
2020-11-22 22:10:26 +03:00
//ToDo плохо, пока дебажил - тут постоянно ловились другие исключения, не связанные с неправильным знаками в пути к сборке
2020-07-09 05:54:55 +03:00
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 )
{
2020-10-11 21:20:44 +03:00
Units . AddElement ( CurrentUnit . SemanticTree , null ) ;
2020-07-09 05:54:55 +03:00
UnitTable [ UnitName ] = CurrentUnit ;
return CurrentUnit ;
}
else
//throw new DLLReadingError(UnitName);
throw new AssemblyReadingError ( CurrentCompilationUnit . SyntaxTree . file_name , UnitName , sc ) ;
}
private bool HasIncludeNamespacesDirective ( CompilationUnit Unit )
{
var directives = ConvertDirectives ( Unit . SyntaxTree ) ;
foreach ( TreeRealization . compiler_directive cd in directives )
{
if ( cd . name . ToLower ( ) = = TreeConverter . compiler_string_consts . include_namespace_directive )
{
return true ;
}
}
return false ;
}
private Dictionary < string , SyntaxTree . syntax_namespace_node > IncludeNamespaces ( CompilationUnit Unit )
{
if ( HasIncludeNamespacesDirective ( Unit ) & & Unit . SyntaxTree is SyntaxTree . unit_module & & ( Unit . SyntaxTree as SyntaxTree . unit_module ) . unit_name . HeaderKeyword ! = SyntaxTree . UnitHeaderKeyword . Library )
throw new IncludeNamespaceInUnit ( CurrentCompilationUnit . SyntaxTree . file_name , CurrentCompilationUnit . SyntaxTree . source_context ) ;
var directives = ConvertDirectives ( Unit . SyntaxTree ) ;
SyntaxTree . unit_module main_library = Unit . SyntaxTree as SyntaxTree . unit_module ;
SyntaxTree . program_module main_program = Unit . SyntaxTree as SyntaxTree . program_module ;
List < string > files = new List < string > ( ) ;
foreach ( TreeRealization . compiler_directive cd in directives )
{
if ( cd . name . ToLower ( ) = = TreeConverter . compiler_string_consts . include_namespace_directive )
{
string directive = cd . directive . Replace ( '/' , Path . DirectorySeparatorChar ) . Replace ( '\\' , Path . DirectorySeparatorChar ) ;
if ( directive = = "*.pas" | | directive . EndsWith ( Path . DirectorySeparatorChar + "*.pas" ) )
{
string dir = Path . Combine ( Path . GetDirectoryName ( Unit . SyntaxTree . file_name ) , directive . Replace ( Path . DirectorySeparatorChar + "*.pas" , "" ) ) ;
foreach ( string file in Directory . EnumerateFiles ( dir , "*.pas" ) )
{
if ( ! File . Exists ( file ) )
throw new FileNotFound ( file , cd . location ) ;
files . Add ( file ) ;
}
}
else
{
string file = Path . Combine ( Path . GetDirectoryName ( Unit . SyntaxTree . file_name ) , directive ) ;
if ( ! File . Exists ( file ) )
throw new FileNotFound ( file , cd . location ) ;
files . Add ( file ) ;
}
}
}
Dictionary < string , SyntaxTree . syntax_namespace_node > namespaces = new Dictionary < string , SyntaxTree . syntax_namespace_node > ( StringComparer . OrdinalIgnoreCase ) ;
List < SyntaxTree . unit_or_namespace > namespace_modules = new List < SyntaxTree . unit_or_namespace > ( ) ;
foreach ( string file in files )
{
SyntaxTree . compilation_unit tree = GetNamespaceSyntaxTree ( file ) ;
if ( ! ( tree is SyntaxTree . unit_module ) )
throw new NamespaceModuleExpected ( tree . source_context ) ;
SyntaxTree . unit_module unit = tree as SyntaxTree . unit_module ;
if ( unit . unit_name . HeaderKeyword ! = SyntaxTree . UnitHeaderKeyword . Namespace )
throw new NamespaceModuleExpected ( unit . unit_name . source_context ) ;
if ( unit . implementation_part ! = null )
throw new NamespaceModuleExpected ( unit . implementation_part . source_context ) ;
if ( unit . finalization_part ! = null )
throw new NamespaceModuleExpected ( unit . finalization_part . source_context ) ;
if ( unit . initialization_part ! = null & & unit . initialization_part . list . Count > 0 )
throw new NamespaceModuleExpected ( unit . initialization_part . source_context ) ;
SyntaxTree . syntax_namespace_node ns = null ;
if ( ! namespaces . TryGetValue ( unit . unit_name . idunit_name . name , out ns ) )
{
ns = new SyntaxTree . syntax_namespace_node ( unit . unit_name . idunit_name . name ) ;
ns . referenced_units = new TreeRealization . unit_node_list ( ) ;
namespaces [ unit . unit_name . idunit_name . name ] = ns ;
}
if ( unit . interface_part . interface_definitions ! = null )
{
foreach ( SyntaxTree . declaration decl in unit . interface_part . interface_definitions . defs )
{
ns . defs . Add ( decl ) ;
}
if ( unit . interface_part . uses_modules ! = null )
{
checkDuplicateUsesUnit ( unit . interface_part . uses_modules . units ) ;
foreach ( SyntaxTree . unit_or_namespace name_space in unit . interface_part . uses_modules . units )
{
if ( IsPossibleNamespace ( name_space , false , Path . GetDirectoryName ( file ) ) )
{
2020-10-11 21:20:44 +03:00
ns . referenced_units . AddElement ( new TreeRealization . namespace_unit_node ( GetNamespace ( name_space ) , get_location_from_treenode ( name_space , tree . file_name ) ) , null ) ;
2020-07-09 05:54:55 +03:00
}
else
{
namespace_modules . Add ( name_space ) ;
}
}
}
}
}
foreach ( string s in namespaces . Keys )
{
if ( main_library ! = null )
main_library . interface_part . interface_definitions . Insert ( 0 , namespaces [ s ] ) ;
else
main_program . program_block . defs . Insert ( 0 , namespaces [ s ] ) ;
}
SyntaxTree . uses_list main_uses = null ;
if ( main_library ! = null )
{
if ( main_library . interface_part . uses_modules ! = null )
main_uses = main_library . interface_part . uses_modules ;
}
else if ( main_program . used_units ! = null )
main_uses = main_program . used_units ;
if ( main_uses = = null )
main_uses = new SyntaxTree . uses_list ( ) ;
Dictionary < string , string > dict = new Dictionary < string , string > ( ) ;
foreach ( SyntaxTree . unit_or_namespace name_space in namespace_modules )
{
string name = SyntaxTree . Utils . IdentListToString ( name_space . name . idents , "." ) . ToLower ( ) ;
if ( ! dict . ContainsKey ( name ) )
{
main_uses . Add ( name_space ) ;
dict . Add ( name , name ) ;
}
}
if ( main_library ! = null )
main_library . interface_part . uses_modules = main_uses ;
else
main_program . used_units = main_uses ;
return namespaces ;
}
private SyntaxTree . compilation_unit GetNamespaceSyntaxTree ( string FileName )
{
string SourceText = GetSourceFileText ( FileName ) ;
List < string > DefinesList = new List < string > ( ) ;
2020-07-11 21:45:38 +03:00
DefinesList . Add ( "PASCALABC" ) ; // SSM 11/07/20
2020-07-09 05:54:55 +03:00
if ( ! compilerOptions . Debug & & ! compilerOptions . ForDebugging )
DefinesList . Add ( "RELEASE" ) ;
else
DefinesList . Add ( "DEBUG" ) ;
2021-11-17 17:10:37 +03:00
DefinesList . AddRange ( CompilerOptions . ForceDefines ) ;
2020-07-09 05:54:55 +03:00
SyntaxTree . compilation_unit SyntaxTree = InternalParseText ( FileName , SourceText , errorsList , warnings , DefinesList ) ;
if ( errorsList . Count > 0 )
throw errorsList [ 0 ] ;
SyntaxTree = syntaxTreeConvertersController . Convert ( SyntaxTree ) as SyntaxTree . compilation_unit ;
return SyntaxTree ;
}
public TreeRealization . unit_node_list GetReferences ( CompilationUnit Unit )
{
//TODO переделать, ConvertDirectives определена дважды и вызывается дважды!
TreeRealization . unit_node_list res = new TreeRealization . unit_node_list ( ) ;
List < TreeRealization . compiler_directive > directives ;
if ( Unit . SemanticTree is TreeRealization . common_unit_node )
directives = ( Unit . SemanticTree as TreeRealization . common_unit_node ) . compiler_directives ;
else
directives = ConvertDirectives ( Unit . SyntaxTree ) ;
2020-12-24 17:07:20 +03:00
foreach ( TreeRealization . compiler_directive cd in directives )
{
if ( cd . name . ToLower ( ) = = TreeConverter . compiler_string_consts . compiler_directive_platformtarget & & ! string . IsNullOrEmpty ( cd . directive ) & & cd . directive . IndexOf ( "dotnet5" ) ! = - 1 )
CompilerOptions . UseDllForSystemUnits = false ;
}
2020-07-09 05:54:55 +03:00
if ( CompilerOptions . UseDllForSystemUnits )
{
2020-11-22 23:55:28 +03:00
directives . Add ( new TreeRealization . compiler_directive ( "reference" , "%GAC%\\PABCRtl.dll" , null , "." ) ) ;
directives . Add ( new TreeRealization . compiler_directive ( "reference" , "%GAC%\\mscorlib.dll" , null , "." ) ) ;
directives . Add ( new TreeRealization . compiler_directive ( "reference" , "%GAC%\\System.dll" , null , "." ) ) ;
directives . Add ( new TreeRealization . compiler_directive ( "reference" , "%GAC%\\System.Core.dll" , null , "." ) ) ;
directives . Add ( new TreeRealization . compiler_directive ( "reference" , "%GAC%\\System.Numerics.dll" , null , "." ) ) ;
directives . Add ( new TreeRealization . compiler_directive ( "reference" , "%GAC%\\System.Windows.Forms.dll" , null , "." ) ) ;
directives . Add ( new TreeRealization . compiler_directive ( "reference" , "%GAC%\\System.Drawing.dll" , null , "." ) ) ;
2020-07-09 05:54:55 +03:00
if ( Unit . SyntaxTree is SyntaxTree . program_module & & ( Unit . SyntaxTree as SyntaxTree . program_module ) . used_units ! = null )
foreach ( SyntaxTree . unit_or_namespace uui in ( Unit . SyntaxTree as SyntaxTree . program_module ) . used_units . units )
{
if ( uui . name . ToString ( ) = = "Graph3D" )
{
2020-11-22 23:55:28 +03:00
directives . Add ( new TreeRealization . compiler_directive ( "reference" , "%GAC%\\PresentationFramework.dll" , null , "." ) ) ;
directives . Add ( new TreeRealization . compiler_directive ( "reference" , "%GAC%\\WindowsBase.dll" , null , "." ) ) ;
directives . Add ( new TreeRealization . compiler_directive ( "reference" , "%GAC%\\PresentationCore.dll" , null , "." ) ) ;
directives . Add ( new TreeRealization . compiler_directive ( "reference" , "%GAC%\\HelixToolkit.Wpf.dll" , null , "." ) ) ;
directives . Add ( new TreeRealization . compiler_directive ( "reference" , "%GAC%\\HelixToolkit.dll" , null , "." ) ) ;
2020-07-09 05:54:55 +03:00
}
}
2020-12-24 17:07:20 +03:00
2020-07-09 05:54:55 +03:00
}
foreach ( TreeRealization . compiler_directive cd in directives )
{
if ( cd . name . ToLower ( ) = = TreeConverter . compiler_string_consts . compiler_directive_reference )
{
if ( string . IsNullOrEmpty ( cd . directive ) )
throw new TreeConverter . SimpleSemanticError ( cd . location , "EXPECTED_ASSEMBLY_NAME" ) ;
else
CompileReference ( res , cd ) ;
}
}
if ( CompilerOptions . ProjectCompiled )
{
foreach ( ReferenceInfo ri in project . references )
{
2020-11-22 23:55:28 +03:00
CompileReference ( res , new TreeRealization . compiler_directive ( "reference" , ri . full_assembly_name , null , project . MainFile ) ) ;
2020-07-09 05:54:55 +03:00
}
}
return res ;
}
private bool IsPossibleNamespace ( SyntaxTree . unit_or_namespace name_space , bool add_to_standard_modules , string curr_path )
{
if ( name_space is SyntaxTree . uses_unit_in )
return false ;
if ( name_space . name . idents . Count > 1 )
return true ;
2020-07-17 01:58:34 +03:00
string src = FindSourceFileName ( name_space . name . idents [ 0 ] . name , curr_path , out _ ) ;
string pcu = FindPCUFileName ( name_space . name . idents [ 0 ] . name , curr_path , out _ ) ;
2020-07-09 05:54:55 +03:00
if ( src = = null & & pcu = = null )
return true ;
if ( CompilerOptions . UseDllForSystemUnits & & src ! = null & & string . Compare ( Path . GetDirectoryName ( src ) , Path . Combine ( CompilerOptions . SystemDirectory , "Lib" ) , true ) = = 0
& & string . Compare ( Path . GetFileNameWithoutExtension ( src ) , "PT4" , true ) ! = 0
& & string . Compare ( Path . GetFileNameWithoutExtension ( src ) , "CRT" , true ) ! = 0
& & string . Compare ( Path . GetFileNameWithoutExtension ( src ) , "Arrays" , true ) ! = 0
//&& string.Compare(Path.GetFileNameWithoutExtension(src), "FormsABC", true) != 0
& & string . Compare ( Path . GetFileNameWithoutExtension ( src ) , "MPI" , true ) ! = 0
& & string . Compare ( Path . GetFileNameWithoutExtension ( src ) , "LibForHaskell" , true ) ! = 0
& & string . Compare ( Path . GetFileNameWithoutExtension ( src ) , "Collections" , true ) ! = 0
& & string . Compare ( Path . GetFileNameWithoutExtension ( src ) , "Core" , true ) ! = 0
& & string . Compare ( Path . GetFileNameWithoutExtension ( src ) , "Oberon00System" , true ) ! = 0 )
{
string s = Path . GetFileNameWithoutExtension ( src ) . ToLower ( ) ;
if ( add_to_standard_modules & & ! StandarModules . Contains ( s ) )
StandarModules . Add ( s ) ;
return true ;
}
if ( CompilerOptions . UseDllForSystemUnits & & pcu ! = null & & string . Compare ( Path . GetDirectoryName ( pcu ) , Path . Combine ( CompilerOptions . SystemDirectory , "Lib" ) , true ) = = 0
& & string . Compare ( Path . GetFileNameWithoutExtension ( pcu ) , "PT4" , true ) ! = 0
& & string . Compare ( Path . GetFileNameWithoutExtension ( pcu ) , "CRT" , true ) ! = 0
& & string . Compare ( Path . GetFileNameWithoutExtension ( pcu ) , "Arrays" , true ) ! = 0
//&& string.Compare(Path.GetFileNameWithoutExtension(pcu), "FormsABC", true) != 0
& & string . Compare ( Path . GetFileNameWithoutExtension ( pcu ) , "MPI" , true ) ! = 0
& & string . Compare ( Path . GetFileNameWithoutExtension ( pcu ) , "LibForHaskell" , true ) ! = 0
& & string . Compare ( Path . GetFileNameWithoutExtension ( pcu ) , "Collections" , true ) ! = 0
& & string . Compare ( Path . GetFileNameWithoutExtension ( pcu ) , "Core" , true ) ! = 0
& & string . Compare ( Path . GetFileNameWithoutExtension ( pcu ) , "Oberon00System" , true ) ! = 0
)
{
string s = Path . GetFileNameWithoutExtension ( pcu ) . ToLower ( ) ;
if ( add_to_standard_modules & & ! StandarModules . Contains ( s ) )
StandarModules . Add ( s ) ;
return true ;
}
return false ;
}
public TreeRealization . using_namespace GetNamespace ( SyntaxTree . unit_or_namespace _name_space )
{
return new TreeRealization . using_namespace ( SyntaxTree . Utils . IdentListToString ( _name_space . name . idents , "." ) ) ;
}
private TreeRealization . using_namespace GetNamespace ( TreeRealization . using_namespace_list using_list , string full_namespace_name , SyntaxTree . unit_or_namespace _name_space , bool possible_is_unit , Dictionary < string , SyntaxTree . syntax_namespace_node > pabc_namespaces )
{
if ( ! NetHelper . NetHelper . NamespaceExists ( full_namespace_name ) & & ! ( pabc_namespaces ! = null & & pabc_namespaces . ContainsKey ( full_namespace_name ) ) )
{
if ( possible_is_unit )
if ( ! full_namespace_name . Contains ( "." ) )
throw new UnitNotFound ( CurrentCompilationUnit . SyntaxTree . file_name , full_namespace_name , _name_space . source_context ) ;
throw new TreeConverter . NamespaceNotFound ( full_namespace_name , get_location_from_treenode ( _name_space . name , CurrentCompilationUnit . SyntaxTree . file_name ) ) ;
}
return new TreeRealization . using_namespace ( full_namespace_name ) ;
}
public void AddNamespaces ( TreeRealization . using_namespace_list using_list , List < SyntaxTree . unit_or_namespace > namespaces , bool possible_is_units , Dictionary < string , SyntaxTree . syntax_namespace_node > pabc_namespaces )
{
foreach ( SyntaxTree . unit_or_namespace ns in namespaces )
using_list . AddElement ( GetNamespace ( using_list , SyntaxTree . Utils . IdentListToString ( ns . name . idents , "." ) , ns , possible_is_units , pabc_namespaces ) ) ;
}
public void AddNamespaces ( TreeRealization . using_namespace_list using_list , SyntaxTree . using_list ul )
{
if ( ul ! = null )
AddNamespaces ( using_list , ul . namespaces , false , null ) ;
}
public SyntaxTree . using_list GetInterfaceSyntaxUsingList ( SyntaxTree . compilation_unit cu )
{
if ( cu is SyntaxTree . unit_module )
return ( cu as SyntaxTree . unit_module ) . interface_part . using_namespaces ;
if ( cu is SyntaxTree . program_module )
return ( cu as SyntaxTree . program_module ) . using_namespaces ;
return null ;
}
private SyntaxTree . using_list GetImplementationSyntaxUsingList ( SyntaxTree . compilation_unit cu )
{
if ( cu is SyntaxTree . unit_module )
if ( ( cu as SyntaxTree . unit_module ) . implementation_part ! = null )
return ( cu as SyntaxTree . unit_module ) . implementation_part . using_namespaces ;
return null ;
}
public string GetSourceFileText ( string FileName )
{
return ( string ) SourceFilesProvider ( FileName , SourceFileOperation . GetText ) ;
}
public SyntaxTree . compilation_unit ParseText ( string FileName , string Text , List < Error > ErrorList , List < CompilerWarning > Warnings )
{
Reset ( ) ;
OnChangeCompilerState ( this , CompilerState . CompilationStarting , FileName ) ;
SyntaxTree . compilation_unit cu = InternalParseText ( FileName , Text , ErrorsList , Warnings ) ;
OnChangeCompilerState ( this , CompilerState . Ready , FileName ) ;
return cu ;
}
private SyntaxTree . compilation_unit InternalParseText ( string FileName , string Text , List < Error > ErrorList , List < CompilerWarning > Warnings , List < string > DefinesList = null )
{
OnChangeCompilerState ( this , CompilerState . BeginParsingFile , FileName ) ;
SyntaxTree . compilation_unit cu = ParsersController . GetCompilationUnit ( FileName , Text , ErrorsList , Warnings , DefinesList ) ;
OnChangeCompilerState ( this , CompilerState . EndParsingFile , FileName ) ;
//Вычисляем сколько строк скомпилировали
if ( ErrorList . Count = = 0 & & cu ! = null & & cu . source_context ! = null )
2020-09-19 23:45:19 +03:00
{
2020-07-09 05:54:55 +03:00
linesCompiled + = ( uint ) ( cu . source_context . end_position . line_num - cu . source_context . begin_position . line_num + 1 ) ;
2020-09-19 23:45:19 +03:00
// 500 - это наибольшая программа для начинающих. БОльшая программа - здоровье кода только по кнопке (чтобы не замедлять)
if ( linesCompiled < = 500 )
{
// Это только для локального компилятора?
var stat = new SyntaxVisitors . ABCStatisticsVisitor ( ) ;
stat . ProcessNode ( cu ) ;
pABCCodeHealth = stat . CalcHealth ( out int neg , out int pos ) ;
}
}
2020-07-09 05:54:55 +03:00
return cu ;
}
/ * private bool check_for_library ( List < compiler_directive > directives )
{
foreach ( compiler_directive cd in directives )
{
if ( string . Compare ( cd . name , "apptype" ) = = 0 & & string . Compare ( cd . directive , "dll" ) = = 0 )
return true ;
}
return false ;
} * /
public static bool is_dll ( SyntaxTree . compilation_unit cu )
{
foreach ( SyntaxTree . compiler_directive cd in cu . compiler_directives )
if ( string . Compare ( cd . Name . text , "apptype" , true ) = = 0 & & string . Compare ( cd . Directive . text , "dll" , true ) = = 0 )
return true ;
return false ;
}
2020-10-11 21:20:44 +03:00
public CompilationUnit CompileUnit ( PascalABCCompiler . TreeRealization . unit_node_list Units , Dictionary < unit_node , CompilationUnit > DirectCompilationUnits , SyntaxTree . unit_or_namespace SyntaxUsesUnit , string prev_path )
2020-07-09 05:54:55 +03:00
{
2021-01-06 00:47:18 +03:00
string UnitFileName = GetUnitFileName ( SyntaxUsesUnit , prev_path ) ;
string UnitId = Path . ChangeExtension ( UnitFileName , null ) ;
2020-12-11 12:17:25 +03:00
// Имя папки, в которой лежит текущий модуль
// Используется для подключения модулей, $include и т.п. из модуля, подключённого с uses-in
2021-01-06 00:47:18 +03:00
var curr_path = Path . GetDirectoryName ( UnitFileName ) ;
2020-07-09 05:54:55 +03:00
2021-01-06 00:47:18 +03:00
CompilationUnit CurrentUnit = UnitTable [ UnitId ] ;
2020-07-09 05:54:55 +03:00
if ( CurrentUnit ! = null & & CurrentUnit . SemanticTree is PascalABCCompiler . TreeRealization . dot_net_unit_node
& & SyntaxUsesUnit is PascalABCCompiler . SyntaxTree . uses_unit_in ui & & ui . in_file ! = null ) // значит, это пространство имен и секция in у него должна отсутствовать
{
ErrorsList . Add ( new NamespaceCannotHaveInSection ( ui . in_file . source_context ) ) ;
}
if ( CurrentUnit ! = null )
if ( CurrentUnit . State ! = UnitState . BeginCompilation | | CurrentUnit . SemanticTree ! = null ) //ИЗБАВИТЬСЯ О Т ВТОРОГО УСЛОВИЯ
{
2020-10-11 21:20:44 +03:00
if ( Units . AddElement ( CurrentUnit . SemanticTree , SyntaxUsesUnit . UsesPath ( ) ) )
DirectCompilationUnits . Add ( CurrentUnit . SemanticTree , CurrentUnit ) ;
2020-07-09 05:54:55 +03:00
Units . AddRange ( GetReferences ( CurrentUnit ) ) ;
return CurrentUnit ;
}
2021-01-06 00:47:18 +03:00
if ( CurrentUnit = = null & & Path . GetExtension ( UnitFileName ) . ToLower ( ) = = CompilerOptions . CompiledUnitExtension )
if ( File . Exists ( UnitFileName ) )
2020-07-09 05:54:55 +03:00
{
2021-01-06 00:47:18 +03:00
if ( UnitTable . Count = = 0 ) throw new ProgramModuleExpected ( UnitFileName , null ) ;
2020-07-09 05:54:55 +03:00
try
{
2021-01-06 00:47:18 +03:00
if ( ( CurrentUnit = ReadPCU ( UnitFileName ) ) ! = null )
2020-07-09 05:54:55 +03:00
{
2020-10-11 21:20:44 +03:00
if ( Units . AddElement ( CurrentUnit . SemanticTree , SyntaxUsesUnit . UsesPath ( ) ) )
DirectCompilationUnits . Add ( CurrentUnit . SemanticTree , CurrentUnit ) ;
2020-07-09 05:54:55 +03:00
Units . AddRange ( GetReferences ( CurrentUnit ) ) ;
2021-01-06 00:47:18 +03:00
UnitTable [ UnitId ] = CurrentUnit ;
2020-07-09 05:54:55 +03:00
return CurrentUnit ;
}
}
catch ( InvalidPCUFule )
{
//Перекомпилируем....
}
catch ( Error )
{
throw ;
}
catch ( Exception e )
{
2021-01-06 00:47:18 +03:00
OnChangeCompilerState ( this , CompilerState . PCUReadingError , UnitFileName ) ;
2020-07-09 05:54:55 +03:00
#if DEBUG
if ( ! InternalDebug . SkipPCUErrors )
throw new Errors . CompilerInternalError ( "PCUReader" , e ) ;
#endif
}
2021-01-06 00:47:18 +03:00
string SourceFileName = FindSourceFileName ( Path . ChangeExtension ( UnitFileName , null ) , null , out _ ) ;
2020-07-09 05:54:55 +03:00
if ( SourceFileName = = null )
2021-01-06 00:47:18 +03:00
throw new ReadPCUError ( UnitFileName ) ;
2020-07-09 05:54:55 +03:00
else
2021-01-06 00:47:18 +03:00
UnitFileName = SourceFileName ;
2020-07-09 05:54:55 +03:00
}
string SourceText = null ;
Dictionary < SyntaxTree . syntax_tree_node , string > docs = null ;
if ( CurrentUnit = = null )
{
CurrentUnit = new CompilationUnit ( ) ;
if ( FirstCompilationUnit = = null )
FirstCompilationUnit = CurrentUnit ;
2021-01-06 00:47:18 +03:00
OnChangeCompilerState ( this , CompilerState . BeginCompileFile , UnitFileName ) ;
2021-09-06 21:37:31 +03:00
if ( compilerOptions . UnitSyntaxTree = = null )
{
SourceText = GetSourceFileText ( UnitFileName ) ;
if ( SourceText = = null )
if ( CurrentUnit = = FirstCompilationUnit )
throw new SourceFileNotFound ( UnitFileName ) ;
else
throw new UnitNotFound ( CurrentCompilationUnit . SyntaxTree . file_name , UnitFileName , SyntaxUsesUnit . source_context ) ;
}
2020-07-09 05:54:55 +03:00
List < string > DefinesList = new List < string > ( ) ;
2020-07-11 21:45:38 +03:00
DefinesList . Add ( "PASCALABC" ) ;
2020-07-09 05:54:55 +03:00
if ( ! compilerOptions . Debug & & ! compilerOptions . ForDebugging )
DefinesList . Add ( "RELEASE" ) ;
else
DefinesList . Add ( "DEBUG" ) ;
2021-11-17 17:10:37 +03:00
DefinesList . AddRange ( CompilerOptions . ForceDefines ) ;
2021-09-06 21:37:31 +03:00
if ( compilerOptions . UnitSyntaxTree ! = null )
{
CurrentUnit . SyntaxTree = compilerOptions . UnitSyntaxTree ;
compilerOptions . UnitSyntaxTree = null ;
}
else
CurrentUnit . SyntaxTree = InternalParseText ( UnitFileName , SourceText , errorsList , warnings , DefinesList ) ;
2020-07-09 05:54:55 +03:00
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 )
{
if ( ( CurrentUnit . SyntaxTree as SyntaxTree . unit_module ) . unit_name . HeaderKeyword = = SyntaxTree . UnitHeaderKeyword . Namespace )
throw new NamespacesCanBeCompiledOnlyInProjects ( CurrentUnit . SyntaxTree . source_context ) ;
compilerOptions . UseDllForSystemUnits = false ;
}
// SSM 21/05/20 Проверка, что мы не записали apptype dll в небиблиотеку
var ccu = CurrentUnit . SyntaxTree ;
2022-06-10 07:07:24 +03:00
// !!!!!!!!!!!!!!!!!!!!!!
if ( ccu ! = null ) // SSM 06.06.22 - здесь была ошибка - ccu может быть null и тогда исключение!!! Добавил if
foreach ( SyntaxTree . compiler_directive cd in ccu . compiler_directives )
2020-07-09 05:54:55 +03:00
if ( string . Compare ( cd . Name . text , "apptype" , true ) = = 0 & & string . Compare ( cd . Directive . text , "dll" , true ) = = 0 )
{
if ( ! ( ccu is SyntaxTree . unit_module ) | |
( ccu is SyntaxTree . unit_module um & & um . unit_name . HeaderKeyword ! = SyntaxTree . UnitHeaderKeyword . Library ) )
{
ErrorsList . Add ( new AppTypeDllIsAllowedOnlyForLibraries ( ccu . file_name , cd . source_context ) ) ;
break ;
}
}
//
if ( is_dll ( CurrentUnit . SyntaxTree ) )
compilerOptions . OutputFileType = PascalABCCompiler . CompilerOptions . OutputType . ClassLibrary ;
2021-09-06 21:37:31 +03:00
if ( ParsersController . LastParser ! = null )
CurrentUnit . CaseSensitive = ParsersController . LastParser . CaseSensitive ;
2020-07-09 05:54:55 +03:00
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 ] ;
}
2021-01-06 00:47:18 +03:00
UnitTable [ UnitId ] = CurrentUnit ;
2020-07-09 05:54:55 +03:00
if ( UnitTable . Count > 1 ) //если это не главный модуль
if ( CurrentUnit . SyntaxTree is SyntaxTree . program_module )
2021-01-06 00:47:18 +03:00
throw new UnitModuleExpected ( UnitFileName , CurrentUnit . SyntaxTree . source_context . LeftSourceContext ) ;
2020-07-09 05:54:55 +03:00
else if ( is_dll ( CurrentUnit . SyntaxTree ) )
2021-01-06 00:47:18 +03:00
throw new UnitModuleExpectedLibraryFound ( UnitFileName , CurrentUnit . SyntaxTree . source_context . LeftSourceContext ) ;
2020-07-09 05:54:55 +03:00
//здесь в начало 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 , curr_path ) )
{
compilerOptions . UseDllForSystemUnits = false ;
break ;
}
}
}
TreeRealization . unit_node_list References = GetReferences ( CurrentUnit ) ;
var namespaces = IncludeNamespaces ( CurrentUnit ) ;
if ( SyntaxUsesList ! = null )
{
for ( int i = SyntaxUsesList . Count - 1 - CurrentUnit . InterfaceUsedUnits . Count ; i > = 0 ; i - - )
{
if ( IsPossibleNamespace ( SyntaxUsesList [ i ] , true , curr_path ) | | namespaces . ContainsKey ( SyntaxUsesList [ i ] . name . idents [ 0 ] . name ) )
{
2020-10-11 21:20:44 +03:00
CurrentUnit . InterfaceUsedUnits . AddElement ( new TreeRealization . namespace_unit_node ( GetNamespace ( SyntaxUsesList [ i ] ) ) , null ) ;
2020-07-09 05:54:55 +03:00
CurrentUnit . PossibleNamespaces . Add ( SyntaxUsesList [ i ] ) ;
}
else
{
2021-01-06 00:47:18 +03:00
var CurrentSyntaxUnitFileName = GetUnitFileName ( SyntaxUsesList [ i ] , curr_path ) ;
var CurrentSyntaxUnitId = Path . ChangeExtension ( CurrentSyntaxUnitFileName , null ) ;
CurrentUnit . CurrentUsesUnitId = CurrentSyntaxUnitId ;
if ( UnitTable [ CurrentSyntaxUnitId ] ! = null )
if ( UnitTable [ CurrentSyntaxUnitId ] . State = = UnitState . BeginCompilation )
2020-07-09 05:54:55 +03:00
{
2021-01-06 00:47:18 +03:00
string CurrentSyntaxUnit_CurrentUsesUnitId = UnitTable [ CurrentSyntaxUnitId ] . CurrentUsesUnitId ;
if ( CurrentSyntaxUnit_CurrentUsesUnitId ! = null )
2020-07-09 05:54:55 +03:00
{
2021-01-06 00:47:18 +03:00
//если сначало взяли pcu а потом решили е г о перекомпилировать, поэтому в таблице е г о нет
if ( UnitTable [ CurrentSyntaxUnit_CurrentUsesUnitId ] = = null )
UnitTable [ CurrentSyntaxUnitId ] . CurrentUsesUnitId = CurrentSyntaxUnit_CurrentUsesUnitId ;
2020-07-09 05:54:55 +03:00
//далее финальная поверка на зацикливание
2021-01-06 00:47:18 +03:00
if ( UnitTable [ CurrentSyntaxUnitId ] . CurrentUsesUnitId ! = null & & UnitTable [ UnitTable [ CurrentSyntaxUnitId ] . CurrentUsesUnitId ] . State = = UnitState . BeginCompilation )
throw new CycleUnitReference ( UnitFileName , SyntaxUsesList [ i ] ) ;
2020-07-09 05:54:55 +03:00
}
}
2020-10-11 21:20:44 +03:00
CompileUnit ( CurrentUnit . InterfaceUsedUnits , CurrentUnit . DirectInterfaceCompilationUnits , SyntaxUsesList [ i ] , curr_path ) ;
2020-07-09 05:54:55 +03:00
if ( CurrentUnit . State = = UnitState . Compiled )
{
2020-10-11 21:20:44 +03:00
if ( Units . AddElement ( CurrentUnit . SemanticTree , SyntaxUsesUnit . UsesPath ( ) ) )
DirectCompilationUnits . Add ( CurrentUnit . SemanticTree , CurrentUnit ) ;
2020-07-09 05:54:55 +03:00
Units . AddRange ( References ) ;
return CurrentUnit ;
}
}
}
}
CurrentCompilationUnit = CurrentUnit ;
CurrentUnit . InterfaceUsedUnits . AddRange ( References ) ;
AddNamespaces ( CurrentUnit . InterfaceUsingNamespaceList , CurrentUnit . PossibleNamespaces , true , namespaces ) ;
AddNamespaces ( CurrentUnit . InterfaceUsingNamespaceList , GetInterfaceSyntaxUsingList ( CurrentUnit . SyntaxTree ) ) ;
//Console.WriteLine("Compile Interface "+UnitName);//DEBUG
#if DEBUG
if ( InternalDebug . SemanticAnalysis )
#endif
{
if ( CurrentUnit . State ! = UnitState . InterfaceCompiled )
{
2021-01-06 00:47:18 +03:00
OnChangeCompilerState ( this , CompilerState . CompileInterface , UnitFileName ) ;
2020-07-09 05:54:55 +03:00
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 ,
2021-09-06 21:37:31 +03:00
CompilerOptions . ForDebugging ,
CompilerOptions . ForIntellisense ,
CompiledVariables
2020-07-09 05:54:55 +03:00
) ;
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 )
{
2020-10-11 21:20:44 +03:00
if ( Units . AddElement ( CurrentUnit . SemanticTree , SyntaxUsesUnit . UsesPath ( ) ) )
DirectCompilationUnits . Add ( CurrentUnit . SemanticTree , CurrentUnit ) ;
2020-07-09 05:54:55 +03:00
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 , curr_path ) )
{
2021-01-06 00:47:18 +03:00
cu = UnitTable [ Path . ChangeExtension ( GetUnitFileName ( SyntaxUsesList [ i ] , curr_path ) , null ) ] ;
2020-07-09 05:54:55 +03:00
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
{
2020-10-11 21:20:44 +03:00
CompileUnit ( CurrentUnit . ImplementationUsedUnits , CurrentUnit . DirectImplementationCompilationUnits , SyntaxUsesList [ i ] , curr_path ) ;
2020-07-09 05:54:55 +03:00
}
}
else
{
2020-10-11 21:20:44 +03:00
CurrentUnit . ImplementationUsedUnits . AddElement ( new TreeRealization . namespace_unit_node ( GetNamespace ( SyntaxUsesList [ i ] ) ) , null ) ;
2020-07-09 05:54:55 +03:00
CurrentUnit . PossibleNamespaces . Add ( SyntaxUsesList [ i ] ) ;
}
}
CurrentCompilationUnit = CurrentUnit ;
AddNamespaces ( CurrentUnit . ImplementationUsingNamespaceList , CurrentUnit . PossibleNamespaces , true , namespaces ) ;
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
{
2021-01-06 00:47:18 +03:00
OnChangeCompilerState ( this , CompilerState . CompileImplementation , UnitFileName ) ;
2020-07-09 05:54:55 +03:00
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 ,
2021-09-06 21:37:31 +03:00
CompilerOptions . ForDebugging ,
CompilerOptions . ForIntellisense ,
CompiledVariables
2020-07-09 05:54:55 +03:00
) ;
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 ) ;
}
2021-01-06 00:47:18 +03:00
OnChangeCompilerState ( this , CompilerState . EndCompileFile , UnitFileName ) ;
2020-07-09 05:54:55 +03:00
//SavePCU(CurrentUnit, UnitName);
2021-01-06 00:47:18 +03:00
CurrentUnit . UnitFileName = UnitFileName ;
2020-07-09 05:54:55 +03:00
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 Dictionary < SyntaxTree . syntax_tree_node , string > AddDocumentationToNodes ( SyntaxTree . compilation_unit cu , string Text )
{
List < PascalABCCompiler . Errors . Error > errors = new List < PascalABCCompiler . Errors . Error > ( ) ;
List < PascalABCCompiler . Errors . CompilerWarning > warnings = new List < CompilerWarning > ( ) ;
string doctagsParserExtension = Path . GetExtension ( cu . file_name ) + "dt" + PascalABCCompiler . Parsers . Controller . HideParserExtensionPostfixChar ;
PascalABCCompiler . SyntaxTree . documentation_comment_list dt = ParsersController . Compile ( System . IO . Path . ChangeExtension ( cu . file_name , doctagsParserExtension ) , Text , errors , warnings , PascalABCCompiler . Parsers . ParseMode . Normal ) as PascalABCCompiler . SyntaxTree . documentation_comment_list ;
if ( errors . Count > 0 ) return null ;
PascalABCCompiler . DocumentationConstructor docconst = new PascalABCCompiler . DocumentationConstructor ( ) ;
return docconst . Construct ( cu , dt ) ;
}
private bool need_gen_doc ( SyntaxTree . compilation_unit cu )
{
if ( project ! = null & & project . generate_xml_doc )
return true ;
if ( cu = = null )
return false ;
if ( cu . file_name ! = null & & internalDebug . DocumentedUnits . Contains ( cu . file_name . ToLower ( ) ) )
return true ;
foreach ( SyntaxTree . compiler_directive cd in cu . compiler_directives )
if ( string . Compare ( cd . Name . text , "gendoc" , true ) = = 0 & & string . Compare ( cd . Directive . text , "true" , true ) = = 0 )
return true ;
return false ;
}
private TreeRealization . unit_node_list buildImplementationUsesList ( CompilationUnit cu )
{
TreeRealization . unit_node_list unl = new PascalABCCompiler . TreeRealization . unit_node_list ( ) ;
unl . AddRange ( cu . ImplementationUsedUnits ) ;
foreach ( TreeRealization . unit_node un in cu . InterfaceUsedUnits )
{
if ( un is TreeRealization . dot_net_unit_node )
2020-10-11 21:20:44 +03:00
unl . AddElement ( un , null ) ;
2020-07-09 05:54:55 +03:00
}
return unl ;
}
2020-07-17 06:22:30 +03:00
public void SavePCU ( CompilationUnit Unit )
2020-07-09 05:54:55 +03:00
{
//#if DEBUG
try
{
if ( Unit . SyntaxTree ! = null & & Unit . SyntaxTree is SyntaxTree . unit_module )
{
if ( ( ( SyntaxTree . unit_module ) Unit . SyntaxTree ) . unit_name . HeaderKeyword = = PascalABCCompiler . SyntaxTree . UnitHeaderKeyword . Library )
return ;
foreach ( SyntaxTree . compiler_directive cd in Unit . SyntaxTree . compiler_directives )
if ( cd . Name . text . ToLower ( ) = = TreeConverter . compiler_string_consts . compiler_savepcu )
if ( ! Convert . ToBoolean ( cd . Directive . text ) )
return ;
}
}
catch
{
}
//#endif
PCUWriter writer = null ;
try
{
#if DEBUG
if ( InternalDebug . PCUGenerate )
#endif
if ( compilerOptions . SavePCU )
if ( ( Unit . SemanticTree as TreeRealization . common_unit_node ) . namespaces . Count > 1 & &
Unit . SyntaxTree ! = null & &
Unit . State = = UnitState . Compiled )
{
writer = new PCUWriter ( this , pr_ChangeState ) ;
bool dbginfo = true ; /*CompilerOptions.Debug*/
#if DEBUG
dbginfo = InternalDebug . IncludeDebugInfoInPCU ;
#endif
2020-07-17 06:22:30 +03:00
2021-01-06 00:47:18 +03:00
writer . SaveSemanticTree ( Unit , Path . ChangeExtension ( Unit . UnitFileName , CompilerOptions . CompiledUnitExtension ) , dbginfo ) ;
2020-07-09 05:54:55 +03:00
}
}
catch ( Exception err )
{
//ErrorsList.Add(new Errors.CompilerInternalError(string.Format("Compiler.Compile[{0}]", Path.GetFileName(this.CurrentCompilationUnit.SyntaxTree.file_name)), err));
2021-01-06 00:47:18 +03:00
OnChangeCompilerState ( this , CompilerState . PCUWritingError , Unit . UnitFileName ) ;
2020-07-09 05:54:55 +03:00
#if DEBUG
if ( ! InternalDebug . SkipPCUErrors )
throw new Errors . CompilerInternalError ( string . Format ( "Compiler.Compile[{0}]" , Path . GetFileName ( this . CurrentCompilationUnit . SyntaxTree . file_name ) ) , err ) ;
writer . RemoveSelf ( ) ;
#endif
}
}
public CompilationUnit ReadPCU ( string FileName )
{
2021-11-15 22:07:20 +03:00
if ( compilerOptions . ForIntellisense & & false )
{
CompilationUnit unit = null ;
if ( pcuCompilationUnits . ContainsKey ( FileName ) )
{
unit = pcuCompilationUnits [ FileName ] ;
return unit ;
}
PCUReader pr = new PCUReader ( this , pr_ChangeState ) ;
unit = pr . GetCompilationUnit ( FileName , CompilerOptions . Debug ) ;
pcuCompilationUnits [ FileName ] = unit ;
return unit ;
}
else
{
PCUReader pr = new PCUReader ( this , pr_ChangeState ) ;
return pr . GetCompilationUnit ( FileName , CompilerOptions . Debug ) ;
}
2020-07-09 05:54:55 +03:00
}
void pr_ChangeState ( object Sender , PCUReaderWriterState State , object obj )
{
switch ( State )
{
case PCUReaderWriterState . BeginReadTree :
OnChangeCompilerState ( this , CompilerState . ReadPCUFile , ( Sender as PCUReader ) . FileName ) ;
break ;
case PCUReaderWriterState . EndReadTree :
CompilationUnit cu = obj as CompilationUnit ;
cu . State = UnitState . Compiled ;
unitTable [ ( Sender as PCUReader ) . FileName ] = cu ;
UnitsSortedList . Add ( cu ) ;
GetReferences ( cu ) ;
break ;
case PCUReaderWriterState . EndSaveTree :
OnChangeCompilerState ( this , CompilerState . SavePCUFile , ( Sender as PCUWriter ) . FileName ) ;
break ;
}
}
/ * TreeRealization . common_unit_node cun11 = CurrentUnit . SemanticTree as TreeRealization . common_unit_node ;
if ( cun11 ! = null )
UnitsSortedList . AddElement ( cun11 ) ; * /
static string standartAssemblyPath = Path . GetDirectoryName ( System . Reflection . Assembly . GetAssembly ( typeof ( string ) ) . ManifestModule . FullyQualifiedName ) ;
public static Dictionary < string , string > standart_assembly_dict = new Dictionary < string , string > ( ) ;
static Compiler ( )
{
string [ ] ss = new string [ ] { "mscorlib.dll" , "System.dll" , "System.Core.dll" , "System.Numerics.dll" , "System.Windows.Forms.dll" , "PABCRtl.dll" } ;
foreach ( var x in ss )
standart_assembly_dict [ x ] = get_standart_assembly_path ( x ) ;
}
public static string get_standart_assembly_path ( string name )
{
name = name . Replace ( "%GAC%\\" , "" ) ;
string ttn = System . IO . Path . GetFileNameWithoutExtension ( name ) ;
string tn = Path . Combine ( standartAssemblyPath , name ) ;
if ( File . Exists ( tn ) )
return tn ;
if ( Environment . OSVersion . Platform ! = PlatformID . Unix & & Environment . OSVersion . Platform ! = PlatformID . MacOSX )
{
string windir = Path . Combine ( Environment . GetEnvironmentVariable ( "windir" ) , "Microsoft.NET" ) ;
tn = windir + @"\assembly\GAC_MSIL\" ;
tn + = ttn + "\\" ;
System . IO . DirectoryInfo di = new System . IO . DirectoryInfo ( tn ) ;
if ( ! di . Exists )
{
tn = windir + @"\assembly\GAC_64\" ;
tn + = ttn + "\\" ;
di = new System . IO . DirectoryInfo ( tn ) ;
if ( ! di . Exists )
{
tn = windir + @"\assembly\GAC_32\" ;
tn + = ttn + "\\" ;
di = new System . IO . DirectoryInfo ( tn ) ;
if ( ! di . Exists )
{
tn = windir + @"\assembly\GAC\" ;
tn + = ttn + "\\" ;
di = new System . IO . DirectoryInfo ( tn ) ;
if ( ! di . Exists )
{
windir = Environment . GetEnvironmentVariable ( "windir" ) ;
tn = windir + @"\assembly\GAC_MSIL\" ;
tn + = ttn + "\\" ;
di = new System . IO . DirectoryInfo ( tn ) ;
if ( ! di . Exists )
{
tn = windir + @"\assembly\GAC_64\" ;
tn + = ttn + "\\" ;
di = new System . IO . DirectoryInfo ( tn ) ;
if ( ! di . Exists )
{
tn = windir + @"\assembly\GAC_32\" ;
tn + = ttn + "\\" ;
di = new System . IO . DirectoryInfo ( tn ) ;
if ( ! di . Exists )
{
tn = windir + @"\assembly\GAC\" ;
tn + = ttn + "\\" ;
di = new System . IO . DirectoryInfo ( tn ) ;
if ( ! di . Exists )
{
return null ;
}
}
}
}
}
}
}
}
System . IO . DirectoryInfo [ ] diarr = di . GetDirectories ( ) ;
tn = Path . Combine ( ( diarr [ 0 ] ) . FullName , name ) ;
}
else
{
string gac_path = "/usr/lib/mono/4.0/gac" ;
DirectoryInfo di = new DirectoryInfo ( Path . Combine ( gac_path , ttn ) ) ;
if ( di . Exists )
{
System . IO . DirectoryInfo [ ] diarr = di . GetDirectories ( ) ;
tn = Path . Combine ( ( diarr [ diarr . Length - 1 ] ) . FullName , name ) ;
}
else
return null ;
}
return tn ;
}
public static string get_assembly_path ( string name , bool search_for_intellisense )
{
//если явно задан каталог то ищем только там
if ( Environment . OSVersion . Platform ! = PlatformID . Unix & & Environment . OSVersion . Platform ! = PlatformID . MacOSX & & ! name . StartsWith ( "%GAC%\\" ) )
{
if ( Path . GetDirectoryName ( name ) ! = string . Empty )
if ( File . Exists ( name ) )
return name ;
else
return null ;
}
if ( Environment . OSVersion . Platform = = PlatformID . Unix | | Environment . OSVersion . Platform = = PlatformID . MacOSX )
{
string SystemDirectory = System . IO . Path . GetDirectoryName ( System . Reflection . Assembly . GetExecutingAssembly ( ) . ManifestModule . FullyQualifiedName ) ;
string SearchDirectory = Path . Combine ( SystemDirectory , "Lib" ) ;
if ( File . Exists ( Path . Combine ( Environment . CurrentDirectory , name ) ) )
return Path . Combine ( Environment . CurrentDirectory , name ) ;
if ( File . Exists ( Path . Combine ( SearchDirectory , name ) ) )
{
File . Copy ( Path . Combine ( SearchDirectory , name ) , Path . Combine ( Environment . CurrentDirectory , name ) , true ) ;
return Path . Combine ( Environment . CurrentDirectory , name ) ;
}
}
if ( ! search_for_intellisense & & ! name . StartsWith ( "%GAC%\\" ) )
{
string dir = Environment . CurrentDirectory ;
if ( File . Exists ( Path . Combine ( dir , name ) ) )
{
return Path . Combine ( dir , name ) ;
}
}
return get_standart_assembly_path ( name ) ;
}
public CompilationUnit ReadDLL ( string FileName )
{
2021-11-15 22:07:20 +03:00
if ( DLLCache . ContainsKey ( FileName ) )
return DLLCache [ FileName ] ;
2020-07-09 05:54:55 +03:00
OnChangeCompilerState ( this , CompilerState . ReadDLL , FileName ) ;
TreeRealization . using_namespace_list using_namespaces = new TreeRealization . using_namespace_list ( ) ;
try
{
TreeRealization . dot_net_unit_node un =
new TreeRealization . dot_net_unit_node ( new NetHelper . NetScope ( using_namespaces ,
/*System.Reflection.Assembly.LoadFrom(FileName)*/
PascalABCCompiler . NetHelper . NetHelper . LoadAssembly ( FileName ) , SyntaxTreeToSemanticTreeConverter . SymbolTable ) ) ;
CompilationUnit cu = new CompilationUnit ( ) ;
cu . SemanticTree = un ;
//un.dotNetScope=new PascalABCCompiler.NetHelper.NetScope(using_namespaces,
// System.Reflection.Assembly.LoadFrom(FileName),SyntaxTreeToSemanticTreeConverter.SymbolTable);
2021-11-15 22:07:20 +03:00
DLLCache [ FileName ] = cu ;
2020-07-09 05:54:55 +03:00
return cu ;
}
catch ( ReflectionTypeLoadException e )
{
Console . Error . WriteLine ( e . Message ) ;
foreach ( var eLoaderException in e . LoaderExceptions )
{
Console . Error . WriteLine ( eLoaderException . Message ) ;
}
return null ;
}
catch ( Exception e )
{
Console . Error . WriteLine ( e . Message ) ;
return null ;
}
}
/ * public CompilationUnit RecompileUnit ( string unit_name )
{
Console . WriteLine ( "recompile {0}" , unit_name ) ;
CurrentSyntaxUnit = new SyntaxTree . uses_unit_in ( new SyntaxTree . string_const ( program_folder + "\\" + unit_name + ".pas" ) ) ;
CompileUnit ( Units , CurrentSyntaxUnit ) ;
CompilationUnit cu = new CompilationUnit ( ) ;
if ( Units . Count ! = 0 )
cu . SemanticTree = Units [ Units . Count - 1 ] ;
else
return null ;
return cu ;
} * /
2020-07-14 00:22:04 +03:00
public bool NeedRecompiled ( string pcu_name , string [ ] included , PCUReader pr )
2020-07-09 05:54:55 +03:00
{
2020-07-14 00:22:04 +03:00
if ( ! Path . IsPathRooted ( pcu_name ) ) throw new InvalidOperationException ( ) ;
2020-07-17 01:58:34 +03:00
string pas_name = FindSourceFileName ( Path . ChangeExtension ( pcu_name , null ) , null , out _ ) ;
2020-07-14 00:22:04 +03:00
var dir = Path . GetDirectoryName ( pcu_name ) ;
2021-01-06 00:47:18 +03:00
if ( UnitTable [ Path . ChangeExtension ( pas_name , null ) ] ! = null )
2020-07-09 05:54:55 +03:00
return true ;
2020-07-14 00:22:04 +03:00
2020-07-09 05:54:55 +03:00
bool need = false ;
for ( int i = 0 ; i < included . Length ; i + + )
{
//if (included[i].Contains("$"))
2020-07-17 01:58:34 +03:00
// continue;
2020-07-20 11:20:59 +03:00
var used_unit_fname = GetUnitFileName ( Path . GetFileNameWithoutExtension ( included [ i ] ) , included [ i ] , dir , null ) ;
2020-07-17 01:58:34 +03:00
var used_unit_is_pcu = Path . GetExtension ( used_unit_fname ) = = CompilerOptions . CompiledUnitExtension ;
if ( ! used_unit_is_pcu )
2020-07-14 00:22:04 +03:00
{
2021-01-06 00:47:18 +03:00
if ( UnitTable [ Path . ChangeExtension ( used_unit_fname , null ) ] ! = null ) return true ;
2020-07-14 00:22:04 +03:00
need = true ;
RecompileList [ pcu_name ] = pcu_name ;
2020-07-09 05:54:55 +03:00
}
}
if ( need ) return true ;
2020-07-14 00:22:04 +03:00
2020-07-09 05:54:55 +03:00
if ( ! SourceFileExists ( pas_name ) ) return false ;
2020-07-14 00:22:04 +03:00
// NeedRecompiled вызывается уже после успешного прочтения заголовка модуля (иначе откуда included)
//if (!File.Exists(pcu_name)) return true;
2020-07-09 05:54:55 +03:00
if ( File . GetLastWriteTime ( pcu_name ) < SourceFileGetLastWriteTime ( pas_name ) ) return true ;
//Console.WriteLine("{0} {1}",name,RecompileList.Count);
for ( int i = 0 ; i < included . Length ; i + + )
{
2020-07-17 01:58:34 +03:00
string pcu_name2 = FindPCUFileName ( included [ i ] , dir , out _ ) ;
2020-07-09 05:54:55 +03:00
//TODO: Спросить у Сащи насчет < и <=.
if ( ( File . Exists ( pcu_name2 ) & & File . GetLastWriteTime ( pcu_name ) < File . GetLastWriteTime ( pcu_name2 ) & & ! pr . AlreadyCompiled ( pcu_name2 ) ) )
{
2020-07-14 00:22:04 +03:00
pr . AddAlreadyCompiledUnit ( pcu_name2 ) ;
2020-07-09 05:54:55 +03:00
return true ;
}
2020-07-14 00:22:04 +03:00
if ( RecompileList . ContainsKey ( pcu_name2 ) )
2020-07-09 05:54:55 +03:00
{
return true ;
}
}
return false ;
}
2021-11-15 22:07:20 +03:00
public void ClearAll ( bool close_pcu = true )
2020-07-09 05:54:55 +03:00
{
_semantic_tree = null ;
2021-11-15 22:07:20 +03:00
if ( close_pcu )
{
PCUReader . CloseUnits ( ) ;
PCUWriter . Clear ( ) ;
}
2020-07-09 05:54:55 +03:00
RecompileList . Clear ( ) ;
CycleUnits . Clear ( ) ;
UnitTable . Clear ( ) ;
UnitsSortedList . Clear ( ) ;
//TreeRealization.PCUReturner.Clear();
BadNodesInSyntaxTree . Clear ( ) ;
2021-11-15 22:07:20 +03:00
if ( close_pcu )
PCUReader . AllReaders . Clear ( ) ;
2020-07-09 05:54:55 +03:00
project = null ;
StandarModules . Clear ( ) ;
2021-11-15 22:07:20 +03:00
CompiledVariables . Clear ( ) ;
if ( ! close_pcu )
{
SyntaxTreeToSemanticTreeConverter = new TreeConverter . SyntaxTreeToSemanticTreeConverter ( ) ;
}
2020-07-09 05:54:55 +03:00
//SystemLibrary.SystemLibrary.RestoreStandartNames();
}
public CompilerType CompilerType
{
get
{
return CompilerType . Standart ;
}
}
public void Free ( )
{
}
}
}