1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-06-17 17:20:29 +02:00

Implement catch and unwind-protect as macros.

* module/language/elisp/compile-tree-il.scm: Remove catch and unwind-protect.
* module/language/elisp/runtime/macro-slot.scm: Re-implement them here.
This commit is contained in:
Daniel Kraft 2009-08-03 18:22:12 +02:00
parent dfbc6e9d54
commit f4dc86f137
2 changed files with 44 additions and 47 deletions

View file

@ -152,6 +152,47 @@
'())))))))))
; Exception handling. unwind-protect and catch are implemented as macros (throw
; is a built-in function).
; catch and throw can mainly be implemented directly using Guile's
; primitives for exceptions, the only difficulty is that the keys used
; within Guile must be symbols, while elisp allows any value and checks
; for matches using eq (eq?). We handle this by using always #t as key
; for the Guile primitives and check for matches inside the handler; if
; the elisp keys are not eq?, we rethrow the exception.
(built-in-macro catch
(lambda (tag . body)
(if (null? body)
(macro-error "catch with empty body"))
(let ((tagsym (gensym)))
`(lexical-let ((,tagsym ,tag))
((guile-primitive catch)
#t
(lambda () ,@body)
,(let* ((dummy-key (gensym))
(elisp-key (gensym))
(value (gensym))
(arglist `(,dummy-key ,elisp-key ,value)))
`(with-always-lexical ,arglist
(lambda ,arglist
(if (eq ,elisp-key ,tagsym)
,value
((guile-primitive throw) ,dummy-key ,elisp-key
,value))))))))))
; unwind-protect is just some weaker construct as dynamic-wind, so
; straight-forward to implement.
(built-in-macro unwind-protect
(lambda (body . clean-ups)
(if (null? clean-ups)
(macro-error "unwind-protect without cleanup code"))
`((guile-primitive dynamic-wind)
(lambda () nil)
(lambda () ,body)
(lambda () ,@clean-ups))))
; Pop off the first element from a list or push one to it.
(built-in-macro pop