00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00020 #ifndef flc_flc_item_H
00021 #define flc_flc_item_H
00022
00023 #include <stdlib.h>
00024 #include <falcon/types.h>
00025 #include <falcon/itemid.h>
00026 #include <falcon/garbageable.h>
00027 #include <falcon/basealloc.h>
00028 #include <falcon/string.h>
00029 #include <falcon/corerange.h>
00030
00031 namespace Falcon {
00032
00033 class Symbol;
00034 class CoreString;
00035 class CoreObject;
00036 class CoreDict;
00037 class CoreArray;
00038 class CoreClass;
00039 class CallPoint;
00040 class CoreFunc;
00041 class GarbageItem;
00042 class VMachine;
00043 class Stream;
00044 class LiveModule;
00045 class MemBuf;
00046 class GarbagePointer;
00047 class FalconData;
00048 class CodeError;
00049 class DeepItem;
00050
00051
00052 typedef void** CommOpsTable;
00053 extern FALCON_DYN_SYM CommOpsTable CommOpsDict[];
00054
00055
00057 class FALCON_DYN_CLASS Item: public BaseAlloc
00058 {
00059 public:
00060
00072 typedef enum {
00073 co_add,
00074 co_sub,
00075 co_mul,
00076 co_div,
00077 co_mod,
00078 co_pow,
00079
00080 co_neg,
00081
00082 co_inc,
00083 co_dec,
00084 co_incpost,
00085 co_decpost,
00086
00087 co_compare,
00088
00089 co_getIndex,
00090 co_setIndex,
00091 co_getProperty,
00092 co_setProperty,
00093
00094 co_call
00095
00096 } e_commops;
00097
00102 typedef enum {
00104 sc_ok,
00106 sc_ferror,
00108 sc_invformat,
00110 sc_missclass,
00112 sc_misssym,
00118 sc_vmerror,
00119
00124 sc_missvm,
00126 sc_eof
00127 }
00128 e_sercode;
00129
00130 protected:
00131 union {
00132 struct {
00133 union {
00134 int32 val32;
00135 int64 val64;
00136 numeric number;
00137 Garbageable *content;
00138
00139 struct {
00140 void *voidp;
00141 void *extra;
00142 } ptr;
00143
00144 } data;
00145
00146 CallPoint *method;
00147
00148 union {
00149 struct {
00150 byte type;
00151 byte flags;
00152 byte oldType;
00153 byte methodId;
00154 } bits;
00155 uint16 half;
00156 uint32 whole;
00157 } base;
00158 } ctx;
00159
00160 struct {
00161 uint64 low;
00162 uint64 high;
00163 } parts;
00164 } all;
00165
00166
00167 bool serialize_object( Stream *file, CoreObject *obj, bool bLive ) const;
00168 bool serialize_symbol( Stream *file, const Symbol *sym ) const;
00169 bool serialize_function( Stream *file, const CoreFunc *func, bool bLive ) const;
00170 bool serialize_class( Stream *file, const CoreClass *cls ) const;
00171
00172 e_sercode deserialize_symbol( Stream *file, VMachine *vm, Symbol **tg_sym, LiveModule **modId );
00173 e_sercode deserialize_function( Stream *file, VMachine *vm );
00174 e_sercode deserialize_class( Stream *file, VMachine *vm );
00175
00176 #ifdef _MSC_VER
00177 #if _MSC_VER < 1299
00178 #define flagIsMethodic 0x02
00179 #define flagIsOob 0x04
00180 #define flagLiteral 0x08
00181 #else
00182 static const byte flagIsMethodic = 0x02;
00183 static const byte flagIsOob = 0x04;
00184 static const byte flagLiteral = 0x08;
00185 #endif
00186 #else
00187 static const byte flagIsMethodic = 0x02;
00188 static const byte flagIsOob = 0x04;
00189 static const byte flagLiteral = 0x08;
00190 #endif
00191
00192 public:
00193 Item( byte t=FLC_ITEM_NIL )
00194 {
00195 type( t );
00196 }
00197
00198 Item( byte t, Garbageable *dt );
00199
00200
00201 Item( CoreFunc* cf )
00202 {
00203 setFunction( cf );
00204 }
00205
00206 void setNil() { type( FLC_ITEM_NIL ); }
00207
00208 Item( const Item &other ) {
00209 copy( other );
00210 }
00211
00215 void setBoolean( bool tof )
00216 {
00217 type( FLC_ITEM_BOOL );
00218 all.ctx.data.val32 = tof? 1: 0;
00219 }
00220
00222 Item( int16 val )
00223 {
00224 setInteger( (int64) val );
00225 }
00226
00228 Item( uint16 val )
00229 {
00230 setInteger( (int64) val );
00231 }
00232
00234 Item( int32 val )
00235 {
00236 setInteger( (int64) val );
00237 }
00238
00240 Item( uint32 val )
00241 {
00242 setInteger( (int64) val );
00243 }
00244
00245
00247 Item( int64 val )
00248 {
00249 setInteger( val );
00250 }
00251
00252
00254 Item( uint64 val )
00255 {
00256 setInteger( (int64)val );
00257 }
00258
00259 void setInteger( int64 val ) {
00260 type(FLC_ITEM_INT);
00261 all.ctx.data.val64 = val;
00262 }
00263
00265 Item( numeric val )
00266 {
00267 setNumeric( val );
00268 }
00269
00270 void setNumeric( numeric val ) {
00271 type( FLC_ITEM_NUM );
00272 all.ctx.data.number = val;
00273 }
00274
00276 Item( CoreRange *r )
00277 {
00278 setRange( r );
00279 }
00280
00281 void setRange( CoreRange *r );
00282
00288 Item( const String &str );
00289
00291 Item( String *str )
00292 {
00293 setString( str );
00294 }
00295
00296
00297
00298
00299
00300
00301
00302 void setString( String *str );
00303
00304
00306 Item( CoreArray *array )
00307 {
00308 setArray( array );
00309 }
00310
00311 void setArray( CoreArray *array );
00312
00314 Item( CoreObject *obj )
00315 {
00316 setObject( obj );
00317 }
00318
00319 void setObject( CoreObject *obj );
00320
00322 Item( CoreDict *obj )
00323 {
00324 setDict( obj );
00325 }
00326
00327 void setDict( CoreDict *dict );
00328
00330 Item( MemBuf *buf )
00331 {
00332 setMemBuf( buf );
00333 }
00334
00335 void setMemBuf( MemBuf *b );
00336
00337 Item( GarbageItem *ref )
00338 {
00339 setReference( ref );
00340 }
00341
00343 void setReference( GarbageItem *ref );
00344
00345 GarbageItem *asReference() const { return (GarbageItem *) all.ctx.data.ptr.voidp; }
00346
00348 void setFunction( CoreFunc* cf );
00349
00362 void setLBind( String *lbind, GarbageItem *val=0 );
00363
00366 bool isLBind() const { return type() == FLC_ITEM_LBIND; }
00367 bool isFutureBind() const { return isLBind() && all.ctx.data.ptr.extra != 0; }
00368
00371 String *asLBind() const { return (String *) all.ctx.data.ptr.voidp; }
00372 GarbageItem *asFBind() const { return (GarbageItem *) all.ctx.data.ptr.extra; }
00373
00374 bool isLitLBind() const { return isLBind() && asLBind()->getCharAt(0) == '.'; }
00375
00376
00377 const Item &asFutureBind() const;
00378 Item &asFutureBind();
00379
00384 Item( const Item &data, CallPoint* func )
00385 {
00386 setMethod( data, func );
00387 }
00388
00389 Item( CoreObject *obj, CoreClass *cls )
00390 {
00391 setClassMethod( obj, cls );
00392 }
00393
00398 void setMethod( const Item &data, CallPoint *func );
00399
00400 void setClassMethod( CoreObject *obj, CoreClass *cls );
00401
00403 Item( CoreClass *cls )
00404 {
00405 setClass( cls );
00406 }
00407
00408 void setClass( CoreClass *cls );
00409
00410
00421 void setOob() { all.ctx.base.bits.flags |= flagIsOob; }
00422
00426 void resetOob() { all.ctx.base.bits.flags &= ~flagIsOob; }
00427
00432 void setOob( bool oob ) {
00433 if ( oob )
00434 all.ctx.base.bits.flags |= flagIsOob;
00435 else
00436 all.ctx.base.bits.flags &= ~flagIsOob;
00437 }
00438
00442 void setGCPointer( FalconData *ptr );
00443 void setGCPointer( GarbagePointer *shell );
00444
00445 FalconData *asGCPointer() const;
00446 GarbagePointer *asGCPointerShell() const;
00447
00448 bool isGCPointer() const { return type() == FLC_ITEM_GCPTR; }
00449
00454 bool isOob() const { return (all.ctx.base.bits.flags & flagIsOob )== flagIsOob; }
00455
00459 bool isComposed() const { return isObject() || isArray() || isDict(); }
00460
00461 byte type() const { return all.ctx.base.bits.type; }
00462 void type( byte nt ) { all.ctx.base.bits.flags = 0; all.ctx.base.bits.type = nt; }
00463
00465 Garbageable *content() const { return all.ctx.data.content; }
00466
00467 void content( Garbageable *dt ) {
00468 all.ctx.data.content = dt;
00469 }
00470
00471 void copy( const Item &other )
00472 {
00473 #ifdef _SPARC32_ITEM_HACK
00474 register int32 *pthis, *pother;
00475 pthis = (int32*) this;
00476 pother = (int32*) &other;
00477 pthis[0]= pother[0];
00478 pthis[1]= pother[1];
00479 pthis[2]= pother[2];
00480 pthis[3]= pother[3];
00481
00482 #else
00483 all = other.all;
00484 #endif
00485 }
00486
00492 bool isCallable() const;
00493
00495 bool canBeMethod() const;
00496
00497 bool isOrdinal() const {
00498 return type() == FLC_ITEM_INT || type() == FLC_ITEM_NUM;
00499 }
00500
00501 bool asBoolean() const
00502 {
00503 return all.ctx.data.val32 != 0;
00504 }
00505
00506 int64 asInteger() const { return all.ctx.data.val64; }
00507
00508 numeric asNumeric() const { return all.ctx.data.number; }
00509
00510 int64 asRangeStart() const { return static_cast<CoreRange*>(all.ctx.data.content)->start(); }
00511 int64 asRangeEnd() const { return static_cast<CoreRange*>(all.ctx.data.content)->end(); }
00512 int64 asRangeStep() const { return static_cast<CoreRange*>(all.ctx.data.content)->step(); }
00513 bool asRangeIsOpen() const { return static_cast<CoreRange*>(all.ctx.data.content)->isOpen(); }
00514 CoreRange* asRange() const { return static_cast<CoreRange*>(all.ctx.data.content); }
00515
00516 String *asString() const { return (String *) all.ctx.data.ptr.voidp; }
00517 LiveModule *asStringModule() const { return (LiveModule *) all.ctx.data.ptr.extra; }
00518 CoreString *asCoreString() const { return (CoreString *) all.ctx.data.ptr.voidp; }
00519
00520 DeepItem *asDeepItem() const { return (DeepItem *) all.ctx.data.ptr.voidp; }
00521
00526 void toString( String &target ) const;
00527 CoreArray *asArray() const { return (CoreArray *) all.ctx.data.ptr.voidp; }
00528 CoreObject *asObject() const;
00529 CoreObject *asObjectSafe() const { return (CoreObject *) all.ctx.data.ptr.voidp; }
00530 CoreDict *asDict() const { return ( CoreDict *) all.ctx.data.ptr.voidp; }
00531 MemBuf *asMemBuf() const { return ( MemBuf *) all.ctx.data.ptr.voidp; }
00532
00533 CoreClass* asClass() const { return (CoreClass *) all.ctx.data.ptr.extra; }
00534 CoreFunc* asFunction() const { return (CoreFunc*) all.ctx.data.ptr.extra; }
00535 CallPoint* asMethodFunc() const { return (CallPoint*) all.ctx.method; }
00536
00538 Item asMethodItem() const {
00539 Item temp = *this;
00540 temp.type( all.ctx.base.bits.oldType );
00541 temp = *temp.dereference();
00542 temp.flagsOn( flagIsMethodic );
00543 return temp;
00544 }
00545
00547 void getMethodItem( Item &itm ) const {
00548 itm = *this;
00549 itm.type( all.ctx.base.bits.oldType );
00550 itm = *itm.dereference();
00551 itm.flagsOn( flagIsMethodic );
00552 }
00553
00555 void deMethod() { type( all.ctx.base.bits.oldType ); }
00556
00557 CoreClass *asMethodClass() const { return (CoreClass*) all.ctx.data.ptr.extra; }
00558 CoreObject *asMethodClassOwner() const { return (CoreObject*) all.ctx.data.ptr.voidp; }
00559
00560
00561
00566 int64 forceInteger() const ;
00567
00574 int64 forceIntegerEx() const ;
00575
00580 numeric forceNumeric() const ;
00581
00584 uint32 hash() const;
00585
00586 bool isNil() const { return type() == FLC_ITEM_NIL; }
00587 bool isBoolean() const { return type() == FLC_ITEM_BOOL; }
00588 bool isInteger() const { return type() == FLC_ITEM_INT; }
00589 bool isNumeric() const { return type() == FLC_ITEM_NUM; }
00590 bool isScalar() const { return type() == FLC_ITEM_INT || type() == FLC_ITEM_NUM; }
00591 bool isRange() const { return type() == FLC_ITEM_RANGE; }
00592 bool isString() const { return type() == FLC_ITEM_STRING; }
00593 bool isArray() const { return type() == FLC_ITEM_ARRAY; }
00594 bool isDict() const { return type() == FLC_ITEM_DICT; }
00595 bool isMemBuf() const { return type() == FLC_ITEM_MEMBUF; }
00596 bool isObject() const { return type() == FLC_ITEM_OBJECT; }
00597 bool isReference() const { return type() == FLC_ITEM_REFERENCE; }
00598 bool isFunction() const { return type() == FLC_ITEM_FUNC; }
00599 bool isMethod() const { return type() == FLC_ITEM_METHOD; }
00600 bool isClassMethod() const { return type() == FLC_ITEM_CLSMETHOD; }
00601 bool isClass() const { return type() == FLC_ITEM_CLASS; }
00602 bool isOfClass( const String &className ) const;
00603
00604 bool isMethodic() const { return (flags() & flagIsMethodic) != 0; }
00605
00606 bool isTrue() const;
00607
00608 Item &operator=( const Item &other ) { copy( other ); return *this; }
00609 bool operator==( const Item &other ) const { return compare(other) == 0; }
00610 bool operator!=( const Item &other ) const { return compare(other) != 0; }
00611 bool operator<(const Item &other) const { return compare( other ) < 0; }
00612 bool operator<=(const Item &other) const { return compare( other ) <= 0; }
00613 bool operator>(const Item &other) const { return compare( other ) > 0; }
00614 bool operator>=(const Item &other) const { return compare( other ) >= 0; }
00615
00616 Item *dereference();
00617 const Item *dereference() const;
00618
00644 bool methodize( const Item& self );
00645 bool methodize( const CoreObject *co )
00646 {
00647 return methodize( Item(const_cast<CoreObject *>(co)) );
00648 }
00649
00650
00665 e_sercode serialize( Stream *out, bool bLive = false ) const;
00666
00667
00680 e_sercode deserialize( Stream *in, VMachine *vm = 0 );
00681
00683 byte flags() const { return all.ctx.base.bits.flags; }
00684 void flags( byte b ) { all.ctx.base.bits.flags = b; }
00685 void flagsOn( byte b ) { all.ctx.base.bits.flags |= b; }
00686 void flagsOff( byte b ) { all.ctx.base.bits.flags &= ~b; }
00687
00688
00704 bool clone( Item &target ) const;
00705
00710 bool isDeep() const { return type() >= FLC_ITEM_FIRST_DEEP; }
00711
00712
00713
00714 void add( const Item &operand, Item &result ) const {
00715 void (*addfunc)( const Item &first, const Item& second, Item &third) =
00716 (void (*)( const Item &first, const Item& second, Item &third))
00717 CommOpsDict[type()][co_add];
00718 addfunc( *this, operand, result );
00719 }
00720
00721 void sub( const Item &operand, Item &result ) const {
00722 void (*func)( const Item &first, const Item& second, Item &third) =
00723 (void (*)( const Item &first, const Item& second, Item &third))
00724 CommOpsDict[type()][co_sub];
00725 func( *this, operand, result );
00726 }
00727
00728 void mul( const Item &operand, Item &result ) const {
00729 void (*func)( const Item &first, const Item& second, Item &third) =
00730 (void (*)( const Item &first, const Item& second, Item &third))
00731 CommOpsDict[type()][co_mul];
00732 func( *this, operand, result );
00733 }
00734
00735 void div( const Item &operand, Item &result ) const {
00736 void (*func)( const Item &first, const Item& second, Item &third) =
00737 (void (*)( const Item &first, const Item& second, Item &third))
00738 CommOpsDict[type()][co_div];
00739 func( *this, operand, result );
00740 }
00741
00742 void mod( const Item &operand, Item &result ) const {
00743 void (*func)( const Item &first, const Item& second, Item &third) =
00744 (void (*)( const Item &first, const Item& second, Item &third))
00745 CommOpsDict[type()][co_mod];
00746 func( *this, operand, result );
00747 }
00748
00749 void pow( const Item &operand, Item &result ) const {
00750 void (*func)( const Item &first, const Item& second, Item &third) =
00751 (void (*)( const Item &first, const Item& second, Item &third))
00752 CommOpsDict[type()][co_pow];
00753 func( *this, operand, result );
00754 }
00755
00756 void neg( Item& target ) const {
00757 void (*func)( const Item &first, Item &tg ) =
00758 (void (*)( const Item &first, Item &tg ))
00759 CommOpsDict[type()][co_neg];
00760 func( *this, target );
00761 }
00762
00763 void inc( Item& target ) {
00764 void (*func)( Item &first, Item &second ) =
00765 (void (*)( Item &first, Item &second ))
00766 CommOpsDict[type()][co_inc];
00767 func( *this, target );
00768 }
00769
00770 void dec( Item& target ) {
00771 void (*func)( Item &first, Item &second ) =
00772 (void (*)( Item &first, Item &second ))
00773 CommOpsDict[type()][co_dec];
00774 func( *this, target );
00775 }
00776
00777 void incpost( Item& target ) {
00778 void (*func)( Item &first, Item &tg ) =
00779 (void (*)( Item &first, Item &tg ))
00780 CommOpsDict[type()][co_incpost];
00781 func( *this, target );
00782 }
00783
00784 void decpost( Item& target ) {
00785 void (*func)( Item &first, Item &tg ) =
00786 (void (*)( Item &first, Item &tg ))
00787 CommOpsDict[type()][co_decpost];
00788 func( *this, target );
00789 }
00790
00791 int compare( const Item &operand ) const {
00792 int (*func)( const Item &first, const Item& second ) =
00793 (int (*)( const Item &first, const Item& second ))
00794 CommOpsDict[type()][co_compare];
00795 return func( *this, operand );
00796 }
00797
00798 void getIndex( const Item &idx, Item &result ) const {
00799 void (*func)( const Item &first, const Item &idx, Item &third) =
00800 (void (*)( const Item &first, const Item &idx, Item &third))
00801 CommOpsDict[type()][co_getIndex];
00802 func( *this, idx, result );
00803 }
00804
00805 void setIndex( const Item &idx, const Item &result ) {
00806 void (*func)( Item &first, const Item &name, const Item &third) =
00807 (void (*)( Item &first, const Item &name, const Item &third))
00808 CommOpsDict[type()][co_setIndex];
00809 func( *this, idx, result );
00810 }
00811
00812 void getProperty( const String &property, Item &result ) const {
00813 void (*func)( const Item &first, const String &property, Item &third) =
00814 (void (*)( const Item &first, const String &property, Item &third))
00815 CommOpsDict[type()][co_getProperty];
00816 func( *this, property, result );
00817 }
00818
00819 void setProperty( const String &prop, const Item &result ) {
00820 void (*func)( Item &first, const String &prop, const Item &third) =
00821 (void (*)( Item &first, const String &prop, const Item &third))
00822 CommOpsDict[type()][co_setProperty];
00823 func( *this, prop, result );
00824 }
00825
00830 void readyFrame( VMachine *vm, uint32 paramCount ) const
00831 {
00832 void (*func)( const Item &first, VMachine *vm, int paramCount ) =
00833 (void (*)( const Item &first, VMachine *vm, int paramCount ))
00834 CommOpsDict[type()][co_call];
00835 func( *this, vm, paramCount );
00836 }
00837
00838 };
00839
00840
00849 class FALCON_DYN_CLASS GarbageItem: public Garbageable
00850 {
00851 Item m_item;
00852
00853 public:
00854 GarbageItem( const Item &origin ):
00855 Garbageable(),
00856 m_item( origin )
00857 {}
00858
00859 virtual ~GarbageItem() {};
00860
00864 const Item &origin() const { return m_item; }
00865
00869 Item &origin() { return m_item; }
00870 };
00871
00872 inline Item *Item::dereference()
00873 {
00874 if ( type() != FLC_ITEM_REFERENCE )
00875 return this;
00876 return &asReference()->origin();
00877 };
00878
00879 inline const Item *Item::dereference() const
00880 {
00881 if ( type() != FLC_ITEM_REFERENCE )
00882 return this;
00883 return &asReference()->origin();
00884 };
00885
00886
00887 class FALCON_DYN_CLASS SafeItem: public Item
00888 {
00889 public:
00890 SafeItem( const SafeItem &other ) {
00891 copy( other );
00892 }
00893
00894 SafeItem( const Item &other ) {
00895 copy( other );
00896 }
00897
00901 void setBoolean( bool tof )
00902 {
00903 type( FLC_ITEM_BOOL );
00904 all.ctx.data.val32 = tof? 1: 0;
00905 }
00906
00908 SafeItem( int16 val )
00909 {
00910 setInteger( (int64) val );
00911 }
00912
00914 SafeItem( uint16 val )
00915 {
00916 setInteger( (int64) val );
00917 }
00918
00920 SafeItem( int32 val )
00921 {
00922 setInteger( (int64) val );
00923 }
00924
00926 SafeItem( uint32 val )
00927 {
00928 setInteger( (int64) val );
00929 }
00930
00931
00933 SafeItem( int64 val )
00934 {
00935 setInteger( val );
00936 }
00937
00938
00940 SafeItem( uint64 val )
00941 {
00942 setInteger( (int64)val );
00943 }
00944
00945 void setInteger( int64 val ) {
00946 type(FLC_ITEM_INT);
00947 all.ctx.data.val64 = val;
00948 }
00949
00951 SafeItem( numeric val )
00952 {
00953 setNumeric( val );
00954 }
00955
00956 void setNumeric( numeric val ) {
00957 type( FLC_ITEM_NUM );
00958 all.ctx.data.number = val;
00959 }
00960
00961 SafeItem( byte t, Garbageable *dt );
00962
00963 SafeItem( CoreRange *r ) { setRange( r ); }
00964 SafeItem( String *str ) { setString( str ); }
00965 SafeItem( CoreArray *array ) { setArray( array ); }
00966 SafeItem( CoreObject *obj ) { setObject( obj ); }
00967 SafeItem( CoreDict *dict ) { setDict( dict ); }
00968 SafeItem( MemBuf *b ) { setMemBuf( b ); }
00969 SafeItem( GarbageItem *r ) { setReference( r ); }
00970 SafeItem( CoreFunc* cf ) { setFunction( cf ); }
00971 SafeItem( String *lbind, GarbageItem *val ) { setLBind( lbind, val ); }
00972 SafeItem( const Item &data, CallPoint *func ) { setMethod( data, func ); }
00973 SafeItem( CoreObject *obj, CoreClass *cls ) { setClassMethod( obj, cls ); }
00974 SafeItem( CoreClass *cls ) { setClass( cls ); }
00975 SafeItem( FalconData *ptr ) { setGCPointer( ptr ); }
00976 SafeItem( GarbagePointer *shell ) { setGCPointer( shell ); }
00977
00978 void setRange( CoreRange *r );
00979 void setString( String *str );
00980 void setArray( CoreArray *array );
00981 void setObject( CoreObject *obj );
00982 void setDict( CoreDict *dict );
00983 void setMemBuf( MemBuf *b );
00984 void setReference( GarbageItem *r );
00985 void setFunction( CoreFunc* cf );
00986 void setLBind( String *lbind, GarbageItem *val );
00987 void setMethod( const Item &data, CallPoint *func );
00988 void setClassMethod( CoreObject *obj, CoreClass *cls );
00989 void setClass( CoreClass *cls );
00990 void setGCPointer( FalconData *ptr );
00991 void setGCPointer( GarbagePointer *shell );
00992 };
00993
00994 }
00995
00996 #endif
00997