13 comments

[ 2.1 ms ] story [ 47.7 ms ] thread
I've been investigating how to program my new HTC Incredible lately, and have therefore finally had to interact nontrivially with Java.

And, since I instinctively refused to look at Eclipse, I've been learning about Ant, which turns out to be almost completely isomorphic to a not-extremely-well-thought-out set of Lisp macros to form a build system.

So, since XML syntax bugs me, I figured I'd write a thing that took a Lisp-syntax file and spit out an XML-syntax file, which led me to google for 'ant lisp,' which led me to this document.

Did you find such a Lisp-to-Ant compiler?
Not yet, but I haven't looked that hard. Offhand, it also seems like it'd be easy and fun to write, so I may write one anyway.
If you're a Common Lisper, you can whip it with cl-who or xml-emitter in an afternoon. I don't know about ant, but XML generation from Lisp macrology is trivial; the "hardest" part is deciding the Lispiest syntax for your tastes.

I like it how with macros, the biggest hurdle in creating a DSL is the actual syntax design, not the actual implementation.

I whipped it with PLT Scheme in an afternoon. Trivial, like you said. This is my ant-make-scm.bat:

  ; @echo off && REM -*- scheme -*-
  ; if not "%MZSCHEME%" == "" goto :run
  ; set MZSCHEME=mzscheme.exe
  ; :run
  ; "%MZSCHEME%" "%~f0" %*
  ; exit /b
  
  #lang scheme
  (require xml)
  
  (permissive-xexprs #t)
  ;(read-comments #t)
  
  
  ;;; Filter to scrub whitespace
  ;;;
  (define f 
    (eliminate-whitespace 
     '(project path target property fileset condition copy exec cvs commandline tar classpath 
  	     tarfileset manifest section junit jar java and or not uptodate javac javadoc delete move) 
     (lambda (x) x)))
  
  
  ;;; Move "name" attribute to the beginning of any attribute list in an xexpr
  ;;;
  (define (name-first-attrib l)
    (letrec
        ;; take attribute list, move any "name" element to its car
        ((reorder-attrs (lambda (alist)
  			(cond
  			 ((null? alist) alist)
  			 ((assq 'name alist) => (lambda (el) (cons el (remove 'name alist (lambda (x y) (eq? x (car y)))))))
  			 (else alist))))
         ;; process any element (tag attrs el*)
         (process-element (lambda (el)
  			  (cons (car l) (cons (reorder-attrs (cadr l)) (map name-first-attrib (cddr l)))))) )
      (if (pair? l)
  	(process-element l)
  	l)))
  
  
  (define (process in out)
    (pretty-print (name-first-attrib (xml->xexpr (f (document-element (read-xml in))))) out))
  
  
  ;;; Open input file before output file, so that an error upon opening input doesn't create a zero-length output file
  ;;; If either parameter is #f, default to stdin/stdout
  ;;;
  (define (call-filter-with-files in-file out-file proc)
    (let ((output-processing-thunk (lambda (from)
  				   (if out-file
  				       (call-with-output-file out-file (lambda (to) (proc from to)))
  				       (proc from (current-output-port))))))
      (if in-file
  	(call-with-input-file in-file output-processing-thunk)
  	(output-processing-thunk (current-input-port)))))
  
  (define input-file (make-parameter #f))
  (define output-file (make-parameter #f))
  
  (command-line
   #:program "ant-make-scm"
   #:once-each
   (("--output" "-o") filename "Create S-expression format Ant buildfile" (output-file filename))
   #:args (build.xml) (unless (string=? "-" build.xml) (input-file build.xml)))
  
  (call-filter-with-files (input-file) (output-file) process)
"So, since XML syntax bugs me,"

If you want to use Ant and XML syntax bugs you - google for Lancet.

I did something similar a long time back for generating mxml (the markup used for building Flex apps).
This pays too much homage to Ant in my opinion.

If you were to strip out the XML from Ant what is left is a poorly designed language which has little expressive power. Short of the surface structure of Ant is nothing like Lisp.

The Ant community couldn't even agree what sort of language it was. A hack pretending not be a hack.

Any Lisp is a direct representation of it's own Abstract Syntax Tree. In other words, it is a syntax which is also its own meta-syntax.
I think understanding Lisp is super valuable for any programmer if only so you can see and appreciate the Lisp like abilities of other languages.