4

我想探索 Clojure 在编译器开发中的强大功能,但我找不到可以开始的示例。

我是一个完全的新手(来自 Ruby),但我相信 Clojure 应该是实现此目的的理想选择。

让我们准确地说我在寻找什么:

  • clojure 中定义的简单 AST开始(比如说一种简单的顺序语言:if、while、func、assign、expression)
  • 这个 AST 的简单访问者(例如漂亮的打印机)
  • 我对词法分析/解析并不感兴趣(因为我认为 s-expression 足以满足我的 DSL 语法)

Clojure 中的正确成语是什么?

4

1 回答 1

4

这是我能想到的最简单的简单示例,它使用由 s 表达式和关键字运算符构建的 AST 树:

;; functions map, can be easily extended with new functions
;; map is of keyword -> code generating function
(def funcs {:if 
                 (fn [cond exp1 exp2] `(if ~cond ~exp1 ~exp2))
            :neg 
                 (fn [exp1] `(- 0 ~exp1))
            :plus 
                 (fn [& exps] `(+ ~@exps))})

;; compile directly to Clojure source code
(defn my-compile [code]
 (cond 
   (sequential? code)   ;; if we have a list, look up the function in funcs
     (cons (funcs (first code)) (map compile (rest code))) 
   :else                ;; treat anything else as a constant literal
     code))

;; example compilation to a Clojure expression
(my-compile `(:if true (:neg 10) (:plus 10 20 30)))
=> (if true (clojure.core/- 0 10) (clojure.core/+ 10 20 30))

;; evaluate compiled code
(eval (my-compile `(:if true (:neg 10) (:plus 10 20 30))))
=> -10

希望这足以给你一些想法/让你开始。要考虑的明显扩展是:

  • 使用元数据编译为 AST 树,而不是直接编译为 Clojure 源。Clojuredefrecord可能适合作为 AST 节点表示
  • 添加其他运算符、循环结构、“goto”等。
  • 简单的优化,例如在编译时评估常量表达式
  • 具有某种形式的执行上下文,允许赋值、动态变量查找等。编译器输出可以是一个将初始上下文作为输入并返回最终上下文的函数。
于 2012-07-26T08:49:32.993 回答