diff options
Diffstat (limited to 'terrafirma.lisp')
-rw-r--r-- | terrafirma.lisp | 32 |
1 files changed, 28 insertions, 4 deletions
diff --git a/terrafirma.lisp b/terrafirma.lisp index 78d74c9..b5ef90c 100644 --- a/terrafirma.lisp +++ b/terrafirma.lisp @@ -3,8 +3,10 @@ (defpackage #:terrafirma (:use #:cl) (:export - #:validate - #:defvalidator)) + #:validation-error ; Condition + #:validate ; Macrolet Symbol + #:defvalidator ; Macro + )) (in-package #:terrafirma) @@ -47,10 +49,31 @@ (defvar *instance*) (defmacro defvalidator ((var type &key name) &body body) + "Defines a validation function. If TYPE is a symbolic type identifier, +then the defined function will have a name like VALID-<TYPE>-P. +Otherwise a NAME must be provided. + +This means you can define validators for types like (CONS CHAR) if you +want. + +Within the body of DEFVALIDATOR, a special VALIDATE macro is +bound. Its syntax is: + +(VALIDATE CHECK FORMATSTRING &REST FORMATARGS) + +E.G. + + (validate (= 10 foo) \"Foo = ~s is not equal to 10\" foo) + +A VALIDATE form returns T if CHECK evaluates to non-nil. If CHECK +signals an error, or if CHECK returns NIL, then the whole validator +fails. + +If all VALIDATE forms pass, then the function returns T." (assert (and var (symbolp var)) (var) "VAR must be a symbol.") (let ((validator-name (cond ((and name (symbolp name)) name) - ((symbolp type) (intern (format nil "VALIDATED-~a" type))) + ((symbolp type) (intern (format nil "VALID-~a-P" type))) (t (error "Validator Name: Either TYPE must be a symbol or a NAME must be provided."))))) `(macrolet ((validate (check msg &rest args) (let ((suberr (gensym))) @@ -65,4 +88,5 @@ (defun ,validator-name (,var) (let ((terrafirma::*type* ',type) (terrafirma::*instance* ,var)) - ,@body))))) + ,@body + t))))) |