• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

polserver / polserver / 16578783200

28 Jul 2025 07:48PM UTC coverage: 59.79% (+0.2%) from 59.58%
16578783200

push

github

web-flow
Short Circuit Optimizer (#797)

* first working short curcuit for && and or
creates jumps after each expressions to skip the following

* fixed valuestack when short circuit jmp does not jump

* use specialized instructions for short circuit && and ||

1: lhs
2: logical jump if false/true goto 4 <- if jmp do logical convert
3: rhs
4: logical convert
5: rest

logical convert is needed since "normal" && || operations convert isTrue
to BLong

added BObjectRef BObjectImp set specialization to remove noise

* fixed converted objimp when jump on false values

* first version of short circuit warning
should be moved to analyzer
added whitelist of module functions which have no sideeffect to reduce
the number of warnings

* moved warning visitor to analyzer and added it as extra compile step
fixed sourceline print and cache the content

* missing include, unused member

* included the correct header

* ecompile.cfg to activate and warn
ecompile cmdline arg to activate it
run all tests also with it active
fixed that only the most right side statement was checked

* ecompile cmdline

* increase ecompile version
cleanup

* compilation error

* missing header

* allow -S- to deactivate shortcircuit like the other params do

* extended whitelist functions

* revert fileformat version increase
fixed escript test cmake

* use the correct arg

* escript testoutput can now be different if shortcircuit is active

* docs

* additional test

* addressed comments

210 of 239 new or added lines in 16 files covered. (87.87%)

1 existing line in 1 file now uncovered.

43653 of 73010 relevant lines covered (59.79%)

466031.96 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

92.03
/pol-core/bscript/compiler/Compiler.cpp
1
#include "Compiler.h"
2

3
#include "bscript/compiler/Profile.h"
4
#include "bscript/compiler/Report.h"
5
#include "bscript/compiler/analyzer/Disambiguator.h"
6
#include "bscript/compiler/analyzer/SemanticAnalyzer.h"
7
#include "bscript/compiler/analyzer/ShortCircuitWarning.h"
8
#include "bscript/compiler/ast/TopLevelStatements.h"
9
#include "bscript/compiler/astbuilder/CompilerWorkspaceBuilder.h"
10
#include "bscript/compiler/codegen/CodeGenerator.h"
11
#include "bscript/compiler/file/PrettifyBuilder.h"
12
#include "bscript/compiler/file/SourceFileCache.h"
13
#include "bscript/compiler/file/SourceFileIdentifier.h"
14
#include "bscript/compiler/format/CompiledScriptSerializer.h"
15
#include "bscript/compiler/format/DebugStoreSerializer.h"
16
#include "bscript/compiler/format/ListingWriter.h"
17
#include "bscript/compiler/model/CompilerWorkspace.h"
18
#include "bscript/compiler/optimizer/Optimizer.h"
19
#include "bscript/compiler/representation/CompiledScript.h"
20
#include "clib/fileutil.h"
21
#include "clib/logfacility.h"
22
#include "clib/timer.h"
23
#include "compilercfg.h"
24

25
namespace Pol::Bscript::Compiler
26
{
27
Compiler::Compiler( SourceFileCache& em_cache, SourceFileCache& inc_cache, Profile& profile )
2,968✔
28
    : em_cache( em_cache ), inc_cache( inc_cache ), profile( profile )
2,968✔
29
{
30
}
2,968✔
31

32
Compiler::~Compiler() = default;
2,968✔
33

34
bool Compiler::write_ecl( const std::string& pathname )
2,099✔
35
{
36
  if ( output )
2,099✔
37
  {
38
    CompiledScriptSerializer( *output ).write( pathname );
2,099✔
39
    return true;
2,099✔
40
  }
41
  else
42
  {
43
    return false;
×
44
  }
45
}
46

47
void Compiler::write_listing( const std::string& pathname )
1,851✔
48
{
49
  if ( output )
1,851✔
50
  {
51
    std::ofstream ofs( pathname );
1,851✔
52
    ListingWriter( *output ).write( ofs );
1,851✔
53
  }
1,851✔
54
}
1,851✔
55

56
void Compiler::write_string_tree( const std::string& pathname )
6✔
57
{
58
  if ( output )
6✔
59
  {
60
    std::ofstream ofs( pathname );
6✔
61
    ofs << output->tree;
6✔
62
  }
6✔
63
}
6✔
64

65
void Compiler::write_dbg( const std::string& pathname, bool include_debug_text )
1,970✔
66
{
67
  if ( output )
1,970✔
68
  {
69
    std::ofstream ofs( pathname, std::ofstream::binary );
1,970✔
70
    auto text_ofs = include_debug_text ? std::make_unique<std::ofstream>( pathname + ".txt" )
1,970✔
71
                                       : std::unique_ptr<std::ofstream>();
1,970✔
72

73
    DebugStoreSerializer( *output ).write( ofs, text_ofs.get() );
1,970✔
74
  }
1,970✔
75
}
1,970✔
76

77
void Compiler::write_included_filenames( const std::string& pathname )
129✔
78
{
79
  if ( output )
129✔
80
  {
81
    std::ofstream ofs( pathname );
129✔
82
    for ( auto& r : output->source_file_identifiers )
1,053✔
83
    {
84
      ofs << r->pathname << "\n";
924✔
85
    }
86
  }
129✔
87
}
129✔
88

89
void Compiler::set_include_compile_mode()
×
90
{
91
  user_function_inclusion = UserFunctionInclusion::All;
×
92
}
×
93

94
bool Compiler::compile_file( const std::string& filename )
2,352✔
95
{
96
  bool success;
97
  try
98
  {
99
    auto pathname = Clib::FullPath( filename.c_str() );
2,352✔
100

101
    Report report( compilercfg.DisplayWarnings || compilercfg.ErrorOnWarning,
2,352✔
102
                   true /* display errors */, compilercfg.DisplayDebugs );
4,704✔
103

104
    compile_file_steps( pathname, report );
2,352✔
105
    display_outcome( pathname, report );
2,350✔
106

107
    bool have_warning_as_error = report.warning_count() && compilercfg.ErrorOnWarning;
2,350✔
108
    success = !report.error_count() && !have_warning_as_error;
2,350✔
109
  }
2,352✔
110
  catch ( std::exception& ex )
2✔
111
  {
112
    ERROR_PRINTLN( ex.what() );
2✔
113
    success = false;
2✔
114
  }
2✔
115
  return success;
2,352✔
116
}
117

118
void Compiler::compile_file_steps( const std::string& pathname, Report& report )
2,352✔
119
{
120
  std::unique_ptr<CompilerWorkspace> workspace = build_workspace( pathname, report );
2,352✔
121
  if ( report.error_count() )
2,350✔
122
    return;
121✔
123

124
  register_constants( *workspace, report );
2,229✔
125
  if ( report.error_count() )
2,229✔
126
    return;
2✔
127

128
  optimize( *workspace, report );
2,227✔
129
  if ( report.error_count() )
2,227✔
130
    return;
10✔
131

132
  disambiguate( *workspace, report );
2,217✔
133
  if ( report.error_count() )
2,217✔
134
    return;
×
135

136
  analyze( *workspace, report );
2,217✔
137
  if ( report.error_count() )
2,217✔
138
    return;
118✔
139

140
  check_short_circuit( *workspace, report );
2,099✔
141
  if ( report.error_count() )
2,099✔
NEW
142
    return;
×
143

144
  output = generate( std::move( workspace ), report );
2,099✔
145
}
2,350✔
146

147
bool Compiler::format_file( const std::string& filename, bool is_module, bool inplace )
616✔
148
{
149
  if ( !Clib::filesize( filename.c_str() ) )
616✔
150
    return true;
×
151

152
  Report report( false, true );
616✔
153
  PrettifyBuilder prettify_builder( profile, report );
616✔
154
  auto formatted = prettify_builder.build( filename, is_module );
616✔
155
  if ( report.error_count() )
616✔
156
    return false;
×
157
  if ( inplace )
616✔
158
  {
159
    std::ofstream filestream;
616✔
160
    filestream.open( filename, std::ios_base::out | std::ios_base::trunc | std::ios::binary );
616✔
161
    filestream << formatted;
616✔
162
    filestream.flush();
616✔
163
  }
616✔
164
  else
165
    INFO_PRINTLN( formatted );
×
166
  return true;
616✔
167
}
616✔
168

169
std::unique_ptr<CompilerWorkspace> Compiler::build_workspace( const std::string& pathname,
2,352✔
170
                                                              Report& report )
171
{
172
  Pol::Tools::HighPerfTimer timer;
2,352✔
173
  CompilerWorkspaceBuilder workspace_builder( em_cache, inc_cache, profile, report );
2,352✔
174
  auto workspace = workspace_builder.build( pathname, user_function_inclusion );
2,352✔
175
  profile.build_workspace_micros += timer.ellapsed().count();
2,350✔
176
  return workspace;
4,700✔
177
}
×
178

179
void Compiler::register_constants( CompilerWorkspace& workspace, Report& report )
2,229✔
180
{
181
  Pol::Tools::HighPerfTimer timer;
2,229✔
182
  SemanticAnalyzer::register_const_declarations( workspace, report );
2,229✔
183
  profile.register_const_declarations_micros += timer.ellapsed().count();
2,229✔
184
}
2,229✔
185

186
void Compiler::optimize( CompilerWorkspace& workspace, Report& report )
2,227✔
187
{
188
  Pol::Tools::HighPerfTimer timer;
2,227✔
189
  Optimizer optimizer( workspace.constants, report );
2,227✔
190
  optimizer.optimize( workspace, user_function_inclusion );
2,227✔
191
  profile.optimize_micros += timer.ellapsed().count();
2,227✔
192
}
2,227✔
193

194
void Compiler::disambiguate( CompilerWorkspace& workspace, Report& report )
2,217✔
195
{
196
  Pol::Tools::HighPerfTimer timer;
2,217✔
197
  Disambiguator disambiguator( workspace.constants, report );
2,217✔
198
  disambiguator.disambiguate( workspace );
2,217✔
199
  profile.disambiguate_micros += timer.ellapsed().count();
2,217✔
200
}
2,217✔
201

202
void Compiler::analyze( CompilerWorkspace& workspace, Report& report )
2,217✔
203
{
204
  Pol::Tools::HighPerfTimer timer;
2,217✔
205
  SemanticAnalyzer analyzer( workspace, report );
2,217✔
206
  analyzer.analyze();
2,217✔
207
  profile.analyze_micros += timer.ellapsed().count();
2,217✔
208
}
2,217✔
209

210
void Compiler::check_short_circuit( CompilerWorkspace& workspace, Report& report )
2,099✔
211
{
212
  ShortCircuitWarning warn{ report };
2,099✔
213
  warn.warn( workspace );
2,099✔
214
}
2,099✔
215

216
std::unique_ptr<CompiledScript> Compiler::generate( std::unique_ptr<CompilerWorkspace> workspace,
2,099✔
217
                                                    Report& report )
218
{
219
  Pol::Tools::HighPerfTimer codegen_timer;
2,099✔
220
  auto compiled_script = CodeGenerator::generate( std::move( workspace ), report,
2,099✔
221
                                                  compilercfg.GenerateAbstractSyntaxTree );
2,099✔
222
  profile.codegen_micros += codegen_timer.ellapsed().count();
2,099✔
223
  return compiled_script;
4,198✔
224
}
×
225

226
void Compiler::display_outcome( const std::string& filename, Report& report )
2,350✔
227
{
228
  auto msg = fmt::format( "{}: {} errors", filename, report.error_count() );
2,350✔
229
  if ( compilercfg.DisplayWarnings || compilercfg.ErrorOnWarning )
2,350✔
230
    msg += fmt::format( ", {} warnings", report.warning_count() );
4,700✔
231
  INFO_PRINTLN( msg + '.' );
2,350✔
232
}
2,350✔
233

234
}  // namespace Pol::Bscript::Compiler
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc