Documentation for property function stuff.

This commit is contained in:
Shinmera 2014-10-29 11:25:54 +01:00
parent d6908c8732
commit 833e7d2ad6
3 changed files with 47 additions and 0 deletions

View File

@ -166,6 +166,22 @@ Returns a list with the RESOLVEd SELECTOR.")
(list (resolve selector))))
(defgeneric consume-item (item readable-list)
(:documentation "Consumes items from READABLE-LIST as required by the ITEM.
Returned should be two values, the first being a property to compile (or NIL)
and the second a block to compile (or NIL).
By default, the following cases are handled:
(LIST)
Simply returns the ITEM as a block.
(SYMBOL)
If it's a keyword, reads until the next keyword or list and returns that as a
property to compile. With property-functions, some sublists may also be read
in automatically. See DEFINE-PROPERTY-FUNCTION. If it is a regular symbol,
CALL-NEXT-METHOD is invoked.
(T)
Signals an error.")
(:method (thing readable-list)
(error "Don't know what to do with ~s (not part of a property)." thing))
(:method ((subblock list) readable-list)

View File

@ -16,6 +16,7 @@
#:compile-property
#:compile-constraint
#:compile-selector
#:consume-item
#:compile-block
#:compile-sheet)
;; lass.lisp
@ -25,6 +26,13 @@
#:define-special-selector
#:generate
#:compile-and-write)
;; property-funcs.lisp
(:export
#:property-function
#:remove-property-function
#:define-property-function
#:define-simple-property-function
#:resolve-function)
;; special.lisp
(:export
#:define-single-arg-selector

View File

@ -9,22 +9,45 @@
(defvar *property-functions* (make-hash-table :test 'equalp))
(defun property-function (name)
"Returns a function to process a property function of NAME, if any."
(gethash (string name) *property-functions*))
(defun (setf property-function) (function name)
"Sets FUNCTION as the new processor for the property function NAME."
(setf (gethash (string name) *property-functions*)
function))
(defun remove-property-function (name)
"Removes the property function NAME."
(remhash (string name) *property-functions*))
(defmacro define-property-function (name args &body body)
"Define a new property function NAME, accepting ARGS.
The body should return a value to use directly, if possible a string.
The results of a property-function should not be RESOVLEd.
Property functions are function calls that occur as (part of) the
value of a property. Due to ambiguity issues with a general sub-block,
property functions need to be explicitly defined and may completely
differ depending on the property. Property functions defined with this
are only the defaults available for all properties. If you want to
minimise collision probability or avoid an illegal function for a
certain property, you should define a direct method on CONSUME-ITEM
to handle the reading of the property values manually."
`(setf (property-function ,(string name))
#'(lambda ,args ,@body)))
(defmacro define-simple-property-function (name args)
"Defines a property function that returns name(arg1,arg2...).
Only required arguments are allowed."
(assert (loop for key in '(&key &optional &rest &allow-other-keys)
never (find key args)) () "Only required arguments are allowed.")
`(define-property-function ,name ,args
(format NIL ,(format NIL "~(~a~)(~{~*~~a~^,~})" name args)
,@(loop for arg in args collect `(resolve ,arg)))))
(defun resolve-function (function &rest args)
"Turns the FUNCTION with its ARGS into a properly usable property value."
(let ((resolver (property-function function)))
(if resolver
(apply resolver args)