2 part forth
1デフォルトの名無しさん
NGNG 第四世代
463デフォルトの名無しさん
2008/10/06(月) 21:49:04 ・リターンスタックが普通のCPUで言うとことの「スタック」。
ワード(Cで言うところの関数、実際にはサブルーチン)
を呼ぶと呼び出し戻るためのアドレスを積む。
# 普通のCPUでCALL命令(68系だとBSR、JSR)を実行すると
# リターンアドレスがスタックに積まれるのは理解しているよね?
・データスタックってのは、言ってみれば「無限に増えるアキュムレータ」って感じ。
・「辞書」が命令コードストレージ、C言語でいえばTEXTセグメント
Forthの本質は上記3点をおさえて置けば理解できるんだが。
BPがリターンスタックと等価なんて言ってる人とか、
>・リターンスタック: 実行する命令列(辞書で展開された単語含む)
>リターンスタックというよりもオーダースタックといった方がちょうど良い気がするけどね
なんて言っている人、本当に理解できてるの?
ワード(Cで言うところの関数、実際にはサブルーチン)
を呼ぶと呼び出し戻るためのアドレスを積む。
# 普通のCPUでCALL命令(68系だとBSR、JSR)を実行すると
# リターンアドレスがスタックに積まれるのは理解しているよね?
・データスタックってのは、言ってみれば「無限に増えるアキュムレータ」って感じ。
・「辞書」が命令コードストレージ、C言語でいえばTEXTセグメント
Forthの本質は上記3点をおさえて置けば理解できるんだが。
BPがリターンスタックと等価なんて言ってる人とか、
>・リターンスタック: 実行する命令列(辞書で展開された単語含む)
>リターンスタックというよりもオーダースタックといった方がちょうど良い気がするけどね
なんて言っている人、本当に理解できてるの?
464デフォルトの名無しさん
2008/10/07(火) 00:25:52 >463
いや、別にWORDがサブルーチンである必要はないんじゃない?WORD毎の環境要らないんだし。
Cとの相性を考えるとサブルーチンにした方が良いと思うけど。
あと、CPUのアーキテクチャには疎いんだけど、最近のCPUでスタック持ってるのってあったっけ?
いや、別にWORDがサブルーチンである必要はないんじゃない?WORD毎の環境要らないんだし。
Cとの相性を考えるとサブルーチンにした方が良いと思うけど。
あと、CPUのアーキテクチャには疎いんだけど、最近のCPUでスタック持ってるのってあったっけ?
465デフォルトの名無しさん
2008/10/07(火) 06:15:51466デフォルトの名無しさん
2008/10/07(火) 06:37:45 >>464
前半は実装と仕様が混乱してそう。
後半は、たぶん、CPUの「レジスタアーキテクチャ」「スタックアーキテクチャ」と
データ構造としてのスタックを混同している。
Wikipediaやblog読んで理解した気にならないで実際に自分で手を動かしてみなよ。
ちょっと恥ずかし過ぎるぞ、あんた。
前半は実装と仕様が混乱してそう。
後半は、たぶん、CPUの「レジスタアーキテクチャ」「スタックアーキテクチャ」と
データ構造としてのスタックを混同している。
Wikipediaやblog読んで理解した気にならないで実際に自分で手を動かしてみなよ。
ちょっと恥ずかし過ぎるぞ、あんた。
467デフォルトの名無しさん
2008/10/07(火) 12:34:16468デフォルトの名無しさん
2008/10/07(火) 13:28:27 post,preのincやdec付きレジスタ間接参照命令があればデータスタックと等価だよね?
リターンスタックってのはサブルーチンコール時に戻りアドレスをpushする為のレジスタの事でしょう?
なら今時のCPUで無い物の方が珍しいと思うんだけど
リターンスタックってのはサブルーチンコール時に戻りアドレスをpushする為のレジスタの事でしょう?
なら今時のCPUで無い物の方が珍しいと思うんだけど
469デフォルトの名無しさん
2008/10/07(火) 20:49:02 x86って俺の生まれる前からあるな。
定年過ぎた方には最近なんでしょうけど。
定年過ぎた方には最近なんでしょうけど。
470デフォルトの名無しさん
2008/10/07(火) 21:09:44 定年過ぎて無く立ってプロセッサ自体30年の歴史しかないじゃないか
471デフォルトの名無しさん
2008/10/07(火) 21:36:31 最近のCPUは古いアーキテクチャのものがほとんどだよね。
細かいところは違うんだろが。
>>468
>戻りアドレスをpushする為のレジスタ
レジストリって意味?
RISCだと、戻りアドレスを保存するレジスタがあること多いよね。
まあ、リターンスタックは、
リターンアドレスを積むため専用(原則)のスタック
ってことがわかれば、いいじゃない。
データスタックと別にある利点もわかってるわけでしょ。
本当は「リターンスタックがあること」じゃなくて、
データスタックが複数のワードを横断して固定されていること、
の方が特徴だよね。
普通の言語の実装だと、
データスタックがサブルーチンごとに別々にリターンスタックの中にあって、
受け渡すデータはコピーする、
という感じなわけだ。比喩的に言えば。
アセンブリレベルでもリターンアドレスのpush/popが自動になってるなら、
気付かない人がいてもしょうがない。
細かいところは違うんだろが。
>>468
>戻りアドレスをpushする為のレジスタ
レジストリって意味?
RISCだと、戻りアドレスを保存するレジスタがあること多いよね。
まあ、リターンスタックは、
リターンアドレスを積むため専用(原則)のスタック
ってことがわかれば、いいじゃない。
データスタックと別にある利点もわかってるわけでしょ。
本当は「リターンスタックがあること」じゃなくて、
データスタックが複数のワードを横断して固定されていること、
の方が特徴だよね。
普通の言語の実装だと、
データスタックがサブルーチンごとに別々にリターンスタックの中にあって、
受け渡すデータはコピーする、
という感じなわけだ。比喩的に言えば。
アセンブリレベルでもリターンアドレスのpush/popが自動になってるなら、
気付かない人がいてもしょうがない。
472464
2008/10/07(火) 23:32:13 >465
いや、スタックポインタ(レジスタ)じゃなくてスタック。>467 の通りですな。>463で『アドレスを積む』とか
書いているからHWスタックのことかと思った。
スタックを内部に持つCPUの話があった記憶があったので勘違いしたわ。すまんね。
forthあんまり詳しくないんで済まんのだけど、『リターンスタックには、ワードを呼ぶと呼び出し戻るため
のアドレスを積む』んだっけ?
正規化の観点からは『まだ実行していないWORD』もリターンスタックに積めた方が便利だと思うけど。
WORDコンパイルの実装で手が抜けなくなるし……
いや、スタックポインタ(レジスタ)じゃなくてスタック。>467 の通りですな。>463で『アドレスを積む』とか
書いているからHWスタックのことかと思った。
スタックを内部に持つCPUの話があった記憶があったので勘違いしたわ。すまんね。
forthあんまり詳しくないんで済まんのだけど、『リターンスタックには、ワードを呼ぶと呼び出し戻るため
のアドレスを積む』んだっけ?
正規化の観点からは『まだ実行していないWORD』もリターンスタックに積めた方が便利だと思うけど。
WORDコンパイルの実装で手が抜けなくなるし……
473デフォルトの名無しさん
2008/10/07(火) 23:56:37474デフォルトの名無しさん
2008/10/08(水) 04:22:01 >>469
いまでも現役バリバリで使われていて
マイクロソフトの最新OS「VISTA」がポーティングされる
x86アーキテクチャが「最近のCPU」では無いとでも?
あるいはCore2DUOとかがX86アーキテクチャじゃないとでも思ってる?
いまでも現役バリバリで使われていて
マイクロソフトの最新OS「VISTA」がポーティングされる
x86アーキテクチャが「最近のCPU」では無いとでも?
あるいはCore2DUOとかがX86アーキテクチャじゃないとでも思ってる?
475デフォルトの名無しさん
2008/10/08(水) 06:31:12 >>472
Forthと関係なく、関数の呼び出し元に戻るためにアドレスをスタックに積む、
という動作は、アセンブリレベルでは普通の関数呼び出し規約。
Forthは言語レベルでリターンスタックを操作できる言語だけど、
普通は意識しなくてもいいから、リターンアドレスが何のために存在しているのか
理解できない人がいても不思議じゃないけど、せめてもう少し自分で勉強して欲しい。
Forthと関係なく、関数の呼び出し元に戻るためにアドレスをスタックに積む、
という動作は、アセンブリレベルでは普通の関数呼び出し規約。
Forthは言語レベルでリターンスタックを操作できる言語だけど、
普通は意識しなくてもいいから、リターンアドレスが何のために存在しているのか
理解できない人がいても不思議じゃないけど、せめてもう少し自分で勉強して欲しい。
476デフォルトの名無しさん
2008/10/08(水) 06:35:19 >forthあんまり詳しくないんで済まんのだけど、
とか、逃げをうたず自分で触ってみろよ。
とか、逃げをうたず自分で触ってみろよ。
477デフォルトの名無しさん
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」ではリターンスタックは必要ない。
自分なりのまとめ。
リターンスタックは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デフォルトの名無しさん
2008/10/08(水) 18:17:31479デフォルトの名無しさん
2008/10/08(水) 18:47:05 で、その「ボクが考えたforth」では、
パラメタはどうやって渡すんだ?
パラメタはどうやって渡すんだ?
480デフォルトの名無しさん
2008/10/08(水) 19:05:03 どう考えても普通にCALL/RETした方が速そうだけど
わざわざ面倒くさくしてどうするの?
あと、ENTER/LEAVEとか使わないの
わざわざ面倒くさくしてどうするの?
あと、ENTER/LEAVEとか使わないの
481デフォルトの名無しさん
2008/10/08(水) 21:00:40 >>477
もはやどこから突っ込んで良いものやら…
二つほど疑問が。
一つ目。
>>479も言ってるけれど、その実装だとパラメタの受け渡しが面倒そうなのだが。
たとえば、その実装方法で、
: foo drop drop 3 4 5 ;
1 2 foo
としたときにスタックがどのように変化していくのか書いてみてくれ。
解決方法を考えられなくもないが、たぶん独立したリターンスタックが
あるほうがシンプルだと思われ。
二つ目。
リターンスタックを操作する命令はどうやって実装するの?
これも独立したリターンスタックがあるほうがシンプルだと思われ。
forthじゃない何かをつくろうとしているのだろうか?
もはやどこから突っ込んで良いものやら…
二つほど疑問が。
一つ目。
>>479も言ってるけれど、その実装だとパラメタの受け渡しが面倒そうなのだが。
たとえば、その実装方法で、
: foo drop drop 3 4 5 ;
1 2 foo
としたときにスタックがどのように変化していくのか書いてみてくれ。
解決方法を考えられなくもないが、たぶん独立したリターンスタックが
あるほうがシンプルだと思われ。
二つ目。
リターンスタックを操作する命令はどうやって実装するの?
これも独立したリターンスタックがあるほうがシンプルだと思われ。
forthじゃない何かをつくろうとしているのだろうか?
482デフォルトの名無しさん
2008/10/08(水) 21:16:43 二つ目用の問題も書いておくよ。
: bar 1 2 3 >r >r 1 + r> r> ;
: bar 1 2 3 >r >r 1 + r> r> ;
483デフォルトの名無しさん
2008/10/08(水) 23:38:28 混乱してるようだから、
まず、ネイティブの場合とスレッディングの場合を分けて考えた方がいい。
ネイティブForthで自然な実装では、
SP=リターンスタックポインタ(RSP)
BP=データスタックポインタ(DSP)
となってる。
UNIX/Cの普通のスタックを知ってれば、機能的な対応は明瞭なはず。
リターンスタックが伸びても、DSPは別フレームに移らないのがForthのポイント。
ちなみに、Forthでも局所変数が使えるヤツがあって、
その局所変数には、リタースタック中にフレームを作って割り当てるのが普通。
これも、標準のスタックがわかってれば意味は明瞭。
スレッディング(直接・間接)方式だと、
呼出しはCallじゃないから、
BPをRSPにしてもかまわんが、
パラメタとリターンアドレスの混合は、
Forthでは無謀。動的にチェックが必要な上に、完璧にはできそうにない。
まず、ネイティブの場合とスレッディングの場合を分けて考えた方がいい。
ネイティブForthで自然な実装では、
SP=リターンスタックポインタ(RSP)
BP=データスタックポインタ(DSP)
となってる。
UNIX/Cの普通のスタックを知ってれば、機能的な対応は明瞭なはず。
リターンスタックが伸びても、DSPは別フレームに移らないのがForthのポイント。
ちなみに、Forthでも局所変数が使えるヤツがあって、
その局所変数には、リタースタック中にフレームを作って割り当てるのが普通。
これも、標準のスタックがわかってれば意味は明瞭。
スレッディング(直接・間接)方式だと、
呼出しはCallじゃないから、
BPをRSPにしてもかまわんが、
パラメタとリターンアドレスの混合は、
Forthでは無謀。動的にチェックが必要な上に、完璧にはできそうにない。
484464
2008/10/09(木) 01:15:39 446です。
forthは興味半分で使ったレベルでしかないですね……
concatenative俺言語の設計の参考にしているぐらいです。
>473
リターンスタックを「次に実行する命令の列」という形に抽象化すると、「現在処理中のWORD」と
「ソースコードを解釈したWORD」「Dictionaryに保持されているWORD列」…つまり呼び出されて
いないWORDを対称(等価/交換可能)に扱うことができるようになるので、バーチャルマシンの
構造を簡単化することができるかと思います。
……forthで許されているのかしらんけど。
forthは興味半分で使ったレベルでしかないですね……
concatenative俺言語の設計の参考にしているぐらいです。
>473
リターンスタックを「次に実行する命令の列」という形に抽象化すると、「現在処理中のWORD」と
「ソースコードを解釈したWORD」「Dictionaryに保持されているWORD列」…つまり呼び出されて
いないWORDを対称(等価/交換可能)に扱うことができるようになるので、バーチャルマシンの
構造を簡単化することができるかと思います。
……forthで許されているのかしらんけど。
485デフォルトの名無しさん
2008/10/09(木) 06:24:10 リターンスタックに積んであるリターンアドレスは、
「これから実行される命令列」へのポインタそのものと見なせるから、
そのアイデアが新しいとは思えないけどな。
Forthぐらいバーチャルマシンの実装が簡単な言語もないし。
ただ、リターンスタックの意味がよくわからないままに、
他の言語のように抽象構文木を再帰的に処理するような
実装にしていると、リターンスタック操作の実装で悩むの
かもしれない。
「これから実行される命令列」へのポインタそのものと見なせるから、
そのアイデアが新しいとは思えないけどな。
Forthぐらいバーチャルマシンの実装が簡単な言語もないし。
ただ、リターンスタックの意味がよくわからないままに、
他の言語のように抽象構文木を再帰的に処理するような
実装にしていると、リターンスタック操作の実装で悩むの
かもしれない。
486464
2008/10/09(木) 08:54:40 >485
>463は呼び出したWORDを積むことを前提にしているし、>451 >472で言ってるのが >463 >473で
思い切り否定されてるので、forthじゃそういう考え方無いのかな、と思った。
もしforthでもそういう使い方しているんだったらおいらの不勉強だね。
>463は呼び出したWORDを積むことを前提にしているし、>451 >472で言ってるのが >463 >473で
思い切り否定されてるので、forthじゃそういう考え方無いのかな、と思った。
もしforthでもそういう使い方しているんだったらおいらの不勉強だね。
487デフォルトの名無しさん
2008/10/09(木) 10:46:32 >>486
485のいってる意味は、
スレッディング方式のforthでは、
辞書は実行されるワードのポインタのリストとみなせるわけで、
リターンアドレスというのは、辞書内への戻りアドレス、
つまり、これから実行されるワードのリストへのポインタといえる
ということと思われる。
ワードのポインタを直接リターンスタックに積み込むような、
インストラクションキャッシュみたいな仕様のリターンスタックの実装は、
ちょっと聞いたことが無い。
というかそれじゃリターンスタックじゃない。
485のいってる意味は、
スレッディング方式のforthでは、
辞書は実行されるワードのポインタのリストとみなせるわけで、
リターンアドレスというのは、辞書内への戻りアドレス、
つまり、これから実行されるワードのリストへのポインタといえる
ということと思われる。
ワードのポインタを直接リターンスタックに積み込むような、
インストラクションキャッシュみたいな仕様のリターンスタックの実装は、
ちょっと聞いたことが無い。
というかそれじゃリターンスタックじゃない。
488デフォルトの名無しさん
2008/10/09(木) 20:52:04 487の言わんとすることを俺なりに解釈してみる…
: foo dup + ;
: bar foo drop ;
bar の処理中に foo を実行するときに、
foo の次の drop のアドレスをリターンスタックに積む。
それで、foo の実行終了時にリターンアドレスから戻り先を取る。
これが、さっき積んだ drop のアドレスということ。
で、「drop のアドレス」っていうのを「ポインタ」と呼んでいる。
: foo dup + ;
: bar foo drop ;
bar の処理中に foo を実行するときに、
foo の次の drop のアドレスをリターンスタックに積む。
それで、foo の実行終了時にリターンアドレスから戻り先を取る。
これが、さっき積んだ drop のアドレスということ。
で、「drop のアドレス」っていうのを「ポインタ」と呼んでいる。
489デフォルトの名無しさん
2008/10/09(木) 21:08:57 fooが呼ばれたときのリターンアドレスは 「dropのアドレス」というより
「dropの直前のアドレス」だ。
微妙なニュアンスに聞こえるかもしれないが。
: bar foo ( ここ ) drop ;
( ここ ) と書いた部分に戻ってくる。
「dropの直前のアドレス」だ。
微妙なニュアンスに聞こえるかもしれないが。
: bar foo ( ここ ) drop ;
( ここ ) と書いた部分に戻ってくる。
490デフォルトの名無しさん
2008/10/09(木) 21:12:38 : foo dup + ;
: bar dup * ;
: baz foo ( ここ ) bar ( そこ ) ;
foo が呼ばれたときリターンスタックには( ここ )が積まれてる。
bar が呼ばれたときリターンスタックには( そこ )が積まれてる。
bar というワード自身がリターンスタックに積まれているのではない。
: bar dup * ;
: baz foo ( ここ ) bar ( そこ ) ;
foo が呼ばれたときリターンスタックには( ここ )が積まれてる。
bar が呼ばれたときリターンスタックには( そこ )が積まれてる。
bar というワード自身がリターンスタックに積まれているのではない。
491デフォルトの名無しさん
2008/10/09(木) 21:16:04 ついでに >>56 のリターンスタックを使ったパズルの説明でも書いておこう。
問題は、
: foo twice ." Hello" ;
で、
HelloHello
を出力する twice を定義しろというパズル。
問題は、
: foo twice ." Hello" ;
で、
HelloHello
を出力する twice を定義しろというパズル。
492デフォルトの名無しさん
2008/10/09(木) 21:22:30 解答は、
: twice r> dup >r >r ;
何が起きているか説明すると、twice が呼ばれたとき、リターンスタックには、
: foo twice ( ここ ) ." Hello" ;
上の( ここ )が積まれている。
twice は最初に r> を実行して、( ここ ) をリターンスタックからデータスタックに移している。
次の dup で ( ここ ) がデータスタックに二つ積まれた状態になる。
最後に、 二つの >r で ( ここ ) が二つリターンスタックに戻される。
: twice r> dup >r >r ;
何が起きているか説明すると、twice が呼ばれたとき、リターンスタックには、
: foo twice ( ここ ) ." Hello" ;
上の( ここ )が積まれている。
twice は最初に r> を実行して、( ここ ) をリターンスタックからデータスタックに移している。
次の dup で ( ここ ) がデータスタックに二つ積まれた状態になる。
最後に、 二つの >r で ( ここ ) が二つリターンスタックに戻される。
493デフォルトの名無しさん
2008/10/09(木) 21:27:12 さて、定義されたワードの終端に到達したので Forthは、
リターンスタックからリターンアドレスを一つ取り出してそこに戻ろうとする。
: foo twice ( ここ ) ." Hello" ;
↑これの ( ここ )に戻ってくるわけだね。
そして、Helloを出力する。
そしてまた定義されたワードの終端に到達するので、Forth は
リターンスタックからリターンアドレスを一つ取り出してそこに戻ろうとするわけだ。
つまり、もう一度 ( ここ ) に戻る。
もう一度、Helloが出力されたら、次にリターンスタックからpopされる
リターンアドレスは foo を呼び出したアドレスなので、ここでようやく、
foo の実行が終了することになる。
リターンスタックからリターンアドレスを一つ取り出してそこに戻ろうとする。
: foo twice ( ここ ) ." Hello" ;
↑これの ( ここ )に戻ってくるわけだね。
そして、Helloを出力する。
そしてまた定義されたワードの終端に到達するので、Forth は
リターンスタックからリターンアドレスを一つ取り出してそこに戻ろうとするわけだ。
つまり、もう一度 ( ここ ) に戻る。
もう一度、Helloが出力されたら、次にリターンスタックからpopされる
リターンアドレスは foo を呼び出したアドレスなので、ここでようやく、
foo の実行が終了することになる。
494デフォルトの名無しさん
2008/10/09(木) 21:29:45 リターンスタックに積まれているリターンアドレスは、
次に実行すべきワード単体ではなくて、
それ以降、実行すべきコード全体の先頭を指し示すアドレスだ、
と、理解できたかしらん?
次に実行すべきワード単体ではなくて、
それ以降、実行すべきコード全体の先頭を指し示すアドレスだ、
と、理解できたかしらん?
495488
2008/10/10(金) 00:34:56 (ここ) は分かってるつもりなんですが、
メモリアドレス的に的確に伝えるには難しいような気が。。。
: baz foo ( ここ ) bar ( そこ ) ;
16bitアドレス環境として、スレデッドコードで考えると、
(ここ)は foo のアドレスと同じか、それとも +1 でしょうか?
# foo のアドレス +2 すると bar のアドレスですよね
なんかアホなこと言っているようですみません。
メモリアドレス的に的確に伝えるには難しいような気が。。。
: baz foo ( ここ ) bar ( そこ ) ;
16bitアドレス環境として、スレデッドコードで考えると、
(ここ)は foo のアドレスと同じか、それとも +1 でしょうか?
# foo のアドレス +2 すると bar のアドレスですよね
なんかアホなこと言っているようですみません。
496デフォルトの名無しさん
2008/10/10(金) 00:55:01 >>495
「barのアドレス」と書くとbazの定義の中のbarの呼び出しのあるアドレスなのか、
それともbar自身の定義のアドレスなのか混乱するから、
( ここ ) と表現したわけで、その違いがわかってるなら問題ないですよん。
あとポインタってわかるよね?
「barのアドレス」と書くとbazの定義の中のbarの呼び出しのあるアドレスなのか、
それともbar自身の定義のアドレスなのか混乱するから、
( ここ ) と表現したわけで、その違いがわかってるなら問題ないですよん。
あとポインタってわかるよね?
497デフォルトの名無しさん
2008/10/10(金) 01:03:18498496
2008/10/10(金) 01:20:54499464
2008/10/10(金) 01:36:27 >498
新しいかどうかなんて知らんよ。単にWORDの扱いを正規化できてVMが簡素になるっつうだけの話。
>497で言及している(ここ)(そこ)みたいな間接ポインタをVMで扱う必要も無くなるし。
まあ、その皺寄せをWORDに押し込んでるだけなんだけどね。
新しいかどうかなんて知らんよ。単にWORDの扱いを正規化できてVMが簡素になるっつうだけの話。
>497で言及している(ここ)(そこ)みたいな間接ポインタをVMで扱う必要も無くなるし。
まあ、その皺寄せをWORDに押し込んでるだけなんだけどね。
500496
2008/10/10(金) 01:42:51 >>499
なんていうか…
「(ここ)(そこ)みたいな間接ポインタ」というそれそのものが、
アセンブリ言語の時代からある「リターンアドレス」という概念なんですよ…。
Forthはそれをリターンスタックに分離して保存・復帰しているだけのこと。
なんていうか…
「(ここ)(そこ)みたいな間接ポインタ」というそれそのものが、
アセンブリ言語の時代からある「リターンアドレス」という概念なんですよ…。
Forthはそれをリターンスタックに分離して保存・復帰しているだけのこと。
501デフォルトの名無しさん
2008/10/10(金) 06:35:09502デフォルトの名無しさん
2008/10/10(金) 08:32:35 >500
今は実際のリターンアドレスの話をしとらんよ。
リターンスタックを「次に実行する命令の列」という形に抽象化するっつうとるだろうに。
今は実際のリターンアドレスの話をしとらんよ。
リターンスタックを「次に実行する命令の列」という形に抽象化するっつうとるだろうに。
503デフォルトの名無しさん
2008/10/10(金) 08:46:05 >>501
." とか、 前付きの " は、Forthではただの引用符じゃなくて、一つのワード。
だから、Helloとの間に空白が要る。
但し、終わりの " はセパレーターだから、空白なしで良い。
前にも出てたけど、
Forthでは文字列リテラルはポインタと長さの二つの数値で表す。
「.」は、トップアイテムを一つpopして値をプリントするワードだから、
" Hello" .
だと5がプリントされるだけ。文字列ポインタがスタックに残る。
「."」 が 「次の " までの文字列をプリントする」というワード。
文字列をスタックに積んだときは
" Hello" type
とやる。
." とか、 前付きの " は、Forthではただの引用符じゃなくて、一つのワード。
だから、Helloとの間に空白が要る。
但し、終わりの " はセパレーターだから、空白なしで良い。
前にも出てたけど、
Forthでは文字列リテラルはポインタと長さの二つの数値で表す。
「.」は、トップアイテムを一つpopして値をプリントするワードだから、
" Hello" .
だと5がプリントされるだけ。文字列ポインタがスタックに残る。
「."」 が 「次の " までの文字列をプリントする」というワード。
文字列をスタックに積んだときは
" Hello" type
とやる。
504デフォルトの名無しさん
2008/10/10(金) 08:52:55 >>502
だから、「次に実行する命令列」は辞書の中に既にあるんであって、
それはスタックである必要はなくて、いってみればアレイ。
辞書の中で実行は動的に行ったり戻ったりするから、
やっぱりリターンアドレスの保存は必要。
だから、「次に実行する命令列」は辞書の中に既にあるんであって、
それはスタックである必要はなくて、いってみればアレイ。
辞書の中で実行は動的に行ったり戻ったりするから、
やっぱりリターンアドレスの保存は必要。
505デフォルトの名無しさん
2008/10/10(金) 09:06:11506デフォルトの名無しさん
2008/10/10(金) 17:24:55 factorだと文字列リテラルはあるよ
507488
2008/10/10(金) 22:08:31 >>496,497 サンクス
スレデッドコードと書いておいて誤解がなかったようだ。
497 のレスだと、俺の中では「次のワード」という認識になる。
(あっち)という表現を使えば確かに誤解はなくなる。
なんだか、リターンスタックのデータ内容と、
(サブルーチン)リターンアドレスを混同した希ガス
スレデッドコードと書いておいて誤解がなかったようだ。
497 のレスだと、俺の中では「次のワード」という認識になる。
(あっち)という表現を使えば確かに誤解はなくなる。
なんだか、リターンスタックのデータ内容と、
(サブルーチン)リターンアドレスを混同した希ガス
508464
2008/10/11(土) 00:37:41 >504
「必要がないから積まない」じゃなくて、「VMの原理を簡単にするために積む」んだって。
VMが辞書の中を行ったり来たりしないようにするのが目的。
もちろん、VMの仕事をWORDに移管しただけの話だし、スタックが大きくなるデメリットもあるけどな。
「必要がないから積まない」じゃなくて、「VMの原理を簡単にするために積む」んだって。
VMが辞書の中を行ったり来たりしないようにするのが目的。
もちろん、VMの仕事をWORDに移管しただけの話だし、スタックが大きくなるデメリットもあるけどな。
509504
2008/10/11(土) 01:03:24 >>508
つまり、ワードを全部インラインにするということ?
それなら確かに理論的には可能だし、リターンスタック自体要らない。
普通は、大きくなるのはスタックじゃなくて辞書だな。
まあ、辞書からインラインで展開したものを
リターンスタックにコピーしてもいいけど、
ランタイムにやるなら相当動作が遅くなると思う。
それに、
なぜそのためにスタックというデータ構造を使うのかがわからない。
後ろから先に積んでいくことになるわけだが。
その発想はインストラクションキャッシュだと思う。
だから、むしろキューがいいと思う。
ソフトウェア的にやると相当遅いとは思うけど、
論理的には可能だと思うよ。
つまり、ワードを全部インラインにするということ?
それなら確かに理論的には可能だし、リターンスタック自体要らない。
普通は、大きくなるのはスタックじゃなくて辞書だな。
まあ、辞書からインラインで展開したものを
リターンスタックにコピーしてもいいけど、
ランタイムにやるなら相当動作が遅くなると思う。
それに、
なぜそのためにスタックというデータ構造を使うのかがわからない。
後ろから先に積んでいくことになるわけだが。
その発想はインストラクションキャッシュだと思う。
だから、むしろキューがいいと思う。
ソフトウェア的にやると相当遅いとは思うけど、
論理的には可能だと思うよ。
510デフォルトの名無しさん
2008/10/11(土) 02:00:15 サンクス >693
5 ソースコード
6 boost::spirit
というので激しく不安になるな。
というか、スクリプトの入門というのなら、BASICタイプ言語の作成とかCタイプ言語の作成
とか分散しないで、どっちか一つに集中すべきじゃない?
入門だったら、むしろ構文はシンプルなforthライクにして、エンジンの中身に拘るべきだと思うけど……
5 ソースコード
6 boost::spirit
というので激しく不安になるな。
というか、スクリプトの入門というのなら、BASICタイプ言語の作成とかCタイプ言語の作成
とか分散しないで、どっちか一つに集中すべきじゃない?
入門だったら、むしろ構文はシンプルなforthライクにして、エンジンの中身に拘るべきだと思うけど……
511デフォルトの名無しさん
2008/10/11(土) 02:02:28 誤爆スマソ
512464
2008/10/11(土) 02:18:22 >509
いや、基本はWORD呼び出し時に展開(そのWORDに定義されたWORD列をスタックに押し込む)。
WORDコンパイル時に全部インラインに展開するわけじゃないです。
#高速化を目的として、WORDコンパイル時にある程度はインライン化することになると思うけど。
WORDに定義されたWORD列を、実行時にその場で積んでその場で処理する必要があるから、
FIFOの仕組みが必要になります。
まあ、小まめにWORDの積み降ろしをやらなきゃいけないから、確かに重そうだけどね。
いや、基本はWORD呼び出し時に展開(そのWORDに定義されたWORD列をスタックに押し込む)。
WORDコンパイル時に全部インラインに展開するわけじゃないです。
#高速化を目的として、WORDコンパイル時にある程度はインライン化することになると思うけど。
WORDに定義されたWORD列を、実行時にその場で積んでその場で処理する必要があるから、
FIFOの仕組みが必要になります。
まあ、小まめにWORDの積み降ろしをやらなきゃいけないから、確かに重そうだけどね。
513デフォルトの名無しさん
2008/10/11(土) 05:37:05 464のやり方は、ありえなくはないけどForth的じゃないね。
どっちかっていうとJava VMのJITコンパイラみたいな。
Forthはシンプルな実装で軽い、ってイメージ。
どっちかっていうとJava VMのJITコンパイラみたいな。
Forthはシンプルな実装で軽い、ってイメージ。
514デフォルトの名無しさん
2008/10/11(土) 06:54:12515464
2008/10/11(土) 13:07:00 >513
いや、実装はこっちの方がシンプルだよ。辞書の解釈を全部WORDに押し付けることができるから。
ただ、スタック操作が増えるから重くなる方向だけどね。
>514
リターンアドレス前提だと難しいよね。作業用スタックがもう一本ありゃいいんだけど。
俺言語のVMだと自前スタックで実装しているので大した話じゃないです。
いや、実装はこっちの方がシンプルだよ。辞書の解釈を全部WORDに押し付けることができるから。
ただ、スタック操作が増えるから重くなる方向だけどね。
>514
リターンアドレス前提だと難しいよね。作業用スタックがもう一本ありゃいいんだけど。
俺言語のVMだと自前スタックで実装しているので大した話じゃないです。
516464
2008/10/11(土) 13:22:12 >514
ちょっと補足。
複数のWORDを押し込もうとすると確かに面倒だね。
俺言語でも
1. 無名WORDを作る
2. 1.のWORDに実行するWORDを押し込む
3. 1.のWORDをリターンスタックに押し込む
といったパック化が必要になります。
ちょっと補足。
複数のWORDを押し込もうとすると確かに面倒だね。
俺言語でも
1. 無名WORDを作る
2. 1.のWORDに実行するWORDを押し込む
3. 1.のWORDをリターンスタックに押し込む
といったパック化が必要になります。
517デフォルトの名無しさん
2008/10/11(土) 13:26:05 464のVMだが、
ハードウェアレベルではもう一般化してる
インストラクションのプリフェッチとおなじだよね。
マシン語のデコーダレベルでのVMという感じか。
実装する場合の最難題は条件付きジャンプだと思う。
IFとか不定ループをどう載せるかが鍵だな。
これを考えると、VMが仕組みとして単純になるかどうかは微妙だと思う。
まあ、ベタでやればできそうな気はするが、
ハードウエアの仕組みをソフトウェアで二重にしてるだけのような気がしないでもない。
ハードウェアレベルではもう一般化してる
インストラクションのプリフェッチとおなじだよね。
マシン語のデコーダレベルでのVMという感じか。
実装する場合の最難題は条件付きジャンプだと思う。
IFとか不定ループをどう載せるかが鍵だな。
これを考えると、VMが仕組みとして単純になるかどうかは微妙だと思う。
まあ、ベタでやればできそうな気はするが、
ハードウエアの仕組みをソフトウェアで二重にしてるだけのような気がしないでもない。
518464
2008/10/11(土) 13:38:04 >514
思い出した……>59を実現するにはreverse自体のパック化も必須なんだっけ。
そういや>59みたいな操作をどうしようか悩んだな。
ただ、こういったWORDを跨ぐ暗黙的なリターンスタック制御てけっこう危険じゃない?
個人的にはWORDはデータスタックの状態にのみ依存すべきだと思うけど、WORDを越えた
範囲までリターンスタックを操作できるようにすると、WORD同士の依存関係が出てしまって
連鎖性(concatenative)が崩れるような気がする。
forthの条件分岐でも、セパレーターを使った明示的な制御をしているわけだし。
思い出した……>59を実現するにはreverse自体のパック化も必須なんだっけ。
そういや>59みたいな操作をどうしようか悩んだな。
ただ、こういったWORDを跨ぐ暗黙的なリターンスタック制御てけっこう危険じゃない?
個人的にはWORDはデータスタックの状態にのみ依存すべきだと思うけど、WORDを越えた
範囲までリターンスタックを操作できるようにすると、WORD同士の依存関係が出てしまって
連鎖性(concatenative)が崩れるような気がする。
forthの条件分岐でも、セパレーターを使った明示的な制御をしているわけだし。
519464
2008/10/11(土) 13:49:31 連投スマソ
>517
そうか、CPUだともう一般的なのか……。さすがに天才的な変態が集まる業界だな。
やっぱりCPUのアーキテクチャ勉強しないといけないなあ。
IFは構文解析で逃げました。
block := block ? WORD1 ! WORD2
という三項演算子を用意して、条件分岐用WORDに解釈するようにしました。
不定ループの構文を用意するかどうかは検討中です。
>517
そうか、CPUだともう一般的なのか……。さすがに天才的な変態が集まる業界だな。
やっぱりCPUのアーキテクチャ勉強しないといけないなあ。
IFは構文解析で逃げました。
block := block ? WORD1 ! WORD2
という三項演算子を用意して、条件分岐用WORDに解釈するようにしました。
不定ループの構文を用意するかどうかは検討中です。
520517
2008/10/11(土) 13:59:32 もうすこし考えてみたんだが、
ワードがどこかで他のワードを呼び出し、そのワードがどこかで他のワードを呼出し...
という場合には、
ワードシーケンスに展開する段階で、
展開すべき個所をたどるためのリターンスタックが必要な気がする。
だから、464のVMは、
普通のForthでの実行と同じ動作でワード系列をコピーして、
それから順番にInterpretして実行するという感じになって、
単なる二度手間ではないかな。
ワードがどこかで他のワードを呼び出し、そのワードがどこかで他のワードを呼出し...
という場合には、
ワードシーケンスに展開する段階で、
展開すべき個所をたどるためのリターンスタックが必要な気がする。
だから、464のVMは、
普通のForthでの実行と同じ動作でワード系列をコピーして、
それから順番にInterpretして実行するという感じになって、
単なる二度手間ではないかな。
521464
2008/10/11(土) 15:30:32 >520
どのみちリターンスタック(実行する命令列を保存する専用スタック)が必要なのはその通り。
WORDの動作:普通のForthでの実行と同じ動作でワード系列をコピー
VMの動作: 順番にInterpretして実行する
というところがポイントですな。VMは辞書のこととか考える必要がないのでシンプルになります。
その代わり「辞書からWORD列を拾ってリターンスタックに展開する」というWORDが必要になるけど。
確かにコピーする手間はムダな気もするんだけどね……
辞書のWORD列を直接トレースするのと比べてどんぐらい余計な手間がかかってるんだろう?
ポインタ操作数回&アクセス数回レベルだと思うけど。
どのみちリターンスタック(実行する命令列を保存する専用スタック)が必要なのはその通り。
WORDの動作:普通のForthでの実行と同じ動作でワード系列をコピー
VMの動作: 順番にInterpretして実行する
というところがポイントですな。VMは辞書のこととか考える必要がないのでシンプルになります。
その代わり「辞書からWORD列を拾ってリターンスタックに展開する」というWORDが必要になるけど。
確かにコピーする手間はムダな気もするんだけどね……
辞書のWORD列を直接トレースするのと比べてどんぐらい余計な手間がかかってるんだろう?
ポインタ操作数回&アクセス数回レベルだと思うけど。
522514
2008/10/11(土) 18:35:01 >>518
普通はリターンスタックとか継続とか触れない言語の方が多いから、
Forthではなく俺言語を作るつもりなら、言語デザイナであるお前様自身の
判断で実現可能にしてもいいし、そうでなくしてもいいと思うよ。
ただForthは言語レベルでリターンスタックを操れる結果、協調的マルチタスクやら
コルーチンやら言語実装のレベルで普通対処するものも、ライブラリレベルで実現できる柔軟さがある。
リターンスタックは他の言語にはないForthの特徴の一つだからね。
俺言語でなんとか実現する方法を悩んでみるのも楽しいんじゃない?
普通はリターンスタックとか継続とか触れない言語の方が多いから、
Forthではなく俺言語を作るつもりなら、言語デザイナであるお前様自身の
判断で実現可能にしてもいいし、そうでなくしてもいいと思うよ。
ただForthは言語レベルでリターンスタックを操れる結果、協調的マルチタスクやら
コルーチンやら言語実装のレベルで普通対処するものも、ライブラリレベルで実現できる柔軟さがある。
リターンスタックは他の言語にはないForthの特徴の一つだからね。
俺言語でなんとか実現する方法を悩んでみるのも楽しいんじゃない?
523514
2008/10/11(土) 18:47:48 あとForthのVMって相当シンプルだよ。
アセンブリ言語で書かれた昔のForthとかコアの部分はアセンブリ言語で数行レベルだった気がする。
どのへんが複雑だと思ったのかは興味がある…
アセンブリ言語で書かれた昔のForthとかコアの部分はアセンブリ言語で数行レベルだった気がする。
どのへんが複雑だと思ったのかは興味がある…
524517
2008/10/11(土) 21:01:10 >>521
いや、そうではなくて、
「WORDの動作」の中の、「普通のForthと同じ動作で」ってところに、
リターンアドレスを保存するスタックという意味でのリターンスタックが、もう必要なのではないかということ。
あと、言葉の問題として、
大きい意味でのワードを展開する動作のところからもうInterpreter(=VM)の動作というのが普通だと思う。
つまり、VMの動作の前半をWORDの動作と呼んで違う名前にしたから、
残ったVMの動作が簡単に見えるというだけなんじゃないかな。
辞書中のワードから始めると、ForthのVMよりも(多分プリミティブ)WORDの系列を作る部分が余分で、
より複雑になってると思う。
でも、自分の言語を作るのをやめろといってるんじゃないよ。
むしろ応援してる。
ちょっと話題はそれるけど、Forthというか、スタック指向言語は、
コンパイラライターフレンドリーなんだよね。
だから、Forthコード書くよりForth(風オレ言語)VMを書く人が多かったりするわけだが、
ホントはForthでアプリケーションを書くときも「オレ言語」を作るつもりで書くと良いと思ってる。
いや、そうではなくて、
「WORDの動作」の中の、「普通のForthと同じ動作で」ってところに、
リターンアドレスを保存するスタックという意味でのリターンスタックが、もう必要なのではないかということ。
あと、言葉の問題として、
大きい意味でのワードを展開する動作のところからもうInterpreter(=VM)の動作というのが普通だと思う。
つまり、VMの動作の前半をWORDの動作と呼んで違う名前にしたから、
残ったVMの動作が簡単に見えるというだけなんじゃないかな。
辞書中のワードから始めると、ForthのVMよりも(多分プリミティブ)WORDの系列を作る部分が余分で、
より複雑になってると思う。
でも、自分の言語を作るのをやめろといってるんじゃないよ。
むしろ応援してる。
ちょっと話題はそれるけど、Forthというか、スタック指向言語は、
コンパイラライターフレンドリーなんだよね。
だから、Forthコード書くよりForth(風オレ言語)VMを書く人が多かったりするわけだが、
ホントはForthでアプリケーションを書くときも「オレ言語」を作るつもりで書くと良いと思ってる。
525デフォルトの名無しさん
2008/10/11(土) 21:33:08 Forthの用語って独特な言い回しがあるからな。
知らない人は結構混乱する。
スレデッドコードのForthの場合、ソースコードを解釈してスレデッドコードを
生成することをコンパイルといい、スレデッドコードを生成する部分を外部インタープリタ、
スレデッドコードを解釈実行する部分を内部インタープリタと呼ぶ。
(これで良かったよな?同志?)
このスレでVMと言った時に内部インタープリタだけなのか、外部インタープリタも含むのか?
どっちだろうか?
知らない人は結構混乱する。
スレデッドコードのForthの場合、ソースコードを解釈してスレデッドコードを
生成することをコンパイルといい、スレデッドコードを生成する部分を外部インタープリタ、
スレデッドコードを解釈実行する部分を内部インタープリタと呼ぶ。
(これで良かったよな?同志?)
このスレでVMと言った時に内部インタープリタだけなのか、外部インタープリタも含むのか?
どっちだろうか?
526デフォルトの名無しさん
2008/10/12(日) 00:45:26 >>525
テキストを読み込んで、
1) ワードを辞書内で特定
2) だめならリテラルに変換
3) ダメならエラーで終了。
という部分が外部インタープリタ
1)または2)で成功したときに
モードに応じてコンパイル(Forth的意味)するか実行する
のが内部インタープリタ
だと思ってました。
Forthはテキストインプットも弄れるという面白さもあるよね。
Forth VMというと、外部も含むのかな。
上のリターンスタック云々の話は、
内部インタープリタのことだと思うけど。
テキストを読み込んで、
1) ワードを辞書内で特定
2) だめならリテラルに変換
3) ダメならエラーで終了。
という部分が外部インタープリタ
1)または2)で成功したときに
モードに応じてコンパイル(Forth的意味)するか実行する
のが内部インタープリタ
だと思ってました。
Forthはテキストインプットも弄れるという面白さもあるよね。
Forth VMというと、外部も含むのかな。
上のリターンスタック云々の話は、
内部インタープリタのことだと思うけど。
527デフォルトの名無しさん
2008/10/12(日) 07:57:23 内部インタプリタて(スレッドコードで実装してる場合は)nextルーチンのことじゃなかったっけ。
528デフォルトの名無しさん
2008/10/12(日) 08:49:02 そうNEXTルーチン。アセンブリ言語で数行、という奴。
529464
2008/10/12(日) 15:10:26 >522
その辺は「自由と責任」というやつですな。「銃で足をブッとばす自由」でもあるけど。
>どのへんが複雑だと思ったのかは興味がある…
自分でも何でだったっけな、と過去の記憶を探り出してみたけど、
・実行中のWORDの次のWORDを辞書の中から探せるようにする仕組みが必要
×実行中のWORDの中身を変更するのが大変(VMのスタックに積んでいるWORD含む)
×番兵などの終了処理が必須
--> VM側のスタックに積むことにすればpop&top参照で正規化できるし、元の値を
コピーするからWORD変更にも影響されない。
・VM側に「WORDを実行する」という手順が必要になる
--> VM側のスタックに積むことにすればpushで正規化できる
ぐらいかもしれない。
コンパイル時にWORDの中身が確定するforthだとあんまり問題にならなそうだね。
その辺は「自由と責任」というやつですな。「銃で足をブッとばす自由」でもあるけど。
>どのへんが複雑だと思ったのかは興味がある…
自分でも何でだったっけな、と過去の記憶を探り出してみたけど、
・実行中のWORDの次のWORDを辞書の中から探せるようにする仕組みが必要
×実行中のWORDの中身を変更するのが大変(VMのスタックに積んでいるWORD含む)
×番兵などの終了処理が必須
--> VM側のスタックに積むことにすればpop&top参照で正規化できるし、元の値を
コピーするからWORD変更にも影響されない。
・VM側に「WORDを実行する」という手順が必要になる
--> VM側のスタックに積むことにすればpushで正規化できる
ぐらいかもしれない。
コンパイル時にWORDの中身が確定するforthだとあんまり問題にならなそうだね。
530464
2008/10/12(日) 15:20:28 >524
「スタックに複数のデータを押し込む操作は機械語レベルだとアトミックにならない」ということ??
C++で実装しているから意識していなかったけど、そうかもしれないですね。
少なくともプリミティブで実装する必要あるね。
>ForthのVMよりも(多分プリミティブ)WORDの系列を作る部分が余分で、
これは狙ってやっていることだから仕様がないですね。
まあ、俺言語ではVM自体もWORD扱いにしているのですが……
「スタックに複数のデータを押し込む操作は機械語レベルだとアトミックにならない」ということ??
C++で実装しているから意識していなかったけど、そうかもしれないですね。
少なくともプリミティブで実装する必要あるね。
>ForthのVMよりも(多分プリミティブ)WORDの系列を作る部分が余分で、
これは狙ってやっていることだから仕様がないですね。
まあ、俺言語ではVM自体もWORD扱いにしているのですが……
531デフォルトの名無しさん
2008/10/12(日) 15:50:56 >>529
んー、やっぱり、思い込みでForthを理解したつもりになるんじゃなくて、
本格的に触ってみたほうが良いと思うんだけどな。
>実行中のWORDの次のWORDを辞書の中から探せるようにする仕組みが必要
通常、Forthは実行時には、スレデッドコードにコンパイルされた命令列を、
上にも出ているnextルーチンで辿るだけなので、仕組みというほどの仕組みはないよ。
>実行中のWORDの中身を変更するのが大変(VMのスタックに積んでいるWORD含む)
間接スレッディングのForthだと定義済みのワードの変更は、一カ所ポインタを書き換える
だけで済むはず。
>番兵などの終了処理が必須
番兵というかワードの最後にnextルーチンへのジャンプかnextルーチン自身を書き込むだけ。
>VM側に「WORDを実行する」という手順が必要になる
スレデッドコードのForthの命令列は、ワードへのポインタが並んでいるだけで、
「WORDを実行する」という意味のインストラクションは必要ないよ。
んー、やっぱり、思い込みでForthを理解したつもりになるんじゃなくて、
本格的に触ってみたほうが良いと思うんだけどな。
>実行中のWORDの次のWORDを辞書の中から探せるようにする仕組みが必要
通常、Forthは実行時には、スレデッドコードにコンパイルされた命令列を、
上にも出ているnextルーチンで辿るだけなので、仕組みというほどの仕組みはないよ。
>実行中のWORDの中身を変更するのが大変(VMのスタックに積んでいるWORD含む)
間接スレッディングのForthだと定義済みのワードの変更は、一カ所ポインタを書き換える
だけで済むはず。
>番兵などの終了処理が必須
番兵というかワードの最後にnextルーチンへのジャンプかnextルーチン自身を書き込むだけ。
>VM側に「WORDを実行する」という手順が必要になる
スレデッドコードのForthの命令列は、ワードへのポインタが並んでいるだけで、
「WORDを実行する」という意味のインストラクションは必要ないよ。
532464
2008/10/12(日) 23:25:00 本格的に触るのは……あの構文は色々と嫌だ。
[条件] IF [肯定時] ELSE [否定時] THEN とか。
せめて条件算子的だったらなぁ。[条件] ? [肯定時] : [否定時] ;
>531
細かいことを言うと、nextルーチンが辞書内のスレッデッドコード構造の詳細を知らなきゃ
ならないので、VMと辞書の関連が密になりそうな気がします。スレッデッドコードをスタックに
pushしてVM内に取り込んじゃえば辞書内の構造を気にする必要無いし。
まあ、最適化のために作り込んでも良い気がするけどね。そこは将来の課題ということで。
>一カ所ポインタを書き換えるだけで済むはず。
WORD自体を置換する場合はそうですね。WORDの挿入や削除はたぶん難しいかと。
そんな特殊なことは禁止にして、新規にWORD定義させた方が良いかも知れないけど。
あるいは無名WORDとかスキップWORDを用意するとか。
>「WORDを実行する」という意味のインストラクションは必要ないよ。
あれ?VMに保存されている「現在実行中のWORD」って、間接ポインタじゃないの?
(nextの動作を考えると、間接ポインタじゃないと色々と面倒臭そうな)
実行前に間接参照からWORDを探す操作が一段余計に必要になるかと思ってた。
[条件] IF [肯定時] ELSE [否定時] THEN とか。
せめて条件算子的だったらなぁ。[条件] ? [肯定時] : [否定時] ;
>531
細かいことを言うと、nextルーチンが辞書内のスレッデッドコード構造の詳細を知らなきゃ
ならないので、VMと辞書の関連が密になりそうな気がします。スレッデッドコードをスタックに
pushしてVM内に取り込んじゃえば辞書内の構造を気にする必要無いし。
まあ、最適化のために作り込んでも良い気がするけどね。そこは将来の課題ということで。
>一カ所ポインタを書き換えるだけで済むはず。
WORD自体を置換する場合はそうですね。WORDの挿入や削除はたぶん難しいかと。
そんな特殊なことは禁止にして、新規にWORD定義させた方が良いかも知れないけど。
あるいは無名WORDとかスキップWORDを用意するとか。
>「WORDを実行する」という意味のインストラクションは必要ないよ。
あれ?VMに保存されている「現在実行中のWORD」って、間接ポインタじゃないの?
(nextの動作を考えると、間接ポインタじゃないと色々と面倒臭そうな)
実行前に間接参照からWORDを探す操作が一段余計に必要になるかと思ってた。
533デフォルトの名無しさん
2008/10/12(日) 23:34:45 >VMと辞書の関連が密
というか、それがFORTHの肝のような気がする。
というか、それがFORTHの肝のような気がする。
534デフォルトの名無しさん
2008/10/13(月) 00:16:22 スレデッドコード自体、ワードへのポインタを並べたものでしかないから、
ジャンプとかコールとかそういう類のインストラクションをデコードする必要がない、
という意味ね。
あとForthの実装にはダイレクトスレデッドなものもあるよ。
nextルーチンからみると命令列を順に辿ってるだけであって、
「辞書からワードを毎回探している」ってわけじゃないしね。
それより、スタックに命令列を毎回pushするオーバーヘッドのほうがよほど大きいと思うし、
nextルーチンに比べてシンプルとも思えないんだな。
ま、いろいろ悩んで勉強して、これだ!と思える言語デザインに邁進してください、と。
このスレが本当に久しぶりに活性化したのは間違いないしね。
ジャンプとかコールとかそういう類のインストラクションをデコードする必要がない、
という意味ね。
あとForthの実装にはダイレクトスレデッドなものもあるよ。
nextルーチンからみると命令列を順に辿ってるだけであって、
「辞書からワードを毎回探している」ってわけじゃないしね。
それより、スタックに命令列を毎回pushするオーバーヘッドのほうがよほど大きいと思うし、
nextルーチンに比べてシンプルとも思えないんだな。
ま、いろいろ悩んで勉強して、これだ!と思える言語デザインに邁進してください、と。
このスレが本当に久しぶりに活性化したのは間違いないしね。
535デフォルトの名無しさん
2008/10/13(月) 00:21:58 >>533
間接スレデッドの場合、Forthコンソールの側から見ると、
逆コンパイルしやすかったり、便利な面はたしかにあるけれど、
VMつうかnextルーチンから見ると、単にポインタを辿っているだけなので、
構造として、VM実装と辞書構造が密、というわけでもないと思う。
実際VM実装テクニックとしてのスレデッドコードは、今や、Forth以外でも
当たり前の技術になってるし。
間接スレデッドの場合、Forthコンソールの側から見ると、
逆コンパイルしやすかったり、便利な面はたしかにあるけれど、
VMつうかnextルーチンから見ると、単にポインタを辿っているだけなので、
構造として、VM実装と辞書構造が密、というわけでもないと思う。
実際VM実装テクニックとしてのスレデッドコードは、今や、Forth以外でも
当たり前の技術になってるし。
536デフォルトの名無しさん
2008/10/27(月) 00:52:54 jonesforth読んだ。
ソース付きなので理解しやすい。
OS Xで動かそうとしたが挫折した。
OSXのGASではマクロが対応してないみたいだ。
ソース付きなので理解しやすい。
OS Xで動かそうとしたが挫折した。
OSXのGASではマクロが対応してないみたいだ。
537デフォルトの名無しさん
2008/11/23(日) 01:13:24 急にスレが進んだと思ったら、止まるのも急だよなこのスレ
やっぱ誰も使ってないってこったな
やっぱ誰も使ってないってこったな
538デフォルトの名無しさん
2008/11/26(水) 17:30:54 ttp://www.intellasys.net/index.php?option=com_frontpage&Itemid=64
なんか並列forthマシンっぽいw
なんか並列forthマシンっぽいw
539デフォルトの名無しさん
2008/12/27(土) 14:00:32 factor使ってる奴いる?
540デフォルトの名無しさん
2008/12/27(土) 21:13:14 とりあえず入れてみたけど特に使ってないなw
541539
2008/12/28(日) 01:26:48 factorおもしろいぜ。デプロイするとスタンドアロンで動く物もできるし。
542デフォルトの名無しさん
2008/12/29(月) 13:31:00 やっぱだめだこの言語。
人間工学から著しく反してる。
人間工学から著しく反してる。
543デフォルトの名無しさん
2008/12/29(月) 19:52:22 サルが人間工学語ってやがる。
544デフォルトの名無しさん
2008/12/29(月) 21:45:56 自分の思考をスタック処理に最適化させればいいんだよw
545デフォルトの名無しさん
2008/12/29(月) 22:06:52 forthに慣れるのはそんなに大変なことじゃないと思うけどなあ。
まあ、問題をごく単純な部分に細分して考えることができないと、
スタック処理が爆発しがちになるとはいえますね。
でも、問題の細分ができない人は、どの言語でプログラミングしても
たかが知れてる。
まあ、問題をごく単純な部分に細分して考えることができないと、
スタック処理が爆発しがちになるとはいえますね。
でも、問題の細分ができない人は、どの言語でプログラミングしても
たかが知れてる。
546デフォルトの名無しさん
2009/01/01(木) 11:45:56 Lispのマクロ的なことができるってほんと?
547デフォルトの名無しさん
2009/01/01(木) 11:56:23 イミディエイトなワードのことかな。
結果としては似たようなことができると言えなくもないけど、
Lispのマクロみたいな2度evalするみたいな高水準のものじゃありません。
結果としては似たようなことができると言えなくもないけど、
Lispのマクロみたいな2度evalするみたいな高水準のものじゃありません。
548デフォルトの名無しさん
2009/01/07(水) 22:44:24 つまり・・・どういうことだってばよ?
549デフォルトの名無しさん
2009/01/07(水) 23:39:44 factorならlispのマクロと同じようなことができるよ
550デフォルトの名無しさん
2009/01/08(木) 00:11:19 同じ機能を達成できるとしても言語が違えばそこに至るロジックは異なる。
具体的に何がしたいのか特定しないと。
factorはおもしろい言語だが、関数型言語のフリし過ぎなのがイヤラシくもある。
具体的に何がしたいのか特定しないと。
factorはおもしろい言語だが、関数型言語のフリし過ぎなのがイヤラシくもある。
551デフォルトの名無しさん
2009/01/09(金) 12:30:14 何かサンプルが欲しいな。
552デフォルトの名無しさん
2009/01/09(金) 22:47:55553デフォルトの名無しさん
2009/02/26(木) 00:17:58 組み込み用FORTH検討中・・・
554デフォルトの名無しさん
2009/03/07(土) 05:11:31 part 1 の URL ってないの?
555デフォルトの名無しさん
2009/03/07(土) 10:00:54556デフォルトの名無しさん
2009/03/07(土) 10:13:20 : Mops ( オブジェクト指向FORTH -- ) ;
http://pc.2ch.net/tech/kako/1000/10001/1000118518.html
http://pc.2ch.net/tech/kako/1000/10001/1000118518.html
557デフォルトの名無しさん
2009/03/07(土) 13:25:33 thanks
558デフォルトの名無しさん
2009/03/07(土) 18:54:17 このスレも長いね
559デフォルトの名無しさん
2009/03/07(土) 21:43:31 factorとかJoyとか触ってる奴いないのかよ
560デフォルトの名無しさん
2009/03/07(土) 23:32:50 普通の関数型言語に比べてどういうメリットがあるのか分からない。
561デフォルトの名無しさん
2009/03/08(日) 10:51:09 forthは関数型ちゃうし
562デフォルトの名無しさん
2009/03/08(日) 12:22:51 >>560はなんでこのスレにいるんだ?
レスを投稿する
ニュース
- 橋下徹氏 外務省幹部の訪中受け「口だけ番長」へ痛烈指摘 「喧嘩は日本の完敗…なんとかっこ悪い日本か」 [冬月記者★]
- 【外国人問題】小野田紀美担当相「不法就労や不法滞在は許さない」 [シャチ★]
- 【野球】井端監督 大谷翔平、山本由伸らのWBCへの参加 「1日も早く返事ほしい」「待っててといっても、国内組が遅くなってしまう」★3 [冬月記者★]
- 経団連会長、日中は建設的対話を 経済3団体が高市首相と初会談も日中関係は話題に登らず… [BFU★]
- 中国で「クレしん」公開延期 対日報復、エンタメに波及 [蚤の市★]
- 東京株式市場 インバウンド関連株が下落 中国政府の渡航自粛要請で [バイト歴50年★]
- 🏡
- スーパーが開くまで約4時間何すりゃいいんだ?
- 有識者「高市総理が発言を撤回したり、辞職するしかないと言っている人は、それで日中関係が今まで通りになると思ってる?」 [834922174]
- 飲みの約束だるい
- 減税は低所得者差別
- 高市さんに土下座してもらったら一発解決なのに何でやらないんだろ??
