Draft: ライブラリ (tidbits remote-repl)

(tidbits remote-repl)はリリース版にはまだ含まれていません。使用するにはsvn repositoryのtrunkをビルドしてください。

Remote REPLのサーバーとクライアントはinetソケットにて接続されます。サーバーにはブロックするタイプとしないタイプが用意されています。ブロックしないタイプを使うことにより、例えばGLUTによるアニメーションを止めること無くインタラクティブにプログラムをデバッグすることが可能となります。どちらの場合も同じサーバーに複数のクライアントを接続することができます。
重要:Remote REPL機能はセキュリティーについてまったく考慮されていません。外部から接続可能なマシンで実行しないでください。

library: (tidbits remote-repl)

Remote REPL機能を提供します。

procedure: blocking-remote-repl

ブロックするタイプのREPLサーバーを実行します。

synopsis:
  (blocking-remote-repl service) 
   => noreturn
arguments:
  service: <string>

serviceで指定されたポートで接続を待つREPLサーバーを実行します。この手続きはリターンしません。

procedure: connect-remote-repl

REPLサーバーに接続しプロンプトを表示します。

synopsis:
  (connect-remote-repl node service) 
   => unspecified
arguments:
  node: <string>
  service: <string>

nodeとserviceで指定されたREPLサーバーに接続しプロンプトを表示して入力待ちの状態になります。プロンプトにCTRL-Dを入力することでリターンします。プロンプトに(exit)を入力することによりREPLサーバーを終了させた場合もリターンします。

procedure: make-remote-repl

ブロックしないタイプのREPLサーバーを作成します。

synopsis:
  (make-remote-repl service) 
   => <procedure>
arguments:
  service: <string>

serviceで指定されたポートで接続要求を受け付けるREPLサーバーを作成します。make-remote-replは引数を取らない手続きを返します。返された手続きを定期的に呼び出すことによりクライアントの接続要求をポーリングします。クライアントの接続要求があればS式を受信してトップレベルで評価します。

ブロックするタイプの例

サーバーの起動(ポート番号"6809"で接続を待つ場合)
> (import (tidbits remote-repl))
> (blocking-remote-repl "6809") ; *1

blocking-remote-repl: ubuntu-core2 #<server-socket tcp stream 0.0.0.0:6809>

*1 blocking-remote-replには接続に使用するポート番号を文字列で与えます。

クライアントの起動(IPアドレス"192.168.1.4"のポート番号"6809"に接続する場合)
> (import (tidbits remote-repl))
> (connect-remote-repl "192.168.1.4" "6809") ; *1

connect: 192.168.1.4:6809 (enter ^D to exit)

REPL> 

*1 connect-remote-replには接続するサーバーのIPアドレスとポート番号を文字列で与えます

クライアントにS式を入力すると、そのS式がサーバーで評価されて結果がクライアントに表示されます。クライアントにはバックトレースなども含めてスタンドアロンでの使用と同じ情報が表示されます。

クライアントセッションの例
> (import (tidbits remote-repl))
> (connect-remote-repl "192.168.1.4" "6809")

connect: 192.168.1.4:6809 (enter ^D to exit)

REPL> (gethostname)
"ubuntu-core2"
REPL> (- x)

error in ubuntu-core2 (#<server-socket tcp stream 0.0.0.0:6809>)
error: unbound variable x

backtrace:
  0  (- x)
  1  (blocking-remote-repl "6809")
  ..."/dev/stdin" line 1

REPL> ^D ; *1
[exit]
>

*1 クライアントのみの終了はプロンプトでCTRL-Dを入力します。サーバーも同時に終了させるには(exit)を入力してください。

ノンブロックタイプの使い方

make-remote-repl手続きを呼び出してサーバーの作成を行います。あとはmake-remote-replの返す手続きをプログラム中で定期的に呼び出すようにするだけです。

組み込みサンプル

exampleディレクトリのglut-demo.scmにポート番号"6809"で接続を待つノンブロック型のサーバーを組み込んでみます。

$ diff -c glut-demo.scm glut-remote-repl-demo.scm 
*** glut-demo.scm
--- glut-remote-repl-demo.scm
***************
*** 15,20 ****
--- 15,22 ----
  (begin
  
    (import (core) (gl) (glut) (rnrs) (rnrs programs))
+   (import (tidbits remote-repl)) ; *1
+   (define pump-repl (make-remote-repl "6809")) ; *2
  
    (define object glutSolidIcosahedron)
    (define reverse #t)
***************
*** 43,48 ****
--- 45,51 ----
  
    (define rotate
      (lambda ()
+       (pump-repl) ; *3
        (cond ((< (+ last-update 16000) (microsecond))
               (if (= (glutGetWindow) 0) (exit 0))
               (if reverse

*1 ライブラリ(tidbits remote-repl)をimportします。*2 make-remote-repl手続きでポート番号"6809"で接続を受け付けるサーバーを作成しmake-remote-replの返り値をpump-repl変数に格納しておきます。*3 このプログラムで定期的に呼び出されているrotate手続きの中からpump-replを呼び出します。

クライアントの使い方は同じです。サーバーを組み込んだglut-remote-repl-demo.scmを起動しクライアントを接続したら例えば(set! object show-torus)と入力してみてください。動作中のプログラムをリモートで操作できることが確認できます。