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は無視してバイナリとして書き出すことにしてみました。

( html ) let ( ( p ( chtml:parse html ( chtml:make-pt-builder ) ) ) ) flet ( name p ) ( chtml:pt-children p ) :key #'chtml:pt-name find name#'chtml:pt-name pick ( chtml:pt-attrs ( pick :pcdata ( pick :p ( pick :body p ) ) ) ) defun html-string-data (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 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& は、 ZEROP の FIXNUM 特化版です。

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の関係の初期の歴史もはっきりするかなと期待しています。

■

