作成中の pico scheme を Graalで動かしてみた


## 概要

継続の使える schemeを作ってみたくなった。
(Common Lispのサブセット（関数１００〜２００程度）は今まで５回ほど、作った事があるが、schemeを作るのは、はじめてである）

そこそこ、うごくようになった。
R7RSのpico仕様というのがあり、それが動くか動かないか程度の出来栄え。

実装言語はJavaで作っている。

## ふいに、Graalで動かしてみたくなった

普段はOpenJDKなのだが、Graalでがんばれば、Nativeコンパイルできるのだろうか？

自宅のMacにGraal入れてみたよ。

SDKMANを入れていなかったので、入れてから、
```
sdk install java 21.0.4-graal
```
ORACLEのGraal Ver21を入れてみたよ。

## うーん、antでコンパイル出来なくなった

デバッグ用のログを吐くのに、slf4jを使っているのだが、そこでコンパイルが通らない。
もう１つはSWINGのGUIで、コンパイルエラー。

#### 色々調べたら、Graalでコンパイルする時は、ソースが必要みたいだ。

とり急ぎ動かしてみたかったので、slf4j-apiのソースだけ落としてくる & SWING-GUIのソースは削除してみた。

#### antでコンパイルできた。
ワーニングがいっぱい出たけどね。


## 証拠画面キャプチャー

Graalですが、nativeコンパイルは、まだ行っていません。

![Graal-Syoko-Gazo.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1339875/d6d959d4-1c7e-86c8-ca10-26520c5f116c.png)

```
java -jar lisp-0.1.jar
```

で、起動すると、slf4jの実装がないよと、メッセージが３行出ている。
（当然ですが このjavaはGraal Ver21です)
メッセージが３行出るのは、まぁ仕方ないな。

ちなみに、メモリはどれくらい食っているのか気になって、Macで調べてみたよ。

![Graal-Memory.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1339875/c34f1b27-58fe-8192-5d32-8e6fd35c3e00.png)


33.5MB か。思ったより随分と少ない。
いい感じである。

ちなみに、このLispインタープリタは、JavaのリフレクションAPIを使って、Javaで実装された足し算とかを呼び出している。
特にソース修正なしで、GraalVM（インタープリター）で動きました。


## 紫藤さんのScheme入門 16.継続はオススメです

このページ本当に、わかりやすい。神。
継続(call/cc)を一度も使った事ない、私でも、なんとか理解できた。（少しだけ）

https://www.shido.info/lisp/scheme_cc.html


ここに載っているサンプルを、入力してみる。

![Graal-call-cc.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1339875/35a59a4e-18db-ed68-a931-0713a94c0cde.png)

紫藤さんの記事に書かれている答えと一致しました。
やったね。

（継続は難しいです。この答えはいくら？と聞かれて自分で考えたら、たぶん５０％以上の確率で、間違える自信あり！）

## R7RS pico

schemeのpico仕様というのがあって、以下にrustで書かれたサンプル実装がありました。

https://github.com/jrincayc/rust_pr7rs/tree/main

私が作っているJavaインタープリタは、まだこのpico仕様と、完全に同じ結果にはなっていません。

ちなみに Gauche(ゴーシュ)でも、やってみたんだけど、完全に同じ結果にはなりませんでした。

## Print処理で、巡回リストの印刷にはじめて対応出来た。

今まで、何回かLispの実装はしているのですが、巡回リストの印刷にはじめて対応できました。
ちょっと、嬉しい。

![Graal-Jyunkai-list.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1339875/3bb1f7de-8647-c186-74d5-ccbd60227b09.png)


## R7RSの文字の仕様と、つちよし問題

R7RS-smallの日本語訳を読んでいた。
6.6章　文字に、以下のような事が書いてあった。

> (char->integer char) 手続き
> (integer->char n) 手続き
> Unicode 文字が与えられたとき，char->integer は
> その文字の Unicode スカラ値に等しい 0 から #xD7FF の間，
> または#xE000 から #x10FFFF の間の正確整数を返す。
> 非 Unicode文字が与えられたときには，#x10FFFF より
> 大きい正確整数を返す。
> これは，実装が内部的に Unicode 表現を使用する
> かどうかとは真に独立している。
> char->integer が適用されたときにその文字が返す値の正確
> 整数が与えられたとき，integer->char はその文字を返す。

#### これって凄くないですか？

私、会社では、JavaでWebシステムの開発をしています。
１年ぐらい前だったか、社内用のシステムで、文章入力欄に
「𠮷田さん」と書いたらエラーになるという報告を受けました。
吉の上の部分が、土になっているのを、「つちよし」というらしいのですが、
この文字は、Javaではサロゲート・ペア文字となってしまいます。
サロゲート・ペアでバグってしまいました。

でも上のR7RS-smallの文字仕様を見て、素直に実装すると、サロゲートペア文字を根絶できそうな気がします。

自作のpico schemeでも、「𠮷」が、「１文字として扱える」ようにすべく絶賛バグ出し中です。


StringBuilder に appendCodePointというメソッドがあるんですね。

```
appendCodePoint(int codePoint)
codePoint引数の文字列表現をこのシーケンスに追加します。
```

1文字をcharではなく、intに入れてから、処理をしています。
こんなメソッドがあるとは知らなかった。
大変勉強になりました。



## まとめ

個人的な見解ですが、自分がlispインタープリタを作るのだったら、一番慣れているJavaか、今勢いのあるrustのどちらかと思っています。

昔だったら、JavaVMの上で動く、SchemeのVMという事で、動作が遅くなりそうでした。
しかし近い将来に、GraalVMのNativeコンパイラによって、スピードも改善されるでしょう。GraalVMに大変期待しています。


それから、  R7RS picoの ソースを使って、rustの学習中です。
（６０歳過ぎると、もの覚えが悪くて困りますが）


そのうち Graal の nativeコンパイルも、やってみたいです。