base: aws-operation: Pass request arguments to request constructor.
authorRicardo Wurmus <rekado@elephly.net>
Sun, 7 Mar 2021 12:03:30 +0000 (13:03 +0100)
committerRicardo Wurmus <rekado@elephly.net>
Sun, 7 Mar 2021 12:08:10 +0000 (13:08 +0100)
Instead of expecting a single input of the required type, the
procedure returned by AWS-OPERATION now accepts keyword arguments
intended for the request constructor.  This makes for a much less
verbose DSL.  Compare the explicit style

  (DeleteFileSystem
    (DeleteFileSystemRequest
      #:FileSystemId "fs-cabba9e"))

with the new implicit style:

  (DeleteFileSystem
   #:FileSystemId "fs-cabba9e")

* aws/base.scm (aws-operation): Accept an input-constructor; apply it
to a provided list of keyword arguments.
* language/aws/spec.scm (compile-operation): Generate code that
specifies the input constructor.
* README.org: Update examples.

README.org
aws/base.scm
language/aws/spec.scm

index dcebd483881efbcdd5626a59715b9603700c116d..c2e20a174a504a974b898e7d5ebf56914b251639 100644 (file)
@@ -1,13 +1,12 @@
 Guile AWS is pre-alpha software.  At the very least it’s yet another demonstration that Guile’s compiler tower can be used to generate an embedded domain specific language from JSON specifications.
 
-The DSL Guile AWS produces is unpolished and thus pretty repetitive and ugly.  Here is an example session to create an EFS and make it ready for mounting on an EC2 instance:
+Here is an example session to create an EFS and make it ready for mounting on an EC2 instance:
 
 #+begin_src scheme
 (import (aws api elasticfilesystem-2015-02-01))
 
 (CreateFileSystem
- (CreateFileSystemRequest
-  #:CreationToken (CreationToken "my-guile-aws-filesystem")))
+ #:CreationToken "my-guile-aws-filesystem")
 
 #; (("ThroughputMode" . "bursting")
  ("Tags" . #())
@@ -35,9 +34,8 @@ The DSL Guile AWS produces is unpolished and thus pretty repetitive and ugly.  H
  ("AvailabilityZoneId" . null))
 
 (CreateAccessPoint
- (CreateAccessPointRequest
-  #:ClientToken (ClientToken "my-guile-aws-filesystem")
-  #:FileSystemId (FileSystemId "fs-8bee03d0")))
+ #:ClientToken "my-guile-aws-filesystem"
+ #:FileSystemId "fs-8bee03d0")
 
 #;
 (("Tags" . #())
@@ -57,9 +55,8 @@ The DSL Guile AWS produces is unpolished and thus pretty repetitive and ugly.  H
 
 ;; Use the same subnet identifier as your EC2 instances.
 (CreateMountTarget
- (CreateMountTargetRequest
-  #:FileSystemId (FileSystemId "fs-8bee03d0")
-  #:SubnetId (SubnetId "subnet-7f6a7102")))
+ #:FileSystemId "fs-8bee03d0"
+ #:SubnetId "subnet-7f6a7102")
 
 #;
 (("VpcId" . "vpc-8e31f4e4")
@@ -75,25 +72,34 @@ The DSL Guile AWS produces is unpolished and thus pretty repetitive and ugly.  H
 
 ;; Tear down
 (DeleteMountTarget
- (DeleteMountTargetRequest
-  #:MountTargetId (MountTargetId "fsmt-284b4e71")))
+ #:MountTargetId "fsmt-284b4e71")
 
 #; #t
 
 (DeleteAccessPoint
- (DeleteAccessPointRequest
-  #:AccessPointId (AccessPointId "fsap-0d9a986284d086526")))
+ #:AccessPointId "fsap-0d9a986284d086526")
 
 #; #t
 
 (DeleteFileSystem
- (DeleteFileSystemRequest
-  #:FileSystemId (FileSystemId "fs-8bee03d0")))
+ #:FileSystemId "fs-8bee03d0")
 
 #; #t
 #+end_src
 
-The output is pretty bad as it is currently unprocessed SXML or JSON.  It may not even work at all, because the AWS APIs are all a little different.
+You can also separate the request definition from submitting the request.  This is useful if you want your requests type-checked well before even getting near to submission:
+
+#+begin_src scheme
+;; This is type-checked right away, so any errors will show up here.
+(define req
+  (DeleteFileSystemRequest
+   #:FileSystemId "fs-8bee03d0"))
+
+;; Actually submit the request
+(DeleteFileSystem req)
+#+end_src
+
+As you can see, the output is pretty bad as it is currently unprocessed SXML or JSON.  It may not even work at all, because the AWS APIs are all a little different.
 
 Considering all these caveats there are a couple of obvious things to work on:
 
index 21a55b900a9c4a31361f2f052a478522de6e5664..676fdd165dffe971b74bceee96b610841f6dd092 100644 (file)
@@ -1,5 +1,5 @@
 ;;; guile-aws --- Scheme DSL for the AWS APIs
-;;; Copyright © 2019 Ricardo Wurmus <rekado@elephly.net>
+;;; Copyright © 2019, 2021 Ricardo Wurmus <rekado@elephly.net>
 ;;;
 ;;; Guile-AWS is free software: you can redistribute it and/or modify
 ;;; it under the terms of the GNU General Public License as published
                    value type))))
 
 \f
-(define* (aws-operation requester #:key name input-type output-type http documentation)
+(define* (aws-operation requester
+                        #:key
+                        name
+                        input-constructor
+                        input-type
+                        output-type
+                        http documentation)
   (let ((proc
-         (lambda* (#:optional input)
-           (unless (eq? (aws-name input) input-type)
-             (error (format #f "~a: input must be of type ~a: ~a~%"
-                            name input-type input)))
-           ;; TODO: do something with the response!
-           (requester #:http http #:operation-name name #:input input))))
+         (lambda args
+           (let ((input*
+                  (match args
+                    ;; Accept a keyword list and pass it to the
+                    ;; appropriate constructor.
+                    (((? keyword?) . rest)
+                     (apply input-constructor args))
+                    ;; Otherwise type check the input
+                    ((input)
+                     (unless (eq? (aws-name input) input-type)
+                       (error (format #f "~a: input must be of type ~a: ~a~%"
+                                      name input-type input)))
+                     input)
+                    (() #false))))
+             ;; TODO: do something with the response!
+             (requester #:http http #:operation-name name #:input input*)))))
     (set-procedure-property! proc 'documentation documentation)
     (set-procedure-property! proc 'name name)
     proc))
index c40367b8dd3d858c0bab0ba7c9e30aeee132b882..f271d2787624342b0f63978cb7f4c9f0cdb97434 100644 (file)
@@ -200,6 +200,10 @@ if this is not a primitive data type."
           (aws-operation
            operation->request
            #:name ,name
+           #:input-constructor
+           ,(and=> (assoc-ref spec "input")
+                   (lambda (input)
+                     (and=> (assoc-ref input "shape") string->symbol)))
            #:input-type
            ',(and=> (assoc-ref spec "input")
                     (lambda (input)