tagged release 0.7.1
[parrot.git] / t / pmc / hash.t
blobfb443350648684e11e07206bcf3cb8e67843269e
1 #! parrot
2 # Copyright (C) 2001-2008, The Perl Foundation.
3 # $Id$
5 =head1 NAME
7 t/pmc/hash.t - Test the Hash PMC
9 =head1 SYNOPSIS
11     % prove t/pmc/hash.t
13 =head1 DESCRIPTION
15 Tests the C<Hash> PMC. Checks key access with various types of
16 normal and potentially hazardous keys. Does a bit of stress testing as
17 well.
19 =cut
21 .sub main :main
22     .include 'include/test_more.pir'
24     plan(147)
26     initial_hash_tests()
27     more_than_one_hash()
28     hash_keys_with_nulls_in_them()
29     nearly_the_same_hash_keys()
30     the_same_hash_keys()
31     key_that_hashes_to_zero()
32     size_of_the_hash()
33     stress_test_loop_set_check()
34     stress_test_lots_of_keys()
35     stress_test_loop_set_loop_check()
36     testing_two_hash_indices_with_integers_at_a_time()
37     testing_two_hash_indices_with_numbers_at_a_time()
38     testing_two_hash_indices_with_strings_at_a_time()
39     setting_and_getting_scalar_pmcs()
40     setting_scalar_pmcs_and_getting_scalar_values()
41     getting_values_from_undefined_keys()
42     setting_and_getting_non_scalar_pmcs()
43     testing_clone()
44     compound_keys()
45     getting_pmcs_from_compound_keys()
46     getting_pmcs_from_string_int_compound_keys()
47     if_hash()
48     unless_hash()
49     defined_hash()
50     exists_hash_key()
51     delete_hash_key()
52     cloning_keys()
53     cloning_pmc_vals()
54     entry_types_type_keyed()
55     delete_and_free_list()
56     exists_with_constant_string_key()
57     hash_in_pir()
58     setting_with_compound_keys()
59     mutating_the_lookup_string()
60     check_whether_interface_is_done()
61     iter_over_hash()
62     broken_delete()
63     unicode_keys_register_rt_39249()
64     unicode_keys_literal_rt_39249()
66 .end
68 .sub initial_hash_tests
69     new $P0, 'Hash'
71     set $P0["foo"], -7
72     set $P0["bar"], 3.5
73     set $P0["baz"], "value"
75     set $I0, $P0["foo"]
76     set $N0, $P0["bar"]
77     set $S0, $P0["baz"]
79     is( $I0, -7,       'lookup Int in hash' )
80     is( $N0, 3.500000, 'lookup Num in hash' )
81     is( $S0, "value",  'lookup Str in hash' )
83     set $S1, "oof"
84     set $S2, "rab"
85     set $S3, "zab"
87     set $P0[$S1], 7
88     set $P0[$S2], -3.5
89     set $P0[$S3], "VALUE"
91     set $I0, $P0[$S1]
92     set $N0, $P0[$S2]
93     set $S0, $P0[$S3]
95     is( $I0, 7,         'lookup Int in hash via Str' )
96     is( $N0, -3.500000, 'lookup Num in hash via Str' )
97     is( $S0, "VALUE",   'lookup Str in hash via Str' )
99 .end
101 .sub more_than_one_hash
102     new $P0, 'Hash'
103     set $S0, "key"
104     set $P0[$S0], 1
106     new $P1, 'Hash'
107     set $S1, "another_key"
108     set $P1[$S1], 2
110     set $I0, $P0[$S0]
111     set $I1, $P1[$S1]
113     is( $I0, 1, 'two hashes: lookup Int from hash via Str' )
114     is( $I1, 2, 'two hashes: lookup Int from hash via Str in second' )
115 .end
117 .sub hash_keys_with_nulls_in_them
118     new $P0, 'Hash'
119     set $S0, "parp\0me"
120     set $S1, "parp\0you"
122     set $P0[$S0], 1             # $P0{parp\0me} = 1
123     set $P0[$S1], 2             # $P0{parp\0you} = 2
125     set $I0, $P0[$S0]
126     set $I1, $P0[$S1]
128     is( $I0, 1, 'hash key with null 1' )
129     is( $I1, 2, 'hash key will null 2' )
130 .end
132 .sub nearly_the_same_hash_keys
133     new $P0, 'Hash'
134     set $S0, "a\0"
135     set $S1, "\0a"
137     set $P0[$S0], 1
138     set $P0[$S1], 2
140     set $I0, $P0[$S0]
141     set $I1, $P0[$S1]
143     is( $I0, 1, 'hash key with null' )
144     is( $I1, 2, 'almost identical hash key with null' )
145 .end
147 .sub the_same_hash_keys
148     new $P0, 'Hash'
149     set $S0, "Happy"
150     set $S1, "Happy"
152     set $P0[$S0], 1
153     set $I0, $P0[$S0]
154     is( $I0, 1, 'lookup by $S0' )
156     set $P0[$S1], 2
157     set $I1, $P0[$S1]
159     is( $I1, 2, 'set and lookup by $S1 (identical to $S0)' )
160 .end
162 # NB Next test depends on "key2" hashing to zero, which it does with
163 # the current algorithm; if the algorithm changes, change the test!
164 # XXX - really? 
166 .sub key_that_hashes_to_zero
167         new $P0, 'Hash'
168         set $S0, "key2"
169         set $P0[$S0], 1
170         set $I0, $P0[$S0]
172         is( $I0, 1, 'key that hashes to zero XXX' )
173 .end
175 .sub size_of_the_hash
176     new $P0, 'Hash'
178     set $P0["0"], 1
179     set $I0, $P0
180     is( $I0, 1, 'hash size of 1' )
182     set $P0["1"], 1
183     set $I0, $P0
184     is( $I0, 2, 'hash size of 2' )
186     set $P0["0"], 1
187     set $I0, $P0
188     is( $I0, 2, 'hash size of 2' )
189 .end
191 .sub stress_test_loop_set_check
192     new $P0, 'Hash'
194         set $I0, 200
195         set $S0, "mikey"
196         set $P0[$S0], "base"
197         concat $S1, $S0, "s"
198         set $P0[$S1], "bases"
199         set $S2, $I0
200         concat $S1, $S0, $S2
201         set $P0[$S1], "start"
202         set $S3, $P0["mikey"]
203         is( $S3, 'base',  'setup: lookup mikey' )
204         set $S3, $P0["mikeys"]
205         is( $S3, 'bases', 'setup: lookup mikeys' )
206         set $S3, $P0["mikey200"]
207         is( $S3, 'start', 'setup: lookup mikey200' )
208 LOOP:
209         eq $I0, 0, DONE
210         sub $I0, $I0, 1
211         set $S2, $I0
212         concat $S1, $S0, $S2
213         concat $S4, $S0, $S2
214         eq $S1, $S4, L1
215         ##  this should be fail(), but it is not implemented yet
216         ok( 0, 'concat mismatch' )
218         set $P0[$S1], $I0
219         set $I1, $P0[$S1]
220         eq $I0, $I1, L2
221         ##  this should be fail(), but it is not implemented yet
222         ok( 0, 'lookup mismatch' )
224         branch LOOP
225 DONE:
226         set $I0, $P0["mikey199"]
227         is( $I0, 199, 'lookup: mikey199' )
228         set $I0, $P0["mikey117"]
229         is( $I0, 117, 'lookup: mikey117' )
230         set $I0, $P0["mikey1"]
231         is( $I0, 1, 'lookup: mikey1' )
232         set $I0, $P0["mikey23"]
233         is( $I0, 23, 'lookup: miky23' )
234         set $I0, $P0["mikey832"]
235         is( $I0, 0, 'lookup: mikey832 (never set)' )
236 .end
238 ## stuff them in, and check periodically that we can pull selected ones out.
239 ##   *_multiple_keys are used by stress_test_lots_of_keys
241 .sub set_multiple_keys
242     .param pmc hash
243     .param int key_index
244     .param int step
245     .param int count
247 again:
248     if count <= 0 goto ret
249     $S0 = key_index
250     $S1 = concat "key", $S0
251     $S2 = concat "value", $S0
252     hash[$S1] = $S2
253     key_index = key_index + step
254     count = count - 1
255     goto again
256 ret:
257 .end
259 .sub delete_multiple_keys
260     .param pmc hash
261     .param int key_index
262     .param int step
263     .param int count
265 again:
266     if count <= 0 goto ret
267     $S0 = key_index
268     $S1 = concat "key", $S0
269     delete hash[$S1]
270     key_index = key_index + step
271     count = count - 1
272     goto again
273 ret:
274 .end
276 .sub check_key
277     .param pmc hash
278     .param int index
280     $S10 = index
281     $S0 = concat "key", $S10
282     $S1 = concat "value", $S10
284     $S2 = hash[$S0]
285     $S3 = concat "correct value for key ", $S10
286     is( $S2, $S1, $S3 )
287 .end
289 .sub stress_test_lots_of_keys
290     new $P30, 'Hash'
291     $I29 = 1
292     $I30 = 1000
293     $I31 = 1000
295     # round 1
296     set_multiple_keys($P30, $I29, $I30, $I31)
297     check_key( $P30, 1 )
298     check_key( $P30, 1001 )
299     check_key( $P30, 2001 )
301     # round 2
302     $I21 = 100000
303     set_multiple_keys($P30, $I21, $I30, $I31)
304     check_key( $P30, 1 )
305     check_key( $P30, 1001 )
306     check_key( $P30, 2001 )
307     check_key( $P30, 100000 )
308     check_key( $P30, 101000 )
309     check_key( $P30, 102000 )
311     # round 3
312     $I22 = 50000
313     set_multiple_keys($P30, $I22, $I29, $I22)
314     check_key( $P30, 1 )
315     check_key( $P30, 1001 )
316     check_key( $P30, 2001 )
317     check_key( $P30, 500000 )
318     check_key( $P30, 510000 )
319     check_key( $P30, 520000 )
321     # round 4
322     delete_multiple_keys($P30, $I22, $I29, $I22)
323     check_key( $P30, 1001 )
324     check_key( $P30, 2001 )
325     $I50 = exists $P30['key50000']
326     $I51 = exists $P30['key51000']
327     $I52 = exists $P30['key52000']
328     is( $I50, 0, 'key50000 does not exist after delete' )
329     is( $I51, 0, 'key51000 does not exist after delete' )
330     is( $I52, 0, 'key52000 does not exist after delete' )
331 .end
333 # Check all values after setting all of them
334 .sub stress_test_loop_set_loop_check
335     new $P0, 'Hash'
337         set $I0, 200
338         set $S0, "mikey"
339 SETLOOP:
340         eq $I0, 0, DONE
341         sub $I0, $I0, 1
342         set $S2, $I0
343         concat $S1, $S0, $S2
344         set $P0[$S1], $I0
345         branch SETLOOP
347         set $I0, 200
348 GETLOOP:
349         eq $I0, 0, DONE
350         sub $I0, $I0, 1
351         set $S2, $I0
352         concat $S1, $S0, $S2
353         set $I1, $P0[$S1]
354         eq $I0, $I1, L2
355           is( $I0, $I1, 'lookup mismatch in stress test loop' )
356           .return()
358         branch GETLOOP
359 DONE:
360         ok( 1, 'stress test: loop set with loop check' )
361 .end
363 .sub testing_two_hash_indices_with_integers_at_a_time
364       new $P0, 'Hash'
366       set $P0["foo"],37
367       set $P0["bar"],-15
369       set $I0,$P0["foo"]
370       is( $I0, 37, 'lookup int in foo' )
372       set $I0,$P0["bar"]
373       is( $I0, -15, 'lookup int in bar' )
375       set $S1,"foo"
376       set $I0,$P0[$S1]
377       is( $I0,37, 'lookup int in foo via var' )
379       set $S1,"bar"
380       set $I0,$P0[$S1]
381       is( $I0,-15, 'lookup int in bar via var' )
382 .end
384 .sub testing_two_hash_indices_with_numbers_at_a_time
385       new $P0, 'Hash'
387       set $P0["foo"],37.100000
388       set $P0["bar"],-15.100000
390       set $N0,$P0["foo"]
391       is( $N0,37.100000, 'lookup num in foo' )
393       set $N0,$P0["bar"]
394       is( $N0,-15.100000, 'lookup num in bar' )
396       set $S1,"foo"
397       set $N0,$P0[$S1]
398       is( $N0,37.100000, 'lookup num in foo via var' )
400       set $S1,"bar"
401       set $N0,$P0[$S1]
402       is( $N0,-15.100000, 'lookup num in bar via var' )
404 .end
406 .sub testing_two_hash_indices_with_strings_at_a_time
407       new $P0, 'Hash'
409       set $P0["foo"],"baz"
410       set $P0["bar"],"qux"
412       set $S0,$P0["foo"]
413       is( $S0,"baz", 'lookup str in foo' )
415       set $S0,$P0["bar"]
416       is( $S0,"qux", 'lookup str in bar' )
418       set $S1,"foo"
419       set $S0,$P0[$S1]
420       is( $S0,"baz", 'lookup str in foo via var' )
422       set $S1,"bar"
423       set $S0,$P0[$S1]
424       is( $S0,"qux", 'lookup str in bar via var' )
426 .end
428 # So far, we have only used INTVALs, FLOATVALs and STRINGs as values
429 # and/or keys. Now we try PMCs.
431 .sub setting_and_getting_scalar_pmcs
432       new $P0, 'Hash'
433       new $P1, 'Integer'
434       new $P2, 'Integer'
436       set $S0, "non-PMC key"
438       set $P1, 10
439       set $P0[$S0], $P1
440       set $P2, $P0[$S0]
441       is( $P2, $P1, 'lookup PMC Integer' )
443       set $P1, -1234.000000
444       set $P0[$S0], $P1
445       set $P2, $P0[$S0]
446       is( $P2, $P1, 'lookup num after PMC Integer in slot' )
448       set $P1, "abcdefghijklmnopq"
449       set $P0[$S0], $P1
450       set $P2, $P0[$S0]
451       is( $P2, $P1, 'lookup string' )
453       new $P1, 'Undef'
454       set $P0[$S0], $P1
455       set $P2, $P0[$S0]
456       typeof $S1, $P2
457       is( $S1, "Undef", 'lookup Undef PMC' )
459 .end
461 .sub setting_scalar_pmcs_and_getting_scalar_values
462       new $P0, 'Hash'
463       new $P1, 'Integer'
465       set $S0, "A rather large key"
467       set $I0, 10
468       set $P1, $I0
469       set $P0[$S0], $P1
470       set $I1, $P0[$S0]
471       is( $I1, $I0, 'lookup PMC and get scalar Int' )
473       set $N0, -1234.000000
474       set $P1, $N0
475       set $P0[$S0], $P1
476       set $N1, $P0[$S0]
477       is( $N1, $N0, 'lookup PMC and get scalar Num' )
479       set $S1, "abcdefghijklmnopq"
480       set $P1, $S1
481       set $P0[$S0], $P1
482       set $S2, $P0[$S0]
483       is( $S2, $S1, 'lookup PMC and get scalar Str' )
485 .end
487 .sub getting_values_from_undefined_keys
488       new $P2, 'Hash'
490       set $I0, $P2["qwerty"]
491       set $N0, $P2["asdfgh"]
492       set $S0, $P2["zxcvbn"]
493       set $P0, $P2["123456"]
495       is( $I0,   0, 'undefined key returns Int 0' )
496       is( $N0, 0.0, 'undefined key returns Num 0.0' )
497       is( $S0,  "", 'undefined key returns Str ""' )
499       $I1 = 1
500       if_null $P0, P0_is_null
501         $I1 = 0
502     P0_is_null:
503       ok( $I1, 'undefined key returns null PMC' )
504 .end
506 .sub setting_and_getting_non_scalar_pmcs
507         new $P0,'Hash'
508         new $P1,'ResizablePMCArray'
509         new $P2,'ResizablePMCArray'
510         set $P1[4],"string"
511         set $P0["one"],$P1
512         set $P2,$P0["one"]
513         set $S0,$P2[4]
514         is( $S0, 'string', 'set and get non-scalar PMCs' )
515 .end
517 .sub testing_clone
518     new $P0, 'Hash'
519     set $S0, "a"
520     set $P0[$S0], $S0
521     new $P2, 'ResizablePMCArray'
522     set $P2, 2
523     set $P0["b"], $P2
525     # $P0 = { a => "a", b => [undef, undef] }
527     clone $P1, $P0
528     set $P0["c"], 4
529     set $P3, $P0["b"]
530     set $P3, 3
531     set $P0["b"], $P3
532     set $P1["a"], "A"
534     # $P0 = { a => "a", b => [undef, undef, undef], c => 4 }
535     # $P1 = { a => "A", b => [undef, undef] }
537     set $S0, $P0["a"]
538     is( $S0, "a", 'original hash lookup pre-clone value' )
540     set $P5, $P0["b"]
541     set $I0, $P5
542     is( $I0, 3, 'original hash lookup post-clone value' )
544     set $I0, $P0["c"]
545     is( $I0, 4, 'original hash lookup post-clone value in new slot' )
547     set $S0, $P1["a"]
548     is( $S0, "A", 'cloned hash lookup post-clone value' )
550     set $P5, $P1["b"]
551     set $I0, $P5
552     is( $I0, 2, 'cloned hash lookup pre-clone complex value' )
554 # XXX: this should return undef or something, but it dies instead.
555 #     set $P3, $P0["c"]
556 #     unless $P3, ok6
557 #     print "not "
558 # ok6:
559 #     print "ok 6\n"
560 .end
562 .sub compound_keys
563     new $P0, 'Hash'
564     new $P1, 'Hash'
565     new $P2, 'ResizablePMCArray'
566     set $P1["b"], "ab"
567     set $P0["a"], $P1
568     set $S0, $P0["a";"b"]
569     is( $S0, "ab", 'Str from compound key' )
570     
571     set $P2[20], 77
572     set $P1["n"], $P2
573     set $I0, $P0["a";"n";20]
574     is( $I0, 77, 'Int from compound key^2' )
575     
576     set $S0, "a"
577     set $S1, "n"
578     set $I0, 20
579     set $I0, $P0[$S0;$S1;$I0]
580     is( $I0, 77, 'Int from indirect compound key^2' )
581     
582     set $P0["c"], $P2
583     set $P2[33], $P1
584     set $S0, $P0["c";33;"b"]
585     is( $S0, "ab", 'Str from indirect/direct compound key^2' )
586     
587     set $S0, "c"
588     set $I1, 33
589     set $S2, "b"
590     set $S0, $P0[$S0;$I1;$S2]
591     is( $S0, "ab", 'Str from indirect compound key^2' )
592     
593     set $P1["b"], 47.11
594     set $N0, $P0["c";$I1;$S2]
595     is( $N0, 47.11, 'Num from indirect compound key^2' )
596 .end
598 .sub getting_pmcs_from_compound_keys
599     new $P0, 'Hash'
600     new $P1, 'Hash'
601     new $P2, 'Integer'
602     set $P2, 12
603     set $P1["b"], $P2
604     set $P0["a"], $P1
605     set $P3, $P0["a";"b"]
606     set $S0, $P3
607     is( $S0, "12", "lookup PMC from compound key" )
608 .end
609 # 12
611 .sub getting_pmcs_from_string_int_compound_keys
612     new $P0, 'Hash'
613     new $P1, 'Hash'
614     new $P2, 'Integer'
615     set $P2, 4
616     set $P1[9], $P2
617     set $I0, $P1[9]
618     is( $I0, 4, 'lookup Int PMC from hash' )
620     set $P0["a"], $P1
621     set $I0, $P0["a";9]
622     is( $I0, 4, 'lookup Inc PMC from compound hash' )
623 .end
625 # A hash is only false if it has size 0
627 .sub if_hash
628     new $P0, 'Hash'
630     ## Could just use Test::More tests directly, but then we are really 
631     ## checking casting to Int then testing value (I think)
632     ## ie. ok( $P0, '...' )
634     $I1 = 0
635     if $P0, L1
636       $I1 = 1
637   L1:
638     ok( $I1, 'Empty hash is false' )
640     set $P0["key"], "value"
641     $I1 = 1
642     if $P0, L2
643       $I1 = 0
644   L2:
645     ok( $I1, 'Hash with one slot is true' )
647     set $P0["key"], ""
648     $I1 = 1
649     if $P0, L3
650       $I1 = 0
651   L3:
652     ok( $I1, 'Hash with one value ("") is true' )
654     new $P1, 'Undef'
655     set $P0["key"], $P1
656     $I1 = 1
657     if $P0, L4
658       $I1 = 0
659   L4:
660     ok( $P0, 'Hash with one value (Undef PMC) is true' )
662 .end
664 .sub unless_hash
665     new $P0, 'Hash'
667     $I0 = 1
668     unless $P0, L1
669       $I0 = 0
670   L1:
671     ok( $I0, 'Empty hash is false in unless' )
673     $I0 = 0
674     set $P0["key"], "value"
675     unless $P0, L2
676       $I0 = 1
677   L2:
678     ok( $I0, 'Hash with one value is true' )
680     $I0 = 0
681     set $P0["key"], "\0"
682     unless $P0, L3
683       $I0 = 1
684   L3:
685     ok( $I0, 'Hash with one value ("\0") is true' )
687     $I0 = 0
688     new $P1, 'Undef'
689     set $P0["key"], $P1
690     unless $P0, L4
691       $I0 = 1
692   L4:
693     ok( $I0, 'Hash with one value (Undef PMC) is true' )
695 .end
697 .sub defined_hash
698     new $P0, 'Hash'
700     defined $I0, $P0
701     ok( $I0, 'Empty has is defined' )
703     ## nok() had not been (correctly) implemented when this test was written
705     defined $I0, $P1
706     $I0 = not $I0
707     ok( $I1, 'Unassigned var is undefined' )
709     set $P0["a"], 1
710     defined $I0, $P0["a"]
711     ok( $I0, 'Int in hash value is defined' )
713     defined $I0, $P0["b"]
714     $I0 = not $I0
715     ok( $I0, 'Unassigned hash slot is undefined' )
717     new $P1, 'Undef'
718     set $P0["c"], $P1
719     defined $I0, $P0["c"]
720     $I0 = not $I0
721     ok( $I0, 'Undef PMC in hash slot is undefined' )
722 .end
724 .sub exists_hash_key
725     new $P0, 'Hash'
727     set $P0["a"], 1
728     exists $I0, $P0["a"]
729     ok( $I0, 'assigned hash key exists' )
730     
731     exists $I0, $P0["b"]
732     $I0 = not $I0
733     ok( $I0, 'unassigned hash key does not exist' )
734     
735     new $P1, 'Undef'
736     set $P0["c"], $P1
737     exists $I0, $P0["c"]
738     ok( $I0, 'hash key assigned Undef PMC exists' )
739 .end
741 .sub delete_hash_key
742     new $P0, 'Hash'
744     set $P0["a"], 1
745     exists $I0, $P0["a"]
746     ok( $I0, 'assigned hash key exists' )
747    
748     delete $P0["a"]
749     exists $I0, $P0["a"]
750     $I0 = not $I0
751     ok( $I0, 'delete hash key does not exist' )
752 .end
754 .sub cloning_keys
755     new $P10, 'Hash'
756     new $P1, 'Key'
758     set $P1, "Bar"
759     set $P10[$P1], "Food"
760     clone $P2, $P1
761     set $S0, $P10[$P2]
762     is( $S0, "Food", 'cloned key looks up same value' )
764     set $S1, "Baa"
765     set $P10[$S1], "Sheep"
766     clone $S2, $S1
767     set $S0, $P10[$S2]
768     is( $S0, "Sheep", 'cloned key again look up same value' )
769 .end
771 .sub cloning_pmc_vals
772     new $P10, 'Hash'
774     new $P1, 'Undef'
775     set $P1, "value"
776     set $P10["str"], $P1
778     new $P1, 'Undef'
779     set $P1, 42
780     set $P10["int"], $P1
782     clone $P2, $P10
783     set $P0, $P2["int"]
784     is( $P0, 42, 'cloned hash contained pre-clone set int' )
785     set $P0, $P2["str"]
786     is( $P0, 'value', 'cloned hash contains pre-clone set str' )
787 .end
789 .sub entry_types_type_keyed
790     ## XXX is there any concern that including this will impact other tests?
791     .include "pmctypes.pasm"
792     new $P1, 'Hash'
794     new $P2, 'Integer'
795     set $P1["Integer"], $P2
796     typeof $I0, $P1["Integer"]
797     is( $I0, .Integer, 'entry type is Integer' )
799     new $P3, 'Integer'
800     set $P1["Integer"], $P3
801     typeof $I0, $P1["Integer"]
802     is( $I0, .Integer, 'entry type is Integer' )
804     set $P1["native int"], -123456
805     typeof $I0, $P1["native int"]
806     is( $I0, .Integer, 'entry type is Integer' )
808     set $P1["native float"], -123.456
809     typeof $I0, $P1["native float"]
810     is( $I0, .Float, 'entry type is Float' )
812     set $P1["native string"], "hello world\n"
813     typeof $I0, $P1["native string"]
814     is( $I0, .String, 'entry type is String' )
816 .end
818 .sub delete_and_free_list
819     set $I2, 10
820     set $I1, 1
821     new $P0, 'SArray'
822     set $P0, 1
823     new $P1, 'Hash'
824 outer:
825     set $P0[0], $I1
826     sprintf $S0, "ok %vd\n", $P0
827     set $P1[$S0], $S0
829     ## set $P1[key]=1 then delete it 100 times
830     set $I0, 100
832     set $P1["key"], 1
833     delete $P1["key"]
834     dec $I0
835     if $I0, lp
837     set $S1, $P1[$S0]
838     # print $S1
839     inc $I1
840     le $I1, $I2, outer
842     set $I0, $P1
843     is( $I0, 10, 'hash has size 10' )
844 .end
846 ## XXX already tested?
847 .sub exists_with_constant_string_key
848     new $P16, 'Hash'
850     set $P16["key1"], "value for key1"
851     set $S16, $P16["key1"]
852     is( $S16, "value for key1" , 'set and lookup value for const str key' )
854     exists $I17, $P16["key1"]
855     ok( $I17, 'exists with constant string key' )
857     exists $I17, $P16["no such"]
858     $I17 = not $I17
859     ok( $I17, 'does not exist with unassigned const string key' )
860 .end
862 .sub hash_in_pir
863     .local pmc hash1
864     hash1 = new 'Hash'
865     hash1['X'] = 'U'
866     .local string val1
867     val1 = hash1['X']
868     is( val1, "U", 'hash in PIR' )
869 .end
871 .sub setting_with_compound_keys
872     .local pmc outer_hash
873     outer_hash = new 'Hash'
874     .local pmc inner_hash
875     inner_hash = new 'Hash'
876     .local pmc inner_array
877     inner_array = new 'ResizablePMCArray'
878     .local string elem_string
879     .local int    elem_int
880     .local pmc    elem_pmc
881     .local num    elem_num
883     # setting and retrieving strings in an inner ResizablePMCArray
884     inner_array[128] = 'inner_array:128'
885     outer_hash['inner_array'] = inner_array
886     elem_string = outer_hash['inner_array';128]
887     is( elem_string, 'inner_array:128', 'string in inner ResizeablePMCArray' )
888     outer_hash['inner_array';128] = 'changed inner_array:128'
889     elem_string = outer_hash['inner_array';128]
890     is( elem_string, 'changed inner_array:128', 'string in inner ResizeablePMCArray' )
892     # setting and retrieving strings in an inner Hash
893     inner_hash['129'] = 'inner_hash:129'
894     outer_hash['inner_hash'] = inner_hash
895     elem_string = outer_hash['inner_hash';'129']
896     is( elem_string, 'inner_hash:129', 'string in inner Hash' )
897     outer_hash['inner_hash';'129'] = 'changed inner_hash:129'
898     elem_string = outer_hash['inner_hash';'129']
899     is( elem_string, 'changed inner_hash:129', 'string in inner Hash' )
901     # setting and retrieving integer in an inner ResizablePMCArray
902     inner_array[130] = 130
903     outer_hash['inner_array'] = inner_array
904     elem_int = outer_hash['inner_array';130]
905     is( elem_int, 130, 'int in inner ResizablePMCArray' )
906     outer_hash['inner_array';130] = -130
907     elem_int = outer_hash['inner_array';130]
908     is( elem_int, -130, 'int in inner ResizablePMCArray' )
910     # setting and retrieving integer in an inner Hash
911     inner_hash['131'] = 131
912     outer_hash['inner_hash'] = inner_hash
913     elem_int = outer_hash['inner_hash';'131']
914     is( elem_int, 131, 'int in inner Hash' )
915     outer_hash['inner_hash';'131'] = -131
916     elem_int = outer_hash['inner_hash';'131']
917     is( elem_int, -131, 'int in inner Hash' )
919     # setting and retrieving a PMC in an inner ResizablePMCArray
920     .local pmc in_pmc
921     in_pmc = new 'String'
922     in_pmc = 'inner_array:132'
923     inner_array[132] = in_pmc
924     outer_hash['inner_array'] = inner_array
925     elem_pmc = outer_hash['inner_array';132]
926     is( elem_pmc, 'inner_array:132', 'PMC in inner ResizablePMCArray' )
927     in_pmc = 'changed inner_array:132'
928     outer_hash['inner_array';132] = in_pmc
929     elem_pmc = outer_hash['inner_array';132]
930     is( elem_pmc, 'changed inner_array:132', 'PMC in inner ResizablePMCArray' )
932     # setting and retrieving a PMC in an inner Hash
933     in_pmc = 'inner_array:133'
934     inner_hash['133'] = in_pmc
935     outer_hash['inner_hash'] = inner_hash
936     elem_string = outer_hash['inner_hash';'133']
937     is( elem_string, 'inner_array:133', 'PMC in inner Hash' )
938     in_pmc = 'changed inner_hash:133'
939     outer_hash['inner_hash';'133'] = in_pmc
940     elem_string = outer_hash['inner_hash';'133']
941     is( elem_string, 'changed inner_hash:133', 'PMC in inner Hash' )
943     # setting and retrieving a float in an inner ResizablePMCArray
944     inner_array[134] = 134.134
945     outer_hash['inner_array'] = inner_array
946     elem_num = outer_hash['inner_array';134]
947     is( elem_num, 134.134000, 'float in inner ResizablePMCArray' )
948     outer_hash['inner_array';134] = -134.134
949     elem_num = outer_hash['inner_array';134]
950     is( elem_num, -134.134000, 'float in inner ResizablePMCArray' )
952     # setting and retrieving a float in an inner Hash
953     inner_hash['135'] = 135.135
954     outer_hash['inner_hash'] = inner_hash
955     elem_num = outer_hash['inner_hash';'135']
956     is( elem_num, 135.135000, 'float in inner Hash' )
957     outer_hash['inner_hash';'135'] = -135.135
958     elem_num = outer_hash['inner_hash';'135']
959     is( elem_num, -135.135000, 'float in inner Hash' )
961 .end
963 .sub mutating_the_lookup_string
964     new $P0, 'Hash'
965     set $P0["a"], "one"
966     set $P0["ab"], "two"
967     set $P0["abc"], "three"
969     set $S0, "a"
970     set $S1, $P0[$S0]
971     is( $S1, "one", 'lookup via str in reg' )
973     concat $S0, "b"
974     set $S1, $P0[$S0]
975     is( $S1, "two", 'lookup via concated str in reg' )
977     concat $S0, "c"
978     set $S1, $P0[$S0]
979     is( $S1, "three", 'lookup via concated^2 str in reg' )
980 .end
982 .sub check_whether_interface_is_done
983     .local pmc pmc1
984     pmc1 = new 'Hash'
985     .local int bool1
987     does bool1, pmc1, "scalar"
988     bool1 = not bool1
989     ok( bool1, 'Hash PMC does not do scalar' )
991     does bool1, pmc1, "hash"
992     ok( bool1, 'Hash PMC does hash' )
993     
994     does bool1, pmc1, "no_interface"
995     bool1 = not bool1
996     ok( bool1, 'Hash PMC does not do no_interface' )
997 .end
999 .sub iter_over_hash
1000     new $P0, 'Hash'
1001     set $P0['a'], 'x'
1003     iter $P1, $P0
1004     $I0 = 1
1005     if $P1 goto L1
1006       $I0 = 0
1007   L1:
1008     ok( $I0, 'iterator is true' )
1010     shift $P2, $P1
1011     is( $P2, 'a', 'shifting iterator give the key' )
1013     $I0 = 0
1014     if $P1 goto L2
1015       $I0 = 1
1016   L2:
1017     ok( $I0, 'iterator is now false' )
1018 .end
1020 ## thx to azuroth on irc
1021 .sub broken_delete
1022   .include "iterator.pasm"
1023   .local string result
1024   result = ""
1026   .local pmc thash
1028   # just put in some dummy data...
1029   thash = new 'Hash'
1030   thash["a"] = "b"
1031   thash["c"] = "d"
1032   thash["e"] = "f"
1034   .local pmc iter
1035   iter = new 'Iterator', thash
1036   iter = .ITERATE_FROM_START
1038   .local string key
1040   # go through the hash, print out all the keys: should be a c and e
1041 preit_loop:
1042   unless iter goto preit_end
1044   key = shift iter
1045   result .= key
1047   branch preit_loop
1048 preit_end:
1050   is( result, 'ace', 'iterated through keys successfully' )
1052   # get rid of the c element?
1053   delete thash["c"]
1055   # what do we have after deletion?
1056   result = ""
1058   iter = new 'Iterator', thash
1059   iter = .ITERATE_FROM_START
1061   # go through the hash, print out all the keys... I believe it should be a and e?
1062   # it actually outputs a, c and e.
1063 postit_loop:
1064   unless iter goto postit_end
1066   key = shift iter
1067   result .= key
1069   branch postit_loop
1070 postit_end:
1072   is( result, 'ae', 'the c key was no longer iterated over' )
1073 .end
1075 .sub unicode_keys_register_rt_39249
1076   $P1 = new 'Hash'
1078   $S99 = unicode:"\u7777"
1079   $P1[$S99] = "ok"
1080   $S1 = $P1[$S99]
1081   is( $S1, 'ok', 'unicode key' )
1082 .end
1084 .sub unicode_keys_literal_rt_39249
1085   $P1 = new 'Hash'
1087   $P1[unicode:"\u7777"] = "ok"
1088   $S1 = $P1[unicode:"\u7777"]
1089   is( $S1, 'ok', 'literal unicode key' )
1091   $S2 = unicode:"\u7777"
1092   $S1 = $P1[$S2]
1093   is( $S1, 'ok', 'literal unicode key lookup via var' )
1094 .end
1096 # Local Variables:
1097 #   mode: pir
1098 #   fill-column: 100
1099 # End:
1100 # vim: expandtab shiftwidth=4 ft=pir: