"-" x -1 should evaluate to an empty string and 0 xx -1 should
evaluate to an empty list. I have hacked pugs/src/Pugs/Prim.hs to
correctly handle negatives, but I don't know Haskell very well and am
not familiar with the layout of Pugs, so I may have written bad code
in a bad place. I have also added tests to pugs/t/operators/repeat.t
to test for correct handling of negative and zero values.
Hopefully the patch will make it through to the list.
diff -ruN pugs.orig/src/Pugs/Prim.hs pugs/src/Pugs/Prim.hs
--- pugs.orig/src/Pugs/Prim.hs 2007-05-25 16:34:55.000000000 -0400
+++ pugs/src/Pugs/Prim.hs 2007-05-25 15:59:47.000000000 -0400
@@ -923,6 +923,11 @@
| last str == '\n' = VStr (init str)
| otherwise = VStr str
+perlReplicate :: VInt -> a -> [a]
+perlReplicate i a = if i < 0
+ then genericReplicate 0 a
+ else genericReplicate i a
+
-- |Implementation of 2-arity primitive operators and functions
op2 :: String -> Val -> Val -> Eval Val
op2 "rename" = guardedIO2 rename
@@ -931,8 +936,8 @@
op2 "*" = op2Numeric (*)
op2 "/" = op2Divide
op2 "%" = op2Modulus
-op2 "x" = op2Cast (\x y -> VStr . concat $ (y :: VInt) `genericReplicate` x)
-op2 "xx" = op2Cast (\x y -> VList . concat $ (y :: VInt) `genericReplicate` x)
+op2 "x" = op2Cast (\x y -> VStr . concat $ (y :: VInt) `perlReplicate` x)
+op2 "xx" = op2Cast (\x y -> VList . concat $ (y :: VInt) `perlReplicate` x)
op2 "+&" = op2Int (.&.)
op2 "+<" = op2Int shiftL
op2 "+>" = op2Int shiftR
diff -ruN pugs.orig/t/operators/repeat.t pugs/t/operators/repeat.t
--- pugs.orig/t/operators/repeat.t 2007-05-25 16:34:55.000000000 -0400
+++ pugs/t/operators/repeat.t 2007-05-25 16:13:29.000000000 -0400
@@ -8,7 +8,7 @@
=cut
-plan 19;
+plan 23;
#L<S03/Changes to Perl 5 operators/"x (which concatenates repetitions of a string to produce a single string">
@@ -16,6 +16,8 @@
is('ab' x 4, 'abababab', 'string repeat operator works on multiple character');
is(1 x 5, '11111', 'number repeat operator works on number and creates string');
is('' x 6, '', 'repeating an empty string creates an empty string');
+is('a' x 0, '', 'repeating zero times produces an empty string');
+is('a' x -1, '', 'repeating negative times produces an empty string');
#L<S03/Changes to Perl 5 operators/"and xx (which creates a list of repetitions of a list or item)">
my @foo = 'x' xx 10;
@@ -23,12 +25,20 @@
is(@foo[9], 'x', 'list repeat operator created correct array');
is([EMAIL PROTECTED], 10, 'list repeat operator created array of the right size');
+
lives_ok { my @foo2 = undef xx 2; }, 'can repeat undefs';
my @foo3 = (1, 2) xx 2;
is(@foo3[0], 1, 'can repeat lists');
is(@foo3[1], 2, 'can repeat lists');
is(@foo3[2], 1, 'can repeat lists');
is(@foo3[3], 2, 'can repeat lists');
+
+my @foo4 = 'x' xx 0;
+is([EMAIL PROTECTED], 0, 'repeating zero times produces an empty list');
+
+my @foo5 = 'x' xx -1;
+is([EMAIL PROTECTED], 0, 'repeating negative times produces an empty list');
+
my @foo_2d = [1, 2] xx 2; # should create 2d
is(@foo_2d[1], [1, 2], 'can create 2d arrays', :todo<bug>); # creates a flat 1d array
# Wrong/unsure: \(1, 2) does not create a ref to the array/list (1,2), but