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

polserver / polserver / 25918451630

15 May 2026 12:43PM UTC coverage: 60.929% (+2.1%) from 58.859%
25918451630

push

github

turleypol
added dynamic property which returns a pointer of the object instead of
a copy like the current imp.
needed to be able to eg store a vector

43 of 61 new or added lines in 2 files covered. (70.49%)

14455 existing lines in 345 files now uncovered.

44695 of 73356 relevant lines covered (60.93%)

449621.59 hits per line

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

78.69
/pol-core/bscript/bclassinstance.cpp
1
#include "bclassinstance.h"
2

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

11
namespace Pol::Bscript
12
{
13
BClassInstance::BClassInstance( ref_ptr<EScriptProgram> program, int index,
402✔
14
                                std::shared_ptr<ValueStackCont> globals )
402✔
15
    : BStruct( OTClassInstance ),
16
      prog_( std::move( program ) ),
402✔
17
      index_( index ),
402✔
18
      globals( std::move( globals ) )
804✔
19
{
20
  passert( index_ < prog_->class_descriptors.size() );
402✔
21
}
402✔
22

23
BClassInstance::BClassInstance( const BClassInstance& B ) : BStruct( B, OTClassInstance )
×
24
{
UNCOV
25
  prog_ = B.prog_;
×
UNCOV
26
  index_ = B.index_;
×
UNCOV
27
  globals = B.globals;
×
UNCOV
28
}
×
29

30
size_t BClassInstance::sizeEstimate() const
145✔
31
{
32
  return base::sizeEstimate() + Clib::memsize( constructors_called ) +
145✔
33
         sizeof( ref_ptr<EScriptProgram> ) + sizeof( unsigned int ) +
34
         sizeof( std::shared_ptr<ValueStackCont> );
145✔
35
}
36

37
ref_ptr<EScriptProgram> BClassInstance::prog() const
239✔
38
{
39
  return prog_;
239✔
40
}
41

42
unsigned BClassInstance::index() const
751✔
43
{
44
  return index_;
751✔
45
}
46

47
BFunctionRef* BClassInstance::makeMethod( const char* method_name )
191✔
48
{
49
  const auto& methods = prog_->class_descriptors[index_].methods;
191✔
50
  auto method_itr =
51
      std::find_if( methods.begin(), methods.end(),
191✔
52
                    [&]( const auto& it )
411✔
53
                    {
54
                      if ( it.first < prog_->symbols.length() )
411✔
55
                      {
56
                        return stricmp( method_name, prog_->symbols.array() + it.first ) == 0;
411✔
57
                      }
UNCOV
58
                      return false;
×
59
                    } );
60

61
  if ( method_itr == methods.end() )
191✔
62
    return nullptr;
6✔
63

64
  return new BFunctionRef( prog_, method_itr->second.function_reference_index, globals,
185✔
65
                           ValueStackCont{} );
370✔
66
}
67

68
const char* BClassInstance::typetag() const
6✔
69
{
70
  // Return the class name as the type tag.
71
  return prog_->symbols.array() + prog_->class_descriptors[index_].name_offset;
6✔
72
}
73

UNCOV
74
const char* BClassInstance::typeOf() const
×
75
{
UNCOV
76
  return "Class";
×
77
}
78

UNCOV
79
u8 BClassInstance::typeOfInt() const
×
80
{
UNCOV
81
  return OTClassInstance;
×
82
}
83

UNCOV
84
BObjectImp* BClassInstance::copy() const
×
85
{
UNCOV
86
  passert_always_r( false, "BClassInstance::copy() should never be called" );
×
87
  return nullptr;
88
}
89

UNCOV
90
bool BClassInstance::isTrue() const
×
91
{
UNCOV
92
  return true;
×
93
}
94

95
BObjectImp* BClassInstance::call_method( const char* method_name, Executor& ex )
666✔
96
{
97
  BFunctionRef* funcr = nullptr;
666✔
98

99
  BObjectImp* callee{ nullptr };
666✔
100
  // Prefer members over class methods by checking contents first.
101
  auto member_itr = contents().find( method_name );
666✔
102

103
  if ( member_itr != contents().end() )
666✔
104
  {
105
    // If the member exists and is NOT a function reference, we will still try
106
    // to "call" it. This is _intentional_, and will result in a runtime
107
    // BError. This is similar to `var foo := 3; print(foo.bar());`, resulting
108
    // in a "Method 'bar' not found" error.
109
    callee = member_itr->second.get()->impptr();
9✔
110

111
    funcr = member_itr->second.get()->impptr_if<BFunctionRef>();
9✔
112
  }
113
  else
114
  {
115
    // Have we already looked up this method?
116
    Executor::ClassMethodKey key{ ex.prog_, index(), method_name };
657✔
117
    auto cache_itr = ex.class_methods.find( key );
657✔
118
    if ( cache_itr != ex.class_methods.end() )
657✔
119
    {
120
      // Switch the callee to the function reference: if the
121
      // funcr->validCall fails, we will go into the funcref
122
      // ins_call_method, giving the error about invalid parameter counts.
123
      funcr = cache_itr->second->impptr_if<BFunctionRef>();
466✔
124
      callee = funcr;
466✔
125
      method_name = getObjMethod( MTH_CALL_METHOD )->code;
466✔
126
    }
127
    else
128
    {
129
      // Does the class define this method?
130
      funcr = makeMethod( method_name );
191✔
131

132
      if ( funcr != nullptr )
191✔
133
      {
134
        // Cache the method for future lookups
135
        ex.class_methods[key] = BObjectRef( funcr );
185✔
136

137
        // Switch the callee to the function reference.
138
        callee = funcr;
185✔
139
        method_name = getObjMethod( MTH_CALL_METHOD )->code;
185✔
140
      }
141
    }
142
  }
657✔
143

144
  if ( funcr != nullptr )
666✔
145
  {
146
    Instruction jmp;
657✔
147
    int id;
148

149
    // Add `this` to the front of the argument list only for class methods,
150
    // skipping eg. an instance member function reference set via
151
    // `this.foo := @(){};`.
152
    if ( funcr->class_method() )
657✔
153
    {
154
      id = MTH_CALL_METHOD;
651✔
155
      ex.fparams.insert( ex.fparams.begin(), ex.ValueStack.back() );
651✔
156
    }
157
    else
158
    {
159
      id = MTH_CALL;
6✔
160
    }
161

162
    if ( funcr->validCall( id, ex, &jmp ) )
657✔
163
    {
164
      BObjectRef funcobj( funcr );  // valuestack gets modified, protect BFunctionRef
636✔
165
      ex.call_function_reference( funcr, nullptr, jmp );
636✔
166
      return BSpecialUserFuncJump::get();
636✔
167
    }
636✔
168
  }
657✔
169
  if ( callee )
30✔
170
    return callee->call_method( method_name, ex );
24✔
171
  return new BError( fmt::format( "Method '{}' not found in class '{}'", method_name, typetag() ) );
12✔
172
}
173

174
BObjectImp* BClassInstance::call_method_id( const int id, Executor& ex, bool /*forcebuiltin*/ )
3✔
175
{
176
  auto method = getObjMethod( id );
3✔
177
  return call_method( method->code, ex );
3✔
178
}
179

180
BObjectRef BClassInstance::get_member_id( const int id )
120✔
181
{
182
  if ( id == MBR_FUNCTION )
120✔
183
  {
184
    const auto funcref_index =
185
        prog_->class_descriptors.at( index_ ).constructor_function_reference_index;
18✔
186

187
    return BObjectRef( new BFunctionRef( prog_, funcref_index, globals, ValueStackCont{} ) );
36✔
188
  }
189

190
  return base::get_member_id( id );
102✔
191
}
192

193
std::string BClassInstance::getStringRep() const
327✔
194
{
195
  auto class_name = prog_->symbols.array() + prog_->class_descriptors[index_].name_offset;
327✔
196
  return fmt::format( "<class {}>", class_name );
654✔
197
}
198

199
BClassInstanceRef::BClassInstanceRef( BClassInstance* inst )
770✔
200
    : BObjectImp( BObjectType::OTClassInstanceRef ), class_instance_( inst )
770✔
201
{
202
}
770✔
203

204
size_t BClassInstanceRef::sizeEstimate() const
145✔
205
{
206
  return sizeof( BClassInstanceRef ) + class_instance_->sizeEstimate();
145✔
207
}
208

209
const char* BClassInstanceRef::typeOf() const
3✔
210
{
211
  return "ClassInstanceRef";
3✔
212
}
213

214
u8 BClassInstanceRef::typeOfInt() const
6✔
215
{
216
  return OTClassInstanceRef;
6✔
217
}
218

219
BObjectImp* BClassInstanceRef::copy() const
368✔
220
{
221
  return new BClassInstanceRef( class_instance_.get() );
368✔
222
}
223

UNCOV
224
bool BClassInstanceRef::isTrue() const
×
225
{
UNCOV
226
  return true;
×
227
}
228

229
BObjectImp* BClassInstanceRef::call_method( const char* methodname, Executor& ex )
663✔
230
{
231
  return class_instance_->call_method( methodname, ex );
663✔
232
}
233

234
BObjectImp* BClassInstanceRef::call_method_id( const int id, Executor& ex, bool forcebuiltin )
3✔
235
{
236
  return class_instance_->call_method_id( id, ex, forcebuiltin );
3✔
237
}
238

239
BObjectRef BClassInstanceRef::get_member_id( const int id )
120✔
240
{
241
  return class_instance_->get_member_id( id );
120✔
242
}
243

244
std::string BClassInstanceRef::getStringRep() const
327✔
245
{
246
  return class_instance_->getStringRep();
327✔
247
}
248

249
ContIterator* BClassInstanceRef::createIterator( BObject* pIterVal )
6✔
250
{
251
  return class_instance_->createIterator( pIterVal );
6✔
252
}
253

UNCOV
254
BObjectRef BClassInstanceRef::OperSubscript( const BObject& obj )
×
255
{
UNCOV
256
  return class_instance_->OperSubscript( obj );
×
257
}
258

259
BObjectRef BClassInstanceRef::set_member( const char* membername, BObjectImp* value, bool copy )
401✔
260
{
261
  return class_instance_->set_member( membername, value, copy );
401✔
262
}
263

264
BObjectRef BClassInstanceRef::get_member( const char* membername )
1,503✔
265
{
266
  return class_instance_->get_member( membername );
1,503✔
267
}
268

UNCOV
269
BObjectRef BClassInstanceRef::operDotPlus( const char* name )
×
270
{
UNCOV
271
  return class_instance_->operDotPlus( name );
×
272
}
273

UNCOV
274
BObjectRef BClassInstanceRef::operDotMinus( const char* name )
×
275
{
UNCOV
276
  return class_instance_->operDotMinus( name );
×
277
}
278

UNCOV
279
BObjectRef BClassInstanceRef::operDotQMark( const char* name )
×
280
{
UNCOV
281
  return class_instance_->operDotQMark( name );
×
282
}
283

UNCOV
284
BObjectImp* BClassInstanceRef::array_assign( BObjectImp* idx, BObjectImp* target, bool copy )
×
285
{
UNCOV
286
  return class_instance_->array_assign( idx, target, copy );
×
287
}
288
}  // namespace Pol::Bscript
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