Inside newLISP (6)

以前国勢調査の本を読んだけど、今年が当たり年だった。インターネットで簡単にってんで 依頼用紙が来てたけど、あれ何よ?

住所とIDが既に紐付けられていた。だから、回等の最後にパスワードの新規設定を求め られるんだな。使える記号の種類が限定されてるってどうよ? サイトを作る方の 都合がふんだんに混じってる可能性があるな。まさかレールならあそこまで限定 させることはないだろう。

そうするとJAAVAで作られているのかな?作った所はFNあたりか。そして運用はんttの 子会社かな。

パソコンでもスマホでもOKって、総務のおばちゃんやるじゃん。って、現在では当たり前。 無線局の電子申請がパソコンのしかもWindows限定って、どこの世界の話だ。早く何とか しろよ。

早く何とかしろよは、今回の電子申請でみんな、どんな環境から回答してるか、知りたいな。 ブラウザーの種類とかOSぐらいは取れるだろうから、公表せい。それとプロバイダーだな。 もう地方の弱小プロバイダーは淘汰されてて、携帯屋がやってるプロバイダーしか出て こないかな。

全世帯の何%が、電子回答したんだろう?最近は年寄りでもスマホを使いこなしているから、 結構な率になるかな。日本の動態よりも、こういう下衆な話の方が面白いぞ。

早く公開してね。

minix3

前回minixなんてのを思い出しちゃったので、懐かしくなって入れてみた。 総本山はMINIX 3 Download こちらです。

一番新しいのが良いだろうってんで、3.3.0を落としてきて、vmwareに入れてみた。 基本的には、ただReturnを叩いていくだけ。あっけなくインストール完了。 pkgin in openssh して、sshをインストール。一度rebootすると、よそから入れるように なった。

このpkginは、NetBSD由来みたいだな。連携出来るようになってる。そんな事より、/usr/srcが 無いんですけど。pkgにあるかと思って探してみたけど見当たらず。なんか間違ってませんか?

ちょっと古い、3.2.1ではどうかと思ってやり直し。今度は入っていた。まずは自分のアカウントを 作っておくんだったな。

# useradd -m -d /home/sakae sakae

つぎは、何かshellでも入れておこう。

# pkgin search shell
bash-2.05.2.7nb11    The GNU Bourne Again Shell (version 2)
bash-4.2nb1          The GNU Bourne Again Shell
dialog-1.1.20110707  Display dialog boxes from shell scripts
getopt-1.1.4nb1      Program to help shell scripts parse command-line parameters
openssh-5.8.2nb5 =   Open Source Secure shell client and server (remote login program)
pdksh-5.2.14nb5      Free clone of the AT&T Korn shell

=: package is installed and up-to-date
<: package is installed but newer version is available
>: installed package has a greater version than available package
# pkgin install pdksh
calculating dependencies... done.

nothing to upgrade.
1 packages to be installed: pdksh-5.2.14nb5 (318K to download, 717K to install)

proceed ? [y/N] y
downloading packages...
pdksh-5.2.14nb5.tgz                 100%  318KB 106.0KB/s  31.5KB/s   00:03
error log can be found in /usr/var/db/pkgin/err.log
installing packages...
installing pdksh-5.2.14nb5...
pdksh-5.2.14nb5: adding /usr/pkg/bin/pdksh to /etc/shells
processing local summary...
updating database: 100%
marking pdksh-5.2.14nb5 as non auto-removable

ソース系

$ cd /usr/src
$ ls
LICENSE      commands     drivers      kernel       sbin         tools
Makefile     common       etc          lib          servers      usr.bin
benchmarks   dist         external     libexec      share        usr.sbin
bin          distrib      gnu          man          sys
build.sh     docs         include      releasetools test

パッケージが/usr/pkgの下に入って、srcも有って、Linuxとは一味違う、miniNetBSDって 趣きでしょうか? OS入れるなら、こうでなくちゃ!!

内部の事で参考になりそうな事は、 MINIX 3 Developers Guide を見れば良いのかな。

いたずらで、newlispがコンパイル出来るかやってみたら、デフォのccがうんと古いclangで 歯が立たず。pkgにgcc44が有ったので、取り寄せて実験

$ gmake -f makefile_netbsd
gcc -m32 -Wall -Wno-uninitialized -Wno-strict-aliasing -O2 -c -g -DREADLINE -D_BSD nl-filesys.c
nl-filesys.c: In function 'processSpawnList':
nl-filesys.c:1468: warning: implicit declaration of function 'munmap'
nl-filesys.c: In function 'p_spawn':
nl-filesys.c:1496: warning: implicit declaration of function 'mmap'
nl-filesys.c:1497: error: 'MAP_SHARED' undeclared (first use in this function)
nl-filesys.c:1497: error: (Each undeclared identifier is reported only once
nl-filesys.c:1497: error: for each function it appears in.)
nl-filesys.c: In function 'p_share':
nl-filesys.c:2151: error: 'MAP_SHARED' undeclared (first use in this function)
gmake: *** [nl-filesys.o] Error 1

っつう事で、MINIXは独自の道を歩んでいるみたい。ソケットの所なんかはボロボロでしたよ。

リベンジ

前回(またかよ)、gambitCに素数検出スクリプトを移植した時、(inc! var) と (inc! var d) を、同時にサポート出来ず、心にわだかまりが残っていた。ちゃんとOn Lispを読めば解決 出来るんだろうけど、ちとLisp-2系と言うか、CommonLispには心が動かなくなっているんで諦めた。

そこで、Lisp-1系のSchemeだけで何とかならんかと、gambitのinfoを見てたんだ。 そしたら使えそうなのが有ったね。condみたいなやつが。

;; gsi -:s xxx.scm
;; gsc -:s -o run -exe xx.scm

;(load "/usr/local/lib/gambit-c/syntax-case") ; comment out for gsc

(define-syntax inc!
              (syntax-rules ()
                ((inc! var)   (set! var (+ var 1)))
                ((inv! var d) (set! var (+ var d)))))

(define aa 0)
(inc! aa 3)
(print aa "\n")
(inc! aa)
(print aa "\n")

パターンマッチングで、ソースを書き換えてから実行ってやつ。こちらの方が分かり易いな。 但し、これを使うには、コマンドラインにおまじないの -:s ってのが必要。syntax-caseの モジュールを読み込ませる必要が有るので、ちと面倒ではあるけど、微妙な所なんでしょうが ないか。

普通は、普通なマクロを使うのが常識かな、 Schemeのマクロをかじってみる でも、Lisp気質のマクロだしね。どうしてもって時のために、引き出しにしまっておくものですな。

悔しいのはもう一つあった。そう、大きなベクターを取ろうとするヒープがオーバーフロー しちゃう事。今回は、素数/非素数が分かればいいんで、1ビットで事足りる。だったら、小さい数を 記憶するベクターでいいじゃん。s8vectorに変更。これだと8ビットの数値しか扱えない。

対して、汎用のvectorは、何でも入れられるのね。数値でも真偽値でも文字列でも。最初 newLISPでびっくりしたけど、まあ、こんなのも有りって事で、配列に入れられるのは、一つの タイプだけって、固定観念が払拭出来たよ。良い子はマネをしない方が望ましいけど。

大きな数値(define N 10000000) で実験

[ob: t]$ time gsi 2gsi.scm >z
    0m45.72s real     0m38.05s user     0m7.19s system
[ob: t]$ gsc -o run -exe 2gsi.scm
[ob: t]$ time ./run >z
    0m2.25s real     0m0.89s user     0m1.31s system

OpenBSDはもっさりしてるんで、比べるなら同じ土俵のウブがいいな。ウブ用のgambitは版が 古くてバイナリーを作成出来なかったので、Gambit v4.7.8の最新版を入れたよ。

sakae@uB:~/z$ time gsi 2gsi.scm >/dev/null
real    0m25.352s
user    0m25.000s
sys     0m0.300s
sakae@uB:~/z$ gsc -o run -exe 2gsi.scm
sakae@uB:~/z$ time ./run > /dev/null
real    0m1.551s
user    0m1.356s
sys     0m0.192s
sakae@uB:~/z$ time ./sieve > /dev/null
real    0m2.401s
user    0m1.940s
sys     0m0.380s

crystalが吐くバイナリーより速かったな。クリスタルさん、頑張ってくださいませ。

newlisp-js

以前から気になっていたnewlisp-js を落としてきた。zipファイルだ。これ一つでnewlispが動くって話。解凍して、index.htmlを 起動したら、デモ画面が出てきた。

テーマで配色を変えられたり、レイアウトで配置を変えられたり、Windowsユーザーが喜びそう (最近ではスマホユーザーか)時代に追いついているかな。

しかけは、infoを見ろって事なんで、うだうだしてると、 JavaScript program統一協会によるemscripten らしい。そこにnewLISP陣営も参加してるのだな。 ざっくり言っちゃうと、C語で書かれたアプリをjavascrit語に変換しちゃいましょ。そうすれば、 ブラウザーだけで動くアプリが出来るじゃんって事。その要になってるのがLLVM。 つらつら見てくとその為の開発環境(SDK)がDL出来るみたいだ。世の中便利だねぇ。

C語のハロワを、

./emcc hello_world.c
node a.out.js

出来上がったのをJSの代表、nodeで実行。-o hello.htmlで、埋め込みも出来るんか。 これなら、何処でも動くな。たのしそうだから後でチャレンジしてみるか。 で、この原稿を書きながら、コンパイルしてみたんだけど、DISKが足りなくなってfailした。 3.3G使っても足りないって、どれほどよ。何処かにバイナリーが落ちていないかな。

簡単アプリが有るとな

The app.html demo file shows how to do this. Everything necessary to write 
your own application is contained in a 3k part of this file. Only app.html 
and the newlisp-js-lib.js library are required to run this newLISP application 
client-side in a web browser.

newlispEvalStr(string)と言うのがnewlisp-js-lib.jsに含まれていて、そいつを使って ブラウザーから、JS版のnewLISPにコードを送り込むようだ。

こういうのは、手を動かすに限る。app.htmlをhoge.htmlにコピーし、それとnewlisp-js-lib.js を適当な所に取り出した。で、アクセスしてみると、ローディング中ってなって、先に 進まない。おかしいなってんで、newlisp-js-lib.html.memも持ってきたら動き出した。 嘘の説明ですか。やってみないと分からんな。後は、実行手続きをフィボからfactに 変更したりしてみた。

この例だと、テキストエリアに貼り付けてあるコードを取り出して、評価してから結果を web画面に貼り付けているんだな。ちょっと修正が半端だけど、

<head>
  :
      function calcFact() {
            var num = document.getElementById('fiboinput').value
            var source = '(fact ' + num + ')'
            var result = newlispEvalStr(source);
            var fieldName = document.getElementById('content');
            fieldName.innerHTML = result;
            }
  :
<body>
  :
    <script type='text/javascript'>
<!--
      var Module = {
        preRun: [],
        postRun: [(function() {
          // import newlispEvalStr from newlisp-js-lib.js library
          newlispEvalStr = Module.cwrap('newlispEvalStr', 'string', ['string']);
          // preload newLISP functions from code textarea id='code'
          newlispEvalStr(document.getElementById('code').value);
        })],
           :
      Module.setStatus('Downloading...');
-->
    </script>

ボタンを押した時に、この関数が実行される。数値を読み取って、S式を組み立てて実行。 結果をWebに表示だな。

このjsになったnewLISPってどう作るかと思ったら、makefile_emscripten_lib_utf8に書いてあった。

OBJS = newlisp.o nl-symbol.o nl-math.o nl-list.o nl-liststr.o nl-string.o nl-filesys.o \
        nl-sock.o nl-web.o nl-xml-json.o nl-matrix.o nl-debug.o pcre.o nl-utf8.o unix-lib.o

CFLAGS = -m32 -Wall -c -DMAC_OSX -DLIBRARY -DEMSCRIPTEN  -DSUPPORT_UTF8

CC = emcc

特徴的なのがunix-lib.cを使ってるのと、コンパイラーの指定がemccって事。 unix-lib.cの中にnewlispEvalStrが定義されてる。

それはそうと、newlisp-js-lib.jsが1.1Mも有る。中身はほとんど数値の羅列だけど、これって JS用のアセンブラ? 多分、newlispが使っていたlibcとかlibmを同梱してるのかな。それとも そんなのは、javascriptのエンジンに入ってるんで、それへの橋渡しをしてるのかな? 余り深く考えるな。

newlisp on ARM

newlisp-jsのバージョンが新しくなっていた。で、ふと本拠を見に行ったら本体の方も開発版という 位置付けながら、新しいのが出てた。これはもう入れてみる鹿。この所失敗続きだからね。 どうせやるなら、新しい器が良いだろう。昔作っておいた、ARMでdebian環境。 そして、お約束のエラー発生。

sakae@arm:~/newlisp-10.6.3$ make
./configure

removing old objects and setting correct permissions ...
discovering platform and default memory model ...

detected memory model ILP32
detected Operating System LINUX
creating makefile_build ...

to make for ILP32 on LINUX type:
    make
to make for any other system do:
    make -f makefile_xxx
where makefile_xxx is one of the preconfigured makefiles

make -f makefile_build
make[1]: Entering directory '/home/sakae/newlisp-10.6.3'
gcc -fPIC -m32 -Wall -Wno-strict-aliasing -Wno-long-long -c -O2 -g -DREADLINE -DSUPPORT_UTF8 -DLINUX -DFFI -I/usr/local/lib/libffi-3.0.13/include newlisp.c
gcc: error: unrecognized command line option ‘-m32’
makefile_build:21: recipe for target 'newlisp.o' failed
make[1]: *** [newlisp.o] Error 1
make[1]: Leaving directory '/home/sakae/newlisp-10.6.3'
Makefile:31: recipe for target 'default' failed
make: *** [default] Error 2

gccが言う事にゃ、糞石32なんてやめれ!! -m32を削除。ついでに、-O2の-O0に変更。

sakae@arm:~/newlisp-10.6.3$ ./newlisp
newLISP v.10.6.3 32-bit on Linux IPv4/6 UTF-8 libffi, options: newlisp -h

> (sys-info)
(437 268435456 409 1 0 2048 0 16354 10603 1153)

どうやら、ちゃんと動いているな。そんじゃ、アセンブルコードにご対面してみるか。

(gdb) disassemble evaluateExpression
Dump of assembler code for function evaluateExpression:
   0x00018258 <+0>:     push    {r4, r11, lr}
   0x0001825c <+4>:     add     r11, sp, #8
   0x00018260 <+8>:     sub     sp, sp, #36     ; 0x24
   0x00018264 <+12>:    str     r0, [r11, #-40] ; 0x28
   0x00018268 <+16>:    ldr     r4, [pc, #1944] ; 0x18a08 <evaluateExpression+1968>
   0x0001826c <+20>:    add     r4, pc, r4
=> 0x00018270 <+24>:    ldr     r3, [pc, #1940] ; 0x18a0c <evaluateExpression+1972>
   0x00018274 <+28>:    ldr     r3, [r4, r3]
   0x00018278 <+32>:    mov     r2, #0
   0x0001827c <+36>:    str     r2, [r3]
   0x00018280 <+40>:    ldr     r3, [pc, #1928] ; 0x18a10 <evaluateExpression+1976>
   0x00018284 <+44>:    ldr     r3, [r4, r3]
    :

うん、まぎれもなくarmなコードだな。

JavaScript

JavaScriptを中心としたWebアプリ開発の栄枯盛衰まとめ ホットな分野だけに、いろいろとあるんですなあ。 JavascriptVMに多数の言語: CoffeeScript 1.0, StratifiedJS, EmscriptenによるC/C++, Python 上で取り上げたと言うか、初めて知ったEmscriptenにも言及されてる。

ウブに有るかと思ったら、有った。

sakae@uB:~$ sudo apt-get install emscripten
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following extra packages will be installed:
  libandroid-json-org-java libargs4j-java libatinject-jsr330-api-java
  libclosure-compiler-java libguava-java libjsr305-java node-amdefine
  node-async node-optimist node-source-map node-uglify node-wordwrap
Suggested packages:
  libandroid-json-org-java-doc libatinject-jsr330-api-java-doc
  libclosure-compiler-java-doc libjsr305-java-doc node-uglify-to-browserify
The following NEW packages will be installed:
  emscripten libandroid-json-org-java libargs4j-java
  libatinject-jsr330-api-java libclosure-compiler-java libguava-java
  libjsr305-java node-amdefine node-async node-optimist node-source-map
  node-uglify node-wordwrap
0 upgraded, 13 newly installed, 0 to remove and 0 not upgraded.
Need to get 25.5 MB of archives.
After this operation, 104 MB of additional disk space will be used.
sakae@uB:~$ emcc -v

==============================================================================
Welcome to Emscripten!

This is the first time any of the Emscripten tools has been run.

A settings file has been copied to ~/.emscripten, at absolute path: /home/sakae/.emscripten

It contains our best guesses for the important paths, which are:

  LLVM_ROOT       = /usr/bin
  NODE_JS         = /usr/bin/nodejs
  EMSCRIPTEN_ROOT = /usr/share/emscripten

Please edit the file if any of those are incorrect.

This command will now exit. When you are done editing those paths, re-run it.
==============================================================================

無謀にもコンパイルにトライ

sakae@uB:~/newlisp-10.6.3$ make -f makefile_emscripten_lib_utf8
emcc -O2 --closure 1 -m32 -Wall -c -DMAC_OSX -DLIBRARY -DEMSCRIPTEN  -DSUPPORT_UTF8 newlisp.c
  :
emcc newlisp.o nl-symbol.o nl-math.o nl-list.o nl-liststr.o nl-string.o nl-filesys.o nl-sock.o nl-web.o nl-xml-json.o nl-matrix.o nl-debug.o pcre.o nl-utf8.o unix-lib.o -m32 -O2 -o newlisp-js-lib.html -s EXPORTED_FUNCTIONS="['_newlispEvalStr']" \
-s MAX_SETJMPS=100 -s TOTAL_MEMORY=33554432 --closure 1 \
--embed-file newlisp-js/readme.txt --embed-file newlisp-js/qa-bench --embed-file newlisp-js/canvas.lsp
Traceback (most recent call last):
  File "/usr/bin/emcc", line 1547, in <module>
    extra_files_to_link = system_libs.calculate([f for _, f in sorted(temp_files)], in_temp, stdout, stderr, forced=forced_stdlibs)
  File "/usr/share/emscripten/tools/system_libs.py", line 545, in calculate
    libfile = shared.Cache.get(name, create)
  File "/usr/share/emscripten/tools/cache.py", line 36, in get
    shutil.copyfile(creator(), cachename)
  File "/usr/share/emscripten/tools/system_libs.py", line 379, in create_libcextra
    return build_libc('libcextra.bc', libcextra_files, ['-O2'])
  File "/usr/share/emscripten/tools/system_libs.py", line 60, in build_libc
    run_commands(commands)
  File "/usr/share/emscripten/tools/system_libs.py", line 45, in run_commands
    call_process(command)
  File "/usr/share/emscripten/tools/system_libs.py", line 14, in call_process
    raise CalledProcessError(proc.returncode, cmd)
subprocess.CalledProcessError: Command '['/usr/bin/python', '/usr/share/emscripten/emcc', '/usr/share/emscripten/system/lib/libc/musl/src/stdio/vfscanf.c', '-o', '/tmp/tmpeLNzGW/vfscanf.c.o', '-I', '/usr/share/emscripten/system/lib/libc/musl/src/internal', '-I', '/usr/share/emscripten/system/lib/libc/musl/arch/js', '-O2']' returned non-zero exit status 1
makefile_emscripten_lib_utf8:29: recipe for target 'default' failed
make: *** [default] Error 1

そしてエラー、-DMAC_OSX と -DLINUXは違うものだろーってんで修正してみたけど、同様なエラー。 無理せず、ハロワからだな。