Skip to content

Instantly share code, notes, and snippets.

@renem2185
Last active March 17, 2024 05:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save renem2185/eb907c6b0f554f95de929420d7d20a77 to your computer and use it in GitHub Desktop.
Save renem2185/eb907c6b0f554f95de929420d7d20a77 to your computer and use it in GitHub Desktop.
Chicken Schemeのコードを Emscriptenを使ってデプロイする

本当は 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

Clang版 Chicken Schemeの導入

ほぼ参照の通り

$ 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

ビルド

  1. Schemeで書いたコードをトランスパイルする
$ $HOME/chicken/chicken-5.1.0-llvm/bin/csc -t -static vectorbfi.scm
  1. Chicken Scheme自体のC言語のソースコードを持ってくる
## 全部使う訳ではない
$ cp $HOME/chicken/chicken-5.1.0/*.c .
  1. Schemeのモジュールを持ってくる
## chicken-installが済んでいればこの場所にソースコードがあるはず
$ cp -r $HOME/.cache/chicken-install/srfi-*/ .
  1. 以下のシェルスクリプトを実行する (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にデプロイしました

参照

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment