[armedbear-cvs] r12560 - in trunk/abcl/doc: . design/pathnames

Mark Evenson mevenson at common-lisp.net
Thu Mar 18 10:15:54 UTC 2010


Author: mevenson
Date: Thu Mar 18 06:15:53 2010
New Revision: 12560

Log:
More work on standalone documentation.



Added:
   trunk/abcl/doc/debugging-internals.markdown
   trunk/abcl/doc/lisp-ffi.markdown
Removed:
   trunk/abcl/doc/misc.markdown
Modified:
   trunk/abcl/doc/design/pathnames/jar-pathnames.markdown
   trunk/abcl/doc/slime.markdown

Added: trunk/abcl/doc/debugging-internals.markdown
==============================================================================
--- (empty file)
+++ trunk/abcl/doc/debugging-internals.markdown	Thu Mar 18 06:15:53 2010
@@ -0,0 +1,5 @@
+Notes on debugging ABCL
+
+*  Need to set *PRINT-CIRCLE* to T when examining the structures in
+   jvm.lisp.
+

Modified: trunk/abcl/doc/design/pathnames/jar-pathnames.markdown
==============================================================================
--- trunk/abcl/doc/design/pathnames/jar-pathnames.markdown	(original)
+++ trunk/abcl/doc/design/pathnames/jar-pathnames.markdown	Thu Mar 18 06:15:53 2010
@@ -1,45 +1,50 @@
 JARs and JAR entries in ABCL
 ============================
 
-Mark Evenson
-Created:  09 JAN 2010
-Modified: 16 MAR 2010 
+    Mark Evenson
+    Created:  09 JAN 2010
+    Modified: 16 MAR 2010 
 
 Notes towards sketching an implementation of "jar:" references to be
-contained in PATHNAMEs within ABCL.  
+contained in Common Lisp `PATHNAMEs` within ABCL.  
 
 Goals
 -----
 
-1.  Use Common Lisp pathnames to refer to entries in a JAR file.
+1.  Use Common Lisp pathnames to refer to entries in a jar file.
 
     
-2.  Use 'jar:' schema as documented in java.net.JarURLConnection for
+2.  Use `'jar:'` schema as documented in [`java.net.JarURLConnection`][jarURLConnection] for
     namestring representation.
 
-An entry in a JAR file:
-    #p"jar:file:baz.jar!/foo"
+    An entry in a JAR file:
+
+         #p"jar:file:baz.jar!/foo"
     
-A JAR file:
-    #p"jar:file:baz.jar!/"
+    A JAR file:
+
+         #p"jar:file:baz.jar!/"
 
-A JAR file accessible via URL
-    #p"jar:http://example.org/abcl.jar!/"
+    A JAR file accessible via URL
 
-An entry in a ABCL FASL in a URL accessible JAR file
-    #p"jar:jar:http://example.org/abcl.jar!/foo.abcl!/foo-1.cls"
+         #p"jar:http://example.org/abcl.jar!/"
 
-3.  MERGE-PATHNAMES working for JAR entries in the following use cases:
+    An entry in a ABCL FASL in a URL accessible JAR file
 
-    (merge-pathnames "foo-1.cls" "jar:jar:file:baz.jar!/foo.abcl!/foo._")
-    "jar:jar:file:baz.jar!/foo.abcl!/foo-1.cls"
+         #p"jar:jar:http://example.org/abcl.jar!/foo.abcl!/foo-1.cls"
+         
+[jarUrlConnection]: http://java.sun.com/javase/6/docs/api/java/net/JarURLConnection.html
 
-    (merge-pathnames "foo-1.cls" "jar:file:foo.abcl!/")
-    "jar:file:foo.abcl!/foo-1.cls"
+3.  `MERGE-PATHNAMES` working for jar entries in the following use cases:
 
-4.  TRUENAME and PROBE-FILE working with "jar:" 
+        (merge-pathnames "foo-1.cls" "jar:jar:file:baz.jar!/foo.abcl!/foo._")
+        ==> "jar:jar:file:baz.jar!/foo.abcl!/foo-1.cls"
 
-4.1  TRUENAME cannonicalizing the JAR reference.
+        (merge-pathnames "foo-1.cls" "jar:file:foo.abcl!/")
+        ==> "jar:file:foo.abcl!/foo-1.cls"
+
+4.  TRUENAME and PROBE-FILE working with "jar:" with TRUENAME
+    cannonicalizing the JAR reference.
 
 5.  DIRECTORY working within JAR files (and within JAR in JAR).
 
@@ -100,163 +105,163 @@
 
 An incomplete BNF of the syntax of JAR PATHNAME would be:
 
-  JAR-PATHNAME ::= "jar:" URL "!/" [ ENTRY ]
+      JAR-PATHNAME ::= "jar:" URL "!/" [ ENTRY ]
+
+      URL ::= <URL parsable via java.net.URL.URL()>
+            | JAR-FILE-PATHNAME
 
-  URL ::= <URL parsable via java.net.URL.URL()>
-        | JAR-FILE-PATHNAME
-  
-  JAR-FILE-PATHNAME ::= "jar:" "file:" JAR-NAMESTRING "!/" [ ENTRY ]
+      JAR-FILE-PATHNAME ::= "jar:" "file:" JAR-NAMESTRING "!/" [ ENTRY ]
 
-  JAR-NAMESTRING  ::=  ABSOLUTE-FILE-NAMESTRING
-                     | RELATIVE-FILE-NAMESTRING
+      JAR-NAMESTRING  ::=  ABSOLUTE-FILE-NAMESTRING
+                         | RELATIVE-FILE-NAMESTRING
 
-  ENTRY ::= [ DIRECTORY "/"]* FILE
+      ENTRY ::= [ DIRECTORY "/"]* FILE
 
 
 ### Notes
 
-1.  ABSOLUTE-FILE-NAMESTRING and RELATIVE-FILE-NAMESTRING use the
+1.  `ABSOLUTE-FILE-NAMESTRING` and `RELATIVE-FILE-NAMESTRING` use the
 local filesystem conventions, meaning that on Windows this could
-contain '\' as the directory separator, while an ENTRY always uses '/'
+contain '\' as the directory separator, while an `ENTRY` always uses '/'
 to separate directories within the jar proper.
 
 
 Use Cases
 ---------
 
-// UC1 -- JAR
-pathname: {
-  namestring: "jar:file:foo/baz.jar!/"
-  device: ( 
-    pathname: {  
-      device: "jar:file:"
-      directory: (:RELATIVE "foo")
-      name: "baz"
-      type: "jar"
+    // UC1 -- JAR
+    pathname: {
+      namestring: "jar:file:foo/baz.jar!/"
+      device: ( 
+        pathname: {  
+          device: "jar:file:"
+          directory: (:RELATIVE "foo")
+          name: "baz"
+          type: "jar"
+        }
+      )
     }
-  )
-}
 
 
-// UC2 -- JAR entry 
-pathname: {
-  namestring: "jar:file:baz.jar!/foo.abcl"
-  device: ( pathname: {
-    device: "jar:file:"
-    name: "baz"
-    type: "jar"
-  }) 
-  name: "foo"
-  type: "abcl"
-}
-
-
-// UC3 -- JAR file in a JAR entry
-pathname: {
-  namestring: "jar:jar:file:baz.jar!/foo.abcl!/"
-  device: ( 
-    pathname: {
-      name: "baz"
-      type: "jar"
-    }
+    // UC2 -- JAR entry 
     pathname: {
+      namestring: "jar:file:baz.jar!/foo.abcl"
+      device: ( pathname: {
+        device: "jar:file:"
+        name: "baz"
+        type: "jar"
+      }) 
       name: "foo"
       type: "abcl"
-    } 
-  )
-}
-
-// UC4 -- JAR entry in a JAR entry with directories
-pathname: {
-  namestring: "jar:jar:file:a/baz.jar!/b/c/foo.abcl!/this/that/foo-20.cls"
-  device: ( 
-    pathname {
-      directory: (:RELATIVE "a")      
-      name: "bar"
-      type: "jar"
     }
-    pathname {
-      directory: (:RELATIVE "b" "c")
-      name: "foo"
-      type: "abcl"
+
+
+    // UC3 -- JAR file in a JAR entry
+    pathname: {
+      namestring: "jar:jar:file:baz.jar!/foo.abcl!/"
+      device: ( 
+        pathname: {
+          name: "baz"
+          type: "jar"
+        }
+        pathname: {
+          name: "foo"
+          type: "abcl"
+        } 
+      )
     }
-  )
-  directory: (:RELATIVE "this" "that")
-  name: "foo-20"
-  type: "cls" 
-}
-
-// UC5 -- JAR Entry in a JAR Entry
-pathname: {
-  namestring: "jar:jar:file:a/foo/baz.jar!/c/d/foo.abcl!/a/b/bar-1.cls"
-  device: (
+
+    // UC4 -- JAR entry in a JAR entry with directories
     pathname: {
-      directory: (:RELATIVE "a" "foo")
-      name: "baz"
-      type: "jar"
+      namestring: "jar:jar:file:a/baz.jar!/b/c/foo.abcl!/this/that/foo-20.cls"
+      device: ( 
+        pathname {
+          directory: (:RELATIVE "a")      
+          name: "bar"
+          type: "jar"
+        }
+        pathname {
+          directory: (:RELATIVE "b" "c")
+          name: "foo"
+          type: "abcl"
+        }
+      )
+      directory: (:RELATIVE "this" "that")
+      name: "foo-20"
+      type: "cls" 
     }
+
+    // UC5 -- JAR Entry in a JAR Entry
     pathname: {
-      directory: (:RELATIVE "c" "d")
-      name: "foo"
-      type: "abcl"
+      namestring: "jar:jar:file:a/foo/baz.jar!/c/d/foo.abcl!/a/b/bar-1.cls"
+      device: (
+        pathname: {
+          directory: (:RELATIVE "a" "foo")
+          name: "baz"
+          type: "jar"
+        }
+        pathname: {
+          directory: (:RELATIVE "c" "d")
+          name: "foo"
+          type: "abcl"
+        }
+      )
+      directory: (:ABSOLUTE "a" "b")
+      name: "bar-1"
+      type: "cls"
     }
-  )
-  directory: (:ABSOLUTE "a" "b")
-  name: "bar-1"
-  type: "cls"
-}
-
-// UC6 -- JAR entry in a http: accessible JAR file
-pathname: {
-  namestring: "jar:http://example.org/abcl.jar!/org/armedbear/lisp/Version.class",
-  device: ( 
-    "http://example.org/abcl.jar"
+
+    // UC6 -- JAR entry in a http: accessible JAR file
     pathname: {
-      directory: (:RELATIVE "org" "armedbear" "lisp")
-      name: "Version"
-      type: "class"
-   }
-}
-
-// UC7 -- JAR Entry in a JAR Entry in a URL accessible JAR FILE
-pathname: {
-   namestring  "jar:jar:http://example.org/abcl.jar!/foo.abcl!/foo-1.cls"
-   device: (
-     "http://example.org/abcl.jar"
-     pathname: { 
-       name: "foo"
-       type: "abcl"
-     }
-  )
-  name: "foo-1"
-  type: "cls"
-}
-
-// UC8 -- JAR in an absolute directory
-
-pathame: {
-   namestring: "jar:file:/a/b/foo.jar!/"
-   device: (
-     pathname: {
-       directory: (:ABSOLUTE "a" "b")
+      namestring: "jar:http://example.org/abcl.jar!/org/armedbear/lisp/Version.class",
+      device: ( 
+        "http://example.org/abcl.jar"
+        pathname: {
+          directory: (:RELATIVE "org" "armedbear" "lisp")
+          name: "Version"
+          type: "class"
+       }
+    }
+
+    // UC7 -- JAR Entry in a JAR Entry in a URL accessible JAR FILE
+    pathname: {
+       namestring  "jar:jar:http://example.org/abcl.jar!/foo.abcl!/foo-1.cls"
+       device: (
+         "http://example.org/abcl.jar"
+         pathname: { 
+           name: "foo"
+           type: "abcl"
+         }
+      )
+      name: "foo-1"
+      type: "cls"
+    }
+
+    // UC8 -- JAR in an absolute directory
+
+    pathame: {
+       namestring: "jar:file:/a/b/foo.jar!/"
+       device: (
+         pathname: {
+           directory: (:ABSOLUTE "a" "b")
+           name: "foo"
+           type: "jar"
+         }
+       )
+    }
+
+    // UC9 -- JAR in an relative directory with entry
+    pathname: {
+       namestring: "jar:file:a/b/foo.jar!/c/d/foo.lisp"
+       device: (
+         directory: (:RELATIVE "a" "b")
+         name: "foo"
+         type: "jar"
+       )
+       directory: (:ABSOLUTE "c" "d")
        name: "foo"
-       type: "jar"
-     }
-   )
-}
-
-// UC9 -- JAR in an relative directory with entry
-pathname: {
-   namestring: "jar:file:a/b/foo.jar!/c/d/foo.lisp"
-   device: (
-     directory: (:RELATIVE "a" "b")
-     name: "foo"
-     type: "jar"
-   )
-   directory: (:ABSOLUTE "c" "d")
-   name: "foo"
-   type: "lisp
-}
+       type: "lisp
+    }
 
 
 History
@@ -267,37 +272,37 @@
 pathname, the device pathname contained the location of the jar.
 
 In the analysis of the desire to treat jar pathnames as valid
-locations for LOAD, we determined that we needed a "double" pathname
+locations for `LOAD`, we determined that we needed a "double" pathname
 so we could refer to the components of a packed FASL in jar.  At first
 we thought we could support such a syntax by having the device
 pathname's device refer to the inner jar.  But with in this use of
-PATHNAMEs linked by the DEVICE field, we found the problem that UNC
-path support uses the DEVICE field so JARs located on UNC mounts can't
-be referenced. via '\\'.
+`PATHNAME`s linked by the `DEVICE` field, we found the problem that UNC
+path support uses the `DEVICE` field so JARs located on UNC mounts can't
+be referenced. via '\\', i.e.  
 
-           i.e.  jar:jar:file:\\server\share\a\b\foo.jar!/this\that!/foo.java
+    jar:jar:file:\\server\share\a\b\foo.jar!/this\that!/foo.java
 
 would not have a valid representation.
 
-So instead of having DEVICE point to a PATHNAME, we decided that the
-DEVICE shall be a list of PATHNAMES, so we would have:
+So instead of having `DEVICE` point to a `PATHNAME`, we decided that the
+`DEVICE` shall be a list of `PATHNAME`, so we would have:
+
+    pathname: {
+      namestring: "jar:jar:file:\\server\share\foo.jar!/foo.abcl!/"
+      device: ( 
+                pathname: {
+                  host: "server"
+                  device: "share"
+                  name: "foo"
+                  type: "jar"
+                }
+                pathname: {
+                  name: "foo"
+                  type: "abcl"
+                }
+    }
 
-pathname: {
-  namestring: "jar:jar:file:\\server\share\foo.jar!/foo.abcl!/"
-  device: ( 
-            pathname: {
-              host: "server"
-              device: "share"
-              name: "foo"
-              type: "jar"
-            }
-            pathname: {
-              name: "foo"
-              type: "abcl"
-            }
-}
-
-Although there is a fair amount of special logic inside Pathname.java
-itself in the resulting implementation, the logic in Load.java seems
-to have been considerably simplified.  
+Although there is a fair amount of special logic inside `Pathname.java`
+itself in the resulting implementation, the logic in `Load.java` seems
+to have been considerably simplified.
 

Added: trunk/abcl/doc/lisp-ffi.markdown
==============================================================================
--- (empty file)
+++ trunk/abcl/doc/lisp-ffi.markdown	Thu Mar 18 06:15:53 2010
@@ -0,0 +1,119 @@
+Lisp FFI
+========
+
+    Mark Evenson
+    Created:  15-FEB-2010
+    Modified: 18-MAR-2010
+
+FFI stands for "Foreign Function Interface", which is the way the
+contemporary Lisp world refers to methods of "calling out" from Lisp
+into "foreign" langauges and envrionments.  This document describes
+the various ways that one interacts with Lisp world of Abcl from Java,
+considering the hosted Lisp as the "Foreign Function" that needs to be
+"Interfaced".
+
+# Lisp FFI
+
+## Calling Lisp from Java
+
+Note: As the entire ABCL Lisp system resides in the org.armedbear.lisp
+package the following code snippets do not show the relevant import
+statements in the interest of brevity.
+
+Per JVM, there can only ever be a single Lisp interpreter.  This is
+started by calling the static method `Interpreter.createInstance()`.
+
+    Interpreter interpreter = Interpreter.createInstance();
+
+If this method has already been invoked in the lifetime of the current
+Java process it will return null, so if you are writing Java whose
+lifecycle is a bit out of your control (like in a Java servlet), a
+safer invocation pattern might be:
+
+    Interpreter interpreter = Interpreter.getInstance();
+    if (interpreter == null) {
+      interpreter = Interpreter.createInstance();
+    }
+
+The Lisp `EVAL` primitive may be simply passed strings for evaluation,
+as follows
+   
+    String line = "(load \"file.lisp\")";
+    LispObject result = interpreter.eval(line);
+
+Notice that all possible return values from an arbitrary Lisp
+computation are collapsed into a single return value.  Doing useful
+further computation on the `LispObject` depends on knowing what the
+result of the computation might be, usually involves some amount
+of instanceof introspection, and forms a whole topic to itself
+(c.f. [Introspecting a LispObject](#introspecting)).  
+
+Using `EVAL` involves the Lisp interpreter.  Lisp functions may be
+directly invoked by Java method calls as follows.  One simply locates
+the package containing the symbol, then obtains a reference to the
+symbol, and then invokes the `execute()` method with the desired
+parameters.
+
+    interpreter.eval("(defun foo (msg) (format nil \"You told me '~A'~%\" msg))");
+    Package pkg = Packages.findPackage("CL-USER");
+    Symbol foo = pkg.findAccessibleSymbol("FOO"); 
+    Function fooFunction = (Function)foo.getSymbolFunction();
+    JavaObject parameter = new JavaObject("Lisp is fun!");
+    LispObject result = fooFunction.execute(parameter);
+    // How to get the "naked string value"?
+    System.out.prinln("The result was " + result.writeToString()); 
+
+If one is calling an primitive function in the CL package the syntax
+becomes considerably simpler if we can locate the instance of
+definition in the ABCL source, we can invoke the symbol directly.  To
+tell if a `LispObject` contains a reference to a symbol.
+
+    boolean nullp(LispObject object) {
+      LispObject result = Primitives.NULL.execute(object);
+      if (result == NIL) {
+        return false;
+      }
+      return true;
+   }
+
+<a name="interpreting"/>
+## Introspecting a LispObject 
+
+We present various patterns for introspecting an an arbitrary
+`LispObject` which can represent the result of every Lisp evaluation
+into semantics that Java can meaniningfully deal with.
+
+### LispObject as boolean
+
+If the LispObject a generalized boolean values, one can use
+`getBooleanValue()` to convert to Java:
+
+     LispObject object = Symbol.NIL;
+     boolean javaValue = object.getBooleanValue();
+
+Although since in Lisp, any value other than NIL means "true", the
+use of Java equality it quite a bit easier and more optimal:
+
+    boolean javaValue = (object != Symbol.NIL);
+
+### LispObject is a list
+
+If LispObject is a list, it will have the type `Cons`.  One can then use
+the `copyToArray[]` to make things a bit more suitable for Java
+iteration.
+
+    LispObject result = interpreter.eval("'(1 2 4 5)");
+    if (result instanceof Cons) {
+      LispObject array[] = ((Cons)result.copyToArray());
+      ...
+    }
+    
+A more Lispy way to iterated down a list is to use the `cdr()` access
+function just as like one would traverse a list in Lisp:;
+
+    LispObject result = interpreter.eval("'(1 2 4 5)");
+    while (result != Symbol.NIL) {
+      doSomething(result.car());
+      result = result.cdr();
+    }
+

Modified: trunk/abcl/doc/slime.markdown
==============================================================================
--- trunk/abcl/doc/slime.markdown	(original)
+++ trunk/abcl/doc/slime.markdown	Thu Mar 18 06:15:53 2010
@@ -1,9 +1,9 @@
 SLIME
 =====
 
-  Author:   Mark Evenson 
-  Created:  16-MAR-2010
-  Modified: 16-MAR-2010
+    Author:   Mark Evenson 
+    Created:  16-MAR-2010
+    Modified: 18-MAR-2010
 
 SLIME is divided conceptually in two parts: the "swank" server process
 which runs in the native Lisp and the "slime" client process running
@@ -24,12 +24,13 @@
 
 One first locates the SLIME directory on the filesystem.  In the code
 that follows, the SLIME top level directory is assumed to be
-"~/work/slime", so adjust this value to your local value as you see
+`"~/work/slime"`, so adjust this value to your local value as you see
 fit.
 
 Then one configures Emacs with the proper initialization hooks by
 adding code something like the following to "~/.emacs":
 
+    :::common-lisp
     (add-to-list 'load-path "~/work/slime")
     (setq slime-lisp-implementations 
       '((abcl ("~/work/abcl/abcl"))
@@ -39,28 +40,29 @@
     (slime-setup '(slime-fancy slime-asdf slime-banner))
 
 One further need to customize the setting of
-SLIME-LISP-IMPLEMENTATIONS to the location(s) of the Lisp(s) you wish to
+`SLIME-LISP-IMPLEMENTATIONS` to the location(s) of the Lisp(s) you wish to
 invoke via SLIME.  The value is list of lists of the form
 
    (SYMBOL ("/path/to/lisp"))
 
 where SYMBOL is a mnemonic for the Lisp implementation, and the string
-"/path/to/lisp" is the absolute path of the Lisp implementation that
+`"/path/to/lisp"` is the absolute path of the Lisp implementation that
 SLIME will associate with this symbol.  In the example above, I have
 defined three implementations, the main abcl implementation, a version
 that corresponds to the latest version from SVN invoked by
-"~/work/abcl.svn/abcl", and a version of SBCL.
+`"~/work/abcl.svn/abcl"`, and a version of SBCL.
 
-To start SLIME one simply issues M-x slime from Emacs.  This will
+To start SLIME one simply issues `M-x slime` from Emacs.  This will
 start the first entry in the SLIME-LISP-IMPLEMENTATIONS list.  If you
-wish to start a subsequent Lisp, prefix the invocation via M-u
-(i.e. M-u M-x slime).  This will present an interactive chooser over
-all symbols contained in SLIME-LISP-IMPLEMENTATIONS.
+wish to start a subsequent Lisp, prefix the Emacs invocation with a
+negative argument (i.e. `C-- M-x slime`).  This will present an
+interactive chooser over all symbols contained in
+`SLIME-LISP-IMPLEMENTATIONS`.
 
 After you invoke SLIME, you'll see a buffer open up named
-*inferior-lisp* where the Lisp image is started up, the required swank
+`*inferior-lisp*` where the Lisp image is started up, the required swank
 code is complied and then loaded, finally, you'll see the "flying
-letters" resolving itself to a "CL-USER>" prompt with an inspiration
+letters" resolving itself to a `"CL-USER>"` prompt with an inspiration
 message in the minibuffer.  Your initiation to SLIME has begun...
 
 
@@ -71,16 +73,16 @@
 from a Lisp image.  One merely needs to change *SLIME-DIRECTORY* to
 point to the top directory of the server process.
 
-` 
+    :::commmon-lisp
     (defvar *slime-directory* #p"~/work/slime/") ;; Don't forget trailing slash
     (load (merge-pathnames "swank-loader.lisp" *slime-directory*) :verbose t)
     (swank-loader:init)
     (swank:start-server "/tmp/swank.port") ;; remove if you don't want
                                           ;; swank to start listening for connections.
-`
+
 When this code finishes executing, an integer representing the port on
-which the server starts will be written to '/tmp/swank.port' and also
-returned as the result of evaluating SWANK:START-SERVER.  One may
-connect to this port via issuing M-x slime-connect in Emacs.
+which the server starts will be written to `'/tmp/swank.port'` and also
+returned as the result of evaluating `SWANK:START-SERVER`.  One may
+connect to this port via issuing `M-x slime-connect` in Emacs.
 
 




More information about the armedbear-cvs mailing list