如果您想阅读状态机的定义而不执行任意代码,可以考虑使用以下宏:
(defmacro def-state-machine (name (&rest assets) &rest states)
`(defparameter ,name
(list
:assets ',(remove-if-not #'legal-asset? assets)
:states ',(remove-if-not #'legal-state? states))))
这将创建一个有效资产和状态的列表(因为我不知道你的机器长什么样子,所以我在这里放置一些抽象谓词-它们可以检查语法是否合法,或者参数是否属于某种类型,或者如果资产或状态非法则会抛出错误)。
假设您还需要定义一些函数来运行机器:
(defmacro def-transition (name args &body body)
`(defun ,name (,@args)
,@body))
使用单独的宏定义函数可以进行额外的安全检查。最后,您可以定义阅读器函数:
(defun load-toy-state-machine (directory)
(let ((path (cl-fad:merge-pathnames-as-file directory #P"machine.lisp"))
)
(with-open-file (stream path :direction :input)
(do ((form (read stream nil 'done)
(read stream nil 'done)))
((eql form 'done) T)
(if (member (car form) '(def-state-machine def-transition))
(eval form)
(error "malformed state machine definition file"))))))
此功能仅对允许的宏(def-state-machine和def-transition)进行评估,这些宏具有固定的语法,并可能包含额外的健全性检查。这两个宏均不会执行代码。