下面是简单的小例子我能想到的,利用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”等。
- 简单的优化在编译时对常量表达式的评估
- 具有某种形式的允许赋值,动态变量查找等的执行上下文。编译器输出可以是一个函数,它将初始上下文作为输入并返回最终上下文。
您不必将搜索限制在Clojure示例中。其他Lisp有很多例子可以轻松移植到Clojure。例如,http://bit.ly/3t1DX或http://bit.ly/I2LFdr – 2012-07-26 07:54:28
我同意。这种说法也可以适用于一般的函数式语言,但我想限制在Clojure中,因为它对于非lispians来说似乎比旧lisses更容易获得/吸引人。 “有史以来最好的口齿伶俐的”人说? – JCLL 2012-07-26 08:19:30
不,功能性语言通常是完全不同的话题。 Clojure是一个Lisp,从某种意义上说它是Lisp最重要的部分 - 一个体面的宏观系统。这实际上使Lisp不同,使得它比其他语言更适合编译器开发。看看我的第二个链接,它使用专门的DSL来定义访问者。这正是一种习惯Lisp的做事方式。在所有的Lisp中都是一样的。至于“有史以来最好的口齿伶俐”,我个人不会同意。没有'cons'的Lisp不是Lisp。 “复发”是可怕的。 – 2012-07-26 08:33:01