Hi Christophe,

> My question:
> Is there any documentation about the building of the Ersatz jar ?
> I guess all the keys are in the mkJar file but I'm lost reading it.

Right, mkJar is the core of building Ersatz, and it is not documented.
Let me try to explain its basic working.

As you noticed, it merges the two files "sys.src" and "fun.src" into a
final "PicoLisp.java":

   (out "PicoLisp.java"
      (in "sys.src"

Most of "sys.src" is simply echoed via the (echo "<xxx>") calls. 'echo'
reads the input stream and writes everything to the output stream until
it hits the pattern "<xxx>".

         (echo "<VERSION>")

Now it stops when seeing "<VERSION>", and outputs

         (prin (glue "," *Version))

then proceeds to

      (echo "<SYM>")

to generate the 'mkSymbol()' calls. This is done by parsing "fun.src"

         (let Cnt (read)
            (in "fun.src"

it skips white space and comments

               (skip "#")

and goes all over the file with

               (loop

Now for every code block, it reads the name at the beginning of the line
till the first space

               (let Name (till " " T)

and outputs a mkSymbol() entry

                  (prinl
                     "mkSymbol(new Number(\""
                     (inc 'Cnt)
                     "\"), \""
                     Name
                     "\", Pico);" ) )

then skips the code till an empty line.

                  (while (line))
                  (prin "      ")
                  (NIL (skip "#")) ) )

The code will be of interest later.

Then it goes to the function area

         (echo "<FUN>")

and parses "fun.src" a second time

         (let Cnt (read)
            (in "fun.src"
               (skip "#")
               (loop

The purpose is to build a huge 'switch' statement for the PicoLisp
primitives. The reason is that an ordered switch (with sequential 'case'
values) is much faster than a method dispatch in Java.

                  (let (Name (till " " T)  Vars (read))
                     (line)
                     (prinl
                        "case "
                        (inc 'Cnt)
                        ":  // "
                        Name )

The function name is put there as a comment.

Short functions are put directly

                     (if (=T Vars)
                        (while (line)
                           (prinl "            " @) )

while longer ones are deferred as a call like doXXX(ex);

                        (prinl "               " "return do" Cnt "(ex);")
                        (while (line)) ) )
                  (prin "            ")
                  (NIL (skip "#")) ) ) )

Finally, it traverses "fun.src" a third time

         (skip)
         (echo "<DEF>")
         (let Cnt (read)
            (in "fun.src"
               (skip "#")
               (loop
                  (inc 'Cnt)
                  (let (Name (till " " T)  Vars (read))
                     (line)

to generate the 'doXXX' functions for the deferred code. Now the short ones
are skipped

                     (if (=T Vars)
                        (while (line))

and the longer ones are generated

                        (prinl
                           "final static Any do"
                           Cnt
                           "(Any ex) { // "
                           Name )

Local variables in the functions are declared according to their types

                        (declLocal Vars "int" '(i j k))
                        ...

and the rest of the function body is passed through

                        (while (line)
                           (prinl "      " @) )
                        (prinl "      }")

Finally, the rest of "sys.src" is written

      (echo) ) )

and the "javac" compiler called on the product


   (when (call "javac" "-O" "-g:none" "PicoLisp.java")
      ..

♪♫ Alex
-- 
UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe

Reply via email to