# 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);