K.Maebashi's BBS

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

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

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

[1381] 【業務連絡】雑記帳が使えなくなっています
投稿者:(ぱ)こと管理人
2009/07/09 02:14:54

このところ更新していませんが、雑記帳 http://kmaebashi.com/zakki/index.html のページが使えなくなっています。 どうやら、(また勝手に)PHPのバージョンが5に上げられていて、 しかもなぜか雑記帳のページだけで「Call to undefined function mysql_connect()」と、 mysqlモジュールがインストールされていないかのようなエラーが出ています…… 見てのとおり、掲示板は動いているのに。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1380] Re:システム変数について
投稿者:(ぱ)こと管理人
2009/07/05 13:18:44

> なぜこの様になったかを説明しても理解してもらうのは困難と思います。 >結局(ぱ)さんにとって、奇妙な言語ができたに過ぎないのではないかと思う >にいたりました。少し残念です。 ええと、私が先の投稿で書きたかったことは、「私から見れば変に見えるけど、 (NScripterがそうであるように)それがよいという人もいるのでしょう」という ことです。お気を悪くされましたらすみません。 私から見れば奇妙な言語であることは確かですが、Domain Specific Languageが 奇妙な言語に見えるのはよくあることですし、奇妙な言語でなければ、わざわざ 自作する価値がない、とも言えるでしょう(その意味で、crowbarやDiksamは 「おとなしすぎる」んだよなー)。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1379] Re:システム変数について
投稿者:
2009/07/03 22:04:56

 ここ数日いろいろ考えたすえ、プロのプログラマやプログラミングに精通して いる人ほど抵抗が大きいと思いました。当初は#defineでは、との返信もありま したが、結局の所シートを前面に出す以上、座標の変数が使われることが多いで しょう。  なぜこの様になったかを説明しても理解してもらうのは困難と思います。 結局(ぱ)さんにとって、奇妙な言語ができたに過ぎないのではないかと思う にいたりました。少し残念です。  今は、マルチスレッド化に専念しています。仕組みのベースがほぼ出来上がっ たので、より深く検証した上で本体に組み込と試験になります。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1378] Re:システム変数について
投稿者:(ぱ)こと管理人
2009/07/01 02:35:56

> 変数名は 「シート+列+データ型+項目番号」 = AAI000 となります。だから >自由に変数名はつけれない。それを解消するために#defnieが必衰でした。 こ、これは…… 名前が連番というのは私にはちょっと、と思いますし、この方法でプログラムを 作るとなると、「システム変数レイアウトシート」みたいなドキュメント(方眼紙か Excelシート?)上で、「ここからここまでにはこのデータを入れて…」といった 管理をしなければならなさそうです。ソースから離れたところにドキュメントが 必要になるのは、メンテナンスされないのでは、と心配になります。 ……というのが私の感想ですが、たとえばゲーム業界ではNScripterという言語が 結構広く使われているようなのですが、この言語は変数名が連番です。 http://kamakura.cool.ne.jp/o_show/nscripter/syo/08.htm 私の感覚ではのけぞってしまいますが、ユーザがいる以上、この仕様がよいという 人がいるということなのでしょう(山さんは、#defineでセル名を隠そうとして いますから、連番がよいと思っておられるわけではないと思いますが)。 あと、システム変数がこういう形式だと、入力フォームや出力帳票に直接 結びつけることができると便利かもしれませんね。 なつかしのRPGあたりを彷彿とさせますが。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1377] Re:システム変数について
投稿者:
2009/06/30 19:08:00

 さすが(ぱ)さんと言うか、鋭い突っ込みありがとうございます。実はシステム変数に ついては多少触れるのを避けていました。。なぜなら(ぱ)さんの「表計算ソフトって」 のコラムで表についての意見を読んでいて、まさにその表を言語に組み込もうとしている のです。だから、完成する前にキツイ指摘を受けるのではないかと…  システム変数は、簡単に説明すると。項と列によって構成されるシートが基本で、この シートによって複数の機能と特徴を持っています。   Aシート    ・・・~・・・     Zシート (26シート)   ----------- ------------   | | | |   | | | |   ----------- ------------  このシート名が変数の最初の「A」にあたり   000 ...................................... 999 (1000個の項目) ------------------------------------------------- A | | ・・・ | | : | | --------------------- | | Z | | | int double string | | | a | | --------------------- | | : | | ↑一つのセルの中に | | : | | 3つのデータがある | | z | | ・・・ | | ------------------------------------------------- (52の列)  変数名は 「シート+列+データ型+項目番号」 = AAI000 となります。だから 自由に変数名はつけれない。それを解消するために#defnieが必衰でした。  ちなみに、システム変数にアクセスする方法は、直値=AAI001と言う形と、相対配列 =ABI010「X][Y] これは、指定の座標から項にX値の相対座標指定、列にY値の相対座標を 指定してアクセスします。 ABI010[X] は項目のX相対座標指定です。  もともとこのシート形式は、目的アプリケーションで必要だった機能を実現する為の 些細なアイデアでした。しかし、言語を作っていく上でシステムの基本となり。言語上 でもかなめ的要素(中心的要素)になったのです。注意、EXCELを作るわけではありません。  ここからは既存の言語的常識を一時保留にして読んでください。  例えば、市役所等での情報の伝達はシート、書式を持った紙です。市民登録、婚姻届等に 必要な項目を記入し提出する。それを受け取り保存する。別にガッシリとデータ定義された 構造体やclassがあるわけではありません。記入する方も総ての項目を初期化したり記入し たりしません、必要な項目のみ記入して提出します。  このイメージをモジュール間の情報伝達に使用しようと考えたのです。例えばシートAに に必要なことを書いて、他のモジュールに動作指示を出す。その時シート名を伝達するだ けでいい、構造体やclassは不要です。なおかつしたい事の種類のよって、多くの構造体や 多くのクラス定義が必要になったりしますが、シートでは必要な部分だけを書けばいい。  と発想したのが元です。  情報伝達の単位は、最小のint,double,string、そして一つのセル、相対X領域,相対Y領域、 相対矩形の領域、列、シート、そしてパックされた情報の8つの単位で情報伝達を考えてい ます。この処理単位で情報伝達するために、言語は関数内では普通の言語的整合性を持って いますが、一歩外のグローバルではシステム変数で情報伝達する。その結果グローバル変数 はシステム変数となり、言語的整合性ではなくシステムの目的にそって作られています。 補足 1、一つのセルの中にint,double,stringデータの情報が入っているのは、もともとはデータ の型別にシートが分かれていました。しかし、リストやソート、検索、辞書(map)の場合、 3つのデータをまとめて処理したほうが利便性がいいとの理由です。そのため1セルに3つの 情報を入れました。しかし、変数としては別々にアクセスします。  例えばstringでソートした場合、intもdoubleもいっしょにソートされます。  例えば、intに優先NOが入っていたら、intでソートしたら文字列もいっしょにソート されます。  利便性の目的のためだけに、3つの情報を一セルに入れました。 2、パックされた情報は、stringデータに入ります。なのでstringデータは複数のデータ を大量に保持することが出来ます。 3.システム変数を言語内の変数と同じように、透過的にアクセスできるように作れたため、 システム変数の操作を速くする事ができた。これは、関数を用いてシステム変数を操作する ことを思えば、スレッドセーフでも、格段に融通が利き速い動作を保証できる。 最後に  この言語だけでは、奇妙な言語が一つ出来ただけの事です。この仕組が受け入れられる かは、その上に乗ったアプリケーションが洗練されていて使いやすく受け入れるか如何に かかっています。ここから先はいかにいい物を作るかだけでしょう。それに、言語の 初心者を対象にしているので、ここからはバリバリな日本語化に走ります。  プログラミング言語ができる人は、C/C++なりJavaなり、その他各種汎用言語を使って ください。がベースにあります。^^  今ある汎用言語は洗練されていて複雑で優秀です。だから私がいまさら作る意味が無い ですし。 追加の補足  上記のことを書いた後に、グローバル変数でもいいのではないか。の発想もありますが、 その場合、情報の集合体としての構造体やclassが必要です。でも、移転届用紙のような 多数の関係の薄そうなデータ総てを構造体やclassに入れるのは、根本的にシステム設計 が間違っている方向でしょう。やはり書式用紙に代表されるデータ構造と、プログラム上の データ構造とは明らかに違っています。プログラムでは関連のあるデータを参照やキー 情報、その他関連情報で持ちます。しかし、この構造は前にも話したように他の何かの サポート無しに完全な一意の意味を保証することは不可能です。  でも、シート形式なら完全かと言うとそうでもありません。実は時系列な情報変化の 保証は出来ないのです。これはあきらめています。時系列的な情報の変化とは、転移届を 受理して完全に処理される前に。同じ人から違う転移届を受け取ってしまった場合の矛盾 です。 これは外部の何らかのサポート、受理処理が完全に終了するまで受け付けない フラグ等のサポートが必要になり。これはシステムではなく、プログラマがそれを理解し 作らなければならないのです。  完全なデータフローマシンでも作ればいいのですが、そのプログラミングはまた違った、 別の複雑な知識が必要になってきます。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1376] Re:システム変数について
投稿者:(ぱ)こと管理人
2009/06/30 01:22:32

> システム変数は宣言だけが違い、多少特殊ですが普通の変数と同じように >使用できます。なおかつスレッドセーフで使用できます。 (中略) > sysval("AAS001",CREATION); 割と素朴な疑問だと思うんですが、システム変数の宣言がこのように関数形式だとすると、 システム変数の型について、コンパイラは知らないままだということになりませんか? ……と思ったのですが、「AAS」という名前がstring型だという型宣言を兼ねている (かつそれをコンパイラが解釈する)のでしょうか? > sysval("AAI001-ACI005",CREATION); そして、こういう書き方だと、AA「I」なので、intの配列の宣言になる、と。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1375] システム変数について
投稿者:
2009/06/29 17:53:00

 ようやくシステム変数の組込みが終わりました。下記に示すような感じで 使用します。上にある#defineは、システムのヘッダーファイルになり。 #includeされます。 また今回は日本語プログラムにするとこんな感じに なります。と言った感じのプログラムリストです。  システム変数は宣言だけが違い、多少特殊ですが普通の変数と同じように 使用できます。なおかつスレッドセーフで使用できます。 //-- システム変数定義ヘッダーファイル -------------- #define システム変数 sysval #define 生成 1 // システム変数使用 #define 廃棄 2 // システム変数廃棄 #define クリア 3 // システム変数を初期化 #define リスト 4 // システム変数のリスト宣言 #define 辞書 5 // システム変数の辞書宣言(予約) #define 昇順ソート 6 // システム変数をソート #define 降順ソート 7 // システム変数をソート #define システム変数検索 sysval_find #define 線形 1 // システム変数リストを線形検索 #define 二分 2 // システム変数リストを二分検索 #define 辞書 3 // システム変数辞書検索(予約) #define システム変数リスト挿入 sysval_push_list #define システム変数リスト取出 sysval_pop_list #define 先頭 1 // システム変数リストの先頭 #define 最後 2 // システム変数リストの最後 //-- 日本語定義ヘッダーファイル ------------------ #define メイン main #define 表示 print #define 文字列 string #define 整数 int //------------------------------------------------ //-- 日本語で書いた場合 ----------------- 整数 表示(文字列 str); 整数 システム変数(文字列 str,整数 type); 整数 メイン() { システム変数("AAS001",生成); システム変数("AAI001-ACI005",生成); システム変数("BAD001-BCD005",生成); システム変数("CAS001-CCS005",生成); AAS001 = "testdata"; 表示("AAS001 = " + AAS001 + "--\n\n"); AAI001[3][1] = 33; BAD002[2] = 3.2; CAS003[1] = "aaa"; 表示("AAI001 = " + AAI001[3][1] + "--\n\n"); 表示("BAD002 = " + BAD002[2] + "--\n\n"); 表示("CAS003 = " + CAS003[1] + "--\n\n"); } //-----------------------------------    ↓    ↓まったく同じプログラムで英語で書いた場合    ↓ //----------------------------------- int print(string str); int sysval(string str,int type); int main() { sysval("AAS001",CREATION); sysval("AAI001-ACI005",CREATION); sysval("BAD001-BCD005",CREATION); sysval("CAS001-CCS005",CREATION); AAS001 = "testdata"; print("AAS001 = " + AAS001 + "--\n\n"); AAI001[3][1] = 33; BAD002[2] = 3.2; CAS003[1] = "aaa"; print("AAI001 = " + AAI001[3][1] + "--\n\n"); print("BAD002 = " + BAD002[2] + "--\n\n"); print("CAS003 = " + CAS003[1] + "--\n\n"); } -----------------------------------    ↓    ↓日本語版も英語版まったく同じ下記のコードになります。    ↓ ------------------------------------ 1:*** 一般関数情報ダンプ ****************** 1:int main() 1:*** 配列定数 数 = 0 ********** 1:*** 文字列 数 = 23 *** 1: 0: "main" 1: 1: "AAS001" 1: 2: "sysval" 1: 3: "AAI001-ACI005" 1: 4: "sysval" 1: 5: "BAD001-BCD005" 1: 6: "sysval" 1: 7: "CAS001-CCS005" 1: 8: "sysval" 1: 9: "testdata" 1: 10: "AAS001 = " 1: 11: "-- " 1: 12: "print" 1: 13: "aaa" 1: 14: "AAI001 = " 1: 15: "-- " 1: 16: "print" 1: 17: "BAD002 = " 1: 18: "-- " 1: 19: "print" 1: 20: "CAS003 = " 1: 21: "-- " 1: 22: "print" 1:*** 使用予定のスタックサイズ = 1292 1:*** 関数コードのディスアセンブラ size = 223 1: 0 push_string_const 1 1: 3 push_int_1byte 1 1: 5 call_function 2 0 0 2 1: 14 pop 1: 15 push_string_const 3 1: 18 push_int_1byte 1 1: 20 call_function 4 0 0 2 1: 29 pop 1: 30 push_string_const 5 1: 33 push_int_1byte 1 1: 35 call_function 6 0 0 2 1: 44 pop 1: 45 push_string_const 7 1: 48 push_int_1byte 1 1: 50 call_function 8 0 0 2 1: 59 pop 1: 60 push_string_const 9 1: 63 pop_sysval_str 3-0-1 1: 68 push_string_const 10 1: 71 push_sysval_str 3-0-1 1: 76 add_string 1: 77 push_string_const 11 1: 80 add_string 1: 81 call_function 12 0 0 1 1: 90 pop 1: 91 push_int_1byte 33 1: 93 push_sysval_array 1-0-1 1: 98 push_int_1byte 3 1: 100 push_array_int 1 1: 102 push_int_1byte 1 1: 104 pop_array_int 1: 105 push_double_8byte 3.200000e+000 1: 114 push_sysval_array 2-52-2 1: 119 push_int_1byte 2 1: 121 pop_array_double 1: 122 push_string_const 13 1: 125 push_sysval_array 3-104-3 1: 130 push_int_1byte 1 1: 132 pop_array_string 1: 133 push_string_const 14 1: 136 push_sysval_array 1-0-1 1: 141 push_int_1byte 3 1: 143 push_array_int 1 1: 145 push_int_1byte 1 1: 147 push_array_int 0 1: 149 cast_int_to_string 1: 150 add_string 1: 151 push_string_const 15 1: 154 add_string 1: 155 call_function 16 0 0 1 1: 164 pop 1: 165 push_string_const 17 1: 168 push_sysval_array 2-52-2 1: 173 push_int_1byte 2 1: 175 push_array_double 0 1: 177 cast_double_to_string 1: 178 add_string 1: 179 push_string_const 18 1: 182 add_string 1: 183 call_function 19 0 0 1 1: 192 pop 1: 193 push_string_const 20 1: 196 push_sysval_array 3-104-3 1: 201 push_int_1byte 1 1: 203 push_array_string 0 1: 205 add_string 1: 206 push_string_const 21 1: 209 add_string 1: 210 call_function 22 0 0 1 1: 219 pop 1: 220 push_int_1byte 0 1: 222 return 1:*** 行情報 数 = 14 *** 1: 20: from 0 size 15 1: 21: from 15 size 15 1: 22: from 30 size 15 1: 23: from 45 size 15 1: 24: from 60 size 8 1: 25: from 68 size 23 1: 26: from 91 size 14 1: 27: from 105 size 17 1: 28: from 122 size 11 1: 29: from 133 size 32 1: 30: from 165 size 28 1: 31: from 193 size 27 1: 154: from 220 size 2 1: 32: from 222 size 1 1:*** end of main() -------------- --------------------------------------------------
[この投稿を含むスレッドを表示] [この投稿を削除]
[1374] Re:関数の再起について
投稿者:
2009/06/25 00:09:10

お返事遅れてすみません。 >ええと、細かいことですが「再起」ではなく「再帰」ですね。 うはは~~指摘ありがとうございます。思わぬミスをよくします。 >ファイバーとか考えるなら再考の必要がありますね……  ファイバーのことを考えてたら、 「ファイバーは関数ではなく、コードの一部を空きスレッドに渡すだけで実行だな」 と考えていたら下記の点を気がつきました。  今までは、スレッドは実行時にオブジェクト生成とスレッド起動を考えていま したが、良くよく考えれば毎回不必要ですね。初期に10なり20なり起動して待ち 状態で待たせ、その後プログラムのスレッド実行は空きスレッドで即実行を^^  この方法で組み込むことにしました。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1373] Re:関数の再起について
投稿者:(ぱ)こと管理人
2009/06/23 02:34:39

ええと、細かいことですが「再起」ではなく「再帰」ですね。 >その後言語内の関数実行部を >作ったのですが。そのまま、再起で実行する部分を使って組み込んだために、関数実行 >はVM実行部の再起になっています。 了解です。 再帰を使わずに作ると、例外処理機構でCの呼び出し階層を遡らなくてよいとか、 ファイバーのような機能を作るときに現在の実行状態を退避できるとかの メリットがあると思いますが、例外処理をDiksamで作ってみたら、再帰を使っている crowbarの例外処理よりもかえって大変だったような気がしますし、再帰なら 再帰でかまわないと思います。 実はDiksamでもネイティブ関数からDiksam関数を呼ぶところは再帰なので、 ファイバーとか考えるなら再考の必要がありますね…… >う~~んどうしようか、当面このままでいこうと思います。既に出来てしまっ >てるし。スタックを増やさない限り再起が450回しか出来ない欠点はあるけど。 実用的には使われてないであろうcrowbarはさておき、RubyやPerlもCのスタックを 使ってガンガン再帰してますからねえ。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1372] Re:関数の再起について
投稿者:
2009/06/22 19:06:01

>すみません、いまいちよくわからないです。関数呼び出しのたびにVM起動して >いるわけではないですよね? そうだった、VMが違うものでした。簡単にVMの構造を説明します。 ↓AP管理からVMとして起動される -------------------------------------- |      VM管理システム      | --------------------------------------  ↓     ・・・       ↓    ------    ------    |   |    |   |    | V |    | V |    | M |    ・・・     | M |    | 実 |    | 実 |    | 行 |    | 行 |    | 部 |    | 部 |    |   |    |   |    ------    ------  VMは上記のような構造をしています。VM管理システムは1つのスレッドで、VM実行 部のスレッド実行管理と各種サービスを提供します。機能は、  ・マルチスレッドでVM実行部の起動・停止・廃棄等の実行管理  ・動的コンパイルの管理、関数の管理  ・タイムスケジュールの管理(タイマーキューの生成と管理)  ・スレッドの実行優先順位管理(キューに優先順位がありその管理)  ・メッセージキューの管理(スレッドの実行はキューによって行われる)  ・グローバル変数の管理  ・その他各種IOや外部機能インターフェースの管理  ・言語のデバック機能  ・上記サービスをスレッドセーフで提供するための排他制御管理 等のいろいろな機能があり、それなりに大きなプログラムです。  それに対し、VM実行部は純粋にバイトコードを実行する以外何の機能も持っていま せん。VM実行部は1つのクラスで、そのオブジェクト一つが1スレッドになり、マルチ スレッドが実行可能であり、VM実行部が再起実行しても問題の無い仕様です。 そして、出来る限り単純で最小になるように作られています。  で^^;、最初に組込み関数部分を作りましたが、その時組込み関数から言語内の関数 を自由に起動したり廃棄したり、スレッド起動したり出来るように作ったので、それを 実行する一番いい方法はVM実行部の再起的実行でした。その後言語内の関数実行部を 作ったのですが。そのまま、再起で実行する部分を使って組み込んだために、関数実行 はVM実行部の再起になっています。今思えば別に再起しなくても良かったかな。^^;  今の実装の欠点は、VMのスタックを消費することと、ほんの少しのオーバーヘッド。 今の方法の利点は関数実行や管理が一元管理されて、プログラム的にすっきりしている。 かな、う~~んどうしようか、当面このままでいこうと思います。既に出来てしまっ てるし。スタックを増やさない限り再起が450回しか出来ない欠点はあるけど。 >なお、現在はDiksamはシングルスレッドですが、スレッドを分けるなら、 >VMのスタックも分離する必要があると考えています。 こちらも、1スレッドおきにスタック領域が作られます。そのためスタック領域はあまり 大きくしたくなっかったので。 ちなみにVM実行部の起動は S_Func_Val * CL_VMexe::execute(CL_Function *sfp,int stackp); 引数は関数情報と戻りスタックポインターです。ローカル変数をスタックに作成後すぐに S_Func_Val * CL_VMexe::execute_code(); のコード実行部が呼ばれる単純な構造です。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1371] Re:関数の再起について
投稿者:(ぱ)こと管理人
2009/06/22 01:46:36

> 関数の再起についてですが、VC++ の標準スタックでデバックビルドの時、 >約460回の再起が可能です。その結果上限として450回を超えたらエラーとし、 >エラー表示とともに関数コールをせずにリターンする処理としました。 >リリースビルドでは多分この数倍いけると思いますが、450回も出来ればOK >だと考えています。スレッド分複数VM起動もしますから。 >diksamではどの様にしていますか? ええと、解析木を再帰でほじって実行するcrowbarならいざしらず、Diksamでは、 Diksamの関数をいくら再帰呼び出ししても、Cのスタックは消費しません。 DVMのスタック(ヒープに確保される)が伸びていくだけです。 なお、現在はDiksamはシングルスレッドですが、スレッドを分けるなら、 DVMのスタックも分離する必要があると考えています。 すみません、いまいちよくわからないです。関数呼び出しのたびにVM起動して いるわけではないですよね?
[この投稿を含むスレッドを表示] [この投稿を削除]
[1370] 関数の再起について
投稿者:
2009/06/22 00:27:40

 関数の再起についてですが、VC++ の標準スタックでデバックビルドの時、 約460回の再起が可能です。その結果上限として450回を超えたらエラーとし、 エラー表示とともに関数コールをせずにリターンする処理としました。 リリースビルドでは多分この数倍いけると思いますが、450回も出来ればOK だと考えています。スレッド分複数VM起動もしますから。 diksamではどの様にしていますか?
[この投稿を含むスレッドを表示] [この投稿を削除]
[1369] Re:配列の実装について
投稿者:
2009/06/20 21:10:37

>本のページの準備やらに追われていまして遅くなりましてすみません。 いえいえ >つまり、Cと同じですね。現実的な落としどころかと思います。 はい、まさにその通りです。スタックに固定で配列を既述する以上。 定数指定も固定にした方が統一的であるし、中身を替えたければ 個別に入れ替えればいいので、この方法にしました。 配列アクセスも直接インデックスなので多少速いですし。 diksamのテストプログラムは、配列の修正とnull削除で総て正しく 動いています。nullは参照の操作が無いのでなくなりました。 今は、システムグローバル変数の組み込みを行っています。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1368] Re:プログラミング言語を作る 書籍
投稿者:(ぱ)こと管理人
2009/06/20 13:46:11

>木曜日に三省堂神保町店で購入しました。ジュンク堂池袋店では、水曜日に入荷してたみたいです。 >http://twitter.com/junkudo_ike_pc/status/2203461804 お買い上げいただきありがとうございます (_o_) 編集さんからは19日ごろからと聞いていたので、サンプルコードをダウンロードできる ページについて、トップからリンクしたのが木曜の晩(というか金曜明け方)、 リンクはしないが暫定公開として配置したのが水曜の晩(というか木曜明け方)でした。 微妙に間に合いませんでした。こころあたりの方は再度見に来ていただきたく、 よろしくお願いいたします……(ここに書いても仕方がないかもしれませんけど) >書店で見つけて、お!と思ったのが書籍のサイズでした。コンパイラ系の本は大学の教科書(まえがきにある∩とかの)風でサイズはA5版が多いように思います(ドラゴンブックも)。 版型の決定については私は関わっていませんが、ゲラを見たとき、思ったより 文字サイズや余白が大きいな、とは思いました。かなり書きすぎた自覚があったので(^^; もっと詰め込まれるのではないかと。少なくとも版型に関しては読みやすい形で まとめていただけたと思っています。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1367] Re:配列の実装について
投稿者:(ぱ)こと管理人
2009/06/20 13:31:48

本のページの準備やらに追われていまして遅くなりましてすみません。 > 下記のように、配列の定数は配列定数バッファーに詰め込んで保持し、1命令で >配列変数に書き込みです。 つまり、Cと同じですね。現実的な落としどころかと思います。 リテラルに定数式しか書けなくなっているかとは思いますが。 つまりC同様、 double[] sin_table = {sin(0), sin(0.2*M_PI), sin(0.4*M_PI), ...}; のような書き方はできませんよね。実際使用することがそうそうあるとは 思えないので、問題ないと思いますが。 そういえば、昔のCは、ローカル変数の配列に初期化子を書くときはstaticしか許さない、 ということになっていました。でも、これで困ることも別段なかった気がしますし。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1366] Re:プログラミング言語を作る 書籍
投稿者:さとう
2009/06/20 00:46:11

木曜日に三省堂神保町店で購入しました。ジュンク堂池袋店では、水曜日に入荷してたみたいです。 http://twitter.com/junkudo_ike_pc/status/2203461804 書店で見つけて、お!と思ったのが書籍のサイズでした。コンパイラ系の本は大学の教科書(まえがきにある∩とかの)風でサイズはA5版が多いように思います(ドラゴンブックも)。 Webの連載を見ていなかったので、GC、VM、クラス、クロージャなどと類書にはなかなか見られない内容までを含むとは思ってもみませんでした。読みこなすのは大変ですが、なんとか読んでいこうと思います。 はてなをみて、ページ下部のおまけに気がつきました^^。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1365] Re:配列の実装について
投稿者:
2009/06/17 20:22:31

 これで、diksam0.2.0の機能で必要な部分は総て組み込むことが出来ました。 これからが本当の目的部分です。グローバルシステム変数関係、マルチスレッド システム関係。等々を組み込んだら言語としては完了となります。  そして、本当の目的アプリケーション…、まて、言語のデバックシステムの 組み込みが。簡単なIDEを組み込みます。まだまだです。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1364] Re:配列の実装について
投稿者:
2009/06/17 20:17:37

 配列の組み込みにより、バイトコードもまた変わりました、下記に。 S_OpcodeInfo D_opcode_info[] = { {"dummy", "", 0}, {"push_int_1byte", "b",16}, {"push_int_2byte", "s",16}, {"push_int_4byte", "i",16}, // 実際の値を持つ {"push_double_0", "", 16}, {"push_double_1", "", 16}, {"push_double_8byte", "d",16}, // 実際の値を持つ {"push_string_const", "s",40}, // 文字列の位置NOを持つ0~ {"push_null", "", 16}, /**********/ {"push_stack_array", "s", 16}, // 配列情報をスタックに {"push_stack_int", "s", 16}, // intローカル変数をi {"push_stack_double", "s", 16}, // {"push_stack_string", "s", 40}, // {"pop_stack_int", "s", -16}, // スタックのintをローカル変数に {"pop_stack_double", "s", -16}, // {"pop_stack_string", "s", -40}, // /**********/ {"push_static_array", "s", 16}, // 配列情報をスタックに 予約 {"push_static_int", "s", 16}, // int静的変数をスタックに 予約 {"push_static_double","s", 16}, // {"push_static_string","s", 40}, // {"pop_static_int", "s", -16}, // スタックのintを静的変数に 予約 {"pop_static_double", "s", -16}, // {"pop_static_string", "s", -40}, // /**********/ {"push_sysval_array", "i", 16}, // 配列情報をスタックに {"push_sysval_int", "i", 16}, // システムグローバル変数をスタックに {"push_sysval_double","i", 16}, // {"push_sysval_str", "i", 40}, // {"pop_sysval_int", "i", -16}, // スタックからシステムグローバル変数に {"pop_sysval_double", "i", -16}, // {"pop_sysval_str", "i", -40}, // /**********/ {"push_array_int", "", -1}, // int配列処理 {"push_array_double", "", -1}, // {"push_array_string", "", -1}, // {"pop_array_int", "", -1}, // スタックからint配列に {"pop_array_double", "", -1}, // {"pop_array_string", "", -1}, // /**********/ {"add_int", "", -16}, // 以下は総て算術演算子 {"add_double", "", -16}, {"add_string", "", -40}, {"sub_int", "", -16}, {"sub_double", "", -16}, {"mul_int", "", -16}, {"mul_double", "", -16}, {"div_int", "", -16}, {"div_double", "", -16}, {"mod_int", "", -16}, {"mod_double", "", -16}, {"minus_int", "", 0}, {"minus_double", "", 0}, {"increment", "", 0}, {"decrement", "", 0}, // ここまで算術演算子 {"cast_int_to_double", "", 0}, // 以下はキャスト処理 {"cast_double_to_int", "", -0}, {"cast_boolean_to_string", "", 24}, {"cast_int_to_string", "", 24}, {"cast_double_to_string", "", 24}, // ここまでキャスト処理 {"eq_int", "", -16}, // 以下は総て論理演算子 {"eq_double", "", -16}, {"eq_string", "", -40}, {"gt_int", "", -16}, {"gt_double", "", -16}, {"gt_string", "", -40}, {"ge_int", "", -16}, {"ge_double", "", -16}, {"ge_string", "", -40}, {"lt_int", "", -16}, {"lt_double", "", -16}, {"lt_string", "", -40}, {"le_int", "", -16}, {"le_double", "", -16}, {"le_string", "", -40}, {"ne_int", "", -16}, {"ne_double", "", -16}, {"ne_string", "", -40}, // ここまで論理演算子 {"logical_and", "", -16}, // {"logical_or", "", -16}, // {"logical_not", "", 0}, // {"pop", "", -1}, // スタックを1つ減らす {"duplicate", "", 16}, // スタック内容をコピーしてスタックに {"jump", "s", 0}, // 指定ポインターにjump {"jump_if_true", "s", -16}, // スタックがtrueならjump {"jump_if_false","s", -16}, // スタックがfalseならjump /**********/ {"push_function", "", 0}, // 関数情報をスタック、未使用 {"call_function","ssss", 1}, // 関数コール {"return", "", -1}, // 関数戻り /**********/ {"set_array_literal_int", "ss", 0}, // int定数配列を変数にコピー {"set_array_literal_double","ss", 0}, // double定数配列を変数にコピー {"set_array_literal_string","ss", 0}, // string定数配列を変数にコピー };
[この投稿を含むスレッドを表示] [この投稿を削除]
[1363] 配列の実装について
投稿者:
2009/06/17 20:11:21

 配列の実装は、結果的にまったく違うものになっています。配列領域を固定で スタックに持つことでGCを無くす。この目的のために結果的に多くの修正をしま した。下記のようなプログラムとディスアセンブルコードを見てください。  この並列はずいぶん悩みましたが、結果的に一番良いであろう方法に落ち着き ました。 ---------------------------------- int main() { int[2][3] i5dim; int id = 33; boolean[2] bdim1 = { true , false }; int[2][3] idim21 = {{1,2,3},{4,300,65536}}; int[2][3][4] idim3 = {{{1,2,3,4},{5,6,7,300},{8,9,10,11}}, {{11,12,13,65536},{14,15,16,17},{18,19,20,21}}}; double[4] ddim1 = { 0.0, 1.0, 4.1, 5.1 }; string[5] sdim1 = {"aa","bb","cc","dd","ee"}; int a1; i5dim[1][2] = 1; a1 = i5dim[i5dim[1][2]][0]; } ----------------------------------   ↓  下記のように、配列の定数は配列定数バッファーに詰め込んで保持し、1命令で 配列変数に書き込みです。もちろん配列数と一致したデータ以外はエラーです。 また、変数の配列次元数が一致しない場合もエラーになる処理が入っています。 int[10] P; P = P; の様なポインター的なコードが書けない仕様です。   ↓ バイトコード   ↓ 1:*** 一般関数情報ダンプ ****************** 1:int main() 1:*** ローカル変数の表示 no = 8 *** 1: 0:int [2][3] i5dim 1: 1:int id 1: 2:boolean [2] bdim1 1: 3:int [2][3] idim21 1: 4:int [2][3][4] idim3 1: 5:double [4] ddim1 1: 6:string [5] sdim1 1: 7:int a1 1:*** 配列定数 数 = 5 ********** 1: 0:int 配列 [2] size=20 1:int[0] = 1 1:int[1] = 0 1: 1:int 配列 [2][3] size=36 1:int[0][0] = 1 1:int[0][1] = 2 1:int[0][2] = 3 1:int[1][0] = 4 1:int[1][1] = 300 1:int[1][2] = 65536 1: 2:int 配列 [2][3][4] size=108 1:int[0][0][0] = 1 1:int[0][0][1] = 2 1:int[0][0][2] = 3 1:int[0][0][3] = 4 1:int[0][1][0] = 5 1:int[0][1][1] = 6 1:int[0][1][2] = 7 1:int[0][1][3] = 300 1:int[0][2][0] = 8 1:int[0][2][1] = 9 1:int[0][2][2] = 10 1:int[0][2][3] = 11 1:int[1][0][0] = 11 1:int[1][0][1] = 12 1:int[1][0][2] = 13 1:int[1][0][3] = 65536 1:int[1][1][0] = 14 1:int[1][1][1] = 15 1:int[1][1][2] = 16 1:int[1][1][3] = 17 1:int[1][2][0] = 18 1:int[1][2][1] = 19 1:int[1][2][2] = 20 1:int[1][2][3] = 21 1: 3:double 配列 [4] size=44 1:double[0] = 0.000000 1:double[1] = 1.000000 1:double[2] = 4.100000 1:double[3] = 5.100000 1: 4:string_no 配列 [5] size=32 1:string[0] = 9 1:string[1] = 10 1:string[2] = 11 1:string[3] = 12 1:string[4] = 13 1:*** 文字列 数 = 14 *** 1: 0: "main" 1: 1: "i5dim" 1: 2: "id" 1: 3: "bdim1" 1: 4: "idim21" 1: 5: "idim3" 1: 6: "ddim1" 1: 7: "sdim1" 1: 8: "a1" 1: 9: "aa" 1: 10: "bb" 1: 11: "cc" 1: 12: "dd" 1: 13: "ee" 1:*** 使用予定のスタックサイズ = 426 1:*** 関数コードのディスアセンブラ size = 63 1: 0 push_int_1byte 33 1: 2 pop_stack_int 1 1: 5 set_array_literal_int 0 2 1: 10 set_array_literal_int 1 3 1: 15 set_array_literal_int 2 4 1: 20 set_array_literal_double 3 5 1: 25 set_array_literal_string 4 6 1: 30 push_int_1byte 1 1: 32 push_stack_array 0 1: 35 push_int_1byte 1 1: 37 push_array_int 1: 38 push_int_1byte 2 1: 40 pop_array_int 1: 41 push_stack_array 0 1: 44 push_stack_array 0 1: 47 push_int_1byte 1 1: 49 push_array_int 1: 50 push_int_1byte 2 1: 52 push_array_int 1: 53 push_array_int 1: 54 push_int_1byte 0 1: 56 push_array_int 1: 57 pop_stack_int 7 1: 60 push_int_1byte 0 1: 62 return 1:*** 行情報 数 = 10 *** 1: 4: from 0 size 5 1: 5: from 5 size 5 1: 6: from 10 size 5 1: 8: from 15 size 5 1: 9: from 20 size 5 1: 10: from 25 size 5 1: 13: from 30 size 11 1: 14: from 41 size 19 1: 19: from 60 size 2 1: 15: from 62 size 1 1:*** end of main() --------------
[この投稿を含むスレッドを表示] [この投稿を削除]
[1362] Re:その後のVM
投稿者:
2009/06/17 19:52:00

>ここで埋め込まれる関数インデックスって、VM内で一意になるんですよね? >だとすれば、コンパイル単位の破棄の際に破棄対象の関数が使っていたインデックスの >ところをぎゅっと圧縮しようとさえ思わなければ、そもそも振りなおし自体不要なのでは >ないかと思うのですが…… 同じ所に、こう書いてあります。 >> 次にスピードの点ですが、現在はVMメイン管理で一元的にカウンターを持ってい >>ますが、これを関数単位でもてば、(ぱ)さんの指摘する問題は回避できます。 >> ただ、初期は出来る限り単純なもので済ませたいとの思いがあり。簡単な機構で >>すめばそのままにしています。 上記のように、今のところ優先順位が低いので、後回しにしています。 もちろん、圧縮等はしていないので、比較的簡単に実装出来ると思います。 たぶん二人とも同じことを考えてると思います。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1361] 管理者により削除されました
2009/06/16 22:54:54

なんだか意味不明の投稿が3連投されています。削除しました。 普通に考えれば広告なのですが、それっぽいページへのリンクもメールアドレスもないので、 何を意図したものかさっぱり。
[この投稿を含むスレッドを表示]
[1359] Re:その後のVM
投稿者:(ぱ)こと管理人
2009/06/16 01:14:21

> コンパイル時の負荷はまず棚においておいて、実際問題、再コンパイルが頻繁に >行わなければならない処理が多いと思われますか?、実際的に考えればそんな設計は >良い設計とは思えません。 うーん、再コンパイルの頻度は低くても、それが起きるたびに以後の関数呼び出しに ついてすべて一度ずつリンクが入るのはちょっと心配ですがそれはさておき、 ここで埋め込まれる関数インデックスって、VM内で一意になるんですよね? だとすれば、コンパイル単位の破棄の際に破棄対象の関数が使っていたインデックスの ところをぎゅっと圧縮しようとさえ思わなければ、そもそも振りなおし自体不要なのでは ないかと思うのですが……
[この投稿を含むスレッドを表示] [この投稿を削除]
[1358] Re:その後のVM
投稿者:
2009/06/14 08:20:38

>この方法だと、コンパイル単位が増えてきたとき、プログラムの端のほうでちょろっと >動的リンクが発生しただけで、それこそprint()みたいにあちこちで使われる関数の >呼び出し箇所すべて(通るところだけですが)に対し再リンクが必要になるような……  必ず突っ込まれるで有ろうと予測した部分が突っ込まれました^^。確かに再コンパ イルが頻繁に行われるようであれば、当然負荷が増えるでしょう。でもその場合、 コンパイル時に再リンクも大きな負荷に思えます。  コンパイル時の負荷はまず棚においておいて、実際問題、再コンパイルが頻繁に 行わなければならない処理が多いと思われますか?、実際的に考えればそんな設計は 良い設計とは思えません。  ではなぜ、動的コンパイルが必要だったか。それは、複数の違った処理を一元的 にメニュー管理する目的があったのです。利用目的ですね。このような利用目的が 無い場合、動的コンパイラは不要です。だからdiksamとは指向性が多少違います。  次にスピードの点ですが、現在はVMメイン管理で一元的にカウンターを持ってい ますが、これを関数単位でもてば、(ぱ)さんの指摘する問題は回避できます。  ただ、初期は出来る限り単純なもので済ませたいとの思いがあり。簡単な機構で すめばそのままにしています。  うう~~上記文は多々説明不足な気がすごくしますが、説明を始めると長くなっ てしまいそうなので短文にしています。「もっと説明しろ!」との指摘がありまし たら、ぜひ言ってくださいませ。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1357] Re:その後のVM
投稿者:(ぱ)こと管理人
2009/06/14 01:49:31

>はい、一つ目は文字列バッファーにある関数名インデックスを示し、二つ目はコン >パイル単位カウンター、三つ目は関数ID=インデックス、四つ目はパラメターの数 >です。P2,P3は実行時に埋め込まれます。コンパイルカウンターは、1~最大値ま >でのループカウンターで動的コンパイル実行時かコンパイル単位の消滅処理時に >+1されます。コード上は最初は0そしてカウンターは1なので、値が違うためP1の >関数名から動的リンクをしてP2に1、P3に関数インデックスが埋めこめられ、この >関数インデックスで直接関数が起動されます。以後、P2のコンパイルカウンターが >一緒なら、P3で直接関数起動です。直接起動の前にIF文が一回入る程度です。 うーん、いまいちわかりませんが、 ・call_functionのふたつめのオペランドを「P2」として、 ・「コンパイルカウンター」は、「動的コンパイル実行時かコンパイル単位の  消滅処理時に+1」というくらいだから、VMにひとつだけ存在するカウンタですよね? つまり、動的コンパイルが動いたり、逆にバイトコードを破棄したりするたびに VMの状態が変わるわけですが、この「状態」に対して、1から始まる連番が振られて いるわけですね。 で、call_functionごとに、それがリンクされた時点の連番(コンパイルカウンター)が 埋め込んであり、呼び出しごとに現在のコンパイルカウンターと比較して違っていたら 再リンクする、と。 この方法だと、コンパイル単位が増えてきたとき、プログラムの端のほうでちょろっと 動的リンクが発生しただけで、それこそprint()みたいにあちこちで使われる関数の 呼び出し箇所すべて(通るところだけですが)に対し再リンクが必要になるような…… ちなみにDiksamでは、バイトコード中の関数インデックスはコンパイル時に 決めています。これは「バイトコードごと」の関数インデックスであり、 ver.0.2~0.3系列では、リンク時に、これを「DVMごと」のインデックスに置き換えます。 ver.0.4では、置換は行わず、変換テーブルをバイトコードごとに持っています。 今のところ動的なバイトコードのアンリンクは実装していません。実装する場合、 DVM上のFunctionテーブルのis_implementedをfalseにすることになるかと思います。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1356] Re:その後のVM
投稿者:
2009/06/12 20:46:52

 追記、変数名とか関数名も文字列バッファーに入れています。これは言語のIDE サポートのためです。今デバックのために使っているモニターシステムがあるの ですが、これを高機能にすればIDEになるので、言語デバック用に簡単なIDEをと 思い追加しています。このデバックモニターシステムはC#で作られています。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1355] Re:その後のVM
投稿者:
2009/06/12 20:27:59

>2つ目と3つ目のオペランドは全部0, 0なのですが、関数の方はprintf, sprintf, printの はい、一つ目は文字列バッファーにある関数名インデックスを示し、二つ目はコン パイル単位カウンター、三つ目は関数ID=インデックス、四つ目はパラメターの数 です。P2,P3は実行時に埋め込まれます。コンパイルカウンターは、1~最大値ま でのループカウンターで動的コンパイル実行時かコンパイル単位の消滅処理時に +1されます。コード上は最初は0そしてカウンターは1なので、値が違うためP1の 関数名から動的リンクをしてP2に1、P3に関数インデックスが埋めこめられ、この 関数インデックスで直接関数が起動されます。以後、P2のコンパイルカウンターが 一緒なら、P3で直接関数起動です。直接起動の前にIF文が一回入る程度です。  このような感じで、スレッドセーフな動的リンクを実現しています。実はこれには 面白い副作用があって、例えば画面に文字を出す関数を動的コンパイル単位にすれば。 メインは一切い変更せず。あるときはゴシックで表示、コンパイル単位の消滅そして、 最コンパイルすると、その時から丸文字表示で文字が出される等が可能です。  関数の内部機能を動的に変えることが出来ます。もちろん総てのスレッドにスレッ ドセーフで。でも、使い道はそんなに無いかもしれませんけどね。^^; そうそう、今の所同じ関数名でも違う文字列IDですが、暇が出来たら同一IDにする 予定。 VMを作り始めてから何度もも構文処理からの修正が必要になり。なかなか前に進み ません。書きあがって動いても、スレッドセーフの問題点が見つかり、書き直しも ごそごそと。言語としては最終的なつめなので、すぐには終わりそうにないです。  でも、思った通りに作れるのはいい感じです。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1354] Re:その後のVM
投稿者:(ぱ)こと管理人
2009/06/11 23:44:05

自己フォロー。 >おそらく4つ目のオペランドが引数の数、2つ目か3つ目が関数のインデックス >なのだと思いますが(確か分割コンパイルはなかったと思うので、ひとつ余りますね…) >最初のオペランドは何でしょう? 2つ目と3つ目のオペランドは全部0, 0なのですが、関数の方はprintf, sprintf, printの 3種類ありますので、これが直接関数のインデックスということはないですね。 単なる場所取りで、実行前に第1オペランドの文字列を使ってインデックスを検索して ここに埋め込むとか……
[この投稿を含むスレッドを表示] [この投稿を削除]
[1353] Re:その後のVM
投稿者:(ぱ)こと管理人
2009/06/11 23:40:18

おお、私はDiksamのほうにさっぱり手を付けられないでいる間に、 だいぶ進んでいますね。 ぱっと見で目を引くのは関数呼び出しのインストラクションのオペランドの 数の多さですが、 >1: 9 call_function 3 0 0 4 おそらく4つ目のオペランドが引数の数、2つ目か3つ目が関数のインデックス なのだと思いますが(確か分割コンパイルはなかったと思うので、ひとつ余りますね…) 最初のオペランドは何でしょう? 関数名を文字列のコンスタントプールで保持していて、そのインデックスに 見えますが、用途がよくわかりません。リンク用の情報で、実行時には使わない? >1:*** 文字列 数 = 9 *** >1: 0: "main" >1: 1: "str" >1: 2: "printf P1 = %d P2 = %d P3 = %d >" >1: 3: "printf" >1: 4: "sprintf P1 = %d >" >1: 5: "sprintf" >1: 6: "print" >1: 7: "---------- test ---------
[この投稿を含むスレッドを表示] [この投稿を削除]
[1352] Re:その後のVM
投稿者:
2009/06/11 22:46:28

 追記で、バイトコードも結構変わっています。下記に。 >---------------------------------- >int printf(string str); >string sprintf(string str); >int print(string str); > >int main() >{ > string str; > printf("printf P1 = %d P2 = %d P3 = %d\n",12,20,30); > str = sprintf("sprintf P1 = %d\n",13); > print(str); > print("---------- test ---------\n"); >} >---------------------------------- ↓  バイトコード ↓ 1:*** 一般関数情報ダンプ ****************** 1:--- int main() 1:*** ローカル変数の表示 no = 1 *** 1: 0:string str 1:*** 文字列 数 = 9 *** 1: 0: "main" 1: 1: "str" 1: 2: "printf P1 = %d P2 = %d P3 = %d " 1: 3: "printf" 1: 4: "sprintf P1 = %d " 1: 5: "sprintf" 1: 6: "print" 1: 7: "---------- test --------- " 1: 8: "print" 1:*** 使用予定のスタックサイズ = 240 1:*** 関数コードのディスアセンブラ size = 65 1: 0 push_string_const 2 1: 3 push_int_1byte 12 1: 5 push_int_1byte 20 1: 7 push_int_1byte 30 1: 9 call_function 3 0 0 4 1: 18 pop 1: 19 push_string_const 4 1: 22 push_int_1byte 13 1: 24 call_function 5 0 0 2 1: 33 pop_stack_string 0 1: 36 push_stack_string 0 1: 39 call_function 6 0 0 1 1: 48 pop 1: 49 push_string_const 7 1: 52 call_function 8 0 0 1 1: 61 pop 1: 62 push_int_1byte 0 1: 64 return 1:*** 行情報 数 = 6 *** 1: 8: from 0 size 19 1: 9: from 19 size 17 1: 10: from 36 size 13 1: 11: from 49 size 13 1: 13: from 62 size 2 1: 12: from 64 size 1 1:*** end of main() --------------
[この投稿を含むスレッドを表示] [この投稿を削除]
[1351] その後のVM
投稿者:
2009/06/11 22:03:54

 ようやく下記のようなプログラムがVMで実行可能になりました。可変長 パラメータ用の書式は作らず、一部の組込み関数のみ可能にしました。 言語としての美しさは…、スタック情報も大きく変わり、VMはほとんど別の ものになりつつあります。VMの完成にはまだまだです。printfはCのprintf と同等ですが、中身はエミュレートを被せてオーバラン等の危険は一切 ありません。 ---------------------------------- int printf(string str); string sprintf(string str); int print(string str); int main() { string str; printf("printf P1 = %d P2 = %d P3 = %d\n",12,20,30); str = sprintf("sprintf P1 = %d\n",13); print(str); print("---------- test ---------\n"); } ----------------------------------  前に出した、組込み関数とのインターフェースは大幅に変更となり。 下記のようになっています。 //== スタック上の組込み関数データ =================================== struct NFstartDat { ushort vtype; // データタイプ E_StackDType ushort size; // スタック消費サイズ ushort m_vmid; // VMID = スレッドID ushort m_prm_inno; // 引き渡されたパラメータ数 void *m_sdatp; // スレッド別データ用ポインター S_Value *m_prmp[PRMMAX]; // 引き渡されたパラメータ S_Value m_return; // 関数からの戻り値データ }; //=================================================================== // 組み込み関数用定義 //=================================================================== class C_NFBase { protected: //-- VMから受け取る情報 ---------------- int m_fid; // 関数ID //-- VMに送る情報 ---------------------- char *m_name; // 関数名 int m_prmno; // 要求するパラメータ数0-10まで20は可変関数 ES_ValueType m_type[PRMMAX]; // 要求するパラメータの型 ES_ValueType m_return_type; // リターン変数タイプ public: C_NFBase() { this->m_name = NULL; this->m_prmno = 0; for(int i=0;i<PRMMAX;i++) { this->m_type[i] = ES_NON; } //----------------------- this->m_fid = 0; this->m_return_type = ES_INT; } virtual ~C_NFBase() { } virtual void * VMstart() { } // VM起動時実行 virtual void VMend() { } // VM終了時実行 virtual void funcexe(NFstartDat *nfd) { } // 関数起動メソッド inline char ** getname() { return &this->m_name; } inline int getprmno() { return this->m_prmno; } inline ES_ValueType getprmtype(int no) { return this->m_type[no]; } inline void setfid(int fid) { this->m_fid = fid; } inline ES_ValueType getrtntype() { return this->m_return_type; } };
[この投稿を含むスレッドを表示] [この投稿を削除]