Free Lisp development environments for DOS.
"Lisp (historically LISP, an abbreviation of "list processing") is a family of programming languages with a long history and a distinctive, fully parenthesized prefix notation. Originally specified in the late 1950s, it is the second-oldest high-level programming language still in common use, after Fortran. Lisp has changed since its early days, and many dialects have existed over its history. Today, the best-known general-purpose Lisp dialects are Common Lisp, Scheme, Racket, and Clojure." [from the Lisp (programming language) article in Wikipedia].
"Common Lisp is a dialect of the Lisp programming language, published in American National Standards Institute (ANSI) standard document ANSI INCITS 226-1994 (S2018), formerly X3.226-1994 (R1999). It is a general-purpose, multi-paradigm programming language that supports a combination of procedural, functional, and object-oriented programming paradigms. As a dynamic programming language, it facilitates evolutionary and incremental software development, with iterative compilation into efficient run-time programs. This incremental development is often done interactively without interrupting the running application." [from the Common Lisp article in Wikipedia].
Concerning Lisp in modern times, Wikipedia writes: "After having declined somewhat in the 1990s, Lisp has experienced a resurgence of interest after 2000. Most new activity has been focused around implementations of Common Lisp, Scheme, Emacs Lisp, Clojure, and Racket, and includes development of new portable libraries and applications. As of 2010, there were eleven actively maintained Common Lisp implementations."
Thus, Lisp already existed in the times of DOS, and there were, of course, Lisp environments available for the first PCs (ex: Microsoft LISP). Other Lisp distributions were/are continued during this century, and include/included a version for DOS (ex: XLISP-PLUS). This text is a review of my experiences when installing some Lisp distributions on FreeDOS resp. MS-DOS 6.22.
Installing XLISP-PLUS on FreeDOS.
"XLISP is an experimental programming language combining some of the features of Common Lisp with an object-oriented extension capability. It was implemented to allow experimentation with object-oriented programming on small computers. Implementations of XLisp run on virtually every operating system. XLisp is completely written in the programming language C and is easily extended with user written built-in functions and classes. It is available in source form to non-commercial users. Many Common Lisp functions are built into XLISP. In addition, XLisp defines the objects object and class as primitives." [from the XLISP article on audacity-forum.de]. "XLISP_PLUS is an evolutionary improvement over David Betz's XLisp 2.1. It contains many enhancements and bug fixes. XLISP-PLUS contains the work of many individuals. While most have contributed their efforts to the public domain, a few reserve their copyrights when XLisp is used commercially. For that reason, XLISP-PLUS is only distributed for non-commercial (or educational) use. XLISP-PLUS was designed to run under multiple platforms. Executable files are available for several 80x86 based operating systems." That's how the programming environment is described on the XLISP-PLUS Homepage. It's from there, that you can download the installation files for DOS, referenced in this article.
There are two implementations of the XLISP-PLUS interpreter version 3.04 available for DOS: A 16-bit real mode version (file xl304exe.zip), and a 32-bit protected mode version (file xl304386.zip), that uses DJ Delorie's GO32 extender and is compatible with DPMI, VCPI, and XMS. There is no real sense to install the 16-bit version (especially on FreeDOS, that has 32-bit support): With the memory limitations of real mode programs, and the interpreter staying in memory, there will not be lots of place left for the source code, and thus you can only write small programs; also, this interpreter is slower than the 32-bit one. On the other hand, you don't hurt anyone if you install both interpreters. They don't require lots of space, have different file names and don't interfere with one another in any way.
Beside the interpreter binary (binaries), you'll need the XLisp files required for operation (file xl305req.zip). Not mandatory, but highly recommendable, to download the documentation (xl305doc.zip). If you want so, you can also download the XLISP-PLUS sources (file xl305src.zip) and the solutions to Project Euler problems done in XLisp to help verify operation (file xlisp_euler.zip).
I unzipped the download archives on my Windows 10 into a temporary directory, then burned the relevant files (no need to copy the __MACOSX files to your DOS machine) onto a CDROM (aka I created an ISO with the files). Be sure that the directory structure is conserved when unpacking the archives.
On my FreeDOS machine, I created a new directory (c:\xlisp), and copied the extracted files and folders to there using the xcopy command.
Supposing the the actual directors is C:\ and F: being the drive letter of my CD-drive, here are the commands to be run:
mkdir xlisp
f:
xcopy *.* c:\XLisp /E /I /H /Q
The screenshot shows how I copied the files from the CDROM to the harddisk. The directory structure in c:\XLisp will be exactly the same as the one shown for drive F: on the screenshot. Note, that the only required directories are "bin" (containing the executables of the two interpreters) and "lsp" (containing the required XLISP files).
To use XLISP-PLUS, the following environment variables have to be set:
- The directory with the executables has to be added to PATH:
set path=%path%;c:\xlisp\bin - The new environment variable XLPATH has to be set to the XLISP-PLUS installation directory:
set xlpath=c:\xlisp - On (very old) machines without floating point coprocessor (I suppose that all virtualization software supports the coprocessor; I use VMware Workstation, and it does),
the emu387 emulator must be used. It is included in the "bin" subdirectory of the XLISP-PLUS installation directory, and you have to set the environment variable:
set go32=emu c:/xlisp/bin/emu387
Creating a custom batch file.
I created a batch file called lisp.bat, that I placed in my custom directory c:\freedos\batch (you can use any directory, that is in the executables' path; e.g.
c:\freedos\bin). It may be used to run either the 16-bit, or the 32-bit interpreter, just starting the interpreter, or also loading a Lisp source file. The script may
be called without, with one, or with 2 arguments:
- When called without arguments, the 32-bit interpreter (xlisp.exe) is started.
- When called with one argument, and this argument is "-r" ("-16"), the 16-bit interpreter is started, if it is "-p" ("-32"), the 32-bit interpreter is started, otherwise the argument is considered to be a filename: it's the 32-bit interpreter that is started and the file specified is loaded.
- When called with two arguments, the first one must be "-r" ("-16") or "-p" ("-32"), otherwise an error occurs. The second argument is a filename. It's either of the two interpreters that is started, and the file specified is loaded.
The script also sets the PATH and XLPATH as required (note that %path0% is a custom environment variable on my system, set to %path% in fdauto,bat and that the environment variable "devel" is specific to my system; you can just comment it out or delete the corresponding line in the file). Before starting the interpreter, the script sets the actual directory to my XLISP-PLUS development directory (directory with my XLisp source files), that actually is d:\devel\xlisp.
Here are the commands:
@echo off
if "%1"=="-r" set _MODE=real
if "%1"=="-p" set _MODE=protected
if "%1"=="-16" set _MODE=real
if "%1"=="-32" set _MODE=protected
if not "%2"=="" goto TwoParams
if not "%1"=="" goto OneParam
:NoParam
set _MODE=protected
goto RunXLisp
:OneParam
if not "%_MODE%"=="" goto RunXLisp
set _SOURCE=%1
goto RunXLisp
:TwoParams
if "%_MODE%"=="" goto InvalidMode
set _SOURCE=%2
:RunXLisp
set path=%path0%;c:\xlisp
set xlpath=.;c:\xlisp;
set devel=xlisp
d:
cd \devel\xlisp
if "%_MODE%"=="real" goto Real
:Prot
c:\xlisp\bin\xlisp.exe %_SOURCE%
goto End
:Real
c:\xlisp\bin\xlispsml.exe %_SOURCE%
goto End
:InvalidMode
echo Invalid mode
echo Usage: lisp -r/-16 or XLisp -p/-32
:End
set _MODE=
set _SOURCE=
Some examples of Lisp expressions.
Lisp uses S-expressions to denote both code and data structure. Function calls, macro forms and special forms are written as lists, with the name of the operator first.
Some examples:
- Adding the integers from 1 to 4:
(+ 1 2 3 4)
- Adding the fractions from 1/2, 1/4 and 1/8:
(+ 1/2 1/4 1/8)
- Setting the variable x to 5:
(setq x 5)
- Setting the global variable *x* to 1.5:
(setf *x* 1.5)
- Defining a function, that calculates the square of a number and calling this function with x = 5:
(defun square (x)
(* x x))
(square 5)
As further example, here is the code of the definition of the factorial function:
(defun fact(x)
(if (> x 0)
(* x (fact(- x 1)))
1
)
)
This code is interpreted as: If x > 0 then fact(x) = x * fact(x - 1), else fact(x) = 1.
The screenshots show the execution of the 16-bit interpreter (on the left), and the 32-bit interpreter (on the right). The only difference that you notice with these examples is that the 32-bit interpreter is slow, and the 16-bit interpreter is even slower. The real difference occurs, if you write large programs; in this case you risk to get an "out o memory" error when using the real mode interpreter.
As you can see on the screenshots, to quit the interpreter (and return to the DOS command line), you have to use (exit). If you want XLISP-PLUS to load a source file at startup, specify this file as command line argument (if no file extension is given, it is supposed to be .lsp). If the file is not found, the message error: can't load file is displayed. You can also load a source, if you are within the interpreter environment; to do so, use the expression (load "<filename>"). The definitions are loaded at the top level, thus all functions defined in the file source are fully available.
To terminate my description of XLISP-PLUS, here are three functions with a string argument. The first function (in file hello1.lsp) requires a name as mandatory argument, and outputs the message "Hello <name>!". The second one (file hello2.lsp), has a second argument, that actually is a key argument. If this (optional) argument is specified and set to t (t stands for "true"), a happy smiley is displayed at the end of the message, otherwise, i.e. if no key argument is specified, or the key argument set to nil (nil stands for "false"), just the message is displayed. The third function (file happy3.lsp) uses a predicate variable to define the function behavior for the case where the key argument is set to nil: display of an unhappy smiley at the end of the message). Here is the code of the three functions:
(defun hello1 (name)
(format t "Hello ~a!~&" name)
)
(defun hello2 (name &key happy)
format t "Hello ~a " name)
(when happy
(format t ":)~&")
)
)
(defun hello3 (name &key (happy nil happy-p))
(format t "Hello ~a " name)
(when happy-p
(if happy
(format t ":)")
(format t ":(")
)
)
)
In these examples, ~a is the most used format directive to print a variable aesthetically, and ~& prints a newline. The key argument is called "happy"; you can specify it as :happy t or :happy nil in the function call. In the third function, "happy-p" is the predicate variable (the usage of the -p suffix is just a convention; you can call the variable differently if you want). To note that these three examples are from the O'Reilly book The Common Lisp Cookbook, that you can find as PDF on the Internet.
The screenshots below show how I loaded the Lisp source code from my .lsp files into the interpreter environment and called the functions with different arguments. Please, note that, as a difference with the code above, the function is called "hello" in all three files (redefining the function just replaces the old definition with the new one, just as assigning a new value to a variable replaces the old value by the new one).
Installing XLisp on MS-DOS 6.22.
"XLisp is an experimental programming language combining some of the features of Common Lisp with an object-oriented extension capability. It was implemented to allow experimentation with object-oriented programming on small computers. Implementations of XLisp run on virtually every operating system. XLisp is completely written in the programming language C and is easily extended with user written built-in functions and classes. It is available in source form to non-commercial users. Many Common Lisp functions are built into XLisp. In addition, XLisp defines the objects object and class as primitives.", they write on audacity-forum.de. The language has been created by David Betz. The here used XLisp 2.0, update 1 (I think that this is sometimes referred to as XLisp 2.1), has a copyright from the year 1998. It can be downloaded from github.
The download archive is a typical FreeDOS package folder structure. As I actually installed the software on MS-DOS 6.22, I extracted the files on my Windows 10 and put them all together on a floppy diskette, from where, on my MS-DOS machine, I copied them to c:\xlisp. The screenshot below shows the content of the installation directory. In fact, it's not more (and not less) than the interactive shell, the documentation, and an archive containing the sources.
You start the interactive XLisp shell by running xlisp.exe, and you leave the shell, as with XLISP-PLUS, by entering (exit). Also, as with XLISP-PLUS, you can load a XLisp source file using the expression (load "<filename>").
The square and factorial functions, described in the XLISP-PLUS section of the tutorial, work well with XLisp on MS-DOS.
The three hello functions, described in the XLISP-PLUS section, however, cause some problems. First, I got the error message Unknown format directive - "&". Second, whereas XLISP-PLUS automatically inserts a linefeed-carriage-return before displaying the "NIL" function return, XLisp 2.0 does not do this, thus it has to be included in all format expressions. How to do to code an end-of-line marker? Just as in C, using \n.
Here are modifications of my three hello functions, that work all correctly with XLisp 2.0:
(defun hello1 (name)
(format t "Hello ~a!\n" name)
)
(defun hello2 (name &key happy)
(format t "Hello ~a " name)
(if happy
(format t ":)\n")
(format t "\n")
)
)
(defun hello3 (name &key (happy nil happy-p))
(format t "Hello ~a " name)
(if happy-p
(if happy
(format t ":)\n")
(format t ":(\n")
)
(format t "\n")
)
)
To note, that a complete documentation (user manual, language reference, objects primer, XLisp internals, and more, is available at audacity-forum.de. Click the following link to download the XLisp documentation as ZIP archive. The archive contains a series of HTML files, with an index.html that allows to access all documents included (and there are functioning links in these documents, too, of course).
Installing Microsoft LISP on FreeDOS.
.....
Installing Star Sapphire Common LISP on FreeDOS.
.....
Installing CLISP on FreeDOS.
.....
Installing PDLISP on MS-DOS 6.22.
.....
Installing Flisp on MS-DOS 6.22.
.....
If you find this text helpful, please, support me and this website by signing my guestbook.