Compiler construction 使用内存中的数据编译文件,而不是使用Common Lisp中的真实文件

Compiler construction 使用内存中的数据编译文件,而不是使用Common Lisp中的真实文件,compiler-construction,common-lisp,Compiler Construction,Common Lisp,是否有一种方法可以实现编译文件的效果,但不是使用磁盘上的常规文件,而是使用流或内存中的字符串?(即,如果我没有文件,也不想用内存中的数据创建临时文件) 编辑 我正在考虑以下用例:从文件系统以外的其他地方加载代码。例如,从归档文件(类似于Java的jars或Python zip处理功能)或网络。除了弯曲编译文件机械装置之外,可能还有其他方法。Rainer Joswig的第一条评论明确了这一点: 不在标准公共Lisp中 您可以在每个实现中搜索从compile file发出的调用,以查看底层实现是否采

是否有一种方法可以实现编译文件的效果,但不是使用磁盘上的常规文件,而是使用流或内存中的字符串?(即,如果我没有文件,也不想用内存中的数据创建临时文件)

编辑


我正在考虑以下用例:从文件系统以外的其他地方加载代码。例如,从归档文件(类似于Java的jars或Python zip处理功能)或网络。除了弯曲
编译文件
机械装置之外,可能还有其他方法。

Rainer Joswig的第一条评论明确了这一点:

不在标准公共Lisp中

您可以在每个实现中搜索从
compile file
发出的调用,以查看底层实现是否采用流

如果您想自己实现这一点,您将为输入和输出流实现一个效率很低的
编译文件
,它生成适合
加载
或您自己版本的可加载表单

用编译单元包装编译,在使用顶级表单时,必须特别注意
宏扩展
,确保将
编程
表单视为顶级表单,即
本地
macrolet
symbol macrolet
表单使用非空词汇环境(操作也不可移植)建立绑定并作为顶级处理其表单,并在表单时处理
eval,其中一些表单可能会被评估、处理或两者兼而有之。然后,生成可外部化的表单,注意哪些可以合并,哪些不能合并(例如符号和包),为
标准对象
结构对象
条件
实例调用
生成加载表单
,并特别注意符号和包,例如,检查要编译的流是否在包
格式中有第一个非原子的
,或者如果使用不同的
*包*
值调用
加载
,则不能发出错误信号

这只是实现最小编译的最重要步骤,或多或少,没有提到编译实际发生的时间(编译时或加载时),
加载时值
表单和许多细节。其中一些步骤需要代码遍历

我的建议是:只要从压缩数据和套接字中提取并保存所有源代码,然后调用
编译文件
,然后调用
加载
,如果您想保留编译和加载语义的话。对于更简单的事情,您可以这样做:

(let* ((*package* *package*)
       (*readtable* *readtable*)
       (eof (copy-symbol 'eof))
       (form nil))
  (loop
    (setf form (read stream nil eof))
    (when (eq form eof)
      (return))
    (funcall (compile nil `(lambda () ,form)))))

如果您不太关心可移植性,那么让您的实现能够处理压缩文件,例如,提供一种解压缩的外部格式来编译文件,并让您的实现能够打开URL(URI、IRI,无论您关心什么),而不仅仅是路径名。好的,ABCL可以打开URL进行输入。然而,当使用这样的外部资源调用时,
编译文件
的输出文件是什么?也许你可以制作自己的
编译和加载
,其中说明了用于
编译文件
输出文件
关键参数和
加载

编译文件
,只使用
编译
,但也许您可以调整您的解决方案来使用它?或者更好,使用闭包树?@MironBrezuleanu感谢这个链接,但我真的对编译某些代码单元感兴趣,就像它们在文件中一样。我已经更新了问题以澄清this@VsevolodDyomkin从您的编辑中,我推断您希望
加载
,而不是
编译文件
(您提到“从其他地方加载代码”)。
编译文件
的CLHS条目似乎并不意味着编译文件也意味着加载。
load
的CLHS条目提到第一个参数可以是流-这不是您需要的吗?也许使用编译单元可以帮助您?