2 # Copyright (C) 2001-2008, Parrot Foundation.
7 t/pmc/objects.t - Objects
11 % prove t/pmc/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' )
146 isa $I0, $P1, "Integer"
147 is( $I0, 1, 'Boolean isa Integer' )
149 isa $I0, $P1, "Integ"
150 is( $I0, 0, 'Boolean !isa Integ' )
153 is( $I0, 0, 'Boolean !isa eger' )
156 is( $I0, 0, 'Boolean !isa " "' )
159 is( $I0, 0, 'Boolean !isa ""' )
163 is( $I0, 0, 'Boolean !isa null $S0' )
167 is( $I0, 1, 'Boolean isa scalar $S0' )
173 does $I0, $P1, "Boolean"
174 is( $I0, 0, 'Boolean !does Boolean' )
176 does $I0, $P1, "Bool"
177 is( $I0, 0, 'Boolean !does Bool' )
179 does $I0, $P1, "scalar"
180 is( $I0, 1, 'Boolean does scalar' )
184 new $P1, ['OrderedHash']
186 does $I0, $P1, "Boolean"
187 is( $I0, 0, 'OrderedHash !does Boolean' )
189 does $I0, $P1, "Bool"
190 is( $I0, 0, 'OrderedHash !does Bool' )
192 does $I0, $P1, "hash"
193 is( $I0, 1, 'OrderedHash does hash' )
195 does $I0, $P1, "array"
196 is( $I0, 1, 'OrderedHash does array' )
202 ok( 1, 'created new object from Foo7 class' )
205 .sub new_object__isa_test
208 ok( 1, 'created new object from Foo8 class' )
211 ok( $I0, 'new object isa Foo8' )
214 .sub new_object__classname
218 is( $S0, "Foo9", 'new object from Foo9 class as a string is Foo9' )
220 typeof $S0, $P2 # object
221 is( $S0, 'Foo9', 'typeof obj is Foo9' )
225 is( $S0, 'Foo9', 'class of obj is Foo9' )
227 typeof $S0, $P2 # object
228 is( $S0, 'Foo9', 'typeof obj is Foo9' )
233 newclass $P1, "Foo10"
234 subclass $P2, $P1, "Bar10"
236 isa_ok( $P2, "Foo10", 'newclass isa Foo10' )
237 isa_ok( $P2, "Bar10", 'new subclass isa Bar10' )
238 isa_ok( $P2, "Foo10", 'new subclass isa parent' )
239 isa_ok( $P2, "Class", 'new subclass isa Class' )
241 isa $I0, $P2, "Object"
242 is( $I0, 0, 'new subclass !isa Object' )
245 .sub isa_subclass__objects
246 newclass $P3, "Foo30"
247 subclass $P4, $P3, "Bar30"
251 isa_ok( $P1, "Foo30", 'obj isa its class' )
252 isa_ok( $P2, "Bar30", 'obj isa its class' )
253 isa_ok( $P2, "Foo30", 'obj isa its parent class' )
254 isa_ok( $P2, "Object", 'obj isa Object' )
255 isa_ok( $P2, "Class", 'obj isa Class' )
259 newclass $P0, 'Foo31'
260 $P2 = get_hll_global 'sayFoo31'
262 # add a method BEFORE creating a Foo object
263 addmethod $P0, 'foo31', $P2
267 # get a method from some other namespace
268 $P2 = get_hll_global ['Bar31'], 'sayBar31'
270 # add a method AFTER creating the object
271 addmethod $P0, 'bar31', $P2
276 ok( 1, 'called method added before creating obj' )
281 ok( 1, 'called method added after created obj' )
284 .namespace [] # Reset to root namespace for next test
286 .sub test_addattribute
287 newclass $P1, "Foo11"
289 addattribute $P1, "foo_i"
290 ok( 1, 'addattribute did not blow up' )
293 is( $S0, "Foo11", '$P1 is still the same class as PMC' )
295 # Check that we can add multiple attributes
299 addattribute $P1, $S0
302 ok( 1, 'addattribute 1000x without blow up' )
305 .sub addattribute_subclass
306 newclass $P1, "Foo12"
307 addattribute $P1, "foo_i"
308 ok( 1, 'addattribute to Foo12' )
310 subclass $P2, $P1, "Bar12"
311 addattribute $P2, "bar_i"
312 ok( 1, 'addattribute to subclass of Foo12' )
315 .sub addattribute_subclass__same_name
316 newclass $P1, "Foo32"
317 addattribute $P1, "i"
318 addattribute $P1, "j"
320 subclass $P2, $P1, "Bar32"
321 addattribute $P2, "j"
322 addattribute $P2, "k"
324 ok( 1, 'created class and subclass and added attributes' )
328 $P0 = getattribute o, 'i'
329 is( $P0, 'Foo32.i', 'parent attrib initialized in init' )
330 $P0 = getattribute o, ['Foo32'], 'j'
331 is( $P0, 'Foo32.j', 'parent attrib initialized in init' )
332 $P0 = getattribute o, ['Bar32'], 'j'
333 is( $P0, 'Bar32.j', 'subclass attrib initialized in init' )
334 $P0 = getattribute o, 'k'
335 is( $P0, 'Bar32.k', 'subclass attrib initialized in init' )
337 $P0 = getattribute o, 'i'
338 is( $P0, 'Foo32.i', 'parent attrib init-ed' )
339 $P0 = getattribute o, ['Foo32'], "j"
340 is( $P0, 'Foo32.j', 'parent attrib init-ed' )
341 $P0 = getattribute o, 'j'
342 is( $P0, 'Bar32.j', 'subclass attrib returned over parent' )
343 $P0 = getattribute o, 'k'
344 is( $P0, 'Bar32.k', 'subclass attrib init-ed' )
349 .sub init :vtable :method
352 setattribute self, ['Foo32'], "i", $P0
355 setattribute self, ["Foo32"], "j", $P0
358 setattribute self, ["Bar32"], "j", $P0
361 setattribute self, ["Bar32"], "k", $P0
364 .namespace [] # Reset to root namespace for next test
366 .sub set_and_get_object_attribs
367 newclass $P1, "Foo13"
368 addattribute $P1, "i"
373 setattribute $P2, "i", $P3
376 getattribute $P4, $P2, "i"
378 is( $P4, 1024, 'set/get Integer attribute' )
381 .sub set_and_get_multiple_object_attribs
382 newclass $P1, "Foo14"
383 addattribute $P1, "i"
384 addattribute $P1, "j"
390 set $P4["Key"], "Value"
392 setattribute $P2, "i", $P3
393 setattribute $P2, "j", $P4
395 getattribute $P5, $P2, "i"
396 is( $P5, '4201', 'set/get Integer attribute' )
398 getattribute $P6, $P2, "j"
400 is( $S0, 'Value', 'set/get Hash attribute on same obj' )
403 .sub attribute_values_are_specific_to_objects
404 newclass $P1, "Foo15"
405 addattribute $P1, "i"
411 setattribute $P2, "i", $P4
413 set $P5, "One hundred"
414 setattribute $P3, "i", $P5
416 getattribute $P6, $P2, "i"
417 is( $P6, 100, 'attribute value on 1st object is specific to obj' )
419 getattribute $P6, $P3, "i"
420 is( $P6, 'One hundred', 'attribute value on 2nd obj is specific to obj' )
423 .sub attribute_values_and_subclassing
424 newclass $P1, "Foo16"
425 addattribute $P1, "i"
426 addattribute $P1, "j"
427 subclass $P2, $P1, "Bar16"
428 addattribute $P2, "k"
429 addattribute $P2, "l"
434 # Note that setattribute holds the actual PMC, not a copy, so
435 # in this test both attributes get the PMC from $P4, and should
436 # both have the same value, despite the C<inc>.
439 setattribute $P2, "i", $P4
441 setattribute $P2, "j", $P4
445 setattribute $P3, "i", $P5
447 setattribute $P3, "j", $P5
449 getattribute $P6, $P2, "i"
450 is( $P6, 11, 'setattrib with a PMC holds actual PMC not copy' )
452 getattribute $P6, $P2, "j"
453 is( $P6, 11, '...so changes to the PMC appear through the attrib' )
455 getattribute $P6, $P3, "i"
456 is( $P6, 101, '...and second test on new objects' )
458 getattribute $P6, $P3, "j"
459 is( $P6, 101, '...should have same result' )
462 .sub attribute_values_and_subclassing_2
463 newclass $P1, "Foo17"
464 # must add attributes before object instantiation
465 addattribute $P1, ".i"
466 addattribute $P1, ".j"
468 subclass $P2, $P1, "Bar17"
469 addattribute $P2, ".k"
470 addattribute $P2, ".l"
472 # subclass is preferred for the SI case over
473 # newclass $P2, "Bar"
476 # which is suitable for adding multiple parents to one class
478 # instantiate a Bar object
481 # Set the attribute values
482 new $P10, ['String'] # set attribute values
483 set $P10, "i" # attribute slots have reference semantics
484 setattribute $P3, ".i", $P10 # so always put new PMCs in
485 # if you have unique values
488 setattribute $P3, ".j", $P10
492 setattribute $P3, ".k", $P10
496 setattribute $P3, ".l", $P10
499 getattribute $P11, $P3, ".i"
500 is( $P11, "i", 'string attribute get/set on parent' )
502 getattribute $P11, $P3, ".j"
503 is( $P11, "j", 'string attribute get/set on parent' )
505 getattribute $P11, $P3, ".k"
506 is( $P11, "k", 'string attribute get/set on subclass' )
508 getattribute $P11, $P3, ".l"
509 is( $P11, "l", 'string attribute get/set on subclass' )
512 .sub PMC_as_classes__overridden_mmd_methods
513 .local pmc myint, i, j, k
515 get_class $P0, "Integer"
516 subclass myint, $P0, "MyInt1"
525 is( k, 13, 'added two MyInt1' )
531 is( k, 106, 'added MyInt1 and an Integer' )
534 .namespace ["MyInt1"]
536 .sub add :multi(MyInt1, MyInt1, MyInt1)
540 ok( 1, 'in the add method' )
541 $P0 = getattribute self, ['Integer'], "proxy"
549 .namespace [] # Reset to root namespace for next test
552 newclass $P0, "Foo21"
554 is( $S0, "Class", 'typeof for a Class PMC is "Class"' )
567 is( $S0, 'A', 'typeof object of class A is "A"' )
568 is( $S1, 'B', 'typeof object of class B is "B"' )
571 .sub multiple_inheritance__with_attributes
573 addattribute $P1, "Spectral Type"
575 newclass $P2, "Company"
576 addattribute $P2, "Annual Profit"
578 subclass $P3, $P1, "Sun"
585 setattribute $P4, "Spectral Type", $P5
588 set $P6, "$100,000,000"
589 setattribute $P4, "Annual Profit", $P6
591 getattribute $P7, $P4, "Spectral Type"
592 is( $P7, 'G', 'direct parents attribute' )
594 getattribute $P8, $P4, "Annual Profit"
595 is( $P8, '$100,000,000', "addparent's attribute" )
598 .sub attributes_two_levels_of_inheritance
599 newclass $P0, "Astronomical Object"
600 addattribute $P0, "Location"
602 subclass $P1, $P0, "Star2"
603 addattribute $P1, "Spectral Type"
613 setattribute $P4, "Location", $P5
614 getattribute $P6, $P4, "Location"
615 is( $P6, 'Taurus', 'attributes with two levels of inheritance' )
619 newclass $P0, "City1"
624 is( $S0, 'City1', 'class op works' )
627 .sub anon_subclass_has_no_name
628 newclass $P0, "City2"
631 is( $S0, '', 'anonymous subclass has no name' )
634 .sub get_attrib_by_name
635 newclass $P1, "Foo18"
636 addattribute $P1, "i"
640 setattribute $P2, "i", $P3
642 getattribute $P4, $P2, ["Foo18"], "i"
643 is( $P4, 'ok', 'get attrib by name' )
646 .sub get_attrib_by_name_subclass
647 newclass $P0, "Bar19"
648 addattribute $P0, "j"
650 subclass $P1, $P0, "Foo19"
651 addattribute $P1, "i"
657 setattribute $P2, "i", $P3
661 setattribute $P2, "j", $P3
663 getattribute $P4, $P2, ["Foo19"], "i"
664 is( $P4, 'foo i', 'attribute from subclass get by name' )
666 getattribute $P4, $P2, ["Bar19"], "j"
667 is( $P4, 'bar j', 'attribute from parent class get by name' )
670 .sub set_attrib_by_name_subclass
671 newclass $P0, "Bar20"
672 addattribute $P0, "j"
674 subclass $P1, $P0, "Foo20"
675 addattribute $P1, "i"
681 setattribute $P2, ["Foo20"], "i", $P3
685 setattribute $P2, ["Bar20"], "j", $P3
687 getattribute $P4, $P2, "i"
688 is( $P4, 'foo i', 'attribute from subclass set by name' )
690 getattribute $P4, $P2, "j"
691 is( $P4, 'bar j', 'attribute from parent class set by name' )
695 get_class $P0, "Integer"
696 ok( 1, "get_class of Integer did't croak" )
698 get_class $P0, "Integer"
699 ok( 1, "get_class of Integer did't croak second time" )
702 is( $S0, 'PMCProxy', 'typeof PMCProxy' )
705 .sub PMC_as_classes__subclass
707 get_class $P0, "Integer"
708 ok( 1, "get_class on Integer didn't blow up" )
710 subclass MyInt3, $P0, "MyInt3"
711 ok( 1, "subclassing didn't blow up" )
714 is( $S0, 'Class', 'new subclass is typeof Class' )
716 $I0 = isa MyInt3, "MyInt3"
717 ok( $I0, 'new subclass isa MyInt' )
719 $I0 = isa MyInt3, "Integer"
720 ok( $I0, 'new subclass isa parent class' )
723 .sub PMC_as_classes__instantiate
725 get_class $P0, "Integer"
726 ok( 1, 'able to get_class of Integer' )
728 subclass MyInt4, $P0, "MyInt4"
729 addattribute MyInt4, ".i"
730 ok( 1, 'able to addattribute to subclass' )
734 ok( 1, 'able to instantiate obj of subclass w/ attribute' )
737 .sub PMC_as_classes__methods
739 get_class $P0, "Integer"
741 subclass MyInt5, $P0, "MyInt5"
742 addattribute MyInt5, "intval"
749 i = 42 # set_integer is inherited from Integer
750 ok( 1, 'able to assign int to MyInt' )
752 $I0 = i # get_integer is overridden below
753 is( $I0, 42, 'get_integer is overridden for MyInt5' )
755 $S0 = i # get_string is overridden below
756 is( $S0, 'MyInt5(42)', 'get_string is overridden for MyInt5' )
759 .namespace ["MyInt5"]
761 .sub set_integer_native :vtable :method
763 $P1 = new ['Integer']
765 setattribute self, "intval", $P1
768 .sub get_integer :vtable :method
769 $P0 = getattribute self, "intval"
774 .sub get_string :vtable :method
775 $P0 = getattribute self, "intval"
784 .namespace [] # Reset to root namespace for next test
786 .sub PMC_as_classes__mmd_methods
788 get_class $P0, "Integer"
789 subclass MyInt6, $P0, "MyInt6"
800 is( $I0, 42, 'MyInt6 defaults to Integer class for mult' )
802 $S0 = k # get_string is overridden below
803 is( $S0, 'MyInt6(42)', 'get_string is overridden for MyInt6' )
806 .namespace ["MyInt6"]
808 .sub get_string :vtable :method
809 $I0 = self # get_integer is not overridden
817 .namespace [] # Reset to root namespace for next test
819 .sub PMC_as_classes__derived_1
822 get_class $P0, "Integer"
824 subclass MyInt8, $P0, "MyInt8"
825 addattribute MyInt8, 'intval'
826 get_class $P1, "MyInt8"
827 subclass MyInt8_2, $P1, "MyInt8_2"
831 $I0 = isa i, "Integer"
832 ok( $I0, 'obj isa grandparent (Integer)' )
834 $I0 = isa i, "MyInt8"
835 ok( $I0, 'obj isa parent (MyInt8)' )
837 $I0 = isa i, "MyInt8_2"
838 ok( $I0, 'obj isa its class (MyInt8_2)' )
840 i = 42 # set_integer is overridden below
841 $I0 = i # get_integer is overridden below
842 is( $I0, 42, 'set/get_integer overridden' )
844 $S0 = i # get_string is overridden below
845 is( $S0, 'MyInt8_2(42)', 'set/get_string overridden' )
848 .namespace ["MyInt8"]
849 .sub 'set_integer_native' :vtable :method
851 $P1 = new ['Integer']
853 setattribute self, "intval", $P1
856 .sub get_integer :vtable :method
857 $P0 = getattribute self, 'intval'
861 .sub get_string :vtable :method
862 $P0 = getattribute self, 'intval'
872 .namespace [] # Reset to root namespace for next test
874 .sub PMC_as_classes__derived_2
877 get_class $P0, "Integer"
879 subclass MyInt9, $P0, "MyInt9"
880 addattribute MyInt9, 'intval'
881 get_class $P1, "MyInt9"
882 subclass MyInt9_2, $P1, "MyInt9_2"
886 $I0 = isa i, "Integer"
887 ok( $I0, 'obj isa grandparent (Integer)' )
888 $I0 = isa i, "MyInt9"
889 ok( $I0, 'obj isa parent (MyInt9)' )
890 $I0 = isa i, "MyInt9_2"
891 ok( $I0, 'obj isa its class (MyInt9_2)' )
893 i = 42 # set_integer is overridden below
894 $I0 = i # get_integer is overridden below
895 is( $I0, 43, 'set/get_integer overridden' )
897 $S0 = i # get_string is overridden below
898 is( $S0, 'MyInt9_2(42)', 'set/get_string overridden' )
901 .namespace ["MyInt9_2"]
902 # subclassing methods from MyInt9 is ok
903 # this one changes the value a bit
904 .sub get_integer :vtable :method
905 $P0 = getattribute self, 'intval'
910 .namespace ["MyInt9"]
911 .sub 'set_integer_native' :vtable :method
913 $P1 = new ['Integer']
915 setattribute self, "intval", $P1
918 .sub get_integer :vtable :method
919 $P0 = getattribute self, 'intval'
923 .sub get_string :vtable :method
924 $P0 = getattribute self, 'intval'
934 .namespace [] # Reset to root namespace for next test
936 .sub PMC_as_classes__derived_3
939 get_class $P0, "Integer"
941 subclass MyInt10, $P0, "MyInt10"
942 addattribute MyInt10, 'intval'
943 get_class $P1, "MyInt10"
944 subclass MyInt10_2, $P1, "MyInt10_2"
948 $I0 = isa i, "Integer"
949 ok( $I0, 'obj isa grandparent (Integer)' )
950 $I0 = isa i, "MyInt10"
951 ok( $I0, 'obj isa parent (MyInt10)' )
952 $I0 = isa i, "MyInt10_2"
953 ok( $I0, 'obj isa its class (MyInt102)' )
955 i = 42 # set_integer is overridden below
956 $I0 = i # get_integer is overridden below
957 is( $I0, 42, 'set/get_integer overridden' )
959 $S0 = i # get_string is overridden below
960 is( $S0, 'MyInt10_2(42)', 'set/get_string overridden' )
963 .namespace ["MyInt10_2"]
964 .sub get_integer :vtable :method
965 $P0 = getattribute self, 'intval'
969 .sub get_string :vtable :method
970 $P0 = getattribute self, 'intval'
979 .namespace ['MyInt10']
980 .sub 'set_integer_native' :vtable :method
982 $P1 = new ['Integer']
984 setattribute self, "intval", $P1
988 .namespace [] # Reset to root namespace for next test
990 .sub subclassing_Class
993 parent = get_class "Class"
994 cl = subclass parent, "Foo33"
995 ok( 1, 'able to subclass Class' )
999 ok( 1, 'able to instantiate subclass of Class' )
1002 is( $S0, 'Foo33', 'object returns correct class' )
1005 .sub namespace_vs_name
1007 newclass cl, "Foo34"
1009 is( o, 'Foo34::get_string', 'found Foo34 namespace' )
1012 is( o, 'Foo34', 'found global Foo34' )
1014 f = get_global "Foo34"
1016 is( o, 'Foo34', 'found global Foo34 explicitly' )
1018 f = get_global ["Foo34"], "Foo34"
1020 is( o, 'Foo34::Foo34', 'found method in Foo34 namespace' )
1027 .namespace [ "Foo34" ]
1029 .sub get_string :vtable :method
1030 .return("Foo34::get_string")
1034 .return("Foo34::Foo34")
1037 .namespace [] # Reset to root namespace for next test
1040 .sub multiple_anon_classes
1041 newclass $P0, "City3"
1043 newclass $P2, "State3"
1045 ok( 1, "multiple anon classes didn't croak (bug #33103)" )
1048 .sub subclassed_Integer_bug
1053 subclass class, "Integer", "LispInteger1"
1055 a = new "LispInteger1"
1056 b = new "LispInteger1"
1062 is( $S0, '1', 'subclassed Integer is 1' )
1064 is( $S0, '1', 'subclassed Integer is 1' )
1068 is( $S0, '1', 'multip and reasign to subclassed Integer is 1' )
1071 .sub equality_of_subclassed_Integer
1073 class = subclass "Integer", "LispInteger2"
1076 a = new 'LispInteger2'
1080 b = new 'LispInteger2'
1084 ok( $I0, '123 is equal to 123' )
1088 .sub short_name_attributes
1089 newclass $P1, "Foo22"
1090 addattribute $P1, "i"
1091 addattribute $P1, "j"
1093 subclass $P2, $P1, "Bar22"
1094 addattribute $P2, "k"
1095 addattribute $P2, "l"
1099 # set a bunch of attribs
1100 new $P4, ['Integer']
1102 setattribute $P2, "i", $P4
1104 new $P4, ['Integer']
1106 setattribute $P2, "j", $P4
1108 new $P4, ['Integer']
1110 setattribute $P2, "k", $P4
1112 new $P4, ['Integer']
1114 setattribute $P2, "l", $P4
1116 getattribute $P6, $P2, "i"
1117 is( $P6, 10, '"i" getattribute on parent class attrib' )
1118 getattribute $P6, $P2, "j"
1119 is( $P6, 11, '"j" getattribute on parent class attrib' )
1121 getattribute $P6, $P2, "k"
1122 is( $P6, 20, '"k" getattribute on subclass attrib' )
1123 getattribute $P6, $P2, "l"
1124 is( $P6, 21, '"l" getattribute on subclass attrib' )
1126 getattribute $P6, $P2, ["Foo22"], "i"
1127 is( $P6, 10, '["Foo22"], "i" getattribute on parent class attrib' )
1128 getattribute $P6, $P2, ["Bar22"], "k"
1129 is( $P6, 20, '["Bar22"], "k" getattribute on subclass attrib' )
1132 .sub init_with_and_without_arg
1133 .local pmc cl, o, h, a
1134 cl = newclass "Foo35"
1135 addattribute cl, "a"
1137 a = getattribute o, "a"
1138 is( a, 'ok 1', 'init without an arg' )
1141 $P0 = new ['String']
1145 a = getattribute o, "a"
1146 is( a, 'ok 2', 'init with an arg' )
1149 .namespace ["Foo35"]
1150 .sub init_pmc :vtable :method
1153 setattribute self, 'a', $P0
1156 .sub init :vtable :method
1157 $P0 = new ['String']
1159 setattribute self, 'a', $P0
1162 .namespace [] # Reset to root namespace for next test
1164 .sub newclass_bracket_parsing
1165 newclass $P0, ['Foo23';'Bar23']
1166 ok( 1, 'newclass created with brackets' )
1169 .sub verify_namespace_types
1170 newclass $P0, ['Foo24';'Bar24']
1172 set $P1, $P0[.IGLOBALS_CLASSNAME_HASH]
1174 is( $S0, 'NameSpace', 'namespace verified' )
1176 set $P2, $P1['Foo24']
1178 is( $S0, 'NameSpace', 'namespace verified' )
1181 .sub verify_data_type
1182 newclass $P0, ['Foo25';'Bar25']
1184 set $P1, $P0[.IGLOBALS_CLASSNAME_HASH]
1185 set $P2, $P1['Foo25']
1186 set $P3, $P2['Bar25']
1190 ok( $I0, 'verified datatype > 0' )
1193 # Puts init in a namespace
1196 cl = newclass ['Foo36';'Bar36']
1197 addattribute cl, "init_check"
1199 ok( 1, 'obj successfully created' )
1201 p = getattribute o, "init_check"
1202 is( p, 999, "overridden init called")
1205 .namespace ['Foo36';'Bar36']
1207 .sub init :vtable :method
1211 setattribute self, "init_check", p
1214 .namespace [] # revert to root for next test
1217 .local pmc c1, c2, o1, o2
1218 c1 = newclass ['Foo37';'Bar37']
1219 c2 = newclass ['Foo37';'Fuz37']
1222 ok( 1, 'objects created successfully' )
1225 .namespace ['Foo37';'Bar37']
1227 .sub init :vtable :method
1228 ok( 1, '__init Bar37' )
1231 .namespace ['Foo37';'Fuz37']
1233 .sub init :vtable :method
1234 ok( 1, '__init Fuz37' )
1237 .namespace [] # revert to root for next test
1240 .local pmc c1, c2, c3, o1, o2, o3
1241 c1 = newclass ['Foo38';'Bar38']
1242 c2 = newclass ['Foo38';'Buz38']
1243 c3 = newclass 'Foo38'
1244 o1 = new ['Foo38';'Bar38']
1245 o2 = new ['Foo38';'Buz38']
1247 ok( 1, 'objects created successfully' )
1250 .namespace ['Foo38';'Bar38']
1252 .sub init :vtable :method
1253 ok( 1, '__init Bar38' )
1256 .namespace ['Foo38';'Buz38']
1258 .sub init :vtable :method
1259 ok( 1, '__init Buz38' )
1262 .namespace ['Foo38']
1264 .sub init :vtable :method
1265 ok( 1, '__init Foo38' )
1268 .namespace [] # revert to root for next test
1271 .local pmc base, o1, o2
1272 base = subclass 'Hash', ['Perl6-3'; 'PAST'; 'Node']
1273 addattribute base, '$.source' # original source
1274 addattribute base, '$.pos' # offset position
1276 $P0 = subclass base, ['Perl6-3'; 'PAST'; 'Sub']
1277 $P0 = subclass base, ['Perl6-3'; 'PAST'; 'Stmt']
1280 o1 = new ['Perl6-3'; 'PAST'; 'Sub']
1281 o2 = new ['Perl6-3'; 'PAST'; 'Stmt']
1282 ok( 1, 'objects created successfully' )
1285 .namespace ['Perl6-3'; 'PAST'; 'Stmt']
1287 .sub init :vtable :method
1288 ok( 1, '__init Stmt' )
1291 .namespace ['Perl6-3'; 'PAST'; 'Sub']
1293 .sub init :vtable :method
1294 ok( 1, '__init Sub' )
1297 .namespace [] # revert to root for next test
1299 .sub test_class_name_multipart_name
1301 base = subclass 'Hash', ['Perl6'; 'PAST'; 'Node']
1304 is( $S0, "Perl6;PAST;Node", "typeof returns object's class name" )
1307 .sub test_get_class_multipart_name
1309 base = subclass 'Hash', ['Perl6a'; 'PAST'; 'Node']
1310 $P0 = get_class ['Perl6a'; 'PAST'; 'Node']
1313 is( $S0, 'Perl6a;PAST;Node', 'typeof returns objects created from get_class' )
1318 .local pmc base, o1, o2
1319 base = subclass 'Hash', ['Perl6b'; 'PAST'; 'Node']
1320 $P0 = new [ 'Perl6b'; 'PAST'; 'Node' ]
1322 $I0 = isa $P0, [ 'Perl6b'; 'PAST'; 'Node']
1323 is( $I0, 1, 'obj isa the full class name' )
1325 $I0 = isa $P0, 'Hash'
1326 is( $I0, 1, 'obj isa the parent class' )
1328 $I0 = isa $P0, 'Perl6b'
1329 is( $I0, 0, 'obj !isa the first part of the class name' )
1332 .sub new_nested_ordering
1333 .local pmc c1, c2, o
1334 c1 = newclass ['Foo39']
1335 c2 = newclass ['Foo39';'Bar39']
1337 ok( 1, 'objects created successfully' )
1340 .namespace ['Foo39']
1342 .sub init :vtable :method
1343 ok( 0, '__init Foo39' ) # shouldn't be called
1346 .namespace ['Foo39';'Bar39']
1348 .sub init :vtable :method
1349 ok( 1, '__init Bar39' ) # should be called
1352 .namespace [] # revert to root for next test
1355 .sub vtable_override_once_removed
1357 $P0 = get_class 'Integer'
1358 base = subclass $P0, 'Foo40' # create subclass 'Foo40'
1359 addattribute base, '@!capt'
1361 $P0 = subclass 'Foo40', 'Bar40' # create subclass 'Bar40'
1362 $P1 = new 'Bar40' # create an instance of 'Bar40'
1364 $S1 = $P1 # get its string representation
1365 is( $S1, 'ok bar', 'get_string overridden' )
1368 .namespace [ 'Bar40' ]
1370 .sub 'get_string' :vtable :method
1375 .namespace [] # revert to root for next test
1378 .sub vtable_fails_for_subclasses_of_core_classes
1379 $P0 = subclass 'Hash', 'Foo41'
1380 $P0 = subclass 'Hash', 'Bar41'
1384 is( $S1, 'Hello world', '__get_string method' )
1388 is( $S1, 'Hello world', 'vtable method get_string' )
1391 .namespace [ 'Foo41' ]
1393 .sub '__get_string' :method
1394 .return('Hello world')
1397 .namespace [ 'Bar41' ]
1399 .sub 'get_string' :method :vtable
1400 .return('Hello world')
1403 .namespace [] # revert to root for next test
1406 .sub super___init_called_twice
1407 $P0 = newclass 'Foo42'
1408 $P1 = subclass $P0, 'Bar42'
1409 addattribute $P1, 'i'
1414 .namespace [ 'Foo42' ]
1416 .sub 'init' :vtable :method
1417 $P0 = getattribute self, 'i'
1419 ok( $I1, 'should be null' )
1421 $P1 = new ['Integer']
1422 setattribute self, "i", $P1 # i won't be null if init called again
1426 .namespace [] # revert to root for next test
1428 .sub using_class_object_from_typeof_op_with_new
1429 $P0 = newclass [ "Monkey" ; "Banana" ]
1432 is( $S0, "Ook!", 'obj created from .new() class method' )
1437 is( $S0, "Ook!", 'obj created from "new" called on result of typeof' )
1440 .namespace [ "Monkey" ; "Banana" ]
1446 .namespace [] # revert to root for next test
1448 .macro exception_is ( M )
1449 .local pmc exception
1450 .local string message
1451 .get_results (exception)
1453 message = exception['message']
1454 is( message, .M, .M )
1457 .sub setting_non_existent_attribute
1458 newclass $P1, "Foo45"
1461 new $P3, ['Integer']
1463 setattribute $P2, "bar", $P3
1465 ok(0, "'No such attribute' exception not thrown")
1468 .exception_is( "No such attribute 'bar'" )
1472 .sub setting_non_existent_attribute_by_name
1473 newclass $P1, "Foo47"
1476 new $P3, ['Integer']
1478 setattribute $P2, ["Foo47"], "no_such", $P3
1480 ok(0, "'No such attribute' exception not thrown")
1483 .exception_is( "No such attribute 'no_such' in class 'Foo47'" )
1488 .sub getting_null_attribute
1489 newclass $P1, "Foo51"
1490 addattribute $P1, "i"
1493 getattribute $P3, $P2, "i"
1495 is($I0, 1, "null attribute is null")
1498 .sub getting_non_existent_attribute
1499 newclass $P1, "Foo52"
1503 getattribute $P3, $P2, "bar"
1505 ok(0, "'No such attribute' exception not thrown")
1508 .exception_is( "No such attribute 'bar'" )
1512 .sub addparent_exceptions_1
1513 newclass $P0, "Astronomical Object 2"
1515 set $P1, "Not a class"
1519 ok(0, "'Parent isn\'t a Class' exception not thrown")
1522 .exception_is( "Parent isn't a Class." )
1526 .sub addparent_exceptions_2
1528 newclass $P1, "Trashcan"
1532 ok(0, "'Only classes can be subclassed' exception not thrown")
1535 .exception_is( "Only classes can be subclassed" )
1539 .sub subclassing_a_non_existent_class
1541 subclass $P1, "Character", "Nemo"
1543 ok(0, "nonexistent class exception not thrown")
1546 .exception_is( "Class 'Character' doesn't exist" )
1550 .sub anon_subclass_of_non_existent_class
1552 subclass $P1, "Character"
1554 ok(0, "nonexistent class exception not thrown")
1557 .exception_is( "Class 'Character' doesn't exist" )
1561 .sub addattribute_duplicate
1562 newclass $P1, "Foo53"
1563 addattribute $P1, "i"
1564 addattribute $P1, "j"
1566 addattribute $P1, "i"
1568 ok(0, "attribute already exists exception not thrown")
1571 .exception_is( "Attribute 'i' already exists in 'Foo53'." )
1575 .sub wrong_way_to_create_new_objects
1579 ok(0, "object instantiation exception not thrown")
1582 .exception_is( "Object must be created by a class." )
1586 .sub attribute_values__subclassing_access_meths
1587 newclass $P1, "Foo54"
1588 # must add attributes before object instantiation
1589 addattribute $P1, "i"
1590 addattribute $P1, "j"
1591 # define attrib access functions in Foo54 namespace
1592 get_global $P5, "Foo54__set"
1593 addmethod $P1, "Foo54__set", $P5
1594 get_global $P5, "Foo54__get"
1595 addmethod $P1, "Foo54__get", $P5
1597 subclass $P2, $P1, "Bar54"
1598 addattribute $P2, "k"
1599 addattribute $P2, "l"
1600 get_global $P5, "Bar54__set"
1601 addmethod $P2, "Bar54__set", $P5
1602 get_global $P5, "Bar54__get"
1603 addmethod $P2, "Bar54__get", $P5
1605 # instantiate a Bar54 object
1608 # Foo54 and Bar54 have attribute accessor methods
1609 new $P5, ['String'] # set attribute values
1610 set $P5, "i" # attribute slots have reference semantics
1611 set_args "0,0", $P5, "i"
1613 callmethodcc $P13, "Foo54__set"
1617 set_args "0,0", $P5, "j"
1619 callmethodcc $P13,"Foo54__set"
1623 set_args "0,0", $P5, "k"
1625 callmethodcc $P13,"Bar54__set"
1629 set_args "0,0", $P5, "l"
1631 callmethodcc $P13,"Bar54__set"
1633 # now retrieve attributes
1635 get_results "0", $P5
1636 callmethodcc $P13,"Foo54__get"
1637 is( $P5, "i", 'got attrib i from Bar54->Foo54__get' )
1640 get_results "0", $P5
1641 callmethodcc $P13,"Foo54__get"
1642 is( $P5, "j", 'got attrib j from Bar54->Foo54__get' )
1645 get_results "0", $P5
1646 callmethodcc $P13,"Bar54__get"
1647 is( $P5, "k", 'got attrib k from Bar54->Bar54__get' )
1650 get_results "0", $P5
1651 callmethodcc $P13,"Bar54__get"
1652 is( $P5, "l", 'got attrib l from Bar54->Bar54__get' )
1655 # set(obj: Pvalue, Iattr_idx)
1657 get_params "0,0", $P5, $S4
1658 ok( 1, "in Foo54__set" )
1659 interpinfo $P2, .INTERPINFO_CURRENT_OBJECT
1660 setattribute $P2, $S4, $P5
1665 # Pattr = get(obj: Iattr_idx)
1668 ok( 1, "in Foo54__get" )
1669 interpinfo $P2, .INTERPINFO_CURRENT_OBJECT
1670 getattribute $P5, $P2, $S4
1671 set_returns "0", $P5
1676 get_params "0,0", $P5, $S4
1677 interpinfo $P2, .INTERPINFO_CURRENT_OBJECT
1678 ok( 1, "in Bar54__set" )
1679 setattribute $P2, $S4, $P5
1686 ok( 1, "in Bar54__get" )
1687 interpinfo $P2, .INTERPINFO_CURRENT_OBJECT
1688 getattribute $P5, $P2, $S4
1689 set_returns "0", $P5
1693 .sub attribute_values__inherited_access_meths
1694 newclass $P1, "Foo56"
1695 # must add attributes before object instantiation
1696 addattribute $P1, "i"
1697 addattribute $P1, "j"
1698 # define attrib access functions
1699 get_global $P5, "set"
1700 addmethod $P1, "set", $P5
1701 get_global $P5, "get"
1702 addmethod $P1, "get", $P5
1704 subclass $P2, $P1, "Bar56"
1705 addattribute $P2, "k"
1706 addattribute $P2, "l"
1707 addattribute $P2, "m"
1709 # subclass is preferred for the SI case over
1710 # newclass $P2, "Bar56"
1712 # addparent $P2, $P1
1713 # which is suitable for adding multiple parents to one class
1715 # instantiate a Bar56 object
1718 # Foo56 and Bar56 have attribute accessor methods
1719 new $P5, ['String'] # set attribute values
1720 set $P5, "i" # attribute slots have reference semantics
1721 set_args "0,0,0", $P5, "Foo56", "i"
1723 callmethodcc $P2, "set"
1727 set_args "0,0,0", $P5, "Foo56", "j"
1729 callmethodcc $P2, "set"
1733 set_args "0,0,0", $P5, "Bar56", "k"
1735 callmethodcc $P2, "set"
1739 set_args "0,0,0", $P5, "Bar56", "l"
1741 callmethodcc $P2, "set"
1745 set_args "0,0,0", $P5, "Bar56", "m"
1747 callmethodcc $P2, "set"
1749 # now retrieve attributes
1750 set_args "0,0", "Foo56", "i"
1751 get_results "0", $P5
1752 callmethodcc $P2, "get"
1753 is( $P5, 'i', 'got attrib i from subclass through parent method' )
1755 set_args "0,0", "Foo56", "j"
1756 get_results "0", $P5
1757 callmethodcc $P2, "get"
1758 is( $P5, "j", 'got attrib i from subclass through parent method' )
1760 set_args "0,0", "Bar56", "k"
1761 get_results "0", $P5
1762 callmethodcc $P2, "get"
1763 is( $P5, "k", 'got attrib i from subclass through parent method' )
1765 set_args "0,0", "Bar56", "l"
1766 get_results "0", $P5
1767 callmethodcc $P2, "get"
1768 is( $P5, "l", 'got attrib i from subclass through parent method' )
1770 set_args "0,0", "Bar56", "m"
1771 get_results "0", $P5
1772 callmethodcc $P2, "get"
1773 is( $P5, "m", 'got attrib i from subclass through parent method' )
1776 # Foo56 provides accessor functions which Bar56 inherits
1777 # they take an additional classname argument SClass
1779 # set(obj: Pvalue, SClass, Sattr)
1781 get_params "0,0,0", $P5, $S4, $S5
1782 interpinfo $P2, .INTERPINFO_CURRENT_OBJECT
1783 setattribute $P2, $S5, $P5
1788 # Pattr = get(obj: SClass, Sattr)
1790 get_params "0,0", $S4, $S5
1791 interpinfo $P2, .INTERPINFO_CURRENT_OBJECT
1792 getattribute $P5, $P2, $S5
1793 set_returns "0", $P5
1800 # cperl-indent-level: 4
1803 # vim: expandtab shiftwidth=4 filetype=pir: