aboutsummaryrefslogtreecommitdiff
path: root/doc/propspecs.rst
diff options
context:
space:
mode:
authorSean Whitton <spwhitton@spwhitton.name>2021-03-10 17:39:41 -0700
committerSean Whitton <spwhitton@spwhitton.name>2021-03-10 17:39:41 -0700
commitf9affbcc8ad37ccd776114f63ed3b24f83864271 (patch)
treece19e3c2a4bbca8ddbd127f8fdf933d36a22d6b6 /doc/propspecs.rst
parent6c86aa50cba6f607c51ac6aa075bc682bf2b1f9b (diff)
downloadconsfigurator-f9affbcc8ad37ccd776114f63ed3b24f83864271.tar.gz
design for new propspec DSL
Signed-off-by: Sean Whitton <spwhitton@spwhitton.name>
Diffstat (limited to 'doc/propspecs.rst')
-rw-r--r--doc/propspecs.rst128
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.).