Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[perl #17358] [PATCH] default.pmc #2

15 views
Skip to first unread message

Sean O'Rourke

unread,
Sep 16, 2002, 11:37:47 AM9/16/02
to perl6-i...@perl.org, bugs-bi...@netlabs.develooper.com, r...@x1.develooper.com
It seems to me that by making everything an exception, this patch goes too
far in a couple of ways. First, some fallback behaviors make sense. For
example, if a class implements set_bignum() but not set_int(), it makes
sense for default.pmc to wrap the int up as a bignum and send it on,
rather than complaining. Second, some methods actually _should_ do
nothing. For example, if a class does not need to do any initialization,
it should not have to explicitly define an empty init() function -- empty
init should be the default. Granted, some of the current or recently past
behaviors (e.g. invoke() silently continuing to the next instruction) are
less than helpful, but if all default does is throw error messages, it's
not that useful.

/s

On Mon, 16 Sep 2002, Leopold Toetsch wrote:

> # New Ticket Created by Leopold Toetsch
> # Please include the string: [perl #17358]
> # in the subject line of all future correspondence about this issue.
> # <URL: http://rt.perl.org/rt2/Ticket/Display.html?id=17358 >
>
>
> This patch makes almost all methods in default.pmc spit out an
> exception. The famous "Subscript on something, that is not an aggregate"
> now looks like, e.g.:
> "set_integer_keyed() not implemented in class 'PerlInt'"
>
> Please apply,
> leo
>
>
> -- attachment 1 ------------------------------------------------------
> url: http://rt.perl.org/rt2/attach/37883/30749/daadd2/default-pmc-2.patch
>
>


Leopold Toetsch

unread,
Sep 16, 2002, 2:11:51 PM9/16/02
to Sean O'Rourke, perl6-i...@perl.org, bugs-bi...@netlabs.develooper.com, r...@x1.develooper.com
Sean O'Rourke wrote:

> It seems to me that by making everything an exception, this patch goes too
> far in a couple of ways. First, some fallback behaviors make sense. For
> example, if a class implements set_bignum() but not set_int(), it makes
> sense for default.pmc to wrap the int up as a bignum and send it on,
> rather than complaining.


In this case, it should inherit from some basic_scalar.pmc, that
implements this for scalars. default.pmc is no more this default scalar
type, it's a "invalid.pmc".
Aggregates and Sub's and so on, don't need this function.

> ... Second, some methods actually _should_ do


> nothing. For example, if a class does not need to do any initialization,
> it should not have to explicitly define an empty init() function -- empty
> init should be the default.


Then they should implement an empty init() function (Currently we don't
have this case AFAIK).

> ... Granted, some of the current or recently past


> behaviors (e.g. invoke() silently continuing to the next instruction) are
> less than helpful, but if all default does is throw error messages, it's
> not that useful.


It safes hundreds of THROW_UNSUPPORTED and it can catch a lot of bugs.

I did have positive response to my RFC, so I take this still granted.


> /s


leo


Sean O'Rourke

unread,
Sep 16, 2002, 3:28:27 PM9/16/02
to Leopold Toetsch, perl6-i...@perl.org, bugs-bi...@netlabs.develooper.com, r...@x1.develooper.com
On Mon, 16 Sep 2002, Leopold Toetsch wrote:

> Sean O'Rourke wrote:
>
> > It seems to me that by making everything an exception, this patch goes too
> > far in a couple of ways. First, some fallback behaviors make sense. For
> > example, if a class implements set_bignum() but not set_int(), it makes
> > sense for default.pmc to wrap the int up as a bignum and send it on,
> > rather than complaining.
>
> In this case, it should inherit from some basic_scalar.pmc, that
> implements this for scalars. default.pmc is no more this default scalar
> type, it's a "invalid.pmc".
> Aggregates and Sub's and so on, don't need this function.

Then they shouldn't define _any_ of the add operations. 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.

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.

> > ... Second, some methods actually _should_ do
> > nothing. For example, if a class does not need to do any initialization,
> > it should not have to explicitly define an empty init() function -- empty
> > init should be the default.
>
> Then they should implement an empty init() function (Currently we don't
> have this case AFAIK).

"Should not!" ;)

> > ... Granted, some of the current or recently past
> > behaviors (e.g. invoke() silently continuing to the next instruction) are
> > less than helpful, but if all default does is throw error messages, it's
> > not that useful.
>
> It safes hundreds of THROW_UNSUPPORTED and it can catch a lot of bugs.

I'll admit, it took me a little while to figure out why my sub's invoke()
method wasn't getting called, when I added an extra space between the
'void' and the '*'. invoke() is a poster-child of a method that should
_not_ have a default -- what does it mean to "invoke" an integer? But I
suspect that there are a lot of operations that can be defined in terms of
others without causing any surprises. The bignum value of something that
knows how to become an int seems perfectly clear to me.

/s

Leopold Toetsch

unread,
Sep 17, 2002, 8:19:10 AM9/17/02
to Sean O'Rourke, perl6-i...@perl.org, bugs-bi...@netlabs.develooper.com, r...@x1.develooper.com
Sean O'Rourke wrote:

> On Mon, 16 Sep 2002, Leopold Toetsch wrote:
>
>
>>Sean O'Rourke wrote:


>>...it should inherit from some basic_scalar.pmc, that


>>implements this for scalars. default.pmc is no more this default scalar
>>type, it's a "invalid.pmc".
>>Aggregates and Sub's and so on, don't need this function.

> Then they shouldn't define _any_ of the add operations.


.... and the default.pmc will catch any abuse of adding a "Sub" to an int
and throw an exception.

> ... 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.


> 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".


>>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.


> I'll admit, it took me a little while to figure out why my sub's invoke()
> method wasn't getting called, when I added an extra space between the
> 'void' and the '*'. invoke() is a poster-child of a method that should
> _not_ have a default -- what does it mean to "invoke" an integer?


It should throw an exception, which "default.pmc" now does (and in case
of invoke already had done)

> But I
> suspect that there are a lot of operations that can be defined in terms of
> others without causing any surprises. The bignum value of something that
> knows how to become an int seems perfectly clear to me.


Yes, that's the planned inheritance from a scalar.pmc.

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


> /s

leo

Sean O'Rourke

unread,
Sep 17, 2002, 11:24:17 AM9/17/02
to Leopold Toetsch, perl6-i...@perl.org, bugs-bi...@netlabs.develooper.com, r...@x1.develooper.com
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


Leopold Toetsch

unread,
Sep 18, 2002, 1:46:53 AM9/18/02
to Sean O'Rourke, perl6-i...@perl.org, bugs-bi...@netlabs.develooper.com, r...@x1.develooper.com
Sean O'Rourke wrote:

> On Tue, 17 Sep 2002, Leopold Toetsch wrote:

>>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.


Yep. My planned layout of classes inheritance will look like this:

[default.pmc]
^

|

|
[sub.pmc]
[contination.pmc]
....

[default.pmc]
^
|

[scalar.pmc]
^
|
[perlint.pmc]
[array.pmc]
....


For the perl* classes, it might be useful, to insert another

"perlscalar.pmc" to inherit from.

>>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?


Because e.g. a continuation shouldn't have a e.g. set_number().


> Here's a list of what seems reasonable to me, default-wise. I suspect we
> agree more than it seems.


[ SNIP ]

Thanks for this comprehensive list.

leo

Dan Sugalski

unread,
Sep 18, 2002, 10:59:58 AM9/18/02
to Sean O'Rourke, perl6-i...@perl.org, bugs-bi...@netlabs.develooper.com, r...@x1.develooper.com
At 8:37 AM -0700 9/16/02, Sean O'Rourke wrote:
>It seems to me that by making everything an exception, this patch goes too
>far in a couple of ways. First, some fallback behaviors make sense. For
>example, if a class implements set_bignum() but not set_int(), it makes
>sense for default.pmc to wrap the int up as a bignum and send it on,
>rather than complaining.

Nope, that's not for default.pmc to do. That's something that we
should weld more smarts into the pmc preprocessor for, rather than
having fallbacks in default.pmc.

I'd rather default.pmc pitch errors unconditionally. We can, and
should, have some other method of indicating default methods should
be built from other methods, but default.pmc should be dead-boring
and stupid.
--
Dan

--------------------------------------"it's like this"-------------------
Dan Sugalski even samurai
d...@sidhe.org have teddy bears and even
teddy bears get drunk

0 new messages