diff options
author | Sean Whitton <spwhitton@spwhitton.name> | 2021-03-10 17:39:41 -0700 |
---|---|---|
committer | Sean Whitton <spwhitton@spwhitton.name> | 2021-03-10 17:39:41 -0700 |
commit | f9affbcc8ad37ccd776114f63ed3b24f83864271 (patch) | |
tree | ce19e3c2a4bbca8ddbd127f8fdf933d36a22d6b6 /doc | |
parent | 6c86aa50cba6f607c51ac6aa075bc682bf2b1f9b (diff) | |
download | consfigurator-f9affbcc8ad37ccd776114f63ed3b24f83864271.tar.gz |
design for new propspec DSL
Signed-off-by: Sean Whitton <spwhitton@spwhitton.name>
Diffstat (limited to 'doc')
-rw-r--r-- | doc/propspecs.rst | 128 |
1 files changed, 105 insertions, 23 deletions
diff --git a/doc/propspecs.rst b/doc/propspecs.rst index 85c9b69..618909f 100644 --- a/doc/propspecs.rst +++ b/doc/propspecs.rst @@ -1,35 +1,117 @@ Property application specifications ("propspecs") ================================================= -Combinators +Purposes +-------- + +Property application specifications are a domain-specific language which +enables + +- combining properties to make new properties, e.g. with ``DEFPROPLIST``; and + +- representing the properties which are to be applied to a host in a form + which can be serialised using the Lisp printer. + +Definitions ----------- -Currently supported: ``(unapply (foo 1 2 3))``, ``((foo 1 2 3) on-change (bar -4 5 6) on-change (baz 7 8 9))`` and combinations thereof. +An *atomic property application* ("propapp") is a list satisfying the lambda +list ``(PROPERTY &rest ARGS)`` where ``PROPERTY`` is a symbol naming a +property and ``ARGS`` satisfies that property's lambda list. A *property +combinator* is a function which takes at least one propapp as one of its +arguments and returns a single propapp, or a macro which takes at least one +form which evaluates to a propapp as one of its arguments, and returns a form +which evaluates to a single propapp. A *property application specification* +("propspec") is + +i. a readably printable Lisp form; +ii. containing propapps combined using property combinators; +iii. containing no free variables except as bound by macro property + combinators, i.e., such that its evaluation is not affected by any + dynamic or lexical context; +iv. associated with a list of ASDF systems, and such that +v. evaluating the propspec produces an atomic property application which, when + those ASDF systems are loaded, applies the propapps in accordance with the + combinators. + +An *unevaluated property application specification* ("unevaluated propspec") +is a list of Lisp forms which can be converted into a property application +specification by + +i. replacing each argument in each propapp with the result of evaluating that + argument in the dynamic and lexical contexts in which the unevaluated + propspec occurs. +ii. wrapping a single property combinator which takes a variable number of + arguments around the resulting list of Lisp forms, usually ``SEQUENCE`` or + ``ALL-OF``. + +That is, the arguments to propapps in an unevaluated propspecs are forms which +will produce the arguments to the property, rather than those arguments +themselves. There is one special case: if the symbol naming the property ends +with the character ``.``, then the propapp is replaced with a new one +according to the following rules (the "dotted propapp rules"): + +i. the property to be applied is the property named by the symbol in the same + package and with the same name as the first element of the propapp, but + with the trailing period removed from the name; + +ii. the first argument is not evaluated if it is a list whose first element is + a keyword, or a if it is a list of lists where the first element of the + first list is a keyword; and + +iii. the last argument is treated as an embedded unevaluated propspec, and is + recursively converted into a propspec according to the usual evaluation + rules, where the surrounding combinator is ``ALL-OF``. + +Available combinators +--------------------- + +``ALL-OF`` +~~~~~~~~~~ + +Function. Applies each of the propapps passed as arguments without stopping +if any of them signal a failed change. Semantically, the propapps are ordered +with respect to their ``:HOSTATTRS`` subroutines, but not with respect to +their ``:APPLY`` subroutines. + +``SEQUENCE`` +~~~~~~~~~~~~ + +Function. Applies each of the propapps passed as arguments, stopping and +signalling a failed change if any of the proapps signal a failed change. +Semantically, each propapp implicitly depends upon the preceding propapps. + +``UNAPPLY`` +~~~~~~~~~~~ + +Function. Unapplies a single propapp. + +``ON-CHANGE`` +~~~~~~~~~~~~~ -Unevaluated property application specifications ("unevaluated propspecs") -------------------------------------------------------------------------- +Macro. Applies properties when attempting to apply the first did not return +``:NO-CHANGE``. -In an atomic property application within an unevaluated property application -specification, if the symbol naming the property ends with the character -``.``, then the following special evaluation rules apply: +Remarks +------- -1. The property to be applied is the property named by the symbol in the same - package and with the same name as the first element of the atomic property - application, but with the trailing period removed from the name. +The conversion of an unevaluated propspec into a propspec must resolve any +free variable references, except where those will be resolved by macro +property combinators. -2. The first argument is not evaluated if it is a list whose first element is - a keyword, or a if it is a list of lists where the first element of the - first list is a keyword. +The ``PROPS`` macro converts an unevaluated propspec into a propspec. -3. The last argument is treated as an unevaluated property application - specification and is converted into a property application specification - according to the usual evaluation rules. +The elements of unevaluated propspecs are typically arguments to macros, such +that the context of evaluation for forms which produce the arguments to the +propapps is the context in which the call to the containing macro appears. +The single property combinator which will be wrapped around the list of forms +depends on the macro. ``DEFHOST`` uses ``ALL-OF``, while ``DEFPROPLIST`` uses +``SEQUENCE``. -This is intended to make applications of properties like DEPLOYS, -DEPLOYS-THESE and CHROOT:DEBOOTSTRAPPED, which take property application -specifications as arguments, easier to read and write in the most common -cases. For example, you can write:: +The dotted propapp rules are intended to make applications of properties like +``DEPLOYS``, ``DEPLOYS-THESE`` and ``CHROOT:DEBOOTSTRAPPED``, which take +property application specifications as arguments, easier to read and write in +the most common cases. For example, you can write:: (deploys. (:ssh (:sudo :as "spwhitton@athena.example.com")) athena.example.com ((additional-property val1) @@ -41,5 +123,5 @@ instead of:: (make-propspec :props `((additional-property ,val1) (a-further-property ,val2)))) -(though note the parentheses around the two property applications remain, -unlike in ``DEPLOY``, ``DEFHOST`` etc.). +(though note the parentheses around the two propapps must remain, unlike in +``DEPLOY``, ``DEFHOST`` etc.). |