【发布时间】:2017-03-26 23:11:55
【问题描述】:
宏(甚至是阅读器宏)能否遍历非 Lisp 语言的 AST 并以某种方式对其进行转换?我想在它自己的编译器中运行 nonLisp 语言,而不是 Lisp 编译器
【问题讨论】:
标签: lisp metaprogramming abstract-syntax-tree
宏(甚至是阅读器宏)能否遍历非 Lisp 语言的 AST 并以某种方式对其进行转换?我想在它自己的编译器中运行 nonLisp 语言,而不是 Lisp 编译器
【问题讨论】:
标签: lisp metaprogramming abstract-syntax-tree
这并不意味着它是不可知论的。这意味着它只做很少的解析。程序的结构与生成的语法树非常相似,与数据结构非常相似。
任何语言的 AST 都是一棵树,所以是的。 Lisp 可以在解析后遍历不同的语言语法树,并且可以对其进行转换。任何语言都可以,因为我们正在谈论将一棵树转换为稍微不同的树。它们中的任何一个看起来都不像原始源代码。这是 algol 语言中强大的宏失败的地方。你不能告诉程序员解释 AST 级别的转换,因为它对她来说是陌生的。
一些算法语言,比如Nermle,有强大的宏。它们与 lisp 完全不同,但它们提供了引号 unquote:
macro for (init, cond, change, body)
{
<[
$init;
def loop () : void {
if ($cond) { $body; $change; loop() }
else ()
};
loop ()
]>
}
这里的魔法是<[ 和]>,它们作为" 围绕字符串工作,除了结果是一个AST。此外,变量前面的$ 表示编译时宏函数的某种排序或替换。
我想用 lisp 为 algol 语言制作编译器而不是自己编写是一种浪费。引导是乐趣的一半。
【讨论】:
首先,大多数 Lisp 宏都使用“非 Lisp”语言:宏的语言。 :)
其次,Lisp 宏确实可以用于扩展结构,最终生成一些完全非 Lisp 的语言,然后在其他地方进行处理。
一个非常常见(现在)的例子是任何一种可用的 HTML 生成系统,其中许多使用宏,最终生成文本文本 HTML(一种结构化的计算机语言),然后最终在用户的浏览器中处理.
如果您想要一个能够使用 Lisp 宏的代码生成系统,简而言之,您所要做的就是以一种由 Lisp 表单评估驱动的方式实现它。
例如,如果你为 X86 制作了一个基于 Lisp 的汇编器,那么使用它来处理像 (movl eax ebx) 这样的表达式,因为它被评估为一个表单,这样实际上就有一个 movl 函数或被调用的宏。这个评估可能需要一些上下文,比如输出应该去的流,并且可以通过一些设置宏来设置:
(with-x86-assembler (:output-file "foo.asm")
(movl eax ebx)) ;; just evaluated!
movl 这个东西知道with-x86-assembler 设置的环境,例如一些动态范围的变量,它保存了目标流和其他上下文。
由于with-x86-assembler宏的内部只是一些需要评估的形式,我们可以在那里使用宏:
(defmacro save-basic-regs (base-reg)
^(progn (movl (ind ,base-reg) eax) ;; movl [<reg>], eax
(movl (ind ,base-reg 4) ebx) ;; movl [<reg> + 4], ebx
...))
现在我们可以在with-x86-assembler 中使用(save-basic-regs edi)。实际上,我们有一个支持宏指令的宏汇编器。
Lisp 宏可用于处理某些完全非 Lisp 语言的 AST,这些语言由与读取宏无关的自定义解析器解析。没有什么能阻止你编写 Lisp 代码来解析 JavaScript 语法并生成 Lisp,然后对其进行评估。然后 Lisp 依赖于各种运行时支持,其中可能包括宏。一些 JavaScript 循环可以变成 (loop ...) 形式,这是一个宏。 Lisp 是该代码的 AST,loop 宏在宏扩展 AST walk 期间被扩展。
【讨论】: