Thursday, April 27, 2006

Rake it using LISP!

Rake - I saw this sometime back when martin fowler wrote about this - and I remember thinking "WOW, Ruby must be cool - its much trickeier to implement a domain specific language in perl!!". And I tried to write a small perl script inteprepretter on lines of rake and made similar progress - 60% functional build in some hours. Now that I am learning LISP I tried my hand at this problem of a build DSL... in LISP - and even a LISP newbie like me could role out a couple of macros - and I am sure, if I spent a whole day at it ever it wil be pretty cool (and I intend to do just that contibute via cliki

(defmacro task (name (&rest dependencies) &body body)
(let ((exec-task-fn-symbol
(intern (string-upcase
(concatenate 'string "exec-task-" (symbol-name name))))))
`(defun ,exec-task-fn-symbol ()
,`(fulfil-task-dependencies
,@(loop for d in dependencies collect `(quote ,d)))
,@body)))

(defun exec-task(task)
(let ((exec-task-fn-symbol
(intern (string-upcase
(concatenate 'string "exec-task-" (symbol-name task))))))
(print exec-task-fn-symbol)
(funcall exec-task-fn-symbol)))

(defun fulfil-task-dependencies(&rest dependencies)
(dolist (d dependencies) (exec-task d)))


;;Examples usage
(task foo (bar bar1 bar2)
(echo "HUM"))
(task bar nil (echo "HOOO"))
(task bar1 nil (echo "HOOO1"))
(task bar2 nil (echo "HOOO2"))

(exec-task-foo)


;;Some file set , file selector like stuff(as in Ant)
(defmacro file-set(&body selectors)
(let (
(root-dir (gensym))
(file-set (gensym)))
`(lambda (,root-dir)
(let (
(,file-set (make-array 32 :fill-pointer 0 :adjustable t)))
,@(loop for s in selectors collect `(funcall ,s ,root-dir
,file-set))))))

(defmacro file-selector((&key type)&rest args)
(cond
((string-equal type "regexp")
`(regexp-file-selector ,@args))
(t (format t "ERROR: type cannot be ~a~%" type))))

(defmacro regexp-file-selector(&key expr)
(let (
(root-dir (gensym))
(file-set (gensym)))
`(lambda (,root-dir ,file-set)
(format t "SELECT FILES FROM ~a~% BASED ON ~a~%" ,root-dir ,expr))))


(defun test-file-set(file-set)
(funcall file-set "ROOT-DIR"))

(defun test-file-selector(file-selector)
(let ((file-set (make-array 32 :fill-pointer 0 :adjustable t)))
(funcall file-selector "ROOT-DIR" file-set)))

;;(test-file-selector (file-selector (:type "regexp") :expr "\\.lisp$"))
;;(test-file-set (file-set (file-selector (:type "regexp") :expr "\\.lisp$")))



DSLs

0 Comments:

Post a Comment

Subscribe to Post Comments [Atom]

<< Home