K.Maebashi's BBS

ご自由に書き込んでください。雑談も可。
テスト書き込みの類はテスト用掲示板にどうぞ

[日付順表示] [日付順インデックス] [スレッド順インデックス]

新規投稿 | 開設者ホームページへ戻る | ヘルプ

[1335] Re:コード生成部分について
投稿者:(ぱ)こと管理人
2009/06/02 01:28:02

>int func(p1[],p2[]) >{ > p1[2]=10; // これはOK > p2[4]=9;    // これはOK > p1=p2;     // これがエラーです >} >ひょっとしてdiksamはOKでしたか? DiksamではOKです。Diksamの配列の仕様はJavaとほぼ同じですので。 よって、[]は演算子です。 int[][]という型の式に対し、1回適用すればその式の型はint[]になりますし、 2回適用すればintになります。 山さんの言語でこのあたりを変えるとなると、fix_tree.cでのTypeSpecifierの 扱いが変わってくるはずです。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1334] えーっと。
投稿者:(ぱ)こと管理人
2009/06/02 00:41:17

>私は「クラス単位」で「オブジェクト」で分割です。 前から思っていたのですが、「クラス」と「オブジェクト」の区別、ついてます? >しかしこれは構造化ですよ。オブジェクト指向ではありません。 すてぜりふ?
[この投稿を含むスレッドを表示] [この投稿を削除]
[1333] Re:スレッドセーフについて
投稿者:(ぱ)こと管理人
2009/06/02 00:29:53

> では、スレッド間で複数のデータを渡す場合の方法が無いのではないだろうかと思われ >るでしょう。これには、変数集合体のパック、アンパック機能を提供し、複数の情報を >パックして他スレッドに渡すことで、スレッドセーフを保障しています。 いまさらなのかも知れませんが、スレッド間のデータの受け渡しがこれぐらい疎結合で よいのなら、ひとつのVMで複数のスレッドを動かすのではなく、VMごと分けてしまって、 それぞれ別のスレッドで動かせばよいのではないでしょうか。 このスレッドでは、まさにそういうことを話していたつもりでした。 http://kmaebashi.com/bbs/thread.php?boardid=kmaebashibbs&from=1221&range=1 >この要求に対しポインターや参照を操作することは、スレッドセーフを著しく >阻害する要因です。 >なぜなら、2つのスレッドで同じ参照を持った場合、そのデータアクセスに対し >スレッドセーフを自動で行うことはとても大変であり重い処理となります。 少なくともDiksamの設計なら、ヒープもグローバル変数もDVMの配下にあります。 よって、DVMを複数生成すれば、ふたつのスレッドで同じオブジェクトへの参照を 持つことはありませんし、グローバル変数も別です。 その上で、VM共有変数とかを導入して、VM間のデータのやり取りを考えれば よいのではないかと。 スクリプト言語において、ひとつのVMで複数のネイティブスレッドを使うことに関しては、 Rubyのまつもとゆきひろさんが以前こんなことを書いています。 http://www.rubyist.net/~matz/20070530.html >global interpreter lockを使っているので、native threadを使ってもさほど >並列性はあがらず性能もあがりません。 >というのも、オブジェクトアクセスひとつひとつを排他制御しなければならないので、 >コンフリクトは無視して問題が起きそうなら自分で対処というようなC++のような >対応はスクリプト言語では難しいでしょう。 (中略) >また、PythonのGuido van Rossumはスクリプト言語の並列性について >http://mail.python.org/pipermail/python-3000/2007-May/007414.html >という(むしろforkを活用すべきという)意見を述べています。 まあ、JVMなんかでも、doubleの操作はアトミックであることを保証してはいないので、 割り切ってしまう、という考え方もあるかもしれませんけれど。 # ポインタが不正になってクラッシュするのはさすがにまずいのかなあ。 # でも、黙って間違った答を吐くアプリケーションはもっとひどいと思うけど。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1332] SEさんの継承の使い方
投稿者:(ぱ)こと管理人
2009/06/01 22:57:31

で、以下の指摘については、何の反論も弁明もなしですか? >仮に実装継承による差分プログラミングを(いろいろの弊害は度外視して)認めると >しても、それが趣旨ならUpperStackをStack型の変数に代入してはいけないし、 http://kmaebashi.com/bbs/list.php?boardid=kmaebashibbs&from=1269&range=1 >Stack st = new Stack(); にて、SEさんは、なぜUpperStackをStackに代入しているのですか? そうすることによるメリットは何ですか? >スタックから要素を取得するメソッドはget()をオーバーライドしてはいけません。 >getUpper()のような別のメソッドを作るべきです。 http://kmaebashi.com/bbs/list.php?boardid=kmaebashibbs&from=1260&range=1 にて、なぜget()をオーバーライドしたのですか? そうすることによるメリットは何ですか? >>FileWriterを例にした方がいいかもしれません。内容的には同じ意図です。 >「同じ意図です」って、どういう意図でしょうか? で、どういう意図でしょうか? #「抽象化」とか、まるっきり意味のない回答をしないでくださいよ。 >FileWriterがこういう継承関係になっている「意図」を理解しているのなら、 >オセロ盤に棋譜を吐かせるのに、Boardクラスによりによって「ファイル名」を >渡すなどという設計がでてくるはずがないのですけど。 >http://kmaebashi.com/bbs/list.php?boardid=kmaebashibbs&from=1303&range=1 私には、SEさんが、継承やポリモルフィズムを理解しているようにはとても見えないのですけど。 # ていうか「インスタンス」も理解してなさそうな。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1331] Re:>(ぱ)こと管理人さん
投稿者:(ぱ)こと管理人
2009/06/01 22:42:23

>>http://kmaebashi.com/programmer/c_yota/module.html >まずモジュールの定義が私と違っていたようです。 >(ぱ)さんの所で言うモジュールは「ヘッダファイル単位」で、私の言っていたのは「ライブラリ単位」だったようです。 むちゃくちゃですね。 「ヘッダファイル単位」っていったいどういう意味ですか? 私がどこかにそんなことを 書きましたか? (書いてあるというのなら引用してください) ご自分が何を言っているか 自分で理解していますか? 「モジュール」が先に決まって、それに対応するヘッダファイルを作ることはあっても、 ヘッダファイルが先に決まることはありえないでしょう。常識的に考えて。 よってモジュールが「ヘッダファイル単位」などということがあるわけがありません。 これではモジュール切り分けの指針がどこにもないではないですか。 件のページで、私はこう書いています。 >さて、Cでは、ソースファイル単位で名前空間の隠蔽が出来ますが、プログラムの >規模がさらに大きく、ソースファイルの数自体が膨大になってくると、今度は、 >いくつかのソースファイルをまとめて、もう1段階大きな固まりを作る必要が >出てきます。以下、この文章中では、この固まりのことを「モジュール」と呼びます。 ># こういうのは「ライブラリ」と呼ばれることもありますが、「ライブラリ」と ># 言うとどうも「下請け」的なイメージがあって、私にはちょっとしっくり来ません。 SEさんは、Cでは、「せいぜいDBアクセスとか通信部分など」しかモジュール化しない そうですが、これはやはり私と同様、「ライブラリ」には下請け的なイメージを 持っていて、DBアクセスとか通信部分のような下請け部分しかモジュール(SEさん用語の ライブラリ)にはしない、と言っているわけでしょう。 では、「せいぜいDBアクセスとか通信部分など」以外の部分は、Cの時代には、 どのように作っていたのですか? いっさい分割なしのぐちゃぐちゃですか? >私は、実装隠蔽の単位としてクラスは適当だと思っていて、機能を単位とするのは間違いだと思います。 で、なぜそう思うわけですか? 具体的にどのような例で、クラスで分割するとうまくいって、機能を単位とすると うまくいかないわけですか? 具体例としてSEさんから出てきたのは、[1287]のこの例だけです。 http://kmaebashi.com/bbs/list.php?boardid=kmaebashibbs&from=1287&range=1 >ちなみに簡単に変更できた例は、 >メモリ上で頻繁に検索するデータが100件から6万件に変わった時の事でした。 >検索にキャッシュやヒストリー機能などあらゆる機能を組み込み高速化しましたが、 >修正したクラスは1つです。もしCの構造化で組んでいたら、修正箇所と影響範囲を >調べるだけで嫌になっていたと思います。 これを普通に読めば、なにかの検索機能という「機能を単位とした」モジュールが あって、それがうまいこと隠蔽されていたから修正箇所がそこだけで済んだ、という 話にしか読めません(誤読であればご指摘ください)。 そこで私は、「そんなものはオブジェクト指向以前の、モジュール化で達成している ことではないか(よって、オブジェクト指向の利点ではない)」と指摘しているわけです。 ここでそう書いてますよね? http://kmaebashi.com/bbs/list.php?boardid=kmaebashibbs&from=1292&range=1 >関連する操作やデータをまとめる、というのは普通にモジュール化であって、 >私が「疑りぶかい~」で書いたオセロの例の、Cでstaticで隠蔽を行った >board.cで達成していることでは? 機能単位のモジュール化では実現できず、オブジェクト指向なら実現できることの 具体例を示してもらわないと、SEさんにとってのオブジェクト指向の定義がさっぱり わからないです。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1330] Re:>(ぱ)こと管理人さん
投稿者:SE
2009/06/01 20:47:24

(ぱ)さんも感じているのではないかと思いますが、何か全てが少しづつ違うようです。 ただこの違和感は経験があります。構造化とオブジェクト指向の違いによる違和感です。 (ぱ)さんは、モジュールは「ヘッダ単位ファイル」で「機能」で分割ですね。 私は「クラス単位」で「オブジェクト」で分割です。 プログラムの組み方も変わります。イメージ的に言うと縦割りと横割りぐらい違います。 話が噛み合わないのは、この縦割りと横割りで見方が違うためでしょう。 実際、構造化プログラミングの観点で言えば、(ぱ)さんの意見は納得出来ます。 私もその観点で言えば、「クラスとカプセル化した関数は同じ」とか、 「利点をあげるとしたら見やすさ」などと言うと思います。 しかしこれは構造化ですよ。オブジェクト指向ではありません。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1329] Re:Smalltalk原理主義を粉砕せよ! (was Re: オブジェクト指向の…
投稿者:kit
2009/06/01 20:07:19

>おお、ご本人が降臨されるとは。 この BBS では、だいぶ久しぶりですよね。 実は Actor よりも Alan Kay のアイディアの方が先だったとは... 勉強になりました。_o_ >「殲滅」ではなくて「粉砕」でしたね。 >しかも対象は「Smalltalk原理主義者」ではなく「Smalltalk原理主義」。 > >主義者を殲滅というのは物騒でいかんですねえ。反省。 字面はたしかにそうでも、内容からすると「河野さんを殲滅せよ!」って感じなので、 実は合ってるかも。:-) 河野さんのボケっぷりが懐かしいですな。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1328] Re:>(ぱ)こと管理人さん
投稿者:SE
2009/06/01 14:39:00

>そういう経験もあって、2000年2月ころに書いたのがこちら。 >http://kmaebashi.com/programmer/c_yota/module.html まずモジュールの定義が私と違っていたようです。 (ぱ)さんの所で言うモジュールは「ヘッダファイル単位」で、私の言っていたのは「ライブラリ単位」だったようです。 ただ、ヘッダーファイル単位だとしてもクラス単位とは違うので、CでJavaと同じ単位ではないと思います。 >なお、なにせCなのでモジュール化の単位はクラスではないですけど、 >これはその方が都合がよいという考えでそうしています。 >Javaでも、メンバのアクセスレベルがデフォルトで「パッケージ」になっている >あたり、「実装隠蔽の単位としてクラスは適当ではない」というのが現状の >コンセンサスでいいんじゃないかと思っています。 私は、実装隠蔽の単位としてクラスは適当だと思っていて、機能を単位とするのは間違いだと思います。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1327] スレッドセーフについて
投稿者:
2009/06/01 11:32:47

 会話の上で言語仕様に食い違いがあった原因を今理解しました。私の考慮不足だったの ですが、当初より言語に求める基本機能に、スレッドセーフなシステムでした。この要求 に対しポインターや参照を操作することは、スレッドセーフを著しく阻害する要因です。  なぜなら、2つのスレッドで同じ参照を持った場合、そのデータアクセスに対しスレッド セーフを自動で行うことはとても大変であり重い処理となります。同一スレッド内でも その機構の一部が動いてしまいます。これは避けたいことです。  次の問題がもっと深刻です。参照先が複数データの場合、他の何らかのサポートなしに 参照された複数のデータをスレッドセーフにすることは原理的に不可能です。  以上2つの理由により、一番最初から、ポインターや参照を直接操作する行為は無いとの、 大前提が私の思考基本にありました。そのため、無意識にそれが前提で思考や会話をして いたことを気がつきました。よくある事ですが考慮不足です。  では、スレッド間で複数のデータを渡す場合の方法が無いのではないだろうかと思われ るでしょう。これには、変数集合体のパック、アンパック機能を提供し、複数の情報を パックして他スレッドに渡すことで、スレッドセーフを保障しています。これは始めて 説明しています。その他にもスレッドセーフを自動保障するシステムがあります。まだ 説明されていません。しばらくお待ちください。なにぶん自己検証を先にしたくて。 本当に申し訳ありません。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1326] Re:コード生成部分について
投稿者:
2009/06/01 01:48:27

>>int[] func(p1,p2,p3); >>これの int[] 配列の戻りが禁止になっています。 > >対策するのであれば、ユーザには、配列への参照自体を取得できないようにしておかな Cで言う所のポインターの存在がありません。だから、グローバル変数に参照を 入れることが出来ません。 int func(p1[],p2[]) { p1[2]=10; // これはOK p2[4]=9;    // これはOK p1=p2;     // これがエラーです } ひょっとしてdiksamはOKでしたか? (駄目だと思い込んでいました)仕様が変わっています。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1325] Re:コード生成部分について
投稿者:(ぱ)こと管理人
2009/06/01 01:30:54

>int[] func(p1,p2,p3); >これの int[] 配列の戻りが禁止になっています。 具体的にどうされているのかがよくわかりませんが、少なくとも、関数の戻り値の型として 配列型を返せないようにするだけでは不完全ではないでしょうか。 ユーザが、配列への参照を取得できるのなら、それをグローバル変数に代入することも できるはずで、もしそれをされたら、関数を抜けてスタックが開放された時点で 不正なポインタになってしまいます。 対策するのであれば、ユーザには、配列への参照自体を取得できないようにしておかないと だめなのでは。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1324] Re:コード生成部分について
投稿者:
2009/06/01 01:11:00

>ええと、ということは、そもそもユーザは配列への参照を取ることができない >(配列を引数として別関数に渡すときは内部的には参照が作られるが、ユーザがそれを >変数に代入したりすることはできない)ということでしょうか? >それなら問題ないように思います。CやJavaに慣れた身にはちょっと不便そうですが。 言葉足らずですみません。 int[] func(p1,p2,p3); これの int[] 配列の戻りが禁止になっています。 int func(p1[][],p2[]) これは問題ありません。内部で操作しても問題なく処理されます。 配列は参照渡しなので、子関数で操作したものは、呼びだし関数の配列内が変わります
[この投稿を含むスレッドを表示] [この投稿を削除]
[1323] Re:コード生成部分について
投稿者:(ぱ)こと管理人
2009/05/31 22:03:45

>>Cですごくありがちなバグである、 > 配列の参照戻しは今エラーにしています。もともと、配列は参照渡しなので、 >リターンで戻す必要を感じなかったので。 ええと、ということは、そもそもユーザは配列への参照を取ることができない (配列を引数として別関数に渡すときは内部的には参照が作られるが、ユーザがそれを 変数に代入したりすることはできない)ということでしょうか? それなら問題ないように思います。CやJavaに慣れた身にはちょっと不便そうですが。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1322] Re:コード生成部分について
投稿者:
2009/05/31 03:19:58

 やはり寝ながら思いついたアイデアは細部まで検討されていませんでした。 出来なくは無いのですが、副作用が見つかったし。やはりトリッキーでnew事態の 一般的な意味の仕様も変えてしまうのは問題が有るので、上のアイデアは 無かったことにしてください。 orz  今日は寝れそうに無くなってしまった…
[この投稿を含むスレッドを表示] [この投稿を削除]
[1321] Re:コード生成部分について
投稿者:
2009/05/31 02:48:40

>Cですごくありがちなバグである、  配列の参照戻しは今エラーにしています。もともと、配列は参照渡しなので、 リターンで戻す必要を感じなかったので。  いや~~寝ようとしたら、動的配列生成でトリッキーな方法を思いついてしまって 眠れなくなってしまいました、ここ2日間の作成をチャラにして元に戻そうかな~~  何を思いついたかと言うと、配列をnew宣言したときにスタック上の配列データの所を 開ける、その為にスタックを移動することです。スタックにリアルアドレスを持ってい るわけではないし、アドレス操作をするときは移動してないわけで。たぶん問題ないかと。  ああ~~~だめだ、思いついたらやらないでおけなくなってしまう。寝ながら だめだ、だめだ、こんな変なこと考えてはと、何度繰り返したことか。でも、どうせ 好きに作れるんだからやってしまおう^^ どう思いますか? 
[この投稿を含むスレッドを表示] [この投稿を削除]
[1320] Re:コード生成部分について
投稿者:(ぱ)こと管理人
2009/05/31 02:10:17

>>(1)Cのように、配列の領域をスタック上に取る。 >ご指摘ありがとうございます。前の書き込みからVMをいろいろ調べていましたが、 >まさに(1)の方法を取ろうと思っています。このレス読んだのがちょうど今日なん >ですよ。 この方法を取るとして、ローカルな配列への参照を、別関数に渡すことは できるのでしょうか? できるとしたら、配列への参照がプログラマの思いのままにできるということですから、 Cですごくありがちなバグである、 char *get_line() { char buf[256]; /* bufに値をつめる処理 */ return buf; } みたいなのも許すことになりませんか?
[この投稿を含むスレッドを表示] [この投稿を削除]
[1319] 配列の仕様について
投稿者:
2009/05/30 21:54:58

 上記の仕様変更により。yacc,lex部分からの修正をしています。 下に示すようなプログラムに。diksamの言語仕様と離れていってしまうのは 仕方の無いことかもしれません。それに、ほぼC言語に近くなってしまう。 ちなみに、配列変数宣言時に[]内に変数を入れるとエラーになります。 ---------------------------------------- int main(int p1,int p2) {   int aa;   string[1+2] msg = { "asd","qwe","zzz"};   int[1+1+1] i1 = {1,2,65537};   int[10][9] id;   id[5][4] = 321;   aa =id[9][8]; } ----------------------------------------  結局の所、GCを装備して配列の動的確保を可能にし、管理のための処理及び間接 アクセスのためのオーバーヘッドを許すか。領域を固定にもって直接スアクセス し、高速で単純な処理だが配列領域は宣言時に固定で確保しなければならないか。 のチョイスで有ったのではないかと思います。  私は今回、連続的な処理(一般的なプログラム)より。マルチスレッドで複数の 小さな処理の集合体による制御を優先しているので下の方を選びました。単にGCを 入れたくなかっただけかもしれませんが^^;
[この投稿を含むスレッドを表示] [この投稿を削除]
[1318] Re:>(ぱ)こと管理人さん
投稿者:(ぱ)こと管理人
2009/05/30 12:38:04

>一応、抽象化されていますが、確かに分かりにくいかもしれません。 「分かりにくい」とか「一応、抽象化」といった話ではなくて、SEさんの出した UpperStackでの継承の使い方は *間違っています*。 仮に実装継承による差分プログラミングを(いろいろの弊害は度外視して)認めると しても、それが趣旨ならUpperStackをStack型の変数に代入してはいけないし、 スタックから要素を取得するメソッドはget()をオーバーライドしてはいけません。 getUpper()のような別のメソッドを作るべきです。 たとえ「リスコフの置換原則」とかの名前を知らなくても、ポリモルフィズムを 理解していれば、当然そう考えると思うんですが。 >FileWriterを例にした方がいいかもしれません。内容的には同じ意図です。 「同じ意図です」って、どういう意図でしょうか? FileWriterがこういう継承関係になっている「意図」を理解しているのなら、 オセロ盤に棋譜を吐かせるのに、Boardクラスによりによって「ファイル名」を 渡すなどという設計がでてくるはずがないのですけど。 http://kmaebashi.com/bbs/list.php?boardid=kmaebashibbs&from=1303&range=1
[この投稿を含むスレッドを表示] [この投稿を削除]
[1317] Re:>(ぱ)こと管理人さん
投稿者:(ぱ)こと管理人
2009/05/30 12:29:14

>Cではモジュール化しようと思った所しかモジュール化しません。 >具体的に言うと、せいぜいDBアクセスとか通信部分などでしょう。 えーっ! 私がある程度大きなプログラムを最初にCで設計から実施したのは、入社2年目でしたから かれこれ15年くらいは前の話ですけれど、すべての関数をモジュールに入れていました。 5万行程度の、UNIX上のシステムで、XとMotifで画面描画するようなシステムでした。 他にもいろいろなシステムを見ましたが、数万行以上の規模なら、誰が設計しても、 まずモジュール分割はやっていたように思います。ヘッダファイルをちゃんと分離して なかったりして変なことになっているケースはよくありましたが。 そういう経験もあって、2000年2月ころに書いたのがこちら。 http://kmaebashi.com/programmer/c_yota/module.html 現在作っているcrowbarやDiksamといった言語も、モジュール分割はしています。 Diksam ver.0.2のソースにGLOBALをかましたのはこちら。 http://kmaebashi.com/programmer/devlang/diksam_src_0_2/index.html メモリ管理モジュールMEMやデバッグ用モジュールDBGの上に、コンパイラDKCと 仮想マシンのDVMがあります。その中でも機能ごとにソースファイルを分けると いったようなことはしています。 なお、なにせCなのでモジュール化の単位はクラスではないですけど、 これはその方が都合がよいという考えでそうしています。 Javaでも、メンバのアクセスレベルがデフォルトで「パッケージ」になっている あたり、「実装隠蔽の単位としてクラスは適当ではない」というのが現状の コンセンサスでいいんじゃないかと思っています。 ……それはさておき。 私も長いことこの仕事をやってますから、いろいろアレな設計やナニなソースを 見てきたつもりでいましたけど、なんだかんだでずいぶん恵まれた環境にいたのかなあ。 これでも。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1316] Re:Smalltalk原理主義を粉砕せよ! (was Re: オブジェクト指向の…
投稿者:(ぱ)こと管理人
2009/05/30 12:11:31

おお、ご本人が降臨されるとは。 >それらしいのを見つけましたがこれですか? >http://groups.google.co.jp/group/fj.comp.oops/msg/973f372a89455de2 そうですそうですこれです。 「殲滅」ではなくて「粉砕」でしたね。 しかも対象は「Smalltalk原理主義者」ではなく「Smalltalk原理主義」。 主義者を殲滅というのは物騒でいかんですねえ。反省。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1315] Re:コード生成部分について
投稿者:
2009/05/29 23:00:15

> {"new_array_int", "b", 16}, // 次元数 基本データ-型の配列生成 > {"new_array_double", "b", 20}, // 次元数 基本データ-型の配列生成 > {"new_array_object", "b", 16}, // 次元数 基本データ-型の配列生成 > {"new_array_literal_int", "s", 16}, // int定数配列を変数に接続 > {"new_array_literal_double","s", 20}, // double定数配列を変数に接続 > {"new_array_literal_object","s", 16}, // object定数配列を変数に接続 補足  このnewは構文のnewではなくスタック上に実配列生成のnewです。 ちなみに、言語上の総ての関数は特に何も記述することなくスレッドセーフに なります。複数のスレッドから関数AAAを同時に呼んでも問題が無いです。 もちろん組み込み関数も。利用者はスレッドを意識することなく自由に組んでも 問題の無い言語になります。  しかしよくよく考えてみると、この仕様がOOのクラスに合わないんです。OOP 好きな私がOOPに合わない言語を作るとは、考えてしまいます。早く作って検証 したくてなりません。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1314] Re:コード生成部分について
投稿者:
2009/05/29 22:32:50

>(1)Cのように、配列の領域をスタック上に取る。 ご指摘ありがとうございます。前の書き込みからVMをいろいろ調べていましたが、 まさに(1)の方法を取ろうと思っています。このレス読んだのがちょうど今日なん ですよ。  ちなみに、配列の添え字記述が宣言時決定でnewは無くなる方向しかないかなと 思っています。スタック上に取る以上は動的確保は無理のようで。VMコードも多少 変わってしまいました。 下記がVMコードの現在の案です。 S_OpcodeInfo D_opcode_info[] = { {"dummy", "", 0}, {"push_int_1byte", "b", 8}, {"push_int_2byte", "s", 8}, {"push_int_4byte", "i", 8}, // 実際の値を持つ {"push_double_0", "", 12}, {"push_double_1", "", 12}, {"push_double_8byte", "d", 12}, // 実際の値を持つ {"push_string", "s", 40}, // 文字列の位置NOを持つ0~ {"push_null", "", 8}, /**********/ {"push_stack_int", "s", 8}, // intローカル変数をスタックに {"push_stack_double", "s", 12}, // {"push_stack_string", "s", 40}, // {"pop_stack_int", "s", -8}, // スタックのintをローカル変数に {"pop_stack_double", "s", -12}, // {"pop_stack_string", "s", -40}, // /**********/ {"push_static_int", "s", 8}, // int静的変数をスタックに {"push_static_double", "s", 12}, // {"push_static_string", "s", 40}, // {"pop_static_int", "s", -8}, // スタックのintを静的変数に {"pop_static_double", "s", -12}, // {"pop_static_string", "s", -40}, // /**********/ {"push_sysval_int", "i", 8}, // システムグローバル変数をスタックに {"push_sysval_double", "i", 12}, // {"push_sysval_str", "i", 40}, // {"pop_sysval_int", "i", -8}, // スタックからシステムグローバル変数に {"pop_sysval_double", "i", -12}, // {"pop_sysval_str", "i", -40}, // /**********/ {"push_array_int", "", 16}, // int配列値をスタックに {"push_array_double", "", 20}, // {"push_array_string", "", 16}, // {"pop_array_int", "", -16}, // スタックからint配列に {"pop_array_double", "", -20}, // {"pop_array_string", "", -16}, // /**********/ {"add_int", "", -8}, // 以下は総て算術演算子 {"add_double", "", -12}, {"add_string", "", -40}, {"sub_int", "", -8}, {"sub_double", "", -12}, {"mul_int", "", -8}, {"mul_double", "", -12}, {"div_int", "", -8}, {"div_double", "", -12}, {"mod_int", "", -8}, {"mod_double", "", -12}, {"minus_int", "", 0}, {"minus_double","", 0}, {"increment", "", 0}, {"decrement", "", 0}, // ここまで算術演算子 {"cast_int_to_double", "", 4}, // 以下はキャスト処理 {"cast_double_to_int", "", -4}, {"cast_boolean_to_string" "", 32}, {"cast_int_to_string", "", 32}, {"cast_double_to_string", "", 28}, // ここまでキャスト処理 {"eq_int", "", -8}, // 以下は総て論理演算子 {"eq_double", "", -12}, {"eq_string", "", -40}, {"gt_int", "", -8}, {"gt_double", "", -12}, {"gt_string", "", -40}, {"ge_int", "", -8}, {"ge_double", "", -12}, {"ge_string", "", -40}, {"lt_int", "", -8}, {"lt_double", "", -12}, {"lt_string", "", -40}, {"le_int", "", -8}, {"le_double", "", -12}, {"le_string", "", -40}, {"ne_int", "", -8}, {"ne_double", "", -12}, {"ne_string", "", -40}, {"logical_and", "", -8}, {"logical_or", "", -8}, {"logical_not", "", 0}, // ここまで論理演算子 {"pop", "", -1}, // スタックを1つ減らす {"duplicate", "", 12}, // スタック内容をコピーしてスタックに {"jump", "s", 0}, // 指定ポインターにjump {"jump_if_true", "s", -1}, // スタックがtrueならjump {"jump_if_false","s", -1}, // スタックがfalseならjump /**********/ {"push_function", "sss", 0},// 関数情報をスタックに {"invoke", "", -1}, // 関数コール {"return", "", -1}, // 関数戻り /**********/ {"new_array_int", "b", 16}, // 次元数 基本データ-型の配列生成 {"new_array_double", "b", 20}, // 次元数 基本データ-型の配列生成 {"new_array_object", "b", 16}, // 次元数 基本データ-型の配列生成 {"new_array_literal_int", "s", 16}, // int定数配列を変数に接続 {"new_array_literal_double","s", 20}, // double定数配列を変数に接続 {"new_array_literal_object","s", 16}, // object定数配列を変数に接続 };  (注:ちなみに1とか-1は未定です)  上の構造だとstringがやたらスタックを食っているのは、string自体の大きさ からです。このへんが、stringを使用するのを変えてしまいそうな気分です。 ちなみに、配列は3次元まで、要素の最大は60KByteまでの制限をする予定。汎用の 言語を作るわけではないし、あくまでもローカル変数の制限だけなので、目的と 効率を優先にしています。  また、スタック構造ですが、VC++だとenumが4byte取るのでスタック対応する フラグは消して、下記のようなS_Valueに変えて、タイプとサイズを持つことに しました。で結局の所、関数のローカル変数は総てスタックに持つことでint用と double当のプールはなくしました。前に話したようにVMは出来るだけシンプルに したいので、持つデータ構造は違う形になりそうです。配列の仕様も変えてし まったし。下記の構造体をスタックで使用します //=================================================================== typedef struct { ushort dimno; // 配列の次元数 ushort dimsno[DIMMAX]; // 配列の添え字数 union { int *intDim; // int配列実態 double *doubleDim; // double配列実態 string *stringDim; // string配列実態 }u; } SV_array; //=================================================================== typedef struct { ushort vtype; // データタイプ E_StackDType ushort size; // スタック消費サイズ union { int int_value; // intデータ double double_value; // doubleデータ string *string_value // string参照 SV_array *i_array; // int配列参照 SV_array *d_array; // double配列参照 SV_array *s_array; // string配列参照 }u; } S_Value;  以上が、今日までに想定した仕様です。まだVM自体を作っていないので、まだ 変更があるかもしれません。ちなみに、組み込み関数についてはラフ案で下記の ようなクラスを使用しようと思っています。組み込み関数からのリターンはエラー コードにする予定。パラメータ可変の関数も対応します。それと変数リファレンス 情報を持って一部の関数は総ての変数をリファレンスに操作します。この点は悩み ました。文字列と配列以外は実数渡しなのですが、一部のシステム関数のみリファ レンス操作してしまうんですよ。その一部のために構文を作るべきか特殊仕様とす るかで、たった2つの関数のために構文を変えることは止めにしました。 目的優先に^^; //=================================================================== typedef struct { char *name; // 変数名 ushort gval_x; // グローバル変数横軸数 ushort gval_y; // グローバル変数縦軸数 S_Value *val_ref; // 変数参照データ S_Value val; // 変数コピーデータ } S_Value_info; //=================================================================== class C_NFBase { //-- VMに送る情報 ---------------------- char *m_name; // 関数名 int m_prmno; // 要求するパラメータ数0-10まで20は可変関数 E_ValueType m_type[PRMMAX]; // 要求するパラメータの型 E_ValueType m_rtntype; // 関数戻り値の型 //-- VMから受け取る情報 ---------------------- int m_prninno; // 引き渡されたパラメータ数 S_Value_info m_prm[PRMMAX]; // 引き渡されたパラメータデータ //-- 関数の戻り情報 ---------------------- S_Value m_return; // 関数からの戻り値データ
[この投稿を含むスレッドを表示] [この投稿を削除]
[1313] Re:>(ぱ)こと管理人さん
投稿者:yuya
2009/05/29 20:02:21

>Cではモジュール化しようと思った所しかモジュール化しません。 主語は誰なんでしょうか……。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1312] Re:>(ぱ)こと管理人さん
投稿者:774RR
2009/05/29 16:59:07

そりゃ単にプログラマの技量の問題ぢゃん。 きれいにモヂュール化された C ソースや Fortran ソースを何度も見たことあるし ぜんぜんモヂュール化されていないグチョグチョ Java ソースも見たことあるよ。 モヂュール化を言語の仕様レベルで推し進める機構があるかないか という点ならば御意。 そしてその機構に関係なくグチョグチョソースを書く下手プログラマが どこにでも、いくらでも、いるのが現実。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1311] Re:>(ぱ)こと管理人さん
投稿者:SE
2009/05/29 16:54:50

>本質は抽象化だと仰っているのにSEさんが出してるスタックの例はまったく >抽象化されていないような気がするのですが…。 一応、抽象化されていますが、確かに分かりにくいかもしれません。 FileWriterを例にした方がいいかもしれません。内容的には同じ意図です。 ----------------------------------------------------------- java.lang.Object  |  +--java.io.Writer     |     +--java.io.OutputStreamWriter        |        +--java.io.FileWriter -----------------------------------------------------------
[この投稿を含むスレッドを表示] [この投稿を削除]
[1310] Re:>(ぱ)こと管理人さん
投稿者:SE
2009/05/29 16:49:09

>Cで「単位を合わせて」モジュール化する困難さと、クラスの階層構造を適切に設計する困難さは、 >あまり違いがないように思うんですが、人によるのかな。 Cではモジュール化しようと思った所しかモジュール化しません。 具体的に言うと、せいぜいDBアクセスとか通信部分などでしょう。 Javaの場合は全てのクラスがモジュール化なのです。 現実的に実システムでは、CでJavaと同様の単位でモジュール化するのは不可能です。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1309] Smalltalk原理主義を粉砕せよ! (was Re: オブジェクト指向の…
投稿者:sumim
2009/05/29 09:01:02

>全然完璧に関係ないですが、大昔、fjに高木浩光さんが >「Smalltalk原理主義者を殲滅せよ」なんてことを書いていて(もちろんネタですが)、 >今これを探そうとしてGoogleグループを見てみたのですが… それらしいのを見つけましたがこれですか? http://groups.google.co.jp/group/fj.comp.oops/msg/973f372a89455de2
[この投稿を含むスレッドを表示] [この投稿を削除]
[1308] Re:コード生成部分について
投稿者:(ぱ)こと管理人
2009/05/29 00:51:22

>それと、GCは不要なシステムになります。INT用とdouble用の固定長プール、そして >文字列はstringに任せてしまうのでVMとしてのGCは無くなりました。 intとdoubleが固定長のプールに保持されてGCがないということは、 配列はグローバルなものだけなのでしょうか? ローカルな配列が使えないのはちょっと不便なような。 ローカルな配列を使えるようにする場合、再帰を考えれば (1)Cのように、配列の領域をスタック上に取る。  →現状のDVMには、スタック上でインデックスを指定して要素を参照する   インストラクションがないので、追加が必要。 (2)配列の領域はヒープに取るが、その参照をスタックに持つ。  →最低でも参照カウンタのGCが必要。 ということになりそうな…
[この投稿を含むスレッドを表示] [この投稿を削除]
[1307] オブジェクト指向の利点の話
投稿者:(ぱ)こと管理人
2009/05/29 00:39:49

件名変えました。 >>関連する操作やデータをまとめる、というのは普通にモジュール化であって、 >>私が「疑りぶかい~」で書いたオセロの例の、Cでstaticで隠蔽を行った >>board.cで達成していることでは? >ここが重要です。 >構造化プログラミングの「モジュール化」は基本的にモジュール化した所でしか有効ではありません。 >1つの関数で考えた場合は分かりにくいかと思いますが、関連する複数の関数での場合を考えてください。 いや、だから私が例に出したboard.cにはちゃんと複数の関数があるんですけど。 http://kmaebashi.com/programmer/object/othello.html もうSEさんが何を言いたいのかさっぱりです。 >オブジェクト指向の >利点は「再利用性が高まる事」=「変更がしやすい、変更しても壊れにくい」。 >本質は「抽象化」 >だと言う事です。 「抽象化」なんてのはおよそあらゆるプログラミングパラダイムの目的みたいなもので、 それだけでは何がなんだかさっぱりです。 >774RRさんの言う通り、「対象読者層が異なる」というだけの話のようです。 >つまり「インスタンスが複数あっていい」というあたりを理解していないプログラマ向けの文書で、 >私の指摘は「インスタンスが複数あるのは当たり前」と理解しているプログラマの視点という事です。 私もそう思っていたのですが、ちょっと疑い始めているところです。 >棋譜をセーブデータとして残すために、コンストラクタかセッターにファイル名を渡すと >言うならボードクラスに入れるのはいいと思いますが、 >名人戦の障害発生対応が違うかもしれないので、エラーログクラスを受け渡すと言うのは >おかしいと思います。 まあそのへんは要件次第で、エラーログならstaticでよいという考え方もあるでしょう (Boardが持つのは「おかしい」と言われると、それは何故かと聞きたくなりますが)。 ええと、しかも、「コンストラクタかセッターに『ファイル名を』渡す」んですか? 棋譜をファイルに吐かず、こっちの画面に出したい、とかの場合はどうするんですか? もともとLoggerの話は、SEさんの[1269]における http://kmaebashi.com/bbs/list.php?boardid=kmaebashibbs&from=1269&range=1 >これを次のように変更します。1行で済みます。 とか、 [1273]における http://kmaebashi.com/bbs/list.php?boardid=kmaebashibbs&from=1273&range=1 >遠くの所でnewした特有の処理の入ったクラスを、引数で使い回すのは、 >構造化のスタンプ結合的で、オブジェクト指向的には良くない設計です。 とかの話から出てきたものです。Loggerを引数で引き回そうが、staticで保持しようが、 遠いところでnewされたオブジェクトを、その実際のクラスがわからない状態で 使用するということに変わりはありません。そのとき、うまく使えばポリモルフィズムで 動きが変えられるというのがよく言われるオブジェクト指向の利点です。 その点、SEさんのUpperStackは、使う側がUpperStackであることを意識して使わなければ ならない(リスコフの置換原則を破っている)のでダメだ、と言っているわけです。 CばっかりずっとやってきたプログラマにJavaで設計させると、機能単位でクラス分割は するものの、 (1)何もかもstaticフィールドとメソッドで作ってしまう。 (2)staticメソッドにしない代わりに、毎回オブジェクトをnewして、いくつか  メソッドを呼んだら使い捨てにしてしまう。 このどちらかの設計にしてしまうことがあります。 正直なところ、SEさんはこの(2)のタイプの人に見えてしょうがないんですが。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1306] Re:>(ぱ)こと管理人さん
投稿者:こくぼ
2009/05/28 18:55:50

>つまり私の言いたいのは、 >オブジェクト指向の >利点は「再利用性が高まる事」=「変更がしやすい、変更しても壊れにくい」。 >本質は「抽象化」 >だと言う事です。 >利点は「見通しの良さ」 >本質は「マルチプルインスタンス」 >ではないと思います。 本質は抽象化だと仰っているのにSEさんが出してるスタックの例はまったく 抽象化されていないような気がするのですが…。
[この投稿を含むスレッドを表示] [この投稿を削除]