• 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

18.98
/pol-core/bscript/tkn_strm.cpp
1
/** @file
2
 *
3
 * @par History
4
 */
5

6

7
#include <sstream>
8
#include <stddef.h>
9

10
#include "objmembers.h"
11
#include "objmethods.h"
12
#include "token.h"
13
#include "tokens.h"
14

15

16
namespace Pol
17
{
18
namespace Bscript
19
{
20
void Token::printOn( std::ostream& os ) const
297✔
21
{
22
  switch ( id )
297✔
23
  {
24
  case TOK_LONG:
63✔
25
    os << lval << "L";
63✔
26
    break;
63✔
27
  case TOK_DOUBLE:
×
28
    os << dval << "LF";
×
29
    break;
×
NEW
30
  case TOK_BOOL:
×
NEW
31
    os << fmt::format( "{} (boolean)", static_cast<bool>( lval ) );
×
NEW
32
    break;
×
33
  case TOK_IDENT:
×
34
    os << token;
×
35
    break;
×
36
  case INS_ADDMEMBER2:
×
37
    os << "addmember(" << token << ")";
×
38
    break;
×
39
  case INS_ADDMEMBER_ASSIGN:
×
40
    os << "addmember-assign(" << token << ")";
×
41
    break;
×
42
  case TOK_STRING:
18✔
43
    os << '\"' << token << '\"';
18✔
44
    break;
18✔
45
  case TOK_LOCALVAR:
49✔
46
    os << "local #" << lval;
49✔
47
    if ( !token.empty() )
49✔
48
      os << " (" << token << ")";
×
49
    break;
49✔
50
  case TOK_GLOBALVAR:
12✔
51
    os << "global #" << lval;
12✔
52
    if ( !token.empty() )
12✔
53
      os << " (" << token << ")";
×
54
    break;
12✔
55

56
  case TOK_ERROR:
4✔
57
    os << "error";
4✔
58
    break;
4✔
59
  case TOK_DICTIONARY:
×
60
    os << "dictionary";
×
61
    break;
×
62

63
  case TOK_MULT:
×
64
    os << "*";
×
65
    break;
×
66
  case TOK_DIV:
×
67
    os << "/";
×
68
    break;
×
69
  case TOK_ADD:
×
70
    os << "+";
×
71
    break;
×
72

73
  case TOK_INSERTINTO:
×
74
    os << "init{}";
×
75
    break;
×
76
  case TOK_SUBTRACT:
×
77
    os << "-";
×
78
    break;
×
79
  case TOK_PLUSEQUAL:
×
80
    os << "+=";
×
81
    break;
×
82
  case TOK_MINUSEQUAL:
×
83
    os << "-=";
×
84
    break;
×
85
  case TOK_TIMESEQUAL:
×
86
    os << "*=";
×
87
    break;
×
88
  case TOK_DIVIDEEQUAL:
×
89
    os << "/=";
×
90
    break;
×
91
  case TOK_MODULUSEQUAL:
×
92
    os << "%=";
×
93
    break;
×
94

95
  case TOK_ASSIGN:
5✔
96
    os << ":=";
5✔
97
    break;
5✔
98
  case INS_ASSIGN_LOCALVAR:
3✔
99
    os << "local" << lval;
3✔
100
    if ( !token.empty() )
3✔
101
      os << " (" << token << ")";
×
102
    os << " := ";
3✔
103
    break;
3✔
104
  case INS_ASSIGN_GLOBALVAR:
×
105
    os << "global" << lval;
×
106
    if ( !token.empty() )
×
107
      os << " (" << token << ")";
×
108
    os << " := ";
×
109
    break;
×
110
  case INS_ASSIGN_CONSUME:
×
111
    os << ":= #";
×
112
    break;
×
113
  case INS_SUBSCRIPT_ASSIGN_CONSUME:
×
114
    os << "[] := (" << lval << ") #";
×
115
    break;
×
116
  case INS_SUBSCRIPT_ASSIGN:
×
117
    os << "[] := (" << lval << ")";
×
118
    break;
×
119
  case TOK_LESSTHAN:
×
120
    os << "<";
×
121
    break;
×
122
  case TOK_LESSEQ:
×
123
    os << "<=";
×
124
    break;
×
125
  case TOK_GRTHAN:
8✔
126
    os << ">";
8✔
127
    break;
8✔
128
  case TOK_GREQ:
×
129
    os << ">=";
×
130
    break;
×
131
  case TOK_EQUAL1:
×
132
    os << "=";
×
133
    break;
×
134
  case TOK_EQUAL:
4✔
135
    os << "==";
4✔
136
    break;
4✔
137
  case TOK_NEQ:
7✔
138
    os << "<>";
7✔
139
    break;
7✔
140
  case TOK_AND:
7✔
141
    os << "&&";
7✔
142
    break;
7✔
143
  case TOK_OR:
×
144
    os << "||";
×
145
    break;
×
146
  case TOK_ARRAY_SUBSCRIPT:
3✔
147
    os << "[] " << lval;
3✔
148
    break;
3✔
149
  case INS_MULTISUBSCRIPT:
9✔
150
    os << "[";
9✔
151
    for ( int i = 1; i < lval; ++i )
18✔
152
      os << ",";
9✔
153
    os << "]";
9✔
154
    break;
9✔
155
  case INS_MULTISUBSCRIPT_ASSIGN:
×
156
    os << "[";
×
157
    for ( int i = 1; i < lval; ++i )
×
158
      os << ",";
×
159
    os << "] :=";
×
160
    break;
×
161
  case TOK_ADDMEMBER:
×
162
    os << ".+";
×
163
    break;
×
164
  case TOK_DELMEMBER:
×
165
    os << ".-";
×
166
    break;
×
167
  case TOK_CHKMEMBER:
×
168
    os << ".?";
×
169
    break;
×
170
  case TOK_MEMBER:
×
171
    os << ".";
×
172
    break;
×
173
  case INS_GET_MEMBER:
×
174
    os << "get member '" << token << "'";
×
175
    break;
×
176
  case INS_SET_MEMBER:
×
177
    os << "set member '" << token << "'";
×
178
    break;
×
179
  case INS_SET_MEMBER_CONSUME:
×
180
    os << "set member '" << token << "' #";
×
181
    break;
×
182
  case INS_GET_MEMBER_ID:
14✔
183
    os << "get member id '" << getObjMember( lval )->code << "' (" << lval << ")";
14✔
184
    break;
14✔
185
  case INS_SET_MEMBER_ID:
×
186
    os << "set member id '" << getObjMember( lval )->code << "' (" << lval << ")";
×
187
    break;
×
188
  case INS_SET_MEMBER_ID_CONSUME:
×
189
    os << "set member id '" << getObjMember( lval )->code << "' (" << lval << ") #";
×
190
    break;
×
191
  case INS_SET_MEMBER_ID_CONSUME_PLUSEQUAL:
×
192
    os << "set member id '" << getObjMember( lval )->code << "' (" << lval << ")  += #";
×
193
    break;
×
194
  case INS_SET_MEMBER_ID_CONSUME_MINUSEQUAL:
×
195
    os << "set member id '" << getObjMember( lval )->code << "' (" << lval << ")  -= #";
×
196
    break;
×
197
  case INS_SET_MEMBER_ID_CONSUME_TIMESEQUAL:
×
198
    os << "set member id '" << getObjMember( lval )->code << "' (" << lval << ")  *= #";
×
199
    break;
×
200
  case INS_SET_MEMBER_ID_CONSUME_DIVIDEEQUAL:
×
201
    os << "set member id '" << getObjMember( lval )->code << "' (" << lval << ")  /= #";
×
202
    break;
×
203
  case INS_SET_MEMBER_ID_CONSUME_MODULUSEQUAL:
×
204
    os << "set member id '" << getObjMember( lval )->code << "' (" << lval << ")  %= #";
×
205
    break;
×
206

207
  case INS_CALL_METHOD_ID:
15✔
208
    os << "Call Method id " << getObjMethod( lval )->code << " (#" << lval << ", "
15✔
209
       << static_cast<int>( type ) << " params)";
15✔
210
    break;
15✔
211
  case TOK_IN:
×
212
    os << "in";
×
213
    break;
×
214
  case INS_DICTIONARY_ADDMEMBER:
×
215
    os << "add dictionary member";
×
216
    break;
×
217

218
  case TOK_UNPLUS:
×
219
    os << "unary +";
×
220
    break;
×
221
  case TOK_UNMINUS:
×
222
    os << "unary -";
×
223
    break;
×
224
  case TOK_LOG_NOT:
×
225
    os << "!";
×
226
    break;
×
227
  case TOK_CONSUMER:
21✔
228
    os << "#";
21✔
229
    break;
21✔
230
  case TOK_REFTO:
×
231
    os << "refto";
×
232
    break;
×
233
  case TOK_UNUSED:
×
234
    os << "unused";
×
235
    break;
×
236
  case TOK_BITAND:
×
237
    os << "&";
×
238
    break;
×
239
  case TOK_BITOR:
×
240
    os << "|";
×
241
    break;
×
242
  case TOK_BSRIGHT:
×
243
    os << ">>";
×
244
    break;
×
245
  case TOK_BSLEFT:
×
246
    os << "<<";
×
247
    break;
×
248
  case TOK_BITXOR:
×
249
    os << "^";
×
250
    break;
×
251
  case TOK_BITWISE_NOT:
×
252
    os << "~";
×
253
    break;
×
254
  case TOK_MODULUS:
×
255
    os << "%";
×
256
    break;
×
257

258
  case INS_INITFOREACH:
6✔
259
    os << "initforeach @" << lval;
6✔
260
    break;
6✔
261
  case INS_STEPFOREACH:
3✔
262
    os << "stepforeach @" << lval;
3✔
263
    break;
3✔
264
  case INS_CASEJMP:
×
265
    os << "casejmp";
×
266
    break;
×
267
  case INS_INITFOR:
4✔
268
    os << "initfor @" << lval;
4✔
269
    break;
4✔
270
  case INS_NEXTFOR:
2✔
271
    os << "nextfor @" << lval;
2✔
272
    break;
2✔
273

274
  case TOK_TERM:
×
275
    os << "Terminator";
×
276
    break;
×
277

278
  case TOK_LPAREN:
×
279
    os << "(";
×
280
    break;
×
281
  case TOK_RPAREN:
×
282
    os << ")";
×
283
    break;
×
284
  case TOK_LBRACKET:
×
285
    os << "[";
×
286
    break;
×
287
  case TOK_RBRACKET:
×
288
    os << "]";
×
289
    break;
×
290
  case TOK_LBRACE:
×
291
    os << "{";
×
292
    break;
×
293
  case TOK_RBRACE:
×
294
    os << "}";
×
295
    break;
×
296

297
  case RSV_JMPIFTRUE:
×
298
    os << "if true goto " << lval;
×
299
    break;
×
300
  case RSV_JMPIFFALSE:
8✔
301
    os << "if false goto " << lval;
8✔
302

303
    break;
8✔
304
  case RSV_ST_IF:
×
305
    os << "if";
×
306
    break;
×
307
  case RSV_GOTO:
6✔
308
    os << "goto " << lval;
6✔
309
    break;
6✔
310
  case RSV_GOSUB:
×
311
    os << "gosub" << lval;
×
312
    break;
×
313
  case RSV_EXIT:
×
314
    os << "exit";
×
315
    break;
×
316
  case RSV_RETURN:
×
317
    os << "return";
×
318
    break;
×
319
  case RSV_LOCAL:
4✔
320
    os << "decl local #" << lval;
4✔
321
    break;
4✔
322
  case RSV_GLOBAL:
×
323
    os << "decl global #" << lval;
×
324
    break;
×
325
  case RSV_VAR:
×
326
    os << "var";
×
327
    break;
×
328
  case RSV_CONST:
×
329
    os << "const";
×
330
    break;
×
331
  case RSV_FUNCTION:
×
332
    os << "function";
×
333
    break;
×
334
  case RSV_ENDFUNCTION:
×
335
    os << "endfunction";
×
336
    break;
×
337
  case RSV_DO:
×
338
    os << "do";
×
339
    break;
×
340
  case RSV_DOWHILE:
×
341
    os << "dowhile";
×
342
    break;
×
343
  case RSV_WHILE:
×
344
    os << "while";
×
345
    break;
×
346
  case RSV_ENDWHILE:
×
347
    os << "endwhile";
×
348
    break;
×
349
  case RSV_REPEAT:
×
350
    os << "repeat";
×
351
    break;
×
352
  case RSV_UNTIL:
×
353
    os << "until";
×
354
    break;
×
355
  case RSV_FOR:
×
356
    os << "for";
×
357
    break;
×
358
  case RSV_ENDFOR:
×
359
    os << "endfor";
×
360
    break;
×
361
  case RSV_FOREACH:
×
362
    os << "foreach";
×
363
    break;
×
364
  case RSV_ENDFOREACH:
×
365
    os << "endforeach";
×
366
    break;
×
367
  case INS_DECLARE_ARRAY:
×
368
    os << "declare array";
×
369
    break;
×
370
  case TOK_ARRAY:
1✔
371
    os << "array";
1✔
372
    break;
1✔
373
  case TOK_STRUCT:
×
374
    os << "struct";
×
375
    break;
×
376
  case TOK_CLASSINST:
×
377
    os << "class instance #" << lval;
×
378
    break;
×
379
  case INS_UNINIT:
×
380
    os << "uninit";
×
381
    break;
×
382
  case RSV_USE_MODULE:
×
383
    os << "use module";
×
384
    break;
×
385
  case RSV_INCLUDE_FILE:
×
386
    os << "include file";
×
387
    break;
×
388

389
  case CTRL_LABEL:
×
390
    os << token << ":";
×
391
    break;
×
392

393
  case TOK_COMMA:
×
394
    os << "','";
×
395
    break;
×
396
  case TOK_SEMICOLON:
×
397
    os << "';'";
×
398
    break;
×
399

400
  case CTRL_STATEMENTBEGIN:
×
401
    os << "[" << ( !token.empty() ? token : "--source not available--" ) << "]";
×
402
    break;
×
403
  case CTRL_PROGEND:
×
404
    os << "progend";
×
405
    break;
×
406
  case CTRL_MAKELOCAL:
×
407
    os << "makelocal";
×
408
    break;
×
409
  case CTRL_JSR_USERFUNC:
×
410
    os << "jmp userfunc @" << lval;
×
411
    break;
×
412
  case INS_CHECK_MRO:
×
413
    os << "check mro (this at offset " << lval << ")";
×
414
    break;
×
415
  case INS_POP_PARAM_BYREF:
×
416
    os << "pop param byref '" << token << "'";
×
417
    break;
×
418
  case INS_POP_PARAM:
×
419
    os << "pop param '" << token << "'";
×
420
    break;
×
421
  case INS_GET_ARG:
×
422
    os << "get arg '" << token << "'";
×
423
    break;
×
424
  case CTRL_LEAVE_BLOCK:
7✔
425
    os << "leave block(" << lval << ")";
7✔
426
    break;
7✔
427

428
  case INS_CALL_METHOD:
×
429
    os << "Call Method " << token << " (" << lval << " params)";
×
430
    break;
×
431
  case TOK_USERFUNC:
×
432
    os << "User Function " << ( !token.empty() ? token : "--function name not available--" );
×
433
    break;
×
434
  case TOK_FUNCREF:
×
435
    os << "Function Ref " << ( !token.empty() ? token : "--function name not available--" ) << "@"
×
436
       << lval;
×
437
    break;
×
438
  case TOK_UNPLUSPLUS:
×
439
    os << "unary ++";
×
440
    break;
×
441
  case TOK_UNMINUSMINUS:
×
442
    os << "unary --";
×
443
    break;
×
444
  case TOK_UNPLUSPLUS_POST:
×
445
    os << "unary ++ post";
×
446
    break;
×
447
  case TOK_UNMINUSMINUS_POST:
×
448
    os << "unary -- post";
×
449
    break;
×
450
  case INS_SET_MEMBER_ID_UNPLUSPLUS:
×
451
    os << "set member id '" << getObjMember( lval )->code << "' unary ++";
×
452
    break;
×
453
  case INS_SET_MEMBER_ID_UNMINUSMINUS:
×
454
    os << "set member id '" << getObjMember( lval )->code << "' unary --";
×
455
    break;
×
456
  case INS_SET_MEMBER_ID_UNPLUSPLUS_POST:
×
457
    os << "set member id '" << getObjMember( lval )->code << "' unary ++ post";
×
458
    break;
×
459
  case INS_SET_MEMBER_ID_UNMINUSMINUS_POST:
×
460
    os << "set member id '" << getObjMember( lval )->code << "' unary -- post";
×
461
    break;
×
462
  case INS_SKIPIFTRUE_ELSE_CONSUME:
×
463
    os << "peek at top of stack; skip " << lval << " instructions if true, otherwise consume it";
×
464
    break;
×
465
  case RSV_COLON:
×
466
    os << "':'";
×
467
    break;
×
468
  case RSV_PROGRAM:
×
469
    os << "program";
×
470
    break;
×
471
  case RSV_ENDPROGRAM:
×
472
    os << "endprogram";
×
473
    break;
×
474
  case RSV_ENUM:
×
475
    os << "enum";
×
476
    break;
×
477
  case RSV_ENDENUM:
×
478
    os << "endenum";
×
479
    break;
×
480
  case RSV_ELVIS:
×
481
    os << "?: (elvis)";
×
482
    break;
×
483
  case TOK_INTERPOLATE_STRING:
×
484
    os << "interpolate string "
485
       << "(" << lval << "parts)";
×
486
    break;
×
487
  case TOK_FORMAT_EXPRESSION:
×
488
    os << "format expression";
×
489
    break;
×
490

491
  case INS_UNPACK_SEQUENCE:
×
492
  {
493
    int rest_index = lval > 0x7F ? ( ( lval >> 7 ) & 0x7F ) : -1;
×
494
    os << fmt::format( "unpack sequence ({} elements, rest index {})", lval & 0x7F, rest_index );
×
495
    break;
×
496
  }
497
  case INS_UNPACK_INDICES:
×
498
  {
499
    int rest_index = lval > 0x7F ? ( ( lval >> 7 ) & 0x7F ) : -1;
×
500
    os << fmt::format( "unpack indices ({} elements, rest index {})", lval & 0x7F, rest_index );
×
501
    break;
×
502
  }
503
  case INS_TAKE_GLOBAL:
×
504
    os << "take global #" << lval;
×
505
    break;
×
506
  case INS_TAKE_LOCAL:
×
507
    os << "take local #" << lval;
×
508
    break;
×
509

510
  case TOK_FUNC:
14✔
511
  {
512
    os << "Func(" << (int)module << "," << lval << "): ";
14✔
513
    if ( !token.empty() )
14✔
514
      os << token;
14✔
515
    else
516
      os << "<unknown>";
×
517
    return;
14✔
518
  }
519

520
  case TOK_SPREAD:
×
521
    os << ( lval ? "spread-into" : "create-spread" );
×
522
    break;
×
523

NEW
524
  case INS_LOGICAL_JUMP:
×
NEW
525
    os << fmt::format( "logical jump if {} to {}", type != TYP_LOGICAL_JUMP_FALSE, lval );
×
NEW
526
    break;
×
NEW
527
  case INS_LOGICAL_CONVERT:
×
NEW
528
    os << "logical convert";
×
NEW
529
    break;
×
530

531
  default:
×
532
    os << "Unknown Token: (" << int( id ) << "," << int( type );
×
533
    if ( !token.empty() )
×
534
      os << ",'" << token << "'";
×
535
    os << ")";
×
536
    break;
×
537
  }
538
}
539

540
std::ostream& operator<<( std::ostream& os, const Token& tok )
297✔
541
{
542
  tok.printOn( os );
297✔
543
  return os;
297✔
544
}
545
}  // namespace Bscript
546
}  // namespace Pol
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