3 ms·
Simple localscope in TXR Lisp: $ txr -i localscope.tl Pour le service en la langue Shell, appuyez sur Ctrl-D. 1> (localscope (+ %pi% %pi%)) ;; OK, %pi% i
by kazinator 2y ago
Simple localscope in TXR Lisp:
$ txr -i localscope.tl
Pour le service en la langue Shell, appuyez sur Ctrl-D.
1> (localscope (+ %pi% %pi%)) ;; OK, %pi% is built-in
6.28318530717959
2> (localscope *print-base*) ;; likewise
10
3> (localscope (+ a b c)) ;; bad
** expr-3:1: localscope: global variables (c b a) used
Code:
(defmacro localscope (:form f :env e . forms)
(let ((body ^(progn ,*forms)))
(tree-bind (exp fv-inner ff-inner fv-outer ff-outer) (expand-with-free-refs
body e)
(ignore ff-inner fv-outer ff-outer)
(let* ((usr (find-package :usr))
(globals [keep-if (do or (not (boundp @1))
(neq (symbol-package @1) usr))
fv-inner]))
(if globals
(compile-error f "global variables ~s used" globals)))
body)))
We get a list of the free variable references emanating from the enclosed forms, and filter them: we are interested in all that do not have bindings as globals in the standard library. I.e. either are not bound at all, or else if they are, are not symbols in the usr: ("user space") package.
- kazinator 2y agoOf course, we need test cases like this: 1> (let (x) (localscope (+ x y))) ** expr-1:1: localscope: global variables (y) used