Update of /project/mcclim/cvsroot/mcclim/Drei
In directory clnet:/tmp/cvs-serv26314
Modified Files:
lisp-syntax.lisp
Log Message:
Somewhat-fixed `token-to-object's handling of backquote forms. Has
been tested by repeatedly using `token-to-object' to convert
lisp-syntax.lisp into lists and feeding them to `eval' (this calls out
for a test case that recompiles Drei using code extracted with this
method!)
--- /project/mcclim/cvsroot/mcclim/Drei/lisp-syntax.lisp 2006/12/04 19:20:47 1.10
+++ /project/mcclim/cvsroot/mcclim/Drei/lisp-syntax.lisp 2006/12/06 11:31:12 1.11
@@ -1050,9 +1050,9 @@
;;;;;;;;;;;;;;;; Comma
;;; parse trees
-(defclass comma-form (form) ())
-(defclass comma-at-form (form) ())
-(defclass comma-dot-form (form) ())
+(defclass comma-form (form complete-form-mixin) ())
+(defclass comma-at-form (form complete-form-mixin) ())
+(defclass comma-dot-form (form complete-form-mixin) ())
(define-parser-state |, | (form-may-follow) ())
(define-parser-state |, form | (lexer-toplevel-state parser-state) ())
@@ -2477,25 +2477,21 @@
:case case
:no-error t))
-(defgeneric token-to-object (syntax token &key no-error package quote read &allow-other-keys)
+(defgeneric token-to-object (syntax token &key no-error package read backquoted &allow-other-keys)
(:documentation "Return the Lisp object `token' would evaluate
to if read. An attempt will be made to construct objects from
incomplete tokens. This function may signal an error if
`no-error' is nil and `token' cannot be converted to a Lisp
object. Otherwise, nil will be returned.")
- (:method :around (syntax (token t) &rest args &key
- package quote no-error &allow-other-keys)
+ (:method :around (syntax (token t) &key package no-error &allow-other-keys)
;; Ensure that every symbol that is READ will be looked up
;; in the correct package. Also handle quoting.
(flet ((act ()
(let ((*package* (or package
(package-at-mark
- syntax (start-offset token)))))
- (cond (quote
- (setf (getf args :quote) nil)
- `',(call-next-method))
- (t
- (call-next-method))))))
+ syntax (start-offset token)))))
+
+ (call-next-method))))
(if no-error
(ignore-errors (act))
(act))))
@@ -2510,6 +2506,57 @@
(error "Cannot convert incomplete form to Lisp object: ~A"
token))))
+;;; The complicated primary structure forms.
+
+;; The problem is that we can't portably create in-memory backquote
+;; forms, so we have to rewrite them to calls to `nconc'. I think this
+;; is valid, because the CLHS doesn't specify the in-memory
+;; representation of backquoted forms, and thus the user can't assume
+;; that it isn't just a whole bunch of calls to `nconc' anyway.
+(defmethod token-to-object (syntax (token list-form) &rest args &key backquoted)
+ (if backquoted
+ `(nconc ,@(loop for child in (children token)
+ if (typep child 'comma-at-form)
+ collect (apply #'token-to-object syntax child :backquoted nil args)
+ else if (typep child 'comma-form)
+ collect `(list ,(apply #'token-to-object syntax child :backquoted nil args))
+ else if (form-token-p child)
+ collect `(list ,`',(apply #'token-to-object syntax child args))
+ else if (formp child)
+ collect `(list ,(apply #'token-to-object syntax child args))))
+ (mapcar #'(lambda (child)
+ (apply #'token-to-object syntax child args))
+ (remove-if-not #'formp (children token)))))
+
+(defmethod token-to-object (syntax (token complete-quote-form) &rest args &key backquoted)
+ (if backquoted
+ (let ((quoted-form (first-form (children token))))
+ (if (form-token-p quoted-form)
+ `(list 'quote (quote ,(apply #'token-to-object syntax (second (children token)) args)))
+ `(list 'quote ,(apply #'token-to-object syntax (second (children token)) args))))
+ `',(apply #'token-to-object syntax (second (children token)) args)))
+
+(defmethod token-to-object (syntax (token incomplete-quote-form) &rest args)
+ (declare (ignore args))
+ ;; Utterly arbitrary, but reasonable in my opinion.
+ '(quote))
+
+;; I'm not sure backquotes are handled correctly, but they should be,
+;; at least when :read t is specified.
+(defmethod token-to-object (syntax (token backquote-form) &rest args)
+ (let ((backquoted-form (first-form (children token))))
+ (if (form-token-p backquoted-form)
+ `',(apply #'token-to-object syntax backquoted-form args)
+ (apply #'token-to-object syntax backquoted-form :backquoted t args))))
+
+(defmethod token-to-object (syntax (token comma-form) &rest args)
+ (apply #'token-to-object syntax (first-form (children token)) :backquoted nil args))
+
+(defmethod token-to-object (syntax (token comma-at-form) &rest args)
+ (apply #'token-to-object syntax (first-form (children token)) :backquoted nil args))
+
+;;; The atom(-ish) forms.
+
(defmethod token-to-object (syntax (token complete-token-lexeme)
&key no-error read (case (readtable-case *readtable*))
&allow-other-keys)
@@ -2531,13 +2578,6 @@
(let ((*read-base* (base syntax)))
(read-from-string (token-string syntax token))))
-(defmethod token-to-object (syntax (token list-form) &rest args)
- (loop for child in (children token)
- if (typep child 'comma-at-form)
- nconc (listed (apply #'token-to-object syntax child args))
- else if (formp child)
- collect (apply #'token-to-object syntax child args)))
-
(defmethod token-to-object (syntax (token simple-vector-form) &key &allow-other-keys)
(apply #'vector (call-next-method)))
@@ -2551,34 +2591,6 @@
(declare (ignore no-error))
(read-from-string (token-string syntax token)))
-(defmethod token-to-object (syntax (token complete-quote-form) &rest args)
- (apply #'token-to-object syntax (second (children token)) :quote t args))
-
-(defmethod token-to-object (syntax (token incomplete-quote-form) &rest args)
- (declare (ignore args))
- ;; Utterly arbitrary, but reasonable in my opinion.
- '(quote))
-
-;; I'm not sure backquotes are handled correctly, but they should be,
-;; at least when :read t is specified.
-(defmethod token-to-object (syntax (token backquote-form) &rest args)
- (let ((backquoted-form (first-form (children token))))
- (if (form-list-p backquoted-form)
- `(list ,@(loop for element in (children backquoted-form)
- if (form-comma-p element)
- collect (apply #'token-to-object syntax element args)
- else if (form-comma-at-p element)
- nconc (listed (apply #'token-to-object syntax element args))
- else if (formp element)
- collect (apply #'token-to-object syntax element :quote t args)))
- `',(apply #'token-to-object syntax backquoted-form args))))
-
-(defmethod token-to-object (syntax (token comma-form) &rest args)
- (apply #'token-to-object syntax (first-form (children token)) args))
-
-(defmethod token-to-object (syntax (token comma-at-form) &rest args)
- (apply #'token-to-object syntax (first-form (children token)) args))
-
(defmethod token-to-object (syntax (token function-form) &rest args)
(list 'cl:function (apply #'token-to-object syntax (second (children token)) args)))