Update of /project/movitz/cvsroot/movitz/losp/muerte
In directory clnet:/tmp/cvs-serv22261
Modified Files:
eval.lisp
Log Message:
Add and employ define-eval-special-operator.
--- /project/movitz/cvsroot/movitz/losp/muerte/eval.lisp 2008/04/27 16:14:10 1.34
+++ /project/movitz/cvsroot/movitz/losp/muerte/eval.lisp 2008/07/09 20:11:23 1.35
@@ -10,7 +10,7 @@
;;;; Author: Frode Vatvedt Fjeld <frodef(a)acm.org>
;;;; Created at: Fri Oct 19 21:15:12 2001
;;;;
-;;;; $Id: eval.lisp,v 1.34 2008/04/27 16:14:10 ffjeld Exp $
+;;;; $Id: eval.lisp,v 1.35 2008/07/09 20:11:23 ffjeld Exp $
;;;;
;;;;------------------------------------------------------------------
@@ -19,6 +19,23 @@
(in-package muerte)
+(define-compile-time-variable *eval-special-operators*
+ (make-hash-table :test #'eq))
+
+(defmacro define-eval-special-operator (operator lambda-list &body body)
+ (let ((name (intern (format nil "~A-~A" 'eval-special-operator operator))))
+ `(progn
+ (eval-when (:compile-toplevel)
+ (setf (gethash (find-symbol ,(symbol-name operator))
+ *eval-special-operators*)
+ ',name))
+ (defun ,name ,lambda-list ,@body))))
+
+(defun special-operator-p (symbol)
+ (if (gethash symbol *eval-special-operators*)
+ t
+ nil))
+
(defun eval (form)
(eval-form form nil))
@@ -77,6 +94,130 @@
;;;
;;;Figure 3-2. Common Lisp Special Operators
+(define-eval-special-operator quote (form env)
+ (declare (ignore env))
+ (cadr form))
+
+(define-eval-special-operator progn (form env)
+ (eval-progn (cdr form) env))
+
+(define-eval-special-operator if (form env)
+ (if (eval-form (second form) env)
+ (eval-form (third form) env)
+ (eval-form (fourth form) env)))
+
+(define-eval-special-operator block (form env)
+ (catch form
+ (eval-progn (cddr form)
+ (cons (list* +eval-binding-type-block+
+ (cadr form)
+ form)
+ env))))
+
+(define-eval-special-operator return-from (form env)
+ (let ((b (cdr (op-env-binding env (cadr form) +eval-binding-type-block+))))
+ (unless b (error "Block ~S is not visible." (cadr form)))
+ (throw (cdr b)
+ (eval-form (caddr form) env))))
+
+(define-eval-special-operator macrolet (form env)
+ (dolist (macrolet (cadr form))
+ (destructuring-bind (name lambda &body body)
+ macrolet
+ (check-type name symbol)
+ (check-type lambda list)
+ (push (list* +eval-binding-type-macrolet+
+ name
+ (cdr macrolet))
+ env)))
+ (eval-progn (cddr form)
+ env))
+
+(define-eval-special-operator let (form env)
+ (let ((var-specs (cadr form))
+ (declarations-and-body (cddr form)))
+ (let (special-vars
+ special-values
+ (local-env env))
+ (multiple-value-bind (body declarations)
+ (parse-declarations-and-body declarations-and-body)
+ (dolist (var-spec var-specs)
+ (multiple-value-bind (var init-form)
+ (if (atom var-spec)
+ (values var-spec nil)
+ (values (car var-spec) (cadr var-spec)))
+ (cond
+ ((or (symbol-special-variable-p var)
+ (declared-special-p var declarations))
+ ;; special
+ (push var special-vars)
+ (push (eval-form init-form env) special-values))
+ (t ;; lexical
+ (push (cons var (eval-form init-form env))
+ local-env)))))
+ (if (null special-vars)
+ (eval-progn body local-env)
+ (progv special-vars special-values
+ (eval-progn body local-env)))))))
+
+(define-eval-special-operator let* (form env)
+ (let ((var-specs (cadr form))~)
+ (if (null var-specs)
+ (eval-progn body env)
+ (multiple-value-bind (body declarations)
+ (parse-declarations-and-body (cddr form))
+ (multiple-value-bind (var init-form)
+ (let ((var-spec (pop var-specs)))
+ (if (atom var-spec)
+ (values var-spec nil)
+ (destructuring-bind (var init-form)
+ var-spec
+ (values var init-form))))
+ (if (or (symbol-special-variable-p var)
+ (declared-special-p var declarations))
+ (progv (list var) (list (eval-form init-form env))
+ (eval-let* var-specs
+ declarations
+ body
+ env))
+ (eval-let* var-specs
+ declarations
+ body
+ (cons (cons var
+ (eval-form init-form env))
+ env))))))))
+
+(define-eval-special-operator multiple-value-call (form env)
+ (apply (eval-form (cadr form) env)
+ (mapcan (lambda (args-form)
+ (multiple-value-list (eval-form args-form env)))
+ (cddr form))))
+
+(define-eval-special-operator catch (form env)
+ (catch (eval-form (second form) env)
+ (eval-progn (cddr form) env)))
+
+(define-eval-special-operator throw (form env)
+ (throw (eval-form (second form) env)
+ (eval-form (third form) env)))
+
+(define-eval-special-operator unwind-protect (form env)
+ (unwind-protect
+ (eval-form (second form) env)
+ (eval-progn (cddr form) env)))
+
+(define-eval-special-operator the (form env)
+ (destructuring-bind (value-type form)
+ (cdr form)
+ (declare (ignore value-type))
+ (eval-form form env)))
+
+(define-eval-special-operator multiple-value-prog1 (form env)
+ (multiple-value-prog1 (eval-form (cadr form) env)
+ (eval-progn (cddr form) env)))
+
+(define-eval-special-operator symbol-macrolet (form env)
+ (error "Special operator ~S not implemented in ~S." (car form) 'eval))
(defun eval-cons (form env)
"3.1.2.1.2 Conses as Forms"
@@ -93,80 +234,16 @@
:whole-p nil))))
(cdr form))
env)
- (case (car form)
- (quote (cadr form))
- (function (eval-function (second form) env))
- (if (if (eval-form (second form) env)
- (eval-form (third form) env)
- (eval-form (fourth form) env)))
- (progn (eval-progn (cdr form) env))
- (prog1 (prog1 (eval-form (cadr form) env)
- (eval-progn (cddr form) env)))
- (tagbody (eval-tagbody form env))
- ((block)
- (catch form
- (eval-progn (cddr form)
- (cons (list* +eval-binding-type-block+
- (cadr form)
- form)
- env))))
- ((macrolet)
- (dolist (macrolet (cadr form))
- (destructuring-bind (name lambda &body body)
- macrolet
- (check-type name symbol)
- (check-type lambda list)
- (push (list* +eval-binding-type-macrolet+
- name
- (cdr macrolet))
- env)))
- (eval-progn (cddr form)
- env))
- ((return-from)
- (let ((b (cdr (op-env-binding env (cadr form) +eval-binding-type-block+))))
- (unless b (error "Block ~S is not visible." (cadr form)))
- (throw (cdr b)
- (eval-form (caddr form) env))))
- (go (eval-go form env))
- (setq (eval-setq form env))
- (setf (eval-setf form env))
- ((defvar) (eval-defvar form env))
- ((let)
- (eval-let (cadr form) (cddr form) env))
- ((let*)
- (multiple-value-bind (body declarations)
- (parse-declarations-and-body (cddr form))
- (eval-let* (cadr form) declarations body env)))
- ((defun) (eval-defun (cadr form) (caddr form) (cdddr form) env))
- ;; ((lambda) (eval-function form env)) ; the lambda macro..
- ((multiple-value-call)
- (apply (eval-form (cadr form) env)
- (mapcan (lambda (args-form)
- (multiple-value-list (eval-form args-form env)))
- (cddr form))))
- ((multiple-value-bind)
- (eval-m-v-bind form env))
- ((multiple-value-prog1)
- (multiple-value-prog1 (eval-form (cadr form) env)
- (eval-progn (cddr form) env)))
- ((catch)
- (catch (eval-form (second form) env)
- (eval-progn (cddr form) env)))
- ((throw)
- (throw (eval-form (second form) env)
- (eval-form (third form) env)))
- ((unwind-protect)
- (unwind-protect
- (eval-form (second form) env)
- (eval-progn (cddr form) env)))
- ((symbol-macrolet)
- (error "Special operator ~S not implemented in ~S." (car form) 'eval))
- ((the)
- (destructuring-bind (value-type form)
- (cdr form)
- (declare (ignore value-type))
- (eval-form form env)))
- (t (eval-funcall form env)))))
+ (let ((special-operator (gethash (car form) *eval-special-operators*)))
+ (if special-operator
+ (funcall special-operator form env)
+ (case (car form)
+ (setq (eval-setq form env))
+ (setf (eval-setf form env))
+;; ((defvar) (eval-defvar form env))
+ ((multiple-value-bind)
+ (eval-m-v-bind form env))
+ (t (eval-funcall form env)))))))
(defun eval-progn (forms env)
(do ((p forms (cdr p)))
@@ -249,17 +326,6 @@
declarations
docstring)))))))
-(defun parse-docstring-declarations-and-body (forms &optional (declare 'declare))
- "From the list of FORMS, return first the list of non-declaration forms, ~
-second the list of declaration-specifiers, third any docstring."
- (assert (eq declare 'declare))
- (if (or (not (cdr forms))
- (not (stringp (car forms))))
- (parse-declarations-and-body forms)
- (multiple-value-call #'values
- (parse-declarations-and-body (cdr forms))
- (car forms))))
-
(defun compute-function-block-name (function-name)
(cond
((symbolp function-name) function-name)
@@ -275,22 +341,6 @@
(member var (cdr d)))
(return t))))
-(defun eval-defun (name lambda-list body env)
- (with-simple-restart (continue "Defun ~S anyway." name)
- (assert (not (eq (symbol-package name)
- (find-package 'common-lisp)))
- () "Won't allow defun of the Common Lisp symbol ~S." name))
- (setf (symbol-function name)
- (install-funobj-name name
- (lambda (&rest args)
- (declare (dynamic-extent args))
- (eval-progn body (make-destructuring-env
- lambda-list args env
- :environment-p nil
- :recursive-p nil
- :whole-p nil)))))
- name)
-
(defun decode-optional-formal (formal)
"3.4.1.2 Specifiers for optional parameters.
Parse {var | (var [init-form [supplied-p-parameter]])}
@@ -405,31 +455,6 @@
env)
env)))
-(defun eval-let (var-specs declarations-and-body env)
- (let (special-vars
- special-values
- (local-env env))
- (multiple-value-bind (body declarations)
- (parse-declarations-and-body declarations-and-body)
- (dolist (var-spec var-specs)
- (multiple-value-bind (var init-form)
- (if (atom var-spec)
- (values var-spec nil)
- (values (car var-spec) (cadr var-spec)))
- (cond
- ((or (symbol-special-variable-p var)
- (declared-special-p var declarations))
- ;; special
- (push var special-vars)
- (push (eval-form init-form env) special-values))
- (t ;; lexical
- (push (cons var (eval-form init-form env))
- local-env)))))
- (if (null special-vars)
- (eval-progn body local-env)
- (progv special-vars special-values
- (eval-progn body local-env))))))
-
(defun eval-let* (var-specs declarations body env)
(if (null var-specs)
(eval-progn body env)
@@ -475,27 +500,28 @@
env)))))
(eval-progn body env)))))
-(defun eval-function (function-name env)
- (etypecase function-name
- (symbol
- (let ((binding (cdr (op-env-binding env function-name +eval-binding-type-flet+))))
- (or (and binding (cdr binding))
- (symbol-function function-name))))
- (list
- (ecase (car function-name)
- ((setf)
- (symbol-function (lookup-setf-function (second function-name))))
- ((lambda)
- (let ((lambda-list (cadr function-name))
- (lambda-body (parse-docstring-declarations-and-body (cddr function-name))))
- (install-funobj-name :anonymous-lambda
- (lambda (&rest args)
- (declare (dynamic-extent args))
- (eval-progn lambda-body
- (make-destructuring-env lambda-list args env
- :environment-p nil
- :recursive-p nil
- :whole-p nil))))))))))
+(define-eval-special-operator function (form env)
+ (let ((function-name (second form)))
+ (etypecase function-name
+ (symbol
+ (let ((binding (cdr (op-env-binding env function-name +eval-binding-type-flet+))))
+ (or (and binding (cdr binding))
+ (symbol-function function-name))))
+ (list
+ (ecase (car function-name)
+ ((setf)
+ (symbol-function (lookup-setf-function (second function-name))))
+ ((lambda)
+ (let ((lambda-list (cadr function-name))
+ (lambda-body (parse-docstring-declarations-and-body (cddr function-name))))
+ (install-funobj-name :anonymous-lambda
+ (lambda (&rest args)
+ (declare (dynamic-extent args))
+ (eval-progn lambda-body
+ (make-destructuring-env lambda-list args env
+ :environment-p nil
+ :recursive-p nil
+ :whole-p nil)))))))))))
(defun lookup-setf-function (name)
(let ((setf-name (gethash name *setf-namespace*)))
@@ -515,28 +541,27 @@
(cons (eval-form (car list) env)
(eval-arglist (cdr list) env))))
-(defun eval-tagbody (form env)
+(define-eval-special-operator tagbody (form env)
;; build the..
(do* ((pc (cdr form) (cdr pc))
(instruction (car pc) (car pc)))
- ((endp pc))
+ ((endp pc))
(when (typep instruction '(or integer symbol))
(push (list* +eval-binding-type-go-tag+ instruction form)
env)))
;; execute body..
(prog ((pc (cdr form)))
start
- (let ((tag (catch form
- (do () ((endp pc) (go end))
- (let ((instruction (pop pc)))
[19 lines skipped]