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

Unexpected behaviour calling method of attribute

7 views
Skip to first unread message

Klaas-Jan Stol

unread,
Jun 12, 2005, 6:43:17 AM6/12/05
to Internals List
Hi,

I have a class A, that has an object of class B as an attribute.
I've overriden the add() method of class A, and I want to let class B
handle the actual work.
The idea is to make this class B replacable by the user, so he can
override the behaviour of a certain object of A, without disturbing
other objects of A.

so, pseudocode may look like this:

class A
{
B b;

method init()
{
b = new B();
}

method __add(left, right)
{
b.__add(left, right); //***
}
}

class B
{
method __add(left, right)
{
// standard behaviour:
print("No __add() defined for objects of <left>");
}

method someCustomAddMethod(left, right)
{
print("Ok!");
}
}

function main()
{
A a1, a2, sum;
sum = a1 + a2;
}

It seems that at the line, marked with "//***", not the __add method of
b is called, but that A's __add method is called again.
However, when this call is replaced by a call to
b."someCustomAddMethod"(left, right), everything is working as expected.

I translate the above pseudo code to: (which runs ok, except for the
"//***"-marked line)


################
.sub main
# create the classes
newclass $P0, "A"
newclass $P1, "B"
addattribute $P0, "b"

# make sure there's an constructor for A creating its member variable b.
new $P10, .String
set $P10, "_new"
setprop $P0, "BUILD", $P10

# create instances of a, and add them
find_type $I0, "A"
new $P20, $I0
new $P21, $I0
new $P22, $I0
$P22 = $P20 + $P21

end
.end

.namespace ["A"]

# constructor for A
.sub _new method
find_type $I0, "B"
new $P0, $I0
setattribute self, "b", $P0
.end

.sub __add method
.param pmc self
.param pmc left
.param pmc right

# get fully qualified named attribute b
getattribute $P1, self, "A\0b"

# now, $P1 should hold the "b", right?
# checking by:
print $P1
# works, 'cause it calls the __get_string() method of B

#scenario 1: doesn't work
# call B's __add() method
#$P1."__add"(left, right) #//*** this does not work!

#scenario 2: works ok

$P1."someCustomAddMethod"(left, right)

.end

.namespace ["B"]
.sub __add method
printerr "No __add() defined for objects of <left>"
.end

.sub someCustomAddMethod method
printerr "Adding with custom method"
# ...
.end

.sub __get_string method
print "this is B"
.end
########################################

The error I get is this:

klaas@jerry:~/parrot$ parrot cltest.pir
No such attribute 'A\0b'
current instr.: 'A :: __add' pc 64 (cltest.pir:36)
called from Sub 'A :: __add' pc 95 (cltest.pir:40)
called from Sub 'main' pc 31 (cltest.pir:15)

It looks as if the .invocant is not set properly, effectively calling
the __add() method on the wrong object (self, instead of b).

Now, the trouble is, it's not doing what I'd expected. It may of course
well be that I'm not thinking right, and I wrote buggy code. OTOH, it
may be it's a bug. Just checking here.

thanks,
klaas-jan


Chip Salzenberg

unread,
Jun 12, 2005, 7:19:12 AM6/12/05
to Klaas-Jan Stol, Internals List
On Sun, Jun 12, 2005 at 12:43:17PM +0200, Klaas-Jan Stol wrote:
> It seems that at the line, marked with "//***", not the __add method of
> b is called, but that A's __add method is called again.

Well, __add is a multimethod now, not a vtable function. I'm not
surprised your code doesn't work as you expect, but I *am* surprised
that Parrot let you execute:

$P1."__add"(left, right)

and didn't die or at least warn that "This does not mean what you
think it means".

Leo?
--
Chip Salzenberg <ch...@pobox.com>

Leopold Toetsch

unread,
Jun 12, 2005, 9:42:14 AM6/12/05
to Klaas-Jan Stol, Internals List
Klaas-Jan Stol wrote:

> method __add(left, right)
> {
> b.__add(left, right); //***
> }

> .sub __add method
> .param pmc self
> .param pmc left
> .param pmc right

The function signatures of your __add methods are bogus.

Pd = Pl + Pr

is the same as:

Pd = __add(Pl, Pr)

or

Pd = Pl.__add(Pr)

The difference between function and method call is just the lookup, if
there are multisubs defined. And both of these ought to return a new PMC
of the desired type:

.sub __add method
.param right
# add self to right giving d
.return (d)
.end

or as function

.sub __add
.param left
.param right
...

leo


Chip Salzenberg

unread,
Jun 12, 2005, 9:55:17 AM6/12/05
to Leopold Toetsch, Klaas-Jan Stol, Internals List
On Sun, Jun 12, 2005 at 03:42:14PM +0200, Leopold Toetsch wrote:
> Klaas-Jan Stol wrote:
> >.sub __add method
> > .param pmc self
> > .param pmc left
> > .param pmc right
>
> The function signatures of your __add methods are bogus.

Since __add has defined semantics per Parrot, I think it's important
for Parrot to generate errors (or at least warnings!) when somebody
makes this kind of quite understandable mistake.
--
Chip Salzenberg <ch...@pobox.com>

0 new messages