From 9f601fc3f131e82e1ee5791783d330bddde468d2 Mon Sep 17 00:00:00 2001 From: Arun Isaac Date: Thu, 23 Nov 2023 17:49:45 +0000 Subject: ccwl: Implement item separators for array inputs. * ccwl/ccwl.scm ()[separator]: New field. * ccwl/ccwl.scm (run-arg-position, run-args): Support array input specifiers. (run-arg-separator): New function. (command): Set separator on input objects. * ccwl/cwl.scm (input->cwl-scm): Serialize itemSeparator. * tests/ccwl.scm ("commands with non-string #:separator parameters must raise a &ccwl-violation condition"): New test. * doc/ccwl.skb (Cookbook)[Array input item separators]: New section. * doc/array-input-item-separators.scm: New file. --- ccwl/ccwl.scm | 47 ++++++++++++++++++++++++++++++++----- ccwl/cwl.scm | 3 ++- doc/array-input-item-separators.scm | 2 ++ doc/ccwl.skb | 11 +++++++++ tests/ccwl.scm | 7 ++++++ 5 files changed, 63 insertions(+), 7 deletions(-) create mode 100644 doc/array-input-item-separators.scm diff --git a/ccwl/ccwl.scm b/ccwl/ccwl.scm index e602f0b..d00609d 100644 --- a/ccwl/ccwl.scm +++ b/ccwl/ccwl.scm @@ -65,6 +65,7 @@ input-default input-position input-prefix + input-separator input-stage? input-other output? @@ -93,6 +94,7 @@ (default input-default set-input-default) (position input-position set-input-position) (prefix input-prefix set-input-prefix) + (separator input-separator set-input-separator) (stage? input-stage?) (other input-other)) @@ -325,11 +327,19 @@ compared using @code{equal?}." RUN-ARGS. If such an input is not present in RUN-ARGS, return #f." (list-index (lambda (run-arg) (let ((run-arg-input - (syntax-case run-arg () + (syntax-case run-arg (array) + ;; input (input (identifier? #'input) (syntax->datum #'input)) + ;; prefixed input ((_ input) (identifier? #'input) (syntax->datum #'input)) + ;; array input specifier + ((array input _ ...) (identifier? #'input) + (syntax->datum #'input)) + ;; prefixed array input specifier + ((_ (array input _ ...)) (identifier? #'input) + (syntax->datum #'input)) (_ #f)))) (and run-arg-input (eq? run-arg-input input-id)))) @@ -342,12 +352,31 @@ input, return #f." ((prefix _) #'prefix) (_ #f))) +(define (run-arg-separator run-arg) + "Return the item separator specified in @var{run-arg} syntax." + (syntax-case run-arg (array) + ;; array input specifier + ((array _ args ...) + (apply (syntax-lambda** (#:key separator) + (if (and separator + (not (string? (syntax->datum separator)))) + (raise-exception + (condition (ccwl-violation separator) + (formatted-message "Invalid #:separator parameter ~a. #:separator parameter must be a string." + (syntax->datum separator)))) + separator)) + #'(args ...))) + ;; prefixed array input specifier + ((_ (array input args ...)) + (run-arg-separator #'(array input args ...))) + (_ #f))) + (define (run-args run defined-input-identifiers) "Return a list of run arguments specified in @var{run} syntax. @var{defined-input-identifiers} is the list of input identifiers defined in the commands." (define (syntax->run-arg x) - (syntax-case x () + (syntax-case x (array) ;; Replace input symbol with quoted symbol. (input (identifier? #'input) ;; Ensure that specified input is defined in #:inputs of @@ -363,6 +392,9 @@ identifiers defined in the commands." ;; Leave string as is. (string-arg (string? (syntax->datum #'string-arg)) (list #'string-arg)) + ;; Extract input symbol from array input specifier. + ((array input _ ...) (identifier? #'input) + (syntax->run-arg #'input)) ;; Flatten prefixed string arguments. They have no ;; special meaning. ((prefix string-arg) (and (string? (syntax->datum #'prefix)) @@ -431,11 +463,14 @@ identifiers defined in the commands." (position (run-arg-position id run)) (run-arg (and position (list-ref run position)))) - #`(set-input-prefix - (set-input-position #,(input input-spec) - #,position) + #`(set-input-separator + (set-input-prefix + (set-input-position #,(input input-spec) + #,position) + #,(and run-arg + (run-arg-prefix run-arg))) #,(and run-arg - (run-arg-prefix run-arg))))) + (run-arg-separator run-arg))))) inputs)) (list #,@(map output outputs)) (list #,@(run-args run (map input-spec-id inputs))) diff --git a/ccwl/cwl.scm b/ccwl/cwl.scm index 53e6548..b4a6025 100644 --- a/ccwl/cwl.scm +++ b/ccwl/cwl.scm @@ -142,7 +142,8 @@ CWL YAML specification." ;; no effect. So, leave this be. (inputBinding . ,(filter-alist `((position . ,(input-position input)) - (prefix . ,(input-prefix input))))))) + (prefix . ,(input-prefix input)) + (itemSeparator . ,(input-separator input))))))) '()) ,@(input-other input))) diff --git a/doc/array-input-item-separators.scm b/doc/array-input-item-separators.scm new file mode 100644 index 0000000..8cb5900 --- /dev/null +++ b/doc/array-input-item-separators.scm @@ -0,0 +1,2 @@ +(command #:inputs (messages #:type (array string)) + #:run "echo" (array messages #:separator ",")) diff --git a/doc/ccwl.skb b/doc/ccwl.skb index bcbb0e1..726b405 100644 --- a/doc/ccwl.skb +++ b/doc/ccwl.skb @@ -349,6 +349,17 @@ inputs to be staged. Here is a rather concocted example.] (scheme-source "doc/array-types.scm")) (p [Nested array types are also supported.] (scheme-source "doc/nested-array-types.scm"))) + (section :title [Array input item separators] + :ident "section-array-input-item-separators" + (p [Occasionally, it is required to serialize array type inputs +by separating them with a specific item separator. This can be +achieved by explicitly specifying a separator in the ,(code [#:run]) +argument of ,(code [command]). For example, to use comma as the item +separator, you could do] + (scheme-source "doc/array-input-item-separators.scm") + [If ,(code "[foo, bar, aal, vel]") is passed in as ,(code +[messages]), then the command invoked is ,(samp "echo +foo,bar,aal,vel").])) (section :title [Scatter/gather] :ident "section-scatter-gather" (p [ccwl supports CWL's dotproduct scatter/gather feature using diff --git a/tests/ccwl.scm b/tests/ccwl.scm index e876912..d3e1a96 100644 --- a/tests/ccwl.scm +++ b/tests/ccwl.scm @@ -308,4 +308,11 @@ '(workflow ((foo #:type string)) (rename #:bar foobar)))) +(test-condition "commands with non-string #:separator parameters must raise a &ccwl-violation condition" + (ccwl-violation-with-message? + "Invalid #:separator parameter ~a. #:separator parameter must be a string.") + (macroexpand + '(command #:inputs (messages #:type (array string)) + #:run "echo" (array messages #:separator foo)))) + (test-end "ccwl") -- cgit v1.2.3