mirror of
https://github.com/polserver/polserver
synced 2026-08-13 08:23:08 -04:00
* Squash only prettify changes from escript_formating_try
* support of "format-off" / "format-on" comments to mark areas without
formatting
* fix typo
* added FormatterIdentLevel, FormatterMergeEmptyLines cfg entry
better line splits for dicts/arrays
* added several spacing options. the current setting list is now:
//LineWidth
FormatterLineWidth 80
// keep original keyword spelling
FormatterKeepKeywords 0
// number of spaces for ident
FormatterIdentLevel 2
// multiple newlines get merged to a single
FormatterMergeEmptyLines 1
// space between emtpy parenthesis eg foo() vs foo( )
FormatterEmptyParenthesisSpacing 0
// space between emtpy brackets eg struct{} vs struct{ }
FormatterEmptyBracketSpacing 0
// space after/before parenthesis in conditionals
// eg if ( true ) vs if (true)
FormatterConditionalParenthesisSpacing 1
// space after/before parenthesis
// eg foo( true ) vs foo(true)
FormatterParenthesisSpacing 1
// space after/before brackets
// eg array{ true } vs array{true}
FormatterBracketSpacing 1
// add space after delimiter comma or semi in for loops
// eg {1, 2, 3} vs {1,2,3}
FormatterDelimiterSpacing 1
// add space around assignment
// eg a := 1; vs a:=1;
FormatterAssignmentSpacing 1
// add space around comparison
// eg a == 1 vs a==1
FormatterComparisonSpacing 1
// add space around operations
// eg a + 1 vs a+1
FormatterOperatorSpacing 1
// use \r\n as newline instead of \n
FormatterWindowsLineEndings 0
* added tab support
// use tabs instead of spaces
FormatterUseTabs 0
// tab width
FormatterTabWidth 4
* extended example ecompile.cfg with formatter settings
* cleanup
* program args comma is optional...
fixed line comments in group splitting
* since tokenids are now correct no more guessing for linecomments needed
* comments use as start tokenid the whitespace token if its on the same
line
* splitted processing from linebuilding
* renamed TokenPart to FmtToken better matches the purpose.
Comments get directly stored as FmtToken
started with a context enum
* better(?) formatting for groups
* fix eof rawlines
added check that all comments/rawlines got parsed
* const correctness
* datatype adapted to antlr
* fixed warnings
* added InsertNewlineAtEOF
* add newline at the end if the original file had one
dont strip comment whitespace if its somejind of "header block"
use the defined lineending for /* */ comments
* docs
* \r\n is default on windows \n otherwise
* fixed warning
---------
Co-authored-by: Kevin Eady <8634912+KevinEady@users.noreply.github.com>
207 lines
6 KiB
C++
207 lines
6 KiB
C++
#include "Compiler.h"
|
|
|
|
#include "bscript/compiler/Profile.h"
|
|
#include "bscript/compiler/Report.h"
|
|
#include "bscript/compiler/analyzer/Disambiguator.h"
|
|
#include "bscript/compiler/analyzer/SemanticAnalyzer.h"
|
|
#include "bscript/compiler/astbuilder/CompilerWorkspaceBuilder.h"
|
|
#include "bscript/compiler/codegen/CodeGenerator.h"
|
|
#include "bscript/compiler/file/PrettifyBuilder.h"
|
|
#include "bscript/compiler/file/SourceFileCache.h"
|
|
#include "bscript/compiler/file/SourceFileIdentifier.h"
|
|
#include "bscript/compiler/format/CompiledScriptSerializer.h"
|
|
#include "bscript/compiler/format/DebugStoreSerializer.h"
|
|
#include "bscript/compiler/format/ListingWriter.h"
|
|
#include "bscript/compiler/model/CompilerWorkspace.h"
|
|
#include "bscript/compiler/optimizer/Optimizer.h"
|
|
#include "bscript/compiler/representation/CompiledScript.h"
|
|
#include "clib/fileutil.h"
|
|
#include "clib/logfacility.h"
|
|
#include "clib/timer.h"
|
|
#include "compilercfg.h"
|
|
|
|
namespace Pol::Bscript::Compiler
|
|
{
|
|
Compiler::Compiler( SourceFileCache& em_cache, SourceFileCache& inc_cache, Profile& profile )
|
|
: em_cache( em_cache ), inc_cache( inc_cache ), profile( profile )
|
|
{
|
|
}
|
|
|
|
Compiler::~Compiler() = default;
|
|
|
|
bool Compiler::write_ecl( const std::string& pathname )
|
|
{
|
|
if ( output )
|
|
{
|
|
CompiledScriptSerializer( *output ).write( pathname );
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
void Compiler::write_listing( const std::string& pathname )
|
|
{
|
|
if ( output )
|
|
{
|
|
std::ofstream ofs( pathname );
|
|
ListingWriter( *output ).write( ofs );
|
|
}
|
|
}
|
|
|
|
void Compiler::write_dbg( const std::string& pathname, bool include_debug_text )
|
|
{
|
|
if ( output )
|
|
{
|
|
std::ofstream ofs( pathname, std::ofstream::binary );
|
|
auto text_ofs = include_debug_text ? std::make_unique<std::ofstream>( pathname + ".txt" )
|
|
: std::unique_ptr<std::ofstream>();
|
|
|
|
DebugStoreSerializer( *output ).write( ofs, text_ofs.get() );
|
|
}
|
|
}
|
|
|
|
void Compiler::write_included_filenames( const std::string& pathname )
|
|
{
|
|
if ( output )
|
|
{
|
|
std::ofstream ofs( pathname );
|
|
for ( auto& r : output->source_file_identifiers )
|
|
{
|
|
ofs << r->pathname << "\n";
|
|
}
|
|
}
|
|
}
|
|
|
|
void Compiler::set_include_compile_mode()
|
|
{
|
|
user_function_inclusion = UserFunctionInclusion::All;
|
|
}
|
|
|
|
bool Compiler::compile_file( const std::string& filename )
|
|
{
|
|
bool success;
|
|
try
|
|
{
|
|
auto pathname = Clib::FullPath( filename.c_str() );
|
|
|
|
Report report( compilercfg.DisplayWarnings || compilercfg.ErrorOnWarning );
|
|
|
|
compile_file_steps( pathname, report );
|
|
display_outcome( pathname, report );
|
|
|
|
bool have_warning_as_error = report.warning_count() && compilercfg.ErrorOnWarning;
|
|
success = !report.error_count() && !have_warning_as_error;
|
|
}
|
|
catch ( std::exception& ex )
|
|
{
|
|
ERROR_PRINTLN( ex.what() );
|
|
success = false;
|
|
}
|
|
return success;
|
|
}
|
|
|
|
void Compiler::compile_file_steps( const std::string& pathname, Report& report )
|
|
{
|
|
std::unique_ptr<CompilerWorkspace> workspace = build_workspace( pathname, report );
|
|
if ( report.error_count() )
|
|
return;
|
|
|
|
register_constants( *workspace, report );
|
|
if ( report.error_count() )
|
|
return;
|
|
|
|
optimize( *workspace, report );
|
|
if ( report.error_count() )
|
|
return;
|
|
|
|
disambiguate( *workspace, report );
|
|
if ( report.error_count() )
|
|
return;
|
|
|
|
analyze( *workspace, report );
|
|
if ( report.error_count() )
|
|
return;
|
|
|
|
output = generate( std::move( workspace ) );
|
|
}
|
|
|
|
bool Compiler::format_file( const std::string& filename, bool is_module, bool inplace )
|
|
{
|
|
Report report( false, true );
|
|
PrettifyBuilder prettify_builder( profile, report );
|
|
auto formatted = prettify_builder.build( filename, is_module );
|
|
if ( report.error_count() )
|
|
return false;
|
|
if ( inplace )
|
|
{
|
|
std::ofstream filestream;
|
|
filestream.open( filename, std::ios_base::out | std::ios_base::trunc );
|
|
filestream << formatted;
|
|
filestream.flush();
|
|
}
|
|
else
|
|
INFO_PRINTLN( formatted );
|
|
return true;
|
|
}
|
|
|
|
std::unique_ptr<CompilerWorkspace> Compiler::build_workspace( const std::string& pathname,
|
|
Report& report )
|
|
{
|
|
Pol::Tools::HighPerfTimer timer;
|
|
CompilerWorkspaceBuilder workspace_builder( em_cache, inc_cache, profile, report );
|
|
auto workspace = workspace_builder.build( pathname, user_function_inclusion );
|
|
profile.build_workspace_micros += timer.ellapsed().count();
|
|
return workspace;
|
|
}
|
|
|
|
void Compiler::register_constants( CompilerWorkspace& workspace, Report& report )
|
|
{
|
|
Pol::Tools::HighPerfTimer timer;
|
|
SemanticAnalyzer::register_const_declarations( workspace, report );
|
|
profile.register_const_declarations_micros += timer.ellapsed().count();
|
|
}
|
|
|
|
void Compiler::optimize( CompilerWorkspace& workspace, Report& report )
|
|
{
|
|
Pol::Tools::HighPerfTimer timer;
|
|
Optimizer optimizer( workspace.constants, report );
|
|
optimizer.optimize( workspace, user_function_inclusion );
|
|
profile.optimize_micros += timer.ellapsed().count();
|
|
}
|
|
|
|
void Compiler::disambiguate( CompilerWorkspace& workspace, Report& report )
|
|
{
|
|
Pol::Tools::HighPerfTimer timer;
|
|
Disambiguator disambiguator( workspace.constants, report );
|
|
disambiguator.disambiguate( workspace );
|
|
profile.disambiguate_micros += timer.ellapsed().count();
|
|
}
|
|
|
|
void Compiler::analyze( CompilerWorkspace& workspace, Report& report )
|
|
{
|
|
Pol::Tools::HighPerfTimer timer;
|
|
SemanticAnalyzer analyzer( workspace, report );
|
|
analyzer.analyze();
|
|
profile.analyze_micros += timer.ellapsed().count();
|
|
}
|
|
|
|
std::unique_ptr<CompiledScript> Compiler::generate( std::unique_ptr<CompilerWorkspace> workspace )
|
|
{
|
|
Pol::Tools::HighPerfTimer codegen_timer;
|
|
auto compiled_script = CodeGenerator::generate( std::move( workspace ) );
|
|
profile.codegen_micros += codegen_timer.ellapsed().count();
|
|
return compiled_script;
|
|
}
|
|
|
|
void Compiler::display_outcome( const std::string& filename, Report& report )
|
|
{
|
|
auto msg = fmt::format( "{}: {} errors", filename, report.error_count() );
|
|
if ( compilercfg.DisplayWarnings || compilercfg.ErrorOnWarning )
|
|
msg += fmt::format( ", {} warnings", report.warning_count() );
|
|
INFO_PRINTLN( msg + '.' );
|
|
}
|
|
|
|
} // namespace Pol::Bscript::Compiler
|