[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index][Thread Index][Top&Search][Original]

[PATCH 5.005_63] Open-ended slices: (a..z)[23..]







Here's a *much* tidied-up version of the open-ended slice patch I've
been working on. I've only confined it to lists, since you can use
@a[$x..@a] on arrays. I haven't included the new perly.c for the
sake of brevity; please make and fix the usual way.
You can now finally do things like (split /:/, $_)[2..] to get all
but the first two elements and (split /:/, $_)[-2..] to get the last
two.

Simon

diff -ruN perl5.005_63/pod/perlop.pod perl5.005_63_new/pod/perlop.pod
--- perl5.005_63/pod/perlop.pod    Sun Oct 24 21:04:39 1999
+++ perl5.005_63_new/pod/perlop.pod      Tue Jan 25 12:55:21 2000
@@ -370,12 +370,13 @@
 operators depending on the context.  In list context, it returns an
 array of values counting (up by ones) from the left value to the right
 value.  If the left value is greater than the right value then it
-returns the empty array.  The range operator is useful for writing
-C<foreach (1..10)> loops and for doing slice operations on arrays.  In
-the current implementation, no temporary array is created when the
-range operator is used as the expression in C<foreach> loops, but older
-versions of Perl might burn a lot of memory when you write something
-like this:
+returns the empty list.  If the right value is not given in a list slice,
+(not an array slice) it returns everything from the left operator to the
+end of the list.  The range operator is useful for writing C<foreach
+(1..10)> loops and for doing slice operations on arrays.  In the current
+implementation, no temporary array is created when the range operator is
+used as the expression in C<foreach> loops, but older versions of Perl
+might burn a lot of memory when you write something like this:

     for (1 .. 1_000_000) {
     # code
diff -ruN perl5.005_63/op.h perl5.005_63_new/op.h
--- perl5.005_63/op.h    Wed Dec 01 12:47:10 1999
+++ perl5.005_63_new/op.h     Tue Jan 25 12:55:23 2000
@@ -79,6 +79,7 @@
                    /*  On OP_ENTERSUB || OP_NULL, saw a "do". */
                    /*  On OP_(ENTER|LEAVE)EVAL, don't clear $@ */
                    /*  On OP_ENTERITER, loop var is per-thread */
+                   /*  On a list slice, make an open-ended range */
                                 /*  On pushre, re is /\s+/ imp. by split "
" */

 /* old names; don't use in new code, but don't break them, either */
diff -ruN perl5.005_63/perly.y perl5.005_63_new/perly.y
--- perl5.005_63/perly.y Thu Dec 09 13:30:47 1999
+++ perl5.005_63_new/perly.y  Tue Jan 25 12:55:22 2000
@@ -87,6 +87,7 @@
 %type <opval> listexpr listexprcom indirob listop method
 %type <opval> formname subname proto subbody cont my_scalar
 %type <opval> subattrlist myattrlist mysubrout myattrterm myterm
+%type <opval> oerange
 %type <pval> label

 %nonassoc PREC_LOW
@@ -558,6 +559,8 @@
               { $$ = newUNOP(OP_AV2ARYLEN, 0, ref($1, OP_AV2ARYLEN));}
     |       subscripted
               { $$ = $1; }
+    |   '(' expr ')' '[' oerange ']'
+              { $$ = newSLICEOP(OPf_SPECIAL, $5, $2); }
     |    '(' expr ')' '[' expr ']'
               { $$ = newSLICEOP(0, $5, $2); }
     |    '(' ')' '[' expr ']'
@@ -651,6 +654,9 @@
     |    WORD
     |    listop
     ;
+
+oerange: term DOTDOT; /* Open ended ranges */
+

 myattrterm:   MY myterm myattrlist
               { $$ = my_attrs($2,$3); }
diff -ruN perl5.005_63/pp.c perl5.005_63_new/pp.c
--- perl5.005_63/pp.c    Thu Dec 09 09:07:06 1999
+++ perl5.005_63_new/pp.c     Tue Jan 25 13:08:51 2000
@@ -2772,6 +2772,9 @@
         ix += max;
     else
         ix -= arybase;
+    if (PL_op->op_flags & OPf_SPECIAL)
+         ix = max-1;
+
     if (ix < 0 || ix >= max)
         *firstlelem = &PL_sv_undef;
     else
@@ -2785,6 +2788,23 @@
     RETURN;
     }

+    if (PL_op->op_flags & OPf_SPECIAL) {
+         /* Open ended range beginning at firstlelem */
+         ix=SvIVx(*firstlelem);
+         lelem=firstlelem;
+         if (ix<0)
+              ix += max;
+         else
+              ix -= arybase;
+
+         is_something_there = TRUE;
+         for (; ix < max; ix++, lelem++) {
+              if (!(*lelem = firstrelem[ix])) /* segfault bait */
+                   *lelem = &PL_sv_undef;
+         }
+         lastlelem=lelem-1;
+    } else {
+
     for (lelem = firstlelem; lelem <= lastlelem; lelem++) {
     ix = SvIVx(*lelem);
     if (ix < 0)
@@ -2799,6 +2819,8 @@
          *lelem = &PL_sv_undef;
     }
     }
+
+    }
     if (is_something_there)
     SP = lastlelem;
     else
diff -ruN perl5.005_63/t/op/list.t perl5.005_63_new/t/op/list.t
--- perl5.005_63/t/op/list.t  Wed Jul 21 02:18:14 1999
+++ perl5.005_63_new/t/op/list.t   Tue Jan 25 13:18:37 2000
@@ -1,6 +1,6 @@
 #!./perl

-print "1..28\n";
+print "1..31\n";

 @foo = (1, 2, 3, 4);
 if ($foo[0] == 1 && $foo[3] == 4) {print "ok 1\n";} else {print "not ok
1\n";}
@@ -87,3 +87,8 @@
     print "not " unless @b == @c and @c == 2;
     print "ok 28\n";
 }
+
+# open-ended range slices
+print "not " unless join(":",(0..6)[5..])  eq "5:6"; print "ok 29\n";
+print "not " unless join(":",(0..6)[-2..]) eq "5:6"; print "ok 30\n";
+print "not " unless join(":",(0..6)[5..5]) eq "5"  ; print "ok 31\n";




Follow-Ups from:
Gurusamy Sarathy <gsar@ActiveState.com>

[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index][Thread Index][Top&Search][Original]