Skip to content

Commit 2231a1d

Browse files
committed
FEAT: Add PAIR! support for REPEAT
This change allows PAIR! values as value argument of REPEAT. This enables convenient traversal over a 2D space: >> repeat p 3x3 [print p] 1x1 2x1 3x1 1x2 2x2 3x2 1x3 2x3 3x3 Similar to REPEAT over decimals, REPEAT over pairs implies a start of 1.0x1.0 and a default bump of 1.0 for each component. The first pair component ("X") is varied first, which is in line with pair!-based indexing into image!s. For the sake of completeness, PAIR! support is also enabled in the legacy C-style FOR: >> for p 10x10 15x20 5x5 [print p] 10x10 15x10 10x15 15x15 10x20 15x20 >> for p 3x1 1x2 -1x1 [print p] 3x1 2x1 1x1 3x2 2x2 1x2 Implements: metaeducation/rebol-issues#1995 (cherry picked from commit ce8838f)
1 parent b95ebfe commit 2231a1d

File tree

2 files changed

+38
-4
lines changed

2 files changed

+38
-4
lines changed

src/boot/natives.r

+4-4
Original file line numberDiff line numberDiff line change
@@ -150,9 +150,9 @@ find-script: native [
150150
for: native [
151151
{Evaluate a block over a range of values. (See also: REPEAT)}
152152
'word [word!] "Variable to hold current value"
153-
start [series! number!] "Starting value"
154-
end [series! number!] "Ending value"
155-
bump [number!] "Amount to skip each time"
153+
start [series! number! pair!] "Starting value"
154+
end [series! number! pair!] "Ending value"
155+
bump [number! pair!] "Amount to skip each time"
156156
body [block!] "Block to evaluate"
157157
]
158158

@@ -259,7 +259,7 @@ reduce: native [
259259
repeat: native [
260260
{Evaluates a block a number of times or over a series.}
261261
'word [word!] {Word to set each time}
262-
value [number! series! none!] {Maximum number or series to traverse}
262+
value [number! series! pair! none!] {Maximum number or series to traverse}
263263
body [block!] {Block to evaluate each time}
264264
]
265265

src/core/n-loop.c

+34
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,31 @@
140140
}
141141

142142

143+
/***********************************************************************
144+
**
145+
*/ static void Loop_Pair(REBVAL *var, REBSER* body, REBD32 xstart, REBD32 ystart, REBD32 xend, REBD32 yend, REBD32 xincr, REBD32 yincr)
146+
/*
147+
***********************************************************************/
148+
{
149+
REBD32 xi;
150+
REBD32 yi;
151+
REBVAL *result;
152+
153+
VAL_SET(var, REB_PAIR);
154+
for (yi = ystart; (yincr > 0.) ? yi <= yend : yi >= yend; yi += yincr) {
155+
for (xi = xstart; (xincr > 0.) ? xi <= xend : xi >= xend; xi += xincr) {
156+
VAL_PAIR_X(var) = xi;
157+
VAL_PAIR_Y(var) = yi;
158+
result = Do_Blk(body, 0);
159+
if (THROWN(result) && Check_Error(result) >= 0) return;
160+
if (!IS_PAIR(var)) Trap_Type(var);
161+
xi = VAL_PAIR_X(var);
162+
yi = VAL_PAIR_Y(var);
163+
}
164+
}
165+
}
166+
167+
143168
/***********************************************************************
144169
**
145170
*/ static void Loop_Number(REBVAL *var, REBSER* body, REBVAL *start, REBVAL *end, REBVAL *incr)
@@ -500,6 +525,12 @@ skip_hidden: ;
500525
//if (ANY_SERIES(end) && VAL_SERIES(start) != VAL_SERIES(end)) Trap_Arg(end);
501526
Loop_Series(var, body, start, ANY_SERIES(end) ? VAL_INDEX(end) : (Int32s(end, 1) - 1), Int32(incr));
502527
}
528+
else if (IS_PAIR(start) && IS_PAIR(end) && IS_PAIR(incr)) {
529+
Loop_Pair(var, body,
530+
VAL_PAIR_X(start), VAL_PAIR_Y(start),
531+
VAL_PAIR_X(end), VAL_PAIR_Y(end),
532+
VAL_PAIR_X(incr), VAL_PAIR_Y(incr));
533+
}
503534
else
504535
Loop_Number(var, body, start, end, incr);
505536

@@ -644,6 +675,9 @@ skip_hidden: ;
644675
else if (IS_INTEGER(count)) {
645676
Loop_Integer(var, body, 1, VAL_INT64(count), 1);
646677
}
678+
else if (IS_PAIR(count)) {
679+
Loop_Pair(var, body, 1., 1., VAL_PAIR_X(count), VAL_PAIR_Y(count), 1., 1.);
680+
}
647681

648682
return R_TOS1;
649683
}

0 commit comments

Comments
 (0)