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