This file is indexed.

/usr/include/falcon/item.h is in falconpl-dev 0.9.6.9-git20120606-2.1+b1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

   1
   2
   3
   4
   5
   6
   7
   8
   9
  10
  11
  12
  13
  14
  15
  16
  17
  18
  19
  20
  21
  22
  23
  24
  25
  26
  27
  28
  29
  30
  31
  32
  33
  34
  35
  36
  37
  38
  39
  40
  41
  42
  43
  44
  45
  46
  47
  48
  49
  50
  51
  52
  53
  54
  55
  56
  57
  58
  59
  60
  61
  62
  63
  64
  65
  66
  67
  68
  69
  70
  71
  72
  73
  74
  75
  76
  77
  78
  79
  80
  81
  82
  83
  84
  85
  86
  87
  88
  89
  90
  91
  92
  93
  94
  95
  96
  97
  98
  99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 149
 150
 151
 152
 153
 154
 155
 156
 157
 158
 159
 160
 161
 162
 163
 164
 165
 166
 167
 168
 169
 170
 171
 172
 173
 174
 175
 176
 177
 178
 179
 180
 181
 182
 183
 184
 185
 186
 187
 188
 189
 190
 191
 192
 193
 194
 195
 196
 197
 198
 199
 200
 201
 202
 203
 204
 205
 206
 207
 208
 209
 210
 211
 212
 213
 214
 215
 216
 217
 218
 219
 220
 221
 222
 223
 224
 225
 226
 227
 228
 229
 230
 231
 232
 233
 234
 235
 236
 237
 238
 239
 240
 241
 242
 243
 244
 245
 246
 247
 248
 249
 250
 251
 252
 253
 254
 255
 256
 257
 258
 259
 260
 261
 262
 263
 264
 265
 266
 267
 268
 269
 270
 271
 272
 273
 274
 275
 276
 277
 278
 279
 280
 281
 282
 283
 284
 285
 286
 287
 288
 289
 290
 291
 292
 293
 294
 295
 296
 297
 298
 299
 300
 301
 302
 303
 304
 305
 306
 307
 308
 309
 310
 311
 312
 313
 314
 315
 316
 317
 318
 319
 320
 321
 322
 323
 324
 325
 326
 327
 328
 329
 330
 331
 332
 333
 334
 335
 336
 337
 338
 339
 340
 341
 342
 343
 344
 345
 346
 347
 348
 349
 350
 351
 352
 353
 354
 355
 356
 357
 358
 359
 360
 361
 362
 363
 364
 365
 366
 367
 368
 369
 370
 371
 372
 373
 374
 375
 376
 377
 378
 379
 380
 381
 382
 383
 384
 385
 386
 387
 388
 389
 390
 391
 392
 393
 394
 395
 396
 397
 398
 399
 400
 401
 402
 403
 404
 405
 406
 407
 408
 409
 410
 411
 412
 413
 414
 415
 416
 417
 418
 419
 420
 421
 422
 423
 424
 425
 426
 427
 428
 429
 430
 431
 432
 433
 434
 435
 436
 437
 438
 439
 440
 441
 442
 443
 444
 445
 446
 447
 448
 449
 450
 451
 452
 453
 454
 455
 456
 457
 458
 459
 460
 461
 462
 463
 464
 465
 466
 467
 468
 469
 470
 471
 472
 473
 474
 475
 476
 477
 478
 479
 480
 481
 482
 483
 484
 485
 486
 487
 488
 489
 490
 491
 492
 493
 494
 495
 496
 497
 498
 499
 500
 501
 502
 503
 504
 505
 506
 507
 508
 509
 510
 511
 512
 513
 514
 515
 516
 517
 518
 519
 520
 521
 522
 523
 524
 525
 526
 527
 528
 529
 530
 531
 532
 533
 534
 535
 536
 537
 538
 539
 540
 541
 542
 543
 544
 545
 546
 547
 548
 549
 550
 551
 552
 553
 554
 555
 556
 557
 558
 559
 560
 561
 562
 563
 564
 565
 566
 567
 568
 569
 570
 571
 572
 573
 574
 575
 576
 577
 578
 579
 580
 581
 582
 583
 584
 585
 586
 587
 588
 589
 590
 591
 592
 593
 594
 595
 596
 597
 598
 599
 600
 601
 602
 603
 604
 605
 606
 607
 608
 609
 610
 611
 612
 613
 614
 615
 616
 617
 618
 619
 620
 621
 622
 623
 624
 625
 626
 627
 628
 629
 630
 631
 632
 633
 634
 635
 636
 637
 638
 639
 640
 641
 642
 643
 644
 645
 646
 647
 648
 649
 650
 651
 652
 653
 654
 655
 656
 657
 658
 659
 660
 661
 662
 663
 664
 665
 666
 667
 668
 669
 670
 671
 672
 673
 674
 675
 676
 677
 678
 679
 680
 681
 682
 683
 684
 685
 686
 687
 688
 689
 690
 691
 692
 693
 694
 695
 696
 697
 698
 699
 700
 701
 702
 703
 704
 705
 706
 707
 708
 709
 710
 711
 712
 713
 714
 715
 716
 717
 718
 719
 720
 721
 722
 723
 724
 725
 726
 727
 728
 729
 730
 731
 732
 733
 734
 735
 736
 737
 738
 739
 740
 741
 742
 743
 744
 745
 746
 747
 748
 749
 750
 751
 752
 753
 754
 755
 756
 757
 758
 759
 760
 761
 762
 763
 764
 765
 766
 767
 768
 769
 770
 771
 772
 773
 774
 775
 776
 777
 778
 779
 780
 781
 782
 783
 784
 785
 786
 787
 788
 789
 790
 791
 792
 793
 794
 795
 796
 797
 798
 799
 800
 801
 802
 803
 804
 805
 806
 807
 808
 809
 810
 811
 812
 813
 814
 815
 816
 817
 818
 819
 820
 821
 822
 823
 824
 825
 826
 827
 828
 829
 830
 831
 832
 833
 834
 835
 836
 837
 838
 839
 840
 841
 842
 843
 844
 845
 846
 847
 848
 849
 850
 851
 852
 853
 854
 855
 856
 857
 858
 859
 860
 861
 862
 863
 864
 865
 866
 867
 868
 869
 870
 871
 872
 873
 874
 875
 876
 877
 878
 879
 880
 881
 882
 883
 884
 885
 886
 887
 888
 889
 890
 891
 892
 893
 894
 895
 896
 897
 898
 899
 900
 901
 902
 903
 904
 905
 906
 907
 908
 909
 910
 911
 912
 913
 914
 915
 916
 917
 918
 919
 920
 921
 922
 923
 924
 925
 926
 927
 928
 929
 930
 931
 932
 933
 934
 935
 936
 937
 938
 939
 940
 941
 942
 943
 944
 945
 946
 947
 948
 949
 950
 951
 952
 953
 954
 955
 956
 957
 958
 959
 960
 961
 962
 963
 964
 965
 966
 967
 968
 969
 970
 971
 972
 973
 974
 975
 976
 977
 978
 979
 980
 981
 982
 983
 984
 985
 986
 987
 988
 989
 990
 991
 992
 993
 994
 995
 996
 997
 998
 999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
/*
   FALCON - The Falcon Programming Language.
   FILE: flc_item.h

   Basic Item Api.
   -------------------------------------------------------------------
   Author: Giancarlo Niccolai
   Begin: lun ott 4 2004

   -------------------------------------------------------------------
   (C) Copyright 2004: the FALCON developers (see list in AUTHORS file)

   See LICENSE file for licensing details.
*/

/** \file
   Basic Item Api
*/

#ifndef flc_flc_item_H
#define flc_flc_item_H

#include <stdlib.h>
#include <falcon/types.h>
#include <falcon/itemid.h>
#include <falcon/garbageable.h>
#include <falcon/basealloc.h>
#include <falcon/string.h>
#include <falcon/corerange.h>

#define OVERRIDE_OP_ADD       "__add"
#define OVERRIDE_OP_SUB       "__sub"
#define OVERRIDE_OP_MUL       "__mul"
#define OVERRIDE_OP_DIV       "__div"
#define OVERRIDE_OP_MOD       "__mod"
#define OVERRIDE_OP_POW       "__pow"
#define OVERRIDE_OP_NEG       "__neg"
#define OVERRIDE_OP_INC       "__inc"
#define OVERRIDE_OP_DEC       "__dec"
#define OVERRIDE_OP_INCPOST   "__incpost"
#define OVERRIDE_OP_DECPOST   "__decpost"
#define OVERRIDE_OP_CALL      "__call"
#define OVERRIDE_OP_GETINDEX  "__getIndex"
#define OVERRIDE_OP_SETINDEX  "__setIndex"

namespace Falcon {

class Symbol;
class CoreString;
class CoreObject;
class CoreDict;
class CoreArray;
class CoreClass;
class CallPoint;
class CoreFunc;
class GarbageItem;
class VMachine;
class Stream;
class LiveModule;
class MemBuf;
class GarbagePointer;
class FalconData;
class CodeError;
class DeepItem;


typedef void** CommOpsTable;
extern FALCON_DYN_SYM CommOpsTable CommOpsDict[];


/** Basic item abstraction.*/
class FALCON_DYN_CLASS Item: public BaseAlloc
{
public:

   /** Common operations that can be performed on items.
      Each item type has a function pointer table taking care of this
      operations.

      Deep items operations is that of searching for overloadings
      via the deep item common DeepItem::getProperty() method,
      and then eventually calling the operator implementation.

      The operator implementation is called on the VM instance of the
      deep item.
   */
   typedef enum {
      co_add,
      co_sub,
      co_mul,
      co_div,
      co_mod,
      co_pow,

      co_neg,

      co_inc,
      co_dec,
      co_incpost,
      co_decpost,

      co_compare,

      co_getIndex,
      co_setIndex,
      co_getProperty,
      co_setProperty,

      co_call

   } e_commops;

   /** Serialization / deserialization error code.
      This value is returned by serialization and deserialization
      functions to communicate what went wrong.
   */
   typedef enum {
      /** All was fine. */
      sc_ok,
      /** File error in serialization/deserialization */
      sc_ferror,
      /** Invalid format in deserialization */
      sc_invformat,
      /** Missing class in deserialization (object cannot be instantiated).*/
      sc_missclass,
      /** Missing symbol in deserialization (requested function not present in VM).*/
      sc_misssym,
      /** VM Error in serialization or de-serialization.
         This is called if VM raised an error during the call of serialization() object
         methods in case serialization is called, or if the VM raises an error during
         init() or deserialization() of deserialized objects.
      */
      sc_vmerror,

      /** Needed VM but missing.
         This serialization or deserialization operation required a VM to be provided,
         but it wasn't.
      */
      sc_missvm,
      /** Hit EOF while de-serializing */
      sc_eof
   }
   e_sercode;

protected:
  union {
      struct {
         union {
            int32 val32;
            int64 val64;
            numeric number;
            Garbageable *content;

            struct {
               void *voidp;
               void *extra;
            } ptr;

         } data;

         CallPoint *method;

         union {
            struct {
               byte type;
               byte flags;
               byte oldType;
               byte reserved;
            } bits;
            uint16 half;
            uint32 whole;
         } base;
      } ctx;

      struct {
         uint64 low;
         uint64 high;
      } parts;
   } all;


   bool serialize_object( Stream *file, CoreObject *obj, bool bLive ) const;
   bool serialize_symbol( Stream *file, const Symbol *sym ) const;
   bool serialize_function( Stream *file, const CoreFunc *func, bool bLive ) const;
   bool serialize_class( Stream *file, const CoreClass *cls ) const;

   e_sercode deserialize_symbol( Stream *file, VMachine *vm, Symbol **tg_sym, LiveModule **modId );
   e_sercode deserialize_function( Stream *file, VMachine *vm );
   e_sercode deserialize_class( Stream *file, VMachine *vm );

#ifdef _MSC_VER
	#if _MSC_VER < 1299
	#define flagIsMethodic 0x02
	#define flagIsOob 0x04
	#define flagLiteral 0x08
	#else
	   static const byte flagIsMethodic = 0x02;
	   static const byte flagIsOob = 0x04;
	   static const byte flagLiteral = 0x08;
	#endif
#else
   static const byte flagIsMethodic = 0x02;
   static const byte flagIsOob = 0x04;
   static const byte flagLiteral = 0x08;
#endif

public:
   Item( byte t=FLC_ITEM_NIL )
   {
      type( t );
   }

   Item( byte t, Garbageable *dt );


   Item( CoreFunc* cf )
   {
      setFunction( cf );
   }

   void setNil() { type( FLC_ITEM_NIL ); }

   void setUnbound() { type( FLC_ITEM_UNB ); }

   Item( const Item &other ) {
      copy( other );
   }

   /** Creates a boolean item. */

   /** Sets this item as boolean */
   void setBoolean( bool tof )
   {
      type( FLC_ITEM_BOOL );
      all.ctx.data.val32 = tof? 1: 0;
   }

   /** Creates an garbage pointer item */
   Item( GarbagePointer* val )
   {
      setGCPointer( val );
   }

   /** Creates an integer item */
   Item( int16 val )
   {
      setInteger( (int64) val );
   }

   /** Creates an integer item */
   Item( uint16 val )
   {
      setInteger( (int64) val );
   }

   /** Creates an integer item */
   Item( int32 val )
   {
      setInteger( (int64) val );
   }

   /** Creates an integer item */
   Item( uint32 val )
   {
      setInteger( (int64) val );
   }


   /** Creates an integer item */
   Item( int64 val )
   {
      setInteger( val );
   }


   /** Creates an integer item */
   Item( uint64 val )
   {
      setInteger( (int64)val );
   }

   void setInteger( int64 val ) {
      type(FLC_ITEM_INT);
      all.ctx.data.val64 = val;
   }

   /** Creates a numeric item */
   Item( numeric val )
   {
      setNumeric( val );
   }

   void setNumeric( numeric val ) {
      type( FLC_ITEM_NUM );
      all.ctx.data.number = val;
   }

   /** Creates a range item */
   Item( CoreRange *r )
   {
      setRange( r );
   }

   void setRange( CoreRange *r );

   /** Creates a corestring.
      The given string is copied and stored in the Garbage system.
      It is also bufferized, as the most common usage of this constructor
      is in patterns like Item( "a static string" );
   */
   Item( const String &str );

   /** Creates a CoreString item */
   Item( String *str )
   {
      setString( str );
   }

   /* Creates a String item dependent from a module */
   /*Item( String *str, LiveModule* lm )
   {
      setString( str, lm );
   }*/

   void setString( String *str );
   //void setString( String *str, LiveModule* lm );

   /** Creates an array item */
   Item( CoreArray *array )
   {
      setArray( array );
   }

   void setArray( CoreArray *array );

   /** Creates an object item */
   Item( CoreObject *obj )
   {
      setObject( obj );
   }

   void setObject( CoreObject *obj );

   /** Creates a dictionary item */
   Item( CoreDict *obj )
   {
      setDict( obj );
   }

   void setDict( CoreDict *dict );

   /** Creates a memory buffer. */
   Item( MemBuf *buf )
   {
      setMemBuf( buf );
   }

   void setMemBuf( MemBuf *b );

   Item( GarbageItem *ref )
   {
      setReference( ref );
   }

   /** Creates a reference to another item. */
   void setReference( GarbageItem *ref );

   GarbageItem *asReference() const { return (GarbageItem *) all.ctx.data.ptr.voidp; }

   /** Creates a function item */
   void setFunction( CoreFunc* cf );

   /** Creates a late binding item.
      The late binding is just a CoreString in a live module which is
      resolved into a value by referencing a item in the current
      context (symbol tables) having the given name at runtime.

      Thus, the CoreString representing the late binding symbol name
      lives in the live module that generated this LBind. If
      the module is unloaded, the LBind is invalidated.

      \param lbind The name of the late binding symbol.
      \param val If provided, a future value (future binding).
   */
   void setLBind( String *lbind, GarbageItem *val=0 );

   /** Returns true if this item is a valid LBind.
   */
   bool isLBind() const { return type() == FLC_ITEM_LBIND; }
   bool isFutureBind() const { return isLBind() && all.ctx.data.ptr.extra != 0; }

   /** Return the binding name associate with this LBind item.
   */
   String *asLBind() const { return (String *) all.ctx.data.ptr.voidp; }
   GarbageItem *asFBind() const { return (GarbageItem *) all.ctx.data.ptr.extra; }

   bool isLitLBind() const { return isLBind() && asLBind()->getCharAt(0) == '.'; }


   const Item &asFutureBind() const;
   Item &asFutureBind();

   /** Creates a method.
      The method is able to remember if it was called with
      a Function pointer or using an external function.
   */
   Item( const Item &data, CallPoint* func )
   {
      setMethod( data, func );
   }

   Item( CoreObject *obj, CoreClass *cls )
   {
      setClassMethod( obj, cls );
   }

   /** Creates a method.
      The method is able to remember if it was called with
      a Function pointer or using an external function.
   */
   void setMethod( const Item &data, CallPoint *func );

   void setClassMethod( CoreObject *obj, CoreClass *cls );

   /** Creates a class item */
   Item( CoreClass *cls )
   {
      setClass( cls );
   }

   void setClass( CoreClass *cls );


   /** Defines this item as a out of band data.
      Out of band data allow out-of-order sequencing in functional programming.
      If an item is out of band, it's type it's still the original one, and
      its value is preserved across function calls and returns; however, the
      out of band data may innescate a meta-level processing of the data
      travelling through the functions.

      In example, returning an out of band NIL value from an xmap mapping
      function will cause xmap to discard the data.
   */
   void setOob() { all.ctx.base.bits.flags |= flagIsOob; }

   /** Clear out of band status of this item.
      \see setOob()
   */
   void resetOob() { all.ctx.base.bits.flags &= ~flagIsOob; }

   /** Sets or clears the out of band status status of this item.
      \param oob true to make this item out of band.
      \see setOob()
   */
   void setOob( bool oob ) {
      if ( oob )
         all.ctx.base.bits.flags |= flagIsOob;
      else
         all.ctx.base.bits.flags &= ~flagIsOob;
   }

   /** Set this item as a user-defined Garbage pointers.
       VM provides GC-control over them.
   */
   void setGCPointer( FalconData *ptr );
   void setGCPointer( GarbagePointer *shell );

   FalconData *asGCPointer() const;
   GarbagePointer *asGCPointerShell() const;

   bool isGCPointer() const { return type() == FLC_ITEM_GCPTR; }

   /** Tells wether this item is out of band.
      \return true if out of band.
      \see oob()
   */
   bool isOob() const { return (all.ctx.base.bits.flags & flagIsOob )== flagIsOob; }

   /** Returns true if this item is an instance of some sort.
      \return true if this is an object, blessed dictionary or bound array.
   */
   bool isComposed() const { return isObject() || isArray() || isDict(); }

   /** Returns the item type*/
   byte type() const { return all.ctx.base.bits.type; }

   /** Returns the item type as string*/
   void typeName( String &target ) const;
   
   /** Changes the item type.
   
      Flags are also reset. For example, if this item was OOB before,
      the OOB flag is cleared.
   */
   void type( byte nt ) { all.ctx.base.bits.flags = 0; all.ctx.base.bits.type = nt; }

   /** Returns the content of the item */
   Garbageable *content() const { return all.ctx.data.content; }

   void content( Garbageable *dt ) {
      all.ctx.data.content = dt;
   }

   void copy( const Item &other )
   {
      #ifdef _SPARC32_ITEM_HACK
      register int32 *pthis, *pother;
      pthis = (int32*) this;
      pother = (int32*) &other;
      pthis[0]= pother[0];
      pthis[1]= pother[1];
      pthis[2]= pother[2];
      pthis[3]= pother[3];

      #else
         all = other.all;
      #endif
   }

   /** Tells if this item is callable.
      This function will turn this object into a nil
      if the item referenced a dead module. As this is a pathological
      situation, a const cast is forced.
   */
   bool isCallable() const;

   /** Return true if this is a callable item that is turned into a method when found as property.*/
   bool canBeMethod() const;

   bool isOrdinal() const {
      return type() == FLC_ITEM_INT || type() == FLC_ITEM_NUM;
   }

   bool asBoolean() const
   {
      return all.ctx.data.val32 != 0;
   }

   int64 asInteger() const { return all.ctx.data.val64; }

   numeric asNumeric() const { return all.ctx.data.number; }

   int64 asRangeStart() const { return static_cast<CoreRange*>(all.ctx.data.content)->start(); }
   int64 asRangeEnd()  const { return static_cast<CoreRange*>(all.ctx.data.content)->end(); }
   int64 asRangeStep()  const { return static_cast<CoreRange*>(all.ctx.data.content)->step(); }
   bool asRangeIsOpen()  const { return static_cast<CoreRange*>(all.ctx.data.content)->isOpen(); }
   CoreRange* asRange() const { return static_cast<CoreRange*>(all.ctx.data.content); }

   String *asString() const { return (String *) all.ctx.data.ptr.voidp; }
   LiveModule *asStringModule() const { return (LiveModule *) all.ctx.data.ptr.extra; }
   CoreString *asCoreString() const { return (CoreString *) all.ctx.data.ptr.voidp; }

   DeepItem *asDeepItem() const { return (DeepItem *) all.ctx.data.ptr.voidp; }

   /** Provides a basic CoreString representation of the item.
      Use Falcon::Format for a finer control of item representation.
      \param target a CoreString where the item CoreString representation will be placed.
   */
   void toString( String &target ) const;
   CoreArray *asArray() const { return (CoreArray *) all.ctx.data.ptr.voidp; }
   CoreObject *asObject() const;
   CoreObject *asObjectSafe() const { return (CoreObject *) all.ctx.data.ptr.voidp; }
   CoreDict *asDict() const { return ( CoreDict *) all.ctx.data.ptr.voidp; }
   MemBuf *asMemBuf() const { return ( MemBuf *) all.ctx.data.ptr.voidp; }

   CoreClass* asClass() const { return (CoreClass *) all.ctx.data.ptr.extra; }
   CoreFunc* asFunction() const { return (CoreFunc*) all.ctx.data.ptr.extra; }
   CallPoint* asMethodFunc() const { return (CallPoint*) all.ctx.method; }

   /** Gets the "self" in an item (return the item version). */
   Item asMethodItem() const {
      Item temp = *this;
      temp.type( all.ctx.base.bits.oldType );
      temp = *temp.dereference();
      temp.flagsOn( flagIsMethodic );
      return temp;
   }

   /** Gets the "self" in an item (pass byref version). */
   void getMethodItem( Item &itm ) const {
      itm = *this;
      itm.type( all.ctx.base.bits.oldType );
      itm = *itm.dereference();
      itm.flagsOn( flagIsMethodic );
   }

   /** Turns a method item into its original "self". */
   void deMethod() { type( all.ctx.base.bits.oldType ); }

   CoreClass *asMethodClass() const { return (CoreClass*) all.ctx.data.ptr.extra; }
   CoreObject *asMethodClassOwner() const { return (CoreObject*) all.ctx.data.ptr.voidp; }

   //LiveModule *asModule() const { return all.ctx.data.ptr.m_liveMod; }

   /** Convert current object into an integer.
      This operations is usually done on integers, numeric and CoreStrings.
      It will do nothing meaningfull on other types.
   */
   int64 forceInteger() const ;

   /** Convert current object into an integer.
      This operations is usually done on integers, numeric and CoreStrings.
      It will do nothing meaningfull on other types.

      \note this version will throw a code error if the item is not an ordinal.
   */
   int64 forceIntegerEx() const ;

   /** Convert current object into a numeric.
      This operations is usually done on integers, numeric and CoreStrings.
      It will do nothing meaningfull on other types.
   */
   numeric forceNumeric() const ;

   /** Calculates the hash function for this item.
   */
   uint32 hash() const;

   bool isNil() const { return type() == FLC_ITEM_NIL; }
   bool isBoolean() const { return type() == FLC_ITEM_BOOL; }
   bool isInteger() const { return type() == FLC_ITEM_INT; }
   bool isNumeric() const { return type() == FLC_ITEM_NUM; }
   bool isScalar() const { return type() == FLC_ITEM_INT || type() == FLC_ITEM_NUM; }
   bool isRange() const { return type() == FLC_ITEM_RANGE; }
   bool isString() const { return type() == FLC_ITEM_STRING; }
   bool isArray() const { return type() == FLC_ITEM_ARRAY; }
   bool isDict() const { return type() == FLC_ITEM_DICT; }
   bool isMemBuf() const { return type() == FLC_ITEM_MEMBUF; }
   bool isObject() const { return type() == FLC_ITEM_OBJECT; }
   bool isReference() const { return type() == FLC_ITEM_REFERENCE; }
   bool isFunction() const { return type() == FLC_ITEM_FUNC; }
   bool isMethod() const { return type() == FLC_ITEM_METHOD; }
   bool isClassMethod() const { return type() == FLC_ITEM_CLSMETHOD; }
   bool isClass() const { return type() == FLC_ITEM_CLASS; }
   bool isUnbound() const { return type() == FLC_ITEM_UNB; }
   bool isOfClass( const String &className ) const;

   bool isMethodic() const { return (flags() & flagIsMethodic) != 0; }

   bool isTrue() const;

   Item &operator=( const Item &other ) { copy( other ); return *this; }
   bool operator==( const Item &other ) const { return compare(other) == 0; }
   bool operator!=( const Item &other ) const { return compare(other) != 0; }
   bool operator<(const Item &other) const { return compare( other ) < 0; }
   bool operator<=(const Item &other) const { return compare( other ) <= 0; }
   bool operator>(const Item &other) const { return compare( other ) > 0; }
   bool operator>=(const Item &other) const { return compare( other ) >= 0; }

   bool exactlyEqual( const Item &other ) const;
   
   inline Item *dereference();
   inline const Item *dereference() const;

   /** Turns this item in a method of the given object.
      This is meant to be used by external functions when accessing object properties.
      VM always creates a method when accessor is used; in example, myObject.someFunc()
      will create a method myObject.someFunc if there is some callable inside the given
      property, and then will call it. In this way, a function may be assigned to that
      property, and the VM will take care to create an item that will turn the function
      in a method.

      But when a non-vm program accesses an object "method", the calling program may
      have assigned something different to it in the meanwhile, and what its returned
      in CoreObject::getProperty() won't be a callable method, but just the assigned
      object.

      Methodize will turn such an item in a callable method of the object given as
      parameter, if this is possible, else it will return false.
      \note External methods (that is, methods calling external functions) won't be
      methodized, as they often rely in external values carried inside their CoreObject
      owners. However, the function will return true, as the object can be called, and
      very probably it will do what expected by the user (as the external method would
      have never used anything other than the VM generated self anyhow).
      \note CoreObject::getMethod() is a shortcut to this function.

      \param self the object that will be set as "self" for the method
      \return true if the item can be called properly, false if it's not a callable.
   */
   bool methodize( const Item& self );
   bool methodize( const CoreObject *co )
   {
      return methodize( Item(const_cast<CoreObject *>(co)) );
   }


   /** Serialize this item.
      This method stores an item on a stream for later retrival.

      The function can return true if the serialization succeded. It will return false if
      the serialization failed; in that case, if there is an error on the stream, it can
      be retreived form the stream variable. If the stream reports no error, then the
      serialization failed because a VM was not provided while a serialized method should
      have been called on the target object, or in any referenced object, or because the
      VM received an error during the method call.

      \param out the output stream
      \param bLive true
      \return an error code in case of error (\see e_sercode).
   */
   e_sercode serialize( Stream *out, bool bLive = false ) const;


   /** Loads a serialized item from a stream.
      This method restores an item previously stored on a stream for later retrival.
      Providing a virtual
      machine that is optional; if not provided, items requiring the VM for deserialization
      won't be correctly restored. Objects deserialization requires a VM readied with
      the class the object derives from.
      \see serialize()

      \param in the input stream
      \param vm the virtual machine that can be used for object deserialization
      \return an error code in case of error (\see e_sercode).
   */
   e_sercode deserialize( Stream *in, VMachine *vm = 0 );

   /** Flags, used for internal vm needs. */
   byte flags() const { return all.ctx.base.bits.flags; }
   void flags( byte b ) { all.ctx.base.bits.flags = b; }
   void flagsOn( byte b ) { all.ctx.base.bits.flags |= b; }
   void flagsOff( byte b ) { all.ctx.base.bits.flags &= ~b; }


   /** Clone the item (with the help of a VM).
      If the item is not cloneable, the method returns false. Is up to the caller to
      raise an appropriate error if that's the case.
      The VM parameter may be zero; in that case, returned items will not be stored in
      any garbage collector.

      Reference items are de-referenced; if cloning a reference, the caller will obtain
      a clone of the target item, not a clone of the reference.

      Also, in that case, the returned item will be free of reference.

      \param vm the virtual machine used for cloning.
      \param target the item where to stored the cloned instance of this item.
      \return true if the clone operation is possible
   */
   bool clone( Item &target ) const;

   /** Return true if the item deep.
      Deep items are the ones that are subject to garbage collecting.
      \return true if the item is deep.
   */
   bool isDeep() const { return type() >= FLC_ITEM_FIRST_DEEP; }

   //====================================================================//

   void add( const Item &operand, Item &result ) const {
      void (*addfunc)( const Item &first, const Item& second, Item &third) =
         (void (*)( const Item &first, const Item& second, Item &third))
         CommOpsDict[type()][co_add];
      addfunc( *this, operand, result );
   }

   void sub( const Item &operand, Item &result ) const {
      void (*func)( const Item &first, const Item& second, Item &third) =
         (void (*)( const Item &first, const Item& second, Item &third))
         CommOpsDict[type()][co_sub];
      func( *this, operand, result );
   }

   void mul( const Item &operand, Item &result ) const {
      void (*func)( const Item &first, const Item& second, Item &third) =
         (void (*)( const Item &first, const Item& second, Item &third))
         CommOpsDict[type()][co_mul];
      func( *this, operand, result );
   }

   void div( const Item &operand, Item &result ) const {
      void (*func)( const Item &first, const Item& second, Item &third) =
         (void (*)( const Item &first, const Item& second, Item &third))
         CommOpsDict[type()][co_div];
      func( *this, operand, result );
   }

   void mod( const Item &operand, Item &result ) const {
      void (*func)( const Item &first, const Item& second, Item &third) =
         (void (*)( const Item &first, const Item& second, Item &third))
         CommOpsDict[type()][co_mod];
      func( *this, operand, result );
   }

   void pow( const Item &operand, Item &result ) const {
      void (*func)( const Item &first, const Item& second, Item &third) =
         (void (*)( const Item &first, const Item& second, Item &third))
         CommOpsDict[type()][co_pow];
      func( *this, operand, result );
   }

   void neg( Item& target ) const {
      void (*func)( const Item &first, Item &tg ) =
         (void (*)( const Item &first, Item &tg ))
         CommOpsDict[type()][co_neg];
      func( *this, target );
   }

   void inc( Item& target ) {
      void (*func)( Item &first, Item &second ) =
         (void (*)( Item &first, Item &second ))
         CommOpsDict[type()][co_inc];
      func( *this, target );
   }

   void dec( Item& target ) {
      void (*func)( Item &first, Item &second ) =
         (void (*)( Item &first, Item &second ))
         CommOpsDict[type()][co_dec];
      func( *this, target );
   }

   void incpost( Item& target ) {
      void (*func)( Item &first, Item &tg ) =
         (void (*)( Item &first, Item &tg ))
         CommOpsDict[type()][co_incpost];
      func( *this, target );
   }

   void decpost( Item& target ) {
      void (*func)( Item &first, Item &tg ) =
         (void (*)( Item &first, Item &tg ))
         CommOpsDict[type()][co_decpost];
      func( *this, target );
   }

   int compare( const Item &operand ) const {
      int (*func)( const Item &first, const Item& second ) =
         (int (*)( const Item &first, const Item& second ))
         CommOpsDict[type()][co_compare];
      return func( *this, operand );
   }

   void getIndex( const Item &idx, Item &result ) const {
      void (*func)( const Item &first, const Item &idx, Item &third) =
         (void (*)( const Item &first, const Item &idx, Item &third))
         CommOpsDict[type()][co_getIndex];
      func( *this, idx, result );
   }

   void setIndex( const Item &idx, const Item &result ) {
      void (*func)( Item &first, const Item &name, const Item &third) =
         (void (*)( Item &first, const Item &name, const Item &third))
         CommOpsDict[type()][co_setIndex];
      func( *this, idx, result );
   }

   void getProperty( const String &property, Item &result ) const {
      void (*func)( const Item &first, const String &property, Item &third) =
         (void (*)( const Item &first, const String &property, Item &third))
         CommOpsDict[type()][co_getProperty];
      func( *this, property, result );
   }

   void setProperty( const String &prop, const Item &result ) {
      void (*func)( Item &first, const String &prop, const Item &third) =
         (void (*)( Item &first, const String &prop, const Item &third))
         CommOpsDict[type()][co_setProperty];
      func( *this, prop, result );
   }

   /** Prepares a call frame that will be called at next VM loop.
      \note You can use vm->execFrame() to execute the prepared frame
      immediately instead of waiting for the loop to complete.
   */
   void readyFrame( VMachine *vm, uint32 paramCount ) const
   {
      void (*func)( const Item &first, VMachine *vm, int paramCount ) =
         (void (*)( const Item &first, VMachine *vm, int paramCount ))
         CommOpsDict[type()][co_call];
      func( *this, vm, paramCount );
   }

};


/** Creates a garbageable version of an item.
   This class repeats the structure of an item holding an instance
   of it, but it derives from Garbageable. This makes it a vessel
   for item references.

   It must be created by a MemPool with the MemPool::referenceItem()
   method.
*/
class FALCON_DYN_CLASS GarbageItem: public Garbageable
{
   Item m_item;

public:
   GarbageItem( const Item &origin ):
      Garbageable(),
      m_item( origin )
   {}

   virtual ~GarbageItem() {};

   /** Returns the item part stored in this garbage item.
      \return the held item.
   */
   const Item &origin() const { return m_item; }

   /** Returns the item part stored in this garbage item.
      \return the held item.
   */
   Item &origin() { return m_item; }
};

inline Item *Item::dereference()
{
   if ( type() != FLC_ITEM_REFERENCE )
      return this;
   return &asReference()->origin();
};

inline const Item *Item::dereference() const
{
   if ( type() != FLC_ITEM_REFERENCE )
      return this;
   return &asReference()->origin();
};


class FALCON_DYN_CLASS SafeItem: public Item
{
public:
   SafeItem( const SafeItem &other ) {
      copy( other );
   }

   SafeItem( const Item &other ) {
      copy( other );
   }

   /** Creates a boolean SafeItem. */

   /** Sets this SafeItem as boolean */
   void setBoolean( bool tof )
   {
      type( FLC_ITEM_BOOL );
      all.ctx.data.val32 = tof? 1: 0;
   }

   /** Creates an integer SafeItem */
   SafeItem( int16 val )
   {
      setInteger( (int64) val );
   }

   /** Creates an integer SafeItem */
   SafeItem( uint16 val )
   {
      setInteger( (int64) val );
   }

   /** Creates an integer SafeItem */
   SafeItem( int32 val )
   {
      setInteger( (int64) val );
   }

   /** Creates an integer SafeItem */
   SafeItem( uint32 val )
   {
      setInteger( (int64) val );
   }


   /** Creates an integer SafeItem */
   SafeItem( int64 val )
   {
      setInteger( val );
   }


   /** Creates an integer SafeItem */
   SafeItem( uint64 val )
   {
      setInteger( (int64)val );
   }

   void setInteger( int64 val ) {
      type(FLC_ITEM_INT);
      all.ctx.data.val64 = val;
   }

   /** Creates a numeric SafeItem */
   SafeItem( numeric val )
   {
      setNumeric( val );
   }

   void setNumeric( numeric val ) {
      type( FLC_ITEM_NUM );
      all.ctx.data.number = val;
   }

   SafeItem( byte t, Garbageable *dt );

   SafeItem( CoreRange *r ) { setRange( r ); }
   SafeItem( String *str ) { setString( str ); }
   SafeItem( CoreArray *array ) { setArray( array ); }
   SafeItem( CoreObject *obj ) { setObject( obj ); }
   SafeItem( CoreDict *dict ) { setDict( dict ); }
   SafeItem( MemBuf *b ) { setMemBuf( b ); }
   SafeItem( GarbageItem *r ) { setReference( r ); }
   SafeItem( CoreFunc* cf ) { setFunction( cf ); }
   SafeItem( String *lbind, GarbageItem *val ) { setLBind( lbind, val ); }
   SafeItem( const Item &data, CallPoint *func ) { setMethod( data, func ); }
   SafeItem( CoreObject *obj, CoreClass *cls ) { setClassMethod( obj, cls ); }
   SafeItem( CoreClass *cls ) { setClass( cls ); }
   SafeItem( FalconData *ptr ) { setGCPointer( ptr ); }
   SafeItem( GarbagePointer *shell ) { setGCPointer( shell ); }

   void setRange( CoreRange *r );
   void setString( String *str );
   void setArray( CoreArray *array );
   void setObject( CoreObject *obj );
   void setDict( CoreDict *dict );
   void setMemBuf( MemBuf *b );
   void setReference( GarbageItem *r );
   void setFunction( CoreFunc* cf );
   void setLBind( String *lbind, GarbageItem *val );
   void setMethod( const Item &data, CallPoint *func );
   void setClassMethod( CoreObject *obj, CoreClass *cls );
   void setClass( CoreClass *cls );
   void setGCPointer( FalconData *ptr );
   void setGCPointer( GarbagePointer *shell );
};

}

#endif
/* end of flc_item.h */