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

polserver / polserver / 28964407401

08 Jul 2026 05:58PM UTC coverage: 61.276% (+0.3%) from 60.927%
28964407401

push

github

web-flow
Split bobject header  (#892)

* splitted bobject header

* fixed runecl

* crashfix

* missing header

* more missing (debug build)

* runecl debug include

* renamed contiter, moved formating

* removed more unused headers

1145 of 1517 new or added lines in 23 files covered. (75.48%)

217 existing lines in 4 files now uncovered.

44972 of 73392 relevant lines covered (61.28%)

557151.3 hits per line

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

88.03
/pol-core/bscript/bfuncref.cpp
1
#include "bfuncref.h"
2

3
#include "../clib/stlutil.h"
4
#include "bclassinstance.h"
5
#include "berror.h"
6
#include "blong.h"
7
#include "bobject.h"
8
#include "executor.h"
9
#include "objmethods.h"
10

11
#include <fmt/format.h>
12

13
namespace Pol::Bscript
14
{
15
BFunctionRef::BFunctionRef( ref_ptr<EScriptProgram> program, unsigned int pid,
3,267✔
16
                            unsigned function_reference_index,
17
                            std::weak_ptr<ValueStackCont> globals, ValueStackCont&& captures )
3,267✔
18
    : BObjectImp( OTFuncRef ),
19
      prog_( std::move( program ) ),
3,267✔
20
      original_pid_( pid ),
3,267✔
21
      function_reference_index_( function_reference_index ),
3,267✔
22
      globals( std::move( globals ) ),
3,267✔
23
      captures( std::move( captures ) )
6,534✔
24
{
25
  passert( function_reference_index_ < prog_->function_references.size() );
3,267✔
26
}
3,267✔
27

28
BFunctionRef::BFunctionRef( const BFunctionRef& B )
841✔
29
    : BFunctionRef( B.prog_, B.original_pid_, B.function_reference_index_, B.globals,
1,682✔
30
                    ValueStackCont( B.captures ) )
841✔
31
{
32
}
841✔
33

34
BObjectImp* BFunctionRef::copy() const
841✔
35
{
36
  return new BFunctionRef( *this );
841✔
37
}
38

39
size_t BFunctionRef::sizeEstimate() const
99✔
40
{
41
  return sizeof( BFunctionRef ) + Clib::memsize( captures );
99✔
42
}
43

44
bool BFunctionRef::isTrue() const
3✔
45
{
46
  return false;
3✔
47
}
48

NEW
49
bool BFunctionRef::operator==( const BObjectImp& /*objimp*/ ) const
×
50
{
NEW
51
  return false;
×
52
}
53

54
BObjectImp* BFunctionRef::selfIsObjImp( const BObjectImp& other ) const
94✔
55
{
56
  auto classinstref = dynamic_cast<const BClassInstanceRef*>( &other );
94✔
57
  if ( !classinstref )
94✔
NEW
58
    return new BLong( 0 );
×
59

60
  auto classinst = classinstref->instance();
94✔
61

62
  // Class index could be maxint if the function reference is not a class
63
  // method.
64
  if ( class_index() >= prog_->class_descriptors.size() )
94✔
NEW
65
    return new BLong( 0 );
×
66

67
  const auto& my_constructors = prog_->class_descriptors.at( class_index() ).constructors;
94✔
68
  passert( !my_constructors.empty() );
94✔
69
  const auto& my_descriptor = my_constructors.front();
94✔
70

71
  const auto& other_descriptors =
72
      classinst->prog()->class_descriptors.at( classinst->index() ).constructors;
94✔
73

74
  // An optimization for same program: since strings are never duplicated inside
75
  // the data section, we can just check for offset equality.
76
  if ( prog_ == classinst->prog() )
94✔
77
  {
78
    for ( const auto& other_descriptor : other_descriptors )
195✔
79
    {
80
      if ( my_descriptor.type_tag_offset == other_descriptor.type_tag_offset )
180✔
81
        return new BLong( 1 );
54✔
82
    }
83
  }
84
  // For different programs, we must check for string equality.
85
  else
86
  {
87
    auto type_tag = prog_->symbols.array() + my_descriptor.type_tag_offset;
25✔
88
    for ( const auto& other_descriptor : other_descriptors )
63✔
89
    {
90
      auto other_type_tag = classinst->prog()->symbols.array() + other_descriptor.type_tag_offset;
51✔
91
      if ( strcmp( type_tag, other_type_tag ) == 0 )
51✔
92
        return new BLong( 1 );
13✔
93
    }
94
  }
95

96
  return new BLong( 0 );
27✔
97
}
98

99
std::string BFunctionRef::getStringRep() const
157✔
100
{
101
  return "FunctionObject";
157✔
102
}
103

104
BObjectImp* BFunctionRef::call_method( const char* methodname, Executor& ex )
21✔
105
{
106
  ObjMethod* objmethod = getKnownObjMethod( methodname );
21✔
107
  if ( objmethod != nullptr )
21✔
108
    return call_method_id( objmethod->id, ex );
21✔
NEW
109
  return nullptr;
×
110
}
111

112
bool BFunctionRef::validCall( const int id, Executor& ex, Instruction* inst ) const
38,235✔
113
{
114
  auto passed_args = static_cast<int>( ex.numParams() );
38,235✔
115

116
  auto [expected_min_args, expected_max_args] = expected_args();
38,235✔
117

118
  if ( id != MTH_CALL && id != MTH_NEW && id != MTH_CALL_METHOD )
38,235✔
NEW
119
    return false;
×
120

121
  if ( id == MTH_NEW && !constructor() )
38,235✔
122
    return false;
27✔
123

124
  if ( passed_args < expected_min_args || ( passed_args > expected_max_args && !variadic() ) )
38,208✔
125
    return false;
99✔
126

127
  inst->func = &Executor::ins_nop;
38,109✔
128

129
  if ( passed_args >= expected_max_args )
38,109✔
130
  {
131
    inst->token.lval = pc();
37,891✔
132
  }
133
  else
134
  {
135
    auto default_parameter_address_index = expected_max_args - passed_args - 1;
218✔
136
    passert( default_parameter_address_index >= 0 &&
218✔
137
             default_parameter_address_index <
138
                 static_cast<int>( default_parameter_addresses().size() ) );
139
    inst->token.lval = default_parameter_addresses().at( default_parameter_address_index );
218✔
140
  }
141

142
  return true;
38,109✔
143
}
144

NEW
145
bool BFunctionRef::validCall( const char* methodname, Executor& ex, Instruction* inst ) const
×
146
{
NEW
147
  ObjMethod* objmethod = getKnownObjMethod( methodname );
×
NEW
148
  if ( objmethod == nullptr )
×
NEW
149
    return false;
×
NEW
150
  return validCall( objmethod->id, ex, inst );
×
151
}
152

153
int BFunctionRef::numParams() const
111,462✔
154
{
155
  return prog_->function_references[function_reference_index_].parameter_count;
111,462✔
156
}
157

158
unsigned BFunctionRef::pc() const
37,891✔
159
{
160
  return prog_->function_references[function_reference_index_].address;
37,891✔
161
}
162

163
bool BFunctionRef::variadic() const
74,598✔
164
{
165
  return prog_->function_references[function_reference_index_].is_variadic;
74,598✔
166
}
167

168
ref_ptr<EScriptProgram> BFunctionRef::prog() const
235✔
169
{
170
  return prog_;
235✔
171
}
172

173
unsigned int BFunctionRef::pid() const
38,109✔
174
{
175
  return original_pid_;
38,109✔
176
}
177

178
unsigned BFunctionRef::class_index() const
269✔
179
{
180
  return prog_->function_references[function_reference_index_].class_index;
269✔
181
}
182

183
bool BFunctionRef::constructor() const
270✔
184
{
185
  return prog_->function_references[function_reference_index_].is_constructor;
270✔
186
}
187

188
bool BFunctionRef::class_method() const
682✔
189
{
190
  return prog_->function_references[function_reference_index_].class_index <
682✔
191
         std::numeric_limits<unsigned>::max();
682✔
192
}
193

194
const std::vector<unsigned>& BFunctionRef::default_parameter_addresses() const
77,104✔
195
{
196
  return prog_->function_references[function_reference_index_].default_parameter_addresses;
77,104✔
197
}
198

199
int BFunctionRef::default_parameter_count() const
76,668✔
200
{
201
  return static_cast<int>( default_parameter_addresses().size() );
76,668✔
202
}
203

204
std::pair<int, int> BFunctionRef::expected_args() const
38,334✔
205
{
206
  auto expected_min_args = numParams() - default_parameter_count();  // remove default parameters
38,334✔
207

208
  return { expected_min_args, expected_min_args + default_parameter_count() };
38,334✔
209
}
210

211
BObjectImp* BFunctionRef::call_method_id( const int id, Executor& ex, bool /*forcebuiltin*/ )
126✔
212
{
213
  bool adjust_for_this = false;
126✔
214

215
  // These are only entered if `ins_call_method_id` did _not_ do the call jump.
216
  switch ( id )
126✔
217
  {
218
  case MTH_NEW:
54✔
219
    if ( !constructor() )
54✔
220
      return new BError( "Function is not a constructor" );
27✔
221
    // intentional fallthrough
222
  case MTH_CALL_METHOD:
223
    adjust_for_this = true;
48✔
224
    // intentional fallthrough
225
  case MTH_CALL:
99✔
226
  {
227
    auto [expected_min_args, expected_max_args] = expected_args();
99✔
228
    auto param_count = ex.numParams();
99✔
229

230
    if ( adjust_for_this )
99✔
231
    {
232
      --expected_min_args;
48✔
233
      --expected_max_args;
48✔
234
      --param_count;
48✔
235
    }
236

237
    auto expected_arg_string = variadic() ? fmt::format( "{}+", expected_min_args )
99✔
238
                               : ( expected_min_args == expected_max_args )
63✔
239
                                   ? std::to_string( expected_min_args )
63✔
240
                                   : fmt::format( "{}-{}", expected_min_args, expected_max_args );
159✔
241

NEW
242
    return new BError( fmt::format( "Invalid argument count: expected {}, got {}",
×
243
                                    expected_arg_string, param_count ) );
198✔
244
  }
99✔
NEW
245
  default:
×
NEW
246
    return nullptr;
×
247
  }
248
}
249
}  // namespace Pol::Bscript
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc