diff --git a/goof.scm b/goof.scm index 1fe8687..eb7c325 100644 --- a/goof.scm +++ b/goof.scm @@ -47,7 +47,7 @@ loop/or loop/list/parallel - :when :unless :break :final :bind :subloop :do :for :acc + :when :unless :break :continue :final :bind :subloop :do :for :acc :initial :length :fill :to :by @@ -107,8 +107,8 @@ #'in-cycle #'in-indexed #'stop-before - #'stop-after - ))) + #'stop-after))) + (define valid-acc-clauses (make-parameter (list #'folding #'listing #'listing-reverse @@ -119,8 +119,8 @@ #'hashing #'hashving #'hashqing - #'vectoring - ))) + #'vectoring))) + (define (add-clause type form) (cond ((eq? type 'for) diff --git a/goof/goof-impl.scm b/goof/goof-impl.scm index 1aadf1d..a33facf 100644 --- a/goof/goof-impl.scm +++ b/goof/goof-impl.scm @@ -29,7 +29,7 @@ (define-aux-syntaxes ;; Auxiliary syntax for the loop clauses - :when :unless :break :final :bind :do :subloop :for :acc + :when :unless :break :final :continue :bind :do :subloop :for :acc ;; Auxiliary syntax for the iterators. :gen ;; auxiliary syntax for some accumulators @@ -122,7 +122,7 @@ ;; cl sorts all the clauses into subloops and positions everything where it should be. (define-syntax cl - (syntax-rules (=> :for :acc :when :unless :break :final :do :bind :subloop) + (syntax-rules (=> :for :acc :when :unless :break :continue :final :do :bind :subloop) ((_ orig name l a v c r f ff user () => expr . body) (emit orig name l a v c r f ff user expr . body)) ((_ orig name l a v c r () ff user () . body) @@ -150,6 +150,10 @@ ((_ orig name l a v c r f ff ((cur-user ...) . user-rest) ((:final expr) clauses ...) . body) (final :acc ((fin) (expr)) cl-next/acc orig name l a v c r f ff ((cur-user ... (:break fin)) . user-rest) (clauses ...) . body)) + ;; USER continue + ((_ orig name l a v c r f ff ((cur-co ...) . co-rest) ((:continue expr) clauses ...) . body) + (cl orig name l a v c r f ff ((cur-co ... (:continue expr)) . co-rest) (clauses ...) . body)) + ;; User do - sideffecting stuff. ((_ orig name l a v c r f ff ((cur-uw ...) . uw-rest) ((:do expr ...) clauses ...) . body) (cl orig name l a v c r f ff ((cur-uw ... (:do expr ...)) . uw-rest) (clauses ...) . body)) @@ -267,7 +271,7 @@ ;; User is responsible for all non-acc/non-for clauses. (define-syntax user - (syntax-rules (:when :bind :break :do :nop) + (syntax-rules (:when :bind :break :continue :do :nop) ((_ final-expr next outer () . body) (begin . body)) ((_ f n o (:nop . rest) . body) @@ -283,6 +287,10 @@ (cond (expr final-expr ...) (else (user (final-expr ...) n o rest . body)))) + ((_ f n outer ((:continue expr) . rest) . body) + (cond + (expr outer) + (else (user f n outer rest . body)))) ((_ f n o ((:do expr ...) . rest) . body) (begin expr ... @@ -397,7 +405,7 @@ (ref-let (refs ...) (user (ff-cur ... ff-above ... final) (innermost-loop accstep ... step ...) - #f + outer (us ...) (let-kw-form name final () (innermost-loop (accvar accstep) ... (var step) ...) . body))))))) @@ -425,7 +433,7 @@ (ref-let (refs ...) (user (ff-cur ... ff-above ... final) (intermediate-loop accstep ... step ...) - #f + outer (us ...) (emit-many/rest orig name diff --git a/goof/iterators.scm b/goof/iterators.scm index 08a353d..165768b 100644 --- a/goof/iterators.scm +++ b/goof/iterators.scm @@ -30,7 +30,7 @@ ;; in-stream (define-syntax in - (syntax-rules () + (syntax-rules (:for) ((in :for ((var) (init)) n . rest) (n () ((var init var)) () () () . rest)) ((in :for ((var) (init step)) n . rest) @@ -393,18 +393,23 @@ ((var (final cursor))) . rest)))) +;; This looks wonky because it needs to reset var to the init value when the loop is re-entered +;; if it is a subloop. It does so by also binding var to folding-init in the outer binding of the current +;; loop. It has to do this because :acc clauses propagates all acc bindings to outside +;; the outermost loop. (define-syntax folding - (syntax-rules (if :acc) - ((_ :acc ((var) (init update (if guard))) n . rest) - (n () - ((var init (if guard update var))) - () () + (syntax-rules (:acc) + ((_ :acc ((var) (init update stop)) n orig name ((lets ...) . l-rest) . rest) + (n ((folding-init init)) + ((var folding-init update)) + (stop) () ((var var)) + orig name ((lets ... (var folding-init)) . l-rest) . rest)) ((_ :acc ((var) (init update)) n . rest) - (folding :acc ((var) (init update (if #t))) n . rest)) + (folding :acc ((var) (init update #f)) n . rest)) ((_ :acc ((var) (init)) n . rest) - (folding :acc ((var) (init var (if #t))) n . rest)))) + (folding :acc ((var) (init var #f)) n . rest)))) (define-syntax listing (syntax-rules (:acc)