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

Set vs. Assign..?

1 view
Skip to first unread message

T.O.G. Of Spookware

unread,
Aug 1, 2003, 2:45:16 PM8/1/03
to perl6-i...@perl.org
Hi, all. I've been following Parrot development and
been playing with Parrot for a...bout a year and a
half, now. First time posting to the list, though, so
forgive me if this has already been covered or is
stupid in some way :-)

Anyway, while playing around with IMCC, this kind of
bugged me:

P3 = 32 # tells the PMC referenced by P3 to
set its value to 32
P3 = P5 # copies reference in P5 to P3

What I don't like about this is that it's not
immediately obvious from looking at the code whether
you're telling P3 to change its value or simply
replace the PMC reference stored in P3 with another.

As I understand it, this is how it works at
the assmbly level:

set Px, Iy # alters the PMC referenced by Px
set Px, Py # only copies a reference
assign Px, Py # alters the PMC referenced by Px

Whether you copy a reference or just tell the
referenced object to change itself depends
on the type of the operands. It would be less
confusing if you had to be explicit about what
you were doing:

assign Px, 3 # Tells Px to set its value to 3
set Px, 3 # Compile error. You can't
set a PMC reference to an int! WTF?

Similarly,
set Sx, Ix
would barf on you, while
assign Sx, Ix
would do what you want, and
set Sx, Sy
would still be perfectly legal. And
assign Ix, Iy
would throw a fit because you cannot really
'change' an integer, but only replace
it with another, and
set Ix, Iy
would still be correct.

So: "set" would consistantly copy references,
while "assign" asks the object currently
referenced to change its value, somehow.

perhaps PASM's "set" <=> IMCC's "=", while
PASM's "assign" <=> IMCC's "<=" or something :-P

Once again, sorry if this is dumb.

__________________________________
Do you Yahoo!?
Yahoo! SiteBuilder - Free, easy-to-use web site design software
http://sitebuilder.yahoo.com

Dan Sugalski

unread,
Aug 4, 2003, 12:18:51 PM8/4/03
to T.O.G. of Spookware, perl6-i...@perl.org
At 11:45 AM -0700 8/1/03, T.O.G. of Spookware wrote:
>
>Hi, all. I've been following Parrot development and
>been playing with Parrot for a...bout a year and a
>half, now. First time posting to the list, though, so
>forgive me if this has already been covered or is
>stupid in some way :-)
>
>Anyway, while playing around with IMCC, this kind of
>bugged me:
>
>P3 = 32 # tells the PMC referenced by P3 to
> set its value to 32
>P3 = P5 # copies reference in P5 to P3
>
>What I don't like about this is that it's not
>immediately obvious from looking at the code whether
>you're telling P3 to change its value or simply
>replace the PMC reference stored in P3 with another.

This is a reasonable thing to worry about, because we have three
separate semantics, set, assign, and clone.

For I and N registers, all three are identical, since integers and
floats are value types at this level.

For S and P registers, things get odd. set just copies the contents
of one register to another. Since P and S registers are pointers, it
means you have two registers that point to the same string or PMC
structure.

Assign takes the contents of the structure that the S or P source
register points to and puts those contents into the structure the
destination register points to. A new structure is not created, and
if the destination is supposed to do something when a value is put
into it, then the destination does that. (If, for example, the
destination variable overloads assignment or is tied, depending on
the language you come from)

Cloning makes a copy of the source, complete with new structure, and
puts a pointer to the new structure into the destination register,
throwing away whatever pointer was in there to begin with.

It's a bit funky, but you need all three semantics to make things
work out right.
--
Dan

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

Togos

unread,
Aug 4, 2003, 1:08:02 PM8/4/03
to Dan Sugalski, perl6-i...@perl.org
--- Dan Sugalski <d...@sidhe.org> wrote:
> At 11:45 AM -0700 8/1/03, TOGoS wrote:
> > ...blah, blah, blah...

> >
> > What I don't like about this is
> > that it's not immediately obvious
> > from looking at the code whether
> > you're telling P3 to change its
> > value or simply replace the PMC
> > reference stored in P3 with another.
>
> This is a reasonable thing to worry
> about, because we have three separate
> semantics, set, assign, and clone.

Well, yes. I understand what set, assign,
and clone do. :-) What I was whining about
was that 'set' doesn't consistantly copy
pointers.

If you say
set PMC, PMC
it copies a pointer, but if you say
set PMC, Int
it behaves like 'assign'.

I just thought it might be better if


you had to be explicit about what you

were doing. If you want assign semantics,
you should have to say "assign". So
set PMC, Int
would be illegal, since you can't copy
an integer to a PMC pointer. You would
be forced to say what you really meant,
which is
assign PMC, Int

And likewise for strings. (At the moment,
I am forced to use 'set' for strings, because
assign S0, 23
throws a 'can't find assign_s_ic' error.)

I just thought that it might save
people from a few headaches if "set"
always meant the same thing :-)

Luke Palmer

unread,
Aug 4, 2003, 1:32:07 PM8/4/03
to chumps...@yahoo.com, d...@sidhe.org, perl6-i...@perl.org
> --- Dan Sugalski <d...@sidhe.org> wrote:
> > At 11:45 AM -0700 8/1/03, TOGoS wrote:
> > > ...blah, blah, blah...
> > >
> > > What I don't like about this is
> > > that it's not immediately obvious
> > > from looking at the code whether
> > > you're telling P3 to change its
> > > value or simply replace the PMC
> > > reference stored in P3 with another.
> >
> > This is a reasonable thing to worry
> > about, because we have three separate
> > semantics, set, assign, and clone.
>
> Well, yes. I understand what set, assign,
> and clone do. :-) What I was whining about
> was that 'set' doesn't consistantly copy
> pointers.
>
> If you say
> set PMC, PMC
> it copies a pointer, but if you say
> set PMC, Int
> it behaves like 'assign'.

Yeah, I agree with this.

> I just thought it might be better if
> you had to be explicit about what you
> were doing. If you want assign semantics,
> you should have to say "assign". So
> set PMC, Int
> would be illegal, since you can't copy
> an integer to a PMC pointer. You would
> be forced to say what you really meant,
> which is
> assign PMC, Int

And ghod forbid, for arrays:

elements PMC, int

(an elements op would be really nice, because then infinite lists
could return infinite elements:)

elements PMC, PMC

It might be confusing to have both "set elements" and "get elements"
by the same name. But those are just details.

> And likewise for strings. (At the moment,
> I am forced to use 'set' for strings, because
> assign S0, 23
> throws a 'can't find assign_s_ic' error.)

But the set_s_ic op doesn't do an assign.

S0 = "Hello"
S1 = S0
S1 = 23
print S0

Prints "Hello".

So basically, I'm for getting rid of some of the C<set> variants in
favor of more explicit ops... usually C<assign>.

> I just thought that it might save
> people from a few headaches if "set"
> always meant the same thing :-)

Luke

Togos

unread,
Aug 4, 2003, 9:09:09 PM8/4/03
to Luke Palmer, perl6-i...@perl.org
> And ghod forbid, for arrays:
>
> elements PMC, int
>
> (an elements op would be really nice, because then
> infinite lists
> could return infinite elements:)
>
> elements PMC, PMC
>
> It might be confusing to have both "set elements"
> and "get elements"
> by the same name. But those are just details.

OK. Took me a while to figure out what
you were getting at here:
Have get_num_elements and set_num_elements ops
instead of having to use get_i_p.
This 'guessing what the user meant based on the types
he passed in' business is for the birds,
though I suppose it cuts down on the size
of vtables a bit... :-/

> > And likewise for strings. (At the moment,
> > I am forced to use 'set' for strings, because
> > assign S0, 23
> > throws a 'can't find assign_s_ic' error.)
>
> But the set_s_ic op doesn't do an assign.
>
> S0 = "Hello"
> S1 = S0
> S1 = 23
> print S0
>
> Prints "Hello".

Bah. OK. Thanks for clearing that up :-)

- TOGoS

Benjamin Goldberg

unread,
Aug 7, 2003, 11:36:53 PM8/7/03
to perl6-i...@perl.org

Having read this thread, I think that the real problem is not just that
there are multiple assignment semantics -- it's that the names "set" and
"assign" are not really meaningful -- that is, they *look* to english
speakers as if they are synonyms... their names alone aren't enough info
to know what precisely they're doing.

Furthermore, the current division of assignments to those three types is
not what *I* would consider intui^H^H^H^H^H the most logical and
sensible of arrangements.

IMHO, we should rename the ops, dividing them up more clearly by
behavior.

I would suggest the opnames/categories "mutate," "alias," and "create."

The mutate ops would all re-use the string or pmc headers, changing the
contents of the first argument to match the contents of the second
argument. The (two) alias ops would simply copy pointers. The create
ops would create new strings or new pmcs. The ops which target ints and
nums would be lumped with the mutate ops, since they neither create
aliases, nor allocate new pmcs or new strings.


Yes, I realize that changing the names of so many ops will require
changing lots of code, and may temporarily introduce breakage, but I
belive that it would be good in the long term. It would make the
different assignment ops *much* easier to remember and understand, and
make it easier for someone looking at parrot code understand which
semantics a particular assignment operation is using. (Not changing the
names would have the same bad effects as breaking a chain letter >:->)


The changes in ops that I am proposing would be as follows:

Alias would be the existing "set(out STR, invar STR)" and "set(out PMC,
in PMC)."

Mutate would be all the existing "assign" opcodes, plus most of the
other "set" opcodes (except the ones which have "out STR" as their first
argument), plus the following new ops:

inline op mutate(in str, in int) {
string_set(INTERP, $1, string_from_int(INTERP, $2));
}
inline op mutate(in str, in num) {
string_set(INTERP, $1, string_from_num(INTERP, $2));
}
inline op mutate(in str, in pmc) {
string_set(INTERP, $1, VTABLE_get_string(INTERP, $2));
}

And lastly, Create would be the remaining "set" ops (which target
strings, creating new strings), and the two "clone" ops, plus the
following new ops:

inline op create(out pmc, in int) {
$1 = pmc_new(INTERP, enum_class_PerlInt);
VTABLE_set_integer_native(INTERP, $1, $2);
}
inline op create(out pmc, in num) {
$1 = pmc_new(INTERP, enum_class_PerlNumber);
VTABLE_set_number_native(INTERP, $1, $2);
}
inline op create(out pmc, in str) {
$1 = pmc_new(INTERP, enum_class_PerlString);
VTABLE_set_string_native(INTERP, $1, $2);
}

(I realize that each of these would be the same as new $Px, .SomeClass,
followed by mutate $Px, $foo... however, the combined ops here would be
easier to write and read (one line instead of two), and in non-jit
environments, faster to run, as well.)

I believe that the most in^H^H logical shorthand spellings of these
opcodes would be ":=", "=", and "<==", for alias, mutate, and create,
respectively.

--
$a=24;split//,240513;s/\B/ => /for@@=qw(ac ab bc ba cb ca
);{push(@b,$a),($a-=6)^=1 for 2..$a/6x--$|;print "$@[$a%6
]\n";((6<=($a-=6))?$a+=$_[$a%6]-$a%6:($a=pop @b))&&redo;}

Leopold Toetsch

unread,
Aug 8, 2003, 2:17:16 AM8/8/03
to Benjamin Goldberg, perl6-i...@perl.org
Benjamin Goldberg <ben.go...@hotpop.com> wrote:

> I would suggest the opnames/categories "mutate," "alias," and "create."

IMHO, we could leave PASM syntax as it is and create opcode aliases
inside the assembler ...

> I believe that the most in^H^H logical shorthand spellings of these
> opcodes would be ":=", "=", and "<==", for alias, mutate, and create,
> respectively.

But what I really want to have is these in the PIR code (except for the
"create" one, which is:

$P0 = new PerlInt

With an underlying create op, that does assign a value too, it could
then be

$P0 = new PerlInt (42)

or something.

leo

Benjamin Goldberg

unread,
Aug 8, 2003, 8:33:19 PM8/8/03
to perl6-i...@perl.org
Leopold Toetsch wrote:
>
> Benjamin Goldberg <ben.go...@hotpop.com> wrote:
>
> > I would suggest the opnames/categories "mutate," "alias," and
> > "create."
>
> IMHO, we could leave PASM syntax as it is and create opcode aliases
> inside the assembler ...

You mean leave the old ops with their names, but merely make new aliases
for them with the scheme I suggested?

I would rather rename the ops, but make their old names aliases to the
new names.

Of course, in theory, there should be no visible difference whatsoever
between these two ideas :)

(Well, maybe for decompiling.)

> > I believe that the most in^H^H logical shorthand spellings of these
> > opcodes would be ":=", "=", and "<==", for alias, mutate, and create,
> > respectively.
>
> But what I really want to have is these in the PIR code (except for the
> "create" one, which is:
>
> $P0 = new PerlInt
>
> With an underlying create op, that does assign a value too, it could
> then be
>
> $P0 = new PerlInt (42)
>
> or something.

But that would tempt people to do:

$P0 = new SomethingElse (42)

Which sadly wouldn't work, since neither the create ops, nor the "new"
op, generalize that way.

But if the syntax is:

$P0 <== 42

, we would not be impling a generality which doesn't exist. Also, it
removes redundancy, since "42" already implies PerlInt, so we don't need
to spell that name out.

Leopold Toetsch

unread,
Aug 9, 2003, 2:23:35 AM8/9/03
to Benjamin Goldberg, perl6-i...@perl.org
Benjamin Goldberg <ben.go...@hotpop.com> wrote:
> Leopold Toetsch wrote:
>>
>> Benjamin Goldberg <ben.go...@hotpop.com> wrote:
>>
>> > I would suggest the opnames/categories "mutate," "alias," and
>> > "create."
>>
>> IMHO, we could leave PASM syntax as it is and create opcode aliases
>> inside the assembler ...

> I would rather rename the ops, but make their old names aliases to the
> new names.

Yes.

> But that would tempt people to do:

> $P0 = new SomethingElse (42)

> Which sadly wouldn't work, since neither the create ops, nor the "new"
> op, generalize that way.

That's fine for Arrays (setting the initial size) and for Subs (setting
branch location). Its kind of the current init_pmc vtable.

> But if the syntax is:

> $P0 <== 42

> , we would not be impling a generality which doesn't exist. Also, it
> removes redundancy, since "42" already implies PerlInt, so we don't need
> to spell that name out.

PieThonInt, RubyInt?

leo

Benjamin Goldberg

unread,
Aug 9, 2003, 7:57:34 PM8/9/03
to perl6-i...@perl.org
Leopold Toetsch wrote:
>
> Benjamin Goldberg <ben.go...@hotpop.com> wrote:
> > Leopold Toetsch wrote:
> >>
> >> Benjamin Goldberg <ben.go...@hotpop.com> wrote:
> >>
> >> > I would suggest the opnames/categories "mutate," "alias," and
> >> > "create."
> >>
> >> IMHO, we could leave PASM syntax as it is and create opcode aliases
> >> inside the assembler ...
>
> > I would rather rename the ops, but make their old names aliases to the
> > new names.
>
> Yes.
>
> > But that would tempt people to do:
>
> > $P0 = new SomethingElse (42)
>
> > Which sadly wouldn't work, since neither the create ops, nor the "new"
> > op, generalize that way.
>
> That's fine for Arrays (setting the initial size) and for Subs (setting
> branch location).

Hmm, yes.

> Its kind of the current init_pmc vtable.

Err, not quite -- the proposed create ops first create a pmc, then call
set_integer_native; this is not in any way related to init_pmc.

Although, I suppose it could be -- if there existed an init_integer,
then it would be more logical for "$P0 = new SomethingElse (42)" to use
that, rather than create then set_integer_native.

Maybe we should have 5 init functions: init, init_pmc, init_integer,
init_double, init_string. (Hmm, what's that init_pmc_props thingy?)

> > But if the syntax is:
>
> > $P0 <== 42
>
> > , we would not be impling a generality which doesn't exist. Also, it
> > removes redundancy, since "42" already implies PerlInt, so we don't
> > need to spell that name out.
>
> PieThonInt, RubyInt?

Hmm. I that parrot should DTRT, and use CurrentLanguageInt. :)

Togos

unread,
Aug 9, 2003, 10:14:25 PM8/9/03
to perl6-i...@perl.org
> > PieThonInt, RubyInt?
>
> Hmm. I that parrot should DTRT, and use
> CurrentLanguageInt. :)

Hmm. I agree with Leo, here.

P6 = new PerlInt (3)

would be equivalent to PASM:

new P6, PerlInt
assign P6, 3

This is more generic and would be portable to
any kind of PMC you want. Arrays, Strings, etc.

Actually, if that's all it does, I wonder if it's
even worth implementing... But I suppose it makes
the code a little clearer.

---

BTW, IMCC won't let me say

new S6, 13

which is kind of annoying... I have to say

repeat S6, " ", 13

instead. I suppose that everyone already knows
about this and that it's just a temporary thing,
though :-) Unless it's going to let me say

S6 = new string, 13

or something. :-S

K Stol

unread,
Aug 11, 2003, 4:22:39 PM8/11/03
to T.O.G. of Spookware, perl6-i...@perl.org, Dan Sugalski

Ok. It *is* possible to implement all these different types of assignments
(reference copies, "real" copies).
However, what about this:

suppose there is some language Foo. This language has 2 different data
types: FooNumbers, which are always used by value, and FooObjects, which are
always used by reference. Both are PMC classes.
When a FooNumber is copied, then I'd like *not* to copy the reference, but
to copy the real value. This implies the usage of "assign"

---------------------------------------------------------------
P0 = new .FooNumber
P0 = 123
P1 = new .FooNumber
assign P1, P0
# now, when incrementing P1, P0 (the original) is not changed.
-------------------------------------------------------------------------

However, when a FooObject is copied, I'd like to copy this by reference.

-------------------------------------------------------------------
P0 = new .FooObject
P0["x"] = 999
P1 = new .FooObject
set P1, P0 #used PASM to be explicit on which op I used.
# now P1 should reference the same object.
---------------------------------------------------------------------


Ok. This works. However, it is annoying if run-time checks have to be done
on the type for deciding which
type of copy has to be applied. Like in this example:

----------------------------------------------------------------------------
------------------
#P0 references some variable, I don't know if it is a FooObject, or a
FooNumber
#P1, same as P0

typeof S0, P0
unless S0 == "FooObject", copyval #if P0 is a FooObject, do "set", otherwise
do "assign"
set P1, P0 # copy by reference
end

copyval:
assign P1, P0 # copy by value
end
----------------------------------------------------------------------------
-----------------
# If P0 is an object, I'd like P1 to get a copy of the reference to that
object. If P0 is a FooNumber, I'd like P1 to
# get a copy of that, so P1 can safely change its own copy.

This is not very nice code for a simple assignment.
However, it would be so much easier when the Foo compiler could just emit
some instruction and the destination PMC decides what to do: just copy the
reference, or do a real "assign"

On a more technical level:

clone uses the vtable of the source PMC (right?), and makes a complete copy
(as is implied by the name "clone")
assign uses the vtable of the destination PMC (so the *destination* decides
what to do).

I'd like an opcode that uses the vtable of the source PMC, like this:

let_src_pmc_decide_what_to_do P1, P0 # P1 will get its own copy of P0 if
P0 is a FooNumber, otherwise just
# a copy
of the contents of register P1.

"let_src_pmc_decide_what_to_do" is the name of this op.

(Some weeks ago, there was also a thread on this (if I remember correctly),
and the proposed opname was "copyval", I believe.)

So, would this be a good idea?

Klaas-Jan

0 new messages