From: Christophe Turle
Subject: how to do java in lisp ?
Date: 
Message-ID: <cd13kc$1r0$1@amma.irisa.fr>
hello,

I'm searching a library to do java in lisp ?

I want to write java programs using lisp forms. The goal is to generate java code from CL. The advantage is to use all the power of Lisp ending in a java application (absolute requirement).

Jil is the nearest of what i want. But it is for Allegro. So no source code and it doesn't run on other platforms (i think)

Linj translates lisp to java programs. But sources are not available ...

Armed Bear Lisp is supposed to compile lisp directly into byte codes. But i didn't find a lot of documentation for this and i don't know the quality of the generated code compared to java code compilation.


??? java s-exp library ? i remember seeing a C s-exp library somewhere ...


Suggestions ?



ctu.

From: David Magda
Subject: Re: how to do java in lisp ?
Date: 
Message-ID: <86pt6zsinh.fsf@number6.magda.ca>
Christophe Turle <······@nospam.fr> writes:

> I'm searching a library to do java in lisp ?

Bill Clementson recently had a couple of entries on his weblog about
this subject. They are:

CL to Java
        Part 1: http://home.comcast.net/~bc19191/blog/040627.html
        Part 2: http://home.comcast.net/~bc19191/blog/040703.html
        Part 3: http://home.comcast.net/~bc19191/blog/040707.html
        Part 4: http://home.comcast.net/~bc19191/blog/040711.html

It's a good summary, maybe it will be helpful.

-- 
David Magda <dmagda at ee.ryerson.ca>, http://www.magda.ca/
Because the innovator has for enemies all those who have done well under
the old conditions, and lukewarm defenders in those who may do well 
under the new. -- Niccolo Machiavelli, _The Prince_, Chapter VI
From: Andras Simon
Subject: Re: how to do java in lisp ?
Date: 
Message-ID: <klacy3worx.fsf@hexagon.renyi.hu>
Christophe Turle <······@nospam.fr> writes:

> hello,
> 
> I'm searching a library to do java in lisp ?
> 
> I want to write java programs using lisp forms. The goal is to generate java code from CL. The advantage is to use all the power of Lisp ending in a java application (absolute requirement).

Do you want Java with sexpr syntax, or a Common Lisp implementation that
compiles to Java (source or bytecodes)?

> 
> Jil is the nearest of what i want. But it is for Allegro. So no source code and it doesn't run on other platforms (i think)
>
> 
> Linj translates lisp to java programs. But sources are not available ...

Why do you need sources?

> 
> Armed Bear Lisp is supposed to compile lisp directly into byte codes. But i didn't find a lot of documentation for this and i don't know the quality of the generated code compared to java code compilation.

How do you know the quality of the code generated by jil? (Not to mention that
jil is nowhere near a full Common Lisp implemetation, while ABCL is very close
to being one.)

> ??? java s-exp library ? i remember seeing a C s-exp library somewhere ...

So you're content with writing Java as sexprs, and manipulate your program in
Lisp? I don't know of any such library, but Richard Waters has a paper
somewhere online that shows how to coerce the pretty printer to print Lisp as
Pascal. That may be a start.

Andras
From: ctu
Subject: Re: how to do java in lisp ?
Date: 
Message-ID: <40f51403$0$29376$626a14ce@news.free.fr>
"Andras Simon" <······@hexagon.renyi.hu> a �crit dans le message de
···················@hexagon.renyi.hu...
> Christophe Turle <······@nospam.fr> writes:
>
> > hello,
> >
> > I'm searching a library to do java in lisp ?
> >
> > I want to write java programs using lisp forms. The goal is to generate
java code from CL. The advantage is to use all the power of Lisp ending in a
java application (absolute requirement).
>
> Do you want Java with sexpr syntax, or a Common Lisp implementation that
> compiles to Java (source or bytecodes)?
>
> >
> > Jil is the nearest of what i want. But it is for Allegro. So no source
code and it doesn't run on other platforms (i think)
> >
> >
> > Linj translates lisp to java programs. But sources are not available ...
>
> Why do you need sources?


1- Linj is not available on all platform.
2- to suit my needs.
3- to learn how it has been coded.


> >
> > Armed Bear Lisp is supposed to compile lisp directly into byte codes.
But i didn't find a lot of documentation for this and i don't know the
quality of the generated code compared to java code compilation.
>
> How do you know the quality of the code generated by jil? (Not to mention
that
> jil is nowhere near a full Common Lisp implemetation, while ABCL is very
close
> to being one.)

Jil generate java code. so i can check the generated code.


>
> > ??? java s-exp library ? i remember seeing a C s-exp library somewhere
...
>
> So you're content with writing Java as sexprs, and manipulate your program
in
> Lisp?

yes.

> I don't know of any such library, but Richard Waters has a paper
> somewhere online that shows how to coerce the pretty printer to print Lisp
as
> Pascal. That may be a start.

i have download it http://www.merl.com/reports/docs/TR93-17.pdf have to read
it now !


Thx.

ctu
From: Mark McConnell
Subject: Re: how to do java in lisp ?
Date: 
Message-ID: <d3aed052.0408101103.57f3cb59@posting.google.com>
> > > Armed Bear Lisp is supposed to compile lisp directly into byte codes.
> But i didn't find a lot of documentation for this
[snip]

I'd like to second this question.  Can you use use ABCL to compile
Lisp to Java class files, the way you can use Kawa to compile Scheme
to Java class files?  I downloaded ABCL, but, like the previous
poster, I haven't found a lot of documentation.  I tried

(compile-file "mytestfile.lisp")

but it returned nil nil nil.
From: Andras Simon
Subject: Re: how to do java in lisp ?
Date: 
Message-ID: <vcdn012spi3.fsf@csusza.math.bme.hu>
···············@yahoo.com (Mark McConnell) writes:

> > > > Armed Bear Lisp is supposed to compile lisp directly into byte codes.
> > But i didn't find a lot of documentation for this
> [snip]
> 
> I'd like to second this question.  Can you use use ABCL to compile
> Lisp to Java class files, the way you can use Kawa to compile Scheme
> to Java class files?  I downloaded ABCL, but, like the previous
> poster, I haven't found a lot of documentation.  I tried
> 
> (compile-file "mytestfile.lisp")
> 
> but it returned nil nil nil.

Get the cvs version. (compile-file "mytestfile.lisp") will then
produce a mytestfile.abcl and a bunch of files with extension .cls;
those are Java class files. 

Andras
From: Mark McConnell
Subject: Re: how to do java in lisp ?
Date: 
Message-ID: <d3aed052.0408120637.58678a28@posting.google.com>
Andras Simon <······@math.bme.hu> wrote in message news:<···············@csusza.math.bme.hu>...
> Get the cvs version. (compile-file "mytestfile.lisp") will then
> produce a mytestfile.abcl and a bunch of files with extension .cls;
> those are Java class files. 
> 
> Andras

On the J download page at SourceForge, there are two files,
j-0.20.2-binary.zip and j-0.20.2.zip.  The second one contains the
source code.  Is that the same as the CVS version?
From: Andras Simon
Subject: Re: how to do java in lisp ?
Date: 
Message-ID: <vcdisbos4j3.fsf@csusza.math.bme.hu>
···············@yahoo.com (Mark McConnell) writes:

> On the J download page at SourceForge, there are two files,
> j-0.20.2-binary.zip and j-0.20.2.zip.  The second one contains the
> source code.  Is that the same as the CVS version?

No. You need a cvs client to check out the most recent version of the
sources. It's well worth the trouble (if any). See the instructions on
http://sourceforge.net/cvs/?group_id=55057.

Andras
From: Peter Herth
Subject: Re: how to do java in lisp ?
Date: 
Message-ID: <cfhuat$i4k$1@newsreader2.netcologne.de>
Andras Simon wrote:

> No. You need a cvs client to check out the most recent version of the
> sources. It's well worth the trouble (if any). See the instructions on
> http://sourceforge.net/cvs/?group_id=55057.

Unfortunately, trying to checkout "j" via cvs stops with an error:
cvs [checkout aborted]: unable to parse /cvsroot/armedbear-j/j/j/src/org
armedbear/lisp/Primitives.java,v; `author' not in the expected place

-- 
pet project: http://dawn.netcologne.de
homepage:    http://www.peter-herth.de
lisp stuff:  http://www.peter-herth.de/lisp.html
get Ltk here: http://www.peter-herth.de/ltk/
From: Andras Simon
Subject: Re: how to do java in lisp ?
Date: 
Message-ID: <vcdekmbrwt5.fsf@csusza.math.bme.hu>
Peter Herth <·····@netcologne.de> writes:

> Unfortunately, trying to checkout "j" via cvs stops with an error:
> cvs [checkout aborted]: unable to parse /cvsroot/armedbear-j/j/j/src/org
> armedbear/lisp/Primitives.java,v; `author' not in the expected place

I don't know if it's related, but until a few minutes ago,
http://cvs.sourceforge.net/viewcvs.py/armedbear-j also gave funny
error messages. That seems to be fixed now, so maybe checkout also
works again. Could you give it another try? If it fails, then a bug
report to SF may be the appropriate next step. 

Andras
From: Tomek Lipski
Subject: Re: how to do java in lisp ?
Date: 
Message-ID: <cd2st5$4ag$1@atlantis.news.tpi.pl>
Christophe Turle wrote:
> 
> hello,
> 
> I'm searching a library to do java in lisp ?
> 
> I want to write java programs using lisp forms. The goal is to generate 
> java code from CL. The advantage is to use all the power of Lisp ending 
> in a java application (absolute requirement).

hi,

I recently wrote simple Java code generator in Lisp and the results were 
very good - Lisp program had about 2k lines of code, takes database 
creation script and results in classes representing tables, references 
between them, and basic operations on database.
So it did the half of my work ;-) - the boring one.

There were some simple macros, but the Java-Lisp abstraction layer 
wasn't very strong or sophisticated - simple strings written to files.

Best regards,

Tomek Lipski
From: ctu
Subject: Re: how to do java in lisp ?
Date: 
Message-ID: <40f514b8$0$29367$626a14ce@news.free.fr>
"Tomek Lipski" <·······@no-spam.com.common-lisp.net> a �crit dans le message
de ·················@atlantis.news.tpi.pl...
> Christophe Turle wrote:
> >
> > hello,
> >
> > I'm searching a library to do java in lisp ?
> >
> > I want to write java programs using lisp forms. The goal is to generate
> > java code from CL. The advantage is to use all the power of Lisp ending
> > in a java application (absolute requirement).
>
> hi,
>
> I recently wrote simple Java code generator in Lisp and the results were
> very good - Lisp program had about 2k lines of code, takes database
> creation script and results in classes representing tables, references
> between them, and basic operations on database.
> So it did the half of my work ;-) - the boring one.
>
> There were some simple macros, but the Java-Lisp abstraction layer
> wasn't very strong or sophisticated - simple strings written to files.
>
> Best regards,
>
> Tomek Lipski

I'm interested in looking at your code : if you have a link else "c.turle" @
"wanadoo.fr"

ctu.
From: Tomek Lipski
Subject: Re: how to do java in lisp ?
Date: 
Message-ID: <cd40t8$c3r$1@nemesis.news.tpi.pl>
ctu wrote:

> "Tomek Lipski" <·······@no-spam.com.common-lisp.net> a ?crit dans le message
> de ·················@atlantis.news.tpi.pl...
> 
>>Christophe Turle wrote:
>>
>>>hello,
>>>
>>>I'm searching a library to do java in lisp ?
>>>
>>>I want to write java programs using lisp forms. The goal is to generate
>>>java code from CL. The advantage is to use all the power of Lisp ending
>>>in a java application (absolute requirement).
>>
>>hi,
>>
>>I recently wrote simple Java code generator in Lisp and the results were
>>very good - Lisp program had about 2k lines of code, takes database
>>creation script and results in classes representing tables, references
>>between them, and basic operations on database.
>>So it did the half of my work ;-) - the boring one.
>>
>>There were some simple macros, but the Java-Lisp abstraction layer
>>wasn't very strong or sophisticated - simple strings written to files.
>>
>>Best regards,
>>
>>Tomek Lipski
> 
> 
> I'm interested in looking at your code : if you have a link else "c.turle" @
> "wanadoo.fr"
I am very sorry, but the code is part of commercial project and i cant 
give it away.
But writing 2000 lines of code, when the idea is quite straightforward, 
shouldn't be a problem to anyone (this is my 3rd lisp program/system, so 
i am rather a beginner).

Best regards,

Tomek Lipski
From: Thomas A. Russ
Subject: Re: how to do java in lisp ?
Date: 
Message-ID: <ymi1xjdqcda.fsf@sevak.isi.edu>
Christophe Turle <······@nospam.fr> writes:

> 
> 
> hello,
> 
> I'm searching a library to do java in lisp ?
> 
> I want to write java programs using lisp forms. The goal is to generate java code from CL. The advantage is to use all the power of Lisp ending in a java application (absolute requirement).

Well, it depends on what you mean by "All the power of lisp.".

If you would settle for a lot of the dynamic programming features,
while giving up on certain things like multi-methods or untyped
functions, you might want to look at Stella:

  http://www.isi.edu/isd/LOOM/Stella/index.html
  
It is open source, and compiles to Common Lisp, Java and C++.

The resulting code is fairly to highly readable in the target
language.  (Cons and symbols are a bit ugly in Java and C++)
The canonical factorial function would look like this:

  (defun (factorial INTEGER) ((n INTEGER))
    (if (= n 0)
        (return 1)
        (return (* n (factorial (1- n))))))

and it compiles to the following:

Common Lisp:

(CL:PROGN
   (CL:DEFUN FACTORIAL (N) 
      (CL:DECLARE (CL:TYPE CL:FIXNUM N))
      (CL:CHECK-TYPE N CL:FIXNUM)  ;; Optional, depending on optimization level
      (CL:IF (CL:= N 0)
             1
             (CL:* N (FACTORIAL (CL:1- N)))))
   (CL:DECLAIM (CL:FTYPE (CL:FUNCTION (CL:FIXNUM) CL:FIXNUM) FACTORIAL)))

Java:   (in class Stella by default:)

public static int factorial(int n) {
  if (n == 0) {
    return (1);
  }
  else {
    return (n * Stella.factorial(n - 1));
  }
}


C++

int factorial(int n) {
  if (n == 0) {
    return (1);
  }
  else {
    return (n * factorial(n - 1));
  }
}

-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: ctu
Subject: Re: how to do java in lisp ?
Date: 
Message-ID: <40f7956b$0$20542$626a14ce@news.free.fr>
"Thomas A. Russ" <···@sevak.isi.edu> a �crit dans le message de
····················@sevak.isi.edu...
> Christophe Turle <······@nospam.fr> writes:
>
> >
> >
> > hello,
> >
> > I'm searching a library to do java in lisp ?
> >
> > I want to write java programs using lisp forms. The goal is to generate
java code from CL. The advantage is to use all the power of Lisp ending in a
java application (absolute requirement).
>
> Well, it depends on what you mean by "All the power of lisp.".
>
> If you would settle for a lot of the dynamic programming features,
> while giving up on certain things like multi-methods or untyped
> functions, you might want to look at Stella:
>
>   http://www.isi.edu/isd/LOOM/Stella/index.html
>
> It is open source, and compiles to Common Lisp, Java and C++.
>
> The resulting code is fairly to highly readable in the target
> language.  (Cons and symbols are a bit ugly in Java and C++)
> The canonical factorial function would look like this:
>
>   (defun (factorial INTEGER) ((n INTEGER))
>     (if (= n 0)
>         (return 1)
>         (return (* n (factorial (1- n))))))
>
> and it compiles to the following:
>
> Common Lisp:
>
> (CL:PROGN
>    (CL:DEFUN FACTORIAL (N)
>       (CL:DECLARE (CL:TYPE CL:FIXNUM N))
>       (CL:CHECK-TYPE N CL:FIXNUM)  ;; Optional, depending on optimization
level
>       (CL:IF (CL:= N 0)
>              1
>              (CL:* N (FACTORIAL (CL:1- N)))))
>    (CL:DECLAIM (CL:FTYPE (CL:FUNCTION (CL:FIXNUM) CL:FIXNUM) FACTORIAL)))
>
> Java:   (in class Stella by default:)
>
> public static int factorial(int n) {
>   if (n == 0) {
>     return (1);
>   }
>   else {
>     return (n * Stella.factorial(n - 1));
>   }
> }
>
>
> C++
>
> int factorial(int n) {
>   if (n == 0) {
>     return (1);
>   }
>   else {
>     return (n * factorial(n - 1));
>   }
> }
>
> -- 
> Thomas A. Russ,  USC/Information Sciences Institute

STELLA is not for me for this project. I want to be able to control all java
output. Which imports ... So i need to write in lisp syntax (sexp) java
programs. Once this done i can build my own abstraction over this java-lisp.
here's an example :


in java-lisp :

(setq *my-class*
'(class :public Test
   (method :public :static void main (String[] args)
     ((println (slot System out) "Hello World !")) )))



after calling (java-lisp-2-java *my-class* "Test.java")


in "Test.java" file :

public class Test
{
    public static void main( String[] args )
    {
        System.out.println( "Hello World !" ) ;
    }
}


Missing the call to integrate personal abstraction : Macros, Code-walker ...


ctu.
From: Antonio Menezes Leitao
Subject: Re: how to do java in lisp ?
Date: 
Message-ID: <874qo8ffu2.fsf@evaluator.pt>
"ctu" <······@nospam.com> writes:

> "Thomas A. Russ" <···@sevak.isi.edu> a �crit dans le message de
> ····················@sevak.isi.edu...
>> Christophe Turle <······@nospam.fr> writes:
>>
>> >
>> >
>> > hello,
>> >
>> > I'm searching a library to do java in lisp ?
>> >
>> > I want to write java programs using lisp forms. The goal is to generate
> java code from CL. The advantage is to use all the power of Lisp ending in a
> java application (absolute requirement).

I guess that what you want is a home-grown version of Stella or Linj.

>> If you would settle for a lot of the dynamic programming features,
>> while giving up on certain things like multi-methods or untyped
>> functions, you might want to look at Stella:
>>
> ...
> STELLA is not for me for this project. I want to be able to control all java
> output. Which imports ... So i need to write in lisp syntax (sexp) java
> programs. Once this done i can build my own abstraction over this java-lisp.
> here's an example :
>
> ...
>
> Missing the call to integrate personal abstraction : Macros, Code-walker ...

I'm afraid you'll find out that your goal is not as simple as you
might think.  Writing Java with sexp syntax is not a huge advantage
over writing Java with Java syntax.  As you already said, you want to
use macros and code-walkers to improve on your simple language and
build something really usable.  Although macros are obviously useful,
IMHO, you should look into the type declarations that your language
needs in order to translate into proper Java.  Unless you include a
good type inference mechanism, I'm afraid those type declarations will
be the most annoying part of your language.

Ant�nio Leit�o.
From: Pascal Bourguignon
Subject: Re: how to do java in lisp ?
Date: 
Message-ID: <871xjcazfr.fsf@thalassa.informatimago.com>
"ctu" <······@nospam.com> writes:
> STELLA is not for me for this project. I want to be able to control all java
> output. Which imports ... So i need to write in lisp syntax (sexp) java
> programs. Once this done i can build my own abstraction over this java-lisp.
> here's an example :
> 
> 
> in java-lisp :
> 
> (setq *my-class*
> '(class :public Test
>    (method :public :static void main (String[] args)
>      ((println (slot System out) "Hello World !")) )))
> 
> 
> 
> after calling (java-lisp-2-java *my-class* "Test.java")
> 
> 
> in "Test.java" file :
> 
> public class Test
> {
>     public static void main( String[] args )
>     {
>         System.out.println( "Hello World !" ) ;
>     }
> }
> 
> 
> Missing the call to integrate personal abstraction : Macros, Code-walker ...

So what you want is just some sugar in your java?


--------------------(example.sava)--------------------------
;; -*- mode: sexped-java -*-

(class Test (:public)
       (method main (:public :static) void ((args String[]))
               (System.out.println "Hello World !")))

;;;; example.sava                     --                     --          ;;;;
------------------------------------------------------------


---------------------(sava.lisp)----------------------------
;; -*- mode: Lisp -*-

(DEFUN LIST-INSERT-SEPARATOR (LIST SEPARATOR)
  "
RETURN:  A list composed of all the elements in `list'
         with `separator' in-between.
EXAMPLE: (list-insert-separator '(a b (d e f)  c) 'x)
         ==> (a x b x (d e f) x c)
"
  (COND
   ((NULL LIST)       '())
   ((NULL (CDR LIST)) (LIST (CAR LIST)))
   (T  (DO ((RESULT '())
            (ITEMS LIST (CDR ITEMS)))
           ((ENDP ITEMS) (NREVERSE (CDR RESULT)))
         (PUSH (CAR ITEMS) RESULT)
         (PUSH SEPARATOR RESULT))))
  );;LIST-INSERT-SEPARATOR


(defparameter *sava-constructs* nil)


(defmacro defsava (name args &body generator)
  `(push (list ',name (function (lambda ,args ,@generator))) *sava-constructs*))


(defun savagen (sava-sexp)
  (let ((savagen (cadr (assoc (car sava-sexp) *sava-constructs*))))
    (if savagen
      (apply savagen (cdr sava-sexp))
      ;; else assume a function call:
      (values
       (list (car sava-sexp)
             '|(| (list-insert-separator (cdr sava-sexp) '|,|) '|);| :nl)
       nil nil))))


(defun savagen-statement (statement)
  (if (listp statement)
    (savagen statement)
    (progn
      (format *error-output* "Cannot generate statement ~S~%" statement)
      (values "" nil t))));;savagen-statement


(defun generate (&rest args)
  (let ((w nil) (f nil))
    (values
     (apply (function concatenate) 'string
            (mapcan
             (lambda (arg)
               (if (eq :nl arg)
                 (list (format nil "~%"))
                 (list
                  (typecase arg
                    (string (format nil "~S" arg)
                            ;; TODO: check that ~S generates the correct 
                            ;;       format for java string literals!
                            )
                    (symbol (string arg))
                    (number (format nil "~A" number)
                            ;; TODO: generate numbers with java syntax!
                            )
                    (list (format nil "~{~A ~}"
                                  (mapcar (function generate) arg)))
                    (otherwise
                     (setf f t)
                     (format *error-output* "Cannot generate ~S~%" arg))) " ")))
             args))
     w f)));;generate



(defsava |class| (name options &rest methods)
  (let ((w nil) (f nil))
    (values
     (list (if (member :|public| options) '|public| '|private|)
               '|class| name '|{| :nl
               (mapcan
                (lambda (m)
                  (if (eq '|method| (first m))
                    (multiple-value-bind (jj ww ff) (savagen m)
                      (setf w (or w ww) f (or f ff))
                      (list jj))
                    (progn 
                      (format *error-output* 
                        "Syntax error: expected a method, not ~S~%" m)
                      (setf f t)
                      nil)))
                methods) '|}| :nl)
     w f)));;|class|


(defsava |method| (name options result-type args &rest body) 
  (let ((w nil) (f nil))
    (values
     (list (if (member :|public| options) '|public| '|private|)
               (if (member :|static| options) '|static| '|dynamic|)
               result-type
               name
               '|(|
               (list-insert-separator
                (mapcar (lambda (arg) (list (second arg) (first arg))) args) '|,|)
               '|)| '|{| :nl
               (mapcan (function savagen-statement) body)
               ;; TODO: add handling of warnings and faillures in argument
               ;;       and statement processing.
               '|}| :nl) w f)));;|method|


(defparameter *sava-readtable
  (let ((rt (copy-readtable))) (setf (readtable-case rt) :preserve)))


(defun read-sava-sexp (&optional (input-stream *standard-input*)
                                 (eof-error-p t) 
                                 (eof-value nil)
                                 (recursive-p nil))
  (let ((*readtable* *sava-readtable*))
    (read input-stream eof-error-p eof-value recursive-p)));;read-sava-sexp


(defun compile-sava-sexp (sava-sexp)
  "Return: a string containing java code; warnings-p; failure-p"
  (multiple-value-bind (j w f) (savagen sava-sexp)
    (if f
      (values "" w f)
      (values (generate j) w f))));;compile-sava-sexp


(defun compile-sava-file (input-file &key output-file 
                                     (verbose *compile-verbose*)
                                     (print *compile-print*)
                                     (external-format :default))
  (let ((output-falsename (or output-file
                                   (merge-pathnames (make-pathname :type "java")
                                                    (truename input-file))))
        (warnings-p nil)
        (failure-p  nil))
    (with-open-file (in (merge-pathnames input-file
                                         *default-pathname-defaults*)
                      :direction :input
                      :if-does-not-exist :error)
      (with-open-file (out output-falsename
                           :direction :output
                           :if-does-not-exist :create
                           :if-exists :supersede
                           :externa-format external-format)
        ;; truename does not work if the file does not exist!
        (setf output-truename (truename output-falsename))
        (when verbose
          (format *standard-output* "~&; Compiling ~A...~%" input-fle))
        (do* ((eof       (gensym))
              (sava-sexp (read-sava-sexp in nil eof)
                         (read-sava-sexp in nil eof)))
            ((eq eof sava-sexp))
          (when print
            (let ((*print-level* 2) (*print-length* 3))
              (format *standard-output* "~&; Compiling ~S~%" sava-sexp)))
          (format out "/* -*- mode: java -*- */~%")
          (multiple-value-bind (j w f) (compile-sava-sexp sava-sexp)
            (unless f (format out "~A" j))
            (setf warnings-p (or warnings-p w)
                  failure-p  (or failure-p  f))))))
    (values output-truename warnings-p failure-p)));;compile-sava-file

;;;; sava.lisp                        --                     --          ;;;;
------------------------------------------------------------


(load "sava.lisp")
(compile-sava-file "example.sava" "example.java")
(with-open-file (in "example.java" :direction :input)
    (do ((line (read-line in nil nil) (read-line in nil nil)))
        ((null line))
      (princ line) (terpri)))

==>
    
/* -*- mode: java -*- */
public  class  Test  {  
 
public  static  void  main  (  String[]  args      )  {  
 
System.out.println  (  "Hello World !"    );  
   }  
     }  


Of course, you could add some pretty printing or just use that of
emacs, for example, adding:

    (format out "~%/*~%Local Variables:~%eval: (indent-region (point-min) (point-max))~%End:~%*/~%")
      
at the end of compile-sava-file, and you could add some smarter logic
to avoid multiple spaces generation (just flatten the list before
generate!), and you will have to add more defsava constructs.


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

There is no worse tyranny than to force a man to pay for what he does not
want merely because you think it would be good for him. -- Robert Heinlein
From: ctu
Subject: Re: how to do java in lisp ?
Date: 
Message-ID: <40f94496$0$29424$626a14ce@news.free.fr>
thx Pascal for a very quick code !

i put your code there with some typos fixed :
 http://perso.wanadoo.fr/turle/lisp/sava.lisp
 http://perso.wanadoo.fr/turle/lisp/test-cases.sava


It's a good start but i can't see how to integrate macro facilities in it ?

example :

;;; test-cases.java

;; not working yet
(defmacro out (s)
  `(System.out.println ,s) )

(class Test (:public)
       (method main (:public :static) void ((args String[]))
          (out "Hello World !")
          (System.out.println "Hello World !")))


;;; output wanted

public  class  Test  {

public  static  void  main  (  String[]  args      )  {

 System.out.println  (  "Hello World !"    );
 System.out.println  (  "Hello World !"    );
   }
     }


;;; actual output

public  class  Test  {

public  static  void  main  (  String[]  args      )  {

out  (  "Hello World !"    );
 System.out.println  (  "Hello World !"    );
   }
     }


I don't want to define a "defsava out ..." => the sava language should be
restricted only to java syntax no more.



ctu.
From: Pascal Bourguignon
Subject: Re: how to do java in lisp ?
Date: 
Message-ID: <87fz7q9tzn.fsf@thalassa.informatimago.com>
"ctu" <······@nospam.com> writes:

> thx Pascal for a very quick code !
> 
> i put your code there with some typos fixed :
>  http://perso.wanadoo.fr/turle/lisp/sava.lisp
>  http://perso.wanadoo.fr/turle/lisp/test-cases.sava
> 
> 
> It's a good start but i can't see how to integrate macro facilities in it ?

There are broadly two ways to do it.

Either you use your lisp implementation mechanisms,
         or you implement your own lisp mechanisms.

Since Lisp is defined in term of Lisp, this is broadly the same,
but of course, if you implement your own mechanisms like I did,
it may give more work.

On the other hand, using your lisp implementation mechanisms leads to
execution by your lisp: you'd have to encapsulate all java sexp in a
macro like:  (defun java (&body savas) (generate-java savas) nil)


Since you don't want to execute your "sava" code in the lisp
environment, I prefered to implement my own read and compile loop.
That means that we'll have to implement our own macros.


------(sava.lisp)-------------------------------------------------------
;; -*- mode: Lisp -*-

(DEFUN LIST-INSERT-SEPARATOR (LIST SEPARATOR)
  "
RETURN:  A list composed of all the elements in `list'
         with `separator' in-between.
EXAMPLE: (list-insert-separator '(a b (d e f)  c) 'x)
         ==> (a x b x (d e f) x c)
"
  (COND
   ((NULL LIST)       '())
   ((NULL (CDR LIST)) (LIST (CAR LIST)))
   (T  (DO ((RESULT '())
            (ITEMS LIST (CDR ITEMS)))
           ((ENDP ITEMS) (NREVERSE (CDR RESULT)))
         (PUSH (CAR ITEMS) RESULT)
         (PUSH SEPARATOR RESULT))))
  );;LIST-INSERT-SEPARATOR


(defparameter *sava-macros*     nil)
(defparameter *sava-constructs* nil)


(defmacro defsavamacro (name args &body body)
  `(push (list ',name (function (lambda ,args ,@body))) *sava-macros*))


(defmacro defsava (name args &body generator)
  `(push (list ',name (function (lambda ,args ,@generator))) *sava-constructs*))


(defun savagen (sava-sexp)
  (if (eq '|defmacro| (car sava-sexp))
    (progn
      (push (list (second sava-sexp)
                  (coerce (list* 'lambda (third sava-sexp) (cdddr sava-sexp))
                          'function))
            *sava-macros*)
      (values '|| nil nil))
    (let ((savamac (cadr (assoc (car sava-sexp) *sava-macros*))))
      (if savamac
        (savagen (apply savamac (cdr sava-sexp)))
        (let ((savagen (cadr (assoc (car sava-sexp) *sava-constructs*))))
          (if savagen
            (apply savagen (cdr sava-sexp))
            ;; else assume a function call:
            (values
             (list (car sava-sexp)
                   '|(| (list-insert-separator (cdr sava-sexp) '|,|) '|);| :nl)
             nil nil)))))))  


(defun savagen-statement (statement)
  (if (listp statement)
    (savagen statement)
    (progn
      (format *error-output* "Cannot generate statement ~S~%" statement)
      (values "" nil t))));;savagen-statement


(defun generate (&rest args)
  (let ((w nil) (f nil))
    (values
     (apply (function concatenate) 'string
            (mapcan
             (lambda (arg)
               (if (eq :nl arg)
                 (list (format nil "~%"))
                 (list
                  (typecase arg
                    (string (format nil "~S" arg)
                            ;; TODO: check that ~S generates the correct 
                            ;;       format for java string literals!
                            )
                    (symbol (string arg))
                    (number (format nil "~A" arg)
                            ;; TODO: generate numbers with java syntax!
                            )
                    (list (format nil "~{~A ~}"
                                  (mapcar (function generate) arg)))
                    (otherwise
                     (setf f t)
                     (format *error-output* "Cannot generate ~S~%" arg))) " ")))
             args))
     w f)));;generate


(defsava |begin| (&rest body)
  (values (list '|{| (mapcan (function savagen-statement) body) '|}|)
          nil nil))


(defsava |class| (name options &rest methods)
  (let ((w nil) (f nil))
    (values
     (list (if (member :|public| options) '|public| '|private|)
               '|class| name '|{| :nl
               (mapcan
                (lambda (m)
                  (if (eq '|method| (first m))
                    (multiple-value-bind (jj ww ff) (savagen m)
                      (setf w (or w ww) f (or f ff))
                      (list jj))
                    (progn 
                      (format *error-output* 
                        "Syntax error: expected a method, not ~S~%" m)
                      (setf f t)
                      nil)))
                methods) '|}| :nl)
     w f)));;|class|


(defsava |method| (name options result-type args &rest body) 
  (let ((w nil) (f nil))
    (values
     (list (if (member :|public| options) '|public| '|private|)
               (if (member :|static| options) '|static| '|dynamic|)
               result-type
               name
               '|(|
               (list-insert-separator
                (mapcar (lambda (arg) (list (second arg) (first arg))) args) '|,|)
               '|)| '|{| :nl
               (mapcan (function savagen-statement) body)
               ;; TODO: add handling of warnings and faillures in argument
               ;;       and statement processing.
               '|}| :nl) w f)));;|method|


(defparameter *sava-readtable*
  (let ((rt (copy-readtable)))
    (setf (readtable-case rt) :preserve)
    rt ))


(defun read-sava-sexp (&optional (input-stream *standard-input*)
                                 (eof-error-p t) 
                                 (eof-value nil)
                                 (recursive-p nil))
  (let ((*readtable* *sava-readtable*))
    (read input-stream eof-error-p eof-value recursive-p)));;read-sava-sexp


(defun compile-sava-sexp (sava-sexp)
  "Return: a string containing java code; warnings-p; failure-p"
  (multiple-value-bind (j w f) (savagen sava-sexp)
    (if f
      (values "" w f)
      (values (generate j) w f))));;compile-sava-sexp


(defun compile-sava-file (input-file &key output-file 
                                     (verbose *compile-verbose*)
                                     (print *compile-print*)
                                     (external-format :default))
  (let ((output-falsename (or output-file
                                   (merge-pathnames (make-pathname :type "java")
                                                    (truename input-file))))
        (warnings-p nil)
        (failure-p  nil))
    (with-open-file (in (merge-pathnames input-file
                                         *default-pathname-defaults*)
                      :direction :input
                      :if-does-not-exist :error)
      (with-open-file (out output-falsename
                           :direction :output
                           :if-does-not-exist :create
                           :if-exists :supersede
                           :external-format external-format)
        ;; truename does not work if the file does not exist!
        (setf output-truename (truename output-falsename))
        (when verbose
          (format *standard-output* "~&; Compiling ~A...~%" input-file))
        (format out "/* -*- mode: java -*- */~%")
        (do* ((eof       (gensym))
              (sava-sexp (read-sava-sexp in nil eof)
                         (read-sava-sexp in nil eof)))
            ((eq eof sava-sexp))
          (when print
            (let ((*print-level* 2) (*print-length* 3))
              (format *standard-output* "~&; Compiling ~S~%" sava-sexp)))
          (multiple-value-bind (j w f) (compile-sava-sexp sava-sexp)
            (unless f (format out "~A" j))
            (setf warnings-p (or warnings-p w)
                  failure-p  (or failure-p  f))))))
    (values output-truename warnings-p failure-p)));;compile-sava-file

;;;; sava.lisp                        --                     --          ;;;;
------------------------------------------------------------------------


-----(test-cases.sava)--------------------------------------------------

(defmacro out (s)
  ;; Note how COMMON-LISP symbols are actually all upcase, 
  ;; since we're in :PRESERVE READTABLE-CASE.
  (IF (STRINGP s)
    `(System.out.println ,s)
    `(begin (System.out.println "Not a string!")
            (System.out.println ,s))));;out

(class Test (:public)
       (method main (:public :static) void ((args String[]))
               (out "Hello World!")
               (System.out.println "In the middle.")
               (out 42)))

  
;;;; test-cases.sava                  --                     --          ;;;;

------------------------------------------------------------------------

-----(test-cases.java)--------------------------------------------------
/* -*- mode: java -*- */
 
public  class  Test  {  
 
public  static  void  main  (  String[]  args      )  {  
 
System.out.println  (  "Hello World!"    );  
 System.out.println  (  "In the middle."    );  
 {  
System.out.println  (  "Not a string!"    );  
 System.out.println  (  42    );  
   }    }  
     }  
  
------------------------------------------------------------------------

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

There is no worse tyranny than to force a man to pay for what he does not
want merely because you think it would be good for him. -- Robert Heinlein
From: Christophe Turle
Subject: Re: how to do java in lisp ?
Date: 
Message-ID: <cdg6g1$rrq$1@amma.irisa.fr>
very cool ! as soon as i have more time i will try to expand it.

thx a lot.

>>It's a good start but i can't see how to integrate macro facilities in it ?
> 
> 
> There are broadly two ways to do it.
> 
> Either you use your lisp implementation mechanisms,
>          or you implement your own lisp mechanisms.
> 
> Since Lisp is defined in term of Lisp, this is broadly the same,
> but of course, if you implement your own mechanisms like I did,
> it may give more work.
> 
> On the other hand, using your lisp implementation mechanisms leads to
> execution by your lisp: you'd have to encapsulate all java sexp in a
> macro like:  (defun java (&body savas) (generate-java savas) nil)
> 
> 
> Since you don't want to execute your "sava" code in the lisp
> environment, I prefered to implement my own read and compile loop.
> That means that we'll have to implement our own macros.
> 
> 
> ------(sava.lisp)-------------------------------------------------------
> ;; -*- mode: Lisp -*-
> 
> (DEFUN LIST-INSERT-SEPARATOR (LIST SEPARATOR)
>   "
> RETURN:  A list composed of all the elements in `list'
>          with `separator' in-between.
> EXAMPLE: (list-insert-separator '(a b (d e f)  c) 'x)
>          ==> (a x b x (d e f) x c)
> "
>   (COND
>    ((NULL LIST)       '())
>    ((NULL (CDR LIST)) (LIST (CAR LIST)))
>    (T  (DO ((RESULT '())
>             (ITEMS LIST (CDR ITEMS)))
>            ((ENDP ITEMS) (NREVERSE (CDR RESULT)))
>          (PUSH (CAR ITEMS) RESULT)
>          (PUSH SEPARATOR RESULT))))
>   );;LIST-INSERT-SEPARATOR
> 
> 
> (defparameter *sava-macros*     nil)
> (defparameter *sava-constructs* nil)
> 
> 
> (defmacro defsavamacro (name args &body body)
>   `(push (list ',name (function (lambda ,args ,@body))) *sava-macros*))
> 
> 
> (defmacro defsava (name args &body generator)
>   `(push (list ',name (function (lambda ,args ,@generator))) *sava-constructs*))
> 
> 
> (defun savagen (sava-sexp)
>   (if (eq '|defmacro| (car sava-sexp))
>     (progn
>       (push (list (second sava-sexp)
>                   (coerce (list* 'lambda (third sava-sexp) (cdddr sava-sexp))
>                           'function))
>             *sava-macros*)
>       (values '|| nil nil))
>     (let ((savamac (cadr (assoc (car sava-sexp) *sava-macros*))))
>       (if savamac
>         (savagen (apply savamac (cdr sava-sexp)))
>         (let ((savagen (cadr (assoc (car sava-sexp) *sava-constructs*))))
>           (if savagen
>             (apply savagen (cdr sava-sexp))
>             ;; else assume a function call:
>             (values
>              (list (car sava-sexp)
>                    '|(| (list-insert-separator (cdr sava-sexp) '|,|) '|);| :nl)
>              nil nil)))))))  
> 
> 
> (defun savagen-statement (statement)
>   (if (listp statement)
>     (savagen statement)
>     (progn
>       (format *error-output* "Cannot generate statement ~S~%" statement)
>       (values "" nil t))));;savagen-statement
> 
> 
> (defun generate (&rest args)
>   (let ((w nil) (f nil))
>     (values
>      (apply (function concatenate) 'string
>             (mapcan
>              (lambda (arg)
>                (if (eq :nl arg)
>                  (list (format nil "~%"))
>                  (list
>                   (typecase arg
>                     (string (format nil "~S" arg)
>                             ;; TODO: check that ~S generates the correct 
>                             ;;       format for java string literals!
>                             )
>                     (symbol (string arg))
>                     (number (format nil "~A" arg)
>                             ;; TODO: generate numbers with java syntax!
>                             )
>                     (list (format nil "~{~A ~}"
>                                   (mapcar (function generate) arg)))
>                     (otherwise
>                      (setf f t)
>                      (format *error-output* "Cannot generate ~S~%" arg))) " ")))
>              args))
>      w f)));;generate
> 
> 
> (defsava |begin| (&rest body)
>   (values (list '|{| (mapcan (function savagen-statement) body) '|}|)
>           nil nil))
> 
> 
> (defsava |class| (name options &rest methods)
>   (let ((w nil) (f nil))
>     (values
>      (list (if (member :|public| options) '|public| '|private|)
>                '|class| name '|{| :nl
>                (mapcan
>                 (lambda (m)
>                   (if (eq '|method| (first m))
>                     (multiple-value-bind (jj ww ff) (savagen m)
>                       (setf w (or w ww) f (or f ff))
>                       (list jj))
>                     (progn 
>                       (format *error-output* 
>                         "Syntax error: expected a method, not ~S~%" m)
>                       (setf f t)
>                       nil)))
>                 methods) '|}| :nl)
>      w f)));;|class|
> 
> 
> (defsava |method| (name options result-type args &rest body) 
>   (let ((w nil) (f nil))
>     (values
>      (list (if (member :|public| options) '|public| '|private|)
>                (if (member :|static| options) '|static| '|dynamic|)
>                result-type
>                name
>                '|(|
>                (list-insert-separator
>                 (mapcar (lambda (arg) (list (second arg) (first arg))) args) '|,|)
>                '|)| '|{| :nl
>                (mapcan (function savagen-statement) body)
>                ;; TODO: add handling of warnings and faillures in argument
>                ;;       and statement processing.
>                '|}| :nl) w f)));;|method|
> 
> 
> (defparameter *sava-readtable*
>   (let ((rt (copy-readtable)))
>     (setf (readtable-case rt) :preserve)
>     rt ))
> 
> 
> (defun read-sava-sexp (&optional (input-stream *standard-input*)
>                                  (eof-error-p t) 
>                                  (eof-value nil)
>                                  (recursive-p nil))
>   (let ((*readtable* *sava-readtable*))
>     (read input-stream eof-error-p eof-value recursive-p)));;read-sava-sexp
> 
> 
> (defun compile-sava-sexp (sava-sexp)
>   "Return: a string containing java code; warnings-p; failure-p"
>   (multiple-value-bind (j w f) (savagen sava-sexp)
>     (if f
>       (values "" w f)
>       (values (generate j) w f))));;compile-sava-sexp
> 
> 
> (defun compile-sava-file (input-file &key output-file 
>                                      (verbose *compile-verbose*)
>                                      (print *compile-print*)
>                                      (external-format :default))
>   (let ((output-falsename (or output-file
>                                    (merge-pathnames (make-pathname :type "java")
>                                                     (truename input-file))))
>         (warnings-p nil)
>         (failure-p  nil))
>     (with-open-file (in (merge-pathnames input-file
>                                          *default-pathname-defaults*)
>                       :direction :input
>                       :if-does-not-exist :error)
>       (with-open-file (out output-falsename
>                            :direction :output
>                            :if-does-not-exist :create
>                            :if-exists :supersede
>                            :external-format external-format)
>         ;; truename does not work if the file does not exist!
>         (setf output-truename (truename output-falsename))
>         (when verbose
>           (format *standard-output* "~&; Compiling ~A...~%" input-file))
>         (format out "/* -*- mode: java -*- */~%")
>         (do* ((eof       (gensym))
>               (sava-sexp (read-sava-sexp in nil eof)
>                          (read-sava-sexp in nil eof)))
>             ((eq eof sava-sexp))
>           (when print
>             (let ((*print-level* 2) (*print-length* 3))
>               (format *standard-output* "~&; Compiling ~S~%" sava-sexp)))
>           (multiple-value-bind (j w f) (compile-sava-sexp sava-sexp)
>             (unless f (format out "~A" j))
>             (setf warnings-p (or warnings-p w)
>                   failure-p  (or failure-p  f))))))
>     (values output-truename warnings-p failure-p)));;compile-sava-file
> 
> ;;;; sava.lisp                        --                     --          ;;;;
> ------------------------------------------------------------------------
> 
> 
> -----(test-cases.sava)--------------------------------------------------
> 
> (defmacro out (s)
>   ;; Note how COMMON-LISP symbols are actually all upcase, 
>   ;; since we're in :PRESERVE READTABLE-CASE.
>   (IF (STRINGP s)
>     `(System.out.println ,s)
>     `(begin (System.out.println "Not a string!")
>             (System.out.println ,s))));;out
> 
> (class Test (:public)
>        (method main (:public :static) void ((args String[]))
>                (out "Hello World!")
>                (System.out.println "In the middle.")
>                (out 42)))
> 
>   
> ;;;; test-cases.sava                  --                     --          ;;;;
> 
> ------------------------------------------------------------------------
> 
> -----(test-cases.java)--------------------------------------------------
> /* -*- mode: java -*- */
>  
> public  class  Test  {  
>  
> public  static  void  main  (  String[]  args      )  {  
>  
> System.out.println  (  "Hello World!"    );  
>  System.out.println  (  "In the middle."    );  
>  {  
> System.out.println  (  "Not a string!"    );  
>  System.out.println  (  42    );  
>    }    }  
>      }  
>   
> ------------------------------------------------------------------------
>