本当は Chicken側にもクロスコンパイルの機能があるようですが、 今回は静的リンクと手製ビルドスクリプトでゴリ押ししました
https://renem2185.github.io/bf/vectorbfi.html
- Ubuntu 22.04.4 LTS (WSL2)
- CHICKEN Scheme 5.1.0
- Emscripten 3.1.5
- Clang 13.0.1-2ubuntu2.2
ほぼ参照の通り
$ mkdir ~/chicken && cd ~/chicken
$ wget https://code.call-cc.org/releases/5.1.0/chicken-5.1.0.tar.gz
$ tar xvf chicken-5.1.0.tar.gz
$ cd chicken-5.1.0
$ make PLATFORM=linux PREFIX=$HOME/chicken/chicken-5.1.0-llvm C_COMPILER=clang
$ make PLATFORM=linux PREFIX=$HOME/chicken/chicken-5.1.0-llvm C_COMPILER=clang install
- Schemeで書いたコードをトランスパイルする
$ $HOME/chicken/chicken-5.1.0-llvm/bin/csc -t -static vectorbfi.scm
- Chicken Scheme自体のC言語のソースコードを持ってくる
## 全部使う訳ではない
$ cp $HOME/chicken/chicken-5.1.0/*.c .
- Schemeのモジュールを持ってくる
## chicken-installが済んでいればこの場所にソースコードがあるはず
$ cp -r $HOME/.cache/chicken-install/srfi-*/ .
- 以下のシェルスクリプトを実行する (Makefileのほうがいいかも)
#!/bin/bash
## build.sh
CSC=$HOME/chicken/chicken-5.1.0-llvm/bin/csc
WD=/home/renem/work/my-bf-wasm/ ## working dir.
EMCC=/usr/bin/emcc
CHICKEN=$HOME/chicken/chicken-5.1.0-llvm
list=(
"srfi-13"
"srfi-14"
"srfi-18"
"srfi-38"
"srfi-48"
"srfi-193"
)
for dir in "${list[@]}" ; do
cd $dir
$CSC -regenerate-import-libraries -setup-mode -static \
-I ${WD}/${dir} \
-emit-link-file ${dir}.link \
-host -D compiling-extension \
-c -unit $dir \
-D compiling-static-extension \
-C -I/${WD}/${dir} \
-O3 -d0 ${dir}.scm -t
mv ${dir}.c ../
cd ..
done
$CSC -t -static vectorbfi.scm
$EMCC -Os -fomit-frame-pointer vectorbfi.c \
-I${CHICKEN}/include/chicken/ \
-DHAVE_CHICKEN_CONFIG_H -DSEARCH_EXE_PATH \
build-version.c eval.c library.c runtime.c chicken-syntax.c expand.c internal.c \
modules.c extras.c data-structures.c eval-modules.c scheduler.c pathname.c port.c irregex.c \
srfi-4.c srfi-13.c srfi-14.c srfi-18.c srfi-38.c srfi-48.c srfi-193.c \
-lm -sMODULARIZE=1 -sEXPORT_ALL=1 \
-o vectorbfi.js
ビルドさえ通ってしまえばあとは概ね https://gist.github.com/renem2185/64742adde3caad5d3368ba4412b201be といっしょ
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<title>My Brainf*** interpreter</title>
</head>
<body>
<h2>My Brainf*** interpreter written in Scheme</h2>
<p>
<a href='https://github.com/renem2185/my-bf'>
https://github.com/renem2185/my-bf
</a>
を WebAssembly向けにコンパイルしてみました
</p>
<p>
<textarea id='input' rows='10' cols='60'
placeholder='Brainf*** code here!'>
</textarea>
<button id='launch'> 実行!</button>
</p>
<p> ↓ 謎に Scheme製のコードがBFを読んで動いてくれます </p>
<p> 結果:
<code id='output'></code>
</p>
<p> デバッグ表示: </p>
<p><code id='stderr'></code></p>
<hr />
<p>
","を使うと入力ダイアログが表示されます、
これ以上入力するものが無いときは「キャンセル」を押してください
</p>
<p> 既知の不具合: Quineを実行しようとするとOOMエラーで止まる? </p>
<script src="vectorbfi.js"></script>
<script>
document.getElementById('launch').addEventListener('click', () => {
document.getElementById('output').textContent = "";
document.getElementById('stderr').textContent = ""; // reset them
fetch('vectorbfi.wasm')
.then(response => response.arrayBuffer())
.then(buffer => new Uint8Array(buffer))
.then(binary => {
var moduleArgs = {
wasmBinary: binary,
arguments: [
"-c",
document.getElementById('input').value
],
print: function(text) {
document.getElementById('output').textContent += text;
},
printErr: function(text) {
document.getElementById('stderr').textContent += text;
}
};
var module = Module(moduleArgs);
});
});
</script>
</body>
</html>
今回はこれらを Hugoの content/
以下に置き、GitHub Pagesにデプロイしました