Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

cppawk: parallel/product iteration syntax.

15 views
Skip to first unread message

Kaz Kylheku

unread,
Mar 30, 2022, 3:18:46 PM3/30/22
to
I didn't suspect C99 preprocessing would be up to this, but, lo and behold:

./cppawk '
#include <loop.h>

BEGIN {
$0 = "o p q r s t u v w x y z" # set fields

split("! @ # $ % ^ & * ( )", arr) # init array

loop (range(i, 1, 10),
from(x, 5),
from_step(y, 100, 5),
str(j, ch, "abcdefghijklmn"),
fields(f),
keys(k, arr))
{
print i, x, y, ch, f, k, arr[k]
}
}'
1 5 100 a o 1 !
2 6 105 a p 2 @
3 7 110 b q 3 #
4 8 115 c r 4 $
5 9 120 d s 5 %
6 10 125 e t 6 ^
7 11 130 f u 7 &
8 12 135 g v 8 *
9 13 140 h w 9 (
10 14 145 i x 10 )

Cross-producing loop:

$ ./cppawk '
#include <loop.h>

BEGIN {
$0 = "a b c" # set fields

split("X Y", arr) # init array

loop_cross (fields(f),
keys(k, arr),
range(i, 1, 3))
{
print f, arr[k], i
}
}'
a X 1
a X 2
a X 3
a Y 1
a Y 2
a Y 3
b X 1
b X 2
b X 3
b Y 1
b Y 2
b Y 3
c X 1
c X 2
c X 3
c Y 1
c Y 2
c Y 3

The loop clauses are user-definable, and easily so; I'm going to have
documentation on exactly how to do that.

For instance, the clause range(index, from, to) is entirely defined in
these three simple lines of code in <loop.h>, which are entirely
isolated from the complexity of loop and loop_cross:

#define __init_range(idx, from, to) (idx = (from))
#define __test_range(idx, from, to) (idx <= (to))
#define __step_range(idx, from, to) (idx++)

Kaz Kylheku

unread,
Mar 30, 2022, 5:38:05 PM3/30/22
to
On 2022-03-30, Kaz Kylheku <480-99...@kylheku.com> wrote:
> The loop clauses are user-definable, and easily so; I'm going to have
> documentation on exactly how to do that.
>
> For instance, the clause range(index, from, to) is entirely defined in
> these three simple lines of code in <loop.h>, which are entirely
> isolated from the complexity of loop and loop_cross:
>
> #define __init_range(idx, from, to) (idx = (from))
> #define __test_range(idx, from, to) (idx <= (to))
> #define __step_range(idx, from, to) (idx++)

E.g. let's make a clause "sfixes"
that loops over string suffixes, e.g "abc" "bc" "c"

./cppawk '
#include <loop.h>

// user-defined "sfixes" loop clause

#define __init_sfixes(idx, ch, str) (idx = 1)
#define __test_sfixes(idx, ch, str) (idx <= length(str) && \
((ch = substr(str, idx)) || 1))
#define __step_sfixes(idx, ch, str) (idx++)

// use it

BEGIN {
loop (sfixes(i, sf, "abcd"))
print i, sf
}'
1 abcd
2 bcd
3 cd
4 d

Or how about controling the length of the string slices.

No, how about completely controlling the string slice and just binding
the variable:

No, let's first make a general clause "let" to set a arbitrary variable
on each iteration of the loop.


./cppawk '
#include <loop.h>

// user-defined "let" loop clause

#define __init_let(var, expr) 0
#define __test_let(var, expr) ((var = (expr)) || 1)
#define __step_let(var, expr) 0

BEGIN {
loop (range(i, 1, 10),
range_step(j, 1, 10, 2),
let(ch, substr("abcdefghijklmn", i, j)))
{
print i, j, ch
}
}
'
1 1 a
2 3 bcd
3 5 cdefg
4 7 defghij
5 9 efghijklm


How about general "first_then_until" stepping clause.

./cppawk '
#include <loop.h>

// user-defined "first_then_until" loop clause

#define __init_first_then_until(var, first, then, until) (var = (first))
#define __test_first_then_until(var, first, then, until) (!(until))
#define __step_first_then_until(var, first, then, until) (var = (then))

BEGIN {
loop (first_then_until(i, 1, i * 2, i >= 60),
first_then_until(s, "x", s s, 0))
{
print i, s
}
}
'
1 x
2 xx
4 xxxx
8 xxxxxxxx
16 xxxxxxxxxxxxxxxx
32 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Kaz Kylheku

unread,
Mar 30, 2022, 7:19:59 PM3/30/22
to
List collection. (Poor implementation: the framework will have to
adjusted to make it possible in a better way):

./cppawk '
#include <loop.h>
#include <cons.h> // Lisp-inspired data structure framework.

#define __init_collect(tmp, var, expr) (tmp = list_begin())
#define __test_collect(tmp, var, expr) ((tmp = list_add(tmp, expr)) && \
(var = list_end(tmp))) || 1
#define __step_collect(tmp, var, expr) 1

BEGIN {
loop (range(i, 1, 10),
collect(tmp, lst, i))
{
print i
}

print sexp(lst)

dolist (i, lst)
print i, i * 10
}
'
1
2
3
4
5
6
7
8
9
10
(1 2 3 4 5 6 7 8 9 10)
1 10
2 20
3 30
4 40
5 50
6 60
7 70
8 80
9 90
10 100

--
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal

0 new messages