#:g1: S-1 Lisp ≡ S-1 Common Lisp ≡ S-1 NIL

Posted 2015-04-20 15:33:56 GMT

S-1 Lisp のダンプファイルを発見

いつものごとく暇潰しにSaildartのファイルを眺めていたのですが、ふと、いつも眺めるLISP方面ではなく、システムのバイナリのディレクトリを眺めてみていました。

このディレクトリにLisp関係のものはないかなーと探索していた所、S1LISP.DMPというファイル名をみつけました。
これはもしや謎の処理系S-1 Lispなのでは、ということで早速調べてみることにしました。

S-1 Lisp とは

その前にS-1 Lispとはなんぞやという所ですが、S-1 Lispは、完成することがなかった割にはCommon Lisp関係者に関わりが深かったようで、やたら文献に登場してくる処理系です。
しかし、実際の所どんなものだったのかは謎。

S-1 Lispが登場する主な文献としては、S-1 Lispの自体の論文である S-1 Common Lisp Implementation や Gabrielベンチでお馴染の Performance and evaluation of Lisp systems 辺りでしょうか。

S-1 Common Lisp Implementation という名前の論文があるので、S-1 Lispが処理系名かと思いきや、どうもS-1 Lispという名前の様子。
当時Common Lispがこれから出てくるぞという所で宣言も兼ねていたのかもしれませんが、Common Lispとした理由も謎です。

また、他にS-1 NIL という処理系が文献に登場することもあるのですが、この辺りも謎の一つです。

ファイルの中身を確認してみる

さて、これらのファイルが置かれていたSAILは、PDP-10ということで、36bitのマシンです。
そのままダンプしても何かできるわけでもないので、何か文字情報を取得したいわけですが、PDP-10では、6bit〜とよくいわれるように、6bitで文字を表すと、36bitに6文字入るので都合が良かったようです(SCHEMEが6文字になったのもこれに由来)。
ということで、6bit単位の並びを8bitに枠にあてはめて、謎の8進数の羅列をバイナリにして書き出してみましたが、書き出してみたものの、文字列らしき物は発見できず。

どういうことかと思いS-1のバイトの扱いを文献で確認してみましたが、S-1というマシンは、どうも1byteは8bitではなくて、1byteが9bitという世にも珍しい構成のようです。
1byte=8bitのマシン上でどう可視化したら良いのか良く分かりませんでしたが、ビットの構成もどうなっているか分からないので、とりあえずで上位1bitは無視してバイナリとして書き出すことにしてみました。

(defun html-string-data (html)
  (let ((p (chtml:parse html (chtml:make-pt-builder))))
    (flet ((pick (name p)
             (find name (chtml:pt-children p) :key #'chtml:pt-name)))
      (chtml:pt-attrs (pick :pcdata (pick :p (pick :body p)))))))

(defun s1dmp (html outfile) (with-open-file (out outfile :direction :output :element-type '(unsigned-byte 8) :if-exists :supersede) (with-input-from-string (in (html-string-data html)) (loop :for line := (read-line in nil) :while line :do (let* ((*read-base* 8.) (a (read-from-string line nil nil :start 0 :end 3)) (b (read-from-string line nil nil :start 3 :end 6)) (c (read-from-string line nil nil :start 6 :end 9)) (d (read-from-string line nil nil :start 9 :end 12))) (mapc (lambda (b) (mapc (lambda (b) (write-byte b out)) (list #|(ldb (byte 8 8) b)|# (ldb (byte 8 0) b)))) (list a b c d)))))))

(s1dmp (*:http-request "http://www.saildart.org/S1DEB.DMP%5B1,3%5D_blob") "/tmp/s1deb.dmp")

こんな感じでファイルに書き出します。

これでできたバイナリを眺めてみると、“S-1 Lisp with debugging tools.” などという文字列があり、Lispシンボルらしきものも沢山ありました。
S1DEBというのは、どうもデバッグツール付きのS-1 Lispということみたいです。

ということで、折角なので、シンボルを抜き出してみました。

&REST *& **TRACE-FNS** **TRACE-INDEN** **WTA** 
*:ALLOCATE-LOCK *:ARRAY-DEFAULT-LEADER *:BLOCK-IO-STATUS *:CHANGE-STACK-GROUP *:CHANGE-TYPE 
*:CONDITIONAL-SET *:COPY-PROCEDURE *:CURRENT-STACK-GROUP *:FATAL-ERROR *:GC-LOCK 
*:GC-SEGMENT-TABLE *:GC-SPACE-BOTTOM *:GC-SPACE-GC-CONSTRAINT *:GC-SPACE-LISTS *:GC-SPACE-SIZE 
*:GC-SPACE-TOP *:GC-STACK-GROUP *:INTERNAL-CHANGE-STACK *:IO-CHANNEL-LOCK *:IO-CHANNEL-TABLE 
*:IO-TYIPEEK-TABLE *:MAKE-PROCEDURE-HEADER *:MAKE-STACK *:NPTR-TYPEP *:OBARRAY 
*:PROCEDURE-PROTOTYPE *:SYSCALL-ALLOCATE-SEGMENT *:SYSCALL-RELEASE-SEGMENT *:SYSCALL-SET-SEGMENT-ACCESS *:SYSTEMIC-QUANTITIES 
*DEFUN *DEFUN-MACRO *GC-LOG-SEGMENTITOS-PER-SEGMENT* *GC-OVERFLOW* *GC-SPACE-CONSTRAINT* 
*GC-SPACE-LOG-SEGMENT-SIZE* *GC-SPACE-MAX* *GC-SPACE-SUCCESS-RATE* *READ-ONLY-LOAD* *TRACE 
*UNTRACE + +& -& 0P& 
1+& 1-& :ASCII :BINARY :IN 
:OUT :READ :WRONG-TYPE-ARGUMENT <& =& 
>& ALLOCATE-STORAGE-0 ALLOCATE-STORAGE-1 ALLOCATE-STORAGE-2 ALLOCATE-STORAGE-3 
APPLY ASCII-STREAM ASSQ BASE BOOT 
BOOT-FASL BOOT-GC BOUNDP BUILD CAAAAR 
CAAADR CAAAR CAADAR CAADDR CAADR 
CAAR CADAAR CADADR CADAR CADDAR 
CADDDR CADDR CADR CAR CDAAAR 
CDAADR CDAAR CDADAR CDADDR CDADR 
CDAR CDDAAR CDDADR CDDAR CDDDAR 
CDDDDR CDDDR CDDR CDR CEIL& 
CERROR CHANNELS CHAR CHARACTER CLOSE 
COLLECTOR COMPLAIN COND CONS CONS-IN-AREA 
DEB:DISPLAY-SEGMENTITOS DEB:DISPLAY-SEGMENTS DEB:DISPLAY-SEGMENTS-AUX DEB:INTERNAL-TRACE DEB:PP-AUX 
DEB:PP-PAIR DEB:PP-STREAM DEB:PP-SYMBOL DEB:PP-VECTOR DEB:PRINT-POINTER 
DEB:PRINT-POS-FIXNUM DEB:STORAGE DEB:STORAGE-AUX DEB:TRACE-PRINT DEBUG1SAS 
DEBUG2SAS DEBUGGING DEFUN DELQ DIGITP 
DSKDEBUG1SAS DSKDEBUG2SAS DSKGARBG1SAS DSKGARBG2SAS DSKGARBG3SAS 
DSKGARBG4SAS DSKGARBG5SAS DSKGARBG6SAS DSKGARBG7SAS ENTER 
ENVIRONMENT EQ EQUAL EVAL EVAL:MAKE-ENV 
EVAL:SYMEVAL EVCOND EVLIST EVSETQ EXIT 
FAS-OBJECTS FASL FASL-FILE FASL-INTERN FASL-MAKE-ARRAY 
FASL-MAKE-CODE FASL-MAKE-EXTENDED-NUMBER FASL-MAKE-NUMBER FASL-MAKE-PROCEDURE FASL-MAKE-SPECIAL-VECTOR 
FASL-MAKE-STRING FASL-MAKE-SYMBOL FASL-MAKE-VECTOR FASL-MARKABLE-VECTOR FASL-NUMBER 
FASL-QW-TYPE-VECTOR FASL-REPLACER FASL-SPECIAL-VECTOR FASL-STACK-POPPER FASLOAD 
FBOUNDP FERROR FIX-ALL-POINTERS FIXNUM FLOOR& 
FORMAT FOUR-BYTES-TO-STRING FSYMEVAL FUNCTION FUNCTIONP 
GARBAGE GARBG1SAS GARBG2SAS GARBG3SAS GARBG4SAS 
GARBG5SAS GARBG6SAS GARBG7SAS GC-ALLOCATE-SEGMENT GC-INTERNAL 
GC-OVERFLOW-HANDLER GC:COLLECT-GARBAGE GC:DEALLOCATE-SEGMENT GC:DEALLOCATE-UNMARKED-STACKS GC:FIND-ORIGINAL-CODE 
GC:FIRST-UNPURE-SEGMENT GC:FORWARD-OBJECT GC:FORWARD-PC GC:FORWARD-VECTOR GC:FORWARD-WORDS 
GC:FORWARD-WORDS# GC:INTERNAL-ALLOCATE-IN-SPACE GC:MARK-REGISTERS GC:MARK-STACK-FRAME GC:MARK-STACKS-UNCOLLECTED 
GC:NEXT-WORD-IN-SPACE GC:PARTIAL-SPACE-CHANGE-ACCESS GC:R GC:RELEASE-SPACE GC:RENAME-SPACE 
GC:SET-PURIFICATION-BIT GC:SPACE-CHANGE-ACCESS GC:SPECIAL-VECTOR-BYTESIZE GC:SWEEP-PROCEDURE-HEADER GC:SWEEP-SPACE 
GC:SWEEP-STACK GC:TRY-FORWARD-PC GET GET-MORE-STORAGE GOBBLE 
GUESS-SEGMENT-SIZE HAULONG& INCH INITIALIZATION INPUT-STREAM-P 
INSERT-IN-SYM-TAB INTERN INTERNAL:CALL-FUN IO:ABORT-STREAM IO:CLOSE-STREAM 
IO:DECREMENT-TRANSFER-COUNTER IO:FORCE-OUTPUT IO:GET-FREE-CHANNEL IO:INCREMENT-TRANSFER-COUNTER IO:INPUT-BUFFER 
IO:LAP-BLOCK-IN IO:LAP-BLOCK-OUT IO:LAP-CLOSE-FILE IO:LAP-DELETE IO:LAP-GET-ASCII 
IO:LAP-GET-FOUR-QW IO:LAP-GET-NEXT-PTR IO:LAP-OPEN-FILE IO:LAP-PUT-ASCII IO:LAP-TRANSFER-WORDS 
IO:LAP-TYI IO:LAP-TYO IO:OPEN-FILE IO:OPEN-STREAM IO:OUTPUT-FULL-BUFFER 
IO:PUT-IN-BUFFER IO:READ-ASCII-CHARACTER IO:RELEASE-CHANNEL LAMBDA LENGTH 
LIST LIST-TO-STRING LOAD MACROP MAKE-STRING 
MAKE-UNMARKABLE-FIXNUM-VECTOR MAKE-VECTOR MAX& MEMBER MEMQ 
MIN& MOD& MSGFILES NCONC NCONS 
NILINI NON-NEG-FIXNUM NOT NREVERSE NTH 
NTHCDR NULL OPEN OPSYS OUCH 
OUTPUT-STREAM-P PRIN1 PRINC PRINLENGTH PRINLEVEL 
PRINT PRINT:PRINT-ATOM PRINT:PRINT-FIXNUM PRINT:PRINT-FLONUM PRINT:PRINT-STRING 
PROGN PUTPROP QELEASE-SPACE QUOTE READ 
READ-BLOCK READ-FOUR-QW READ-NEXT-PTR READ:READ-ATOM READ:READ-DOTTED-PAIR 
READ:READ-NUMBER READ:READ-STRING READ:SKIP-WHITESPACE RELEASE-SPACE REMAINDER& 
REMPROP RESTARTNIL REVERSE ROUND& RPLACHAR 
S-1 S-1-FASLOAD SAVE-DEBUG SETPLIST SETQ 
SIMULATOR STANDARD-OUTPUT STREAM STREAMP STRING 
STRING-EQUAL STRING-SXHASH STRING-UPCASE SXHASH SYMBOL-PLIST 
SYMTAB-REF TERPRI TOPLEVEL TRACE TRUNC& 
TYI TYIPEEK TYO UNTRACE USED 
VALID-FASL-HEADERP VALID-FASLP VREF VSET

S-1 Lisp は NIL だった

NILを知っている人には、すぐ分かるのですが、抜き出したシンボルには、NIL特有の物が沢山あります。
例えば、*というパッケージ名や、0P&という関数です。 *パッケージは、なんのパッケージかは謎なのですが、どうもグローバルなパッケージのようで、非常に特徴的な名前の0P&は、ZEROPFIXNUM特化版です。

S-1 Lispの歴史によれば、NILの開発チームと共同開発したようなことも書いてありますが、このファイルを眺める限りは、どうもLispのベースはNILだったのではないかと思われます。

ここで、Common LispとNILの関係を整理すると、NILの開発当初にCommon Lispはありませんでしたが、Common Lispがレキシカルスコープを採用したのはNIL由来だったり、NIL自体がCommon Lispの仕様の成長と共にCommon Lispの一実装になってしまいました。
中々混沌とした流れがありますが、S-1 Lispは、NILで、NILはCommon Lispということになれば、S-1 Lisp ≡ S-1 Common Lisp ≡ S-1 NIL という謎もとけた感じです。

まとめ

NILのマニュアルは数年前に公開されたのですが、処理系のソースコードは公になっていません。
いつか公開されれば、S-1、NIL、Common Lispの関係の初期の歴史もはっきりするかなと期待しています。


HTML generated by 3bmd in SBCL 1.2.10

comments powered by Disqus