/** @file * * @par History * - 2006/10/28 Shinigami: GCC 4.1.1 fix - invalid use of constructor as a template * - 2009/09/05 Turley: Added struct .? and .- as shortcut for .exists() and .erase() * - 2009/12/21 Turley: ._method() call fix */ #ifndef BSCRIPT_BOBJECT_H #define BSCRIPT_BOBJECT_H #ifdef NDEBUG #define BOBJECTIMP_DEBUG 0 #else #define BOBJECTIMP_DEBUG 1 #endif #if BOBJECTIMP_DEBUG #define INLINE_BOBJECTIMP_CTOR 0 #else #define INLINE_BOBJECTIMP_CTOR 1 #endif #include #include "eprog.h" #include "../clib/fixalloc.h" #include "../clib/passert.h" #include "../clib/rawtypes.h" #include "../clib/refptr.h" #include "../clib/spinlock.h" #if INLINE_BOBJECTIMP_CTOR #include "escriptv.h" #endif #include #include #include #include #include /** * Bscript namespace is for escript stuff, like compiler and basic modules */ namespace Pol::Bscript { class BObjectImp; class BObject; class BObjectRef; class ContIterator; class Executor; class Instruction; class BLong; class Double; class String; class ObjArray; class UninitObject; class BError; class BStruct; class BDictionary; class BBoolean; class BFunctionRef; class BClassInstance; class BClassInstanceRef; class BContinuation; class BSpread; class BRegExp; class BSpecialUserFuncJump; class BApplicObjBase; using ValueStackCont = std::vector; class BObjectImp : public ref_counted { public: /** * Specify the object type for the child classes * * @warning This is directly returned by TypeOfInt(), so don't forget to * keep constants inside basic.em in sync! It is better to always * add new values at the end and use explicit int conversion to * avoid breaking backward compatibility. */ enum BObjectType : u8 { OTUnknown = 0, OTUninit = 1, OTString = 2, OTLong = 3, OTDouble = 4, OTArray = 5, // unused OTApplicObj = 7, OTError = 8, OTDictionary = 9, OTStruct = 10, OTPacket = 11, OTBinaryFile = 12, OTXMLFile = 13, OTXMLNode = 14, OTXMLAttributes = 15, OTPolCoreRef = 16, // non direct used constants (for TypeOfInt) start OTAccountRef = 17, OTConfigFileRef = 18, OTConfigElemRef = 19, OTDataFileRef = 20, OTDataElemRef = 21, OTGuildRef = 22, OTPartyRef = 23, OTBoundingBox = 24, OTDebugContext = 25, OTScriptExRef = 26, OTPackage = 27, OTMenuRef = 28, OTMobileRef = 29, OTOfflineMobileRef = 30, OTItemRef = 31, OTBoatRef = 32, OTMultiRef = 33, OTClientRef = 34, // non direct used Constants (for TypeOfInt) end OTSQLConnection = 35, OTSQLResultSet = 36, OTSQLRow = 37, OTBoolean = 38, OTFuncRef = 39, OTExportScript = 40, OTStorageArea = 41, OTClassInstanceRef = 42, OTRegExp = 43, // Used internally only during executor runtime. Can be modified without // breaking compatibility. OTContinuation = 100, OTSpread = 101, OTClassInstance = 102, OTSpecialUserFuncJump = 103, }; #if INLINE_BOBJECTIMP_CTOR explicit BObjectImp( BObjectType type ) : type_( type ) { ++eobject_imp_count; ++eobject_imp_constructions; } ~BObjectImp() override { --eobject_imp_count; } #else explicit BObjectImp( BObjectType type ); virtual ~BObjectImp(); #endif // Class Machinery: static BObjectImp* unpack( const char* pstr ); static BObjectImp* unpack( std::istream& is ); bool isa( BObjectType type ) const; BObjectType type() const; #if BOBJECTIMP_DEBUG unsigned int instance() const { return instance_; } #endif static const char* typestr( BObjectType typ ); virtual BObjectImp* copy() const = 0; virtual std::string getStringRep() const = 0; virtual std::string getFormattedStringRep() const; virtual size_t sizeEstimate() const = 0; virtual const char* typeOf() const; virtual u8 typeOfInt() const; virtual std::string pack() const; virtual void packonto( std::string& os ) const; virtual void printOn( std::ostream& ) const; virtual bool operator==( const BObjectImp& objimp ) const; virtual bool operator<( const BObjectImp& objimp ) const; virtual bool operator<=( const BObjectImp& objimp ) const; virtual bool operator>( const BObjectImp& objimp ) const; virtual bool operator>=( const BObjectImp& objimp ) const; virtual bool operator!=( const BObjectImp& objimp ) const; virtual BObjectImp* selfIsObjImp( const BObjectImp& objimp ) const; virtual BObjectImp* selfIsObj( const BObjectImp& objimp ) const; virtual BObjectImp* selfPlusObjImp( const BObjectImp& objimp ) const; virtual BObjectImp* selfPlusObj( const BObjectImp& objimp ) const; virtual BObjectImp* selfPlusObj( const BLong& objimp ) const; virtual BObjectImp* selfPlusObj( const Double& objimp ) const; virtual BObjectImp* selfPlusObj( const String& objimp ) const; virtual BObjectImp* selfPlusObj( const ObjArray& objimp ) const; virtual void selfPlusObjImp( BObjectImp& objimp, BObject& obj ); virtual void selfPlusObj( BObjectImp& objimp, BObject& obj ); virtual void selfPlusObj( BLong& objimp, BObject& obj ); virtual void selfPlusObj( Double& objimp, BObject& obj ); virtual void selfPlusObj( String& objimp, BObject& obj ); virtual void selfPlusObj( ObjArray& objimp, BObject& obj ); virtual BObjectImp* selfMinusObjImp( const BObjectImp& objimp ) const; virtual BObjectImp* selfMinusObj( const BObjectImp& objimp ) const; virtual BObjectImp* selfMinusObj( const BLong& objimp ) const; virtual BObjectImp* selfMinusObj( const Double& objimp ) const; virtual BObjectImp* selfMinusObj( const String& objimp ) const; virtual BObjectImp* selfMinusObj( const ObjArray& objimp ) const; virtual void selfMinusObjImp( BObjectImp& objimp, BObject& obj ); virtual void selfMinusObj( BObjectImp& objimp, BObject& obj ); virtual void selfMinusObj( BLong& objimp, BObject& obj ); virtual void selfMinusObj( Double& objimp, BObject& obj ); virtual void selfMinusObj( String& objimp, BObject& obj ); virtual void selfMinusObj( ObjArray& objimp, BObject& obj ); virtual BObjectImp* selfTimesObjImp( const BObjectImp& objimp ) const; virtual BObjectImp* selfTimesObj( const BObjectImp& objimp ) const; virtual BObjectImp* selfTimesObj( const BLong& objimp ) const; virtual BObjectImp* selfTimesObj( const Double& objimp ) const; virtual BObjectImp* selfTimesObj( const String& objimp ) const; virtual BObjectImp* selfTimesObj( const ObjArray& objimp ) const; virtual void selfTimesObjImp( BObjectImp& objimp, BObject& obj ); virtual void selfTimesObj( BObjectImp& objimp, BObject& obj ); virtual void selfTimesObj( BLong& objimp, BObject& obj ); virtual void selfTimesObj( Double& objimp, BObject& obj ); virtual void selfTimesObj( String& objimp, BObject& obj ); virtual void selfTimesObj( ObjArray& objimp, BObject& obj ); virtual BObjectImp* selfDividedByObjImp( const BObjectImp& objimp ) const; virtual BObjectImp* selfDividedByObj( const BObjectImp& objimp ) const; virtual BObjectImp* selfDividedByObj( const BLong& objimp ) const; virtual BObjectImp* selfDividedByObj( const Double& objimp ) const; virtual BObjectImp* selfDividedByObj( const String& objimp ) const; virtual BObjectImp* selfDividedByObj( const ObjArray& objimp ) const; virtual void selfDividedByObjImp( BObjectImp& objimp, BObject& obj ); virtual void selfDividedByObj( BObjectImp& objimp, BObject& obj ); virtual void selfDividedByObj( BLong& objimp, BObject& obj ); virtual void selfDividedByObj( Double& objimp, BObject& obj ); virtual void selfDividedByObj( String& objimp, BObject& obj ); virtual void selfDividedByObj( ObjArray& objimp, BObject& obj ); virtual BObjectImp* selfModulusObjImp( const BObjectImp& objimp ) const; virtual BObjectImp* selfModulusObj( const BObjectImp& objimp ) const; virtual BObjectImp* selfModulusObj( const BLong& objimp ) const; virtual BObjectImp* selfModulusObj( const Double& objimp ) const; virtual BObjectImp* selfModulusObj( const String& objimp ) const; virtual BObjectImp* selfModulusObj( const ObjArray& objimp ) const; virtual void selfModulusObjImp( BObjectImp& objimp, BObject& obj ); virtual void selfModulusObj( BObjectImp& objimp, BObject& obj ); virtual void selfModulusObj( BLong& objimp, BObject& obj ); virtual void selfModulusObj( Double& objimp, BObject& obj ); virtual void selfModulusObj( String& objimp, BObject& obj ); virtual void selfModulusObj( ObjArray& objimp, BObject& obj ); virtual BObjectImp* selfBitShiftRightObjImp( const BObjectImp& objimp ) const; virtual BObjectImp* selfBitShiftRightObj( const BObjectImp& objimp ) const; virtual BObjectImp* selfBitShiftRightObj( const BLong& objimp ) const; virtual BObjectImp* selfBitShiftRightObj( const Double& objimp ) const; virtual BObjectImp* selfBitShiftRightObj( const String& objimp ) const; virtual BObjectImp* selfBitShiftRightObj( const ObjArray& objimp ) const; virtual void selfBitShiftRightObjImp( BObjectImp& objimp, BObject& obj ); virtual void selfBitShiftRightObj( BObjectImp& objimp, BObject& obj ); virtual void selfBitShiftRightObj( BLong& objimp, BObject& obj ); virtual void selfBitShiftRightObj( Double& objimp, BObject& obj ); virtual void selfBitShiftRightObj( String& objimp, BObject& obj ); virtual void selfBitShiftRightObj( ObjArray& objimp, BObject& obj ); virtual BObjectImp* selfBitShiftLeftObjImp( const BObjectImp& objimp ) const; virtual BObjectImp* selfBitShiftLeftObj( const BObjectImp& objimp ) const; virtual BObjectImp* selfBitShiftLeftObj( const BLong& objimp ) const; virtual BObjectImp* selfBitShiftLeftObj( const Double& objimp ) const; virtual BObjectImp* selfBitShiftLeftObj( const String& objimp ) const; virtual BObjectImp* selfBitShiftLeftObj( const ObjArray& objimp ) const; virtual void selfBitShiftLeftObjImp( BObjectImp& objimp, BObject& obj ); virtual void selfBitShiftLeftObj( BObjectImp& objimp, BObject& obj ); virtual void selfBitShiftLeftObj( BLong& objimp, BObject& obj ); virtual void selfBitShiftLeftObj( Double& objimp, BObject& obj ); virtual void selfBitShiftLeftObj( String& objimp, BObject& obj ); virtual void selfBitShiftLeftObj( ObjArray& objimp, BObject& obj ); virtual BObjectImp* selfBitAndObjImp( const BObjectImp& objimp ) const; virtual BObjectImp* selfBitAndObj( const BObjectImp& objimp ) const; virtual BObjectImp* selfBitAndObj( const BLong& objimp ) const; virtual BObjectImp* selfBitAndObj( const Double& objimp ) const; virtual BObjectImp* selfBitAndObj( const String& objimp ) const; virtual BObjectImp* selfBitAndObj( const ObjArray& objimp ) const; virtual void selfBitAndObjImp( BObjectImp& objimp, BObject& obj ); virtual void selfBitAndObj( BObjectImp& objimp, BObject& obj ); virtual void selfBitAndObj( BLong& objimp, BObject& obj ); virtual void selfBitAndObj( Double& objimp, BObject& obj ); virtual void selfBitAndObj( String& objimp, BObject& obj ); virtual void selfBitAndObj( ObjArray& objimp, BObject& obj ); virtual BObjectImp* selfBitXorObjImp( const BObjectImp& objimp ) const; virtual BObjectImp* selfBitXorObj( const BObjectImp& objimp ) const; virtual BObjectImp* selfBitXorObj( const BLong& objimp ) const; virtual BObjectImp* selfBitXorObj( const Double& objimp ) const; virtual BObjectImp* selfBitXorObj( const String& objimp ) const; virtual BObjectImp* selfBitXorObj( const ObjArray& objimp ) const; virtual void selfBitXorObjImp( BObjectImp& objimp, BObject& obj ); virtual void selfBitXorObj( BObjectImp& objimp, BObject& obj ); virtual void selfBitXorObj( BLong& objimp, BObject& obj ); virtual void selfBitXorObj( Double& objimp, BObject& obj ); virtual void selfBitXorObj( String& objimp, BObject& obj ); virtual void selfBitXorObj( ObjArray& objimp, BObject& obj ); virtual BObjectImp* selfBitOrObjImp( const BObjectImp& objimp ) const; virtual BObjectImp* selfBitOrObj( const BObjectImp& objimp ) const; virtual BObjectImp* selfBitOrObj( const BLong& objimp ) const; virtual BObjectImp* selfBitOrObj( const Double& objimp ) const; virtual BObjectImp* selfBitOrObj( const String& objimp ) const; virtual BObjectImp* selfBitOrObj( const ObjArray& objimp ) const; virtual void selfBitOrObjImp( BObjectImp& objimp, BObject& obj ); virtual void selfBitOrObj( BObjectImp& objimp, BObject& obj ); virtual void selfBitOrObj( BLong& objimp, BObject& obj ); virtual void selfBitOrObj( Double& objimp, BObject& obj ); virtual void selfBitOrObj( String& objimp, BObject& obj ); virtual void selfBitOrObj( ObjArray& objimp, BObject& obj ); virtual BObjectImp* bitnot() const; virtual BObjectRef operDotPlus( const char* name ); virtual BObjectRef operDotMinus( const char* name ); virtual BObjectRef operDotQMark( const char* name ); virtual void operInsertInto( BObject& obj, const BObjectImp& objimp ); virtual void operPlusEqual( BObject& obj, BObjectImp& objimp ); virtual void operMinusEqual( BObject& obj, BObjectImp& objimp ); virtual void operTimesEqual( BObject& obj, BObjectImp& objimp ); virtual void operDivideEqual( BObject& obj, BObjectImp& objimp ); virtual void operModulusEqual( BObject& obj, BObjectImp& objimp ); virtual BObject operator-() const; virtual char /*BObjectRef */ member( const BObject& obj ) const; virtual char /*BObjectImp* */ str_member( const std::string& membername ) const; virtual BObjectImp* call_method( const char* methodname, Executor& ex ); virtual BObjectImp* call_method_id( const int id, Executor& ex, bool forcebuiltin = false ); virtual BObjectRef set_member( const char* membername, BObjectImp* valueimp, bool copy ); virtual BObjectRef get_member( const char* membername ); virtual BObjectRef get_member_id( const int id ); // test id virtual BObjectRef set_member_id( const int id, BObjectImp* valueimp, bool copy ); // test id virtual BObjectRef OperSubscript( const BObject& obj ); virtual BObjectRef OperMultiSubscript( std::stack& indices ); virtual BObjectRef OperMultiSubscriptAssign( std::stack& indices, BObjectImp* target ); virtual bool isTrue() const; virtual long contains( const BObjectImp& objimp ) const; virtual BObjectImp* array_assign( BObjectImp* idx, BObjectImp* target, bool copy ); virtual BObjectImp* inverse() const; virtual void selfPlusPlus(); virtual void selfMinusMinus(); virtual ContIterator* createIterator( BObject* pIterVal ); friend std::ostream& operator<<( std::ostream&, const BObjectImp& ); private: BObjectType type_; #if BOBJECTIMP_DEBUG unsigned int instance_; static unsigned int instances_; static Clib::SpinLock bobjectimp_lock; #endif }; inline char /*BObjectRef */ BObjectImp::member( const BObject& ) const { return 0; } inline char /*BObjectImp* */ BObjectImp::str_member( const std::string& ) const { return 0; } inline bool BObjectImp::isa( BObjectType type ) const { return ( type == type_ ); } inline BObjectImp::BObjectType BObjectImp::type() const { return type_; } namespace { template // static_assert(false) is not valid, need a typedependent false struct always_false : std::false_type { }; } // namespace // accepts const/non-const BObjectImp pointers template requires std::is_base_of_v>> T* impptrIf( I* objimp ) { if ( !objimp ) return nullptr; #define impif_test( type ) std::is_same_v, type> #define impif_return( ot ) return objimp->isa( ot ) ? static_cast( objimp ) : nullptr #define impif_i( ot, type ) \ if constexpr ( impif_test( type ) ) \ impif_return( ot ) #define impif_e( ot, type ) else if constexpr ( impif_test( type ) ) impif_return( ot ) impif_i( BObjectImp::OTUninit, UninitObject ); impif_e( BObjectImp::OTString, String ); impif_e( BObjectImp::OTLong, BLong ); impif_e( BObjectImp::OTDouble, Double ); impif_e( BObjectImp::OTArray, ObjArray ); impif_e( BObjectImp::OTError, BError ); impif_e( BObjectImp::OTDictionary, BDictionary ); impif_e( BObjectImp::OTStruct, BStruct ); impif_e( BObjectImp::OTBoolean, BBoolean ); impif_e( BObjectImp::OTFuncRef, BFunctionRef ); // BClassInstance objects are never given to scripts directly, so no need for // inclusion here (so far...) impif_e( BObjectImp::OTClassInstanceRef, BClassInstanceRef ); impif_e( BObjectImp::OTContinuation, BContinuation ); impif_e( BObjectImp::OTSpread, BSpread ); impif_e( BObjectImp::OTRegExp, BRegExp ); impif_e( BObjectImp::OTSpecialUserFuncJump, BSpecialUserFuncJump ); impif_e( BObjectImp::OTApplicObj, BApplicObjBase ); else static_assert( always_false::value, "unsupported type" ); #undef impif_i #undef impif_e #undef impif_return #undef impif_test } class BObject : public ref_counted { public: explicit BObject( BObjectImp* objimp ) : ref_counted(), objimp( objimp ) { passert( objimp ); } BObject( const BObject& obj ) : ref_counted(), objimp( obj.objimp ) {} ~BObject() override = default; BObject& operator=( const BObject& ) = delete; size_t sizeEstimate() const; void* operator new( std::size_t len ); void operator delete( void* ); bool operator!=( const BObject& obj ) const; bool operator==( const BObject& obj ) const; bool operator<( const BObject& obj ) const; bool operator<=( const BObject& obj ) const; bool operator>( const BObject& obj ) const; bool operator>=( const BObject& obj ) const; BObjectImp* operator->() const { return objimp.get(); } bool isTrue() const { return objimp->isTrue(); } BObject* clone() const; bool isa( BObjectImp::BObjectType type ) const; friend std::ostream& operator<<( std::ostream&, const BObject& ); void printOn( std::ostream& ) const; template T* impptr(); template const T* impptr() const; template T* impptr_if(); // also als freestanding function available template T* impptr_if() const; // also als freestanding function available template T& impref(); template const T& impref() const; virtual void setimp( BObjectImp* imp ); private: ref_ptr objimp; }; class BConstObject : public BObject { public: explicit BConstObject( BObjectImp* objimp ) : BObject( objimp ) {} ~BConstObject() override = default; void setimp( BObjectImp* ) override { /* do nothing */ }; // This class does not use a specific fixed allocator, sharing the BObject // one. Do not add new members to this class. }; using BObjectImpRefVec = std::vector>; extern Clib::fixed_allocator bobject_alloc; inline void* BObject::operator new( std::size_t /*len*/ ) { return bobject_alloc.allocate(); } inline void BObject::operator delete( void* p ) { bobject_alloc.deallocate( p ); } inline bool BObject::isa( BObjectImp::BObjectType type ) const { return objimp->isa( type ); } template inline T* BObject::impptr() { return static_cast( objimp.get() ); } template inline const T* BObject::impptr() const { return static_cast( objimp.get() ); } template T* BObject::impptr_if() { return impptrIf( objimp.get() ); } template T* BObject::impptr_if() const { return impptrIf( objimp.get() ); } template inline T& BObject::impref() { return static_cast( *objimp ); } template inline const T& BObject::impref() const { return static_cast( *objimp ); } inline void BObject::setimp( BObjectImp* imp ) { objimp.set( imp ); } class BObjectRef : public ref_ptr { public: explicit BObjectRef( BObject* pobj = nullptr ) : ref_ptr( pobj ) {} explicit BObjectRef( BObjectImp* pimp ) : ref_ptr( new BObject( pimp ) ) {} void set( BObject* obj ) { ref_ptr::set( obj ); } void set( BObjectImp* imp ) { ref_ptr::set( new BObject( imp ) ); } size_t sizeEstimate() const; }; class UninitObject final : public BObjectImp { public: UninitObject(); UninitObject( const UninitObject& i ); static UninitObject* SharedInstance; static ref_ptr SharedInstanceOwner; static BObjectRef SharedInstanceRef; BObjectImp* copy() const override; size_t sizeEstimate() const override; std::string getStringRep() const override { return ""; } void printOn( std::ostream& os ) const override; bool isTrue() const override; bool operator==( const BObjectImp& objimp ) const override; bool operator<( const BObjectImp& objimp ) const override; void* operator new( std::size_t len ); void operator delete( void* ); static UninitObject* create() { return SharedInstance; } static void ReleaseSharedInstance() { SharedInstanceOwner.clear(); SharedInstance = nullptr; } }; extern Clib::fixed_allocator uninit_alloc; inline void* UninitObject::operator new( std::size_t /*len*/ ) { return uninit_alloc.allocate(); } inline void UninitObject::operator delete( void* p ) { uninit_alloc.deallocate( p ); } class ObjArray final : public BObjectImp { public: using NameCont = std::vector; using name_iterator = NameCont::iterator; using const_name_iterator = NameCont::const_iterator; using Cont = std::vector; using iterator = Cont::iterator; using const_iterator = Cont::const_iterator; NameCont name_arr; Cont ref_arr; ObjArray(); ObjArray( const ObjArray& i ); // copy constructor void packonto( std::string& str ) const override; static BObjectImp* unpack( std::istream& is ); size_t sizeEstimate() const override; BObjectImp* copy() const override; BObjectRef operDotPlus( const char* name ) override; long contains( const BObjectImp& imp ) const override; void operInsertInto( BObject& obj, const BObjectImp& objimp ) override; BObjectImp* selfPlusObjImp( const BObjectImp& other ) const override; BObjectImp* selfPlusObj( const BObjectImp& objimp ) const override; BObjectImp* selfPlusObj( const BLong& objimp ) const override; BObjectImp* selfPlusObj( const Double& objimp ) const override; BObjectImp* selfPlusObj( const String& objimp ) const override; BObjectImp* selfPlusObj( const ObjArray& objimp ) const override; void selfPlusObjImp( BObjectImp& objimp, BObject& obj ) override; void selfPlusObj( BObjectImp& objimp, BObject& obj ) override; void selfPlusObj( BLong& objimp, BObject& obj ) override; void selfPlusObj( Double& objimp, BObject& obj ) override; void selfPlusObj( String& objimp, BObject& obj ) override; void selfPlusObj( ObjArray& objimp, BObject& obj ) override; BObjectImp* call_method( const char* methodname, Executor& ex ) override; BObjectImp* call_method_id( const int id, Executor& ex, bool forcebuiltin = false ) override; BObjectRef set_member( const char* membername, BObjectImp* value, bool copy ) override; BObjectRef get_member( const char* membername ) override; void addElement( BObjectImp* imp ); const BObjectImp* imp_at( unsigned index ) const; // 1-based std::string getStringRep() const override; void printOn( std::ostream& os ) const override; BObjectImp* array_assign( BObjectImp* idx, BObjectImp* target, bool copy ) override; BObjectRef OperSubscript( const BObject& obj ) override; BObjectRef OperMultiSubscript( std::stack& indices ) override; bool operator==( const BObjectImp& objimp ) const override; ContIterator* createIterator( BObject* pIterVal ) override; protected: explicit ObjArray( BObjectType type ); void deepcopy(); }; class BLong final : public BObjectImp { using base = BObjectImp; public: #if BOBJECTIMP_DEBUG explicit BLong( int lval = 0L ); BLong( const BLong& L ); #else explicit BLong( int lval = 0L ) : BObjectImp( OTLong ), lval_( static_cast( lval ) ) {} BLong( const BLong& L ) : BObjectImp( OTLong ), lval_( L.lval_ ) {} #endif private: ~BLong() override = default; public: void* operator new( std::size_t len ); void operator delete( void* ); void operator delete( void*, size_t ); static BObjectImp* unpack( std::istream& is ); static std::string pack( int val ); void packonto( std::string& os ) const override; size_t sizeEstimate() const override; int value() const { return lval_; } int increment() { return ++lval_; } public: // Class Machinery BObjectImp* copy() const override; BObjectImp* inverse() const override { return new BLong( -lval_ ); } void copyvalue( const BLong& ni ) { lval_ = ni.lval_; } bool isTrue() const override; bool operator==( const BObjectImp& objimp ) const override; bool operator<( const BObjectImp& objimp ) const override; BObjectImp* selfPlusObjImp( const BObjectImp& objimp ) const override; BObjectImp* selfPlusObj( const BLong& objimp ) const override; BObjectImp* selfPlusObj( const Double& objimp ) const override; BObjectImp* selfPlusObj( const String& objimp ) const override; void selfPlusObjImp( BObjectImp& objimp, BObject& obj ) override; void selfPlusObj( BLong& objimp, BObject& obj ) override; void selfPlusObj( Double& objimp, BObject& obj ) override; void selfPlusObj( String& objimp, BObject& obj ) override; BObjectImp* selfMinusObjImp( const BObjectImp& objimp ) const override; BObjectImp* selfMinusObj( const BLong& objimp ) const override; BObjectImp* selfMinusObj( const Double& objimp ) const override; BObjectImp* selfMinusObj( const String& objimp ) const override; void selfMinusObjImp( BObjectImp& objimp, BObject& obj ) override; void selfMinusObj( BLong& objimp, BObject& obj ) override; void selfMinusObj( Double& objimp, BObject& obj ) override; void selfMinusObj( String& objimp, BObject& obj ) override; BObjectImp* selfTimesObjImp( const BObjectImp& objimp ) const override; BObjectImp* selfTimesObj( const BLong& objimp ) const override; BObjectImp* selfTimesObj( const Double& objimp ) const override; void selfTimesObjImp( BObjectImp& objimp, BObject& obj ) override; void selfTimesObj( BLong& objimp, BObject& obj ) override; void selfTimesObj( Double& objimp, BObject& obj ) override; BObjectImp* selfDividedByObjImp( const BObjectImp& objimp ) const override; BObjectImp* selfDividedByObj( const BLong& objimp ) const override; BObjectImp* selfDividedByObj( const Double& objimp ) const override; void selfDividedByObjImp( BObjectImp& objimp, BObject& obj ) override; void selfDividedByObj( BLong& objimp, BObject& obj ) override; void selfDividedByObj( Double& objimp, BObject& obj ) override; BObjectImp* selfModulusObjImp( const BObjectImp& objimp ) const override; BObjectImp* selfModulusObj( const BLong& objimp ) const override; BObjectImp* selfModulusObj( const Double& objimp ) const override; void selfModulusObjImp( BObjectImp& objimp, BObject& obj ) override; void selfModulusObj( BLong& objimp, BObject& obj ) override; void selfModulusObj( Double& objimp, BObject& obj ) override; BObjectImp* selfBitShiftRightObjImp( const BObjectImp& objimp ) const override; BObjectImp* selfBitShiftRightObj( const BLong& objimp ) const override; void selfBitShiftRightObjImp( BObjectImp& objimp, BObject& obj ) override; void selfBitShiftRightObj( BLong& objimp, BObject& obj ) override; BObjectImp* selfBitShiftLeftObjImp( const BObjectImp& objimp ) const override; BObjectImp* selfBitShiftLeftObj( const BLong& objimp ) const override; void selfBitShiftLeftObjImp( BObjectImp& objimp, BObject& obj ) override; void selfBitShiftLeftObj( BLong& objimp, BObject& obj ) override; BObjectImp* selfBitAndObjImp( const BObjectImp& objimp ) const override; BObjectImp* selfBitAndObj( const BLong& objimp ) const override; void selfBitAndObjImp( BObjectImp& objimp, BObject& obj ) override; void selfBitAndObj( BLong& objimp, BObject& obj ) override; BObjectImp* selfBitXorObjImp( const BObjectImp& objimp ) const override; BObjectImp* selfBitXorObj( const BLong& objimp ) const override; void selfBitXorObjImp( BObjectImp& objimp, BObject& obj ) override; void selfBitXorObj( BLong& objimp, BObject& obj ) override; BObjectImp* selfBitOrObjImp( const BObjectImp& objimp ) const override; BObjectImp* selfBitOrObj( const BLong& objimp ) const override; void selfBitOrObjImp( BObjectImp& objimp, BObject& obj ) override; void selfBitOrObj( BLong& objimp, BObject& obj ) override; BObjectImp* bitnot() const override; void selfPlusPlus() override { ++lval_; } void selfMinusMinus() override { --lval_; } std::string getStringRep() const override; void printOn( std::ostream& ) const override; protected: int lval_; }; extern Clib::fixed_allocator blong_alloc; inline void* BLong::operator new( std::size_t len ) { (void)len; passert_paranoid( len == sizeof( BLong ) ); return blong_alloc.allocate(); } inline void BLong::operator delete( void* p ) { blong_alloc.deallocate( p ); } inline void BLong::operator delete( void* p, size_t /*len*/ ) { blong_alloc.deallocate( p ); } class Double final : public BObjectImp { using base = BObjectImp; public: explicit Double( double dval = 0.0 ) : BObjectImp( OTDouble ), dval_( dval ) {} Double( const Double& dbl ) : BObjectImp( OTDouble ), dval_( dbl.dval_ ) {} static std::string double_to_string( double val ); protected: ~Double() override = default; public: void* operator new( std::size_t len ); void operator delete( void* ); static BObjectImp* unpack( std::istream& is ); void packonto( std::string& str ) const override; size_t sizeEstimate() const override; double value() const { return dval_; } void copyvalue( const Double& dbl ) { dval_ = dbl.dval_; } double increment() { return ++dval_; } public: // Class Machinery bool isTrue() const override { return ( dval_ != 0.0 ); } BObjectImp* copy() const override { return new Double( *this ); } bool operator==( const BObjectImp& objimp ) const override; bool operator<( const BObjectImp& objimp ) const override; BObjectImp* selfPlusObjImp( const BObjectImp& objimp ) const override; BObjectImp* selfPlusObj( const BLong& objimp ) const override; BObjectImp* selfPlusObj( const Double& objimp ) const override; BObjectImp* selfPlusObj( const String& objimp ) const override; void selfPlusObjImp( BObjectImp& objimp, BObject& obj ) override; void selfPlusObj( BLong& objimp, BObject& obj ) override; void selfPlusObj( Double& objimp, BObject& obj ) override; void selfPlusObj( String& objimp, BObject& obj ) override; BObjectImp* selfMinusObjImp( const BObjectImp& objimp ) const override; BObjectImp* selfMinusObj( const BLong& objimp ) const override; BObjectImp* selfMinusObj( const Double& objimp ) const override; BObjectImp* selfMinusObj( const String& objimp ) const override; void selfMinusObjImp( BObjectImp& objimp, BObject& obj ) override; void selfMinusObj( BLong& objimp, BObject& obj ) override; void selfMinusObj( Double& objimp, BObject& obj ) override; void selfMinusObj( String& objimp, BObject& obj ) override; BObjectImp* selfTimesObjImp( const BObjectImp& objimp ) const override; BObjectImp* selfTimesObj( const BLong& objimp ) const override; BObjectImp* selfTimesObj( const Double& objimp ) const override; void selfTimesObjImp( BObjectImp& objimp, BObject& obj ) override; void selfTimesObj( BLong& objimp, BObject& obj ) override; void selfTimesObj( Double& objimp, BObject& obj ) override; BObjectImp* selfDividedByObjImp( const BObjectImp& objimp ) const override; BObjectImp* selfDividedByObj( const BLong& objimp ) const override; BObjectImp* selfDividedByObj( const Double& objimp ) const override; void selfDividedByObjImp( BObjectImp& objimp, BObject& obj ) override; void selfDividedByObj( BLong& objimp, BObject& obj ) override; void selfDividedByObj( Double& objimp, BObject& obj ) override; void selfPlusPlus() override { ++dval_; } void selfMinusMinus() override { --dval_; } BObjectImp* selfModulusObjImp( const BObjectImp& objimp ) const override; BObjectImp* selfModulusObj( const BLong& objimp ) const override; BObjectImp* selfModulusObj( const Double& objimp ) const override; void selfModulusObjImp( BObjectImp& objimp, BObject& obj ) override; void selfModulusObj( BLong& objimp, BObject& obj ) override; void selfModulusObj( Double& objimp, BObject& obj ) override; BObjectImp* inverse() const override { return new Double( -dval_ ); } std::string getStringRep() const override; void printOn( std::ostream& ) const override; private: double dval_; }; extern Clib::fixed_allocator double_alloc; inline void* Double::operator new( std::size_t len ) { (void)len; passert_paranoid( len == sizeof( Double ) ); return double_alloc.allocate(); } inline void Double::operator delete( void* p ) { double_alloc.deallocate( p ); } class BBoolean final : public BObjectImp { using base = BObjectImp; public: #if BOBJECTIMP_DEBUG explicit BBoolean( bool bval = false ); BBoolean( const BBoolean& B ); #else explicit BBoolean( bool bval = false ) : BObjectImp( OTBoolean ), bval_( bval ) {} BBoolean( const BBoolean& B ) : BBoolean( B.bval_ ) {} #endif private: ~BBoolean() override = default; public: static BObjectImp* unpack( std::istream& is ); void packonto( std::string& os ) const override; size_t sizeEstimate() const override; bool value() const { return bval_; } public: // Class Machinery BObjectImp* copy() const override; bool isTrue() const override; bool operator==( const BObjectImp& objimp ) const override; std::string getStringRep() const override; void printOn( std::ostream& ) const override; private: bool bval_; }; class BFunctionRef final : public BObjectImp { using base = BObjectImp; public: BFunctionRef( ref_ptr program, unsigned int pid, unsigned function_reference_index, std::weak_ptr globals, ValueStackCont&& captures ); BFunctionRef( const BFunctionRef& B ); private: ~BFunctionRef() override = default; public: size_t sizeEstimate() const override; bool validCall( const int id, Executor& ex, Instruction* inst ) const; bool validCall( const char* methodname, Executor& ex, Instruction* inst ) const; int numParams() const; unsigned pc() const; bool variadic() const; ref_ptr prog() const; unsigned int pid() const; unsigned class_index() const; bool constructor() const; bool class_method() const; const std::vector& default_parameter_addresses() const; int default_parameter_count() const; // Does not consider variadic functions. Caller must handle variadic() // explicitly! std::pair expected_args() const; public: // Class Machinery BObjectImp* copy() const override; bool isTrue() const override; bool operator==( const BObjectImp& objimp ) const override; BObjectImp* selfIsObjImp( const BObjectImp& ) const override; std::string getStringRep() const override; BObjectImp* call_method( const char* methodname, Executor& ex ) override; BObjectImp* call_method_id( const int id, Executor& ex, bool forcebuiltin = false ) override; private: // Need to reference the program, not the Executor, as the exec that created // this funcref could be destroyed by the time the funcref gets called ref_ptr prog_; unsigned int original_pid_; unsigned function_reference_index_; public: std::weak_ptr globals; ValueStackCont captures; }; class BSpread final : public BObjectImp { public: BSpread( BObjectRef obj ); BSpread( const BSpread& B ); private: ~BSpread() override = default; public: size_t sizeEstimate() const override; public: // Class Machinery BObjectImp* copy() const override; bool isTrue() const override; std::string getStringRep() const override; BObjectRef object; }; // very very special Imp, should never be actually used // we need to tell the executor that in certain cases // call_method and call_method_id do not return a BObjectImp // and the ValueStack should not be modified // should not be handled like a "imp" and never be passed to // a BObject since its a singleton class BSpecialUserFuncJump final : public BObjectImp { public: static BSpecialUserFuncJump* get(); static void ReleaseSharedInstance(); public: // needed minimal imp size_t sizeEstimate() const override; BObjectImp* copy() const override; std::string getStringRep() const override; private: BSpecialUserFuncJump(); ~BSpecialUserFuncJump() override = default; static std::unique_ptr imp_special_userjmp; friend std::unique_ptr std::make_unique(); friend std::unique_ptr::deleter_type; }; class BApplicObjType { }; class BApplicObjBase : public BObjectImp { public: explicit BApplicObjBase( const BApplicObjType* object_type ); const BApplicObjType* object_type() const; public: // Class Machinery BObjectImp* copy() const override = 0; std::string getStringRep() const override; void printOn( std::ostream& ) const override; size_t sizeEstimate() const override = 0; private: const BApplicObjType* object_type_; }; inline BApplicObjBase::BApplicObjBase( const BApplicObjType* object_type ) : BObjectImp( OTApplicObj ), object_type_( object_type ) { } inline const BApplicObjType* BApplicObjBase::object_type() const { return object_type_; } template class BApplicObj : public BApplicObjBase { public: explicit BApplicObj( const BApplicObjType* object_type ); BApplicObj( const BApplicObjType*, T ); T& value(); const T& value() const; T* operator->(); const char* typeOf() const override = 0; u8 typeOfInt() const override = 0; BObjectImp* copy() const override = 0; size_t sizeEstimate() const override; protected: T obj_; }; template BApplicObj::BApplicObj( const BApplicObjType* object_type ) : BApplicObjBase( object_type ) { } template BApplicObj::BApplicObj( const BApplicObjType* object_type, T obj ) : BApplicObjBase( object_type ), obj_( std::move( obj ) ) { } template inline size_t BApplicObj::sizeEstimate() const { return sizeof( BApplicObj ); } template T& BApplicObj::value() { return obj_; } template const T& BApplicObj::value() const { return obj_; } template T* BApplicObj::operator->() { return &obj_; } } // namespace Pol::Bscript template <> struct fmt::formatter : fmt::ostream_formatter { }; template <> struct fmt::formatter : fmt::ostream_formatter { }; #endif