2020-11-02 22:11:45 +01:00
|
|
|
;; goof loop - a bastardisation of chibi loop.
|
|
|
|
;;
|
2021-01-28 20:01:24 +01:00
|
|
|
;; Copyright 2020, 2021 Linus Björnstam
|
2020-11-02 22:11:45 +01:00
|
|
|
;;
|
|
|
|
;; Redistribution and use in source and binary forms, with or without
|
|
|
|
;; modification, are permitted provided that the following conditions
|
|
|
|
;; are met:
|
|
|
|
;; 1. Redistributions of source code must retain the above copyright
|
|
|
|
;; notice, this list of conditions and the following disclaimer.
|
|
|
|
;; 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
;; notice, this list of conditions and the following disclaimer in the
|
|
|
|
;; documentation and/or other materials provided with the distribution.
|
|
|
|
;; 3. The name of the author(s) may not be used to endorse or promote products
|
|
|
|
;; derived from this software without specific prior written permission.
|
|
|
|
;;
|
|
|
|
;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
|
|
;; IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
|
|
;; OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
|
|
;; IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
|
|
;; INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
|
|
;; NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
;; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
|
|
;; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
;; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
|
|
;; THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
|
|
|
|
;; This is a looping construct obviously based on (chibi loop) (aka:
|
|
|
|
;; foof-loop) by Alex Shinn. The name goof-loop is a play on that
|
|
|
|
;; name, and the fact that I goofed in the chibi issue tracker when
|
|
|
|
;; trying to understand the iterator protocol.
|
2020-11-09 13:30:02 +01:00
|
|
|
|
2020-12-16 20:17:13 +01:00
|
|
|
(define-module (goof)
|
|
|
|
#:use-module (goof helpers)
|
|
|
|
#:use-module (goof ref-let)
|
|
|
|
#:use-module ((srfi srfi-1) #:select (circular-list))
|
2021-01-02 21:43:10 +01:00
|
|
|
#:use-module ((srfi srfi-43) #:select (vector-copy vector-copy!))
|
2020-12-16 20:17:13 +01:00
|
|
|
#:use-module (srfi srfi-71)
|
|
|
|
#:use-module (rnrs io simple)
|
|
|
|
#:use-module (ice-9 futures)
|
|
|
|
#:export (loop
|
|
|
|
|
|
|
|
loop/list
|
|
|
|
loop/sum
|
|
|
|
loop/product
|
|
|
|
loop/first
|
|
|
|
loop/last
|
|
|
|
loop/and
|
|
|
|
loop/or
|
|
|
|
loop/list/parallel
|
|
|
|
|
|
|
|
:when :unless :break :final :let :let* :subloop :for :acc
|
2021-01-02 21:43:10 +01:00
|
|
|
:length :fill
|
2020-11-02 22:11:45 +01:00
|
|
|
|
2020-12-16 20:17:13 +01:00
|
|
|
in
|
|
|
|
in-list
|
|
|
|
in-lists
|
|
|
|
|
|
|
|
in-vector in-reverse-vector
|
|
|
|
in-string in-reverse-string
|
2021-01-02 12:03:03 +01:00
|
|
|
in-hash
|
2020-12-16 20:17:13 +01:00
|
|
|
|
|
|
|
in-port
|
|
|
|
in-file
|
|
|
|
in-generator
|
|
|
|
up-from
|
|
|
|
down-from
|
|
|
|
accumulating
|
|
|
|
folding
|
|
|
|
listing
|
|
|
|
listing-reverse
|
|
|
|
appending
|
|
|
|
appending-reverse
|
|
|
|
summing
|
|
|
|
multiplying
|
2021-01-02 12:03:03 +01:00
|
|
|
hashing
|
2021-01-02 21:43:10 +01:00
|
|
|
vectoring
|
2020-12-16 20:17:13 +01:00
|
|
|
|
|
|
|
in-cycle
|
|
|
|
in-indexed
|
|
|
|
))
|
2020-11-02 22:11:45 +01:00
|
|
|
|
2021-01-28 20:01:24 +01:00
|
|
|
;; This contains the portable parts of goof-loop.
|
|
|
|
(include "goof-impl.scm")
|
2020-11-02 22:11:45 +01:00
|
|
|
|
|
|
|
;; Helper procedures for let-kw-form
|
|
|
|
(define (syntax= s1 s2)
|
|
|
|
(equal? (syntax->datum s1) (syntax->datum s2)))
|
|
|
|
|
2020-11-04 11:58:58 +01:00
|
|
|
(define (update-name params name val)
|
|
|
|
(cond
|
2020-11-22 21:47:48 +01:00
|
|
|
((null? params) (error "unknown loop variable name " name (list '=> name val)))
|
2020-11-04 11:58:58 +01:00
|
|
|
((syntax= name (caar params))
|
|
|
|
(cons (list (caar params) val) (cdr params)))
|
|
|
|
(else
|
|
|
|
(cons (car params) (update-name (cdr params) name val)))))
|
2020-11-02 22:11:45 +01:00
|
|
|
|
|
|
|
|
2020-12-02 21:39:47 +01:00
|
|
|
(define-syntax inner-recur
|
|
|
|
(syntax-rules ()
|
|
|
|
((_ loop-name final-fun () ((v s) ...))
|
|
|
|
(loop-name s ...))
|
|
|
|
((_ loop-name final-fun (user-finals ...) ((v s) ...))
|
|
|
|
(let ((v s) ...)
|
|
|
|
(if (or user-finals ...)
|
|
|
|
final-fun
|
|
|
|
(loop-name v ...))))))
|
2021-01-28 20:01:24 +01:00
|
|
|
|
|
|
|
|
|
|
|
(define (syntax->list stx)
|
|
|
|
(syntax-case stx ()
|
|
|
|
((a ...) #'(a ...))))
|
|
|
|
|
2020-12-02 21:39:47 +01:00
|
|
|
|
2020-11-02 22:11:45 +01:00
|
|
|
(define-syntax let-kw-form
|
|
|
|
(syntax-rules ()
|
2020-11-22 21:47:48 +01:00
|
|
|
((_ macro-name final-fun (user-finals ...) (loop-name (var step) ...) . body)
|
2020-11-02 22:11:45 +01:00
|
|
|
(let-syntax ((macro-name
|
|
|
|
(lambda (stx)
|
|
|
|
(with-ellipsis :::
|
2020-11-04 11:58:58 +01:00
|
|
|
(let loop ((lst (cdr (syntax->list stx)))
|
|
|
|
(params (list #'(var step) ...)))
|
2020-11-02 22:11:45 +01:00
|
|
|
(if (null? lst)
|
|
|
|
(with-syntax ((((v s) :::) params))
|
2020-12-02 21:39:47 +01:00
|
|
|
#'(inner-recur loop-name final-fun
|
|
|
|
(user-finals ...)
|
|
|
|
((v s) :::)))
|
2020-11-02 22:11:45 +01:00
|
|
|
(syntax-case (car lst) (=>)
|
|
|
|
((=> name val)
|
2020-11-04 11:58:58 +01:00
|
|
|
(loop (cdr lst) (update-name params #'name #'val)))
|
|
|
|
(_ (error "Malformed looping clause in macro")))))))))
|
2020-11-02 22:11:45 +01:00
|
|
|
. body))))
|
2020-12-01 20:53:25 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
2020-11-22 21:47:48 +01:00
|
|
|
(define-syntax loop/list/parallel
|
|
|
|
(syntax-rules ()
|
2020-12-01 20:53:25 +01:00
|
|
|
((n (clauses ...) body ...)
|
|
|
|
(forify (n (clauses ...) body ...)
|
|
|
|
parallel-list-loop
|
|
|
|
() (clauses ... (%acc futures (listing-reverse (future (let () body ...)))))
|
|
|
|
=> (loop ((:for future (in-list futures))
|
|
|
|
(:acc futures2 (listing-reverse (touch future))))
|
|
|
|
=> futures2)
|
|
|
|
(parallel-list-loop)))))
|