/
embed-foo-with-conditions-and-restarts.lisp
58 lines (42 loc) · 1.74 KB
/
embed-foo-with-conditions-and-restarts.lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
;;
;; Copyright (c) 2005, Gigamonkeys Consulting All rights reserved.
;;
(in-package :com.gigamonkeys.foo)
;; Conditions
(define-condition embedded-lisp-in-interpreter (error)
((form :initarg :form :reader form)))
(define-condition value-in-interpreter (embedded-lisp-in-interpreter) ()
(:report
(lambda (c s)
(format s "Can't embed values when interpreting. Value: ~s" (form c)))))
(define-condition code-in-interpreter (embedded-lisp-in-interpreter) ()
(:report
(lambda (c s)
(format s "Can't embed code when interpreting. Code: ~s" (form c)))))
;; Implementation with restarts provided
(defmethod embed-value ((pp text-pretty-printer) value)
(restart-case (error 'value-in-interpreter :form value)
(evaluate ()
:report (lambda (s) (format s "EVAL ~s in null lexical environment." value))
(raw-string pp (escape (princ-to-string (eval value)) *escapes*) t))))
(defmethod embed-code ((pp text-pretty-printer) code)
(restart-case (error 'code-in-interpreter :form code)
(evaluate ()
:report (lambda (s) (format s "EVAL ~s in null lexical environment." code))
(eval code))))
;; Restart functions
(defun evaluate (&optional condition)
(declare (ignore condition))
(invoke-restart 'evaluate))
(defun eval-dynamic-variables (&optional condition)
(when (and (symbolp (form condition)) (boundp (form condition)))
(evaluate)))
(defun eval-code (&optional condition)
(when (consp (form condition))
(evaluate)))
;; Macro to automate binding of handlers to invoke evaluate restart.
(defmacro with-dynamic-evaluation ((&key values code) &body body)
`(handler-bind (
,@(if values `((value-in-interpreter #'evaluate)))
,@(if code `((code-in-interpreter #'evaluate))))
,@body))