> and was wondering why and how some pieces of code didn't have parens.
> My guess about the «why»: since its an assembler, there is no need for
> a tree of instruction.
Exactly. This is assembly and not Lisp. Though the normal Lisp _reader_
is used to parse the sources.
Assembly language is not a functional language, i.e. the individual
instructions do not "return" a value. So a fully paranthized syntax is
useless and just tedious.
> Now about the «how», I got lost trying to follow the Makefile…
In essence, the above assembly language is translated by a generic
assembler - which is written in PicoLisp - to some target assembly
language (normally GNU assembler for the given platform), which in turn
is assembled by the platform's assembler and linker to a binary
It works like this:
In "src64/Makefile" a shell script "mkAsm" is called. This script tries
to locate some exeutable PicoLisp to do the assembly. It tries
"/usr/bin/pil", "../pil" and "../ersatz/pil", in that order.
When found, it is used to run "mkAsm.l", which loads "lib/asm.l" and
some other stuff.
"lib/asm.l" is the generic assembler, it produces the target assembly
code (or C code in case of the emulator), by calling the function
'build' with the interpreter's source files in "src64/".
'build' sets up the output environment, and calls 'run' to execute the
"Prg" body, which is simply a 'load' in "mkAsm.l". That is, the sources
are indeed 'load'ed, at least they start to do so. Because the first
expression in e.g. "flow.l":
is a call to 'code'. And 'code' is a variation of 'section'.
Each section (can be 'code' or 'data') extends till the first non-atomic
expression is reached.
An this 'section' is tha actual workhorse of the assembler. If you look
at it, you see it calls (read) to parse the assembly sources, build the
'*Program', do some optimizations, and finally output it with the
'apply' call at the end.