2012-07-26 41 views
4

我想探索Clojure的编译器开发的力量,但我找不到示例。在Clojure编译器开发的习语

我是一个新手(来自Ruby),但我确信Clojure应该是理想的这个目的。

让我们确切什么我在寻找:

  • 开始从Clojure中定义的简单AST(为让说一个简单的顺序语言:如果,同时,FUNC,分配,表达)
  • 简单游客对这个AST(例如漂亮的打印)
  • 我不是真的词法/感兴趣的解析(因为我认为S-表达足以成为我的DSL语法)

在Clojure中,这是什么合适的成语?

+0

您不必将搜索限制在Clojure示例中。其他Lisp有很多例子可以轻松移植到Clojure。例如,http://bit.ly/3t1DX或http://bit.ly/I2LFdr – 2012-07-26 07:54:28

+0

我同意。这种说法也可以适用于一般的函数式语言,但我想限制在Clojure中,因为它对于非lispians来说似乎比旧lisses更容易获得/吸引人。 “有史以来最好的口齿伶俐的”人说? – JCLL 2012-07-26 08:19:30

+0

不,功能性语言通常是完全不同的话题。 Clojure是一个Lisp,从某种意义上说它是Lisp最重要的部分 - 一个体面的宏观系统。这实际上使Lisp不同,使得它比其他语言更适合编译器开发。看看我的第二个链接,它使用专门的DSL来定义访问者。这正是一种习惯Lisp的做事方式。在所有的Lisp中都是一样的。至于“有史以来最好的口齿伶俐”,我个人不会同意。没有'cons'的Lisp不是Lisp。 “复发”是可怕的。 – 2012-07-26 08:33:01

回答

3

下面是简单的小例子我能想到的,利用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] `(+ [email protected]))}) 

;; 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源。 Clojure defrecord可能适合作为AST节点表示
  • 添加其他运算符,循环构造,“goto”等。
  • 简单的优化在编译时对常量表达式的评估
  • 具有某种形式的允许赋值,动态变量查找等的执行上下文。编译器输出可以是一个函数,它将初始上下文作为输入并返回最终上下文。