如果您想在不执行任意代码的情况下读取状态机的定义,您可以考虑以下宏:
(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))
用于定义函数的单独宏允许额外的健全性检查。最后,你可以定义 reader 函数:
(defun load-toy-state-machine (directory)
(let ((path (cl-fad:merge-pathnames-as-file directory #P"machine.lisp"))
;(*readtable* (copy-readtable nil))
)
; (make-dispatch-macro-character #\#)
(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),它们具有固定的语法,并且可能包含额外的健全性检查。这些都不执行代码。