annotate paper/chapter/02-interface.tex @ 37:b8cb6fcd9342

...
author anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
date Sun, 31 Jan 2021 21:04:41 +0900
parents d9c29dddf64f
children ae00fdac2e99
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
16
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1 \section{GearsOSのInterfaceの構文の改良}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2 GearsOSのInterfaceでは、 従来はDataGearとCodeGearを分離して記述していた。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
3 CodeGearの入出力をDataGearとして列挙する必要があった。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
4 CodeGearの入出力として\texttt{\_\_code()}の間に記述したDataGearの一覧と、Interface上部で記述したDataGearの集合が一致している必要がある。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
5
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
6 従来の分離している記法の場合、 このDataGearの宣言が一致していないケースが多々発生した。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
7 またInterfaceの入力としてのDataGearではなく、 フィールド変数としてDataGearを使うようなプログラミングスタイルを取ってしまうケースも見られた。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
8 GearsOSでは、 DataGearやフィールド変数をオブジェクトに格納したい場合、 Interface側ではなくImpl側に変数を保存する必要がある。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
9 Interface側に記述してしまう原因は複数考えられる。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
10 GearsOSのプログラミングスタイルに慣れていないことも考えられるが、構文によるところも考えられる。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
11 CodeGearとDataGearはInterfaceの場合は密接な関係性にあるが、 分離して記述してしまうと「DataGearの集合」と「CodeGearの集合」を別個で捉えてしまう。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
12 あくまでInterfaceで定義するCodeGearとDataGearはInterfaceのAPIである。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
13 これをユーザーに強く意識させる必要がある。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
14
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
15 golangにもInterfaceの機能が実装されている。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
16 golangの場合はInterfaceは関数の宣言部分のみを記述するルールになっている。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
17 変数名は含まれていても含まなくても問題ない。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
18
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
19 \begin{lstlisting}[frame=lrbt,label=src:golang_interface,caption={golangのinterface宣言}]
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
20 type geometry interface {
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
21 area() float64
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
22 perim() float64
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
23 }
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
24 \end{lstlisting}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
25
37
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 25
diff changeset
26 \section{Implementの型をいれたことによる間違ったGearsプログラミング}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 25
diff changeset
27 Implementの型を導入したが、 GearsOSのプログラミングをするにつれていくつかの間違ったパターンがあることがわかった。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 25
diff changeset
28 自動生成されるStubCodeGearは、 goto metaから遷移するのが前提であるため、 引数をContextから取り出す必要がある。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 25
diff changeset
29 Contextから取り出す場合は、 実装しているInterfaceに対応している置き場所からデータを取り出す。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 25
diff changeset
30 この置き場所は\texttt{data}配列であり、 配列の添え字は\texttt{enum Data}と対応している。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 25
diff changeset
31 また各CodeGearからgotoする際に、 遷移先のInterfaceに値を書き込みに行く。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 25
diff changeset
32
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 25
diff changeset
33
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 25
diff changeset
34 Interfaceで定義したCodeGearと対応しているImplementのCodeGearの場合はこのデータの取り出し方で問題はない。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 25
diff changeset
35 しかしImplementのCodeGearから内部でgotoするCodeGearの場合は事情が異なる。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 25
diff changeset
36 内部でgotoするCodeGearは、 Javaなどのプライベートメソッドのように使うことを想定している。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 25
diff changeset
37 このCodeGearのことをprivate CodeGearと呼ぶ。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 25
diff changeset
38 privateCodeGearにgotoする場合、 goto元のCodeGearからは\texttt{goto meta}経由で遷移する。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 25
diff changeset
39 goto metaが発行されるとStub Code Gearに遷移するが、現在のシステムではInterfaceから値をとってくることになってしまう。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 25
diff changeset
40
16
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
41
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
42 \section{メタ計算部分の入れ替え}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
43 GearsOSでは次のCodeGearに移行する前のMetaCodeGearとして、 デフォルトでは\texttt{\_\_code meta}が使われている。
20
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 16
diff changeset
44 \texttt{\_\_code meta}はcontextに含まれているCodeGearの関数ポインタを、 enumからディスパッチして次のStub CodeGearに継続するものである。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 16
diff changeset
45
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 16
diff changeset
46 例えばモデル検査をGearsOSで実行する場合、 通常のStub CodeGearのほかに状態の保存などを行う必要がある。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 16
diff changeset
47 この状態の保存に関する一連の処理は明らかにメタ計算であるので、 ノーマルレベルのCodeGearではない箇所で行いたい。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 16
diff changeset
48 ノーマルレベル以外のCodeGearで実行する場合は、 通常のコード生成だとStubCodeGearの中で行うことになる。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 16
diff changeset
49 StubCodeGearは自動生成されてしまうため、 値の取り出し以外のことを行う場合は自分で実装する必要がある。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 16
diff changeset
50 しかしモデル検査に関する処理は様々なCodeGearの後に行う必要があるため、 すべてのCodeGearのStubを静的に実装するのは煩雑である。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 16
diff changeset
51
22
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 21
diff changeset
52 ノーマルレベルのCodeGearの処理の後に、StubCodeGear以外のMeta Code Gearを実行したい。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 21
diff changeset
53 Stub Code Gearに直ちに遷移してしまう\texttt{\_\_code meta}以外のMeta CodeGearに、 特定のCodeGearの計算が終わったら遷移したい。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 21
diff changeset
54 このためには、特定のCodeGearの遷移先のMetaCodeGearをユーザーが定義できるAPIが必要となる。
20
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 16
diff changeset
55 このAPIを実装すると、ユーザーが柔軟にメタ計算を選択することが可能となる。
16
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
56
20
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 16
diff changeset
57 GearsOSのビルドシステムのAPIとして\texttt{meta.pm}を作製した。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 16
diff changeset
58 これはPerlのモジュールファイルとして実装した。
23
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 22
diff changeset
59 meta.pmはPerlで実装されたGearsOSのトランスコンパイラであるgenerate\_stub.plから呼び出される。
21
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 20
diff changeset
60 meta.pmの中のサブルーチンである\texttt{replaceMeta}に変更対象のCodeGearと変更先のMetaCodeGearへのgotoを記述する。
22
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 21
diff changeset
61 ユーザーはmeta.pmのPerlファイルをAPIとしてGearsOSのトランスコンパイラにアクセスすることが可能となる。
20
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 16
diff changeset
62
21
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 20
diff changeset
63 具体的な使用例をコード\ref{src:metapm}に示す。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 20
diff changeset
64 meta.pmはサブルーチン\texttt{replaceMeta}が返すリストの中に、特定のパターンで配列を設定する。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 20
diff changeset
65 各配列の0番目には、goto metaを置換したいCodeGearの名前を示すPerl正規表現リテラルを入れる。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 20
diff changeset
66 コード\ref{src:metapm}の例では、\texttt{PhilsImpl}が名前に含まれるCodeGearを指定している。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 20
diff changeset
67 すべてのCodeGearのgotoの先を切り替える場合は\texttt{qr/.*\//}などの正規表現を指定する。
20
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 16
diff changeset
68
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 16
diff changeset
69 \lstinputlisting[label=src:metapm, caption=meta.pm]{src/meta.pm}
25
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 23
diff changeset
70
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 23
diff changeset
71 generate\_stub.plはGears CbCファイルの変換時に、 CbCファイルがあるディレクトリにmeta.pmがあるかを確認する。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 23
diff changeset
72 meta.pmがある場合はモジュールロードを行う。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 23
diff changeset
73 meta.pmがない場合はmeta Code Gearにgotoするものをデフォルト設定として使う。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 23
diff changeset
74 各Gode Gearが\texttt{goto文}を呼び出したタイミングでreplaceMetaを呼び出し、 ルールにしたがってgoto文を書き換える。
37
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 25
diff changeset
75 変換するCodeGearがルールになかった場合は、 デフォルト設定が呼び出される。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 25
diff changeset
76
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 25
diff changeset
77 \section{別Interfaceからの書き出しを取得する必要があるCodeGear}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 25
diff changeset
78
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 25
diff changeset
79 従来のMetaCodeGearの生成では、 別のInterfaceからの入力を受け取るCodeGearのStubの生成に問題があった。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 25
diff changeset
80 具体的なこの問題が発生する例題をソースコード\ref{src:insertTest1}に示す。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 25
diff changeset
81 この例では\texttt{pop2Test}Code Gearから \texttt{stack->pop2}を呼び出し、 継続として\texttt{pop2Test1}を渡している。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 25
diff changeset
82 \texttt{pop2Test}自体はStackTest Interfaceであり、 \texttt{stack->pop2}の\texttt{stack}はStack Interfaceである。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 25
diff changeset
83
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 25
diff changeset
84 \lstinputlisting[label=src:insertTest1, caption=2つ以上の出力があるCodeGearからの遷移例]{src/pop2test.cbc}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 25
diff changeset
85
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 25
diff changeset
86 当初Perlスクリプトが生成した\texttt{insertCase1}のstub CodeGearはソースコード\ref{src:pop2stub-origin}のものである。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 25
diff changeset
87 \texttt{insertCase1}はtree, parent, grandparentの3引数必要であるが、生成されたコードの引数がそろっていないことがわかる。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 25
diff changeset
88
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 25
diff changeset
89
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 25
diff changeset
90 \lstinputlisting[label=src:pop2stub-origin, caption=生成されたStub]{src/pop2stub-origin.cbc}