This is an FP interpreter. It is written in FP. It can be run
in two ways: interactive or batch.

To run in interactive mode, "make". Then type "ffpi". You
are now in the FFP interpreter, which you can leave by
typing ^D (control-D). The interpreter looks at every
line you type. A line with a colon (":") is assumed to
be of the form
	function : argument
The function is applied to the argument, and the result is printed
out. Argument may be any valid FP object, as long as it is a valid
argument for function.

If the line does not contain a colon, the interpreter assumes
that it is the first line of a definition, and keeps reading
until it sees an empty line. When it sees the empty line, it
accepts the definition and prints the function name.

In this sample session, the lines printed by ffpi are preceded by =>

% ffpi
=> welcome to ffpi
reverse : <1, 2, 3, a>
=> <a, 3, 2, 1>
Def flatten null -> id;		# want to eliminate nils
	    atom -> [id];	# and keep atoms, in order
	    append o aa flatten	# flatten vectors recursively

=> flatten
flatten: <<a, b>, <c, d>>
=> <a, b, c, d>
^D
=> done
%

To run in batch mode, you must "make batch" or "make ffpb". Then,
prepare an input file "file.inp" of the form <function-name, argument,
definitions>, with function-name a name, argument an FFP value, and
definitions a vector of elements with syntax <name, body>; the body is
a valid FFP expression. Then typing "ffpint < file" will apply the
function to the argument and print the result on the standard output.
In batch mode, all definitions must be in FFP, so this is effectively
an FFP interpreter instead of an FP interpreter.

to be done:
add something that will load the standard libraries into ffpi (or ffpint?)
at startup time.
add some pseudo-functions for controlling the interpreter:
load : "filename"
loadm : <"filename", ..., "filename">
addpath : "pathname"	(used to search for files to load)
Add tracing, and pseudo-functions trace : "fname", untrace : "fname"
