• 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

85.94
/pol-core/bscript/compiler/analyzer/ShortCircuitWarning.cpp
1
#include "ShortCircuitWarning.h"
2

3
#include "bscript/compiler/Report.h"
4
#include "bscript/compiler/ast/BinaryOperator.h"
5
#include "bscript/compiler/ast/BinaryOperatorShortCircuit.h"
6
#include "bscript/compiler/ast/ElementAssignment.h"
7
#include "bscript/compiler/ast/Function.h"
8
#include "bscript/compiler/ast/FunctionCall.h"
9
#include "bscript/compiler/ast/MemberAssignment.h"
10
#include "bscript/compiler/ast/MemberAssignmentByOperator.h"
11
#include "bscript/compiler/ast/MethodCall.h"
12
#include "bscript/compiler/ast/ModuleFunctionDeclaration.h"
13
#include "bscript/compiler/ast/Program.h"
14
#include "bscript/compiler/ast/TopLevelStatements.h"
15
#include "bscript/compiler/ast/UnaryOperator.h"
16
#include "bscript/compiler/ast/UserFunction.h"
17
#include "bscript/compiler/ast/VariableAssignmentStatement.h"
18
#include "bscript/compiler/model/CompilerWorkspace.h"
19
#include "bscript/compiler/model/FunctionLink.h"
20
#include "bscript/compilercfg.h"
21
#include "bscript/tokens.h"
22
#include "clib/strutil.h"
23

24
namespace Pol::Bscript::Compiler
25
{
26
ShortCircuitWarning::ShortCircuitWarning( Report& report ) : visitor( report ) {}
2,099✔
27

28
void ShortCircuitWarning::warn( CompilerWorkspace& workspace )
2,099✔
29
{
30
  if ( !compilercfg.ShortCircuitEvaluation || !compilercfg.ShortCircuitEvaluationWarning )
2,099✔
31
    return;
1,481✔
32
  workspace.top_level_statements->accept( *this );
618✔
33
  if ( auto& program = workspace.program )
618✔
34
  {
35
    program->accept( *this );
73✔
36
  }
37
  for ( auto& user_function : workspace.user_functions )
1,246✔
38
  {
39
    user_function->accept( *this );
628✔
40
  }
41
}
42

43
void ShortCircuitWarning::visit_binary_operator_short_circuit( BinaryOperatorShortCircuit& op )
38✔
44
{
45
  // check only right side, left is only needed if more compile
46
  // optimizations are done
47
  // left still could be a ShortCircuit so visit it with this instance
48
  op.lhs().accept( *this );
38✔
49
  op.rhs().accept( visitor );
38✔
50
}
38✔
51

52
///////
53

54
ShortCircuitReporter::ShortCircuitReporter( Report& report ) : report( report ) {}
2,099✔
55

56
void ShortCircuitReporter::trigger( Node& op )
16✔
57
{
58
  report.warning( op.source_location,
16✔
59
                  "Short circuit change: \"{}\" will potentially not been executed.\n{}",
60
                  op.describe(), op.source_location.getSourceLine() );
32✔
61
}
16✔
62

63
void ShortCircuitReporter::visit_binary_operator( BinaryOperator& op )
5✔
64
{
65
  switch ( op.token_id )
5✔
66
  {
67
  case TOK_ASSIGN:
3✔
68
  case INS_ASSIGN_CONSUME:
69
  case TOK_PLUSEQUAL:
70
  case TOK_MINUSEQUAL:
71
  case TOK_TIMESEQUAL:
72
  case TOK_DIVIDEEQUAL:
73
  case TOK_MODULUSEQUAL:
74
  case TOK_ADDMEMBER:
75
  case TOK_DELMEMBER:
76
    trigger( op );
3✔
77
    return;
3✔
78

79
  default:
2✔
80
    visit_children( op );
2✔
81
    return;
2✔
82
  }
83
}
84

85
void ShortCircuitReporter::visit_element_assignment( ElementAssignment& op )
1✔
86
{
87
  trigger( op );
1✔
88
}
1✔
89

90
void ShortCircuitReporter::visit_function_call( FunctionCall& op )
9✔
91
{
92
  // Whitelist of module functions without sideeffects
93
  // not all, just some I found
94
  static std::map<std::string, std::vector<std::string>> modulefuncs = {
95
      { "attributes", { "getattribute" } },
96
      { "basicio", {} },
97
      { "basic",
98
        { "casc", "cascz", "cdbl", "cint", "cstr", "find", "hex", "len", "lower", "upper", "sizeof",
99
          "typeof", "typeofint" } },
100
      { "cfgfile", { "getconfigint", "getconfigreal", "getconfigstring" } },
101
      { "math", { "abs" } },
102
      { "npc", { "self" } },
103
      { "os", { "getpid", "getprocess" } },
104
      { "util", {} },
105
      { "uo",
106
        { "accessible", "checklineofsight", "checklosat", "coordinatedistance", "distance",
107
          "distanceeuclidean", "enumerateitemsincontainer", "getamount", "getequipmentbylayer",
108
          "getglobalproperty", "getobjproperty", "getobjpropertynames", "getobjtypebyname",
109
          "listequippeditems", "listhostiles", "listmobilesatlocation", "listmobilesnearlocation",
110
          "readgameclock", "systemfindobjectbyserial" } },
111

112
  };
109✔
113
  if ( auto mf = op.function_link->module_function_declaration() )
9✔
114
  {
115
    bool ignore = false;
5✔
116
    if ( auto mod = modulefuncs.find( Clib::strlowerASCII( mf->scope ) ); mod != modulefuncs.end() )
5✔
117
    {
118
      if ( mod->second.empty() )
5✔
119
        ignore = true;
5✔
NEW
120
      else if ( std::find( mod->second.begin(), mod->second.end(),
×
NEW
121
                           Clib::strlowerASCII( mf->name ) ) != mod->second.end() )
×
NEW
122
        ignore = true;
×
123
    }
124
    if ( ignore )
5✔
125
    {
126
      visit_children( op );
5✔
127
      return;
5✔
128
    }
129
  }
130
  trigger( op );
4✔
131
}
84✔
132

133
void ShortCircuitReporter::visit_member_assignment( MemberAssignment& op )
1✔
134
{
135
  trigger( op );
1✔
136
}
1✔
137

NEW
138
void ShortCircuitReporter::visit_member_assignment_by_operator( MemberAssignmentByOperator& op )
×
139
{
140
  // todo what
NEW
141
  trigger( op );
×
NEW
142
}
×
143

NEW
144
void ShortCircuitReporter::visit_variable_assignment_statement( VariableAssignmentStatement& op )
×
145
{
146
  // todo what
NEW
147
  trigger( op );
×
NEW
148
}
×
149

150
void ShortCircuitReporter::visit_method_call( MethodCall& op )
3✔
151
{
152
  trigger( op );
3✔
153
}
3✔
154

155
void ShortCircuitReporter::visit_unary_operator( UnaryOperator& op )
6✔
156
{
157
  switch ( op.token_id )
6✔
158
  {
159
  case TOK_UNPLUSPLUS:
4✔
160
  case TOK_UNMINUSMINUS:
161
  case TOK_UNPLUSPLUS_POST:
162
  case TOK_UNMINUSMINUS_POST:
163
  case INS_SET_MEMBER_ID_UNPLUSPLUS:
164
  case INS_SET_MEMBER_ID_UNMINUSMINUS:
165
  case INS_SET_MEMBER_ID_UNPLUSPLUS_POST:
166
  case INS_SET_MEMBER_ID_UNMINUSMINUS_POST:
167
    trigger( op );
4✔
168
    return;
4✔
169
  default:
2✔
170
    visit_children( op );
2✔
171
    return;
2✔
172
  }
173
}
174
}  // 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