summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ccwl/ccwl.scm181
1 files changed, 89 insertions, 92 deletions
diff --git a/ccwl/ccwl.scm b/ccwl/ccwl.scm
index e173d9e..547cf23 100644
--- a/ccwl/ccwl.scm
+++ b/ccwl/ccwl.scm
@@ -28,6 +28,7 @@
   #:use-module (srfi srfi-9 gnu)
   #:use-module (srfi srfi-26)
   #:use-module (ice-9 match)
+  #:use-module (ccwl utils)
   #:use-module (ccwl yaml)
   #:export (command
             workflow
@@ -127,104 +128,68 @@
 (define append-command-outputs
   (field-appender command-outputs set-command-outputs))
 
-(define* (command id arguments #:key (additional-inputs '()) (outputs '()) (other '()))
-  (make-step id
-             (make-command additional-inputs outputs arguments #f other)
-             ;; A command can use the same input multiple times. So,
-             ;; deduplicate.
-             (delete-duplicates
-              (append (filter input? arguments)
-                      additional-inputs)
-              input=?)
-             outputs))
+(define* (command #:key run (additional-inputs '()) (outputs '()) stdin (other '()))
+  (make-command additional-inputs outputs run stdin other))
 
 (define (input=? input1 input2)
   (string=? (input-id input1)
             (input-id input2)))
 
-(define (auto-connect steps)
-  "Auto-connect STEPS by matching inputs to outputs using their unique
-identifiers. If any inputs are already matched, they are not
-re-matched."
-  (map (lambda (step)
-         (set-step-in step
-                      (map (lambda (input)
-                             ;; If input is already connected, return
-                             ;; it unaltered. Else, try to connect it
-                             ;; to a source.
-                             (cond
-                              ((input-source input)
-                               input)
-                              ;; Input that should be connected to
-                              ;; some intermediate output
-                              ((find (lambda (step)
-                                       (member (input-id input)
-                                               (map output-id (step-out step))))
-                                     steps)
-                               => (lambda (source-step)
-                                    (set-input-source input
-                                                      (string-append (step-id source-step)
-                                                                     "/" (input-id input)))))
-                              ;; Non-internal input that should be
-                              ;; interfaced with the outside world
-                              (else input)))
-                           (step-in step))))
-       steps))
-
-(define* (workflow id steps outputs #:key (other '()))
+(define (invoke-command step-id command . args)
+  (make-step step-id
+             command
+             (plist->alist args)
+             (command-outputs command)))
+
+(define* (make-workflow steps outputs #:key (other '()))
   "Build a Workflow class CWL workflow."
-  (let* ((steps (auto-connect steps))
-         (inputs
-          ;; When the same input is used by multiple steps, there will
-          ;; be duplicates. So, deduplicate.
-          (delete-duplicates
-           (append (append-map step-in steps)
-                   ;; If an input is directly copied to the output, an
-                   ;; output-source will be an <input> object.
-                   (filter-map (lambda (output)
-                                 (and (input? (output-source output))
-                                      (output-source output)))
-                               outputs))
-           input=?))
-         ;; List of non-internal inputs that should be interfaced with
-         ;; the outside world.
-         (interface-inputs (remove input-source inputs)))
-    (make-step id
-               `((cwl-version . ,%cwl-version)
-                 (class . Workflow)
-                 (requirements (Subworkflow-feature-requirement))
-                 ,@other
-                 (inputs . ,(map (lambda (input)
-                                   `(,(input-id input)
-                                     ,@(filter-alist
-                                        `((type . ,(input-type input))
-                                          (label . ,(input-label input))
-                                          (default . ,(and (not (unspecified-default? (input-default input)))
-                                                           (input-default input)))))
-                                     ,@(input-other input)))
-                                 interface-inputs))
-                 (outputs . ,(map (lambda (output)
-                                    `(,(output-id output)
-                                      (type . ,(output-type output))
-                                      (output-source . ,(match (output-source output)
-                                                          ((? string? source) source)
-                                                          ((? input? input) (input-id input))))))
-                                  outputs))
-                 (steps . ,(map (lambda (step)
-                                  `(,(step-id step)
-                                    (in . ,(map (lambda (input)
-                                                  (cons (input-id input)
-                                                        (or (input-source input)
-                                                            (input-id input))))
-                                                (step-in step)))
-                                    (out . ,(list->vector (map output-id (step-out step))))
-                                    (run . ,(match (step-run step)
-                                              ((? command? command)
-                                               (command->cwl command))
-                                              (tree tree)))))
-                                steps)))
-               interface-inputs
-               outputs)))
+  `((cwl-version . ,%cwl-version)
+    (class . Workflow)
+    (requirements (Subworkflow-feature-requirement))
+    ,@other
+    (inputs . ,(map (lambda (input)
+                      `(,(input-id input)
+                        ,@(filter-alist
+                           `((type . ,(input-type input))
+                             (label . ,(input-label input))
+                             (default . ,(and (not (unspecified-default? (input-default input)))
+                                              (input-default input)))))
+                        ,@(input-other input)))
+                    ;; When the same input is used by multiple steps,
+                    ;; there will be duplicates. So, deduplicate.
+                    (delete-duplicates
+                     (append-map (lambda (step)
+                                   (filter-map (match-lambda
+                                                 ((_ . (? input? input))
+                                                  input)
+                                                 (_ #f))
+                                               (step-in step)))
+                                 steps)
+                     input=?)))
+    (outputs . ,(map (lambda (output)
+                       `(,(output-id output)
+                         (type . ,(match (output-type output)
+                                    ('stdout 'File)
+                                    (some-other-type some-other-type)))
+                         (output-source . ,(match (output-source output)
+                                             ((? string? source) source)
+                                             ((? input? input) (input-id input))))))
+                     outputs))
+    (steps . ,(map (lambda (step)
+                     `(,(step-id step)
+                       (in . ,(map (lambda (in)
+                                     (match in
+                                       ((id . (? string? source))
+                                        in)
+                                       ((id . (? input? input))
+                                        (cons id (input-id input)))))
+                                   (step-in step)))
+                       (out . ,(list->vector (map output-id (step-out step))))
+                       (run . ,(match (step-run step)
+                                 ((? command? command)
+                                  (command->cwl command))
+                                 (tree tree)))))
+                   steps))))
 
 (define* (pipeline id steps
                    #:optional
@@ -351,3 +316,35 @@ re-matched."
                          (command->cwl run)
                          run))
          <>)))
+
+(define (workflow-steps x)
+  (syntax-case x ()
+    ((command (step-id) args ...)
+     (cons #`(invoke-command
+              step-id command
+              #,@(append-map (lambda (pair)
+                               (syntax-case pair ()
+                                 ((key . (_ (id) _ ...))
+                                  (list #'key (string-append
+                                               (syntax->datum #'id)
+                                               "/" (symbol->string
+                                                    (keyword->symbol
+                                                     (syntax->datum #'key))))))
+                                 ((key . atom)
+                                  (list #'key #'atom))))
+                             (pairify #'(args ...))))
+           (append-map workflow-steps #'(args ...))))
+    (atom (list))))
+
+(define-syntax workflow
+  (lambda (x)
+    (syntax-case x ()
+      ((_ root)
+       #`(make-workflow
+          (list #,@(workflow-steps #'root))
+          #,(syntax-case x ()
+              ((_ (command (step-id) _ ...))
+               #'(map (lambda (output)
+                        (set-output-source
+                         output (string-append step-id "/" (output-id output))))
+                      (command-outputs command)))))))))