Mercurial > core / lisp/lib/dat/sxp.lisp
changeset 698: |
96958d3eb5b0 |
parent: |
5bd0eb9fa1fa
|
author: |
Richard Westhaver <ellis@rwest.io> |
date: |
Fri, 04 Oct 2024 22:04:59 -0400 |
permissions: |
-rw-r--r-- |
description: |
fixes |
1 ;;; lib/dat/sxp.lisp --- S-eXPressions 3 ;; sxp is a unified S-Expression data format 9 (or (consp form) (atom form))) 15 (define-condition sxp-error (error) ()) 17 (define-condition sxp-syntax-error (sxp-error) ()) 20 (defgeneric wrap (self form)) 21 (defgeneric unwrap (self)) 22 (defgeneric unwrap-or (self lambda)) 23 (defgeneric sxpp (self form)) 25 (defgeneric write-sxp-stream (self stream &key pretty case)) 26 (defgeneric read-sxp-stream (self stream)) 28 (defgeneric build-ast (self &key &allow-other-keys) 29 (:documentation "build the sxp representation of SELF and store it in the :ast 30 slot. The :ast slot is always ignored.")) 32 (defgeneric load-ast (self) 33 (:documentation "load the object SELF from the :ast slot.")) 35 (defgeneric load-ast* (self context) 36 (:documentation "load the object SELF from the :ast slot with additional CONTEXT.")) 40 ((ast :initarg :ast :type form :accessor ast)) 41 (:documentation "Dynamic class representing a SXP form.")) 43 (defmethod wrap ((self sxp) form) (setf (slot-value self 'ast) form)) 45 (defmethod unwrap ((self sxp)) (slot-value self 'ast)) 47 (defmethod unwrap-or ((self sxp) (else-fn function)) 48 (if (slot-unbound 'sxp self 'ast) 49 (slot-value self 'ast) 50 (if (null (slot-value self 'ast)) 53 (defmethod write-sxp-stream ((self sxp) stream &key (pretty *print-pretty*) (case :downcase)) 59 (defmethod read-sxp-stream ((self sxp) stream) 60 (setf (ast self) (slurp-stream-forms stream :count nil))) 62 ;; (defsetf unwrap ) (defsetf wrap ) 65 (defun read-sxp-file (file) 66 (make-instance 'sxp :ast (read-file-forms file))) 68 (defun write-sxp-file (sxp file &optional &key if-exists) 69 (with-output-file (out file) :if-exists if-exists 70 (write-sxp-stream sxp out))) 72 (defun read-sxp-string (self str) (with-input-from-string (s str) (read-sxp-stream self s))) 74 (defun write-sxp-string (sxp) 75 (let ((ast (ast sxp))) 77 (if (> (length ast) 1) 79 (write-to-string (car ast))))) 81 (defun make-sxp (&rest form) (make-instance 'sxp :ast form)) 83 (deftype sxp-fmt-designator () '(member :canonical :collapsed :pretty)) 85 (declaim (inline unwrap-object)) ;; inline -200 86 (defun unwrap-object (obj &key (slots t) (methods nil) 87 (indirect nil) (tag nil) 88 (unboundp nil) (nullp nil) 90 "Build and return a new `form' from OBJ by traversing the class 91 definition. This differs from the generic function `unwrap' which 92 always uses the ast slot as an internal buffer. We can also call this 93 on any class instance (doesn't need to subclass `sxp'). 95 SLOTS specifies the slots to be included in the output. If the value 96 is t, all slots are included. The ast slot is not included by default, 97 but this behavior may change in future revisions. 99 When INDIRECT is non-nil, also include methods which indirectly 102 When TAG is non-nil, return a cons where car is TAG and cdr is the 103 output. If TAG is t, use the class-name symbol." 104 (declare (type standard-object obj) 105 (type (or list boolean) slots) 106 (type (or list boolean) methods) 107 (type boolean indirect) 109 (unless (or slots methods) 110 (error "Required one missing key arg: SLOTS or METHODS")) 111 (let* ((class (class-of obj)) 112 (res (when tag (list (if (eq t tag) (class-name class) tag))))) 114 (when-let ((slots (when slots 115 (list-class-slots class slots exclude)))) 116 (let ((slot-vals (list-slot-values-using-class class obj (remove-if #'null slots) nullp unboundp))) 119 (return-from unwrap (push slot-vals res))))) 120 (when-let ((methods (when methods (list-class-methods class methods indirect)))) 125 (defun wrap-object (class form) 126 "Given a CLASS prototype and an input FORM, return a new instance of 127 CLASS. FORM is assumed to be the finalized lisp object which has 128 already passed through `read' -- not a string or file-stream for 130 (declare (type class class) 133 (defun file-read-forms (file) 134 (declare (sb-kernel:pathname-designator file)) 135 (awhen (the list (read-file-forms file)) 136 (if (> (length it) 1) 140 ;; (defmacro define-fmt ()) 141 ;; (defmacro define-macro ())