X-Git-Url: https://git.distorted.org.uk/~mdw/sod/blobdiff_plain/e0808c472145fc81e52898bc9ac289e10c4f4f41..refs/heads/master:/src/pset-proto.lisp diff --git a/src/pset-proto.lisp b/src/pset-proto.lisp index d77a058..f03ec51 100644 --- a/src/pset-proto.lisp +++ b/src/pset-proto.lisp @@ -43,9 +43,9 @@ (:predicate propertyp) (:conc-name p-) (:constructor %make-property - (name value - &key type location seenp - &aux (key (property-key name)) (%type type)))) + (name value + &key type location seenp + &aux (key (property-key name)) (%type type)))) "A simple structure for holding a property in a property set. The main useful feature is the ability to tick off properties which have @@ -55,24 +55,19 @@ distinctly about identifiers, strings and symbols, and we've only got two obvious Lisp types to play with. Sad, but true." - (name nil :type (or string symbol)) - (value nil :type t) - (%type nil :type symbol) - (location (file-location nil) :type file-location) - (key nil :type symbol) + (name nil :type (or string symbol) :read-only t) + (value nil :type t :read-only t) + (%type nil :type symbol :read-only t) + (location (file-location nil) :type file-location :read-only t) + (key nil :type symbol :read-only t) (seenp nil :type boolean)) -(define-access-wrapper p-type p-%type) +(define-access-wrapper p-type p-%type :read-only t) (export 'decode-property) (defgeneric decode-property (raw) (:documentation "Decode a RAW value into a TYPE, VALUE pair.") - (:method ((raw symbol)) (values :symbol raw)) - (:method ((raw integer)) (values :int raw)) - (:method ((raw string)) (values :string raw)) - (:method ((raw character)) (values :char raw)) (:method ((raw property)) (values (p-type raw) (p-value raw))) - (:method ((raw cons)) (values (car raw) (cdr raw))) - (:method ((raw function)) (values :func raw))) + (:method ((raw cons)) (values (car raw) (cdr raw)))) (export 'make-property) (defun make-property (name raw-value &key type location seenp) @@ -85,52 +80,6 @@ :location (file-location location) :seenp seenp))) -(defun string-to-symbol - (string &key (package *package*) (swap-case t) (swap-hyphen t)) - "Convert STRING to a symbol in PACKAGE. - - Parse off a `PACKAGE:' prefix from STRING if necessary, to identify the - package; PACKAGE is used if there isn't a prefix. A doubled colon allows - access to internal symbols, and will intern if necessary. Note that - escape characters are /not/ processed; don't put colons in package names - if you want to use them from SOD property sets. - - The portions of the string are modified by `frob-identifier'; the - arguments SWAP-CASE and SWAP-HYPHEN are passed to `frob-identifier' to - control this process." - - (let* ((length (length string)) - (colon (position #\: string))) - (multiple-value-bind (start internalp) - (cond ((not colon) (values 0 t)) - ((and (< (1+ colon) length) - (char= (char string (1+ colon)) #\:)) - (values (+ colon 2) t)) - (t - (values (1+ colon) nil))) - (when colon - (let* ((package-name (if (zerop colon) "KEYWORD" - (frob-identifier (subseq string 0 colon) - :swap-case swap-case - :swap-hyphen swap-hyphen))) - (found (find-package package-name))) - (unless found - (error "Unknown package `~A'" package-name)) - (setf package found))) - (let ((name (frob-identifier (subseq string start) - :swap-case swap-case - :swap-hyphen swap-hyphen))) - (multiple-value-bind (symbol status) - (funcall (if internalp #'intern #'find-symbol) name package) - (cond ((or internalp (eq status :external)) - symbol) - ((not status) - (error "Symbol `~A' not found in package `~A'" - name (package-name package))) - (t - (error "Symbol `~A' not external in package `~A'" - name (package-name package))))))))) - (export 'coerce-property-value) (defgeneric coerce-property-value (value type wanted) (:documentation @@ -144,9 +93,10 @@ ;; say it didn't work. (:method (value type wanted) (if (eql type wanted) value - (error "Incorrect type: expected ~A but found ~A" wanted type))) + (error "Incorrect type: expected ~(~A~) but found ~(~A~)" + wanted type))) - ;; If the caller asks for type T then give him the raw thing. + ;; If the caller asks for type T then give them the raw thing. (:method (value type (wanted (eql t))) (declare (ignore type)) value)) @@ -305,6 +255,7 @@ ;;;-------------------------------------------------------------------------- ;;; Utility macros. +(export 'default-slot-from-property) (defmacro default-slot-from-property ((instance slot &optional (slot-names t)) (pset property type @@ -316,7 +267,8 @@ We initialize SLOT in INSTANCE. In full: if PSET contains a property called NAME, then convert it to TYPE, bind the value to PVAR and evaluate CONVERT-FORMS -- these default to just using the property value. If - there's no property, and the slot is named in SLOT-NAMES and currently + there's no property, and DEFAULT-FORMS contains at least one non- + declaration form, and the slot is named in SLOT-NAMES and currently unbound, then evaluate DEFAULT-FORMS and use their value to compute the slot value." @@ -332,7 +284,8 @@ (setf (slot-value ,instance ,slot) (with-default-error-location (,floc) ,@(or convert-forms `(,pvar)))) - (default-slot (,instance ,slot ,slot-names) - ,@body))))))) + ,@(and body + `((default-slot (,instance ,slot ,slot-names) + ,@body))))))))) ;;;----- That's all, folks --------------------------------------------------