【问题标题】:If Lisp source code is basically an AST, does that mean Lisp macros are language agnostic?如果 Lisp 源代码基本上是 AST,这是否意味着 Lisp 宏与语言无关?
【发布时间】:2017-03-26 23:11:55
【问题描述】:

宏(甚至是阅读器宏)能否遍历非 Lisp 语言的 AST 并以某种方式对其进行转换?我想在它自己的编译器中运行 nonLisp 语言,而不是 Lisp 编译器

【问题讨论】:

    标签: lisp metaprogramming abstract-syntax-tree


    【解决方案1】:

    这并不意味着它是不可知论的。这意味着它只做很少的解析。程序的结构与生成的语法树非常相似,与数据结构非常相似。

    任何语言的 AST 都是一棵树,所以是的。 Lisp 可以在解析后遍历不同的语言语法树,并且可以对其进行转换。任何语言都可以,因为我们正在谈论将一棵树转换为稍微不同的树。它们中的任何一个看起来都不像原始源代码。这是 algol 语言中强大的宏失败的地方。你不能告诉程序员解释 AST 级别的转换,因为它对她来说是陌生的。

    一些算法语言,比如Nermle,有强大的宏。它们与 lisp 完全不同,但它们提供了引号 unquote:

    macro for (init, cond, change, body)
    {
      <[ 
        $init;
        def loop () : void {
          if ($cond) { $body; $change; loop() } 
          else ()
        };
        loop ()
      ]>
    }
    

    这里的魔法是&lt;[]&gt;,它们作为" 围绕字符串工作,除了结果是一个AST。此外,变量前面的$ 表示编译时宏函数的某种排序或替换。

    我想用 lisp 为 algol 语言制作编译器而不是自己编写是一种浪费。引导是乐趣的一半。

    【讨论】:

    • @DiamondFox 是什么让您认为 Python 不是 Algol?如果您将对齐的空格替换为块,则很难区分。
    【解决方案2】:

    首先,大多数 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 期间被扩展。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-06-14
      • 1970-01-01
      • 2013-12-01
      • 2012-09-29
      • 2022-11-29
      相关资源
      最近更新 更多