;;;; ;;;; This file defines a dynamic string encapsulation called ;;;; "dstring". It simply stores the characters on a list in reverse ;;;; order making it easy for "cons" to append to the string. ;;;; However, with Lisp, it is better to just us adjustable arrays ;;;; (see "dstring.lisp").

;;;; ;;;; @author Paul Serice ;;;; ;;;; ;; This method returns a new, empty dynamic string. Unlike Scheme, ;; global variables in Lisp are dynamically scoped and override ;; lexically scoped variables with the same name. To work around ;; this, we use "gensym" to create a unique name for the underlying ;; list of characters, and a macro to generate the return value. ;; ;; @return dstring (defmacro dstring () (let ((lst-name (gensym))) `(let ((,lst-name '())) ;; Return a list of functions that have the list with name ;; "list-name" lexically scoped. (list ;; Get lst. (lambda () ,lst-name) ;; Set lst. (lambda (x) (setf ,lst-name x)))))) ;;;; ;; Get the underlying list. ;; ;; @param[in] s dstring ;; @return underlying list (defmacro dstring-get-lst (s) `(funcall (car ,s))) ;;;; ;; Set the underlying list. The list should hold the characters in ;; reverse order to match the way "cons" works. ;; ;; @param[in] s dstring ;; @param[in] lst new list of characters to use. ;; @return underlying list (defmacro dstring-set-lst (s lst) `(funcall (cadr ,s) ,lst)) ;;;; ;; Return the conversion of the dstring "s" to a list. ;; ;; @param[in] s dstring ;; @return conversion of s to a list (defun dstring->list (s) (reverse (dstring-get-lst s))) ;;;; ;; Return the conversion of the dstring "s" to a standard string. ;; ;; @param[in] s dstring ;; @return conversion of s to a standard string (defun dstring->string (s) (coerce (dstring->list s) 'string)) ;;;; ;; Append the standard string "x" to the dstring "s". ;; ;; @param[in] s dstring ;; @param[in] x standard string (defun dstring-append (s x) (dstring-set-lst s (reduce (lambda (rv c) (cons c rv)) (coerce x 'list) :initial-value (dstring-get-lst s)))) ;;;; ;; Append the character "c" to the dstring "s". ;; ;; @param[in] s dstring ;; @param[in] c character (defun dstring-append-char (s c) (dstring-set-lst s (cons c (dstring-get-lst s)))) ;;;; ;; Append the optional standard string "x" to the dstring "s" then ;; append the new-line character. ;; ;; @param[in] s dstring ;; @param[in] x optional standard string to append (defun dstring-append-line (s &optional (x nil)) (if (not (null x)) (dstring-append s x)) (dstring-append-char s #\newline)) ;;;; ;; Clear the dstring "s". (defun dstring-clear (s) (dstring-set-lst s '()))