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

polserver / polserver / 21100551564

17 Jan 2026 08:40PM UTC coverage: 60.504% (+0.01%) from 60.492%
21100551564

Pull #857

github

turleypol
fixed scope
Pull Request #857: ClangTidy readability-else-after-return

837 of 1874 new or added lines in 151 files covered. (44.66%)

48 existing lines in 26 files now uncovered.

44445 of 73458 relevant lines covered (60.5%)

515341.61 hits per line

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

94.44
/pol-core/bscript/compiler/astbuilder/CompoundStatementBuilder.cpp
1
#include "CompoundStatementBuilder.h"
2

3
#include "bscript/compiler/ast/ArrayInitializer.h"
4
#include "bscript/compiler/ast/BasicForLoop.h"
5
#include "bscript/compiler/ast/Block.h"
6
#include "bscript/compiler/ast/BooleanValue.h"
7
#include "bscript/compiler/ast/BranchSelector.h"
8
#include "bscript/compiler/ast/CaseDispatchDefaultSelector.h"
9
#include "bscript/compiler/ast/CaseDispatchGroup.h"
10
#include "bscript/compiler/ast/CaseDispatchGroups.h"
11
#include "bscript/compiler/ast/CaseDispatchSelectors.h"
12
#include "bscript/compiler/ast/CaseStatement.h"
13
#include "bscript/compiler/ast/ConstDeclaration.h"
14
#include "bscript/compiler/ast/CstyleForLoop.h"
15
#include "bscript/compiler/ast/DebugStatementMarker.h"
16
#include "bscript/compiler/ast/DoWhileLoop.h"
17
#include "bscript/compiler/ast/EmptyStatement.h"
18
#include "bscript/compiler/ast/EnumDeclaration.h"
19
#include "bscript/compiler/ast/ExitStatement.h"
20
#include "bscript/compiler/ast/Expression.h"
21
#include "bscript/compiler/ast/ForeachLoop.h"
22
#include "bscript/compiler/ast/FunctionCall.h"
23
#include "bscript/compiler/ast/Identifier.h"
24
#include "bscript/compiler/ast/IfThenElseStatement.h"
25
#include "bscript/compiler/ast/IntegerValue.h"
26
#include "bscript/compiler/ast/JumpStatement.h"
27
#include "bscript/compiler/ast/RepeatUntilLoop.h"
28
#include "bscript/compiler/ast/ReturnStatement.h"
29
#include "bscript/compiler/ast/StringValue.h"
30
#include "bscript/compiler/ast/UninitializedValue.h"
31
#include "bscript/compiler/ast/WhileLoop.h"
32
#include "bscript/compiler/astbuilder/BuilderWorkspace.h"
33
#include "bscript/compiler/model/CompilerWorkspace.h"
34
#include "bscript/compiler/model/ScopeName.h"
35

36
using EscriptGrammar::EscriptParser;
37

38
namespace Pol::Bscript
39
{
40
extern int include_debug;
41
}
42

43
namespace Pol::Bscript::Compiler
44
{
45
CompoundStatementBuilder::CompoundStatementBuilder(
7,180✔
46
    const SourceFileIdentifier& source_file_identifier, BuilderWorkspace& workspace )
7,180✔
47
    : SimpleStatementBuilder( source_file_identifier, workspace )
7,180✔
48
{
49
}
7,180✔
50

51
void CompoundStatementBuilder::add_statements( EscriptParser::StatementContext* ctx,
34,055✔
52
                                               std::vector<std::unique_ptr<Statement>>& statements )
53
{
54
  if ( include_debug )
34,055✔
55
  {
56
    add_intrusive_debug_marker( ctx, statements );
×
57
  }
58

59
  if ( auto expr_ctx = ctx->expression() )
34,055✔
60
  {
61
    statements.push_back( expression( expr_ctx, true ) );
17,702✔
62
  }
63
  else if ( auto if_st = ctx->ifStatement() )
16,353✔
64
  {
65
    statements.push_back( if_statement( if_st ) );
3,909✔
66
  }
67
  else if ( auto var_statement = ctx->varStatement() )
12,444✔
68
  {
69
    add_var_statements( var_statement, "", statements );
5,683✔
70
  }
71
  else if ( auto return_st = ctx->returnStatement() )
6,765✔
72
  {
73
    statements.push_back( return_statement( return_st ) );
4,805✔
74
  }
75
  else if ( auto foreach_statement = ctx->foreachStatement() )
1,960✔
76
  {
77
    statements.push_back( foreach_loop( foreach_statement ) );
481✔
78
  }
79
  else if ( auto for_st = ctx->forStatement() )
1,479✔
80
  {
81
    std::string label;
141✔
82
    if ( auto statement_label = for_st->statementLabel() )
141✔
83
      label = text( statement_label->IDENTIFIER() );
×
84
    statements.push_back( for_loop( for_st->forGroup(), std::move( label ) ) );
141✔
85
  }
141✔
86
  else if ( auto while_statement = ctx->whileStatement() )
1,338✔
87
  {
88
    statements.push_back( while_loop( while_statement ) );
417✔
89
  }
90
  else if ( auto break_st = ctx->breakStatement() )
921✔
91
  {
92
    statements.push_back( break_statement( break_st ) );
458✔
93
  }
94
  else if ( auto continue_st = ctx->continueStatement() )
463✔
95
  {
96
    statements.push_back( continue_statement( continue_st ) );
192✔
97
  }
98
  else if ( auto enum_statement = ctx->enumStatement() )
271✔
99
  {
100
    statements.push_back( enum_declaration( enum_statement ) );
55✔
101
  }
102
  else if ( auto case_st = ctx->caseStatement() )
216✔
103
  {
104
    statements.push_back( case_statement( case_st ) );
112✔
105
  }
106
  else if ( auto repeat_statement = ctx->repeatStatement() )
104✔
107
  {
108
    statements.push_back( repeat_until_loop( repeat_statement ) );
47✔
109
  }
110
  else if ( auto exit = ctx->exitStatement() )
57✔
111
  {
112
    statements.push_back( std::make_unique<ExitStatement>( location_for( *exit ) ) );
18✔
113
  }
114
  else if ( auto const_statement = ctx->constStatement() )
39✔
115
  {
116
    workspace.compiler_workspace.const_declarations.push_back(
×
117
        const_declaration( const_statement ) );
×
118
  }
119
  else if ( auto do_statement = ctx->doStatement() )
39✔
120
  {
121
    statements.push_back( do_while_loop( do_statement ) );
39✔
122
  }
123
  else if ( ctx->SEMI() )
×
124
  {
125
    statements.push_back( std::make_unique<EmptyStatement>( location_for( *ctx ) ) );
×
126
  }
127
  else
128
  {
129
    location_for( *ctx ).internal_error( "unhandled statement" );
×
130
  }
131
}
34,053✔
132

133
std::unique_ptr<BasicForLoop> CompoundStatementBuilder::basic_for_loop(
72✔
134
    EscriptParser::BasicForStatementContext* ctx, std::string label )
135
{
136
  auto identifier = text( ctx->IDENTIFIER() );
72✔
137
  auto first = expression( ctx->expression( 0 ) );
72✔
138
  auto last = expression( ctx->expression( 1 ) );
72✔
139
  auto body = block( ctx->block() );
72✔
140

141
  return std::make_unique<BasicForLoop>( location_for( *ctx ), std::move( label ),
72✔
142
                                         std::move( identifier ), std::move( first ),
72✔
143
                                         std::move( last ), std::move( body ) );
216✔
144
}
72✔
145

146
std::vector<std::unique_ptr<Statement>> CompoundStatementBuilder::block_statements(
10,053✔
147
    EscriptParser::BlockContext* ctx )
148
{
149
  std::vector<std::unique_ptr<Statement>> statements;
10,053✔
150

151
  for ( auto statement_context : ctx->statement() )
33,024✔
152
  {
153
    add_statements( statement_context, statements );
22,971✔
154
  }
10,053✔
155

156
  return statements;
10,053✔
157
}
×
158

159
std::unique_ptr<Block> CompoundStatementBuilder::block( EscriptParser::BlockContext* ctx )
6,216✔
160
{
161
  auto statements = block_statements( ctx );
6,216✔
162
  return std::make_unique<Block>( location_for( *ctx ), std::move( statements ) );
12,432✔
163
}
6,216✔
164

165
std::unique_ptr<CaseStatement> CompoundStatementBuilder::case_statement(
112✔
166
    EscriptParser::CaseStatementContext* ctx )
167
{
168
  // possibilities:
169
  // case (expr)
170
  //  4:
171
  //  "xz":
172
  //  CONSTANT:
173
  //  default:
174
  auto loc = location_for( *ctx );
112✔
175
  std::string case_label;
112✔
176
  if ( auto statement_label = ctx->statementLabel() )
112✔
177
    case_label = text( statement_label->IDENTIFIER() );
3✔
178

179
  auto determinant = expression( ctx->expression() );
112✔
180

181
  std::vector<std::unique_ptr<CaseDispatchGroup>> dispatch_groups;
112✔
182

183
  for ( auto group : ctx->switchBlockStatementGroup() )
459✔
184
  {
185
    std::vector<std::unique_ptr<Node>> selectors;
347✔
186

187
    for ( auto group_label : group->switchLabel() )
697✔
188
    {
189
      if ( auto integer_literal = group_label->integerLiteral() )
350✔
190
      {
191
        selectors.push_back( integer_value( integer_literal ) );
94✔
192
      }
193
      else if ( auto identifier = group_label->IDENTIFIER() )
256✔
194
      {
195
        selectors.push_back(
68✔
196
            std::make_unique<Identifier>( location_for( *identifier ), text( identifier ) ) );
136✔
197
      }
198
      else if ( auto string_literal = group_label->STRING_LITERAL() )
188✔
199
      {
200
        selectors.push_back( string_value( string_literal ) );
101✔
201
      }
202
      if ( auto bool_literal = group_label->boolLiteral() )
350✔
203
      {
204
        selectors.push_back( bool_value( bool_literal ) );
12✔
205
      }
206
      else if ( auto scoped_ident = group_label->scopedIdentifier() )
338✔
207
      {
208
        selectors.push_back( scoped_identifier( scoped_ident ) );
9✔
209
      }
210
      else if ( auto uninit = group_label->UNINIT() )
329✔
211
      {
212
        selectors.push_back( std::make_unique<UninitializedValue>( location_for( *uninit ) ) );
3✔
213
      }
214
      else if ( auto dflt = group_label->DEFAULT() )
326✔
215
      {
216
        selectors.push_back(
63✔
217
            std::make_unique<CaseDispatchDefaultSelector>( location_for( *dflt ) ) );
126✔
218
      }
219
    }
347✔
220
    auto dispatch_selectors =
221
        std::make_unique<CaseDispatchSelectors>( location_for( *group ), std::move( selectors ) );
347✔
222
    auto body = block( group->block() );
347✔
223
    auto dispatch_group = std::make_unique<CaseDispatchGroup>(
224
        location_for( *group ), std::move( dispatch_selectors ), std::move( body ) );
347✔
225
    dispatch_groups.push_back( std::move( dispatch_group ) );
347✔
226
  }
459✔
227
  auto holder = std::make_unique<CaseDispatchGroups>( loc, std::move( dispatch_groups ) );
112✔
228

229
  return std::make_unique<CaseStatement>( loc, std::move( case_label ), std::move( determinant ),
112✔
230
                                          std::move( holder ) );
336✔
231
}
112✔
232

233
std::unique_ptr<CstyleForLoop> CompoundStatementBuilder::cstyle_for_loop(
69✔
234
    EscriptParser::CstyleForStatementContext* ctx, std::string label )
235
{
236
  auto initializer = expression( ctx->expression( 0 ) );
69✔
237
  auto predicate = expression( ctx->expression( 1 ) );
69✔
238
  auto advancer = expression( ctx->expression( 2 ) );
69✔
239
  auto body = block( ctx->block() );
69✔
240
  return std::make_unique<CstyleForLoop>( location_for( *ctx ), std::move( label ),
69✔
241
                                          std::move( initializer ), std::move( predicate ),
69✔
242
                                          std::move( advancer ), std::move( body ) );
207✔
243
}
69✔
244

245
std::unique_ptr<DoWhileLoop> CompoundStatementBuilder::do_while_loop(
39✔
246
    EscriptParser::DoStatementContext* ctx )
247
{
248
  auto source_location = location_for( *ctx );
39✔
249
  std::string label;
39✔
250
  if ( auto statement_label = ctx->statementLabel() )
39✔
251
    label = text( statement_label->IDENTIFIER() );
2✔
252
  auto body = block( ctx->block() );
39✔
253
  auto predicate = expression( ctx->parExpression()->expression() );
39✔
254
  return std::make_unique<DoWhileLoop>( source_location, std::move( label ), std::move( body ),
39✔
255
                                        std::move( predicate ) );
117✔
256
}
39✔
257

258
std::unique_ptr<Statement> CompoundStatementBuilder::for_loop( EscriptParser::ForGroupContext* ctx,
141✔
259
                                                               std::string label )
260
{
261
  if ( auto cstyle = ctx->cstyleForStatement() )
141✔
262
  {
263
    return cstyle_for_loop( cstyle, std::move( label ) );
69✔
264
  }
265
  if ( auto basic = ctx->basicForStatement() )
72✔
266
  {
267
    return basic_for_loop( basic, std::move( label ) );
72✔
268
  }
269

NEW
270
  location_for( *ctx ).internal_error(
×
271
      "neither c-style nor basic-style for statement in for group" );
272
}
273

274
std::unique_ptr<Expression> CompoundStatementBuilder::foreach_iterable_expression(
481✔
275
    EscriptParser::ForeachIterableExpressionContext* ctx )
276
{
277
  if ( auto scoped_ident = ctx->scopedIdentifier() )
481✔
278
  {
279
    return scoped_identifier( scoped_ident );
3✔
280
  }
281
  if ( auto identifier = ctx->IDENTIFIER() )
478✔
282
  {
283
    return std::make_unique<Identifier>( location_for( *identifier ), text( identifier ) );
267✔
284
  }
285
  if ( auto m_call = ctx->functionCall() )
211✔
286
  {
287
    return function_call( location_for( *m_call ), m_call, ScopeName::None );
49✔
288
  }
289
  if ( auto scoped_call = ctx->scopedFunctionCall() )
162✔
290
  {
291
    return scoped_function_call( scoped_call );
3✔
292
  }
293
  if ( auto array_init = ctx->explicitArrayInitializer() )
159✔
294
  {
295
    return array_initializer( array_init );
9✔
296
  }
297
  if ( auto bare_array = ctx->bareArrayInitializer() )
150✔
298
  {
299
    return array_initializer( bare_array );
17✔
300
  }
301
  if ( auto par_ex = ctx->parExpression() )
133✔
302
  {
303
    return expression( par_ex->expression() );
133✔
304
  }
NEW
305
  location_for( *ctx ).internal_error( "unhandled foreach iterable expression" );
×
306
}
307

308
std::unique_ptr<ForeachLoop> CompoundStatementBuilder::foreach_loop(
481✔
309
    EscriptParser::ForeachStatementContext* ctx )
310
{
311
  auto source_location = location_for( *ctx );
481✔
312
  std::string label;
481✔
313
  if ( auto statement_label = ctx->statementLabel() )
481✔
314
    label = text( statement_label->IDENTIFIER() );
12✔
315
  std::string iterator_name = text( ctx->IDENTIFIER() );
481✔
316
  auto iterable = foreach_iterable_expression( ctx->foreachIterableExpression() );
481✔
317
  auto body = block( ctx->block() );
481✔
318
  return std::make_unique<ForeachLoop>( source_location, std::move( label ),
481✔
319
                                        std::move( iterator_name ), std::move( iterable ),
481✔
320
                                        std::move( body ) );
1,443✔
321
}
481✔
322

323
std::unique_ptr<Statement> CompoundStatementBuilder::if_statement(
3,909✔
324
    EscriptParser::IfStatementContext* ctx )
325
{
326
  //
327
  // if (expr0) block0 elseif (expr1) block1 ... elseif (exprN-1) blockN-1 else blockN
328
  //
329

330
  auto blocks = ctx->block();
3,909✔
331
  auto par_expression = ctx->parExpression();
3,909✔
332

333
  auto else_clause =
334
      ctx->ELSE() ? block( blocks.at( blocks.size() - 1 ) ) : std::unique_ptr<Node>();
3,909✔
335

336
  auto if_statement_ast = std::unique_ptr<Statement>();
3,909✔
337

338
  size_t num_expressions = par_expression.size();
3,909✔
339
  for ( auto clause_index = num_expressions; clause_index != 0; )
8,104✔
340
  {
341
    --clause_index;
4,195✔
342
    auto expression_ctx = par_expression.at( clause_index );
4,195✔
343
    auto expression_ast = expression( expression_ctx->expression() );
4,195✔
344
    auto consequent_ast = block( blocks.at( clause_index ) );
4,195✔
345
    auto alternative_ast =
346
        if_statement_ast ? std::move( if_statement_ast ) : std::move( else_clause );
4,195✔
347
    auto source_location = location_for( *expression_ctx );
4,195✔
348

349
    auto branch_selector = std::make_unique<BranchSelector>(
350
        source_location, BranchSelector::IfFalse, std::move( expression_ast ) );
4,195✔
351

352
    if ( alternative_ast )
4,195✔
353
    {
354
      if_statement_ast = std::make_unique<IfThenElseStatement>(
1,670✔
355
          source_location, std::move( branch_selector ), std::move( consequent_ast ),
835✔
356
          std::move( alternative_ast ) );
1,670✔
357
    }
358
    else
359
    {
360
      if_statement_ast = std::make_unique<IfThenElseStatement>(
6,720✔
361
          source_location, std::move( branch_selector ), std::move( consequent_ast ) );
6,720✔
362
    }
363
  }
4,195✔
364

365
  return if_statement_ast;
7,818✔
366
}
3,909✔
367

368
std::unique_ptr<RepeatUntilLoop> CompoundStatementBuilder::repeat_until_loop(
47✔
369
    EscriptParser::RepeatStatementContext* ctx )
370
{
371
  auto source_location = location_for( *ctx );
47✔
372
  std::string label;
47✔
373
  if ( auto statement_label = ctx->statementLabel() )
47✔
374
    label = text( statement_label->IDENTIFIER() );
×
375
  auto body = block( ctx->block() );
47✔
376
  auto predicate = expression( ctx->expression() );
47✔
377
  return std::make_unique<RepeatUntilLoop>( source_location, std::move( label ), std::move( body ),
47✔
378
                                            std::move( predicate ) );
141✔
379
}
47✔
380

381
std::unique_ptr<WhileLoop> CompoundStatementBuilder::while_loop(
417✔
382
    EscriptParser::WhileStatementContext* ctx )
383
{
384
  std::string label;
417✔
385
  if ( auto statement_label = ctx->statementLabel() )
417✔
386
    label = text( statement_label->IDENTIFIER() );
29✔
387
  auto source_location = location_for( *ctx );
417✔
388
  auto predicate = expression( ctx->parExpression()->expression() );
417✔
389
  auto body = block( ctx->block() );
417✔
390
  return std::make_unique<WhileLoop>( source_location, std::move( label ), std::move( predicate ),
417✔
391
                                      std::move( body ) );
1,251✔
392
}
417✔
393

394
}  // 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