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条目提到第一个参数可以是流-这不是您需要的吗?也许使用编译单元可以帮助您?