forked from Roxxi/diesel
/
a_dsl_with_clojure.clj
46 lines (38 loc) · 1.48 KB
/
a_dsl_with_clojure.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
(ns diesel.growing.a-dsl-with-clojure
"Using Diesel to implement
http://pragprog.com/magazines/2011-07/growing-a-dsl-with-clojure
You should read this blog post before attempting to understand
what this file is doing."
{:author "Alex Bahouth"
:date "12/23/2013"}
(:use clojure.test
diesel.core))
;; Heh, since we handle constants
;; to be defined as (not lists)
;; This is pretty small!
(def ^{:dynamic true} *current-impl*)
(derive ::bash ::common)
(derive ::batch ::common)
(definterpreter shell-interp []
['println => [*current-impl* :println]]
['statements => [*current-impl* :statements]])
(defmethod shell-interp [::bash :println] [[_ val]]
(str "echo " val))
(defmethod shell-interp [::batch :println] [[_ val]]
(str "ECHO " val))
(defmethod shell-interp [::common :statements] [[_ & statements]]
(str (clojure.string/join "; " (map shell-interp statements) )))
(deftest multi-shell-interp-test
(testing "Testing to make sure we can use dynamic
bindings to switch between our implementation routes to
share common implementation"
(is (= "echo \"hello\"; echo \"world\""
(binding [*current-impl* ::bash]
(shell-interp
'(statements (println "\"hello\"")
(println "\"world\""))))))
(is (= "ECHO \"hello\"; ECHO \"world\""
(binding [*current-impl* ::batch]
(shell-interp
'(statements (println "\"hello\"")
(println "\"world\""))))))))