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

Behaviour of PMCs on assignment

10 views
Skip to first unread message

Dan Sugalski

unread,
Mar 26, 2004, 4:51:22 PM3/26/04
to perl6-i...@perl.org
This has come up before and the discussion always semi-warnocks, but
it's time to bring it up again.

All the vtable operations that do PMC things are three-arg
versions--they get both the args and the destination PMCs passed in.
This is done specifically for speed reasons, as the assumption is
that, for example, the add vtable method for a PMC represents the
expression:

a = b + c

turns to

add a, b, c

in which case b's add function does the math and hand the result to a
via it's set vtable function, which is fine. A has the option of
overriding the assignment if that's necessary, for example if its
tied to a backing store of some sort. Fine. The addition may create a
temporary PMC, but there's really no way around that if we're to
maintain the proper API.

This becomes a bit less efficient when we're looking at intermediate
values of expressions. Something like:

a = b + c + d

turns to

new $P0, SomeIntermediateType
add $P0, b, c
add a, $P0, d

and we need to create that $P0 temp beforehand. While that's fine, it
leave things to the compiler to figure out what the intermediate type
should be, and often ends up creating two temps instead of one.
Moreover, it's distinctly possible that the temp that's created isn't
the right type, as the compiler may not know what the intermediate
expression will return.

I see three options:

1) Have a version of the binary vtable methods that create the destination PMC
2) Make a universal assignment PMC that takes on the characteristics
of the RHS of the assignment
3) Have a "this PMC intentionally left blank" flag to mark blank PMCs
and have vtable methods check that first

#1 doubles the number of vtable entries. Ick.
#2 has the most overhead
#3 leaves it to the vtable methods to check, which is error prone.
(Though if the #2 and #3 schemes were implemented with the same PMC
there'd be a good fallback)

Discussion time, folks. Pointing out things I've missed wouldn't be
out of line either...
--
Dan

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

Brent 'Dax' Royal-Gordon

unread,
Mar 26, 2004, 5:05:18 PM3/26/04
to Dan Sugalski, perl6-i...@perl.org
Dan Sugalski wrote:
> This becomes a bit less efficient when we're looking at intermediate
> values of expressions. Something like:
>
> a = b + c + d
>
> turns to
>
> new $P0, SomeIntermediateType
> add $P0, b, c
> add a, $P0, d

Well...how about this:

1. Have all vtable methods which take a dest return a PMC *.

2. If dest is NULL, it's filled with the appropriate type before
anything else is done.

3. At the end of the method, there's a "return dest;".

Thus, an op like add should be written like:

op add(inout PMC, in PMC, in PMC) {
$1=VTABLE_add(interpreter, $2, $3, $1); /* or whatever */
}

This does mean checking if dest == NULL at the beginning of each vtable
function, but other than that, it's fairly clean. It might even be
possible for pmc2c to insert this code automagically. (I believe PMC
registers are initialized to NULL, so it should Just Work most of the
time, and there's always the null_p op when you need to do it explicitly.)

--
Brent "Dax" Royal-Gordon <br...@brentdax.com>
Perl and Parrot hacker

Oceania has always been at war with Eastasia.

Leopold Toetsch

unread,
Mar 27, 2004, 1:38:43 AM3/27/04
to Dan Sugalski, perl6-i...@perl.org
Dan Sugalski <d...@sidhe.org> wrote:

> This becomes a bit less efficient when we're looking at intermediate
> values of expressions. Something like:

> a = b + c + d

> turns to

> new $P0, SomeIntermediateType
> add $P0, b, c
> add a, $P0, d

> and we need to create that $P0 temp beforehand. While that's fine, it
> leave things to the compiler to figure out what the intermediate type
> should be, and often ends up creating two temps instead of one.

Well, yes. It's up to the compiler. Perl6 would insert

$P1 = new PerlUndef

and Pie-Thon would have a C<new PieScalar> or such.

Why should it create two temps?

> Moreover, it's distinctly possible that the temp that's created isn't
> the right type, as the compiler may not know what the intermediate
> expression will return.

The C<new Undef> something has to morph itself into an appropriate type
IMHO.

> I see three options:

I think its really up to the HLL compiler to generate a suitable LHS
PMC that (accompanied by appropriate assign vtables) does the right
thing.

To you have examples, which indicate that this isn't possible?

leo

Leopold Toetsch

unread,
Mar 27, 2004, 1:27:29 AM3/27/04
to Brent 'Dax' Royal-Gordon, perl6-i...@perl.org
Brent 'Dax' Royal-Gordon <br...@brentdax.com> wrote:
> Dan Sugalski wrote:
>> This becomes a bit less efficient when we're looking at intermediate
>> values of expressions. Something like:
>>
>> a = b + c + d
>>
>> turns to
>>
>> new $P0, SomeIntermediateType
>> add $P0, b, c
>> add a, $P0, d

> Well...how about this:

> 1. Have all vtable methods which take a dest return a PMC *.

> 2. If dest is NULL, it's filled with the appropriate type before
> anything else is done.

*Strong NAK* :)

The register allocator has to track the life span of each variable and
temp. If the life of a register ends at one point, this register is
reused:

# a = b + c + d
$P0 = $P1 + $P2 # (1]
$P3 = new PerlUndef # (2)
$P3 = $P0 + $P4

Let's assume that C<$P1> or C<$P2> are also temps and not reused beyond
instruction (1). With that in mind $P3 is assigned to the same Parrot
register as one of this temps.

With the Parrot Calling Conventions we did effectively cut down the
assignable register range to P16..P31 (using registers in the low range
is possible but not easy).

So back to your proposal: Above example could look like:

$P0 = $P1 + $P2
$P3 = $P0 + $P4

Now the register allocator does of course not know, *if* the C<$P3> is
C<PMCNULL> at runtime. It has to assume that it isn't. No register can
be reused, the register allocator would run short of registers after
very few instructions.

> (I believe PMC
> registers are initialized to NULL,

That's a wrong assumption too. They are intially PMCNULL in @MAIN. But
when you call a subroutine, the registers are just that, what they used
to be in the caller.

It could work, if the sequence is:

$P0 = $P1 + $P2
null $P3
$P3 = $P0 + $P4

The C<null (out PMC)> opcode cuts the life range of C<$P3> because of
its C<out> specifier.

But now we have the runtime overhead in each such vtable method (test
for PMCNULL) and one additional function argument to pass.

leo

Brent 'Dax' Royal-Gordon

unread,
Mar 27, 2004, 3:01:25 AM3/27/04
to l...@toetsch.at, perl6-i...@perl.org
And I show my ignorance yet again. I really need to do some serious
research into how things have changed...

Leopold Toetsch wrote:
> It could work, if the sequence is:
>
> $P0 = $P1 + $P2
> null $P3
> $P3 = $P0 + $P4
>
> The C<null (out PMC)> opcode cuts the life range of C<$P3> because of
> its C<out> specifier.

Hmmm...that might work.

> But now we have the runtime overhead in each such vtable method (test
> for PMCNULL) and one additional function argument to pass.

I don't see the additional argument--dest is already being passed to the
vtable methods. There's a new return value, but no new argument. There
is also a branch on dest == PMCNULL, which is rather suboptimal.

What if, by calling PMCNULL's set_(integer|string|float|pmc) vtable
methods, you actually allocate a new PMC of the appropriate type? In
other words, for null:

PMC* set_integer_native(INTVAL value) {
PMC* ret=pmc_new(INTERP, some_integer_type); /* Er... */
VTABLE_set_integer_native(INTERP, ret, value);
return ret;
}

And then for an integer type:

PMC* add(PMC* value, PMC* dest) {
/* A bunch of fancy logic that boils down to... */
return VTABLE_set_integer_native(INTERP, dest,
VTABLE_get_integer(INTERP, SELF) +
VTABLE_get_integer(INTERP, value)
);
}

Any other type's set_integer_native would be like:

PMC* set_integer_native(INTVAL value) {
PMC_int_val(SELF)=value;
return SELF;
}

(Plus or minus morphing code.)

The big problem is some_integer_type. I'm not really sure what to do
about that.

Leopold Toetsch

unread,
Mar 27, 2004, 5:43:35 AM3/27/04
to Brent 'Dax' Royal-Gordon, perl6-i...@perl.org
Brent 'Dax' Royal-Gordon <br...@brentdax.com> wrote:
> And I show my ignorance yet again. I really need to do some serious
> research into how things have changed...

> Leopold Toetsch wrote:
>> It could work, if the sequence is:
>>
>> $P0 = $P1 + $P2
>> null $P3
>> $P3 = $P0 + $P4
>>
>> The C<null (out PMC)> opcode cuts the life range of C<$P3> because of
>> its C<out> specifier.

> Hmmm...that might work.

>> But now we have the runtime overhead in each such vtable method (test
>> for PMCNULL) and one additional function argument to pass.

> I don't see the additional argument--dest is already being passed to the
> vtable methods. There's a new return value, but no new argument. There
> is also a branch on dest == PMCNULL, which is rather suboptimal.

Yep.

> What if, by calling PMCNULL's set_(integer|string|float|pmc) vtable
> methods, you actually allocate a new PMC of the appropriate type? In
> other words, for null:

> PMC* set_integer_native(INTVAL value) {
> PMC* ret=pmc_new(INTERP, some_integer_type); /* Er... */
> VTABLE_set_integer_native(INTERP, ret, value);
> return ret;
> }

Well that seems to boil down to move the problem from PerlUndef to
PMCNULL. What is the approprate type? HLL should know it. It's getting
worse IMHO.

A PerlInt/PerlNum ... knows how to morph a destination PerlUndef to the
appropriate type. So should a Python scalar. Moving this to PMCNULL for
*all* different HLL scalars isn't really good.

leo

Togos

unread,
Mar 27, 2004, 4:36:07 PM3/27/04
to perl6-i...@perl.org
Ergh. Once agian, sorry if this shows up twice. If
someone can tell me a way to be subscribed to the list
without actually getting every message (I prefer to
read from the archive), that'd be great. Anyway...

> This has come up before and the discussion
> always semi-warnocks, but

Yeah...

> 1) Have a version of the binary vtable
> methods that create the destination PMC
> 2) Make a universal assignment PMC that
> takes on the characteristics
> of the RHS of the assignment
> 3) Have a "this PMC intentionally left blank"
> flag to mark blank PMCs
> and have vtable methods check that first

> #1 doubles the number of vtable entries. Ick.
> #2 has the most overhead
> #3 leaves it to the vtable methods to check,
> which is error prone.

Well, as I was saying last summer, #1 is really what
the add instruction should have done in the first
place, as that would make it behave the same way as it
does for ints and floats (replacing the value, not
altering the current one), and it is what most high
level languages expect, anyway.

However, my argument was mostly about the former (that
opcode name and IMCC syntax should differentiate
between the 2 types of behavior) rather than the
latter (that there should be a non-destructive version
of PMC add).

The Right Thing to do would be to rename the current
add op to "add_destructive" or something, and call the
new one just "add", acting like add for ints and
floats. The imcc "a = b + c" opererator would use the
non-destructive version.

But judging by the way I was pretty much ignored the
first time, and that Dan's already using Parrot at
work, and nobody wants to re-write the code they
started working on last week, I don't expect that to
actually happen. But it would be the Right Thing.

whether or not any opcode renaming is done, I'd say
that adding the non-destructive ops is probably the
best thing to do, as HLLs are going to want them
anyway. It certainly makes the compiler's job a lot
easier, and would lead to much cleaner output.
Otherwise these operations would have to be
implemented as methods (or something) in any case
where the compiler doesn't know *exactly* what kind of
object an arithmetic operation will result in.Re:

__________________________________
Do you Yahoo!?
Yahoo! Finance Tax Center - File online. File on time.
http://taxes.yahoo.com/filing.html

Leopold Toetsch

unread,
Mar 29, 2004, 2:11:54 AM3/29/04
to Togos, perl6-i...@perl.org
Togos <chumps...@yahoo.com> wrote:

>> 1) Have a version of the binary vtable
>> methods that create the destination PMC

> Well, as I was saying last summer, #1 is really what


> the add instruction should have done in the first
> place, as that would make it behave the same way as it
> does for ints and floats (replacing the value, not
> altering the current one), and it is what most high
> level languages expect, anyway.

What about:

a = global "$a" # or fetch a lexcical or ...


a = b + c

All PMCs living in aggregates have reference semantics. When the LHS is
a lexical, global, property, array member, or hash member, the current
opcodes (and vtables) do the rigth thing.

If a temp is needed the HLL compiler emits the code for creating a temp:

$P4711 = new PerlUndef # or PyScalar or ...

Having two sets of opcodes and vtables doesn't help the HLL compiler. It
has to select to correct opcode anyway. Two sets of opcodes and vtables
just increase opcode and vtable count up to an insane number.

leo

Togos

unread,
Mar 27, 2004, 4:02:52 AM3/27/04
to perl6-i...@perl.org
> This has come up before and the discussion
> always semi-warnocks, but

Yeah...

> 1) Have a version of the binary vtable


> methods that create the destination PMC

> 2) Make a universal assignment PMC that
> takes on the characteristics
> of the RHS of the assignment
> 3) Have a "this PMC intentionally left blank"
> flag to mark blank PMCs
> and have vtable methods check that first

> #1 doubles the number of vtable entries. Ick.
> #2 has the most overhead
> #3 leaves it to the vtable methods to check,
> which is error prone.

Well, as I was saying last summer, #1 is really what


the add instruction should have done in the first
place, as that would make it behave the same way as it
does for ints and floats (replacing the value, not
altering the current one), and it is what most high
level languages expect, anyway.

However, my argument was mostly about the former (that


opcode name and IMCC syntax should differentiate
between the 2 types of behavior) rather than the
latter (that there should be a non-destructive version
of PMC add).

The Right Thing to do would be to rename the current
add op to "add_destructive" or something, and call the
new one just "add", acting like add for ints and
floats. The imcc "a = b + c" opererator would use the
non-destructive version.

But judging by the way I was pretty much ignored the
first time, and that Dan's already using Parrot at
work, and nobody wants to re-write the code they
started working on last week, I don't expect that to
actually happen. But it would be the Right Thing.

whether or not any opcode renaming is done, I'd say
that adding the non-destructive ops is probably the
best thing to do, as HLLs are going to want them
anyway. It certainly makes the compiler's job a lot
easier, and would lead to much cleaner output.
Otherwise these operations would have to be
implemented as methods (or something) in any case
where the compiler doesn't know *exactly* what kind of
object an arithmetic operation will result in.

__________________________________

Dan Sugalski

unread,
Mar 29, 2004, 9:17:44 AM3/29/04
to Brent 'Dax' Royal-Gordon, perl6-i...@perl.org
At 2:05 PM -0800 3/26/04, Brent 'Dax' Royal-Gordon wrote:
>This does mean checking if dest == NULL at the beginning of each
>vtable function, but other than that, it's fairly clean.

That's one of the things I was trying to avoid in the original
design, though. It means a null check in every vtable function,
something that's both somewhat error prone, as well as time
consuming. (Not a *lot* of time, mind, but we can do a lot of vtable
ops a second, and the extra few cycles adds up)

Dan Sugalski

unread,
Mar 29, 2004, 10:10:20 AM3/29/04
to l...@toetsch.at, perl6-i...@perl.org
At 7:38 AM +0100 3/27/04, Leopold Toetsch wrote:
>Dan Sugalski <d...@sidhe.org> wrote:
>
>> This becomes a bit less efficient when we're looking at intermediate
>> values of expressions. Something like:
>
>> a = b + c + d
>
>> turns to
>
>> new $P0, SomeIntermediateType
>> add $P0, b, c
>> add a, $P0, d
>
>> and we need to create that $P0 temp beforehand. While that's fine, it
>> leave things to the compiler to figure out what the intermediate type
>> should be, and often ends up creating two temps instead of one.
>
>Well, yes. It's up to the compiler. Perl6 would insert
>
> $P1 = new PerlUndef
>
>and Pie-Thon would have a C<new PieScalar> or such.

Except that in a multi-language environment (such as the one we're
encouraging) the compiler can't know for sure what to insert, if
theres a choice.

>Why should it create two temps?

Well, if the vtable function that adds $P0 and D doesn't know
anything about the structure of A (so it can't poke at its innards
directly) it has to hand a value to A's assign method. If the
addition of $P0 and D produces a non-simple value (something that's
not an int, float, or string) then it'll end up creating a temp PMC,
and calling set_pmc on A. That

> > Moreover, it's distinctly possible that the temp that's created isn't
>> the right type, as the compiler may not know what the intermediate
>> expression will return.
>
>The C<new Undef> something has to morph itself into an appropriate type
>IMHO.

I'm leaning that way myself, but I'm not 100% convinced yet.

> > I see three options:
>
>I think its really up to the HLL compiler to generate a suitable LHS
>PMC that (accompanied by appropriate assign vtables) does the right
>thing.

As I've said, it can't. There's too much uncertainty.

>To you have examples, which indicate that this isn't possible?

Start mixing overloaded objects, python, perl 5, perl 6, ruby, and
lisp returned values in an expression. It's not tough to come up with
a whole slew of reasonable possibilities.

Togos

unread,
Mar 29, 2004, 6:32:32 PM3/29/04
to perl6-i...@perl.org
Well I just realized something. Or at least realized a
better way to explain it.

Let's say we have a HLL that is mapping HL variables
to Parrot registers.

someint1 = someint2 + someint3

will, of course, map to something like

$I1 = $I2 + $I3

Now, if those ints were replaced by PMC references:
(behavior A)

somepmc1 = somepmc2 + somepmc3

we Ruby folks would like to be able to do:

$P1 = $P2 + $P3

Which, of course, doesn't work. But this is what
languages like Python or Ruby would expect to be able
to do, as they don't need Perl's fancy variable
objects -- a register is good enough. The current
sementics of

$P1 = $P2 + $P3

look more like this:
(behavior B)

somepmc1.value = somepmc2 + somepmc3

Which is obviously different than the semantics of
behavior A. That's not to say it's useless, as Leo
pointed out, it could be used in cases like

> a = global "$a" # or fetch a lexcical or ...

> a = b + c

But it certainly is different.

One problem is that the current semantics use behavior
B, but appear to use behavior A ('a = b + c' acts
differently if you're talking about ints or PMCs). The
other problem is that we often want behavior A, but
have to jump through hoops to implement it using
behavior B. The argument that we shouldn't implement
behavior A because it would add more opcodes seems
akin to arguing that we shouldn't waste opcodes making
a subtraction op since we already have one for
division. They're very different things, and shouldn't
be confused or mangled to serve the purpose of the
other.

My proposal still stands, then:

$P1 = $P2 + $P3

should have the semantics of

pmc1 = pmc2 + pmc3 (Ruby/Python code)

rather than it's current behavior of

pmc1.value = pmc2 + pmc3

And if the latter behavior is common enough, then it
should have its own instruction. 'content_add' or
something. Same goes for the other PMC modifying ops.

- TOGoS

Leopold Toetsch

unread,
Mar 30, 2004, 1:10:48 AM3/30/04
to Togos, perl6-i...@perl.org
Togos <chumps...@yahoo.com> wrote:

> $I1 = $I2 + $I3

> $P1 = $P2 + $P3

> Which, of course, doesn't work. But this is what
> languages like Python or Ruby would expect to be able
> to do, as they don't need Perl's fancy variable
> objects -- a register is good enough.

> sementics of

That and other arguments are of course all correct. I just have the gut
feeling that having both opcode and vtable variants blows core size up
to an isane value.

Can someone calculate opcode count (math, logical, bitwise...) and needed
vtables so that we can estimate the increase.

leo

Dan Sugalski

unread,
Apr 1, 2004, 3:58:35 PM4/1/04
to TOGoS, perl6-i...@perl.org
At 3:32 PM -0800 3/29/04, TOGoS wrote:
>Well I just realized something. Or at least realized a
>better way to explain it.
>
>Let's say we have a HLL that is mapping HL variables
>to Parrot registers.
>
> someint1 = someint2 + someint3
>
>will, of course, map to something like
>
> $I1 = $I2 + $I3
>
>Now, if those ints were replaced by PMC references:
>(behavior A)
>
> somepmc1 = somepmc2 + somepmc3
>
>we Ruby folks would like to be able to do:
>
> $P1 = $P2 + $P3
>
>Which, of course, doesn't work.

Well... actually you don't want what you're asking for.

Specifically you don't want

foo = bar + baz

to access the foo, bar, or baz named slots in the global or lexical
variable areas if you can possibly help it. Really, you don't--doing
so likely needs a hash lookup (for globals) or an indirect slot
lookup (for lexicals, if you're lucky. If not you have a hash lookup)
You *definitely* don't want it to translate into:

$P0 = fetch_lex "bar"
$P1 = fetch_lex "baz"
add_new $P2, $P0, $P1
store_lex "foo", $P2

Because that's really inefficient if you've used foo, bar, or baz
elsewhere in the compilation unit already. It's also very wrong if
foo is *not* an object, because you don't want assignment to
unconditionally rebind--the destination variable has to control what
happens on assignment. Rebinding might be the right thing, but, then,
it might not be. (If foo, for example, is a low-level 32 bit integer
you would *not* want it rebinding)

The standard, and arguably correct, thing to do here is to introduce
a mediating structure. It's a pretty common thing--you bind the name
to the mediating structure essentially permanently, and then hand
your object off that structure. Doing assignment then, rather than
rebinding the name to the new object, instead rebinds the mediating
structure to the new object. This allows the compiler to cache what
is fetched from the symbol tables--since the binding to the mediating
structure is permanent you can avoid multiple fetches and stores.

The added bonus here is that if the thing you got out of the symbol
table *isn't* one of these mediating structures (because it's a PMC
for an int, say, or a matrix) then assignment still Does The Right
Thing, since the destination controls the assignment.

Right now the missing piece for Parrot is that mediating
structure--ParrotObjects, rather than going directly into the symbol
tables, really need to be hidden behind ParrotReference or
ParrotObjectHandle PMCs to provide the appropriate level of
indirection.

If we do that it all works out right, which is quite nice.

Togos

unread,
Apr 1, 2004, 7:21:44 PM4/1/04
to perl6-i...@perl.org, Dan Sugalski

--- Dan Sugalski <d...@sidhe.org> wrote:
> >we Ruby folks would like to be able to do:
> >
> > $P1 = $P2 + $P3
> >
> >Which, of course, doesn't work.
>
> Well... actually you don't want what you're asking
> for.

Maybe... :/

Well, I understand the reason for using mediating
structures for efficiency, but why do I never want
assignment to unconditionally re-bind? In my
experience, that usually *is* what I want.

> The standard, and arguably correct, thing to do here
> is to introduce
> a mediating structure. It's a pretty common
> thing--you bind the name
> to the mediating structure essentially permanently,
> and then hand
> your object off that structure. Doing assignment
> then, rather than
> rebinding the name to the new object, instead
> rebinds the mediating
> structure to the new object. This allows the
> compiler to cache what
> is fetched from the symbol tables--since the binding
> to the mediating
> structure is permanent you can avoid multiple
> fetches and stores.

So you would normally never use store_global, but only
fetch_global, and then assign to that container? In
that case, it might be useful to have another op that
retrieves that container, or creates it if it doesn't
exist (find_or_create_global).

> The added bonus here is that if the thing you got
> out of the symbol
> table *isn't* one of these mediating structures
> (because it's a PMC
> for an int, say, or a matrix) then assignment still
> Does The Right
> Thing, since the destination controls the
> assignment.

So if you don't want people messing with your object
when assigning to a global, you'd better put it in a
mediating structure before storing it in that global?

> Right now the missing piece for Parrot is that
> mediating
> structure--ParrotObjects, rather than going directly
> into the symbol
> tables, really need to be hidden behind
> ParrotReference or
> ParrotObjectHandle PMCs to provide the appropriate
> level of
> indirection.
>
> If we do that it all works out right, which is quite
> nice.

My main issue with this is that you're assuming that
there is *always* a mediating structure involved, and
building this assumption into the PIR syntax by using
the same operator ("=") both for operations that work
on the register directly (new), and for those that go
through the reference object (add). It's fine to have
operations that work through the reference object,
even to *only* have those, but they should look
different than those that work directly on values (as
the int or float version of 'add' do). There should be
one operator for binding, and one for 'assign'ment. So
when I look at this PIR code

foo = bar + baz

it shouldn't matter if foo, bar, and baz are PMCs or
ints or floats. It'll either have 'set' behavior, or
not compile (assuming "=" represents the binding op,
and not the assignment op. Otherwise, replace "set"
with "assign").


__________________________________
Do you Yahoo!?
Yahoo! Small Business $15K Web Design Giveaway
http://promotions.yahoo.com/design_giveaway/

Piers Cawley

unread,
Apr 7, 2004, 4:20:49 AM4/7/04
to l...@toetsch.at, Togos, perl6-i...@perl.org
Leopold Toetsch <l...@toetsch.at> writes:

> Togos <chumps...@yahoo.com> wrote:
>
>> $I1 = $I2 + $I3
>
>> $P1 = $P2 + $P3
>
>> Which, of course, doesn't work. But this is what
>> languages like Python or Ruby would expect to be able
>> to do, as they don't need Perl's fancy variable
>> objects -- a register is good enough.
>> sementics of
>
> That and other arguments are of course all correct. I just have the gut
> feeling that having both opcode and vtable variants blows core size up
> to an isane value.

Couldn't you have a single opcode, C<assign_content Pn, Pm>, which uses
Pn's vtable assignment, and make C<add $P1, $P2, $P3> etc simply use
the 'make a new PMC' thing. That means that, to get the current
semantics you'd have to do

$P2 = $P3 + $P4
assign_content $P1, $P2

But I'm not sure that's an enormous loss.

Leopold Toetsch

unread,
Apr 7, 2004, 4:52:44 AM4/7/04
to Piers Cawley, perl6-i...@perl.org
Piers Cawley <pdca...@bofh.org.uk> wrote:
> Leopold Toetsch <l...@toetsch.at> writes:

>> That and other arguments are of course all correct. I just have the gut
>> feeling that having both opcode and vtable variants blows core size up
>> to an isane value.

> Couldn't you have a single opcode, C<assign_content Pn, Pm>, which uses
> Pn's vtable assignment, and make C<add $P1, $P2, $P3> etc simply use
> the 'make a new PMC' thing. That means that, to get the current
> semantics you'd have to do

> $P2 = $P3 + $P4
> assign_content $P1, $P2

When C<add> and friends create a new PMC always, this isn't really good,
when working with any kind of references:

$P2 = global "$a"


$P2 = $P3 + $P4

Globals and lexicals already have a PMC inside, which we should just
assign a new value. Aggregates are a bit different, they might or might
not have already a value:

$P2 = hash["key"]


$P2 = $P3 + $P4

BTW - it's still undecided, if the created PerlUndef for a non-existent
key should be stored in the hash.

The automatic creation of LHS PMCs is really only usefull with temps.
But if such a temp isn't stored into an array or such, the temp PMC
could even be reused, e.g. if the temp is the RHS of another math
operation.

leo

Togos

unread,
Apr 7, 2004, 10:37:21 AM4/7/04
to perl6-i...@perl.org, Piers Cawley

That would make a lot of sense (well, actually I think
just using 'assign' would do the trick here). *I* like
it, but then I'm not familiar with all the things that
Dan and Leo are that would make it suck :)

In any case, the way Dan described the way things are
*supposed* to work (all PMCs act like variable
references), it seems like there will be a need for an
op that assigns the content of one PMC to another, so
you could do like this:

# foo = bar

find_global $P1, "bar"
find_or_create_global $P2, "foo"
assign_content $P1, $P2

(plain ole' assign wouldn't quite do the trick, as
it'd assign the reference to foo, and then foo'd be a
reference to a reference, which probably isn't what
you want).

And, BTW, being subscribed only to the digest does
seem to allow me to post to the list without delay.
Whether that's a good thing or not is for y'all to
decide :P

0 new messages