[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     ! 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>