****************************************************************
****************************************************************
**                                                            **
**          FLISP,  a LISP interpreter for FreeDOS            **
**                                                            **
**          Copyright (C) 2005 Francesco Zamblera             **
**          under the GNU  General Public License             **
**                                                            **
**                       Version 1.0                          **
**                                                            **
**                    vilnergoy@yahoo.it                      **
**                                                            **
****************************************************************
****************************************************************



0..................Copyright and Disclaimer.
1..................Introduction.
2..................Principal characteristics of FLISP.
3..................List of supported LISP Functions.
4..................Non-standard FLISP functions.
5..................Limits, bugs and things to come.



****************************************************************
0. Copyright and Disclaimer
****************************************************************


    This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

    This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

(the text of the GNU GPL is in the file COPYING.TXT)


****************************************************************
1. Introduction
****************************************************************


    This mini LISP interpreter is written for the FreeDOS operating system
(www.freedos.org). The PASCAL source code has been compiled with FreePASCAL
(www.freepascal.org), a GNU 32-bit Pascal compiler which is compatible with
Turbo Pascal 7.0, and supports many platforms other than DOS.

    I am a linguist, and need LISP mostly to write NLP (Natural Language
Processing) applications. I began to write this mini LISP interpreter
in order to have a LISP on a FreeDOS platform which could support the use of
non-western European fonts. FLISP interacts with the FreeDOS utility XKEYB
and a modified version of GNUCHCP, in order to load fonts and keyboard
drivers; I will add some Unicode support in later releases. I am writing a
shell which will enable the user to switch fonts without having the compiler
"jumping" to the DOS and back to LISP (although this happens automatically
through a Batch script, it is loss of time, and it must be done from the
top-level read-eval-print cycle: you can't write a function that changes
font or keyboard driver).

    FLISP is still in its beginnings: only a basic subset of LISP functions
has been implemented, and some bugs and imperfections remain. However, the
interpreter is already operative, and I am anxious to share it with the Open
Source community, so here it is: Version 1.0.

    You will find the interpreter binaries and some bitmap fonts and
keyboard drivers, together with a font loader, which is similar to Kurt
Zammit's utility GNUCHCP.

    Many ideas for the interpreter are derived from John Crenshaw's course
"Let's write a compiler". In particular, the top-down recursive-descent
scanner is much as he showed in his course. The code is my own, though).

    Once uzipped, the binary package should look as follows:

    \flisp10\
       flisp10.exe        (the interpreter executable)
       flisp.bat          (a batch script to run the interpreter from)
       flisp.txt          (this file)
       flisp.lib          (FLISP library functions)
       copying.txt        (a copy of the GNU GPL)
       \fonts\
          rus.fnt         (Russian-Belarusan-Ukrainian fonts)
          rus.kbd         (Russian keyboard)
          gnuchcp3.exe    (32-bit font loader)
          gnuchcp3.pas    (font-loader source code)
          loadf.bat       (a batch script to load a bitmap and a keyboard)
          unloadf.bat     (a batch script which unloads font and keyboard)
          readme.txt      (font and keyboard information)
       \temp\


****************************************************************
2. Principal characteristics of FLISP.
****************************************************************

    Like Common LISP, FLISP is not context sensitive (to define an atom
context-sensitively, you have to enclose it between two |s: so 'ciao and
'CIAO are both CIAO, while '|ciao| is |ciao| and '|CIAO| is |CIAO|).

    Function definition (with DEFUN) admits &rest and &optional, but still no
&key.

    Backquote and comma-at is implemented (see as an example, in FLISP.LIB,
macros "when", "push", "pop").

    FLISP has a bulk of funcions implemented directly in the interpreter;
other functions are defined in LISP; their code is in the library file
FLISP.LIB, which is loaded and compiled into internal code automatically
when FLISP is started (a list of supported functions is in section 3).

    If you want to use the non-standard functions REFRESH, LOAD-FONTS,
LOAD_KEYB, UNLOAD-FONTS and UNLOAD-KEYB, please invoke FLISP via the batch
script FLISP.BAT. Otherwise, the mentioned functions will cause the
interpreter to exit. However, if this should inadvertedly happen, your data
wouldn't be lost: just invoke again FLISP with -c switch:

                                flisp10.exe -c

and your session will be restored. The upper mentioned functions work as
follows: a copy of all the global variables and all the user-defined
functions which are in memory is saved to various files (see below). The
program then exits with a particular exit-code; the exit-code is "caught"
by the shell script, which loads/unloads the fonts and keyboards etc, and
then invokes again the interpreter with the switch -c (continue). This makes
the interpreter load and compile those files which were saved. These files
are:

          $globvar.dat
          $func.dat
          $openfile.dat
          $fileids.dat
          $filedirs.dat
          $filename.dat
          $filepos.dat

   Font and keyboard functions also rewrite a file called

          script.bat

   All these files are located in the \temp directory. So please make sure
you don't have any files with these names there, because they would get
erased.


****************************************************************
3. List of supported LISP Functions
****************************************************************

    The following functions are defined for FLISP.
    Those written in capital letters, as well as the ones represented
by operands (such as *, -, etc.) are implemented directly in the interpreter;
the ones written in small letters are defined in the library (flisp.lib).
    Finally, those functions are marked with a (*) whose usage somewhat
differs from standard Common Lisp practice (further comments in section 4).


*
**
***

+
*
-
/

=
/=
<
>
<=
>=

and
append                 (*)
apply
aref                   (*)
assoc
BACKQUOTE
BOUNDP
butlast
BYE
CAR
case
CATCH
CDR
cddr
char
CLOSE
COERCE                (*)
COMMA
COMMA-AT
concatenate           (*)
COND
CONS                  (*)
COS
DEFUN
DEFMACRO
defstruct
DO
DO*
DOLIST
DOLOOP
DOTIMES
EQ
eql
equal
EVAL
EXP
expt                  (*)
find
first
fixnum                (*)
float
FORMAT
funcall
getf
IF
intersection
is-list
HELP                  (*)
LAMBDA
last                  (*)
lastelem              (*)
length
LET
LET*
LIST
LOAD
LOOP
make-array
MAKE-SYMBOL
mapcar
max
member
min
mod
not
nth
null
OPEN
or
QUIT
QUOTE
pop
position
PRINC
PRINT
progn
push
RANDOM
READ
READ-LINE
rem
remove
rest
reverse
RETURN
second
SETQ
set-difference
setf                   (*)
SIN
SQRT
sort
square
STRING=
STRING/=
STRING>
STRING<
subseq
subsetp
SYMBOL-NAME
TERPRI
THROW
TYPE-OF
union
unless
when
WRITE
WRITE-LINE


    Also defined in the library:

++ (corresponds to Common Lisp 1+)
-- (corresponds to Common Lisp 1-)


    Library functions use a number of auxiliary functions:

append-elem
append-list
aref-aux
case-aux
conc-aux
length-list
make-vector
ok
position-list
reverse-list
setf-array
setf-struct
setf-vector
sort-func
subseq-list



****************************************************************
4. Non-standard FLISP functions.
****************************************************************

    These function are proper to FLISP, and provide some commands which
interface with FreeDOS:


INIT-FILE: see SAVE-FUNCTION, following.


SAVE-FUNCTION (or simply SF). This function is useful in interactive
programming: suppose you are defining some functions; when, after a
trials-and-errors stage, you get to write the definitive version of your
functions, you can type

                      (SF myfunction)

and the code of the function you have just defined will be saved on a
"desktop" file. This file must have been declared previously with the
function

                      (INIT-FILE "filename")

    Function INIT-FILE doesn't overwrite the file if it already exists
(however, perhaps you had better making a backup copy first - remember the
disclaimer section!).

    If you save the same function more than once, all the variants will be
saved (the last one will appear last).


   LOAD-FONT. Use: (LOAD-FONT 'font-filename). This function saves the
current status of the system (global variables with their values and
user-defined functions, as well as the library). The interpreter then exits
to the shell script FLISP.BAT, which loads the bitmap font specified (using
GNUCHCP3) AND the keyboard driver with the same name; then calls FLISP again,
with switch -c  --  this will restore the status of the system previously
saved.

    Bitmap fonts and keyboard drivers are in the directory .\flisp\fonts.
Bitmaps have the extension .fnt, and drivers -- .key. These files come in
pairs with the same file name: a bitmap and a keyboard driver for that
bitmap. When you call LOAD-FONT, simply give this name as a parameter,
without extensions.


LOAD-KEYB. Use: (LOAD-KEYB 'filename). Loads a keyboard driver for XKEYB.
Filename is the same as for the LOAD-FONT function (without extension). For
details about fonts and keyboard drivers, see the README.TXT file in the
directory .\flisp\fonts.


UNLOAD-FONT. Use: (UNLOAD-FONT). Restores the default DOS 8x16 fonts.


UNLOAD-KEYB. Use (UNLOAD-KEYB). Unloads the keyboard driver (calling the
FreeDOS command xkeyb /U).


WRITE-FUNC. Use: (WRITE-FUNC 'function-name). Writes the function whose name
is given as a parameter to standard output.
                 (WRITE-FUNC 'file-name 'function-name). Writes the function
whose name is given as the second parameter to the file whose name is
represented by the first parameter.


REFRESH: This is a function I hope to dispense with in later releases. The
extensive use of pointers and the very primitive garbage collection makes
that, if there is not much free memory, the execution of long programs can
become very slow. (REFRESH) saves the data (like LOAD-FONT), exits the
interpreter, and starts it again, with the switch -c, so that the data be
loaded once again. In order for REFRESH to work properly, it must be called
only from the topmost read-eval-print cycle (that is, not embedded in some
function), and the interpreter must have been started from the batch script
FLISP.BAT, and not directly with FLISP10.EXE. In this latter case, the
interpreter just saves global variables and functrions and exits. If this
should happen, restart the interpreter with

                                   flisp10 -c.


    These are standard LISP functions, whose use is somewhat different in
FLISP:

APPEND: concatenates TWO lists or two strings. E.g.
        (append "abcd" "efg") gives "abcdefg";
        (append '(a b c d) '(e f g)) gives (a b c d e f g).

AREF:   as in Common LISP, AREF returns the value of a field of an array.
        However, it can't be used to change that value. So, if a
        is a three-place vector, (AREF a 2) will return the value of the
        third position. To refer to the fields of a structure, you use
        the functions defined automatically when you declare a structure
        with DEFSTRUCT: if, for example, you have declared

             (DEFSTRUCT goofy field1 field2 field3)

        you can refer to the fields with the automatically-defined functions
        GOOFY-FIELD1, GOOFY-FIELD2, GOOFY-FIELD3.
        To assign a value to a field of a structure or array, see SETF below.

COERCE  can change also characters to fixnums (their ASCII code) and
        vice-versa. So, (COERCE #\a 'fixnum) returns 97 (ASCII code for the
        character "a"), while (COERCE 97 'char) returns #\a.

        COERCE can also change character lists to strings:
               (COERCE "abcd" 'lst) returns (#\a #\b #\c)
               (remember that the name of the list type
               it's LST and not LIST! LIST is the standard LISP function to
               build a list from its elements);
               (COERCE '(#\A #\b #\C #\d)) returns "AbCd".

CONCATENATE works only with strings, and gives strings or lists of characters
       as result. Unlike APPEND, you can CONCATENATE more than two strings.
       For example, (concatenate 'string "abcd" "ef" "gh") returns
       "abcdefgh", while (concatenate 'list "abc" "de") returns
       (#\a #\b #\c #\d #\e)

CONS: the second argument must be a list. There are no dotted pairs in FLISP.

EXPT: works only with integer positive powers.

FIXNUM: converts floats to fixnums, and also chars to their ASCII code.

HELP: still to be implemented.

LAST: returns A LIST with thwe last element of the list given as a parameter.
      For example, (last '(a b c d e)) gives (e).

LASTELEM: returns the last element of a list. E.g. (lastelem '(a b c d e))
      returns e.

SETF uses a different syntax from CLISP:

          (SETF structure-name field value)

    For example, let A be the array (NIL NIL NIL NIL) and B the structure
    (:FIELD1 NIL :FIELD2 NIL :FIELD3 NIL):

    (setf a 2 5) modifies the array A, which will contain (NIL NIL 5 NIL)
    (recall that the first field of an array is the field number zero, like
    in C).

    (setf b :field2 'ciao) modifies B as follows:
    (:FIELD1 NIL :FIELD2 'CIAO :FIELD3 NIL).

    AREF and the automatically-defined functions to refer elements of a
structure cannot used to assign alues to the fields.

STRUCTURES and ARRAYS in FLISP are implemented simply as lists.


****************************************************************
5. Limits, bugs and things to come.
****************************************************************

LIMITS:
 - The code is somewhat a "wild" one -- no real garbage collection and
   extensive use of pointers. Further, many procedures typically repeat
   pieces of code across one another. A sapient rewriting of the code with
   some use of OOP could do much better job.

 - The interpreter is rather slow.

 - Error checking is unsatisfactory. Sometimes you will get a lot of error
   messages, because, once the first error is found, the scanner goes on and
   scans further, spitting out nonsense errors. So please just consider the
   first error you get and ignore the rest.

 - No function call with keywords to identify parameters.


BUGS:
 - Some syntax errors make the program terminate and exit unespectedly (via a
   PASCAL runtime error), so please always save your functions once you have
   written it one at a time, using the SAVE-FUNCTION (or SF) command.

THINGS TO COME:
 - A better error-checking;
 - More fonts, and a bitmap font editor;
 - A shell internal to the interpreter, with font and keyboard driver;
 - Read and write UNICODE strings.
 - Better documentation.
