From 5c0119253f246e5e9b7aa6da0979875201d78f48 Mon Sep 17 00:00:00 2001 From: NoahStoryM Date: Mon, 29 Aug 2022 18:30:24 +0800 Subject: [PATCH 01/16] Define identity elements for `tee` and `relay`. --- qi-lib/flow/compiler.rkt | 16 +++++----------- qi-lib/flow/impl.rkt | 21 +++++++++++++++++++-- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/qi-lib/flow/compiler.rkt b/qi-lib/flow/compiler.rkt index 823452eb4..dcf82683b 100644 --- a/qi-lib/flow/compiler.rkt +++ b/qi-lib/flow/compiler.rkt @@ -91,7 +91,7 @@ ;;; Core routing elements [(~or* (~datum ⏚) (~datum ground)) - #'(qi0->racket (select))] + #'*->1] [((~or* (~datum ~>) (~datum thread)) onex:clause ...) #`(compose . #,(reverse (syntax->list @@ -105,11 +105,7 @@ (with-syntax ([len #`#,(length (syntax->list #'(onex ...)))]) #'(qi0->racket (group len (== onex ...) rest-onex) ))] [((~or* (~datum -<) (~datum tee)) onex:clause ...) - #'(λ args - (apply values - (append (values->list - (apply (qi0->racket onex) args)) - ...)))] + #'(tee (qi0->racket onex) ...)] [e:select-form (select-parser #'e)] [e:block-form (block-parser #'e)] [((~datum bundle) (n:number ...) @@ -308,6 +304,7 @@ the DSL. (define (select-parser stx) (syntax-parse stx + [(_) #'*->1] [(_ n:number ...) #'(qi0->racket (-< (esc (arg n)) ...))] [(_ arg ...) ; error handling catch-all (report-syntax-error 'select @@ -488,17 +485,14 @@ the DSL. (define (fanout-parser stx) (syntax-parse stx [_:id #'repeat-values] + [(_ 0) #'*->1] [(_ n:number) ;; a slightly more efficient compile-time implementation ;; for literally indicated N #`(λ args (apply values (append #,@(make-list (syntax->datum #'n) 'args))) )] - [(_ n:expr) - #'(lambda args - (apply values - (apply append - (make-list n args))))])) + [(_ e:expr) #`(let ([n e]) (#,fanout-parser n))])) (define (feedback-parser stx) (syntax-parse stx diff --git a/qi-lib/flow/impl.rkt b/qi-lib/flow/impl.rkt index 16df7327c..a82b71789 100644 --- a/qi-lib/flow/impl.rkt +++ b/qi-lib/flow/impl.rkt @@ -10,7 +10,10 @@ map-values filter-values partition-values + 1->1 + *->1 relay + tee loom-compose parity-xor arg @@ -198,6 +201,9 @@ (append (values->list (apply op vs)) (apply zip-with op (map rest seqs)))))) +(define 1->1 (λ () (values))) +(define *->1 (λ _ (values))) + ;; from mischief/function - requiring it runs aground ;; of some "name is protected" error while building docs, not sure why; ;; so including the implementation directly here for now @@ -207,8 +213,19 @@ (keyword-apply f ks vs xs)))) (define (relay . fs) - (λ args - (apply values (zip-with call fs args)))) + (if (null? fs) + 1->1 + (λ args (apply values (zip-with call fs args))))) + +(define (tee . fs) + (let ([fs (remq* (list *->1) fs)]) + (if (null? fs) + *->1 + (λ args + (apply values + (append* + (for/list ([f (in-list fs)]) + (values->list (apply f args))))))))) (define (~all? . args) (match args From ad78814f340471897d006e642dfa4f1ed6a0e778 Mon Sep 17 00:00:00 2001 From: NoahStoryM Date: Mon, 29 Aug 2022 20:00:22 +0800 Subject: [PATCH 02/16] Update. --- qi-lib/flow/impl.rkt | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/qi-lib/flow/impl.rkt b/qi-lib/flow/impl.rkt index a82b71789..74e82198a 100644 --- a/qi-lib/flow/impl.rkt +++ b/qi-lib/flow/impl.rkt @@ -219,13 +219,17 @@ (define (tee . fs) (let ([fs (remq* (list *->1) fs)]) - (if (null? fs) - *->1 - (λ args - (apply values - (append* - (for/list ([f (in-list fs)]) - (values->list (apply f args))))))))) + (match fs + ['() *->1] + [`(,f) f] + [_ + (define teed + (λ args + (apply values + (append* + (for/list ([f (in-list fs)]) + (values->list (apply f args))))))) + teed]))) (define (~all? . args) (match args From 9618e10d8ef981f77a96bf4f739f0fc3dba6ccd3 Mon Sep 17 00:00:00 2001 From: NoahStoryM Date: Mon, 29 Aug 2022 20:15:25 +0800 Subject: [PATCH 03/16] Fix `fanout-parser`. --- qi-lib/flow/compiler.rkt | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/qi-lib/flow/compiler.rkt b/qi-lib/flow/compiler.rkt index dcf82683b..287bc175d 100644 --- a/qi-lib/flow/compiler.rkt +++ b/qi-lib/flow/compiler.rkt @@ -492,7 +492,14 @@ the DSL. #`(λ args (apply values (append #,@(make-list (syntax->datum #'n) 'args))) )] - [(_ e:expr) #`(let ([n e]) (#,fanout-parser n))])) + [(_ e:expr) + #'(let ([n e]) + (if (zero? n) + *->1 + (λ args + (apply values + (apply append + (make-list n args))))))])) (define (feedback-parser stx) (syntax-parse stx From 37b7e14afda67b8900aa1313354dc160ce01481d Mon Sep 17 00:00:00 2001 From: NoahStoryM Date: Mon, 29 Aug 2022 20:30:51 +0800 Subject: [PATCH 04/16] Use thunk. --- qi-lib/flow/impl.rkt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/qi-lib/flow/impl.rkt b/qi-lib/flow/impl.rkt index 74e82198a..a3ee51c77 100644 --- a/qi-lib/flow/impl.rkt +++ b/qi-lib/flow/impl.rkt @@ -29,6 +29,8 @@ (require racket/match (only-in racket/function + thunk + thunk* const negate) racket/bool @@ -201,8 +203,8 @@ (append (values->list (apply op vs)) (apply zip-with op (map rest seqs)))))) -(define 1->1 (λ () (values))) -(define *->1 (λ _ (values))) +(define 1->1 (thunk (values))) +(define *->1 (thunk* (values))) ;; from mischief/function - requiring it runs aground ;; of some "name is protected" error while building docs, not sure why; From c0506bc2d4c8a7058adcad3dfc8a46b63be48970 Mon Sep 17 00:00:00 2001 From: NoahStoryM Date: Tue, 30 Aug 2022 12:25:32 +0800 Subject: [PATCH 05/16] Add identity element for `gen`. --- qi-lib/flow/compiler.rkt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/qi-lib/flow/compiler.rkt b/qi-lib/flow/compiler.rkt index 287bc175d..1d53b2db2 100644 --- a/qi-lib/flow/compiler.rkt +++ b/qi-lib/flow/compiler.rkt @@ -63,8 +63,10 @@ #'(disjoin (qi0->racket onex) ...)] [((~datum not) onex:clause) #'(negate (qi0->racket onex))] + [((~datum gen)) + #'*->1] [((~datum gen) ex:expr ...) - #'(λ _ (values ex ...))] + #'(thunk* (values ex ...))] [(~or* (~datum NOT) (~datum !)) #'not] [(~or* (~datum AND) (~datum &)) From 063cd215fa2ac1fa289f8f036bd39927ff37845a Mon Sep 17 00:00:00 2001 From: NoahStoryM Date: Tue, 30 Aug 2022 12:51:56 +0800 Subject: [PATCH 06/16] Optimize `(fanout 1)`. --- qi-lib/flow/compiler.rkt | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/qi-lib/flow/compiler.rkt b/qi-lib/flow/compiler.rkt index 1d53b2db2..153a91520 100644 --- a/qi-lib/flow/compiler.rkt +++ b/qi-lib/flow/compiler.rkt @@ -488,20 +488,17 @@ the DSL. (syntax-parse stx [_:id #'repeat-values] [(_ 0) #'*->1] + [(_ 1) #'values] [(_ n:number) ;; a slightly more efficient compile-time implementation ;; for literally indicated N - #`(λ args - (apply values - (append #,@(make-list (syntax->datum #'n) 'args))) )] + #'(curry repeat-values n)] [(_ e:expr) #'(let ([n e]) - (if (zero? n) - *->1 - (λ args - (apply values - (apply append - (make-list n args))))))])) + (case n + [(0) *->1] + [(1) values] + [else (curry repeat-values n)]))])) (define (feedback-parser stx) (syntax-parse stx From 8f6eca01819ba9b4c229d99d6981bda5e9331544 Mon Sep 17 00:00:00 2001 From: NoahStoryM Date: Tue, 30 Aug 2022 12:55:43 +0800 Subject: [PATCH 07/16] Use `append*` instead of `apply append`. --- qi-lib/flow/impl.rkt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qi-lib/flow/impl.rkt b/qi-lib/flow/impl.rkt index a3ee51c77..d5e8ab4ed 100644 --- a/qi-lib/flow/impl.rkt +++ b/qi-lib/flow/impl.rkt @@ -174,7 +174,7 @@ [b (in-value (cdr c+b))] [args (in-value (hash-ref by-cs c))]) (call-with-values (λ () (apply b args)) list))) - (apply values (apply append results))) + (apply values (append* results))) (define (->boolean v) (not (not v))) @@ -255,7 +255,7 @@ (define none? (compose not not ~none?)) (define (repeat-values n . vs) - (apply values (apply append (make-list n vs)))) + (apply values (append* (make-list n vs)))) (define (power n f) (apply compose (make-list n f))) From f74b270dd9906e7f0a80efafbbfb27c22c22543b Mon Sep 17 00:00:00 2001 From: NoahStoryM Date: Tue, 30 Aug 2022 18:21:01 +0800 Subject: [PATCH 08/16] Update `tee`. --- qi-lib/flow/impl.rkt | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/qi-lib/flow/impl.rkt b/qi-lib/flow/impl.rkt index d5e8ab4ed..7664eef8f 100644 --- a/qi-lib/flow/impl.rkt +++ b/qi-lib/flow/impl.rkt @@ -220,18 +220,16 @@ (λ args (apply values (zip-with call fs args))))) (define (tee . fs) - (let ([fs (remq* (list *->1) fs)]) - (match fs - ['() *->1] - [`(,f) f] - [_ - (define teed - (λ args - (apply values - (append* - (for/list ([f (in-list fs)]) - (values->list (apply f args))))))) - teed]))) + (match (remq* (list *->1) fs) + ['() *->1] + [`(,f) f] + [fs + (define (teed . args) + (apply values + (append* + (for/list ([f (in-list fs)]) + (values->list (apply f args)))))) + teed])) (define (~all? . args) (match args From 845aa79728c4c40bf4669c3b1f997f15c36613d4 Mon Sep 17 00:00:00 2001 From: NoahStoryM Date: Tue, 30 Aug 2022 18:25:35 +0800 Subject: [PATCH 09/16] Name `relayed`. --- qi-lib/flow/impl.rkt | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/qi-lib/flow/impl.rkt b/qi-lib/flow/impl.rkt index 7664eef8f..b1535f12e 100644 --- a/qi-lib/flow/impl.rkt +++ b/qi-lib/flow/impl.rkt @@ -215,9 +215,12 @@ (keyword-apply f ks vs xs)))) (define (relay . fs) - (if (null? fs) - 1->1 - (λ args (apply values (zip-with call fs args))))) + (cond + [(null? fs) 1->1] + [else + (define (relayed . args) + (apply values (zip-with call fs args))) + relayed])) (define (tee . fs) (match (remq* (list *->1) fs) From f429750fa72bc09484b618d4f83f17d81e6aa3c6 Mon Sep 17 00:00:00 2001 From: NoahStoryM Date: Wed, 31 Aug 2022 11:44:17 +0800 Subject: [PATCH 10/16] Remove `const`. --- qi-lib/flow/impl.rkt | 1 - 1 file changed, 1 deletion(-) diff --git a/qi-lib/flow/impl.rkt b/qi-lib/flow/impl.rkt index b1535f12e..6c9dab059 100644 --- a/qi-lib/flow/impl.rkt +++ b/qi-lib/flow/impl.rkt @@ -31,7 +31,6 @@ (only-in racket/function thunk thunk* - const negate) racket/bool racket/list From 9ad9257f8c69eafc698cc283954186c63b19bb6f Mon Sep 17 00:00:00 2001 From: NoahStoryM Date: Thu, 1 Sep 2022 11:19:55 +0800 Subject: [PATCH 11/16] Name some flows. --- qi-lib/flow/compiler.rkt | 132 ++++++++++++++++++++++++--------------- qi-lib/flow/impl.rkt | 38 +++++------ 2 files changed, 102 insertions(+), 68 deletions(-) diff --git a/qi-lib/flow/compiler.rkt b/qi-lib/flow/compiler.rkt index 153a91520..032d01992 100644 --- a/qi-lib/flow/compiler.rkt +++ b/qi-lib/flow/compiler.rkt @@ -301,8 +301,11 @@ the DSL. "list?" _)))] [(_ onex:clause) - #'(λ (v . vs) - ((qi0->racket (~> △ (>< (apply (qi0->racket onex) _ vs)))) v))])) + #'(let ([compiled-sep-flow + (λ (v . vs) + ((qi0->racket (~> △ (>< (apply (qi0->racket onex) _ vs)))) + v))]) + compiled-sep-flow)])) (define (select-parser stx) (syntax-parse stx @@ -332,8 +335,10 @@ the DSL. (qi0->racket remainder-onex) n)] [_:id - #'(λ (n selection-flo remainder-flo . vs) - (apply (qi0->racket (group n selection-flo remainder-flo)) vs))] + #'(let ([compiled-group-flow + (λ (n selection-flo remainder-flo . vs) + (apply (qi0->racket (group n selection-flo remainder-flo)) vs))]) + compiled-group-flow)] [(_ arg ...) ; error handling catch-all (report-syntax-error 'group (syntax->datum #'(arg ...)) @@ -341,7 +346,7 @@ the DSL. (define (switch-parser stx) (syntax-parse stx - [(_) #'(qi0->racket _)] + [(_) #'values] [(_ ((~or* (~datum divert) (~datum %)) condition-gate:clause consequent-gate:clause)) @@ -410,10 +415,12 @@ the DSL. #'(qi0->racket (-< (~> (pass condition) sonex) (~> (pass (not condition)) ronex)))] [_:id - #'(λ (condition sonex ronex . args) - (apply (qi0->racket (-< (~> (pass condition) sonex) - (~> (pass (not condition)) ronex))) - args))] + #'(let ([compiled-sieve-flow + (λ (condition sonex ronex . args) + (apply (qi0->racket (-< (~> (pass condition) sonex) + (~> (pass (not condition)) ronex))) + args))]) + compiled-sieve-flow)] [(_ arg ...) ; error handling catch-all (report-syntax-error 'sieve (syntax->datum #'(arg ...)) @@ -434,14 +441,16 @@ the DSL. [(_ flo [error-condition-flo error-handler-flo] ...+) - #'(λ args - (with-handlers ([(qi0->racket error-condition-flo) - (λ (e) - ;; TODO: may be good to support reference to the - ;; error via a binding / syntax parameter - (apply (qi0->racket error-handler-flo) args))] - ...) - (apply (qi0->racket flo) args)))] + #'(let ([compiled-try-flow + (λ args + (with-handlers ([(qi0->racket error-condition-flo) + (λ (e) + ;; TODO: may be good to support reference to the + ;; error via a binding / syntax parameter + (apply (qi0->racket error-handler-flo) args))] + ...) + (apply (qi0->racket flo) args)))]) + compiled-try-flow)] [(_ arg ...) (report-syntax-error 'try (syntax->datum #'(arg ...)) @@ -472,17 +481,21 @@ the DSL. (syntax-parse stx [(_ consequent:clause alternative:clause) - #'(λ (f . args) - (if (apply f args) - (apply (qi0->racket consequent) args) - (apply (qi0->racket alternative) args)))] + #'(let ([compiled-if-flow + (λ (f . args) + (if (apply f args) + (apply (qi0->racket consequent) args) + (apply (qi0->racket alternative) args)))]) + compiled-if-flow)] [(_ condition:clause consequent:clause alternative:clause) - #'(λ args - (if (apply (qi0->racket condition) args) - (apply (qi0->racket consequent) args) - (apply (qi0->racket alternative) args)))])) + #'(let ([compiled-if-flow + (λ args + (if (apply (qi0->racket condition) args) + (apply (qi0->racket consequent) args) + (apply (qi0->racket alternative) args)))]) + compiled-if-flow)])) (define (fanout-parser stx) (syntax-parse stx @@ -492,13 +505,18 @@ the DSL. [(_ n:number) ;; a slightly more efficient compile-time implementation ;; for literally indicated N - #'(curry repeat-values n)] + #'(procedure-rename + (curry repeat-values n) + 'compiled-fanout-flow)] [(_ e:expr) #'(let ([n e]) (case n [(0) *->1] [(1) values] - [else (curry repeat-values n)]))])) + [else + (procedure-rename + (curry repeat-values n) + 'compiled-fanout-flow)]))])) (define (feedback-parser stx) (syntax-parse stx @@ -510,9 +528,10 @@ the DSL. (qi0->racket thenex))] [(_ ((~datum while) tilex:clause) ((~datum then) thenex:clause)) - #'(λ (f . args) - (apply (qi0->racket (feedback (while tilex) (then thenex) f)) - args))] + #'(let ([compiled-feedback-flow + (λ (f . args) + (apply (qi0->racket (feedback (while tilex) (then thenex) f)) args))]) + compiled-feedback-flow)] [(_ ((~datum while) tilex:clause) onex:clause) #'(qi0->racket (feedback (while tilex) (then _) onex))] [(_ ((~datum while) tilex:clause)) @@ -523,17 +542,23 @@ the DSL. #'(feedback-times (qi0->racket onex) n (qi0->racket thenex))] [(_ n:expr ((~datum then) thenex:clause)) - #'(λ (f . args) - (apply (qi0->racket (feedback n (then thenex) f)) args))] + #'(let ([compiled-feedback-flow + (λ (f . args) + (apply (qi0->racket (feedback n (then thenex) f)) args))]) + compiled-feedback-flow)] [(_ n:expr onex:clause) #'(qi0->racket (feedback n (then _) onex))] [(_ onex:clause) - #'(λ (n . args) - (apply (qi0->racket (feedback n onex)) args))] + #'(let ([compiled-feedback-flow + (λ (n . args) + (apply (qi0->racket (feedback n onex)) args))]) + compiled-feedback-flow)] [_:id - #'(λ (n flo . args) - (apply (qi0->racket (feedback n flo)) - args))])) + #'(let ([compiled-feedback-flow + (λ (n flo . args) + (apply (qi0->racket (feedback n flo)) + args))]) + compiled-feedback-flow)])) (define (side-effect-parser stx) (syntax-parse stx @@ -549,7 +574,9 @@ the DSL. [_:id #'map-values] [(_ onex:clause) - #'(curry map-values (qi0->racket onex))] + #'(procedure-rename + (curry map-values (qi0->racket onex)) + 'compiled-amp-flow)] [(_ onex0:clause onex:clause ...) (report-syntax-error 'amp @@ -562,7 +589,9 @@ the DSL. [_:id #'filter-values] [(_ onex:clause) - #'(curry filter-values (qi0->racket onex))])) + #'(procedure-rename + (curry filter-values (qi0->racket onex)) + 'compiled-pass-flow)])) (define (fold-left-parser stx) (syntax-parse stx @@ -607,18 +636,23 @@ the DSL. (syntax-parse stx [_:id #:do [(define chirality (syntax-property stx 'chirality))] - (if (and chirality (eq? chirality 'right)) - #'(λ (f . args) (apply curryr f args)) - #'(λ (f . args) (apply curry f args)))] + #`(let ([compiled-clos-flow + (λ (f . args) + (apply #,(if (and chirality (eq? chirality 'right)) + #'curryr #'curry) + f args))]) + compiled-clos-flow)] [(_ onex:clause) #:do [(define chirality (syntax-property stx 'chirality))] - (if (and chirality (eq? chirality 'right)) - #'(λ args - (qi0->racket (~> (-< _ (~> (gen args) △)) - onex))) - #'(λ args - (qi0->racket (~> (-< (~> (gen args) △) _) - onex))))])) + #`(let ([compiled-clos-flow + (λ args + (qi0->racket + (~> + #,(if (and chirality (eq? chirality 'right)) + #'(-< _ (~> (gen args) △)) + #'(-< (~> (gen args) △) _)) + onex)))]) + compiled-clos-flow)])) (define (literal-parser stx) (syntax-parse stx diff --git a/qi-lib/flow/impl.rkt b/qi-lib/flow/impl.rkt index f1f54849f..ec02bded1 100644 --- a/qi-lib/flow/impl.rkt +++ b/qi-lib/flow/impl.rkt @@ -43,22 +43,22 @@ ;; we use a lambda to capture the arguments at runtime ;; since they aren't available at compile time -(define (loom-compose f g [n #f]) - (let ([n (or n (procedure-arity f))]) +(define (loom-compose f g [n (procedure-arity f)]) + (define compiled-group-flow (λ args - (let ([num-args (length args)]) - (if (< num-args n) - (if (= 0 num-args) - (values) - (error 'group (~a "Can't select " - n - " arguments from " - args))) - (let ([sargs (take args n)] - [rargs (drop args n)]) - (apply values - (append (values->list (apply f sargs)) - (values->list (apply g rargs)))))))))) + (define num-args (length args)) + (if (< num-args n) + (if (= 0 num-args) + (values) + (error 'group (~a "Can't select " + n + " arguments from " + args))) + (let-values ([(sargs rargs) (split-at args n)]) + (apply values + (append (values->list (apply f sargs)) + (values->list (apply g rargs)))))))) + compiled-group-flow) (define (parity-xor . args) (and (foldl xor #f args) #t)) @@ -204,21 +204,21 @@ (cond [(null? fs) 1->1] [else - (define (relayed . args) + (define (compiled-relay-flow . args) (apply values (zip-with call fs args))) - relayed])) + compiled-relay-flow])) (define (tee . fs) (match (remq* (list *->1) fs) ['() *->1] [`(,f) f] [fs - (define (teed . args) + (define (compiled-tee-flow . args) (apply values (append* (for/list ([f (in-list fs)]) (values->list (apply f args)))))) - teed])) + compiled-tee-flow])) (define (all? . args) (and (for/and ([v (in-list args)]) v) #t)) From ee6b1f89453bf6bc05dd2dea8c8c87a72c8de861 Mon Sep 17 00:00:00 2001 From: NoahStoryM Date: Thu, 1 Sep 2022 13:29:35 +0800 Subject: [PATCH 12/16] Update. --- qi-lib/flow/compiler.rkt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/qi-lib/flow/compiler.rkt b/qi-lib/flow/compiler.rkt index 032d01992..c35f68f36 100644 --- a/qi-lib/flow/compiler.rkt +++ b/qi-lib/flow/compiler.rkt @@ -103,6 +103,8 @@ #'(qi0->racket (~> ▽ reverse △))] [((~or* (~datum ==) (~datum relay)) onex:clause ...) #'(relay (qi0->racket onex) ...)] + [((~or* (~datum ==*) (~datum relay*))) + #'1->1] [((~or* (~datum ==*) (~datum relay*)) onex:clause ... rest-onex:clause) (with-syntax ([len #`#,(length (syntax->list #'(onex ...)))]) #'(qi0->racket (group len (== onex ...) rest-onex) ))] From 575b27f8c775beab87ff77aa71da2f183c0c4319 Mon Sep 17 00:00:00 2001 From: NoahStoryM Date: Tue, 11 Oct 2022 11:17:30 +0800 Subject: [PATCH 13/16] Undo `(fanout n:number)` case. --- qi-lib/flow/compiler.rkt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/qi-lib/flow/compiler.rkt b/qi-lib/flow/compiler.rkt index c35f68f36..1a9793513 100644 --- a/qi-lib/flow/compiler.rkt +++ b/qi-lib/flow/compiler.rkt @@ -507,9 +507,11 @@ the DSL. [(_ n:number) ;; a slightly more efficient compile-time implementation ;; for literally indicated N - #'(procedure-rename - (curry repeat-values n) - 'compiled-fanout-flow)] + #`(let ([compiled-fanout-flow + (λ args + (apply values + (append #,@(make-list (syntax->datum #'n) 'args))))]) + compiled-fanout-flow)] [(_ e:expr) #'(let ([n e]) (case n From b5ea1c047462ac5423f9e4c00c454dc30f29df34 Mon Sep 17 00:00:00 2001 From: NoahStoryM Date: Tue, 11 Oct 2022 17:22:03 +0800 Subject: [PATCH 14/16] More tests for edge cases. --- qi-test/tests/flow.rkt | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/qi-test/tests/flow.rkt b/qi-test/tests/flow.rkt index 7f41fe490..2c8508a78 100644 --- a/qi-test/tests/flow.rkt +++ b/qi-test/tests/flow.rkt @@ -242,6 +242,9 @@ "separate into a non-primitive flow with presupplied values")) (test-suite "gen" + (check-eq? (☯ (gen)) (☯ ⏚)) + (check-eq? ((☯ (~> (gen) ▽))) + '()) (check-equal? ((☯ (gen 5))) 5) (check-equal? ((☯ (gen 5)) 3) @@ -420,6 +423,11 @@ "a")) (test-suite "-<" + (check-eq? (☯ (-<)) (☯ ⏚)) + (check-eq? (☯ (-< add1 (-<))) + add1) + (check-eq? (☯ (-< (-<) add1)) + add1) (check-equal? ((☯ (~> (-< sqr add1) ▽)) 5) (list 25 6)) @@ -452,6 +460,8 @@ "named tee junction form")) (test-suite "==" + (check-eq? ((☯ (~> (==) ▽))) + '()) (check-equal? ((☯ (~> (== sqr add1) ▽)) 5 7) (list 25 8)) @@ -486,6 +496,8 @@ "named relay form")) (test-suite "==*" + (check-eq? ((☯ (~> (==*) ▽))) + '()) (check-equal? ((☯ (~> (==* add1 sub1 +) ▽)) 1 1 1 1 1) (list 2 0 3)) @@ -503,7 +515,9 @@ 6) (check-equal? ((☯ (-< ground add1)) 5) - 6))) + 6) + (check-eq? (☯ (-< ⏚ add1)) add1) + (check-eq? (☯ ⏚) (☯ (-<))))) (test-suite "Exceptions" @@ -939,6 +953,9 @@ (check-equal? (~> (2 3) (fanout 0) ▽) null "N=0 produces no values.") + (check-equal? (~> (2 3) (fanout 1) ▽) + (list 2 3) + "N=1 produces original values.") (check-equal? (~> () (fanout 3) ▽) null "No inputs produces no outputs.") @@ -1051,6 +1068,7 @@ "grouping more inputs than are available shows a helpful error")) (test-suite "select" + (check-equal? (☯ (~> (select))) (☯ ⏚)) (check-equal? ((☯ (~> (select) ▽)) 1) null) From 46aed9f7d7631cc849656e2b8fa20a14bc58c73c Mon Sep 17 00:00:00 2001 From: NoahStoryM Date: Fri, 14 Oct 2022 20:34:57 +0800 Subject: [PATCH 15/16] Optimize `relay` and `relay*`. --- qi-lib/flow/compiler.rkt | 2 ++ qi-lib/flow/impl.rkt | 9 +++++---- qi-test/tests/flow.rkt | 9 ++++++++- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/qi-lib/flow/compiler.rkt b/qi-lib/flow/compiler.rkt index 1a9793513..049d9f943 100644 --- a/qi-lib/flow/compiler.rkt +++ b/qi-lib/flow/compiler.rkt @@ -105,6 +105,8 @@ #'(relay (qi0->racket onex) ...)] [((~or* (~datum ==*) (~datum relay*))) #'1->1] + [((~or* (~datum ==*) (~datum relay*)) onex:clause) + #'onex] [((~or* (~datum ==*) (~datum relay*)) onex:clause ... rest-onex:clause) (with-syntax ([len #`#,(length (syntax->list #'(onex ...)))]) #'(qi0->racket (group len (== onex ...) rest-onex) ))] diff --git a/qi-lib/flow/impl.rkt b/qi-lib/flow/impl.rkt index ec02bded1..331008cf9 100644 --- a/qi-lib/flow/impl.rkt +++ b/qi-lib/flow/impl.rkt @@ -200,10 +200,11 @@ (lambda (ks vs f . xs) (keyword-apply f ks vs xs)))) -(define (relay . fs) - (cond - [(null? fs) 1->1] - [else +(define relay + (case-lambda + [() 1->1] + [(f) (procedure-reduce-arity-mask f 2)] + [fs (define (compiled-relay-flow . args) (apply values (zip-with call fs args))) compiled-relay-flow])) diff --git a/qi-test/tests/flow.rkt b/qi-test/tests/flow.rkt index 2c8508a78..e2bf1df5f 100644 --- a/qi-test/tests/flow.rkt +++ b/qi-test/tests/flow.rkt @@ -486,7 +486,11 @@ 5 7) (list 5 5 8) "relay with arity-increasing clause") - (check-exn exn:fail? + (check-eq? ((☯ (~> (== add1))) 1) 2) + (check-exn exn:fail:contract:arity? + (thunk ((☯ (~> (== +))) + 1 2 3))) + (check-exn exn:fail:contract:arity? (thunk ((☯ (~> (== ⏚ add1) ▽)) 5 7 8)) "relay elements must be in one-to-one correspondence with input") @@ -498,6 +502,9 @@ "==*" (check-eq? ((☯ (~> (==*) ▽))) '()) + (check-eq? ((☯ (~> (==* +))) + 1 2 3 4 5) + 15) (check-equal? ((☯ (~> (==* add1 sub1 +) ▽)) 1 1 1 1 1) (list 2 0 3)) From 88a740650680fa2e996f483386cb0387542ef977 Mon Sep 17 00:00:00 2001 From: NoahStoryM Date: Sat, 15 Oct 2022 16:23:59 +0800 Subject: [PATCH 16/16] Fix `==*`. --- qi-lib/flow/compiler.rkt | 2 +- qi-test/tests/flow.rkt | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/qi-lib/flow/compiler.rkt b/qi-lib/flow/compiler.rkt index 049d9f943..df8c4e772 100644 --- a/qi-lib/flow/compiler.rkt +++ b/qi-lib/flow/compiler.rkt @@ -106,7 +106,7 @@ [((~or* (~datum ==*) (~datum relay*))) #'1->1] [((~or* (~datum ==*) (~datum relay*)) onex:clause) - #'onex] + #'(qi0->racket onex)] [((~or* (~datum ==*) (~datum relay*)) onex:clause ... rest-onex:clause) (with-syntax ([len #`#,(length (syntax->list #'(onex ...)))]) #'(qi0->racket (group len (== onex ...) rest-onex) ))] diff --git a/qi-test/tests/flow.rkt b/qi-test/tests/flow.rkt index e2bf1df5f..2d596cebb 100644 --- a/qi-test/tests/flow.rkt +++ b/qi-test/tests/flow.rkt @@ -505,6 +505,9 @@ (check-eq? ((☯ (~> (==* +))) 1 2 3 4 5) 15) + (check-eq? ((☯ (~> (==* (~> +)))) + 1 2 3 4 5) + 15) (check-equal? ((☯ (~> (==* add1 sub1 +) ▽)) 1 1 1 1 1) (list 2 0 3))