2 # Copyright (C) 2001-2010, Parrot Foundation.
7 t/oo/objects.t - Objects
11 % prove t/oo/objects.t
15 Tests the object/class subsystem.
20 .include 'test_more.pir'
21 .include "iglobals.pasm"
22 .include "interpinfo.pasm"
26 get_classname_from_class()
32 new_object__isa_test()
33 new_object__classname()
35 isa_subclass__objects()
38 addattribute_subclass()
39 addattribute_subclass__same_name()
40 set_and_get_object_attribs()
41 set_and_get_multiple_object_attribs()
42 attribute_values_are_specific_to_objects()
43 attribute_values_and_subclassing()
44 attribute_values_and_subclassing_2()
45 PMC_as_classes__overridden_mmd_methods()
48 multiple_inheritance__with_attributes()
49 attributes_two_levels_of_inheritance()
51 anon_subclass_has_no_name()
53 get_attrib_by_name_subclass()
54 set_attrib_by_name_subclass()
56 PMC_as_classes__subclass()
57 PMC_as_classes__instantiate()
58 PMC_as_classes__methods()
59 PMC_as_classes__mmd_methods()
60 PMC_as_classes__derived_1()
61 PMC_as_classes__derived_2()
62 PMC_as_classes__derived_3()
65 multiple_anon_classes()
66 subclassed_Integer_bug()
67 equality_of_subclassed_Integer()
68 short_name_attributes()
69 init_with_and_without_arg()
70 newclass_bracket_parsing()
71 verify_namespace_types()
77 test_class_name_multipart_name()
78 test_get_class_multipart_name()
81 vtable_override_once_removed()
82 vtable_fails_for_subclasses_of_core_classes()
83 super___init_called_twice()
84 using_class_object_from_typeof_op_with_new()
85 setting_non_existent_attribute()
86 setting_non_existent_attribute_by_name()
87 getting_null_attribute()
88 getting_non_existent_attribute()
89 addparent_exceptions_1()
90 addparent_exceptions_2()
91 subclassing_a_non_existent_class()
92 anon_subclass_of_non_existent_class()
93 addattribute_duplicate()
94 wrong_way_to_create_new_objects()
95 attribute_values__subclassing_access_meths()
96 attribute_values__inherited_access_meths()
101 .sub get_classname_from_class
104 is( $S0, "Foo5", "got classname Foo5" )
106 subclass $P2, $P1, "Bar5"
108 is( $S1, "Bar5", "got subclass Bar5" )
110 subclass $P3, "Foo5", "Baz5"
112 is( $S2, "Baz5", "got subclass Baz5" )
117 get_class $P2, "Foo6"
119 is( $S2, "Foo6", 'get_class for Foo6' )
121 subclass $P3, $P1, "FooBar6"
122 get_class $P4, "FooBar6"
124 is( $S4, 'FooBar6', 'get_class for FooBar6' )
126 get_class $P3, "NoSuch6"
128 ok( $I0, "no class for 'NoSuch6'" )
134 isa $I0, $P1, "Boolean"
135 is( $I0, 1, 'Boolean isa Boolean' )
138 is( $I0, 0, 'Boolean !isa Bool' )
140 isa $I0, $P1, "scalar"
141 is( $I0, 1, 'Boolean isa scalar' )
143 isa $I0, $P1, "calar"
144 is( $I0, 0, 'Boolean !isa calar' )
147 is( $I0, 0, 'Boolean !isa " "' )
150 is( $I0, 0, 'Boolean !isa ""' )
154 is( $I0, 0, 'Boolean !isa null $S0' )
158 is( $I0, 1, 'Boolean isa scalar $S0' )
164 does $I0, $P1, "Boolean"
165 is( $I0, 0, 'Boolean !does Boolean' )
167 does $I0, $P1, "Bool"
168 is( $I0, 0, 'Boolean !does Bool' )
170 does $I0, $P1, "scalar"
171 is( $I0, 1, 'Boolean does scalar' )
175 new $P1, ['OrderedHash']
177 does $I0, $P1, "Boolean"
178 is( $I0, 0, 'OrderedHash !does Boolean' )
180 does $I0, $P1, "Bool"
181 is( $I0, 0, 'OrderedHash !does Bool' )
183 does $I0, $P1, "hash"
184 is( $I0, 1, 'OrderedHash does hash' )
186 does $I0, $P1, "array"
187 is( $I0, 1, 'OrderedHash does array' )
193 ok( 1, 'created new object from Foo7 class' )
196 .sub new_object__isa_test
199 ok( 1, 'created new object from Foo8 class' )
202 ok( $I0, 'new object isa Foo8' )
205 .sub new_object__classname
209 is( $S0, "Foo9", 'new object from Foo9 class as a string is Foo9' )
211 typeof $S0, $P2 # object
212 is( $S0, 'Foo9', 'typeof obj is Foo9' )
216 is( $S0, 'Foo9', 'class of obj is Foo9' )
218 typeof $S0, $P2 # object
219 is( $S0, 'Foo9', 'typeof obj is Foo9' )
224 newclass $P1, "Foo10"
225 subclass $P2, $P1, "Bar10"
227 isa_ok( $P2, "Foo10", 'newclass isa Foo10' )
228 isa_ok( $P2, "Bar10", 'new subclass isa Bar10' )
229 isa_ok( $P2, "Foo10", 'new subclass isa parent' )
230 isa_ok( $P2, "Class", 'new subclass isa Class' )
232 isa $I0, $P2, "Object"
233 is( $I0, 0, 'new subclass !isa Object' )
236 .sub isa_subclass__objects
237 newclass $P3, "Foo30"
238 subclass $P4, $P3, "Bar30"
242 isa_ok( $P1, "Foo30", 'obj isa its class' )
243 isa_ok( $P2, "Bar30", 'obj isa its class' )
244 isa_ok( $P2, "Foo30", 'obj isa its parent class' )
245 isa_ok( $P2, "Object", 'obj isa Object' )
246 isa_ok( $P2, "Class", 'obj isa Class' )
250 newclass $P0, 'Foo31'
251 $P2 = get_hll_global 'sayFoo31'
253 # add a method BEFORE creating a Foo object
254 addmethod $P0, 'foo31', $P2
258 # get a method from some other namespace
259 $P2 = get_hll_global ['Bar31'], 'sayBar31'
261 # add a method AFTER creating the object
262 addmethod $P0, 'bar31', $P2
267 ok( 1, 'called method added before creating obj' )
272 ok( 1, 'called method added after created obj' )
275 .namespace [] # Reset to root namespace for next test
277 .sub test_addattribute
278 newclass $P1, "Foo11"
280 addattribute $P1, "foo_i"
281 ok( 1, 'addattribute did not blow up' )
284 is( $S0, "Foo11", '$P1 is still the same class as PMC' )
286 # Check that we can add multiple attributes
290 addattribute $P1, $S0
293 ok( 1, 'addattribute 1000x without blow up' )
296 .sub addattribute_subclass
297 newclass $P1, "Foo12"
298 addattribute $P1, "foo_i"
299 ok( 1, 'addattribute to Foo12' )
301 subclass $P2, $P1, "Bar12"
302 addattribute $P2, "bar_i"
303 ok( 1, 'addattribute to subclass of Foo12' )
306 .sub addattribute_subclass__same_name
307 newclass $P1, "Foo32"
308 addattribute $P1, "i"
309 addattribute $P1, "j"
311 subclass $P2, $P1, "Bar32"
312 addattribute $P2, "j"
313 addattribute $P2, "k"
315 ok( 1, 'created class and subclass and added attributes' )
319 $P0 = getattribute o, 'i'
320 is( $P0, 'Foo32.i', 'parent attrib initialized in init' )
321 $P0 = getattribute o, ['Foo32'], 'j'
322 is( $P0, 'Foo32.j', 'parent attrib initialized in init' )
323 $P0 = getattribute o, ['Bar32'], 'j'
324 is( $P0, 'Bar32.j', 'subclass attrib initialized in init' )
325 $P0 = getattribute o, 'k'
326 is( $P0, 'Bar32.k', 'subclass attrib initialized in init' )
328 $P0 = getattribute o, 'i'
329 is( $P0, 'Foo32.i', 'parent attrib init-ed' )
330 $P0 = getattribute o, ['Foo32'], "j"
331 is( $P0, 'Foo32.j', 'parent attrib init-ed' )
332 $P0 = getattribute o, 'j'
333 is( $P0, 'Bar32.j', 'subclass attrib returned over parent' )
334 $P0 = getattribute o, 'k'
335 is( $P0, 'Bar32.k', 'subclass attrib init-ed' )
340 .sub init :vtable :method
343 setattribute self, ['Foo32'], "i", $P0
346 setattribute self, ["Foo32"], "j", $P0
349 setattribute self, ["Bar32"], "j", $P0
352 setattribute self, ["Bar32"], "k", $P0
355 .namespace [] # Reset to root namespace for next test
357 .sub set_and_get_object_attribs
358 newclass $P1, "Foo13"
359 addattribute $P1, "i"
364 setattribute $P2, "i", $P3
367 getattribute $P4, $P2, "i"
369 is( $P4, 1024, 'set/get Integer attribute' )
372 .sub set_and_get_multiple_object_attribs
373 newclass $P1, "Foo14"
374 addattribute $P1, "i"
375 addattribute $P1, "j"
381 set $P4["Key"], "Value"
383 setattribute $P2, "i", $P3
384 setattribute $P2, "j", $P4
386 getattribute $P5, $P2, "i"
387 is( $P5, '4201', 'set/get Integer attribute' )
389 getattribute $P6, $P2, "j"
391 is( $S0, 'Value', 'set/get Hash attribute on same obj' )
394 .sub attribute_values_are_specific_to_objects
395 newclass $P1, "Foo15"
396 addattribute $P1, "i"
402 setattribute $P2, "i", $P4
404 set $P5, "One hundred"
405 setattribute $P3, "i", $P5
407 getattribute $P6, $P2, "i"
408 is( $P6, 100, 'attribute value on 1st object is specific to obj' )
410 getattribute $P6, $P3, "i"
411 is( $P6, 'One hundred', 'attribute value on 2nd obj is specific to obj' )
414 .sub attribute_values_and_subclassing
415 newclass $P1, "Foo16"
416 addattribute $P1, "i"
417 addattribute $P1, "j"
418 subclass $P2, $P1, "Bar16"
419 addattribute $P2, "k"
420 addattribute $P2, "l"
425 # Note that setattribute holds the actual PMC, not a copy, so
426 # in this test both attributes get the PMC from $P4, and should
427 # both have the same value, despite the C<inc>.
430 setattribute $P2, "i", $P4
432 setattribute $P2, "j", $P4
436 setattribute $P3, "i", $P5
438 setattribute $P3, "j", $P5
440 getattribute $P6, $P2, "i"
441 is( $P6, 11, 'setattrib with a PMC holds actual PMC not copy' )
443 getattribute $P6, $P2, "j"
444 is( $P6, 11, '...so changes to the PMC appear through the attrib' )
446 getattribute $P6, $P3, "i"
447 is( $P6, 101, '...and second test on new objects' )
449 getattribute $P6, $P3, "j"
450 is( $P6, 101, '...should have same result' )
453 .sub attribute_values_and_subclassing_2
454 newclass $P1, "Foo17"
455 # must add attributes before object instantiation
456 addattribute $P1, ".i"
457 addattribute $P1, ".j"
459 subclass $P2, $P1, "Bar17"
460 addattribute $P2, ".k"
461 addattribute $P2, ".l"
463 # subclass is preferred for the SI case over
464 # newclass $P2, "Bar"
467 # which is suitable for adding multiple parents to one class
469 # instantiate a Bar object
472 # Set the attribute values
473 new $P10, ['String'] # set attribute values
474 set $P10, "i" # attribute slots have reference semantics
475 setattribute $P3, ".i", $P10 # so always put new PMCs in
476 # if you have unique values
479 setattribute $P3, ".j", $P10
483 setattribute $P3, ".k", $P10
487 setattribute $P3, ".l", $P10
490 getattribute $P11, $P3, ".i"
491 is( $P11, "i", 'string attribute get/set on parent' )
493 getattribute $P11, $P3, ".j"
494 is( $P11, "j", 'string attribute get/set on parent' )
496 getattribute $P11, $P3, ".k"
497 is( $P11, "k", 'string attribute get/set on subclass' )
499 getattribute $P11, $P3, ".l"
500 is( $P11, "l", 'string attribute get/set on subclass' )
503 .sub PMC_as_classes__overridden_mmd_methods
504 .local pmc myint, i, j, k
506 get_class $P0, "Integer"
507 subclass myint, $P0, "MyInt1"
516 is( k, 13, 'added two MyInt1' )
522 is( k, 106, 'added MyInt1 and an Integer' )
525 .namespace ["MyInt1"]
527 .sub add :multi(MyInt1, MyInt1, MyInt1)
531 ok( 1, 'in the add method' )
532 $P0 = getattribute self, ['Integer'], "proxy"
540 .namespace [] # Reset to root namespace for next test
543 newclass $P0, "Foo21"
545 is( $S0, "Class", 'typeof for a Class PMC is "Class"' )
558 is( $S0, 'A', 'typeof object of class A is "A"' )
559 is( $S1, 'B', 'typeof object of class B is "B"' )
562 .sub multiple_inheritance__with_attributes
564 addattribute $P1, "Spectral Type"
566 newclass $P2, "Company"
567 addattribute $P2, "Annual Profit"
569 subclass $P3, $P1, "Sun"
576 setattribute $P4, "Spectral Type", $P5
579 set $P6, "$100,000,000"
580 setattribute $P4, "Annual Profit", $P6
582 getattribute $P7, $P4, "Spectral Type"
583 is( $P7, 'G', 'direct parents attribute' )
585 getattribute $P8, $P4, "Annual Profit"
586 is( $P8, '$100,000,000', "addparent's attribute" )
589 .sub attributes_two_levels_of_inheritance
590 newclass $P0, "Astronomical Object"
591 addattribute $P0, "Location"
593 subclass $P1, $P0, "Star2"
594 addattribute $P1, "Spectral Type"
604 setattribute $P4, "Location", $P5
605 getattribute $P6, $P4, "Location"
606 is( $P6, 'Taurus', 'attributes with two levels of inheritance' )
610 newclass $P0, "City1"
615 is( $S0, 'City1', 'class op works' )
618 .sub anon_subclass_has_no_name
619 newclass $P0, "City2"
622 is( $S0, '', 'anonymous subclass has no name' )
625 .sub get_attrib_by_name
626 newclass $P1, "Foo18"
627 addattribute $P1, "i"
631 setattribute $P2, "i", $P3
633 getattribute $P4, $P2, ["Foo18"], "i"
634 is( $P4, 'ok', 'get attrib by name' )
637 .sub get_attrib_by_name_subclass
638 newclass $P0, "Bar19"
639 addattribute $P0, "j"
641 subclass $P1, $P0, "Foo19"
642 addattribute $P1, "i"
648 setattribute $P2, "i", $P3
652 setattribute $P2, "j", $P3
654 getattribute $P4, $P2, ["Foo19"], "i"
655 is( $P4, 'foo i', 'attribute from subclass get by name' )
657 getattribute $P4, $P2, ["Bar19"], "j"
658 is( $P4, 'bar j', 'attribute from parent class get by name' )
661 .sub set_attrib_by_name_subclass
662 newclass $P0, "Bar20"
663 addattribute $P0, "j"
665 subclass $P1, $P0, "Foo20"
666 addattribute $P1, "i"
672 setattribute $P2, ["Foo20"], "i", $P3
676 setattribute $P2, ["Bar20"], "j", $P3
678 getattribute $P4, $P2, "i"
679 is( $P4, 'foo i', 'attribute from subclass set by name' )
681 getattribute $P4, $P2, "j"
682 is( $P4, 'bar j', 'attribute from parent class set by name' )
686 get_class $P0, "Integer"
687 ok( 1, "get_class of Integer did't croak" )
689 get_class $P0, "Integer"
690 ok( 1, "get_class of Integer did't croak second time" )
693 is( $S0, 'PMCProxy', 'typeof PMCProxy' )
696 .sub PMC_as_classes__subclass
698 get_class $P0, "Integer"
699 ok( 1, "get_class on Integer didn't blow up" )
701 subclass MyInt3, $P0, "MyInt3"
702 ok( 1, "subclassing didn't blow up" )
705 is( $S0, 'Class', 'new subclass is typeof Class' )
707 $I0 = isa MyInt3, "MyInt3"
708 ok( $I0, 'new subclass isa MyInt' )
710 $I0 = isa MyInt3, "Integer"
711 ok( $I0, 'new subclass isa parent class' )
714 .sub PMC_as_classes__instantiate
716 get_class $P0, "Integer"
717 ok( 1, 'able to get_class of Integer' )
719 subclass MyInt4, $P0, "MyInt4"
720 addattribute MyInt4, ".i"
721 ok( 1, 'able to addattribute to subclass' )
725 ok( 1, 'able to instantiate obj of subclass w/ attribute' )
728 .sub PMC_as_classes__methods
730 get_class $P0, "Integer"
732 subclass MyInt5, $P0, "MyInt5"
733 addattribute MyInt5, "intval"
740 i = 42 # set_integer is inherited from Integer
741 ok( 1, 'able to assign int to MyInt' )
743 $I0 = i # get_integer is overridden below
744 is( $I0, 42, 'get_integer is overridden for MyInt5' )
746 $S0 = i # get_string is overridden below
747 is( $S0, 'MyInt5(42)', 'get_string is overridden for MyInt5' )
750 .namespace ["MyInt5"]
752 .sub set_integer_native :vtable :method
754 $P1 = new ['Integer']
756 setattribute self, "intval", $P1
759 .sub get_integer :vtable :method
760 $P0 = getattribute self, "intval"
765 .sub get_string :vtable :method
766 $P0 = getattribute self, "intval"
775 .namespace [] # Reset to root namespace for next test
777 .sub PMC_as_classes__mmd_methods
779 get_class $P0, "Integer"
780 subclass MyInt6, $P0, "MyInt6"
791 is( $I0, 42, 'MyInt6 defaults to Integer class for mult' )
793 $S0 = k # get_string is overridden below
794 is( $S0, 'MyInt6(42)', 'get_string is overridden for MyInt6' )
797 .namespace ["MyInt6"]
799 .sub get_string :vtable :method
800 $I0 = self # get_integer is not overridden
808 .namespace [] # Reset to root namespace for next test
810 .sub PMC_as_classes__derived_1
813 get_class $P0, "Integer"
815 subclass MyInt8, $P0, "MyInt8"
816 addattribute MyInt8, 'intval'
817 get_class $P1, "MyInt8"
818 subclass MyInt8_2, $P1, "MyInt8_2"
822 $I0 = isa i, "Integer"
823 ok( $I0, 'obj isa grandparent (Integer)' )
825 $I0 = isa i, "MyInt8"
826 ok( $I0, 'obj isa parent (MyInt8)' )
828 $I0 = isa i, "MyInt8_2"
829 ok( $I0, 'obj isa its class (MyInt8_2)' )
831 i = 42 # set_integer is overridden below
832 $I0 = i # get_integer is overridden below
833 is( $I0, 42, 'set/get_integer overridden' )
835 $S0 = i # get_string is overridden below
836 is( $S0, 'MyInt8_2(42)', 'set/get_string overridden' )
839 .namespace ["MyInt8"]
840 .sub 'set_integer_native' :vtable :method
842 $P1 = new ['Integer']
844 setattribute self, "intval", $P1
847 .sub get_integer :vtable :method
848 $P0 = getattribute self, 'intval'
852 .sub get_string :vtable :method
853 $P0 = getattribute self, 'intval'
863 .namespace [] # Reset to root namespace for next test
865 .sub PMC_as_classes__derived_2
868 get_class $P0, "Integer"
870 subclass MyInt9, $P0, "MyInt9"
871 addattribute MyInt9, 'intval'
872 get_class $P1, "MyInt9"
873 subclass MyInt9_2, $P1, "MyInt9_2"
877 $I0 = isa i, "Integer"
878 ok( $I0, 'obj isa grandparent (Integer)' )
879 $I0 = isa i, "MyInt9"
880 ok( $I0, 'obj isa parent (MyInt9)' )
881 $I0 = isa i, "MyInt9_2"
882 ok( $I0, 'obj isa its class (MyInt9_2)' )
884 i = 42 # set_integer is overridden below
885 $I0 = i # get_integer is overridden below
886 is( $I0, 43, 'set/get_integer overridden' )
888 $S0 = i # get_string is overridden below
889 is( $S0, 'MyInt9_2(42)', 'set/get_string overridden' )
892 .namespace ["MyInt9_2"]
893 # subclassing methods from MyInt9 is ok
894 # this one changes the value a bit
895 .sub get_integer :vtable :method
896 $P0 = getattribute self, 'intval'
901 .namespace ["MyInt9"]
902 .sub 'set_integer_native' :vtable :method
904 $P1 = new ['Integer']
906 setattribute self, "intval", $P1
909 .sub get_integer :vtable :method
910 $P0 = getattribute self, 'intval'
914 .sub get_string :vtable :method
915 $P0 = getattribute self, 'intval'
925 .namespace [] # Reset to root namespace for next test
927 .sub PMC_as_classes__derived_3
930 get_class $P0, "Integer"
932 subclass MyInt10, $P0, "MyInt10"
933 addattribute MyInt10, 'intval'
934 get_class $P1, "MyInt10"
935 subclass MyInt10_2, $P1, "MyInt10_2"
939 $I0 = isa i, "Integer"
940 ok( $I0, 'obj isa grandparent (Integer)' )
941 $I0 = isa i, "MyInt10"
942 ok( $I0, 'obj isa parent (MyInt10)' )
943 $I0 = isa i, "MyInt10_2"
944 ok( $I0, 'obj isa its class (MyInt102)' )
946 i = 42 # set_integer is overridden below
947 $I0 = i # get_integer is overridden below
948 is( $I0, 42, 'set/get_integer overridden' )
950 $S0 = i # get_string is overridden below
951 is( $S0, 'MyInt10_2(42)', 'set/get_string overridden' )
954 .namespace ["MyInt10_2"]
955 .sub get_integer :vtable :method
956 $P0 = getattribute self, 'intval'
960 .sub get_string :vtable :method
961 $P0 = getattribute self, 'intval'
970 .namespace ['MyInt10']
971 .sub 'set_integer_native' :vtable :method
973 $P1 = new ['Integer']
975 setattribute self, "intval", $P1
979 .namespace [] # Reset to root namespace for next test
981 .sub subclassing_Class
984 parent = get_class "Class"
985 cl = subclass parent, "Foo33"
986 ok( 1, 'able to subclass Class' )
990 ok( 1, 'able to instantiate subclass of Class' )
993 is( $S0, 'Foo33', 'object returns correct class' )
996 .sub namespace_vs_name
1000 is( o, 'Foo34::get_string', 'found Foo34 namespace' )
1003 is( o, 'Foo34', 'found global Foo34' )
1005 f = get_global "Foo34"
1007 is( o, 'Foo34', 'found global Foo34 explicitly' )
1009 f = get_global ["Foo34"], "Foo34"
1011 is( o, 'Foo34::Foo34', 'found method in Foo34 namespace' )
1018 .namespace [ "Foo34" ]
1020 .sub get_string :vtable :method
1021 .return("Foo34::get_string")
1025 .return("Foo34::Foo34")
1028 .namespace [] # Reset to root namespace for next test
1030 .sub multiple_anon_classes
1031 newclass $P0, "City3"
1033 newclass $P2, "State3"
1035 ok( 1, "multiple anon classes didn't croak (bug #33103)" )
1038 .sub subclassed_Integer_bug
1043 subclass class, "Integer", "LispInteger1"
1045 a = new "LispInteger1"
1046 b = new "LispInteger1"
1052 is( $S0, '1', 'subclassed Integer is 1' )
1054 is( $S0, '1', 'subclassed Integer is 1' )
1058 is( $S0, '1', 'multip and reasign to subclassed Integer is 1' )
1061 .sub equality_of_subclassed_Integer
1063 class = subclass "Integer", "LispInteger2"
1066 a = new 'LispInteger2'
1070 b = new 'LispInteger2'
1074 ok( $I0, '123 is equal to 123' )
1078 .sub short_name_attributes
1079 newclass $P1, "Foo22"
1080 addattribute $P1, "i"
1081 addattribute $P1, "j"
1083 subclass $P2, $P1, "Bar22"
1084 addattribute $P2, "k"
1085 addattribute $P2, "l"
1089 # set a bunch of attribs
1090 new $P4, ['Integer']
1092 setattribute $P2, "i", $P4
1094 new $P4, ['Integer']
1096 setattribute $P2, "j", $P4
1098 new $P4, ['Integer']
1100 setattribute $P2, "k", $P4
1102 new $P4, ['Integer']
1104 setattribute $P2, "l", $P4
1106 getattribute $P6, $P2, "i"
1107 is( $P6, 10, '"i" getattribute on parent class attrib' )
1108 getattribute $P6, $P2, "j"
1109 is( $P6, 11, '"j" getattribute on parent class attrib' )
1111 getattribute $P6, $P2, "k"
1112 is( $P6, 20, '"k" getattribute on subclass attrib' )
1113 getattribute $P6, $P2, "l"
1114 is( $P6, 21, '"l" getattribute on subclass attrib' )
1116 getattribute $P6, $P2, ["Foo22"], "i"
1117 is( $P6, 10, '["Foo22"], "i" getattribute on parent class attrib' )
1118 getattribute $P6, $P2, ["Bar22"], "k"
1119 is( $P6, 20, '["Bar22"], "k" getattribute on subclass attrib' )
1122 .sub init_with_and_without_arg
1123 .local pmc cl, o, h, a
1124 cl = newclass "Foo35"
1125 addattribute cl, "a"
1127 a = getattribute o, "a"
1128 is( a, 'ok 1', 'init without an arg' )
1131 $P0 = new ['String']
1135 a = getattribute o, "a"
1136 is( a, 'ok 2', 'init with an arg' )
1139 .namespace ["Foo35"]
1140 .sub init_pmc :vtable :method
1143 setattribute self, 'a', $P0
1146 .sub init :vtable :method
1147 $P0 = new ['String']
1149 setattribute self, 'a', $P0
1152 .namespace [] # Reset to root namespace for next test
1154 .sub newclass_bracket_parsing
1155 newclass $P0, ['Foo23';'Bar23']
1156 ok( 1, 'newclass created with brackets' )
1159 .sub verify_namespace_types
1160 newclass $P0, ['Foo24';'Bar24']
1162 set $P1, $P0[.IGLOBALS_CLASSNAME_HASH]
1164 is( $S0, 'NameSpace', 'namespace verified' )
1166 set $P2, $P1['Foo24']
1168 is( $S0, 'NameSpace', 'namespace verified' )
1171 .sub verify_data_type
1172 newclass $P0, ['Foo25';'Bar25']
1174 set $P1, $P0[.IGLOBALS_CLASSNAME_HASH]
1175 set $P2, $P1['Foo25']
1176 set $P3, $P2['Bar25']
1180 ok( $I0, 'verified datatype > 0' )
1183 # Puts init in a namespace
1186 cl = newclass ['Foo36';'Bar36']
1187 addattribute cl, "init_check"
1189 ok( 1, 'obj successfully created' )
1191 p = getattribute o, "init_check"
1192 is( p, 999, "overridden init called")
1195 .namespace ['Foo36';'Bar36']
1197 .sub init :vtable :method
1201 setattribute self, "init_check", p
1204 .namespace [] # revert to root for next test
1207 .local pmc c1, c2, o1, o2
1208 c1 = newclass ['Foo37';'Bar37']
1209 c2 = newclass ['Foo37';'Fuz37']
1212 ok( 1, 'objects created successfully' )
1215 .namespace ['Foo37';'Bar37']
1217 .sub init :vtable :method
1218 ok( 1, '__init Bar37' )
1221 .namespace ['Foo37';'Fuz37']
1223 .sub init :vtable :method
1224 ok( 1, '__init Fuz37' )
1227 .namespace [] # revert to root for next test
1230 .local pmc c1, c2, c3, o1, o2, o3
1231 c1 = newclass ['Foo38';'Bar38']
1232 c2 = newclass ['Foo38';'Buz38']
1233 c3 = newclass 'Foo38'
1234 o1 = new ['Foo38';'Bar38']
1235 o2 = new ['Foo38';'Buz38']
1237 ok( 1, 'objects created successfully' )
1240 .namespace ['Foo38';'Bar38']
1242 .sub init :vtable :method
1243 ok( 1, '__init Bar38' )
1246 .namespace ['Foo38';'Buz38']
1248 .sub init :vtable :method
1249 ok( 1, '__init Buz38' )
1252 .namespace ['Foo38']
1254 .sub init :vtable :method
1255 ok( 1, '__init Foo38' )
1258 .namespace [] # revert to root for next test
1261 .local pmc base, o1, o2
1262 base = subclass 'Hash', ['Perl6-3'; 'PAST'; 'Node']
1263 addattribute base, '$.source' # original source
1264 addattribute base, '$.pos' # offset position
1266 $P0 = subclass base, ['Perl6-3'; 'PAST'; 'Sub']
1267 $P0 = subclass base, ['Perl6-3'; 'PAST'; 'Stmt']
1270 o1 = new ['Perl6-3'; 'PAST'; 'Sub']
1271 o2 = new ['Perl6-3'; 'PAST'; 'Stmt']
1272 ok( 1, 'objects created successfully' )
1275 .namespace ['Perl6-3'; 'PAST'; 'Stmt']
1277 .sub init :vtable :method
1278 ok( 1, '__init Stmt' )
1281 .namespace ['Perl6-3'; 'PAST'; 'Sub']
1283 .sub init :vtable :method
1284 ok( 1, '__init Sub' )
1287 .namespace [] # revert to root for next test
1289 .sub test_class_name_multipart_name
1291 base = subclass 'Hash', ['Perl6'; 'PAST'; 'Node']
1294 is( $S0, "Perl6;PAST;Node", "typeof returns object's class name" )
1297 .sub test_get_class_multipart_name
1299 base = subclass 'Hash', ['Perl6a'; 'PAST'; 'Node']
1300 $P0 = get_class ['Perl6a'; 'PAST'; 'Node']
1303 is( $S0, 'Perl6a;PAST;Node', 'typeof returns objects created from get_class' )
1307 .local pmc base, o1, o2
1308 base = subclass 'Hash', ['Perl6b'; 'PAST'; 'Node']
1309 $P0 = new [ 'Perl6b'; 'PAST'; 'Node' ]
1311 $I0 = isa $P0, [ 'Perl6b'; 'PAST'; 'Node']
1312 is( $I0, 1, 'obj isa the full class name' )
1314 $I0 = isa $P0, 'Hash'
1315 is( $I0, 1, 'obj isa the parent class' )
1317 $I0 = isa $P0, 'Perl6b'
1318 is( $I0, 0, 'obj !isa the first part of the class name' )
1321 .sub new_nested_ordering
1322 .local pmc c1, c2, o
1323 c1 = newclass ['Foo39']
1324 c2 = newclass ['Foo39';'Bar39']
1326 ok( 1, 'objects created successfully' )
1329 .namespace ['Foo39']
1331 .sub init :vtable :method
1332 ok( 0, '__init Foo39' ) # shouldn't be called
1335 .namespace ['Foo39';'Bar39']
1337 .sub init :vtable :method
1338 ok( 1, '__init Bar39' ) # should be called
1341 .namespace [] # revert to root for next test
1343 .sub vtable_override_once_removed
1345 $P0 = get_class 'Integer'
1346 base = subclass $P0, 'Foo40' # create subclass 'Foo40'
1347 addattribute base, '@!capt'
1349 $P0 = subclass 'Foo40', 'Bar40' # create subclass 'Bar40'
1350 $P1 = new 'Bar40' # create an instance of 'Bar40'
1352 $S1 = $P1 # get its string representation
1353 is( $S1, 'ok bar', 'get_string overridden' )
1356 .namespace [ 'Bar40' ]
1358 .sub 'get_string' :vtable :method
1363 .namespace [] # revert to root for next test
1365 .sub vtable_fails_for_subclasses_of_core_classes
1366 $P0 = subclass 'Hash', 'Foo41'
1367 $P0 = subclass 'Hash', 'Bar41'
1371 is( $S1, 'Hello world', 'get_string :vtable :method' )
1375 is( $S1, 'Hello world', 'get_string :method :vtable' )
1378 .namespace [ 'Foo41' ]
1380 .sub 'get_string' :vtable :method
1381 .return('Hello world')
1384 .namespace [ 'Bar41' ]
1386 .sub 'get_string' :method :vtable
1387 .return('Hello world')
1390 .namespace [] # revert to root for next test
1392 .sub super___init_called_twice
1393 $P0 = newclass 'Foo42'
1394 $P1 = subclass $P0, 'Bar42'
1395 addattribute $P1, 'i'
1400 .namespace [ 'Foo42' ]
1402 .sub 'init' :vtable :method
1403 $P0 = getattribute self, 'i'
1405 ok( $I1, 'should be null' )
1407 $P1 = new ['Integer']
1408 setattribute self, "i", $P1 # i won't be null if init called again
1412 .namespace [] # revert to root for next test
1414 .sub using_class_object_from_typeof_op_with_new
1415 $P0 = newclass [ "Monkey" ; "Banana" ]
1418 is( $S0, "Ook!", 'obj created from .new() class method' )
1423 is( $S0, "Ook!", 'obj created from "new" called on result of typeof' )
1426 .namespace [ "Monkey" ; "Banana" ]
1432 .namespace [] # revert to root for next test
1434 .macro exception_is ( M )
1435 .local pmc exception
1436 .local string message
1437 .get_results (exception)
1439 message = exception['message']
1440 is( message, .M, .M )
1443 .sub setting_non_existent_attribute
1444 newclass $P1, "Foo45"
1447 new $P3, ['Integer']
1449 setattribute $P2, "bar", $P3
1451 ok(0, "'No such attribute' exception not thrown")
1454 .exception_is( "No such attribute 'bar'" )
1458 .sub setting_non_existent_attribute_by_name
1459 newclass $P1, "Foo47"
1462 new $P3, ['Integer']
1464 setattribute $P2, ["Foo47"], "no_such", $P3
1466 ok(0, "'No such attribute' exception not thrown")
1469 .exception_is( "No such attribute 'no_such' in class 'Foo47'" )
1473 .sub getting_null_attribute
1474 newclass $P1, "Foo51"
1475 addattribute $P1, "i"
1478 getattribute $P3, $P2, "i"
1480 is($I0, 1, "null attribute is null")
1483 .sub getting_non_existent_attribute
1484 newclass $P1, "Foo52"
1488 getattribute $P3, $P2, "bar"
1490 ok(0, "'No such attribute' exception not thrown")
1493 .exception_is( "No such attribute 'bar'" )
1497 .sub addparent_exceptions_1
1498 newclass $P0, "Astronomical Object 2"
1500 set $P1, "Not a class"
1504 ok(0, "'Parent isn\'t a Class' exception not thrown")
1507 .exception_is( "Parent isn't a Class." )
1511 .sub addparent_exceptions_2
1513 newclass $P1, "Trashcan"
1517 ok(0, "'Only classes can be subclassed' exception not thrown")
1520 .exception_is( "Only classes can be subclassed" )
1524 .sub subclassing_a_non_existent_class
1526 subclass $P1, "Character", "Nemo"
1528 ok(0, "nonexistent class exception not thrown")
1531 .exception_is( "Class 'Character' doesn't exist" )
1535 .sub anon_subclass_of_non_existent_class
1537 subclass $P1, "Character"
1539 ok(0, "nonexistent class exception not thrown")
1542 .exception_is( "Class 'Character' doesn't exist" )
1546 .sub addattribute_duplicate
1547 newclass $P1, "Foo53"
1548 addattribute $P1, "i"
1549 addattribute $P1, "j"
1551 addattribute $P1, "i"
1553 ok(0, "attribute already exists exception not thrown")
1556 .exception_is( "Attribute 'i' already exists in 'Foo53'." )
1560 .sub wrong_way_to_create_new_objects
1564 ok(0, "object instantiation exception not thrown")
1567 .exception_is( "Object must be created by a class." )
1571 .sub attribute_values__subclassing_access_meths
1572 newclass $P1, "Foo54"
1573 # must add attributes before object instantiation
1574 addattribute $P1, "i"
1575 addattribute $P1, "j"
1576 # define attrib access functions in Foo54 namespace
1577 get_global $P5, "Foo54__set"
1578 addmethod $P1, "Foo54__set", $P5
1579 get_global $P5, "Foo54__get"
1580 addmethod $P1, "Foo54__get", $P5
1582 subclass $P2, $P1, "Bar54"
1583 addattribute $P2, "k"
1584 addattribute $P2, "l"
1585 get_global $P5, "Bar54__set"
1586 addmethod $P2, "Bar54__set", $P5
1587 get_global $P5, "Bar54__get"
1588 addmethod $P2, "Bar54__get", $P5
1590 # instantiate a Bar54 object
1593 # Foo54 and Bar54 have attribute accessor methods
1594 new $P5, ['String'] # set attribute values
1595 set $P5, "i" # attribute slots have reference semantics
1596 set_args "0,0", $P5, "i"
1597 callmethodcc $P13, "Foo54__set"
1602 set_args "0,0", $P5, "j"
1603 callmethodcc $P13,"Foo54__set"
1608 set_args "0,0", $P5, "k"
1609 callmethodcc $P13,"Bar54__set"
1614 set_args "0,0", $P5, "l"
1615 callmethodcc $P13,"Bar54__set"
1618 # now retrieve attributes
1620 callmethodcc $P13,"Foo54__get"
1621 get_results "0", $P5
1622 is( $P5, "i", 'got attrib i from Bar54->Foo54__get' )
1625 callmethodcc $P13,"Foo54__get"
1626 get_results "0", $P5
1627 is( $P5, "j", 'got attrib j from Bar54->Foo54__get' )
1630 callmethodcc $P13,"Bar54__get"
1631 get_results "0", $P5
1632 is( $P5, "k", 'got attrib k from Bar54->Bar54__get' )
1635 callmethodcc $P13,"Bar54__get"
1636 get_results "0", $P5
1637 is( $P5, "l", 'got attrib l from Bar54->Bar54__get' )
1640 # set(obj: Pvalue, Iattr_idx)
1642 get_params "0,0", $P5, $S4
1643 ok( 1, "in Foo54__set" )
1644 interpinfo $P2, .INTERPINFO_CURRENT_OBJECT
1645 setattribute $P2, $S4, $P5
1650 # Pattr = get(obj: Iattr_idx)
1653 ok( 1, "in Foo54__get" )
1654 interpinfo $P2, .INTERPINFO_CURRENT_OBJECT
1655 getattribute $P5, $P2, $S4
1656 set_returns "0", $P5
1661 get_params "0,0", $P5, $S4
1662 interpinfo $P2, .INTERPINFO_CURRENT_OBJECT
1663 ok( 1, "in Bar54__set" )
1664 setattribute $P2, $S4, $P5
1671 ok( 1, "in Bar54__get" )
1672 interpinfo $P2, .INTERPINFO_CURRENT_OBJECT
1673 getattribute $P5, $P2, $S4
1674 set_returns "0", $P5
1678 .sub attribute_values__inherited_access_meths
1679 newclass $P1, "Foo56"
1680 # must add attributes before object instantiation
1681 addattribute $P1, "i"
1682 addattribute $P1, "j"
1683 # define attrib access functions
1684 get_global $P5, "set"
1685 addmethod $P1, "set", $P5
1686 get_global $P5, "get"
1687 addmethod $P1, "get", $P5
1689 subclass $P2, $P1, "Bar56"
1690 addattribute $P2, "k"
1691 addattribute $P2, "l"
1692 addattribute $P2, "m"
1694 # subclass is preferred for the SI case over
1695 # newclass $P2, "Bar56"
1697 # addparent $P2, $P1
1698 # which is suitable for adding multiple parents to one class
1700 # instantiate a Bar56 object
1703 # Foo56 and Bar56 have attribute accessor methods
1704 new $P5, ['String'] # set attribute values
1705 set $P5, "i" # attribute slots have reference semantics
1706 set_args "0,0,0", $P5, "Foo56", "i"
1707 callmethodcc $P2, "set"
1711 set_args "0,0,0", $P5, "Foo56", "j"
1712 callmethodcc $P2, "set"
1716 set_args "0,0,0", $P5, "Bar56", "k"
1717 callmethodcc $P2, "set"
1721 set_args "0,0,0", $P5, "Bar56", "l"
1722 callmethodcc $P2, "set"
1726 set_args "0,0,0", $P5, "Bar56", "m"
1727 callmethodcc $P2, "set"
1729 # now retrieve attributes
1730 set_args "0,0", "Foo56", "i"
1731 callmethodcc $P2, "get"
1732 get_results "0", $P5
1733 is( $P5, 'i', 'got attrib i from subclass through parent method' )
1735 set_args "0,0", "Foo56", "j"
1736 callmethodcc $P2, "get"
1737 get_results "0", $P5
1738 is( $P5, "j", 'got attrib i from subclass through parent method' )
1740 set_args "0,0", "Bar56", "k"
1741 callmethodcc $P2, "get"
1742 get_results "0", $P5
1743 is( $P5, "k", 'got attrib i from subclass through parent method' )
1745 set_args "0,0", "Bar56", "l"
1746 callmethodcc $P2, "get"
1747 get_results "0", $P5
1748 is( $P5, "l", 'got attrib i from subclass through parent method' )
1750 set_args "0,0", "Bar56", "m"
1751 callmethodcc $P2, "get"
1752 get_results "0", $P5
1753 is( $P5, "m", 'got attrib i from subclass through parent method' )
1756 # Foo56 provides accessor functions which Bar56 inherits
1757 # they take an additional classname argument SClass
1759 # set(obj: Pvalue, SClass, Sattr)
1761 get_params "0,0,0", $P5, $S4, $S5
1762 interpinfo $P2, .INTERPINFO_CURRENT_OBJECT
1763 setattribute $P2, $S5, $P5
1768 # Pattr = get(obj: SClass, Sattr)
1770 get_params "0,0", $S4, $S5
1771 interpinfo $P2, .INTERPINFO_CURRENT_OBJECT
1772 getattribute $P5, $P2, $S5
1773 set_returns "0", $P5
1782 # vim: expandtab shiftwidth=4 ft=pir: