- 1 名前:デフォルトの名無しさん [04/01/10 03:45]
- 第四世代
- 369 名前:デフォルトの名無しさん mailto:sage [2008/03/20(木) 15:22:35 ]
- >>368
実装にもよるけど、 ワード ( を読むと、フラグが立って、ワード ) まで無視する。 Forth で書いてある、ってこういう意味ってことでいいのかな?
- 370 名前:デフォルトの名無しさん [2008/03/20(木) 15:50:12 ]
- >>369
いやなんかマクロみたいな機能を使って書かれているのかなーと forth知らないので全然分かんないんですけど 要するに↓みたいにforth言語で書かれているのか?ってことです : ( hoge hoge ... ;
- 371 名前:デフォルトの名無しさん mailto:sage [2008/03/20(木) 20:15:20 ]
- 『標準FORTH』だと pp.166 にある。
: ( 29 WORD DROP ; IMMEDIATE 29 は ')' のコード WORD はスタックトップと同じキャラが出てくるまで入力を読んで、 その先頭のアドレスをスタックトップに置くワード。DROP は説明の 必要ないな。IMMEDIATE は直前に定義されたワードを、 イミディエイトワードにするワード。 C マガジンのきだあきらさんの連載『千言万語』の Forth の時に 紹介してたネタだったような気もする。
- 372 名前:デフォルトの名無しさん mailto:sage [2008/03/20(木) 20:16:04 ]
- 千言万語単行本にならねーかな
- 373 名前:デフォルトの名無しさん mailto:sage [2008/03/20(木) 21:37:32 ]
- 追加。
イミディエイトワード、というのが、プログラムの実行時ではなく 読み込み時に意味を持つワードなので、マクロのような機能と 言えるかもしれません。
- 374 名前:デフォルトの名無しさん [2008/03/21(金) 07:42:46 ]
- >>371-373
サンクス www.geocities.jp/naosacra/mops/particle2/immediate.html これ見てるけどimmediateの意味がいまいちわからん… 何のためのものなんだ? : ( 29 WORD DROP ; IMMEDIATE 例えば↑にimmediateがついてなかったらどういう動作になるんだろう
- 375 名前:デフォルトの名無しさん mailto:sage [2008/03/21(金) 08:55:03 ]
- 仮に ( がイミディエイトワードで無かったとすると、
: hoge ほげほげ ( ほげほげ ) ; とか書いた場合に、hoge の定義の一部として、実行される部分になって しまいます。定義中でも直ちに実行されるワードがイミディエイトワードです。
- 376 名前:デフォルトの名無しさん [2008/03/22(土) 10:18:31 ]
- >>375
なるほど 理解した。サンクス
- 377 名前:デフォルトの名無しさん [2008/03/27(木) 22:38:05 ]
- 最近、Concatenativeな言語というもの目にしたんでage
- 378 名前:デフォルトの名無しさん mailto:sage [2008/03/28(金) 00:23:41 ]
- なんか酷いのみつけてきたwwwww
ちょっと草植えときますね型言語 Grass www.blue.sky.or.jp/grass/doc_ja.html スタックマシン使ってるってだけみたいだが(俺には良く分からん)
- 379 名前:デフォルトの名無しさん mailto:sage [2008/03/31(月) 10:36:35 ]
- forth厨はなんでもかんでもスタックマシンにするな
- 380 名前:デフォルトの名無しさん mailto:sage [2008/04/03(木) 02:09:52 ]
- factorでHelloWorldのCGIやってみた
httpdからのfactor起動はバッチファイルで USING: io ; "Content-type: text/html; charset=Shift_JIS\n\n" print "<HTML><head><title></title></head>\n<body>" print "はろ〜factor表\示可能\" print "<br>\n</body></HTML>" print なんか楽しいw
- 381 名前:デフォルトの名無しさん mailto:sage [2008/04/10(木) 03:00:58 ]
- あれ?factorの新しいの入れたら日本語出なくなった
エンコード関係?
- 382 名前:デフォルトの名無しさん mailto:sage [2008/05/14(水) 14:10:30 ]
- factorソースから入れるのめんどくさいな・・・
gitなんて初めて知ったよ
- 383 名前:デフォルトの名無しさん mailto:sage [2008/06/03(火) 17:56:33 ]
- 何か面白い話無い?
- 384 名前:デフォルトの名無しさん mailto:sage [2008/06/05(木) 11:05:57 ]
- スタック1本で動作する処理系作れ
- 385 名前:デフォルトの名無しさん mailto:sage [2008/06/05(木) 16:18:58 ]
- バロースのメインフレームはシングルスタックなんだぜ?
- 386 名前:デフォルトの名無しさん mailto:sage [2008/06/05(木) 18:37:49 ]
- wikipediaより
> スタックを1つしか持たないスタックマシンは、 > 計算モデルとしては非常に弱い。例えば、1-スタックマシンでは、 > 0n1n(0の並びの後に同じ個数の1が並ぶ言語)のような単純な言語も認識できない。 > 1-スタックマシンの計算能力は、有限オートマトンよりも高いが、 > 決定性プッシュダウン・オートマトンよりも低い。 > 一方、複数のスタックを持つスタックマシンはチューリング機械と等価である。 > 例えば、2-スタックマシンでは、チューリング機械をエミュレートできる > (チューリング機械のヘッド位置から左側のテープをひとつのスタックが代替し、 > 右側のテープをもうひとつのスタックが代替する)。 へぇ〜
- 387 名前:デフォルトの名無しさん mailto:sage [2008/07/17(木) 00:50:58 ]
- factorのドキュメント消えてら
- 388 名前:デフォルトの名無しさん [2008/08/01(金) 21:55:57 ]
- V
en.wikipedia.org/wiki/V_(programming_language) Onyx www.canonware.com/onyx/ Forthもこれらも俺には使いこなせないんだけどね orz
- 389 名前:388 mailto:sage [2008/08/01(金) 21:57:15 ]
- Vはこっちのページも
code.google.com/p/v-language/
- 390 名前:デフォルトの名無しさん mailto:sage [2008/08/02(土) 03:04:06 ]
- Forthの実装中sage
実装法のドキュメント付きで晒すかも
- 391 名前:デフォルトの名無しさん mailto:sage [2008/08/02(土) 04:01:08 ]
- forthって、引数の数ミスるだけで崩壊するよな
>>390 どんな俺フォースを見せてくれるんだい? 誰もいないしここ、日記帳のつもりで使ってくれよ。
- 392 名前:デフォルトの名無しさん mailto:sage [2008/08/02(土) 06:07:26 ]
- 久々にレスキタワァ*・゜゚・*:.。..。.:*・゜(n‘∀‘)η゚・*:.。. .。.:*・゜゚・* !!!!!
- 393 名前:デフォルトの名無しさん mailto:sage [2008/08/02(土) 08:44:15 ]
- >>390
www.google.co.jp/search?hl=ja&q=codepad&btnG=%E6%A4%9C%E7%B4%A2&lr= どんな言語使って作るかしらん こんなの補助として使ってみるのも便利かもしらん
- 394 名前:390 mailto:sage [2008/08/02(土) 14:40:33 ]
- 過疎っぷりに見てる人もいないと思ったら、意外といたのね。
>>391 Forthの実装は初めてなので、古典的で教科書通りのIndirect Threaded Code、 Cで書いた仮想マシンの上で動かすってかんじで。 今はMac OS XとLinux(x86)とLinux Zaurus(arm)の上でぽちぽち書いてる。 ポータビリティーは良いのでメモリがあって速度も気にしなければ 簡単にマイコンにも移植可能だと思う。H8なら余裕かな。 今月のトラ技の78K0基板持ってるんだけど、こっちはきついかも。 >>392 あばばばばばば >>393 おお、こんな面白いのがあったのね。 とりあえずアカウント取ってみた。 このスレに落書きしつつ、blogにまとめてけばいいかな。 ANS-ForthのCORE準拠を目指して www.taygeta.com/forth/dpans.html 読んでるんだけど、けっこうめんどいなあ。 ある程度実装の目処がたったらコード晒してくつもり。 少々お待ちを。
- 395 名前:デフォルトの名無しさん mailto:sage [2008/08/04(月) 22:59:11 ]
- Forth は実装が簡単だって聞いてたんで、
自分も作ってみようとちょっと調べたんだけど、 仕組みがよく分からなかったし(ワードの定義とか)、 規格に沿った物にしようとすると意外に仕様が大きくて、 挫折しますた><
- 396 名前:390 mailto:sage [2008/08/05(火) 23:09:27 ]
- >>395
辞書まわりは次の10個のワードがあればOK(たぶんね) CREATE COMMA(,) [ ] IMMEDIATE TICK(') COLON(:) SEMICOLON(;) FIND WORD このあたりのワードの挙動は、 www.annexia.org/forth ここのjonesforthを参考にすればいいと思う。 これをインスパイヤしたCと日本語のドキュメントを書いてるんだが・・・仕事が忙しくてね・・・ これをざーっと読んで、yforthあたりの簡単な処理系のコード眺めて 実際に動作を確かめればANS-Forthの準拠もそう難しくないかと。 たださ、ANS-Forthって処理系の内部の規定しすぎじゃね? もっと好きなようにやらしてくれよ。一回確保したWORDが二度と解放できないとか、 文字列はヌル終端しない代わりに文字数を記憶するとか、ちょっと気持ち悪い気がする。
- 397 名前:デフォルトの名無しさん mailto:sage [2008/08/05(火) 23:23:59 ]
- >文字列はヌル終端しない代わりに文字数を記憶する
これは正当だと思う。ヌル終端がどれだけのバグを生み出しているか……
- 398 名前:デフォルトの名無しさん mailto:sage [2008/08/06(水) 21:05:50 ]
- 実装としては文字列をヌル終端にしても可。
但し、文字数は必要、かつ、 ヌル終端を当てにしたコードを書いても一般には動く保証なし。 が規定の内容と思われます。他の規定も同様。
- 399 名前:デフォルトの名無しさん mailto:sage [2008/08/08(金) 19:23:22 ]
- ASCIIZはねーよマジで
- 400 名前:デフォルトの名無しさん mailto:sage [2008/08/09(土) 16:38:27 ]
- でも、C言語で作られたプログラムとの連携したいときは、NUL文字終端がいいよね。
C言語で作られたプログラムの数の多さ、便利さから言うと、無視できないなと。
- 401 名前:デフォルトの名無しさん mailto:sage [2008/08/09(土) 18:30:35 ]
- Cは捨てるのがよろしいかと。
C++をbetter Cとして使う方がまだましだと思う。 C++を使えないようなリソースのキツい環境で使うんだったらforthを直書きした方が良いんじゃね?
- 402 名前:デフォルトの名無しさん mailto:sage [2008/08/10(日) 00:15:50 ]
- >C++をbetter Cとして使う
それ最悪
- 403 名前:デフォルトの名無しさん mailto:sage [2008/08/11(月) 00:15:21 ]
- 402 と同感だが、better Cとして使うのは FORTH 実装にはない(価値が少ない)だろ。
自己学習として作るならまだしも、 FORTHに期待される動作環境だったらアセンブリレベルの設計が必要だろ。 C++使うならC++的設計をしろって。
- 404 名前:デフォルトの名無しさん mailto:sage [2008/08/27(水) 00:31:36 ]
- forthチック俺言語のプロセスが回った記念カキコ。
forthだと引数管理がけっこう面倒だと思うけど、wordの名前に 引数の数の情報を盛り込んだら楽にならんかね? 俺言語ではこんな感じでドットの数=引数の数にしているんだけど、どう思う? 1 2 ..sum 1 2 3 .:sum 名前の衝突も起こりにくくなって一石二鳥かと思うんだけど。
- 405 名前:デフォルトの名無しさん mailto:sage [2008/08/27(水) 09:31:38 ]
- ドット打つのがひたすらめんどくさそう
ifだと.:ifになるの?
- 406 名前:デフォルトの名無しさん mailto:sage [2008/08/27(水) 21:05:33 ]
- こういう風にしたらどう?
・引数可変のワードは # で始まることとする ・ワード [ は現在のパラメータスタックポインタの値を リターンスタックに積む ・ワード ] は現在のパラメータスタックポインタの値と リターンスタックポインタのトップの値の差から パラメータ数を計算しパラメータスタックに積む たとえば [ 10 20 30 ] #sum と書くと、#sum実行直前にはパラメータスタックは 10 20 30 3 となっていて、#sumは3つの数の和を求めればいいことがわかる。
- 407 名前:404 mailto:sage [2008/08/27(水) 22:38:18 ]
- >405
そこは構文糖使った方がよろしいかと (a ? b ! cの三項演算子とか) >406 それも考えたけど、そうするとConcatenativeのメリットが死ぬんだよね。 できるだけ前の計算結果に依存しないように考えると、セパレータのようなものを スタックに積むのは良くないので、ワード単体で引数までを意味するようにしたい、 ということですな。
- 408 名前:デフォルトの名無しさん mailto:sage [2008/08/28(木) 02:39:56 ]
- prologみたいにsum/3みたいにするとか。
よく判ってないが。
- 409 名前:デフォルトの名無しさん mailto:sage [2008/09/19(金) 17:01:15 ]
- 引数管理しなきゃいけないようなコードの構成だと崩壊しそう
- 410 名前:デフォルトの名無しさん mailto:sage [2008/09/25(木) 03:11:26 ]
- しばらくforthやってたら他の言語がいじれなくなってて驚いた。
のめり込むのは危険だなw
- 411 名前:デフォルトの名無しさん mailto:sage [2008/09/25(木) 03:16:06 ]
- >>407
そのセパレータってリスト終端のnullに相当するから あながち間違ってないと思う。
- 412 名前:デフォルトの名無しさん mailto:sage [2008/09/25(木) 21:54:56 ]
- concatenativeの論理を詰めて行くと、
スタックの機構はコード設計のための因子から外されるのかも。
- 413 名前:デフォルトの名無しさん mailto:sage [2008/09/25(木) 22:34:55 ]
- >411
Wordの中でWordを呼ぼうとすると破綻するよ。 >412 結局はトップを基点とした対称性(みたいなもの)になるからな。 対称性があれば何でもOK
- 414 名前:デフォルトの名無しさん mailto:sage [2008/10/01(水) 00:29:26 ]
- スタック型プログラミング言語の最少命令セットを探して
Whitespaceに辿りついたのですが、 これよりも言語仕様的に小さいスタック型言語ってあります?
- 415 名前:デフォルトの名無しさん mailto:sage [2008/10/01(水) 01:55:39 ]
- define
call return conditional jump push pop これだけで足りるかな?
- 416 名前:デフォルトの名無しさん mailto:sage [2008/10/01(水) 07:09:50 ]
- callに条件をつければjumpも省けるんじゃないか?
- 417 名前:デフォルトの名無しさん mailto:sage [2008/10/02(木) 03:17:37 ]
- それより、ひと目で何やってるか判るforth作ってくれないかな。
>>54-65とか何やってるのかわからん。 記号覚えればいいんだろうけど。 : は定義っぽいということは文脈で判った。許す。 >rとかr>は何かと。 ;は文の終り? LISPでいう 'a は (quote a)です、みたいに特殊記号をあまり使わずに 誰が見ても大体判るように、平易な形にならないかな。
- 418 名前:デフォルトの名無しさん mailto:sage [2008/10/02(木) 17:56:08 ]
- >>417
: word でワードの定義開始、;で定義の終端 >r,r>はリターンスタックへのプッシュとポップ >>54の括弧内はそのワードを実行するとデータスタックの状態がどう変わるかをコメントで表している 他の言語と違って裸のスタックが丸見えなんよ
- 419 名前:デフォルトの名無しさん mailto:sage [2008/10/03(金) 02:22:08 ]
- リターンスタックに何をプッシュ(とポップ)するの?TOSの内容ってこと?
>rとr>って判りにくいと思う。 一瞬で見分けられないというか。 不等号ちがうんかと。 記号使わずに全部記述的にできないかな。 mindとかそんなのかな。
- 420 名前:デフォルトの名無しさん mailto:sage [2008/10/03(金) 03:00:42 ]
- わかりやすい文法が欲しいのならforth系はあきらめた方がいいと思うよ
- 421 名前:デフォルトの名無しさん mailto:sage [2008/10/03(金) 06:08:32 ]
- : pushTOStoReturnStack postpone >r ; immediate
: popFromReturnStackToTOS postpone r> ; immediate
- 422 名前:デフォルトの名無しさん mailto:sage [2008/10/03(金) 12:26:50 ]
- 自分も420に賛成する、forthは裸の2スタックマシンのアセンブラと思えばいいんだけど、それがつらいとちょっときついと思う
ただ、それがインタラクティブ環境を作るあたりと小さな核で構築できるのが非常に面白いのでがんばって覚えてみてよ。 逆に言うと簡単にぶっ壊れるとも言う
- 423 名前:デフォルトの名無しさん mailto:sage [2008/10/03(金) 16:59:48 ]
- Cとかの他の言語の常識持ち込もうとしてるヤツいないか?
「Forthではこう書く」ってのに納得いかないなら 悪いことは言わんから、使うのやめとけ
- 424 名前:デフォルトの名無しさん mailto:sage [2008/10/03(金) 17:54:20 ]
- スタックっつうのはあくまで機械にやさしいものであってユーザーフレンドリーなものじゃないしな
- 425 名前:デフォルトの名無しさん mailto:sage [2008/10/03(金) 18:38:23 ]
- 頻繁にスタックを意識しないといけないのは悪いForthコード
- 426 名前:デフォルトの名無しさん mailto:sage [2008/10/03(金) 20:05:40 ]
- 正直アセンブラの方が楽だよ
- 427 名前:デフォルトの名無しさん mailto:sage [2008/10/03(金) 20:24:33 ]
- 慣れると気持ちいいよJoy。forthは知らんけど
- 428 名前:デフォルトの名無しさん mailto:sage [2008/10/03(金) 20:29:08 ]
- >426
Forthは仮想スタックマシンのアセンブラだから、 (仮想)マシンの理解度によるだろな。
- 429 名前:デフォルトの名無しさん mailto:sage [2008/10/03(金) 22:29:45 ]
- いや、もっと視認しやすい記号セットを使ってくれって話だろ。
ハイライトできるエディタで単語登録するか、トランスレータでもかますのがいいと思う。
- 430 名前:デフォルトの名無しさん mailto:sage [2008/10/03(金) 23:01:49 ]
- ところでリターンスタックって別に必要なの?
普通のCPUは1本だよね。 スタックに対して相対アドレッシングがないからってことかな?
- 431 名前:デフォルトの名無しさん mailto:sage [2008/10/03(金) 23:57:29 ]
- >419
>rとr>は確かに見た目がわかりにくい。 よほどのことが無い限り使わない。 localがあれば要らない。 >430 呼出しのときにデータスタックで直接パラメターを渡すためでしょう。
- 432 名前:デフォルトの名無しさん mailto:sage [2008/10/04(土) 00:00:27 ]
- >>430
普通のアーキテクチャだと関数呼び出しのスタックにパラメータも突っ込んじゃうけど forthはデータのpushと関数呼び出しの戻りアドレスが入るスタックが別なんよ。 っていうか別だから面白いことができるので、一緒だったらループとかで涙が出そうだと思う。
- 433 名前:デフォルトの名無しさん mailto:sage [2008/10/04(土) 00:10:21 ]
- SP, BPレジスタに相当するものがあれば良いのでは
- 434 名前:デフォルトの名無しさん mailto:sage [2008/10/04(土) 17:45:11 ]
- リターンスタックとデータスタックが一緒だと、
リターンアドレスを壊さないようにデータをいじるのがメンドイ。 リターンアドレスが詰まれている位置を避けるようにして スタックをアクセスしなきゃいけないから。 それはSPとBPがあってもメンドイことに変わりはない。
- 435 名前:デフォルトの名無しさん mailto:sage [2008/10/04(土) 19:46:33 ]
- >>430
まあ、便利だから? 実装としてはバローズのメインフレーム見たく演算とリターン アドレス保存を一本のスタックでこなすものもあるよ。
- 436 名前:デフォルトの名無しさん mailto:sage [2008/10/04(土) 21:37:24 ]
- factorだともうひとつスタックあるよ
- 437 名前:デフォルトの名無しさん mailto:sage [2008/10/04(土) 23:25:44 ]
- データスタックとリターンスタックがないと
チューリングマシンと等価じゃないらしいぞ
- 438 名前:デフォルトの名無しさん mailto:sage [2008/10/05(日) 00:17:09 ]
- >>437
等価じゃないとはよく聞くけど、等価じゃないとする説明ってどっかにないですかね。 それで実用で困ることありますかね。
- 439 名前:デフォルトの名無しさん mailto:sage [2008/10/05(日) 01:12:05 ]
- 今理解した。
リターンスタックってそのままBP相当じゃん。 ほんとはBPポインタ一個あれば十分だよね? 素直にBPを持たずにわざわざリターンスタックなんて用意してるのは、 スタックマシンと言えなくなるからかね。 なんだかなあ。
- 440 名前:デフォルトの名無しさん mailto:sage [2008/10/05(日) 03:10:12 ]
- BPあってもメモリがないとな
- 441 名前:デフォルトの名無しさん mailto:sage [2008/10/05(日) 03:49:49 ]
- 今理解した。
BPってそのままリターンスタック相当じゃん。 ほんとはリターンスタックあれば十分だよね? 素直にリターンスタックを持たずに、わざわざBPなんて用意してるのは、 レジスタマシンと言えなくなるからかね。 なんだかなあ。
- 442 名前:デフォルトの名無しさん mailto:sage [2008/10/05(日) 07:20:41 ]
- >>437
メモリアクセスできない純粋なスタックマシンなら、スタックが二本ないと チューリング等価ではないかも知れないが、FORTHはメモリアクセス @ ! が あるから、たとえスタック一本であってもチューリング等価じゃね? 考えてみればわかるが、メモリアクセスがあるとスタックの本数を自由に増やせる。 FORTHとスタックマシンとConcatenative言語は、それぞれ別の概念で、 単純に等号で結べないから、何について話しているのか意識しないと混乱すると思われ。
- 443 名前:デフォルトの名無しさん mailto:sage [2008/10/05(日) 09:51:29 ]
- ForthのVMとしては、
論理的には最低限二つの区別されたスタックがある。 標準的な実装での利点(v.s.スタックフレーム方式)は、 サブルーチン間でのデータのコピーが減らせること。 スタックフレーム一本でやるのはCとかでも標準的な実装だけど、 VMという同じ抽象度で比べれば、Cにはスタックは無い。 VMが実装できれば機械自体の仕組みはどうでも良い。
- 444 名前:デフォルトの名無しさん mailto:sage [2008/10/05(日) 13:26:57 ]
- 込み入った話は分からんけど、
とりあえずBF書けたらチューリング完全じゃなかったっけ?
- 445 名前:デフォルトの名無しさん mailto:sage [2008/10/05(日) 14:12:31 ]
- なんか話が噛み合ってない気がする。
- 446 名前:デフォルトの名無しさん mailto:sage [2008/10/05(日) 15:11:57 ]
- なんでそこまでチューリングマシンにこだわるのかわからん。
Forthがチューリングマシンであろうとなかろうと Forthで実用的なプログラムは書ける。 あともう一人、やたらリターンスタックを排除したがる奴も 何をしたいのかさっぱりわからん。
- 447 名前:デフォルトの名無しさん mailto:sage [2008/10/05(日) 17:47:31 ]
- まず当たり前の大前提の確認からだけど、Forthはチューリング完全だから。
仮にForthの仕様からリターンスタックだけを排除したとしても(それはForthとは呼べないだろうが) チューリング完全だ。理由は>>442 リターンスタックがBPで代用できるとか正直意味わからん。 スタック演算自体理解してない希ガス。
- 448 名前:デフォルトの名無しさん mailto:sage [2008/10/05(日) 18:27:08 ]
- リターンスタックという名前がいかんのだろ。
- 449 名前:デフォルトの名無しさん mailto:sage [2008/10/05(日) 18:35:04 ]
- >>437
スタックオートマトンとスタックマシンをごっちゃにしてる気がする。
- 450 名前:デフォルトの名無しさん mailto:sage [2008/10/05(日) 18:39:13 ]
- >>448
むしろリターンスタック以外の名前があるなら知りたいものだが。
- 451 名前:デフォルトの名無しさん mailto:sage [2008/10/05(日) 19:02:41 ]
- >442
大雑把にはこんな感じかね。 ・データスタック: 引数&戻り値 ・リターンスタック: 実行する命令列(辞書で展開された単語含む) リターンスタックというよりもオーダースタックといった方がちょうど良い気がするけどね
- 452 名前:デフォルトの名無しさん mailto:sage [2008/10/05(日) 19:25:44 ]
- リターンアドレスを積んでいるからリターンスタック
それでいいと思うが、難しく考えすぎじゃね?>>451
- 453 名前:デフォルトの名無しさん mailto:sage [2008/10/05(日) 19:28:44 ]
- Aスタック←→Bスタック
だったら勘違いが起きなかったと思う。
- 454 名前:デフォルトの名無しさん mailto:sage [2008/10/05(日) 19:34:19 ]
- >>453
むしろ勘違いを引き起こしそうなんだが。 リターンスタックが難しいんじゃなくて、 リターンアドレスをスタックに積むという 当たり前の関数呼び出し規約を説明しなければ、 理解されない時代になったということか…
- 455 名前:デフォルトの名無しさん mailto:sage [2008/10/05(日) 21:59:43 ]
- なんでリターンスタックの名前で混乱とか勘違いがあるの?
ひょっとして、リターンと聞いて戻り値を連想しちゃう人がいる、とか? だとしたらかなりキビシい状況だな。
- 456 名前:デフォルトの名無しさん mailto:sage [2008/10/06(月) 01:09:11 ]
- カールスタックの方が一般的じゃね?
- 457 名前:デフォルトの名無しさん mailto:sage [2008/10/06(月) 01:09:52 ]
- あ、カールじゃなくてコールスタック
- 458 名前:デフォルトの名無しさん mailto:sage [2008/10/06(月) 01:24:45 ]
- カールはスナックだな
- 459 名前:デフォルトの名無しさん mailto:sage [2008/10/06(月) 07:35:22 ]
- カールと言えば薄べったいのが出てることを最近知った。
従来品に比べて口の裏に張り付きにくいのはメリットだが、 少し物足りない気がした。
- 460 名前:デフォルトの名無しさん mailto:sage [2008/10/06(月) 11:21:56 ]
- Forth では昔からリターンスタックと呼んできたので、その伝統に則ればいいと
思うんだけどな。Wikipedia だと項目はコールスタックで立てられているが。
- 461 名前:デフォルトの名無しさん mailto:sage [2008/10/06(月) 12:10:36 ]
- コールスタック->カールスナック->コーンスターチ->張り付かないならカールじゃない
勉強し過ぎでしょう。
- 462 名前:461 mailto:sage [2008/10/06(月) 12:30:27 ]
- 補:そもそもForthが一般的じゃない
- 463 名前:デフォルトの名無しさん mailto:sage [2008/10/06(月) 21:49:04 ]
- ・リターンスタックが普通のCPUで言うとことの「スタック」。
ワード(Cで言うところの関数、実際にはサブルーチン) を呼ぶと呼び出し戻るためのアドレスを積む。 # 普通のCPUでCALL命令(68系だとBSR、JSR)を実行すると # リターンアドレスがスタックに積まれるのは理解しているよね? ・データスタックってのは、言ってみれば「無限に増えるアキュムレータ」って感じ。 ・「辞書」が命令コードストレージ、C言語でいえばTEXTセグメント Forthの本質は上記3点をおさえて置けば理解できるんだが。 BPがリターンスタックと等価なんて言ってる人とか、 >・リターンスタック: 実行する命令列(辞書で展開された単語含む) >リターンスタックというよりもオーダースタックといった方がちょうど良い気がするけどね なんて言っている人、本当に理解できてるの?
- 464 名前:デフォルトの名無しさん mailto:sage [2008/10/07(火) 00:25:52 ]
- >463
いや、別にWORDがサブルーチンである必要はないんじゃない?WORD毎の環境要らないんだし。 Cとの相性を考えるとサブルーチンにした方が良いと思うけど。 あと、CPUのアーキテクチャには疎いんだけど、最近のCPUでスタック持ってるのってあったっけ?
- 465 名前:デフォルトの名無しさん mailto:sage [2008/10/07(火) 06:15:51 ]
- x86アーキテクチャには思いっきりスタックポインタがありますが?
>>464のいう「最近のCPU」が非ノイマンアーキテクチャとかを指すなら スタックがないCPUもあるかも知れないけど。
- 466 名前:デフォルトの名無しさん mailto:sage [2008/10/07(火) 06:37:45 ]
- >>464
前半は実装と仕様が混乱してそう。 後半は、たぶん、CPUの「レジスタアーキテクチャ」「スタックアーキテクチャ」と データ構造としてのスタックを混同している。 Wikipediaやblog読んで理解した気にならないで実際に自分で手を動かしてみなよ。 ちょっと恥ずかし過ぎるぞ、あんた。
- 467 名前:デフォルトの名無しさん mailto:sage [2008/10/07(火) 12:34:16 ]
- >>464 の言ってる「スタック」はハードウェアスタックのことと思われる。
>>463 の 「データスタックってのは、言ってみれば「無限に増えるアキュムレータ」って感じ。」 ってのは、確かにハードウェアスタックを思わせる記述だが。
- 468 名前:デフォルトの名無しさん mailto:sage [2008/10/07(火) 13:28:27 ]
- post,preのincやdec付きレジスタ間接参照命令があればデータスタックと等価だよね?
リターンスタックってのはサブルーチンコール時に戻りアドレスをpushする為のレジスタの事でしょう? なら今時のCPUで無い物の方が珍しいと思うんだけど
- 469 名前:デフォルトの名無しさん mailto:sage [2008/10/07(火) 20:49:02 ]
- x86って俺の生まれる前からあるな。
定年過ぎた方には最近なんでしょうけど。
- 470 名前:デフォルトの名無しさん mailto:sage [2008/10/07(火) 21:09:44 ]
- 定年過ぎて無く立ってプロセッサ自体30年の歴史しかないじゃないか
- 471 名前:デフォルトの名無しさん mailto:sage [2008/10/07(火) 21:36:31 ]
- 最近のCPUは古いアーキテクチャのものがほとんどだよね。
細かいところは違うんだろが。 >>468 >戻りアドレスをpushする為のレジスタ レジストリって意味? RISCだと、戻りアドレスを保存するレジスタがあること多いよね。 まあ、リターンスタックは、 リターンアドレスを積むため専用(原則)のスタック ってことがわかれば、いいじゃない。 データスタックと別にある利点もわかってるわけでしょ。 本当は「リターンスタックがあること」じゃなくて、 データスタックが複数のワードを横断して固定されていること、 の方が特徴だよね。 普通の言語の実装だと、 データスタックがサブルーチンごとに別々にリターンスタックの中にあって、 受け渡すデータはコピーする、 という感じなわけだ。比喩的に言えば。 アセンブリレベルでもリターンアドレスのpush/popが自動になってるなら、 気付かない人がいてもしょうがない。
- 472 名前:464 mailto:sage [2008/10/07(火) 23:32:13 ]
- >465
いや、スタックポインタ(レジスタ)じゃなくてスタック。>467 の通りですな。>463で『アドレスを積む』とか 書いているからHWスタックのことかと思った。 スタックを内部に持つCPUの話があった記憶があったので勘違いしたわ。すまんね。 forthあんまり詳しくないんで済まんのだけど、『リターンスタックには、ワードを呼ぶと呼び出し戻るため のアドレスを積む』んだっけ? 正規化の観点からは『まだ実行していないWORD』もリターンスタックに積めた方が便利だと思うけど。 WORDコンパイルの実装で手が抜けなくなるし……
- 473 名前:デフォルトの名無しさん mailto:sage [2008/10/07(火) 23:56:37 ]
- >>472
意味が理解できん。 「まだ実行してないWord」を積む、って具体的に何を積むの? まだ実行してないワードのアドレスなら辞書に入ってると思う(関節スレッディングの場合)
- 474 名前:デフォルトの名無しさん mailto:sage [2008/10/08(水) 04:22:01 ]
- >>469
いまでも現役バリバリで使われていて マイクロソフトの最新OS「VISTA」がポーティングされる x86アーキテクチャが「最近のCPU」では無いとでも? あるいはCore2DUOとかがX86アーキテクチャじゃないとでも思ってる?
- 475 名前:デフォルトの名無しさん mailto:sage [2008/10/08(水) 06:31:12 ]
- >>472
Forthと関係なく、関数の呼び出し元に戻るためにアドレスをスタックに積む、 という動作は、アセンブリレベルでは普通の関数呼び出し規約。 Forthは言語レベルでリターンスタックを操作できる言語だけど、 普通は意識しなくてもいいから、リターンアドレスが何のために存在しているのか 理解できない人がいても不思議じゃないけど、せめてもう少し自分で勉強して欲しい。
- 476 名前:デフォルトの名無しさん mailto:sage [2008/10/08(水) 06:35:19 ]
- >forthあんまり詳しくないんで済まんのだけど、
とか、逃げをうたず自分で触ってみろよ。
- 477 名前:デフォルトの名無しさん mailto:sage [2008/10/08(水) 14:37:36 ]
- 441だけど盛り上がってるね。
自分なりのまとめ。 リターンスタックはBPとcall/retの役割がある。 call/retを他の命令で書くと ・関数の呼び出し push $LNEXT jmp func $LNEXT: ・関数のret pop ecx ; $LNEXTのアドレスがecxに入る jmp [ecx] ・関数のはじめ push ebp mov ebp, esp ・関数のおわり mov esp, ebp pop ebp こうなる。 つまりBPはリターンスタックのトップと同じ。 BPを基点にすればデータスタックだけでも同じ事ができる。 「ボクが考えたforth」ではリターンスタックは必要ない。
- 478 名前:デフォルトの名無しさん mailto:sage [2008/10/08(水) 18:17:31 ]
- >>441=477
それを実際に作って発表したら いままで君をバカにしていた連中にギャフンと言わせられるよ。 ガンバ。
- 479 名前:デフォルトの名無しさん mailto:sage [2008/10/08(水) 18:47:05 ]
- で、その「ボクが考えたforth」では、
パラメタはどうやって渡すんだ?
- 480 名前:デフォルトの名無しさん mailto:sage [2008/10/08(水) 19:05:03 ]
- どう考えても普通にCALL/RETした方が速そうだけど
わざわざ面倒くさくしてどうするの? あと、ENTER/LEAVEとか使わないの
- 481 名前:デフォルトの名無しさん mailto:sage [2008/10/08(水) 21:00:40 ]
- >>477
もはやどこから突っ込んで良いものやら… 二つほど疑問が。 一つ目。 >>479も言ってるけれど、その実装だとパラメタの受け渡しが面倒そうなのだが。 たとえば、その実装方法で、 : foo drop drop 3 4 5 ; 1 2 foo としたときにスタックがどのように変化していくのか書いてみてくれ。 解決方法を考えられなくもないが、たぶん独立したリターンスタックが あるほうがシンプルだと思われ。 二つ目。 リターンスタックを操作する命令はどうやって実装するの? これも独立したリターンスタックがあるほうがシンプルだと思われ。 forthじゃない何かをつくろうとしているのだろうか?
- 482 名前:デフォルトの名無しさん mailto:sage [2008/10/08(水) 21:16:43 ]
- 二つ目用の問題も書いておくよ。
: bar 1 2 3 >r >r 1 + r> r> ;
- 483 名前:デフォルトの名無しさん mailto:sage [2008/10/08(水) 23:38:28 ]
- 混乱してるようだから、
まず、ネイティブの場合とスレッディングの場合を分けて考えた方がいい。 ネイティブForthで自然な実装では、 SP=リターンスタックポインタ(RSP) BP=データスタックポインタ(DSP) となってる。 UNIX/Cの普通のスタックを知ってれば、機能的な対応は明瞭なはず。 リターンスタックが伸びても、DSPは別フレームに移らないのがForthのポイント。 ちなみに、Forthでも局所変数が使えるヤツがあって、 その局所変数には、リタースタック中にフレームを作って割り当てるのが普通。 これも、標準のスタックがわかってれば意味は明瞭。 スレッディング(直接・間接)方式だと、 呼出しはCallじゃないから、 BPをRSPにしてもかまわんが、 パラメタとリターンアドレスの混合は、 Forthでは無謀。動的にチェックが必要な上に、完璧にはできそうにない。
- 484 名前:464 mailto:sage [2008/10/09(木) 01:15:39 ]
- 446です。
forthは興味半分で使ったレベルでしかないですね…… concatenative俺言語の設計の参考にしているぐらいです。 >473 リターンスタックを「次に実行する命令の列」という形に抽象化すると、「現在処理中のWORD」と 「ソースコードを解釈したWORD」「Dictionaryに保持されているWORD列」…つまり呼び出されて いないWORDを対称(等価/交換可能)に扱うことができるようになるので、バーチャルマシンの 構造を簡単化することができるかと思います。 ……forthで許されているのかしらんけど。
- 485 名前:デフォルトの名無しさん mailto:sage [2008/10/09(木) 06:24:10 ]
- リターンスタックに積んであるリターンアドレスは、
「これから実行される命令列」へのポインタそのものと見なせるから、 そのアイデアが新しいとは思えないけどな。 Forthぐらいバーチャルマシンの実装が簡単な言語もないし。 ただ、リターンスタックの意味がよくわからないままに、 他の言語のように抽象構文木を再帰的に処理するような 実装にしていると、リターンスタック操作の実装で悩むの かもしれない。
- 486 名前:464 mailto:sage [2008/10/09(木) 08:54:40 ]
- >485
>463は呼び出したWORDを積むことを前提にしているし、>451 >472で言ってるのが >463 >473で 思い切り否定されてるので、forthじゃそういう考え方無いのかな、と思った。 もしforthでもそういう使い方しているんだったらおいらの不勉強だね。
- 487 名前:デフォルトの名無しさん mailto:sage [2008/10/09(木) 10:46:32 ]
- >>486
485のいってる意味は、 スレッディング方式のforthでは、 辞書は実行されるワードのポインタのリストとみなせるわけで、 リターンアドレスというのは、辞書内への戻りアドレス、 つまり、これから実行されるワードのリストへのポインタといえる ということと思われる。 ワードのポインタを直接リターンスタックに積み込むような、 インストラクションキャッシュみたいな仕様のリターンスタックの実装は、 ちょっと聞いたことが無い。 というかそれじゃリターンスタックじゃない。
- 488 名前:デフォルトの名無しさん mailto:sage [2008/10/09(木) 20:52:04 ]
- 487の言わんとすることを俺なりに解釈してみる…
: foo dup + ; : bar foo drop ; bar の処理中に foo を実行するときに、 foo の次の drop のアドレスをリターンスタックに積む。 それで、foo の実行終了時にリターンアドレスから戻り先を取る。 これが、さっき積んだ drop のアドレスということ。 で、「drop のアドレス」っていうのを「ポインタ」と呼んでいる。
- 489 名前:デフォルトの名無しさん mailto:sage [2008/10/09(木) 21:08:57 ]
- fooが呼ばれたときのリターンアドレスは 「dropのアドレス」というより
「dropの直前のアドレス」だ。 微妙なニュアンスに聞こえるかもしれないが。 : bar foo ( ここ ) drop ; ( ここ ) と書いた部分に戻ってくる。
- 490 名前:デフォルトの名無しさん mailto:sage [2008/10/09(木) 21:12:38 ]
- : foo dup + ;
: bar dup * ; : baz foo ( ここ ) bar ( そこ ) ; foo が呼ばれたときリターンスタックには( ここ )が積まれてる。 bar が呼ばれたときリターンスタックには( そこ )が積まれてる。 bar というワード自身がリターンスタックに積まれているのではない。
- 491 名前:デフォルトの名無しさん mailto:sage [2008/10/09(木) 21:16:04 ]
- ついでに >>56 のリターンスタックを使ったパズルの説明でも書いておこう。
問題は、 : foo twice ." Hello" ; で、 HelloHello を出力する twice を定義しろというパズル。
- 492 名前:デフォルトの名無しさん mailto:sage [2008/10/09(木) 21:22:30 ]
- 解答は、
: twice r> dup >r >r ; 何が起きているか説明すると、twice が呼ばれたとき、リターンスタックには、 : foo twice ( ここ ) ." Hello" ; 上の( ここ )が積まれている。 twice は最初に r> を実行して、( ここ ) をリターンスタックからデータスタックに移している。 次の dup で ( ここ ) がデータスタックに二つ積まれた状態になる。 最後に、 二つの >r で ( ここ ) が二つリターンスタックに戻される。
- 493 名前:デフォルトの名無しさん mailto:sage [2008/10/09(木) 21:27:12 ]
- さて、定義されたワードの終端に到達したので Forthは、
リターンスタックからリターンアドレスを一つ取り出してそこに戻ろうとする。 : foo twice ( ここ ) ." Hello" ; ↑これの ( ここ )に戻ってくるわけだね。 そして、Helloを出力する。 そしてまた定義されたワードの終端に到達するので、Forth は リターンスタックからリターンアドレスを一つ取り出してそこに戻ろうとするわけだ。 つまり、もう一度 ( ここ ) に戻る。 もう一度、Helloが出力されたら、次にリターンスタックからpopされる リターンアドレスは foo を呼び出したアドレスなので、ここでようやく、 foo の実行が終了することになる。
- 494 名前:デフォルトの名無しさん mailto:sage [2008/10/09(木) 21:29:45 ]
- リターンスタックに積まれているリターンアドレスは、
次に実行すべきワード単体ではなくて、 それ以降、実行すべきコード全体の先頭を指し示すアドレスだ、 と、理解できたかしらん?
- 495 名前:488 mailto:sage [2008/10/10(金) 00:34:56 ]
- (ここ) は分かってるつもりなんですが、
メモリアドレス的に的確に伝えるには難しいような気が。。。 : baz foo ( ここ ) bar ( そこ ) ; 16bitアドレス環境として、スレデッドコードで考えると、 (ここ)は foo のアドレスと同じか、それとも +1 でしょうか? # foo のアドレス +2 すると bar のアドレスですよね なんかアホなこと言っているようですみません。
- 496 名前:デフォルトの名無しさん mailto:sage [2008/10/10(金) 00:55:01 ]
- >>495
「barのアドレス」と書くとbazの定義の中のbarの呼び出しのあるアドレスなのか、 それともbar自身の定義のアドレスなのか混乱するから、 ( ここ ) と表現したわけで、その違いがわかってるなら問題ないですよん。 あとポインタってわかるよね?
- 497 名前:デフォルトの名無しさん mailto:sage [2008/10/10(金) 01:03:18 ]
- >>495
その言い方で言えば、(ここ)はbarのアドレスですね。 正確には、bazの定義の中のbarのアドレス。 >>490 での例を少し補って、 : foo dup + ; : bar ( あっち ) dup * ; : baz foo ( ここ ) bar ( そこ ) ; と書けば、「barというワード自身」というのは( あっち )のことになる。
- 498 名前:496 mailto:sage [2008/10/10(金) 01:20:54 ]
- >>497
補足ありがとう。 >>486の書き込みの問題点を考えてみると、Forthのリターンスタックは、 明らかに「WORDを積」んではいない。 WORDを積むという表現で想起されるのは、>>497の( あっち ) を積むという ことだとForth使いは受け取るだろうから。 そして ( ここ ) や ( そこ ) は明らかに>>484の「次に実行する命令の列」を 指し示しているわけなので、何が新しいのかよくわからない、という感想に なるのだと思う。
- 499 名前:464 mailto:sage [2008/10/10(金) 01:36:27 ]
- >498
新しいかどうかなんて知らんよ。単にWORDの扱いを正規化できてVMが簡素になるっつうだけの話。 >497で言及している(ここ)(そこ)みたいな間接ポインタをVMで扱う必要も無くなるし。 まあ、その皺寄せをWORDに押し込んでるだけなんだけどね。
- 500 名前:496 mailto:sage [2008/10/10(金) 01:42:51 ]
- >>499
なんていうか… 「(ここ)(そこ)みたいな間接ポインタ」というそれそのものが、 アセンブリ言語の時代からある「リターンアドレス」という概念なんですよ…。 Forthはそれをリターンスタックに分離して保存・復帰しているだけのこと。
- 501 名前:デフォルトの名無しさん mailto:sage [2008/10/10(金) 06:35:09 ]
- >>491
>そして、Helloを出力する。 . "Hello" がなんでHelloを出力することになるの? "Hello" . じゃないのはなんで? 文字列リテラルは特別扱い?
- 502 名前:デフォルトの名無しさん mailto:sage [2008/10/10(金) 08:32:35 ]
- >500
今は実際のリターンアドレスの話をしとらんよ。 リターンスタックを「次に実行する命令の列」という形に抽象化するっつうとるだろうに。
- 503 名前:デフォルトの名無しさん mailto:sage [2008/10/10(金) 08:46:05 ]
- >>501
." とか、 前付きの " は、Forthではただの引用符じゃなくて、一つのワード。 だから、Helloとの間に空白が要る。 但し、終わりの " はセパレーターだから、空白なしで良い。 前にも出てたけど、 Forthでは文字列リテラルはポインタと長さの二つの数値で表す。 「.」は、トップアイテムを一つpopして値をプリントするワードだから、 " Hello" . だと5がプリントされるだけ。文字列ポインタがスタックに残る。 「."」 が 「次の " までの文字列をプリントする」というワード。 文字列をスタックに積んだときは " Hello" type とやる。
- 504 名前:デフォルトの名無しさん mailto:sage [2008/10/10(金) 08:52:55 ]
- >>502
だから、「次に実行する命令列」は辞書の中に既にあるんであって、 それはスタックである必要はなくて、いってみればアレイ。 辞書の中で実行は動的に行ったり戻ったりするから、 やっぱりリターンアドレスの保存は必要。
- 505 名前:デフォルトの名無しさん mailto:sage [2008/10/10(金) 09:06:11 ]
- >>503
>「."」 が 「次の " までの文字列をプリントする」というワード。 なんじゃそら ワロタ
- 506 名前:デフォルトの名無しさん mailto:sage [2008/10/10(金) 17:24:55 ]
- factorだと文字列リテラルはあるよ
- 507 名前:488 mailto:sage [2008/10/10(金) 22:08:31 ]
- >>496,497 サンクス
スレデッドコードと書いておいて誤解がなかったようだ。 497 のレスだと、俺の中では「次のワード」という認識になる。 (あっち)という表現を使えば確かに誤解はなくなる。 なんだか、リターンスタックのデータ内容と、 (サブルーチン)リターンアドレスを混同した希ガス
- 508 名前:464 mailto:sage [2008/10/11(土) 00:37:41 ]
- >504
「必要がないから積まない」じゃなくて、「VMの原理を簡単にするために積む」んだって。 VMが辞書の中を行ったり来たりしないようにするのが目的。 もちろん、VMの仕事をWORDに移管しただけの話だし、スタックが大きくなるデメリットもあるけどな。
- 509 名前:504 mailto:sage [2008/10/11(土) 01:03:24 ]
- >>508
つまり、ワードを全部インラインにするということ? それなら確かに理論的には可能だし、リターンスタック自体要らない。 普通は、大きくなるのはスタックじゃなくて辞書だな。 まあ、辞書からインラインで展開したものを リターンスタックにコピーしてもいいけど、 ランタイムにやるなら相当動作が遅くなると思う。 それに、 なぜそのためにスタックというデータ構造を使うのかがわからない。 後ろから先に積んでいくことになるわけだが。 その発想はインストラクションキャッシュだと思う。 だから、むしろキューがいいと思う。 ソフトウェア的にやると相当遅いとは思うけど、 論理的には可能だと思うよ。
- 510 名前:デフォルトの名無しさん mailto:sage [2008/10/11(土) 02:00:15 ]
- サンクス >693
5 ソースコード 6 boost::spirit というので激しく不安になるな。 というか、スクリプトの入門というのなら、BASICタイプ言語の作成とかCタイプ言語の作成 とか分散しないで、どっちか一つに集中すべきじゃない? 入門だったら、むしろ構文はシンプルなforthライクにして、エンジンの中身に拘るべきだと思うけど……
- 511 名前:デフォルトの名無しさん mailto:sage [2008/10/11(土) 02:02:28 ]
- 誤爆スマソ
- 512 名前:464 mailto:sage [2008/10/11(土) 02:18:22 ]
- >509
いや、基本はWORD呼び出し時に展開(そのWORDに定義されたWORD列をスタックに押し込む)。 WORDコンパイル時に全部インラインに展開するわけじゃないです。 #高速化を目的として、WORDコンパイル時にある程度はインライン化することになると思うけど。 WORDに定義されたWORD列を、実行時にその場で積んでその場で処理する必要があるから、 FIFOの仕組みが必要になります。 まあ、小まめにWORDの積み降ろしをやらなきゃいけないから、確かに重そうだけどね。
- 513 名前:デフォルトの名無しさん mailto:sage [2008/10/11(土) 05:37:05 ]
- 464のやり方は、ありえなくはないけどForth的じゃないね。
どっちかっていうとJava VMのJITコンパイラみたいな。 Forthはシンプルな実装で軽い、ってイメージ。
- 514 名前:デフォルトの名無しさん mailto:sage [2008/10/11(土) 06:54:12 ]
- >>464のやり方だと実行の度にリターンスタックに命令列のコピーが発生するわけだな。
対して普通のForthはリターンアドレス一つのコピーで済む。 Forthでは関数の戻り場所を実行時に入れ替えたりできる( >>59, >>62 ) わけだけど、 >>464のやり方だと命令列自体の入れ替えになるから相当面倒。 Forthの自由度をわざわざ減らしている気がするんだけどな。 でも作るというならがんがれ。 様々な進化があってこそ発展もある。
- 515 名前:464 mailto:sage [2008/10/11(土) 13:07:00 ]
- >513
いや、実装はこっちの方がシンプルだよ。辞書の解釈を全部WORDに押し付けることができるから。 ただ、スタック操作が増えるから重くなる方向だけどね。 >514 リターンアドレス前提だと難しいよね。作業用スタックがもう一本ありゃいいんだけど。 俺言語のVMだと自前スタックで実装しているので大した話じゃないです。
- 516 名前:464 mailto:sage [2008/10/11(土) 13:22:12 ]
- >514
ちょっと補足。 複数のWORDを押し込もうとすると確かに面倒だね。 俺言語でも 1. 無名WORDを作る 2. 1.のWORDに実行するWORDを押し込む 3. 1.のWORDをリターンスタックに押し込む といったパック化が必要になります。
- 517 名前:デフォルトの名無しさん mailto:sage [2008/10/11(土) 13:26:05 ]
- 464のVMだが、
ハードウェアレベルではもう一般化してる インストラクションのプリフェッチとおなじだよね。 マシン語のデコーダレベルでのVMという感じか。 実装する場合の最難題は条件付きジャンプだと思う。 IFとか不定ループをどう載せるかが鍵だな。 これを考えると、VMが仕組みとして単純になるかどうかは微妙だと思う。 まあ、ベタでやればできそうな気はするが、 ハードウエアの仕組みをソフトウェアで二重にしてるだけのような気がしないでもない。
- 518 名前:464 mailto:sage [2008/10/11(土) 13:38:04 ]
- >514
思い出した……>59を実現するにはreverse自体のパック化も必須なんだっけ。 そういや>59みたいな操作をどうしようか悩んだな。 ただ、こういったWORDを跨ぐ暗黙的なリターンスタック制御てけっこう危険じゃない? 個人的にはWORDはデータスタックの状態にのみ依存すべきだと思うけど、WORDを越えた 範囲までリターンスタックを操作できるようにすると、WORD同士の依存関係が出てしまって 連鎖性(concatenative)が崩れるような気がする。 forthの条件分岐でも、セパレーターを使った明示的な制御をしているわけだし。
- 519 名前:464 mailto:sage [2008/10/11(土) 13:49:31 ]
- 連投スマソ
>517 そうか、CPUだともう一般的なのか……。さすがに天才的な変態が集まる業界だな。 やっぱりCPUのアーキテクチャ勉強しないといけないなあ。 IFは構文解析で逃げました。 block := block ? WORD1 ! WORD2 という三項演算子を用意して、条件分岐用WORDに解釈するようにしました。 不定ループの構文を用意するかどうかは検討中です。
- 520 名前:517 mailto:sage [2008/10/11(土) 13:59:32 ]
- もうすこし考えてみたんだが、
ワードがどこかで他のワードを呼び出し、そのワードがどこかで他のワードを呼出し... という場合には、 ワードシーケンスに展開する段階で、 展開すべき個所をたどるためのリターンスタックが必要な気がする。 だから、464のVMは、 普通のForthでの実行と同じ動作でワード系列をコピーして、 それから順番にInterpretして実行するという感じになって、 単なる二度手間ではないかな。
- 521 名前:464 mailto:sage [2008/10/11(土) 15:30:32 ]
- >520
どのみちリターンスタック(実行する命令列を保存する専用スタック)が必要なのはその通り。 WORDの動作:普通のForthでの実行と同じ動作でワード系列をコピー VMの動作: 順番にInterpretして実行する というところがポイントですな。VMは辞書のこととか考える必要がないのでシンプルになります。 その代わり「辞書からWORD列を拾ってリターンスタックに展開する」というWORDが必要になるけど。 確かにコピーする手間はムダな気もするんだけどね…… 辞書のWORD列を直接トレースするのと比べてどんぐらい余計な手間がかかってるんだろう? ポインタ操作数回&アクセス数回レベルだと思うけど。
- 522 名前:514 mailto:sage [2008/10/11(土) 18:35:01 ]
- >>518
普通はリターンスタックとか継続とか触れない言語の方が多いから、 Forthではなく俺言語を作るつもりなら、言語デザイナであるお前様自身の 判断で実現可能にしてもいいし、そうでなくしてもいいと思うよ。 ただForthは言語レベルでリターンスタックを操れる結果、協調的マルチタスクやら コルーチンやら言語実装のレベルで普通対処するものも、ライブラリレベルで実現できる柔軟さがある。 リターンスタックは他の言語にはないForthの特徴の一つだからね。 俺言語でなんとか実現する方法を悩んでみるのも楽しいんじゃない?
- 523 名前:514 mailto:sage [2008/10/11(土) 18:47:48 ]
- あとForthのVMって相当シンプルだよ。
アセンブリ言語で書かれた昔のForthとかコアの部分はアセンブリ言語で数行レベルだった気がする。 どのへんが複雑だと思ったのかは興味がある…
- 524 名前:517 mailto:sage [2008/10/11(土) 21:01:10 ]
- >>521
いや、そうではなくて、 「WORDの動作」の中の、「普通のForthと同じ動作で」ってところに、 リターンアドレスを保存するスタックという意味でのリターンスタックが、もう必要なのではないかということ。 あと、言葉の問題として、 大きい意味でのワードを展開する動作のところからもうInterpreter(=VM)の動作というのが普通だと思う。 つまり、VMの動作の前半をWORDの動作と呼んで違う名前にしたから、 残ったVMの動作が簡単に見えるというだけなんじゃないかな。 辞書中のワードから始めると、ForthのVMよりも(多分プリミティブ)WORDの系列を作る部分が余分で、 より複雑になってると思う。 でも、自分の言語を作るのをやめろといってるんじゃないよ。 むしろ応援してる。 ちょっと話題はそれるけど、Forthというか、スタック指向言語は、 コンパイラライターフレンドリーなんだよね。 だから、Forthコード書くよりForth(風オレ言語)VMを書く人が多かったりするわけだが、 ホントはForthでアプリケーションを書くときも「オレ言語」を作るつもりで書くと良いと思ってる。
- 525 名前:デフォルトの名無しさん mailto:sage [2008/10/11(土) 21:33:08 ]
- Forthの用語って独特な言い回しがあるからな。
知らない人は結構混乱する。 スレデッドコードのForthの場合、ソースコードを解釈してスレデッドコードを 生成することをコンパイルといい、スレデッドコードを生成する部分を外部インタープリタ、 スレデッドコードを解釈実行する部分を内部インタープリタと呼ぶ。 (これで良かったよな?同志?) このスレでVMと言った時に内部インタープリタだけなのか、外部インタープリタも含むのか? どっちだろうか?
- 526 名前:デフォルトの名無しさん mailto:sage [2008/10/12(日) 00:45:26 ]
- >>525
テキストを読み込んで、 1) ワードを辞書内で特定 2) だめならリテラルに変換 3) ダメならエラーで終了。 という部分が外部インタープリタ 1)または2)で成功したときに モードに応じてコンパイル(Forth的意味)するか実行する のが内部インタープリタ だと思ってました。 Forthはテキストインプットも弄れるという面白さもあるよね。 Forth VMというと、外部も含むのかな。 上のリターンスタック云々の話は、 内部インタープリタのことだと思うけど。
- 527 名前:デフォルトの名無しさん mailto:sage [2008/10/12(日) 07:57:23 ]
- 内部インタプリタて(スレッドコードで実装してる場合は)nextルーチンのことじゃなかったっけ。
- 528 名前:デフォルトの名無しさん mailto:sage [2008/10/12(日) 08:49:02 ]
- そうNEXTルーチン。アセンブリ言語で数行、という奴。
- 529 名前:464 mailto:sage [2008/10/12(日) 15:10:26 ]
- >522
その辺は「自由と責任」というやつですな。「銃で足をブッとばす自由」でもあるけど。 >どのへんが複雑だと思ったのかは興味がある… 自分でも何でだったっけな、と過去の記憶を探り出してみたけど、 ・実行中のWORDの次のWORDを辞書の中から探せるようにする仕組みが必要 ×実行中のWORDの中身を変更するのが大変(VMのスタックに積んでいるWORD含む) ×番兵などの終了処理が必須 --> VM側のスタックに積むことにすればpop&top参照で正規化できるし、元の値を コピーするからWORD変更にも影響されない。 ・VM側に「WORDを実行する」という手順が必要になる --> VM側のスタックに積むことにすればpushで正規化できる ぐらいかもしれない。 コンパイル時にWORDの中身が確定するforthだとあんまり問題にならなそうだね。
- 530 名前:464 mailto:sage [2008/10/12(日) 15:20:28 ]
- >524
「スタックに複数のデータを押し込む操作は機械語レベルだとアトミックにならない」ということ?? C++で実装しているから意識していなかったけど、そうかもしれないですね。 少なくともプリミティブで実装する必要あるね。 >ForthのVMよりも(多分プリミティブ)WORDの系列を作る部分が余分で、 これは狙ってやっていることだから仕様がないですね。 まあ、俺言語ではVM自体もWORD扱いにしているのですが……
- 531 名前:デフォルトの名無しさん mailto:sage [2008/10/12(日) 15:50:56 ]
- >>529
んー、やっぱり、思い込みでForthを理解したつもりになるんじゃなくて、 本格的に触ってみたほうが良いと思うんだけどな。 >実行中のWORDの次のWORDを辞書の中から探せるようにする仕組みが必要 通常、Forthは実行時には、スレデッドコードにコンパイルされた命令列を、 上にも出ているnextルーチンで辿るだけなので、仕組みというほどの仕組みはないよ。 >実行中のWORDの中身を変更するのが大変(VMのスタックに積んでいるWORD含む) 間接スレッディングのForthだと定義済みのワードの変更は、一カ所ポインタを書き換える だけで済むはず。 >番兵などの終了処理が必須 番兵というかワードの最後にnextルーチンへのジャンプかnextルーチン自身を書き込むだけ。 >VM側に「WORDを実行する」という手順が必要になる スレデッドコードのForthの命令列は、ワードへのポインタが並んでいるだけで、 「WORDを実行する」という意味のインストラクションは必要ないよ。
- 532 名前:464 mailto:sage [2008/10/12(日) 23:25:00 ]
- 本格的に触るのは……あの構文は色々と嫌だ。
[条件] IF [肯定時] ELSE [否定時] THEN とか。 せめて条件算子的だったらなぁ。[条件] ? [肯定時] : [否定時] ; >531 細かいことを言うと、nextルーチンが辞書内のスレッデッドコード構造の詳細を知らなきゃ ならないので、VMと辞書の関連が密になりそうな気がします。スレッデッドコードをスタックに pushしてVM内に取り込んじゃえば辞書内の構造を気にする必要無いし。 まあ、最適化のために作り込んでも良い気がするけどね。そこは将来の課題ということで。 >一カ所ポインタを書き換えるだけで済むはず。 WORD自体を置換する場合はそうですね。WORDの挿入や削除はたぶん難しいかと。 そんな特殊なことは禁止にして、新規にWORD定義させた方が良いかも知れないけど。 あるいは無名WORDとかスキップWORDを用意するとか。 >「WORDを実行する」という意味のインストラクションは必要ないよ。 あれ?VMに保存されている「現在実行中のWORD」って、間接ポインタじゃないの? (nextの動作を考えると、間接ポインタじゃないと色々と面倒臭そうな) 実行前に間接参照からWORDを探す操作が一段余計に必要になるかと思ってた。
- 533 名前:デフォルトの名無しさん mailto:sage [2008/10/12(日) 23:34:45 ]
- >VMと辞書の関連が密
というか、それがFORTHの肝のような気がする。
- 534 名前:デフォルトの名無しさん mailto:sage [2008/10/13(月) 00:16:22 ]
- スレデッドコード自体、ワードへのポインタを並べたものでしかないから、
ジャンプとかコールとかそういう類のインストラクションをデコードする必要がない、 という意味ね。 あとForthの実装にはダイレクトスレデッドなものもあるよ。 nextルーチンからみると命令列を順に辿ってるだけであって、 「辞書からワードを毎回探している」ってわけじゃないしね。 それより、スタックに命令列を毎回pushするオーバーヘッドのほうがよほど大きいと思うし、 nextルーチンに比べてシンプルとも思えないんだな。 ま、いろいろ悩んで勉強して、これだ!と思える言語デザインに邁進してください、と。 このスレが本当に久しぶりに活性化したのは間違いないしね。
- 535 名前:デフォルトの名無しさん mailto:sage [2008/10/13(月) 00:21:58 ]
- >>533
間接スレデッドの場合、Forthコンソールの側から見ると、 逆コンパイルしやすかったり、便利な面はたしかにあるけれど、 VMつうかnextルーチンから見ると、単にポインタを辿っているだけなので、 構造として、VM実装と辞書構造が密、というわけでもないと思う。 実際VM実装テクニックとしてのスレデッドコードは、今や、Forth以外でも 当たり前の技術になってるし。
- 536 名前:デフォルトの名無しさん mailto:sage [2008/10/27(月) 00:52:54 ]
- jonesforth読んだ。
ソース付きなので理解しやすい。 OS Xで動かそうとしたが挫折した。 OSXのGASではマクロが対応してないみたいだ。
- 537 名前:デフォルトの名無しさん mailto:sage [2008/11/23(日) 01:13:24 ]
- 急にスレが進んだと思ったら、止まるのも急だよなこのスレ
やっぱ誰も使ってないってこったな
- 538 名前:デフォルトの名無しさん mailto:sage [2008/11/26(水) 17:30:54 ]
- ttp://www.intellasys.net/index.php?option=com_frontpage&Itemid=64
なんか並列forthマシンっぽいw
- 539 名前:デフォルトの名無しさん mailto:sage [2008/12/27(土) 14:00:32 ]
- factor使ってる奴いる?
- 540 名前:デフォルトの名無しさん mailto:sage [2008/12/27(土) 21:13:14 ]
- とりあえず入れてみたけど特に使ってないなw
- 541 名前:539 mailto:sage [2008/12/28(日) 01:26:48 ]
- factorおもしろいぜ。デプロイするとスタンドアロンで動く物もできるし。
- 542 名前:デフォルトの名無しさん mailto:sage [2008/12/29(月) 13:31:00 ]
- やっぱだめだこの言語。
人間工学から著しく反してる。
- 543 名前:デフォルトの名無しさん mailto:sage [2008/12/29(月) 19:52:22 ]
- サルが人間工学語ってやがる。
- 544 名前:デフォルトの名無しさん mailto:sage [2008/12/29(月) 21:45:56 ]
- 自分の思考をスタック処理に最適化させればいいんだよw
- 545 名前:デフォルトの名無しさん mailto:sage [2008/12/29(月) 22:06:52 ]
- forthに慣れるのはそんなに大変なことじゃないと思うけどなあ。
まあ、問題をごく単純な部分に細分して考えることができないと、 スタック処理が爆発しがちになるとはいえますね。 でも、問題の細分ができない人は、どの言語でプログラミングしても たかが知れてる。
- 546 名前:デフォルトの名無しさん mailto:sage [2009/01/01(木) 11:45:56 ]
- Lispのマクロ的なことができるってほんと?
- 547 名前:デフォルトの名無しさん mailto:sage [2009/01/01(木) 11:56:23 ]
- イミディエイトなワードのことかな。
結果としては似たようなことができると言えなくもないけど、 Lispのマクロみたいな2度evalするみたいな高水準のものじゃありません。
- 548 名前:デフォルトの名無しさん mailto:sage [2009/01/07(水) 22:44:24 ]
- つまり・・・どういうことだってばよ?
- 549 名前:デフォルトの名無しさん mailto:sage [2009/01/07(水) 23:39:44 ]
- factorならlispのマクロと同じようなことができるよ
- 550 名前:デフォルトの名無しさん mailto:sage [2009/01/08(木) 00:11:19 ]
- 同じ機能を達成できるとしても言語が違えばそこに至るロジックは異なる。
具体的に何がしたいのか特定しないと。 factorはおもしろい言語だが、関数型言語のフリし過ぎなのがイヤラシくもある。
- 551 名前:デフォルトの名無しさん mailto:sage [2009/01/09(金) 12:30:14 ]
- 何かサンプルが欲しいな。
- 552 名前:デフォルトの名無しさん mailto:sage [2009/01/09(金) 22:47:55 ]
- ancient.s6.xrea.com/factor/cookbook.html
- 553 名前:デフォルトの名無しさん [2009/02/26(木) 00:17:58 ]
- 組み込み用FORTH検討中・・・
- 554 名前:デフォルトの名無しさん mailto:sage [2009/03/07(土) 05:11:31 ]
- part 1 の URL ってないの?
- 555 名前:デフォルトの名無しさん mailto:sage [2009/03/07(土) 10:00:54 ]
- piza.2ch.net/tech/kako/987/987562311.html
- 556 名前:デフォルトの名無しさん mailto:sage [2009/03/07(土) 10:13:20 ]
- : Mops ( オブジェクト指向FORTH -- ) ;
pc.2ch.net/tech/kako/1000/10001/1000118518.html
- 557 名前:デフォルトの名無しさん mailto:sage [2009/03/07(土) 13:25:33 ]
- thanks
- 558 名前:デフォルトの名無しさん mailto:sage [2009/03/07(土) 18:54:17 ]
- このスレも長いね
- 559 名前:デフォルトの名無しさん mailto:sage [2009/03/07(土) 21:43:31 ]
- factorとかJoyとか触ってる奴いないのかよ
- 560 名前:デフォルトの名無しさん mailto:sage [2009/03/07(土) 23:32:50 ]
- 普通の関数型言語に比べてどういうメリットがあるのか分からない。
- 561 名前:デフォルトの名無しさん mailto:sage [2009/03/08(日) 10:51:09 ]
- forthは関数型ちゃうし
- 562 名前:デフォルトの名無しさん mailto:sage [2009/03/08(日) 12:22:51 ]
- >>560はなんでこのスレにいるんだ?
- 563 名前:デフォルトの名無しさん mailto:sage [2009/03/08(日) 19:52:03 ]
- いや、factorがって事なんだが。
- 564 名前:デフォルトの名無しさん mailto:sage [2009/03/08(日) 20:01:58 ]
- なんで関数型言語と比較するんだ?
Factor = forth + 無名関数とオブジェクト指向だよ
- 565 名前:デフォルトの名無しさん mailto:sage [2009/03/19(木) 13:57:45 ]
- 全然Forthと関係ない話だが、AMDのシニアアーキテクトが
チャック・ムーアって名前なのは結構心臓に悪いな。
|

|