Ignore:
Timestamp:
06/16/11 14:56:43 (10 years ago)
Author:
Mark Evenson
Message:

Fold freestanding documentation into the Manual.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/abcl/doc/manual/abcl.tex

    r13334 r13335  
    7878\end{itemize}
    7979
     80\subsubsection{Lisp FFI}
     81
     82FFI stands for "Foreign Function Interface", which is the way the
     83contemporary Lisp world refers to methods of "calling out" from Lisp
     84into "foreign" langauges and envrionments.  This document describes
     85the various ways that one interacts with Lisp world of Abcl from Java,
     86considering the hosted Lisp as the "Foreign Function" that needs to be
     87"Interfaced".
     88
     89
     90\subsubsubsection{Calling Lisp from Java}
     91
     92Note: As the entire ABCL Lisp system resides in the org.armedbear.lisp
     93package the following code snippets do not show the relevant import
     94statements in the interest of brevity.
     95
     96Per JVM, there can only ever be a single Lisp interpreter.  This is
     97started by calling the static method `Interpreter.createInstance()`.
     98
     99\begin{code}{java}
     100Interpreter interpreter = Interpreter.createInstance();
     101\end{code}
     102
     103If this method has already been invoked in the lifetime of the current
     104Java process it will return null, so if you are writing Java whose
     105lifecycle is a bit out of your control (like in a Java servlet), a
     106safer invocation pattern might be:
     107
     108\begin{code}{java}
     109Interpreter interpreter = Interpreter.getInstance();
     110if (interpreter == null) {
     111  interpreter = Interpreter.createInstance();
     112}
     113\end{code}
     114
     115
     116
     117The Lisp `EVAL` primitive may be simply passed strings for evaluation,
     118as follows
     119
     120\begin{code}{java}   
     121String line = "(load \"file.lisp\")";
     122LispObject result = interpreter.eval(line);
     123\end{code}
     124
     125
     126Notice that all possible return values from an arbitrary Lisp
     127computation are collapsed into a single return value.  Doing useful
     128further computation on the `LispObject` depends on knowing what the
     129result of the computation might be, usually involves some amount
     130of instanceof introspection, and forms a whole topic to itself
     131(c.f. [Introspecting a LispObject](#introspecting)). 
     132
     133Using `EVAL` involves the Lisp interpreter.  Lisp functions may be
     134directly invoked by Java method calls as follows.  One simply locates
     135the package containing the symbol, then obtains a reference to the
     136symbol, and then invokes the `execute()` method with the desired
     137parameters.
     138
     139\begin{code}{java}   
     140    interpreter.eval("(defun foo (msg) (format nil \"You told me '~A'~%\" msg))");
     141    Package pkg = Packages.findPackage("CL-USER");
     142    Symbol foo = pkg.findAccessibleSymbol("FOO");
     143    Function fooFunction = (Function)foo.getSymbolFunction();
     144    JavaObject parameter = new JavaObject("Lisp is fun!");
     145    LispObject result = fooFunction.execute(parameter);
     146    // How to get the "naked string value"?
     147    System.out.prinln("The result was " + result.writeToString());
     148\end{code}
     149
     150If one is calling an primitive function in the CL package the syntax
     151becomes considerably simpler if we can locate the instance of
     152definition in the ABCL source, we can invoke the symbol directly.  To
     153tell if a `LispObject` contains a reference to a symbol.
     154
     155\begin{code}{java}   
     156    boolean nullp(LispObject object) {
     157      LispObject result = Primitives.NULL.execute(object);
     158      if (result == NIL) {
     159        return false;
     160      }
     161      return true;
     162   }
     163
     164\end{code}
     165
     166/subsubsubsection{Introspecting a LispObject}
     167
     168We present various patterns for introspecting an an arbitrary
     169`LispObject` which can represent the result of every Lisp evaluation
     170into semantics that Java can meaniningfully deal with.
     171
     172/subsubsubsubsection{LispObject as \java{boolean}}
     173
     174If the LispObject a generalized boolean values, one can use
     175\java{getBooleanValue()} to convert to Java:
     176
     177\begin{code}{java}
     178     LispObject object = Symbol.NIL;
     179     boolean javaValue = object.getBooleanValue();
     180\end{code}
     181
     182Although since in Lisp, any value other than NIL means "true", the
     183use of Java equality it quite a bit easier and more optimal:
     184
     185\begin{code}{java}
     186    boolean javaValue = (object != Symbol.NIL);
     187\end{code}
     188
     189/subsubsubsubsection{LispObject is a list}
     190
     191If LispObject is a list, it will have the type `Cons`.  One can then use
     192the `copyToArray[]` to make things a bit more suitable for Java
     193iteration.
     194
     195\begin{code}{java}
     196    LispObject result = interpreter.eval("'(1 2 4 5)");
     197    if (result instanceof Cons) {
     198      LispObject array[] = ((Cons)result.copyToArray());
     199      ...
     200    }
     201\end{code}
     202   
     203A more Lispy way to iterated down a list is to use the `cdr()` access
     204function just as like one would traverse a list in Lisp:;
     205
     206\begin{code}{java}
     207    LispObject result = interpreter.eval("'(1 2 4 5)");
     208    while (result != Symbol.NIL) {
     209      doSomething(result.car());
     210      result = result.cdr();
     211    }
     212\end{code}
     213
     214
    80215\subsection{JAVA}
    81216
Note: See TracChangeset for help on using the changeset viewer.