Combining these two, I have a couple comments.

On Thursday 15 November 2001 02:07 pm, Simon Cozens wrote:
>  if (pmc->flags & PS_INTEGER_OK) {
>       return ((struct PerlScalarData *)(pmc->data))->intdata;

Why are you storing flags for PerlScalarData inside the pmc-flags?  If the 
nested type is doing the caching, then it should store the flags.   
Additionally, you should probably break out the variables for readibility:


The following assumes macros (bite me), typedefs (don't know why this isn't 
standardized, ever since programming in c++, I've never left c-structs 
untypedef'd), and unions (as with Uri's suggestion)

static INTVAL Parrot_scalar_get_integer (struct Parrot_Interp *interpreter, 
PMC* pmc) {
    if ( isPMCScalarClass( pmc ) ) {
      PerlScalarData* psd = pmc->data.scalar;
      switch ( psd->type ) {
        case SCALAR_STR:
           psd->intdata = String2Int( psd->stringdata );
           setScalarIntOK( psd );
           return psd->intdata;

        case SCALAR_NUM:
        case SCALAR_NUM_STR:
           psd->intdata = (int) psd->numdata;
           setScalarIntOK( psd );
           /* falls through */

        case SCALAR_INT_NUM_STR:
        case SCALAR_INT_STR:
        case SCALAR_INT_NUM:
        case SCALAR_INT: return psd->intdata;

        default: // throw exception
      }
    } else {
      .... // exception since we're specifically equesting a scalar??
    } 
}

Nested if-statements could be used instead, but so long as type is <= 
num_items, then this gets optimized into a fast table-lookup (with -O2 is 
used).  Though a bit longer, I think this is still readible.

> On Thu, Nov 15, 2001 at 02:01:53PM -0500, Dan Sugalski wrote:
> > *) Use the cache entry in the PMC header. It'll mean for ints and floats
> > you won't need to bother with a separate structure or dereference

Currently, the "cache" only holds a single value.  Is this for space 
efficiency?  If we broke out the union into independant cached values, then 
the two layers could be collapsed into one.  (data would go unused for 
scalars)  Course the switch statement above would have to be masked, as with:

#define getScalarID(x) ( ( x->flags & SCLAR_MASK ) >> SCALAR_MASK_OFFSET )

switch ( getScalarID(pmc) ) {
  ...
}

In general, I feel that OO-symantics would be most readible here:

if ( pmc->isInteger() ) {
   return pmc->getInt();
} else if ( pmc->isNum() ) {
   return pmc->cvtNumToInt()->getInt();
} else if ( pmc->isString() ) {
   return pmc->cvtStrToInt()->getInt();
}

If this were C++, then the isXXX, cvtXXX would be inlined functions, which 
would have the same effect as macro's but with much greater maintainability.  
Unfortunately we're using C, so the closest we have is macro's.

While speed is king, readibility is VERY important (as I'm sure we all agree).

The last alternative I can think of is to break PerlScalarData into it's own 
sub vtable.  Thus

if ( isPMCScalar( pmc ) ) {
   return pmc->data.scalar->vtable[ SCALAR_GET_INT ]->( pmc->data.scalar );
}

This would have similar overhead to the table-lookup switch-statement, and 
since these are extremely simple functions, many architectures (most notably 
SUN) wouldn't require a full blown function call with frame management.

As a last sort of alternative.  I had invisioned PMC's has having separate 
vtables for each of the many different types of operations.  Meaning, that a 
scalar-int would be separate from a scalar-string-num, etc.  Since it seems 
that we're not currently doing this, it would require 8 times as many 
vtable's, but it would prevent hardly any if-statements.

>
> I can't. :(
>
> /* It's more efficient to use our own caching than the PMC's cache
>    Why? Because we also need to store state on what type of thing is
>    in the cache, and this can be one of three things. (four, if you
>    include "nothing") Four things is two bits, which means two flag
>    tests instead of one. Hence, we just use the old-style IOK/NOK/POK */
>
> > *) Swap out vtables as the pmc internals change, rather than vectoring
> > off flags.

Ops, yeah, that's what I was trying to say above.

>
> That's probably the right way to do it. But what about overlapping types
> that are both integer and string OK?

Hense the larger number of combined types coupled with removing the cache and 
just storing each explicit type.

On Thursday 15 November 2001 02:07 pm, Uri Guttman wrote:
> and the PMC would have in it:
>
>       union {
>
>               INTVAL  *int ;
>               NUMVAL  *num ;
>       } data ;
>

-Michael

Reply via email to