Robot Language and a Tail Recursive Interpreter
Upcoming SlideShare
Loading in...5
×
 

Robot Language and a Tail Recursive Interpreter

on

  • 270 views

とても簡単なプログラミング言語Robotのインタープリタを、 ...

とても簡単なプログラミング言語Robotのインタープリタを、
末尾再帰インタープリタとして実現した。
その解説。
スタックが非常に少なくても、末尾再帰の無限ループが、永遠に回る。

Statistics

Views

Total Views
270
Views on SlideShare
151
Embed Views
119

Actions

Likes
3
Downloads
0
Comments
0

3 Embeds 119

https://twitter.com 89
http://shigemk2.hatenablog.com 31
https://tweetdeck.twitter.com 1

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Robot Language and a Tail Recursive Interpreter Presentation Transcript

  • 1. 1 Robot言語 と 末尾再帰インタープリタ 2014/OCT/18 たけおか@AXE twitter: @takeoka www.takeoka.org/~take/
  • 2. 2 Robot言語
  • 3. 3 Robot言語とは ● 再帰的な曲線を描くための言語 ● 貧弱だが、ピュア関数型言語といえる ● タートル・グラフィックスで画を描く ● 非常に単純なプログラミング言語 ● 繰り返し回数を記憶するために、Accが一つだけある ● オリジナルのRobot仕様書 & 実装 Litchen Wang: An Interactive programming Language for control of robots, DDJ, Vol.2, Issue 10, pp.60-63 (1977). ● 日本での紹介文書 石田晴久: ロボット言語, bit,Vol10, No.7, pp.35- 50(1978)) ● たけおかのページ http://www.takeoka.org/~take/kvm/robj.html
  • 4. 4 組み込み関数など ● + ● 1+ Accをインクリメント ● - ● 1- Accをデクリメント ● h ● Home 画面中央部に移動 ● n ● North 画面上方を向く ● c ● Clear 画面を消去 ● r ● Rotate 45度右へ回る ● f ● Forward 線を引きながら1step進む ● j ● Jump 線を引かずに1step進む ● t(<非ゼロ文>)(<ゼロ文>) ● Test Accが0でないなら<非ゼロ文>のみを ● Accが0なら<ゼロ文>のみを実行する ● dF(<定義文>) ● defun ユーザ関数Fを<定義文>として定義する ● a ● Acc項になってAccの値を示す ● このRobotにはAccが一つだけある ● (0-2^31の値を取る) ● ユーザ関数 ● 英小文字かつ予約されていない一 文字がユーザ関数名として使える。 ● dでdefineする
  • 5. 5 実行例 ● ヒルベルト曲線 du(t(-vfxuyfufxv+)(x)) dv(t(-uyfvfxvyfu+)(y)) dx(6r) dy(2r) chna-5+2ru ● 無限ループ db(z) dz(frb)
  • 6. 6 実行例 ● ドラゴン曲線 dx(t(-x6rk+)(f)) dk(t(-x2rk+)(f)) chna-10+x ● シェルピンスキー曲線 dx(t(-xfxufuxfx+)(v)) du(5r) dv(2r) dy(6r3r4(fx)) chna-2+y
  • 7. 7 テイル・リカーシブ・インタープリタ (末尾再帰インタープリタ)
  • 8. 末尾再帰呼出し→ループ 変換(コンパイル時) 8 ● 自分自身の再帰呼出しは、容易に、ループに変換可能 ● 再帰呼び出し recursive call int fact_tail_rec(int n, int a) { if(n == 1){ return a; } else return fact_tail_rec(n-1, a*n); } ● ループ int fact_loop(int n, int a) { for(;;){ if(n==1) return a; a= a * n; n= n-1; } }
  • 9. 9 コンパイラって楽だよね ● コンパイル時間が長くても、怒られない ● コンパイル時に、めちゃくちゃメモリを喰っても怒られない ● 程度問題はあるが… ● 広域を見れる ● (自己)末尾再帰を見つけるのも、関数のアタマからお尻ま でゆっくりと見れる ● 実行時間が速ければそれで良し ● 組込みだと、メモリ・フットプリントも重要だが – コード・サイズ – ワーキング・メモリ(RAM)
  • 10. 10 インタープリタは大変 ● インタープリタの性能 = 実行時間 ● JIT なんていうものも大事か… ● でも、JIT やるなら、実行前に機械語に変換しろよ – 大方の言語なら可能だ – Javaとか、わざと複雑にしてるよな – 古いx86の自己書き換えコードなんか動かなくてもいい よ(フツーの場合)
  • 11. 11 インタープリタは末尾再帰呼び出しを 見抜けるのか? ● Tail recursive call は、コンパイラなら、コンパイル中に 見つけて、静的に変換 ● インタープリタって、基本、極めて局所しか見ない ● 局所しか見ないで、末尾再帰の最適化はできるのか?
  • 12. 12 末尾再帰インタープリタ ● 末尾再帰の最適化を見つけるためのものじゃないよ ● インタープリタの構造が、末尾再帰 ● Continuation Passing 的なことを、インタープリタ内部で、 インタープリタ自身がやっている ↓ ● インタープリタが、不要なスタックを消費しない ● テイル・リカーシブ・インタープリタ : インタープリタの実現方法 ● 実行時に、実行のために明らかに不要な情報を記憶しない。 ● 当然のようであるが、素朴な古い実装では、なかなか難し い。 ● テイル・リカーシブな実現のインタープリタで有名な言語 は、Schemeである。
  • 13. 13 本インタープリタの実現int exeq() // 1命令を実行する { n= term(); switch((ccc=CT[Pc++])){ case 'f' : x1=x + n*v*step; y1=y + n*u*step; drawLine(x,y, x1,y1, 0); x=x1; y=y1; break; case '0' : /* func end */ { Context *c; c=stk_pop(); Pc=c->pc; CT=c->ct; top= c->top; n= c->n-1; if(Pc== -1){ contAble=false;finishIt(); return; // 評価、全終了} if(n>0){ /* n回 繰り返し中 */ c->n=n; stk_push(c); CT=top; Pc=0; //再度、関数の先頭 return; } return; } :
  • 14. 14 本インタープリタの実現 : default: /* ユーザ定義関数 */ top= defun[ccc-'a']; /* 末尾再帰 最適化可能な時は、pushしない ユーザ関数定義の末尾、すなわち、後に実行すべきものが何もない */ if(n!=1 || CT[Pc]!='0'){ Context c; c.n=n; c.top=top; c.pc=Pc; c.ct=CT; stk_push(&c); } CT= top; Pc=0; //printf(" userFunc %c CT=%x ",ccc,CT); } }
  • 15. 15 ここまで ● 関係ないけど… ● Lispプログラマ、Prologプログラマ募集中 ● ルールベースの人工知能 開発中 ● 機械学習も取り込んだ、ハイブリッドAI ● 普通の32bit or 64bitマシンが対象です
  • 16. 16 おまけ
  • 17. 17 古い素朴なインタープリタ実現 ● 古い素朴なインタープリタ実現の話をしよう。
  • 18. 18 昔風、素朴なeval eval(関数) { : 関数をどんどん実行する : if(関数呼び出しに出会った) eval(新しい関数); 残りを実行 : }
  • 19. 19 古い素朴なインタープリタ実現 ● 関数実行の本体(中心部)は 「eval」と いう関数 ● evalが、eval自身を再帰的に呼び出す実現が素朴に行われている ● 新しい関数を実行するたびに、 evalが呼び出される。 ● そして、前のevalに戻 るための情報を、常に記憶 ● 実行対象のソースコード が末尾再帰になっていても… 前のevalのための情報が必ず記憶され、まったく最適化(節約)され ない ● 模式evalで、eval中からevalを再帰的に呼び出す ● このeval呼び出しによっ て、 「残りを実行」のための情報を記憶する ● 呼び出しの度に、記憶している情報はどんどん増える。
  • 20. 20 テイル・リカーシブなeval eval(関数) { eval_loop: : 関数をどんどん実行する : if(関数呼び出しに出会った){ if(新しい関数呼び出しの後に、仕事はある?){ 今evalしている情報を、スタックへ退避 } プログラムカウンタ=新しい関数; goto eval_loop; } ※1 残りを実行 : ※2 if(スタック!=空){ スタックから、情報を戻す goto eval_loop; } }
  • 21. 21 テイル・リカーシブなeval ※2のあたりで、 うまいことeval_loopへgotoできるようにするのがコツ 難しいところかな。 ※1の「残りを実行」は なるべく無くすのが、インタープリタをすっきりさせるためには、 良い
  • 22. 22 テイル・リカーシブなeval ● evalそのものが大きなループになっている ● 新しい関数の実行をしても、evalの呼び出しは深くならない。 ● 関数の末尾からの関数呼び出しは、何も記憶する必要がない ● テイル・リカーシブ・インタープリタは、何も記憶しない。 ● 関数が自分自身を呼び出していない時も、最適化される ● 実行途中の関数を継続(再開)するために必要な情報は、 ソフトウェアで作った スタックに格納する。 ● 当然に、テイル・リカーシブでない呼び出しは、 普通に記憶を消費する。
  • 23. 23 テイル・リカーシブなeval ● 関数の末尾からの関数呼び出しは、何も記憶する必要がな い。 ● テイル・リカーシブ・インタープリタは、何も記憶しない。 ↓ ● テイル・リカーシブ・インタープリタは、 局所しか見ない、単純な構成のインタープリタでも、 末尾再帰ループの場合に、無駄な 記憶を消費することがない ● Prologインタープリタや、コンパイルされたコードを実行する仮 想マシンのインタープリタ(実行系)は、 テイル・リカーシブ・インタープリタとして実現されているのが、 普通である。
  • 24. 24 Robot言語 詳細
  • 25. 25 Robot言語とは ● 再帰的な曲線を描くための言語 ● タートル・グラフィックスで画を描く ● 非常に単純なプログラミング言語 ● 繰り返し回数を記憶するために、Accが一つだけある ● オリジナルのRobot仕様書 & 実装 Litchen Wang: An Interactive programming Language for control of robots, DDJ, Vol.2, Issue 10, pp.60-63 (1977). ● 日本での紹介文書 石田晴久: ロボット言語, bit,Vol10, No.7, pp.35- 50(1978)) ● たけおかのページ http://www.takeoka.org/~take/kvm/robj.html
  • 26. 26 文法 <文> ::= <項><関数> | <項>(<文>) | <文><文> ● Robotは<文>を実行します。 ● <項>はすぐ後のものの繰り返し回数を表わします。 <項> ::= a | <数> | 「何もなし」 ● 「何もなし」は1を意味します。 ● aはAccの内容を意味します。 <数> ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | <数><数> ● 0は2^31を意味します。 <関数> ::= 「組み込み関数」 | 「ユーザ関数」 ● 「組み込み関数」、「ユーザ関数」ともに以下。
  • 27. 27 組み込み関数 ● + ● 1+ Accをインクリメント ● - ● 1- Accをデクリメント ● h ● Home 画面中央部に移動 ● n ● North 画面上方を向く ● c ● Clear 画面を消去 ● r ● Rotate 45度右へ回る ● f ● Forward 線を引きながら1step進む ● j ● Jump 線を引かずに1step進む ● t(<非ゼロ文>)(<ゼロ文>) ● Test Accが0でないなら<非ゼロ文>のみを ● Accが0なら<ゼロ文>のみを実行する ● dF(<定義文>) ● defun ユーザ関数Fを<定義文>として定義する
  • 28. 28 予約語 ● a ● Acc 項になってAccの値を示す ● このRobotにはAccが一つだけある ● (0-2^31の値を取る) ● : ● コマンドであることをしめす。 ● コマンドは本Robot独自の機能である。 ● Robotの言語仕様にはない。
  • 29. 29 ユーザ関数 ● 英小文字かつ予約されていない一文字がユーザ関数名として使 えます。 ● dでdefineする
  • 30. 30 コマンド(独自拡張) ● コマンドはKRobot独自の機能である。 ● コマンドは実行管理環境(トップレベル)に対する指令である。 ● :d ● ユーザ関数の全ての定義を表示する ● :n ● ユーザ関数をすべて消去する ● :<項>s ● f関数で進む距離をドット数で指定する ● コマンドを実行する場合も文を入力した後、 DoItでトップレベルに評価さ せる。 ● 一部のコマンドは、それを評価することによって、PC,スタックなどに影響を 与えてしまう。 ● よって、一部のコマンド評価後はContはできなくなる。
  • 31. 31 以上