【问题标题】:Intermediate representation for a Lisp / Clojure DSLLisp / Clojure DSL 的中间表示
【发布时间】:2012-05-26 02:46:37
【问题描述】:

我正在 Clojure 中设计一个 DSL,它用于驱动代码生成器(在本例中用于程序图像合成 - clisk),但我无法确定中间值的最佳表示。

最初,DSL 由返回一种或多种形式的函数组成,例如(说明)

(v+ 1.0 [1.0 'y])
=> ['(+ 1.0 1.0) '(+ 1.0 y)]

然后可以组合这些函数来构建更大的代码块。

这很简单,生成的表单可以直接输入代码生成器。但是,我现在已经确定了这种方法的一些弱点,例如,如果需要传递一些辅助数据(例如,无法以 BufferedImages 等形式编码的对象、对优化有用的元数据等)。

我确信这是 Lisp 世界中一个已解决的问题 - 这种 DSL 的最佳中间表示通常是什么?

【问题讨论】:

    标签: clojure functional-programming lisp code-generation dsl


    【解决方案1】:

    每当您需要用于生成代码的中间表示时,我想到的最明显的事情就是抽象语法树 (AST)。您的示例表示是列表,根据我的经验,它的形式不那么灵活。除了琐碎的代码生成之外,我不会拐弯抹角,而只是使用完整的 AST 表示。通过使用列表,您将更多的工作推到生成端来解析信息,例如类型和第一项的含义。转向 AST 表示将为您提供更大的灵活性并解耦更多的系统,但代价是解析方面的工作更多(或生成表单的函数的工作更多)。生成端也将做更多的工作,但其中许多组件可以解耦,因为它们的输入将更加结构化。

    就 AST 应该是什么样子而言,我会复制 Christophe Grand 的 enlive,他使用 {:tag <tag name> :attrs <map of attrs> :content <some collection>}

    或者 clojure 脚本使用什么,{:op <some operator> :children <some collection>}

    这使其非常通用,因为您可以定义任意步行者来窥视:children,并且可以遍历任何结构,而无需确切知道:op:tag 是什么。

    然后对于原子组件,您可以将其包装在一个映射中,并为其提供一些类型信息(关于您的 DSL 的语义),这些信息与对象的实际类型无关。 {:atom <the object> :type :background-image}.

    在代码生成方面,当遇到原子时,您的代码可以在:type 上调度,然后,如果您愿意,可以在对象的实际类型上进一步调度。从集合表单生成也很容易,在 :op/:tag 上调度,然后与孩子一起重复。对于儿童使用什么集合,我会阅读更多关于谷歌群组的讨论。他们的结论对我很有启发。

    https://groups.google.com/forum/#!topic/clojure-dev/vZLVKmKX0oc/discussion

    总结一下,对于儿童来说,如果在 if 语句中存在语义排序重要性,则使用映射 {:conditional z :then y :else x}。如果它只是一个参数列表,那么你可以使用一个向量。

    【讨论】:

      【解决方案2】:

      我想我不明白。我自己会使用列表或结构。

      在 Lisp 中,列表可以包含任何东西。我应该说,一个 CONS 单元格可以指向任何东西,因此列表可以包含任何东西。几乎任何其他数据结构(结构、数组、映射等)也可以。

      现在,这些结构无法通过 PRINT 呈现或呈现为可读的内容(通过 READ),但这并不意味着它们无法存储和操作。

      是否有某些原因需要将这种表示形式外部化?

      【讨论】:

      【解决方案3】:

      不是一个真正的答案,因为我不知道 Clojure 在这方面是如何工作的,但是在 CL 中有专门为这种情况设计的阅读器宏:即您将定义用于打印不可打印对象的函数 + 一个阅读器宏从您打印它们的方式读取它们。要定义打印对象的方式,您需要定义一个新方法 print-object,该方法专门处理您需要的对象类型,并定义 set-macro-character 向 readtable 添加一个函数,该函数知道如何读取您的设计对象。

      有很多事情需要注意,但有些情况通常就像定时炸弹一样,当对象被允许递归引用自己时,在这种情况下打印需要考虑以前打印的对象。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-07-24
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多