# New Ticket Created by  Ion Alexandru Morega 
# Please include the string:  [perl #30528]
# in the subject line of all future correspondence about this issue. 
# <URL: http://rt.perl.org:80/rt3/Ticket/Display.html?id=30528 >


This is the latest version of the String PMC, complete with iterators.

In my understanding, the default implementation of morph() would check 
if the new class number is the same as the old one, and if it isn't then 
it would destroy the pmc and create a new one. For some reason this 
default method is sometimes not found (resulting in "morph() not 
implemented" errors). Am I wrong or is this a bug?

alexm

--- parrot/t/pmc/string.t	Thu Jun 24 13:50:54 2004
+++ my_parrot/t/pmc/string.t	Mon Jun 28 12:09:36 2004
@@ -8,7 +8,7 @@
 
 =head1 SYNOPSIS
 
-	% perl t/pmc/string.t
+    % perl t/pmc/string.t
 
 =head1 DESCRIPTION
 
@@ -16,92 +16,89 @@
 
 =cut
 
-use Parrot::Test tests => 30;
+use Parrot::Test tests => 32;
 use Test::More; # Included for skip().
 
 my $fp_equality_macro = <<'ENDOFMACRO';
 .macro fp_eq ( J, K, L )
-	save	N0
-	save	N1
-	save	N2
-
-	set	N0, .J
-	set	N1, .K
-	sub	N2, N1,N0
-	abs	N2, N2
-	gt	N2, 0.000001, .$FPEQNOK
-
-	restore N2
-	restore	N1
-	restore	N0
-	branch	.L
+    save	N0
+    save	N1
+    save	N2
+
+    set	N0, .J
+    set	N1, .K
+    sub	N2, N1,N0
+    abs	N2, N2
+    gt	N2, 0.000001, .$FPEQNOK
+
+    restore N2
+    restore	N1
+    restore	N0
+    branch	.L
 .local $FPEQNOK:
-	restore N2
-	restore	N1
-	restore	N0
+    restore N2
+    restore	N1
+    restore	N0
 .endm
 .macro fp_ne ( J, K, L )
-	save	N0
-	save	N1
-	save	N2
-
-	set	N0, .J
-	set	N1, .K
-	sub	N2, N1,N0
-	abs	N2, N2
-	lt	N2, 0.000001, .$FPNENOK
-
-	restore	N2
-	restore	N1
-	restore	N0
-	branch	.L
+    save	N0
+    save	N1
+    save	N2
+
+    set	N0, .J
+    set	N1, .K
+    sub	N2, N1,N0
+    abs	N2, N2
+    lt	N2, 0.000001, .$FPNENOK
+
+    restore	N2
+    restore	N1
+    restore	N0
+    branch	.L
 .local $FPNENOK:
-	restore	N2
-	restore	N1
-	restore	N0
+    restore	N2
+    restore	N1
+    restore	N0
 .endm
 ENDOFMACRO
 
-output_is(<<CODE, <<OUTPUT, "Set/get strings");
+output_is(<<'CODE', <<'OUTPUT', "Set/get strings");
         new P0, .String
         set P0, "foo"
         set S0, P0
         eq S0, "foo", OK1
         print "not "
-OK1:    print "ok 1\\n"
+OK1:    print "ok 1\n"
 
         set P0, "\0"
         set S0, P0
         eq S0, "\0", OK2
         print "not "
-OK2:    print "ok 2\\n"
+OK2:    print "ok 2\n"
 
         set P0, ""
         set S0, P0
         eq S0, "", OK3
         print "not "
-OK3:    print "ok 3\\n"
+OK3:    print "ok 3\n"
 
         set P0, 123
         set S0, P0
         eq S0, "123", OK4
         print "not "
-OK4:    print "ok 4\\n"
+OK4:    print "ok 4\n"
 
-# XXX: can't handle double yet - string_from_num() in src/string.c
-#        set P0, 1.23456789
-#        print P0
-#        set S0, P0
-#        print S0
-#        eq S0, "1.23456789", OK5
-#        print "not "
-OK5:    print "ok 5\\n"
+        set P0, 1.2345
+        set S0, P0
+        eq S0, "1.2345", OK5
+        print "not "
+OK5:    print "ok 5\n"
 
         set P0, "0xFFFFFF"
         set S0, P0
         eq S0, "0xFFFFFF", OK6
         print "not "
-OK6:    print "ok 6\\n"
+OK6:    print "ok 6\n"
 
         end
 CODE
@@ -113,38 +110,38 @@
 ok 6
 OUTPUT
 
-output_is(<<CODE, <<OUTPUT, "Setting integers");
-        new P0, .String
-        set P0, "1"
-        set I0, P0
-        print I0
-        print "\\n"
+output_is(<<'CODE', <<'OUTPUT', "Setting integers");
+    new P0, .String
+    set P0, "1"
+    set I0, P0
+    print I0
+    print "\n"
 
-        new P0, .String
-        set P0, "2.0"
-        set I0, P0
-        print I0
-        print "\\n"
+    new P0, .String
+    set P0, "2.0"
+    set I0, P0
+    print I0
+    print "\n"
 
-        new P0, .String
-        set P0, ""
-        set I0, P0
-        print I0
-        print "\\n"
+    new P0, .String
+    set P0, ""
+    set I0, P0
+    print I0
+    print "\n"
 
-        new P0, .String
-        set P0, "\0"
-        set I0, P0
-        print I0
-        print "\\n"
+    new P0, .String
+    set P0, "\0"
+    set I0, P0
+    print I0
+    print "\n"
 
-        new P0, .String
-        set P0, "foo"
-        set I0, P0
-        print I0
-        print "\\n"
+    new P0, .String
+    set P0, "foo"
+    set I0, P0
+    print I0
+    print "\n"
 
-        end
+    end
 CODE
 1
 2
@@ -153,7 +150,7 @@
 0
 OUTPUT
 
-output_is(<<"CODE", <<OUTPUT, "Setting numbers");
+output_is(<<"CODE", <<'OUTPUT', "Setting numbers");
 @{[ $fp_equality_macro ]}
         new P0, .String
         set P0, "1"
@@ -177,7 +174,7 @@
 OK3:    print "ok 3\\n"
 
         new P0, .String
-        set P0, "\0"
+        set P0, "\\0"
         set N0, P0
         .fp_eq(N0, 0.0, OK4)
         print "not "
@@ -207,30 +204,29 @@
 ok 6
 OUTPUT
 
-output_is(<<CODE, <<OUTPUT, "ensure that concat ppp copies strings");
-	new P0, .String
-	new P1, .String
-	new P2, .String
-	set P0, "foo"
-	concat	P1, P0, P0
-
-	print	P0
-	print "\\n"
+output_is(<<'CODE', <<'OUTPUT', "ensure that concat ppp copies strings");
+    new P0, .String
+    new P1, .String
+    new P2, .String
+    set P0, "foo"
+    concat	P1, P0, P0
 
-	print	P1
-	print "\\n"
+    print	P0
+    print "\n"
+    print	P1
+    print "\n"
 
-	set P1, "You can't teach an old dog new..."
-	set P2, "clear physics"
-	concat P0, P1, P2
+    set P1, "You can't teach an old dog new..."
+    set P2, "clear physics"
+    concat P0, P1, P2
 
-	print P1
-	print "\\n"
-	print P2
-	print "\\n"
-	print P0
-	print "\\n"
-	end
+    print P1
+    print "\n"
+    print P2
+    print "\n"
+    print P0
+    print "\n"
+    end
 CODE
 foo
 foofoo
@@ -239,91 +235,91 @@
 You can't teach an old dog new...clear physics
 OUTPUT
 
-output_is(<<CODE, <<OUTPUT, "ensure that concat pps copies strings");
-	new P0, .String
-	new P1, .String
+output_is(<<'CODE', <<'OUTPUT', "ensure that concat pps copies strings");
+    new P0, .String
+    new P1, .String
 
-	set S0, "Grunties"
-	set P1, "fnargh"
-	concat P0, P1, S0
+    set S0, "Grunties"
+    set P1, "fnargh"
+    concat P0, P1, S0
 
-	print S0
-	print "\\n"
-	print P1
-	print "\\n"
-	print P0
-	print "\\n"
+    print S0
+    print "\n"
+    print P1
+    print "\n"
+    print P0
+    print "\n"
 
-	end
+    end
 CODE
 Grunties
 fnargh
 fnarghGrunties
 OUTPUT
 
-output_is(<<CODE, <<OUTPUT, "Setting string references");
-	new P0, .String
-	set S0, "C2H5OH + 10H20"
-	set P0, S0
-	chopn S0, 8
+output_is(<<'CODE', <<'OUTPUT', "Setting string references");
+    new P0, .String
+    set S0, "C2H5OH + 10H20"
+    set P0, S0
+    chopn S0, 8
 
-	print S0
-	print "\\n"
-	print P0
-	print "\\n"
-	end
+    print S0
+    print "\n"
+    print P0
+    print "\n"
+    end
 CODE
 C2H5OH
 C2H5OH
 OUTPUT
 
-output_is(<<CODE, <<OUTPUT, "Assigning string copies");
-	new P0, .String
-	set S0, "C2H5OH + 10H20"
-	assign P0, S0
-	chopn S0, 8
+output_is(<<'CODE', <<'OUTPUT', "Assigning string copies");
+    new P0, .String
+    set S0, "C2H5OH + 10H20"
+    assign P0, S0
+    chopn S0, 8
 
-	print S0
-	print "\\n"
-	print P0
-	print "\\n"
-	end
+    print S0
+    print "\n"
+    print P0
+    print "\n"
+    end
 CODE
 C2H5OH
 C2H5OH + 10H20
 OUTPUT
 
-output_is(<<'CODE', <<OUTPUT, "repeat");
-	new P0, .String
-	set P0, "x"
-	new P1, .Integer
-	set P1, 12
-	new P2, .String
-	repeat P2, P0, P1
-        print P2
-        print "\n"
+output_is(<<'CODE', <<'OUTPUT', "repeat");
+    new P0, .String
+    set P0, "x"
+    new P1, .Integer
+    set P1, 12
+    new P2, .String
+    repeat P2, P0, P1
+    print P2
+    print "\n"
 
-        set P0, "y"
-        new P1, .Float
-        set P1, 6.5
-        repeat P2, P0, P1
-        print P2
-        print "\n"
+    set P0, "y"
+    new P1, .Float
+    set P1, 6.5
+    repeat P2, P0, P1
+    print P2
+    print "\n"
 
-        set P0, "z"
-        new P1, .String
-        set P1, "3"
-        repeat P2, P0, P1
-        print P2
-        print "\n"
+    set P0, "z"
+    new P1, .String
+    set P1, "3"
+    repeat P2, P0, P1
+    print P2
+    print "\n"
 
-        set P0, "a"
-        new P1, .Undef
-        repeat P2, P0, P1
-        print P2
-        print "\n"
+    set P0, "a"
+    new P1, .Undef
+    repeat P2, P0, P1
+    print P2
+    print "\n"
 
-	end
+    end
 CODE
 xxxxxxxxxxxx
 yyyyyy
@@ -331,36 +327,36 @@
 
 OUTPUT
 
-output_is(<<'CODE', <<OUTPUT, "repeat_int");
-	new P0, .String
-	set P0, "x"
-	set I1, 12
-	new P2, .String
-	repeat P2, P0, I1
-        print P2
-        print "\n"
+output_is(<<'CODE', <<'OUTPUT', "repeat_int");
+    new P0, .String
+    set P0, "x"
+    set I1, 12
+    new P2, .String
+    repeat P2, P0, I1
+    print P2
+    print "\n"
 
-        set P0, "za"
-        set I1, 3
-        repeat P2, P0, I1
-        print P2
-        print "\n"
-	end
+    set P0, "za"
+    set I1, 3
+    repeat P2, P0, I1
+    print P2
+    print "\n"
+    end
 CODE
 xxxxxxxxxxxx
 zazaza
 OUTPUT
 
 
-output_is(<<CODE, <<OUTPUT, "if(String)");
+output_is(<<'CODE', <<'OUTPUT', "get_bool");
         new P0, .String
-	set S0, "True"
-	set P0, S0
+        set S0, "True"
+        set P0, S0
         if P0, TRUE
         print "false"
         branch NEXT
 TRUE:   print "true"
-NEXT:   print "\\n"
+NEXT:   print "\n"
 
         new P1, .String
         set S1, ""
@@ -369,7 +365,7 @@
         print "false"
         branch NEXT2
 TRUE2:  print "true"
-NEXT2:  print "\\n"
+NEXT2:  print "\n"
 
         new P2, .String
         set S2, "0"
@@ -378,7 +374,7 @@
         print "false"
         branch NEXT3
 TRUE3:  print "true"
-NEXT3:  print "\\n"
+NEXT3:  print "\n"
 
         new P3, .String
         set S3, "0123"
@@ -387,14 +383,14 @@
         print "false"
         branch NEXT4
 TRUE4:  print "true"
-NEXT4:  print "\\n"
+NEXT4:  print "\n"
 
         new P4, .String
         if P4, TRUE5
         print "false"
         branch NEXT5
 TRUE5:  print "true"
-NEXT5:  print "\\n"
+NEXT5:  print "\n"
         end
 CODE
 true
@@ -404,117 +400,49 @@
 false
 OUTPUT
 
-# XXX unimplemented ops... should remove tests
+output_is(<<'CODE', <<'OUTPUT', "concat");
+    new P0, .String
+    new P1, .Undef
+    set P0, "foo"
+    concat	P1, P0, P0
 
-## XXX these tests better should get generated
-##     with all combinations of params and ops
-#output_is(<<'CODE', <<OUTPUT, "add str_int, str_int");
-#	new P0, .String
-#	set P0, "23"
-#	new P1, .String
-#	set P1, "2"
-#	new P2, .Undef
-#	add P2, P0, P1
-#	print P2
-#	print "\n"
-#	end
-#CODE
-#25
-#OUTPUT
-
-#output_is(<<"CODE", <<OUTPUT, "add str_int, str_num");
[EMAIL PROTECTED] $fp_equality_macro ]}
-# 	new P0, .String
-# 	set P0, "23"
-# 	new P1, .String
-# 	set P1, "2.5"
-# 	new P2, .Undef
-# 	add P2, P0, P1
-#         .fp_eq(P2, 25.5, EQ1)
-#         print "not "
-# EQ1:    print "ok 1\\n"
-# 	end
-# CODE
-# ok 1
-# OUTPUT
-
-# output_is(<<'CODE', <<OUTPUT, "add str_int, int");
-# 	new P0, .String
-# 	set P0, "23"
-# 	new P1, .Integer
-# 	set P1, 2
-# 	new P2, .Undef
-# 	add P2, P0, P1
-# 	print P2
-# 	print "\n"
-# 	end
-# CODE
-# 25
-# OUTPUT
-
-# output_is(<<"CODE", <<OUTPUT, "add str_int, num");
-# @{[ $fp_equality_macro ]}
-# 	new P0, .String
-# 	set P0, "23"
-# 	new P1, .Float
-# 	set P1, 2.5
-# 	new P2, .Undef
-# 	add P2, P0, P1
-#         .fp_eq(P2, 25.5, EQ1)
-#         print "not "
-# EQ1:    print "ok 1\\n"
-# 	end
-# CODE
-# ok 1
-# OUTPUT
-
-# output_is(<<"CODE", <<OUTPUT, "add str_num, int");
-# @{[ $fp_equality_macro ]}
-# 	new P0, .String
-# 	set P0, "23.5"
-# 	new P1, .Integer
-# 	set P1, 2
-# 	new P2, .Undef
-# 	add P2, P0, P1
-#         .fp_eq(P2, 25.5, EQ1)
-#         print "not "
-# EQ1:    print "ok 1\\n"
-# 	end
-# CODE
-# ok 1
-#OUTPUT
+    print	P0
+    print "\n"
+    print	P1
+    print "\n"
 
-output_is(<<'CODE', <<OUTPUT, "concat");
-	new P0, .String
-	new P1, .Undef
-	set P0, "foo"
-	concat	P1, P0, P0
+    new P0, .String
+    new P1, .Undef
+    set P0, "bar"
+    concat	P0, P0, P1
 
-	print	P0
-	print "\n"
-	print	P1
-	print "\n"
+    print	P0
+    print "\n"
+    print	P1
+    print "\n"
 
-	new P0, .String
-	new P1, .Undef
-	set P0, "bar"
-	concat	P0, P0, P1
+    new P0, .String
+    new P1, .Undef
+    set P1, "str"
+    concat	P1, P0, P1
 
-	print	P0
-	print "\n"
-	print	P1
-	print "\n"
+    print	P0
+    print "\n"
+    print	P1
+    print "\n"
 
-	new P0, .String
-	new P1, .Undef
-	set P1, "str"
-	concat	P1, P0, P1
+    new P0, .String
+    new P1, .String
+    set P0, "abc"
+    set S0, "def"
+    concat P1, P0, S0
 
-	print	P0
-	print "\n"
-	print	P1
-	print "\n"
-	end
+    print P0
+    print "\n"
+    print P1
+    print "\n"
+
+    end
 CODE
 foo
 foofoo
@@ -522,155 +450,183 @@
 
 
 str
+abc
+abcdef
 OUTPUT
 
-output_is(<<'CODE', <<OUTPUT, "cmp");
+output_is(<<'CODE', <<'OUTPUT', "cmp with string");
 	new P1, .String
-	new P2, .String
 
-        set P1, "abc"
-        set P2, "abc"
-        cmp I0, P1, P2
-        print I0
-        print "\n"
+	set P1, "abc"
+    set S1, "abc"
+    cmp I0, P1, S1
+    print I0
+    print "\n"
 
-        set P1, "abcde"
-        set P2, "abc"
-        cmp I0, P1, P2
-        print I0
-        print "\n"
+    set P1, "abcde"
+    set S1, "abc"
+    cmp I0, P1, S1
+    print I0
+    print "\n"
 
-        set P1, "abc"
-        set P2, "abcde"
-        cmp I0, P1, P2
-        print I0
-        print "\n"
+    set P1, "abc"
+    set S1, "abcde"
+    cmp I0, P1, S1
+    print I0
+    print "\n"
 
-        end
+    end
 CODE
 0
 1
 -1
 OUTPUT
 
-output_is(<<'CODE', <<OUTPUT, "cmp with Integer");
-	new P1, .Integer
-	new P2, .String
-        set P2, "10"
+output_is(<<'CODE', <<'OUTPUT', "cmp with num");
+	new P1, .String
+    set P1, "10"
 
-# Int. vs Str.
-        set P1, 10
-        cmp I0, P1, P2
-        print I0
-        print "\n"
+    set N1, 0.0
+    cmp I0, P1, N1
+    print I0
+    print "\n"
 
-        set P1, 20
-        cmp I0, P1, P2
-        print I0
-        print "\n"
+    set N1, 20.0
+    cmp I0, P1, N1
+    print I0
+    print "\n"
 
-        set P1, 0
-        cmp I0, P1, P2
-        print I0
-        print "\n"
+    set N1, 10.0
+    cmp I0, P1, N1
+    print I0
+    print "\n"
 
-# Str. vs Int.
-        set P1, 0
-        cmp I0, P2, P1
-        print I0
-        print "\n"
+CODE
+1
+-1
+0
+OUTPUT
 
-        set P1, 20
-        cmp I0, P2, P1
-        print I0
-        print "\n"
+output_is(<<'CODE', <<'OUTPUT', "cmp with PMC");
+	new P1, .String
+	new P2, .Integer
+	new P3, .String
+    set P1, "10"
 
-        set P1, 10
-        cmp I0, P2, P1
-        print I0
-        print "\n"
+# String vs Integer
+    set P2, 0
+    cmp I0, P1, P2
+    print I0
+    print "\n"
 
-        end
+    set P2, 20
+    cmp I0, P1, P2
+    print I0
+    print "\n"
+
+    set P2, 10
+    cmp I0, P1, P2
+    print I0
+    print "\n"
+
+# String vs String
+    set P1, "abcd"
+    set P3, "abcde"
+    cmp I0, P1, P3
+    print I0
+    print "\n"
+
+    set P3, "abcd"
+    cmp I0, P1, P3
+    print I0
+    print "\n"
+
+    set P3, "abca"
+    cmp I0, P1, P3
+    print I0
+    print "\n"
+
+    end
 CODE
-0
 1
 -1
-1
+0
 -1
 0
+1
 OUTPUT
 
-output_is(<<'CODE', <<OUTPUT, "substr");
-        new P0, .String
-        set P0, "This is a test\n"
-        substr S0, P0, 0, 5
-        substr S1, P0, 10, 4
-        substr S2, P0, -11, 3
-        substr S3, P0, 7, 1000  # Valid offset, but length > string length
-        print S0
-        print S1
-        print S2
-        print S3
-        print P0 # Check that the original is unmodified
-        end
+output_is(<<'CODE', <<'OUTPUT', "substr");
+    new P0, .String
+    set P0, "This is a test\n"
+    substr S0, P0, 0, 5
+    substr S1, P0, 10, 4
+    substr S2, P0, -11, 3
+    substr S3, P0, 7, 1000  # Valid offset, but length > string length
+    print S0
+    print S1
+    print S2
+    print S3
+    print P0 # Check that the original is unmodified
+    end
 CODE
 This test is a test
 This is a test
 OUTPUT
 
 output_like(<<'CODE', <<'OUTPUT', "Out-of-bounds substr, +ve offset");
-        new P0, .String
-        set P0, "Woburn"
-        substr S0, P0, 123, 22
-        end
+    new P0, .String
+    set P0, "Woburn"
+    substr S0, P0, 123, 22
+    end
 CODE
 /^Cannot take substr outside string$/
 OUTPUT
 
 output_like(<<'CODE', <<'OUTPUT', "Out-of-bounds substr, -ve offset");
-        new P0, .String
-        set P0, "Woburn"
-        substr S0, P0, -123, 22
-        end
+    new P0, .String
+    set P0, "Woburn"
+    substr S0, P0, -123, 22
+    end
 CODE
 /^Cannot take substr outside string$/
 OUTPUT
 
-output_is( <<'CODE', <<OUTPUT, "bands NULL string");
+output_is( <<'CODE', <<'OUTPUT', "bands NULL string");
         new P1, .String
-	new P2, .String
-	new P3, .String
-	null S1
-	set S2, "abc"
-	set P1, S1
-	set P2, S2
-	bands P1, P2
-	null S3
-	set P3, S3
-	eq P1, P3, ok1
-	print "not "
-ok1:	print "ok 1\n"
-	set P1, ""
-	bands P1, P2
-	unless P1, ok2
-	print "not "
-ok2:	print "ok 2\n"
+        new P2, .String
+        new P3, .String
+        null S1
+        set S2, "abc"
+        set P1, S1
+        set P2, S2
+        bands P1, P2
+        null S3
+        set P3, S3
+        eq P1, P3, ok1
+        print "not "
+ok1:    print "ok 1\n"
+        set P1, ""
+        bands P1, P2
+        unless P1, ok2
+        print "not "
+ok2:    print "ok 2\n"
 
-	null S2
-	set P2, S2
-	set P1, "abc"
-	bands P1, P2
-	null S3
-	set P3, S3
-	eq P1, P3, ok3
-	print "not "
-ok3:	print "ok 3\n"
-	set P2, ""
-	bands P1, P2
-	unless P1, ok4
-	print "not "
-ok4:	print "ok 4\n"
-	end
+        null S2
+        set P2, S2
+        set P1, "abc"
+        bands P1, P2
+        null S3
+        set P3, S3
+        eq P1, P3, ok3
+        print "not "
+ok3:    print "ok 3\n"
+        set P2, ""
+        bands P1, P2
+        unless P1, ok4
+        print "not "
+ok4:    print "ok 4\n"
+        end
 CODE
 ok 1
 ok 2
@@ -678,24 +634,24 @@
 ok 4
 OUTPUT
 
-output_is( <<'CODE', <<OUTPUT, "bands 2");
-        new P1, .String
-	new P2, .String
-	set P1, "abc"
-	set P2, "EE"
-	bands P1, P2
-	print P1
-	print "\n"
-	print P2
-	print "\n"
-	end
+output_is( <<'CODE', <<'OUTPUT', "bands 2");
+    new P1, .String
+    new P2, .String
+    set P1, "abc"
+    set P2, "EE"
+    bands P1, P2
+    print P1
+    print "\n"
+    print P2
+    print "\n"
+    end
 CODE
 A@
 EE
 OUTPUT
 
-output_is( <<'CODE', <<OUTPUT, "bands 3");
-        new P1, .String
+output_is( <<'CODE', <<'OUTPUT', "bands 3");
+    new P1, .String
 	new P2, .String
 	new P0, .String
 	set P1, "abc"
@@ -714,44 +670,44 @@
 EE
 OUTPUT
 
-output_is( <<'CODE', <<OUTPUT, "bors NULL string");
+output_is( <<'CODE', <<'OUTPUT', "bors NULL string");
         new P1, .String
-	new P2, .String
-	new P3, .String
-	null S1
-	null S2
-	set P1, S1
-	set P2, S2
-	bors P1, P2
-	null S3
-	set P3, S3
-	eq P1, P3, OK1
-	print "not "
+        new P2, .String
+        new P3, .String
+        null S1
+        null S2
+        set P1, S1
+        set P2, S2
+        bors P1, P2
+        null S3
+        set P3, S3
+        eq P1, P3, OK1
+        print "not "
 OK1:    print "ok 1\n"
 
-	null S1
-	set P1, S1
-	set P2, ""
-	bors P1, P2
-	null S3
-	set P3, S3
-	eq P1, P3, OK2
-	print "not "
+        null S1
+        set P1, S1
+        set P2, ""
+        bors P1, P2
+        null S3
+        set P3, S3
+        eq P1, P3, OK2
+        print "not "
 OK2:    print "ok 2\n"
         bors P2, P1
         eq P2, P3, OK3
         print "not "
 OK3:    print "ok 3\n"
 
-	null S1
-	set P1, S1
-	set P2, "def"
-	bors P1, P2
-	eq P1, "def", OK4
-	print "not "
+        null S1
+        set P1, S1
+        set P2, "def"
+        bors P1, P2
+        eq P1, "def", OK4
+        print "not "
 OK4:    print "ok 4\n"
         null S2
-	set P2, S2
+        set P2, S2
         bors P1, P2
         eq P1, "def", OK5
         print "not "
@@ -759,8 +715,8 @@
 
         null S1
         null S2
-	set P1, S1
-	set P2, S2
+        set P1, S1
+        set P2, S2
         bors P3, P1, P2
         null S4
         eq P3, S4, OK6
@@ -800,23 +756,23 @@
 ok 10
 OUTPUT
 
-output_is( <<'CODE', <<OUTPUT, "bors 2");
-        new P1, .String
-	new P2, .String
-	set P1, "abc"
-	set P2, "EE"
-	bors P1, P2
-	print P1
-	print "\n"
-	print P2
-	print "\n"
-	end
+output_is( <<'CODE', <<'OUTPUT', "bors 2");
+    new P1, .String
+    new P2, .String
+    set P1, "abc"
+    set P2, "EE"
+    bors P1, P2
+    print P1
+    print "\n"
+    print P2
+    print "\n"
+    end
 CODE
 egc
 EE
 OUTPUT
 
-output_is( <<'CODE', <<OUTPUT, "bors 3");
+output_is( <<'CODE', <<'OUTPUT', "bors 3");
         new P1, .String
 	new P2, .String
 	new P0, .String
@@ -836,7 +792,7 @@
 EE
 OUTPUT
 
-output_is( <<'CODE', <<OUTPUT, "bxors NULL string");
+output_is( <<'CODE', <<'OUTPUT', "bxors NULL string");
      new P1, .String
      new P2, .String
      new P3, .String
@@ -920,7 +876,7 @@
 ok 10
 OUTPUT
 
-output_is( <<'CODE', <<OUTPUT, "bxors 2");
+output_is( <<'CODE', <<'OUTPUT', "bxors 2");
     new P1, .String
     new P2, .String
     new P3, .String
@@ -946,7 +902,7 @@
    X
 OUTPUT
 
-output_is( <<'CODE', <<OUTPUT, "bxors 3");
+output_is( <<'CODE', <<'OUTPUT', "bxors 3");
     new P1, .String
     new P2, .String
     new P0, .String
@@ -978,7 +934,7 @@
    Y
 OUTPUT
 
-output_is( <<'CODE', <<OUTPUT, "bnots NULL string");
+output_is( <<'CODE', <<'OUTPUT', "bnots NULL string");
      new P1, .String
      new P2, .String
      new P3, .String
@@ -1011,7 +967,7 @@
 ok 3
 OUTPUT
 
-output_is( <<'CODE', <<OUTPUT, "bnots 2");
+output_is( <<'CODE', <<"OUTPUT", "bnots 2");
  getstdout P0
  push P0, "utf8"
  new P1, .String
@@ -1036,7 +992,7 @@
 a2c
 OUTPUT
 
-output_is( <<'CODE', <<OUTPUT, "eq_str");
+output_is( <<'CODE', <<'OUTPUT', "eq_str");
         new P1, .String
         new P2, .String
         set P1, "ABC"
@@ -1071,7 +1027,7 @@
 ok 4
 OUTPUT
 
-output_is( <<'CODE', <<OUTPUT, "ne_str");
+output_is( <<'CODE', <<'OUTPUT', "ne_str");
         new P1, .String
         new P2, .String
         set P1, "ABC"
@@ -1104,16 +1060,59 @@
 ok 4
 OUTPUT
 
-output_is( <<'CODE', <<OUTPUT, "set const and chop");
+output_is( <<'CODE', <<'OUTPUT', "set const and chop");
    new P0, .String
    set P0, "str"
    set S0, P0
    chopn S0, 2
-   print "str"
+   print P0
    print "\n"
    end
 CODE
-str
+s
+OUTPUT
+
+output_is( <<'CODE', <<'OUTPUT', "iterator and keyed access");
+        .include "iterator.pasm"
+
+        new P1, .String
+        set P1, "blah"
+        new P0, .Iterator, P1
+        set P0, .ITERATE_FROM_START
+
+        unless P0, BAD
+        shift I0, P0
+        print I0
+        print "\n"
+
+        unless P0, BAD
+        shift S0, P0
+        print S0
+        print "\n"
+
+        unless P0, BAD
+        shift P2, P0
+        print P2
+        print "\n"
+
+        unless P0, BAD
+        shift S0, P0
+        print S0
+        print "\n"
+
+        unless P0, OK
+
+BAD:    print "nok\n"
+
+OK:     print "ok\n"
+
+        end
+CODE
+98
+l
+a
+h
+ok
 OUTPUT
 
 1;
--- parrot/classes/string.pmc	2004-06-29 14:43:43.000000000 +0300
+++ my_parrot/classes/string.pmc	2004-06-29 14:31:36.000000000 +0300
@@ -8,9 +8,8 @@
 
 =head1 DESCRIPTION
 
-C<String> extends C<mmd_default> to provide a string for languages
-that want a C<string> type without going to an S register. Acts as a
-wrapper for the functions in /src/string.c
+C<String> provides a string for languages that want a C<string> type without
+going to an S register. Acts as a wrapper for the functions in /src/string.c
 
 =head2 Methods
 
@@ -24,6 +23,14 @@
 
 pmclass String {
 
+    /* XXX this is here to avoid the error "morph() not implemented in class
+       String" which is probably an error in the vtable code */
+    void morph (INTVAL type) {
+        if (SELF->vtable->base_type == type)
+            return;
+        SUPER(type);
+    }
+
 /*
 
 =item C<void init()>
@@ -78,70 +85,46 @@
 
 Returns the integer representation of the string.
 
-=cut
+=item C<FLOATVAL get_number()>
 
-*/
+Returns the floating-point representation of the string.
 
-    INTVAL get_integer () {
-        STRING *s = (STRING*) PMC_str_val(SELF);
-        return string_to_int(INTERP, s);
-    }
+=item C<BIGNUM* get_bignum()>
 
-/*
+Returns the big numbers representation of the string.
+(unimplemented, returns NULL)
 
-=item C<FLOATVAL get_number()>
+=item C<STRING* get_string()>
 
-Returns the floating-point representation of the string.
+Returns the string itself.
+
+=item C<INTVAL get_bool()>
+
+Returns the boolean value of the string.
 
 =cut
 
 */
 
+    INTVAL get_integer () {
+        STRING *s = (STRING*) PMC_str_val(SELF);
+        return string_to_int(INTERP, s);
+    }
+
     FLOATVAL get_number () {
         STRING *s = (STRING*) PMC_str_val(SELF);
         return string_to_num(INTERP, s);
     }
 
-/*
-
-=item C<BIGNUM* get_bignum()>
-
-Returns the big numbers representation of the string.
-(unimplemented, returns NULL)
-
-=cut
-
-*/
-
     BIGNUM* get_bignum () {
         /* XXX */
         return (BIGNUM*)0;
     }
 
-/*
-
-=item C<STRING* get_string()>
-
-Returns the string itself.
-
-=cut
-
-*/
-    /* XXX useless? */
     STRING* get_string () {
         return (STRING*) PMC_str_val(SELF);
     }
 
-/*
-
-=item C<INTVAL get_bool()>
-
-Returns the boolean value of the string.
-
-=cut
-
-*/
-
     INTVAL get_bool () {
         STRING *s = (STRING*) PMC_str_val(SELF);
         return string_bool(INTERP, s);
@@ -153,30 +136,10 @@
 
 Sets the value of the string to the integer C<value>.
 
-=cut
-
-*/
-
-    void set_integer_native (INTVAL value) {
-        PMC_str_val(SELF) = string_from_int(INTERP, value);
-    }
-
-/*
-
 =item C<VOID set_number_native(FLOATVAL value)>
 
 Sets the value of the string to the floating-point C<value>.
 
-=cut
-
-*/
-
-    void set_number_native (FLOATVAL value) {
-        PMC_str_val(SELF) = string_from_num(INTERP, value);
-    }
-
-/*
-
 =item C<VOID set_bignum_native(BIGNUM* value)>
 
 Sets the value of the string to the big number C<value>.
@@ -186,6 +149,14 @@
 
 */
 
+    void set_integer_native (INTVAL value) {
+        PMC_str_val(SELF) = string_from_int(INTERP, value);
+    }
+
+    void set_number_native (FLOATVAL value) {
+        PMC_str_val(SELF) = string_from_num(INTERP, value);
+    }
+
     void set_bignum_native (BIGNUM* value) {
         /* XXX */
     }
@@ -196,31 +167,10 @@
 
 Sets the value of the string to that of the specified C<string>.
 
-=cut
-
-*/
-
-    void set_string_native (STRING* value) {
-        PMC_str_val(SELF) = value;
-    }
-
-/*
-
 =item C<VOID assign_string_native(STRING* value)>
 
 Sets the value of the string to a copy of the specified C<string>.
 
-=cut
-
-*/
-
-    void assign_string_native (STRING* value) {
-        PMC_str_val(SELF) =
-            string_set(INTERP, PMC_str_val(SELF), value);
-    }
-
-/*
-
 =item C<VOID set_string_same(PMC* value)>
 
 Sets the value of the string to the value of
@@ -230,6 +180,15 @@
 
 */
 
+    void set_string_native (STRING* value) {
+        PMC_str_val(SELF) = value;
+    }
+
+    void assign_string_native (STRING* value) {
+        PMC_str_val(SELF) =
+            string_set(INTERP, PMC_str_val(SELF), value);
+    }
+
     void set_string_same (PMC* value) {
         PMC_str_val(SELF) =
             string_set(INTERP, PMC_str_val(SELF), PMC_str_val(value));
@@ -242,15 +201,6 @@
 Sets the value of the string to the string value of
 the specified C<PMC>.
 
-=cut
-
-*/
-    void set_pmc (PMC* value) {
-        PMC_str_val(SELF) = VTABLE_get_string(INTERP, value);
-    }
-
-/*
-
 =item C<VOID assign_pmc(PMC* value)>
 
 Sets the value of the string to the string value of
@@ -259,6 +209,10 @@
 =cut
 
 */
+    void set_pmc (PMC* value) {
+        PMC_str_val(SELF) = VTABLE_get_string(INTERP, value);
+    }
+
     void assign_pmc (PMC* value) {
         STRING *s = VTABLE_get_string(INTERP, value);
         PMC_str_val(SELF) = string_set(INTERP, PMC_str_val(SELF), s);
@@ -266,24 +220,18 @@
 
 /*
 
-=item C<VOID bitwise_or(PMC* value, PMC* dest)>
-=cut
-=item C<VOID bitwise_and(PMC* value, PMC* dest)>
-=cut
-=item C<VOID bitwise_xor(PMC* value, PMC* dest)>
-=cut
 =item C<VOID bitwise_ors(PMC* value, PMC* dest)>
-=cut
+
 =item C<VOID bitwise_ors_str(PMC* value, PMC* dest)>
-=cut
+
 =item C<VOID bitwise_ands(PMC* value, PMC* dest)>
-=cut
+
 =item C<VOID bitwise_ands_str(PMC* value, PMC* dest)>
-=cut
+
 =item C<VOID bitwise_xors(PMC* value, PMC* dest)>
-=cut
+
 =item C<VOID bitwise_xors_str(PMC* value, PMC* dest)>
-=cut
+
 =item C<VOID bitwise_nots(PMC* value)>
 
 These functions perform bitwise operations on entire
@@ -292,27 +240,6 @@
 =cut
 
 */
-    void bitwise_or (PMC* value, PMC* dest) {
-        STRING *s = PMC_str_val(SELF);
-        STRING *v = VTABLE_get_string(INTERP, value);
-        VTABLE_set_string_native(
-            INTERP, dest, string_bitwise_or(INTERP, s, v, NULL));
-    }
-
-    void bitwise_and (PMC* value, PMC* dest) {
-        STRING *s = PMC_str_val(SELF);
-        STRING *v = VTABLE_get_string(INTERP, value);
-        VTABLE_set_string_native(
-            INTERP, dest, string_bitwise_and(INTERP, s, v, NULL));
-    }
-
-    void bitwise_xor (PMC* value, PMC* dest) {
-        STRING *s = PMC_str_val(SELF);
-        STRING *v = VTABLE_get_string(INTERP, value);
-        VTABLE_set_string_native(
-            INTERP, dest, string_bitwise_xor(INTERP, s, v, NULL));
-    }
-
     void bitwise_ors (PMC* value, PMC* dest) {
         STRING *s = PMC_str_val(SELF);
         STRING *v = VTABLE_get_string(INTERP, value);
@@ -364,6 +291,10 @@
 
 Concatenates the string with C<value> and places the result in C<dest>.
 
+=item C<VOID concatenate_str(STRING* value, PMC* dest)>
+
+Concatenates the string with C<value> and places the result in C<dest>.
+
 =cut
 
 */
@@ -371,51 +302,40 @@
         STRING *s = PMC_str_val(SELF);
         STRING *v = VTABLE_get_string(INTERP, value);
         STRING *o = string_concat(INTERP, s, v, 0);
-        VTABLE_set_string_native(
-            INTERP, dest, o);
+        VTABLE_morph(INTERP, dest, enum_class_String);
+        PMC_str_val(dest) = o;
     }
 
-/*
-
-=item C<VOID concatenate_str(STRING* value, PMC* dest)>
-
-Concatenates the string with C<value> and places the result in C<dest>.
-
-=cut
-
-*/
     void concatenate_str (STRING* value, PMC* dest) {
         STRING *s = PMC_str_val(SELF);
         STRING *o = string_concat(INTERP, s, value, 0);
-        VTABLE_set_string_native(INTERP, dest, o);
+        VTABLE_morph(INTERP, dest, enum_class_String);
+        PMC_str_val(dest) = o;
     }
 
 /*
 
 =item C<INTVAL is_equal(PMC* value)>
 
-Compares the string with C<value>; returns true if
-they match.
-
-=cut
-
-*/
-    INTVAL is_equal (PMC* value) {
-        STRING *s = PMC_str_val(SELF);
-        STRING *v = VTABLE_get_string(INTERP, value);
-        return (INTVAL)(0 == string_equal(INTERP, s, v));
-    }
-
-/*
+Compares the string with C<value>; returns true if they match.
 
 =item C<INTVAL is_equal_num(PMC* value)>
 
 Compares the numerical value of the string with that of
 C<value>; returns true if they match.
 
+=item C<INTVAL is_equal_str(PMC* value)>
+
+Compares the string with C<value>; returns FALSE if they match.
+
 =cut
 
 */
+    INTVAL is_equal (PMC* value) {
+        STRING *s = PMC_str_val(SELF);
+        STRING *v = VTABLE_get_string(INTERP, value);
+        return (INTVAL)(0 == string_equal(INTERP, s, v));
+    }
 
     INTVAL is_equal_num (PMC* value) {
         FLOATVAL sf = string_to_num(INTERP, PMC_str_val(SELF));
@@ -423,20 +343,10 @@
         return (INTVAL)(sf == vf);
     }
 
-/*
-
-=item C<INTVAL is_equal_str(PMC* value)>
-
-Compares the string with C<value>; returns FALSE if they match.
-
-=cut
-
-*/
-
     INTVAL is_equal_str (PMC* value) {
         STRING *s = PMC_str_val(SELF);
         STRING *v = VTABLE_get_string(INTERP, value);
-        return string_equal(INTERP, s, v) == 0;
+        return (INTVAL)(0 == string_equal(INTERP, s, v));
     }
 
 /*
@@ -447,8 +357,6 @@
 Returns true if this PMC and the one in C<value> are of the same PMC
 class and their strings are aliases of the same internal string.
 
-(this can only happen if you use the set_string_native method)
-
 =cut
 
 */
@@ -469,26 +377,27 @@
 string is smaller, 0 if they are equal, and 1 if C<value>
 is smaller.
 
-=cut
-
-*/
-    INTVAL cmp (PMC* value) {
-        STRING *s = PMC_str_val(SELF);
-        STRING *v = VTABLE_get_string(INTERP, value);
-        return string_compare(INTERP, s, v);
-    }
-
-/*
-
 =item C<INTVAL cmp_num(PMC* value)>
 
 Compares the numerical value of the string with that of
 C<value>; returns -1 if the string is smaller, 0 if they
 are equal, and 1 if C<value> is smaller.
 
+=item C<INTVAL cmp_string(PMC* value)>
+
+Compares the string with C<value>; returns -1 if the
+string is smaller, 0 if they are equal, and 1 if C<value>
+is smaller.
+
 =cut
 
 */
+    INTVAL cmp (PMC* value) {
+        STRING *s = PMC_str_val(SELF);
+        STRING *v = VTABLE_get_string(INTERP, value);
+        return string_compare(INTERP, s, v);
+    }
+
     INTVAL cmp_num (PMC* value) {
         FLOATVAL sf = string_to_num(INTERP, PMC_str_val(SELF));
         FLOATVAL vf = VTABLE_get_number(INTERP, value);
@@ -499,17 +408,6 @@
         return (INTVAL)(0);
     }
 
-/*
-
-=item C<INTVAL cmp_string(PMC* value)>
-
-Compares the string with C<value>; returns -1 if the
-string is smaller, 0 if they are equal, and 1 if C<value>
-is smaller.
-
-=cut
-
-*/
     INTVAL cmp_string (PMC* value) {
         STRING *s = PMC_str_val(SELF);
         STRING *v = VTABLE_get_string(INTERP, value);
@@ -522,6 +420,10 @@
 
 Repeats the string C<value> times and places the result in C<dest>.
 
+=item C<void repeat_int(INTVAL value, PMC* dest)>
+
+Repeats the string C<value> times and places the result in C<dest>.
+
 =cut
 
 */
@@ -529,22 +431,15 @@
         INTVAL n = VTABLE_get_integer(INTERP, value);
         STRING *s = PMC_str_val(SELF);
         STRING *s2 = string_repeat(INTERP, s, n, NULL);
-        VTABLE_set_string_native(INTERP, dest, s2);
+        VTABLE_morph(INTERP, dest, enum_class_String);
+        PMC_str_val(dest) = s2;
     }
 
-/*
-
-=item C<void repeat_int(INTVAL value, PMC* dest)>
-
-Repeats the string C<value> times and places the result in C<dest>.
-
-=cut
-
-*/
     void repeat_int (INTVAL value, PMC* dest) {
         STRING *s = PMC_str_val(SELF);
         STRING *s2 = string_repeat(INTERP, s, value, NULL);
-        VTABLE_set_string_native(INTERP, dest, s2);
+        VTABLE_morph(INTERP, dest, enum_class_String);
+        PMC_str_val(dest) = s2;
     }
 
 /*
@@ -554,6 +449,11 @@
 Extracts the substring starting at C<offset>, with size
 C<length>, and places it in C<dest>.
 
+=item C<STRING* substr_str(INTVAL offset, INTVAL length)>
+
+Extracts the substring starting at C<offset>, with size
+C<length>, and returns it.
+
 =cut
 
 */
@@ -563,61 +463,90 @@
         VTABLE_set_string_native(INTERP, dest, s2);
     }
 
-/*
-
-=item C<void substr(INTVAL offset, INTVAL length)>
-
-Extracts the substring starting at C<offset>, with size
-C<length>, and returns it.
-
-=cut
-
-*/
     STRING* substr_str (INTVAL offset, INTVAL length) {
         STRING *s = PMC_str_val(SELF);
         return string_substr(INTERP, s, offset, length, NULL, 0);
     }
 
 /*
+=back
 
-=item C<INTVAL exists_keyed(PMC *key)>
+=head2 Iterator interface
 
-Returns true if the C<key>'th character in the string exists. Negative
-numbers count from the end.
+=over 4
 
-=cut
+=item C<INTVAL elements()>
 
-*/
+Returns the length of the string.
 
-    INTVAL exists_keyed(PMC* key) {
-        INTVAL n = string_length(INTERP, PMC_str_val(SELF));
-        INTVAL k = VTABLE_get_integer(INTERP, key);
-        return (INTVAL)( (k>=0 && k<=n) || (k<0 && -k<=n) );
-    }
+=item C<PMC* slice(PMC* key)>
 
-/*
+Creates a slice of the string.
+
+=item C<PMC* nextkey_keyed(PMC* key, INTVAL what)
+
+Advances the iterator.
 
 =item C<STRING *get_string_keyed(PMC *key)>
 
-Returns the C<key>'th character in the string. Negative numbers count
-from the end.
+Returns the C<key>'th character in the string.
+
+=item C<INTVAL *get_integer_keyed(PMC *key)>
+
+Returns the code of the C<key>'th character in the string.
+
+=item C<PMC* get_pmc_keyed(PMC* key)>
+Returns the C<key>'th character as a new String PMC.
 
 =cut
 
 */
 
+    INTVAL elements() {
+        return string_length(INTERP, PMC_str_val(SELF));
+    }
+
+    PMC* slice(PMC* key) {
+        PMC *iter = pmc_new_init(INTERP, enum_class_Iterator, SELF);
+        PMC_struct_val(iter) = key;
+        return iter;
+    }
+
+    PMC* nextkey_keyed(PMC *key, INTVAL what) {
+        return VTABLE_nextkey_keyed(INTERP, key, SELF, what);
+    }
+
     STRING* get_string_keyed(PMC* key) {
         STRING *s = PMC_str_val(SELF);
         INTVAL k = VTABLE_get_integer(INTERP, key);
         return string_substr(INTERP, s, k, 1, NULL, 0);
     }
+    
+    INTVAL get_integer_keyed(PMC* key) {
+        return string_ord(INTERP, PMC_str_val(SELF), PMC_int_val(key));
+    }
+
+    PMC* get_pmc_keyed(PMC* key) {
+        STRING *s = PMC_str_val(SELF);
+        INTVAL k = VTABLE_get_integer(INTERP, key);
+        STRING *chr = string_substr(INTERP, s, k, 1, NULL, 0);
 
+        PMC *ret = pmc_new_noinit(INTERP, enum_class_String);
+        PObj_custom_mark_SET(ret);
+        PMC_str_val(ret) = chr;
+        return ret;
+    }
+    
 /*
 
 =item C<void freeze(visit_info *info)>
 
 Used to archive the string.
 
+=item C<void thaw(visit_info *info)>
+
+Used to unarchive the string.
+
 =cut
 
 */
@@ -627,15 +556,6 @@
         io->vtable->push_string(INTERP, io, PMC_str_val(SELF));
     }
 
-/*
-
-=item C<void thaw(visit_info *info)>
-
-Used to unarchive the string.
-
-=cut
-
-*/
     void thaw(visit_info *info) {
         IMAGE_IO *io = info->image_io;
         SUPER(info);

Reply via email to