On Tue, 17 Sep 2002, Leopold Toetsch wrote:
> ... and the default.pmc will catch any abuse of adding a "Sub" to an int
> and throw an exception.

Right.  The current default.pmc non-error implementation of get_integer
(returning cache.int_val) is wrong, and should go away.

> > ... IMHO once a class
> > says how it can be interpreted as e.g. a number, it's eminently reasonable
> > to default the rest of its numeric operations, and to do widening
> > conversions to take advantage of implemented ops.
>
> Yes of course. What once was in "default.pmc" will be "scalar.pmc",
> where all scalar like classes can inherit from.

And from which perlarray.pmc, perlhash.pmc, and (probably) a whole host of
other types that need scalar-like operations will inherit.

> > I guess one way to measure which way makes more sense is to put in the new
> > default.pmc, then see if there end up being any classes inheriting from it
> > directly, or if everything goes through an intermediate conversion class.
>
> As I already stated, we had til now _no_ inheritance from "default.pmc"
> except for the famous "Subscript on something that's not an aggregate".

And invoke for integers.

> >>Then they should implement an empty init() function (Currently we don't
> >>have this case AFAIK).
>
> > "Should not!" ;)
>
> This is one additional line. Please compare this with 5KB lines I saved
> in array.pmc.

Okay, but these two things are unrelated.  We can save both the 5k in
array.pmc _and_ the two lines in every single other class by having a
default empty init.

> Summary:
> default.pmc catches errors, and may provide e.g. ->name or ->type.
> scalar.pmc will be the default scalar base class.

Why only (or even) ->name and ->type?

Here's a list of what seems reasonable to me, default-wise.  I suspect we
agree more than it seems.  You also might want to take a look at
pdd02_vtables, which gives some indication of what should and should not
throw exceptions.  These will doubtless need some tweaking, but better to
figure this out once now than to keep playing with it into the indefinite
future, when a bunch of dependent classes may have to change along with
it.

/s

For X_keyed_int(y) where X_keyed() exists, the default should be to
call X_keyed(make_key(y)).  When X_keyed() is the default/error
implementation, doing so will throw an error.

For X_keyed(k, y), call get_pmc_keyed(k)->X(y), e.g. elements_keyed(k)
becomes get_pmc_keyed(k)->elements().

For X_keyed(k, y, value_key), call
get_pmc_keyed(k)->X_keyed(rest_of_key, y, value_key).

For set_X(PMC p) where set_X_native(n) exists, call
set_X_native(p->get_X()) if it exists in non-default form.  If not,
call set_pmc(p), e.g. set_number(p) becomes either
set_number_native(p->get_number()) or set_pmc(p), depending on what
our derived class implements.

Analogously, for set_X_same(PMC p), call set_X(p) if it is
non-default, or set_same(p).

For arithmetic op OP (add,subtract,multiply,divide,mod):
        - OP_int(v, res) -> res->set_integer_native(v OP
SELF->get_integer())
        - OP_number(v, res) -> res->set_number_native(v OP
SELF->get_number())
        - OP_bignum(v, res) -> res->set_bignum_native(bignum_OP(v,
                                SELF->get_bignum())
        - OP_same -> OP
        - OP(v, res) -> error
        - OP_keyed[_int] -> (see above)

For bitwise op OP (or,and,xor,shl,shr,not):
        - OP_int(v, res) -> res->set_integer_native(v OP
SELF->get_integer())
        - OP_same -> OP
        - OP -> error

void init()
        - do nothing (or call init_pmc(NULL))
void init_pmc(PMC* initializer)
        - do nothing
void morph(INTVAL type)
        - error
PMC* mark(PMC* tail)
        - nothing
void destroy()
        - nothing

INTVAL type()
        - return whatever type this has been enumerated to be
INTVAL type_keyed(PMC* key)
        - error

UINTVAL subtype(INTVAL type)
        - subtypes don't seem to be used now
UINTVAL subtype_keyed(PMC* key, INTVAL type)
        - error

STRING* name()
        - "return whoami"?
STRING* name_keyed(PMC* key)
        - error

PMC* clone()
        - memcpy
PMC* clone_keyed(PMC* key)
        - error

PMC* find_method(STRING* method_name)
        - error
PMC* find_method_keyed(PMC* key, STRING* method_name)
        - error

INTVAL get_integer()
        - error

FLOATVAL get_number()
        - (FLOATVAL)get_integer(), or maybe an error if FLOATVALs lose
          precision when converting to INTVALs on this platform.

BIGNUM* get_bignum()
        - make_bignum(get_{integer,number}()) -- depends which people
prefer

STRING* get_string()
        - error

INTVAL get_bool()
        - error, unless everyone agrees on a common standard of truth
          w.r.t. get_string or get_integer.

INTVAL elements()
        - error

PMC* get_pmc()
        - return SELF, assuming very few classes will return something
          other than themselves.

INTVAL is_same(PMC* value)
        - return value == SELF (i.e. same address)

void set_integer_native(INTVAL value)
        - set_number_native((FLOATVAL)value), or set_bignum_native if
          loss of precision might result.

void set_number_native(FLOATVAL value)
        - set_bignum(make_bignum(value))

void set_bignum_native(BIGNUM* value)
        - error

void set_string_native(STRING* value)
        - error

void set_pmc(PMC* value)
        - error

void set_same(PMC* value)
        - set_pmc(value)
void set_same_keyed(PMC* key, PMC* value, PMC* value_key)
        - get_pmc_keyed(key)->set_pmc_keyed(rest_of_key, value, value_key)

INTVAL pop_integer()
        - (INTVAL)pop_float/pop_bignum, depending on width, if it is
          non-default.  Otherwise, pop_pmc()->get_integer()

FLOATVAL pop_float()
        - (FLOATVAL)pop_bignum() or pop_pmc->get_float().  This should
          be renamed to pop_number().

BIGNUM* pop_bignum()
        - pop_pmc->get_bignum()

STRING* pop_string()
        - pop_pmc->get_string()

PMC* pop_pmc()
        - error or splice

void push_integer(INTVAL value)
        - push_number(value)

void push_float(FLOATVAL value)
        - push_bignum(value)

void push_bignum(BIGNUM* value)
        - error

void push_string(STRING* value)
        - error

void push_pmc(PMC* value)
        - error

shift, unshift -- same as push/pop

## void splice ???
        - would be nice...

void neg(PMC* dest)
        - error (?)

void concatenate(PMC* value, PMC* dest)
        - concatenate_native(value->get_string(), dest)
void concatenate_native(STRING* value, PMC* dest)
        - dest->set_string_native(cat(SELF->get_string(), value))
void concatenate_same(PMC* value, PMC* dest)
        - concatenate()

INTVAL is_equal(PMC* value)
        - if cmp is non-default, (cmp(value) == 0), otherwise
          is_same().

INTVAL cmp(PMC* value)
        - error
INTVAL cmp_num(PMC* value)
        - numcmp(SELF->get_bignum(), value->get_bignum())
INTVAL cmp_string(PMC* value)
        - strcmp(SELF->get_string(), value->get_string())

NOTE: particularly for xor, but also for other things, we could use a
set_boolean(PMC) and a set_boolean_native(INTVAL).

void logical_or(PMC* value, PMC* dest)
        - if SELF->get_bool()
             dest->set_boolean(SELF)
          else
             dest->set_boolean(value)

void logical_and(PMC* value, PMC* dest)
        - if !(SELF->get_bool())
             dest->set_boolean(SELF)
          else
             dest->set_boolean(value)

void logical_xor(PMC* value, PMC* dest)
        - dest->set_boolean_native(SELF->get_bool() xor value->get_bool())

void logical_not(PMC* dest)
        - dest->set_boolean_native(!SELF->get_bool())

void repeat(PMC* value, PMC* dest)
        - repeat_int(value->get_integer(), dest)
void repeat_int(INTVAL value, PMC* dest)
        - error

void increment()
        - SELF->set_same(SELF->add_integer(1, SELF))

void decrement()
        - SELF->set_same(SELF->subtract_integer(1, SELF))

INTVAL exists_keyed(PMC* key)
        - error

INTVAL defined()
        - return 1

void delete_keyed(PMC* key)
        - error

PMC* nextkey_keyed(PMC* key)
        - error

void substr(INTVAL offset, INTVAL length, PMC* dest)
        - dest->set_string_native(substr_str(offset, length))
STRING* substr_str(INTVAL offset, INTVAL length)
        - substr(SELF->get_string(), offset, length)

void* invoke(void* next)
        - error


Reply via email to