Sometime between r11268 (probably) and 11276, there was a change to
the way that initialization methods get called, regardless of whether
"__init" or a 'BUILD' property is used.  If I do

        .local pmc foo, hash
        .local int foo_class
        foo_class = find_type "User::Foo"
        foo = new foo_class, hash

to construct the object, the build method gets ".param pmc hash" bound
to the hash, as happened in earlier versions, and it works.  If I
instantiate the same class without a hash via a string constant:

        .local pmc foo
        foo = new "User::Foo"

then the build method sees self in the hash parameter, and dies.  It's
not obvious to me how this is happening.  Are these somehow getting
treated differently by the new argument passing code?  TIA,

                                        -- Bob Rogers
                                           http://rgrjr.dyndns.org/

Index: t/pmc/objects.t
===================================================================
--- t/pmc/objects.t     (revision 11276)
+++ t/pmc/objects.t     (working copy)
@@ -6,7 +6,7 @@
 use warnings;
 use lib qw( . lib ../lib ../../lib );
 use Test::More;
-use Parrot::Test tests => 62;
+use Parrot::Test tests => 66;
 
 =head1 NAME
 
@@ -1916,3 +1916,191 @@
 10
 20
 OUTPUT
+
+my $foo_methods = <<'FOO_METHODS';
+.sub foo_slot1 :method
+       classoffset $I33, self, "User::Foo"
+       add $I34, $I33, 0
+       getattribute $P35, self, $I34
+       .return ($P35)
+.end
+.sub _set_foo_slot1 :method
+       .param pmc new_value
+       classoffset $I33, self, "User::Foo"
+       add $I34, $I33, 0
+       setattribute self, $I34, new_value
+       .return (new_value)
+.end
+.sub foo_slot2 :method
+       classoffset $I33, self, "User::Foo"
+       add $I34, $I33, 1
+       getattribute $P35, self, $I34
+       .return ($P35)
+.end
+.sub _set_foo_slot2 :method
+       .param pmc new_value
+       classoffset $I33, self, "User::Foo"
+       add $I34, $I33, 1
+       setattribute self, $I34, new_value
+       .return (new_value)
+.end
+FOO_METHODS
+
+my $foo_class = <<'FOO_CLASS'."\n".$foo_methods;
+## this uses a 'BUILD' property to define the initializer.
+.namespace ["User::Foo"]
+.sub Foo_onload
+       newclass $P0, "User::Foo"
+       addattribute $P0, "SLOT1"
+       addattribute $P0, "SLOT2"
+       $P1 = new "String"
+       $P1 = 'build_Foo'
+       setprop $P0, 'BUILD', $P1
+.end
+.sub build_Foo :method
+       .param pmc hash
+       $S0 = typeof hash
+       print "[hash arg isa "
+       print $S0
+       print "]\n"
+       defined $I32, hash
+       unless $I32 goto L0
+       classoffset $I33, self, "User::Foo"
+       $P34 = hash["SLOT1"]
+       setattribute self, $I33, $P34
+       inc $I33
+       $P34 = hash["SLOT2"]
+       setattribute self, $I33, $P34
+L0:
+       .return (self)
+.end
+FOO_CLASS
+
+pir_output_is(<<CODE, <<'OUTPUT', "foo BUILD without hash param.");
+$foo_class
+.sub main :main
+       .local pmc foo, s1, s2, s3
+       Foo_onload()
+       foo = new "User::Foo"
+       s1 = new String
+       s1 = "slot1 value"
+       foo."_set_foo_slot1"(s1)
+       s2 = new String
+       s2 = "slot2 value"
+       foo."_set_foo_slot1"(s2)
+       ## now print them out.
+       s3 = foo."foo_slot1"()
+       print_item s3
+       s3 = foo."foo_slot2"()
+       print_item s3
+       print "\\n"
+.end
+CODE
+[hash arg isa Null]
+slot1 value slot2 value
+OUTPUT
+
+pir_output_is(<<CODE, <<'OUTPUT', "foo BUILD with hash param.");
+$foo_class
+.sub main :main
+       .local pmc foo, hash, s1, s2, s3
+       .local int foo_class
+       Foo_onload()
+       hash = new .Hash
+       s1 = new String
+       s1 = "slot1 value"
+       hash['SLOT1'] = s1
+       s2 = new String
+       s2 = "slot2 value"
+       hash['SLOT2'] = s2
+       foo_class = find_type "User::Foo"
+       foo = new foo_class, hash
+       ## now print them out.
+       s3 = foo."foo_slot1"()
+       print_item s3
+       s3 = foo."foo_slot2"()
+       print_item s3
+       print "\\n"
+.end
+CODE
+[hash arg isa Hash]
+slot1 value slot2 value
+OUTPUT
+
+$foo_class = <<'FOO_CLASS'."\n".$foo_methods;
+## this uses an __init method instead of a 'BUILD' property.
+.namespace ["User::Foo"]
+.sub Foo_onload
+       newclass $P0, "User::Foo"
+       addattribute $P0, "SLOT1"
+       addattribute $P0, "SLOT2"
+.end
+.sub __init :method
+       .param pmc hash
+       $S0 = typeof hash
+       print "[hash arg isa "
+       print $S0
+       print "]\n"
+       defined $I32, hash
+       unless $I32 goto L0
+       classoffset $I33, self, "User::Foo"
+       $P34 = hash["SLOT1"]
+       setattribute self, $I33, $P34
+       inc $I33
+       $P34 = hash["SLOT2"]
+       setattribute self, $I33, $P34
+L0:
+       .return (self)
+.end
+FOO_CLASS
+
+pir_output_is(<<CODE, <<'OUTPUT', "foo __init without hash param.");
+$foo_class
+.sub main :main
+       .local pmc foo, s1, s2, s3
+       Foo_onload()
+       foo = new "User::Foo"
+       s1 = new String
+       s1 = "slot1 value"
+       foo."_set_foo_slot1"(s1)
+       s2 = new String
+       s2 = "slot2 value"
+       foo."_set_foo_slot1"(s2)
+       ## now print them out.
+       s3 = foo."foo_slot1"()
+       print_item s3
+       s3 = foo."foo_slot2"()
+       print_item s3
+       print "\\n"
+.end
+CODE
+[hash arg isa Null]
+slot1 value slot2 value
+OUTPUT
+
+pir_output_is(<<CODE, <<'OUTPUT', "foo __init with hash param.");
+$foo_class
+.sub main :main
+       .local pmc foo, hash, s1, s2, s3
+       .local int foo_class
+       Foo_onload()
+       hash = new .Hash
+       s1 = new String
+       s1 = "slot1 value"
+       hash['SLOT1'] = s1
+       s2 = new String
+       s2 = "slot2 value"
+       hash['SLOT2'] = s2
+       foo_class = find_type "User::Foo"
+       foo = new foo_class, hash
+       ## now print them out.
+       s3 = foo."foo_slot1"()
+       print_item s3
+       s3 = foo."foo_slot2"()
+       print_item s3
+       print "\\n"
+.end
+CODE
+[hash arg isa Hash]
+slot1 value slot2 value
+OUTPUT

Reply via email to