[BACK]Return to prog1.txt CVS log [TXT][DIR] Up to [local] / OpenXM / src / k097 / Doc

Annotation of OpenXM/src/k097/Doc/prog1.txt, Revision 1.1.1.1

1.1       maekawa     1:
                      2:
                      3: yacc/Doc/prog1.txt  (1997, 4/11, 4/17)
                      4: kan/k0 の内部構造とプログラミングに関する注意.
                      5:
                      6: kan/k0 におけるクラスの取扱は C++ や Java に一見して似ているが,
                      7: 実は全く違う.  むしろ, SmallTalk の方が近い.
                      8:
                      9: ☆ クラスのインスタンス変数は class 宣言のすぐ後, 次のように宣言する.
                     10:
                     11:    class  クラス名 extends スーパークラス名 {
                     12:       local インスタンス変数名1,
                     13:             インスタンス変数名2,
                     14:                 ...
                     15:             インスタンス変数名n;
                     16:
                     17:       メンバー関数定義
                     18:    }
                     19:
                     20:    上の local 宣言を二つ以上書くとエラーになる.
                     21:
                     22: ☆ インスタンス変数名は, そのクラス内での 局所変数名, メンバー関数引数名と
                     23:    して使えない.
                     24:
                     25:    たとえば,
                     26:    class abc extends Object {
                     27:      local a,b;
                     28:      def foo(a) {
                     29:
                     30:    は インスタンス変数名 a を引数として用いているのでエラーである.
                     31:    現在のところ エラーメッセージを表示しないのでもっとたちがわるい.
                     32:
                     33: ☆ インスタンス変数名にたいする ピリオド . を用いた参照, 代入はできない.
                     34:     たとえば,
                     35:           this.a
                     36:     といった参照はできない.  (将来的には, できるようにしたい. )
                     37:     参照, 代入はかならず, メンバー関数を用いて行なう.
                     38:
                     39: ☆  生成子の書き方は, 次の形式に従うこと. (yacc/debug/graph.kk より)
                     40:
                     41:     def new0(引数) {                   生成子名はなんでもいい.
                     42:       this = new();                    かならず, this = new(....) を書く.
                     43:                                        クラスの実体が PrimitiveObject の
                     44:                                        array として生成される.
                     45:       インスタンス変数の初期化
                     46:       return(this);                    かならず、this を戻す.
                     47:     }
                     48:
                     49:
                     50:     new() は, 上のように, new() とよんでもいいし,
                     51:         this = new(super.スーパークラスの生成子)
                     52:     と書いてもいい.
                     53:
                     54: ☆  class インスタンスの内部形式.
                     55:
                     56:     class インスタンス は PrimitiveObject としては, array であり,
                     57:     その最初の要素は class タグである.
                     58:     インスタンス変数は, その array の要素である.
                     59:
                     60: 例えば,
                     61:    class Circle extends Object {
                     62:      local x,  /* 中心 */
                     63:            y,
                     64:            r;  /* 半径 */
                     65:      ;
                     66:    }
                     67:
                     68:    class GraphicCircle extends Circle {
                     69:      local outline, fill;
                     70:      ;
                     71:    }
                     72:
                     73: なる宣言をすると, Circle インスタンスは,
                     74:    [Circle, xの値, yの値, rの値]
                     75: なる array,   GraphicCircle インスタンスは,
                     76:    [GraphicCircle, xの値, yの値, rの値, outlineの値, fillの値]
                     77: なる array となる.
                     78: kan/k0 インタプリタは, たとえば,  x という変数があらわれると,
                     79: kan/sm1 の,
                     80:        this 1 get
                     81: なるコマンドを生成している.   インスタンス変数名と, その位置インデックス
                     82: の対応は, yacc/dic.c の関数で管理されている.
                     83:
                     84: ☆  extends により, 名前空間が, PrimitiveObject --- Object を頂点とする木構造に
                     85: なっている.  メソッドの検索は次のようにおこなわれる.
                     86:
                     87: 関数呼び出しは, 次のように翻訳される.
                     88:      aaa.foo(b,c)             aaa [b c] {foo} sendmsg2
                     89:      foo(b,c)                 this [b c] {foo} sendmsg2
                     90:
                     91: すべての関数は二つの引数がスタックにあることを仮定している.
                     92: sendmsg2 は, 第一引数が, クラスのインスタンス であるばあい,
                     93: 名前空間 (コンテキスト)
                     94: をその クラス のものに変更して, 関数呼び出しをおこなう.
                     95: 例えば, 上の例で, aaa が Graphic の インスタンスであると,
                     96: foo の実行は, Graphic の名前空間で実行される.
                     97:
                     98:
                     99: operator +,-,*,/ については次のように翻訳される.
                    100:     a + b                   a  b  {add} sendmsg2
                    101: sendmsg2 は, 第一引数または第2引数が, クラスのインスタンス であるばあい,
                    102: 名前空間 (コンテキスト)
                    103: をその クラス のものに変更して, 関数呼び出しをおこなう.
                    104: 例:
                    105:    class Integer extends Object {
                    106:      local ival;
                    107:      def new0(i) {
                    108:         this = new();
                    109:         if (IsInteger(i)) ival = i;
                    110:         else {
                    111:            k00_error("new0","Argument must be integer."); sm1(" error ");
                    112:         }
                    113:         return(this);
                    114:      }
                    115:      def value() { return( ival ); }
                    116:      def operator add(b) {
                    117:        local r;
                    118:        r = Integer.new0(ival+b.value());
                    119:        return(r);
                    120:      }
                    121:    }
                    122:
                    123:    a = Integer.new0(3);
                    124:    a + a :
                    125:
                    126:
                    127:
                    128:
                    129:
                    130: なお, 上の4つ以外の,
                    131: <,>, = , == などの operator に関しては, override はできないことに注意.
                    132:
                    133:
                    134:
                    135: ☆  kan/k0 のエンジン部分は初期状態で, 4本のスタックと 一つのコンテキスト
                    136:    をもっている.
                    137:
                    138:    Operand Stack  (標準のスタック, Kan/stackmachine.c では StandardStack)
                    139:    db.VariableStack
                    140:    db.ErrorStack
                    141:    db.DebugStack
                    142:    これらは var.sm1 で定義され,  debug/db.k で活用される.
                    143:
                    144:    db.VariableStack は, 関数呼び出しのときの, 引数や 関数の局所変数を
                    145:    一次的に格納する stack である.
                    146:
                    147:    db.DebugStack は, 関数呼び出しのとき, 現在実行中の関数を格納する
                    148:    stack である. --- engine error or interrupt :  in function xxxxx
                    149:    という表示は, このスタックの情報をもとにしている.
                    150:
                    151:    db.ErrorStack は, engine エラーが積まれるスタックである.
                    152:
                    153:
                    154:    コンテキストは,
                    155:    PrimitiveContextp  (StandardContextp)
                    156:    が初期状態である.  incmac.sm1 を参照せよ.
                    157:    なお PrimitiveObject = [PrimitiveContextp]  である.
                    158:
                    159:
                    160:    SmallTalk のバイトコードマシンでは, コンテキストは, 名前辞書とスタック
                    161:    を合わせたものであるが, kan/k0 の場合, コンテキストとは, 名前辞書のことを
                    162:    さす.  名前辞書は名前とその値よりなる対応表である. 辞書はハッシュ法で
                    163:    検索され, その辞書で値が見つからないと, その super 辞書へ検索が移行する.
                    164:    このような木構造での名前空間の実現については, Kan/stackmachine.c
                    165:    の  *userDictionary*  なる名前の関数を参照されたい.
                    166:
                    167: ☆ コンテキストスイッチについての注意.
                    168:
                    169:    上で説明したような, 名前空間の動的な変更はエラー処理に関して混乱をひきお
                    170:    こす.  したがって, kan/k0 では, 次のような単純な, 解決法をとった.
                    171:
                    172:    エンジンエラー,  ctrl-C の入力があった場合, 必ず CurrentContext を,
                    173:    PrimitiveContext へ戻す.
                    174:
                    175:    この方針は別の問題を引き起こす.  たとえば, エラーが起きた時点の変数の
                    176:    値の検査が一般にできない.  いまのところ, kan/sm1 のコマンドをつかうしか
                    177:    ない.
                    178:    たとえば, class Abc でエラーが起きたとすると,
                    179:        sm1("Abc  0 get setcontext ");
                    180:    で, class Abc の名前空間に移行できる.
                    181:        sm1(" show_user_dictionary ") で現在の辞書に登録されている名前を
                    182:    みることができる.  また,
                    183:         Println(変数名);
                    184:    でその変数の値を検査できる.
                    185:
                    186:    以上のような仕組みの問題点としては,
                    187:    Cleards();  による, 変数の値の回復ができないことをあげておく.
                    188:    (つまり現在の変数スタックは, どの名前空間かの情報をもっていないので、
                    189:     変数の値の正しい回復ができない, また, context ごとに別のスタックを
                    190:     用意している訳でない.)
                    191:    したがって, class  を用いたプログラムは, エラーが起きたら, 再スタートするの
                    192:    が賢明である.
                    193:
                    194:
                    195: ☆ Object については, 必ず概要, および, 実例を記述しておくこと.
                    196:
                    197:    class を用いて書かれたプログラムは一般に読みにくい場合が多々ある.
                    198:    Object が中心にありプログラムをしているにもかかわらず, その Obeject の
                    199:    概要を理解するのがソースからはむづかしいことが多いのが,
                    200:    その理由であると思われる.
                    201:    例えば, ??????????????   (考えること)
                    202:
                    203:

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>