Common Lisp中等效的WAR文件

时间:2015-02-09 00:02:26

标签: lisp common-lisp

我有一个用Lisp编写的系统运行状态机。我只想给出目录名称,从目录动态加载状态机的定义和任何所需的资产(图像等)。将有多个不同的状态机。这与Apache加载和运行WAR文件类似,但不完全相同。

我担心的是,简单地编译和加载文件几乎可以运行任何东西。理想情况下,我只想获得状态机定义,使用资产路径配置它,并让它可以执行。现在我正在加载一个实现特定基类的类,但这不是直截了当的。有没有标准的技术呢?

感谢。

2 个答案:

答案 0 :(得分:3)

你是说你担心从文件中读取任意代码执行的可能性?我应该考虑重新定义读取表以排除不需要的符号。

有关结帐this的示例,请查找“SAFE-READ-FROM-STRING”。

它不完整但是你可以使用#'sread来获取数据结构,做一些健全性检查并在需要时进行编译。

如果这不是你想要的,那么我道歉,你能否进一步解释你在寻找什么?

答案 1 :(得分:1)

鉴于您想要在不执行任意代码的情况下读取状态机的定义,您可以考虑以下宏:

(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"))
        ;(*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"))))))

eval只允许使用具有固定语法的宏(def-state-machine和def-transition),并且可能包含额外的健全性检查。这些都不执行代码。