annotate paper/chapter/04-interface.tex @ 81:9974be9e2d1c

add arg
author anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
date Fri, 05 Feb 2021 09:22:30 +0900
parents 3022da6f729f
children 3fb7c17d8e91
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
51
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 48
diff changeset
1 \chapter{GearsOSのInterfaceの改良}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 48
diff changeset
2
16
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
3 \section{GearsOSのInterfaceの構文の改良}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
4 GearsOSのInterfaceでは、 従来はDataGearとCodeGearを分離して記述していた。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
5 CodeGearの入出力をDataGearとして列挙する必要があった。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
6 CodeGearの入出力として\texttt{\_\_code()}の間に記述したDataGearの一覧と、Interface上部で記述したDataGearの集合が一致している必要がある。
53
1a4d4e64f0b8 add Stack Interface code
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 52
diff changeset
7 ソースコード\ref{src:old-stack}はStackのInterfaceの例である。
1a4d4e64f0b8 add Stack Interface code
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 52
diff changeset
8 \lstinputlisting[label=src:old-stack, caption=従来のStack Interface]{src/old-stack.h}
16
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
9
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
10 従来の分離している記法の場合、 このDataGearの宣言が一致していないケースが多々発生した。
58
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
11 またInterfaceの入力としてのDataGearではなく、 フィールド変数としてDataGearを使うプログラミングスタイルを取るケースも見られた。
16
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
12 GearsOSでは、 DataGearやフィールド変数をオブジェクトに格納したい場合、 Interface側ではなくImpl側に変数を保存する必要がある。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
13 Interface側に記述してしまう原因は複数考えられる。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
14 GearsOSのプログラミングスタイルに慣れていないことも考えられるが、構文によるところも考えられる。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
15 CodeGearとDataGearはInterfaceの場合は密接な関係性にあるが、 分離して記述してしまうと「DataGearの集合」と「CodeGearの集合」を別個で捉えてしまう。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
16 あくまでInterfaceで定義するCodeGearとDataGearはInterfaceのAPIである。
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 golangにもInterfaceの機能が実装されている。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
20 golangの場合はInterfaceは関数の宣言部分のみを記述するルールになっている。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
21 変数名は含まれていても含まなくても問題ない。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
22
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
23 \begin{lstlisting}[frame=lrbt,label=src:golang_interface,caption={golangのinterface宣言}]
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
24 type geometry interface {
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
25 area() float64
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
26 perim() float64
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
27 }
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
28 \end{lstlisting}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
29
53
1a4d4e64f0b8 add Stack Interface code
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 52
diff changeset
30 GearsOSのInterfaceは入力と出力のAPIを定義するものであるので、 golangのInterfaceのように、関数のAPIを並べて記述するほうが簡潔であると考えた。
54
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 53
diff changeset
31 改良したInterfaceの構文でStackを定義したものをソースコード\ref{src:stack}に示す。
53
1a4d4e64f0b8 add Stack Interface code
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 52
diff changeset
32 \lstinputlisting[label=src:stack, caption=変更後のStack Interface]{src/stack.h}
1a4d4e64f0b8 add Stack Interface code
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 52
diff changeset
33
54
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 53
diff changeset
34
58
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
35 従来のInterfaceでは\texttt{<Type, Impl>}キーワードが含まれていた。
54
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 53
diff changeset
36 これはジェネリクスの機能を意識して導入された構文である。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 53
diff changeset
37 \texttt{Impl}キーワードは実装自身の型を示す型変換として使われていた。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 53
diff changeset
38 しかし基本Interfaceの定義を行う際にGearsOSのシステム上、CodeGearの第一引数は\texttt{Impl}型のポインタが来る。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 53
diff changeset
39 これはオブジェクト指向言語で言う\texttt{self}に相当するものであり、 自分自身のインスタンスを示すポインタである。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 53
diff changeset
40 Implキーワードは共通して使用されるために、 宣言部分からは取り外し、デフォルトの型キーワードとして定義した。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 53
diff changeset
41 \texttt{Type}キーワードは型変数としての利用を意識して導入されていたが、現在までのGearsOSの例題では導入されていなかった。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 53
diff changeset
42 ジェネリクスとしての型変数の利用の場合は\texttt{T}などの1文字変数がよく使われる。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 53
diff changeset
43 変更後の構文ではのちのジェネリクス導入のことを踏まえて、\texttt{Type}キーワードは削除した。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 53
diff changeset
44
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 53
diff changeset
45
56
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
46
53
1a4d4e64f0b8 add Stack Interface code
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 52
diff changeset
47 構文を変更するには、 GearsOSのビルドシステム上でInterfaceを利用している箇所を修正する必要がある。
1a4d4e64f0b8 add Stack Interface code
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 52
diff changeset
48 Interfaceはgenerate\_stub.plで読み込まれ、 CodeGearと入出力のDataGearの数え上げが行われる。
1a4d4e64f0b8 add Stack Interface code
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 52
diff changeset
49 この処理はInterfaceのパースに相当するものである。
1a4d4e64f0b8 add Stack Interface code
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 52
diff changeset
50 当然ではあるが、パース対象のInterfaceの構文は、変更前の構文にしか対応していない。
1a4d4e64f0b8 add Stack Interface code
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 52
diff changeset
51
1a4d4e64f0b8 add Stack Interface code
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 52
diff changeset
52
56
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
53 \section{Implementの型定義ファイルの導入}
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
54 Interfaceを使う言語では、 Interfaceが決まるとこれを実装するクラスや型が生まれる。
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
55 GearsOSもInterfaceに対応する実装が存在する。
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
56 例えばStack Interfaceの実装はSingleLinkedStackであり、 Queueの実装はSingleLinkedQueueやSynchronizedQueueが存在する。
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
57
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
58 このSynchronizedQueueはGearsOSではDataGearとして扱われる。
58
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
59 Interfaceの定義と同等な型定義ファイルが、 実装の型については存在しなかった。
56
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
60 従来はcontext.hのDataGearの宣言部分に、構造体の形式で表現したものを手で記述していた。(ソースコード\ref{src:singleContext.h})
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
61 \lstinputlisting[label=src:singleContext.h, caption=cotnext.hに直接書かれた型定義]{src/singleContext.h}
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
62
58
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
63 CbCファイルからはcontext.hをインクルードすることで問題なく型の使用は可能である。
56
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
64 Perlのトランスコンパイラであるgenerate\_stub.plはInterfaceの型定義ファイルをパースしていた。
58
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
65 しかし型定義ファイルの存在の有無がInterfaceと実装で異なっている為に、 generate\_stub.plでImplementの型に関する操作ができない。
56
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
66 Implementの型も同様に定義ファイルを作製すれば、generate\_stub.plで型定義を用いた様々な処理が可能となり、ビルドシステムが柔軟な挙動が可能となる。
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
67 また型定義は一貫して\texttt{*.h}に記述すれば良くなるため、 プログラマの見通しも良くなる。
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
68 本研究では新たにImplementの型定義ファイルを考案する。
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
69
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
70 GearsOSではすでにInterfaceの型定義ファイルを持っている。
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
71 Implementの型定義ファイルも、 Interfaceの型定義ファイルと似たシンタックスにしたい。
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
72 Implementの型定義ファイルで持たなければいけないのは、 どのInterfaceを実装しているかの情報である。
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
73 この情報は他言語ではInterfaceの実装を持つ型の宣言時に記述するケースと、型名の記述はせずに言語システムが実装しているかどうかを確認するケースが存在する。
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
74 Javaでは\texttt{implements}キーワードを用いてどのInterfaceを実装しているかを記述する。\cite{javaimpl}
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
75 ソースコード\ref{src:javaimpl}では、\texttt{Pig}クラスは\texttt{Animal} Interfaceを実装している。
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
76 \lstinputlisting[label=src:javaimpl, caption=JavaのImplementキーワード]{src/java-interface-implements.java}
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
77 golangではInterfaceの実装は特にキーワードを指定せずに、 そのInterfaceで定義しているメソッドを、Implementに相当する構造体がすべて実装しているかどうかでチェックされる。
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
78 これはgolangはクラスを持たず、構造体を使ってInterfaceの実装を行う為に、 構造体の定義にどのInterfaceの実装であるかの情報をシンタックス上書けない為である。
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
79 GearsOSでは型定義ファイルを持つことができるために、 golangのような実行時チェックは行わず、 Javaに近い形で表現したい。
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
80
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
81 導入した型定義でSynchronizedQueueを定義したものをソースコード\ref{src:syncqueue}に示す。
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
82 大まかな定義方法はInterface定義のものと同様である。
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
83 違いとして\texttt{impl}キーワードを導入した。
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
84 これはJavaの\texttt{implements}に相当する機能であり、 実装したInterfaceの名前を記述する。
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
85 現状のGearsOSではImplが持てるInterfaceは1つのみであるため、\texttt{impl}の後ろにはただ1つの型が書かれる。
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
86 型定義の中では独自に定義したCodeGearを書いてもいい。
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
87 これはJavaのプライベートメソッドに相当するものである。
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
88 特にプライベートメソッドがない場合は、 実装側で所持したい変数定義を記述する。
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
89 SynchronizedQueueの例では\texttt{top}などが実装側で所持している変数である。
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
90 \lstinputlisting[label=src:syncqueue, caption=SynchronizedQueueの定義ファイル]{src/SynchronizedQueue.h}
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
91 従来context.hに直接記述していたすべてのDataGearの定義は、 スクリプトで機械的にInterfaceおよびImplementの型定義ファイルに変換している。
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
92
37
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 25
diff changeset
93 \section{Implementの型をいれたことによる間違ったGearsプログラミング}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 25
diff changeset
94 Implementの型を導入したが、 GearsOSのプログラミングをするにつれていくつかの間違ったパターンがあることがわかった。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 25
diff changeset
95 自動生成されるStubCodeGearは、 goto metaから遷移するのが前提であるため、 引数をContextから取り出す必要がある。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 25
diff changeset
96 Contextから取り出す場合は、 実装しているInterfaceに対応している置き場所からデータを取り出す。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 25
diff changeset
97 この置き場所は\texttt{data}配列であり、 配列の添え字は\texttt{enum Data}と対応している。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 25
diff changeset
98 また各CodeGearからgotoする際に、 遷移先のInterfaceに値を書き込みに行く。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 25
diff changeset
99
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 25
diff changeset
100
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 25
diff changeset
101 Interfaceで定義したCodeGearと対応しているImplementのCodeGearの場合はこのデータの取り出し方で問題はない。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 25
diff changeset
102 しかしImplementのCodeGearから内部でgotoするCodeGearの場合は事情が異なる。
58
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
103 内部でgotoするCodeGearは、 Javaなどのプライベートメソッドとして使用できる。
37
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 25
diff changeset
104 このCodeGearのことをprivate CodeGearと呼ぶ。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 25
diff changeset
105 privateCodeGearにgotoする場合、 goto元のCodeGearからは\texttt{goto meta}経由で遷移する。
58
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
106 goto metaが発行されるとStub Code Gearに遷移するが、現在のシステムではInterfaceから値を取得しに行く。
66
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 60
diff changeset
107 private CodeGearの入力もStubから取得したいと考え、 ImplementをInterfaceのつもりでGearsOSのコードを記述した。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 60
diff changeset
108
44
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 43
diff changeset
109
68
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 66
diff changeset
110 \section{Interfaceのパーサーの構築}
78
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 72
diff changeset
111 従来のGearsOSのトランスコンパイラでは、 generate\_stub.plがInterfaceファイルを開き、情報を解析していた。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 72
diff changeset
112 この情報解析はgetDataGear関数で行われていた。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 72
diff changeset
113 しかしこの関数は、CbCファイルのCodeGear、DataGearの解析で使用するルーチンと同じものである。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 72
diff changeset
114 従って、 Interface特有のパースが出来ていなかった。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 72
diff changeset
115
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 72
diff changeset
116 例えば開いたヘッダファイルがInterfaceのファイルでも、そうでないCのヘッダファイルでも同様の解析をしてしまう。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 72
diff changeset
117 Interfaceの定義ファイルの構文はすでに統一されたものを使用している。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 72
diff changeset
118 この構文で実装されていないInterfaceファイルを読み込んだ場合は、 エラーとして処理したい。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 72
diff changeset
119 また、Interfaceが満たすべきCodeGearの種類やInputDataGearの数の管理も行いたい。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 72
diff changeset
120 さらにInterfaceではなく、Implementの定義ファイルも同様にパースし、情報を解析したい。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 72
diff changeset
121
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 72
diff changeset
122 これらを実現するには、最初からInterfaceに特化したパーサーが必要となる。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 72
diff changeset
123 本研究ではGears::Interfaceモジュールとして実装した。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 72
diff changeset
124
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 72
diff changeset
125 \subsection{Gears::Interfaceの構成}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 72
diff changeset
126
68
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 66
diff changeset
127
60
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 59
diff changeset
128 \section{Interfaceの実装のCbCファイルへの構文の導入}
37
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 25
diff changeset
129
58
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
130 \section{GearsCbCのInterfaceの実装時の問題}
39
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 38
diff changeset
131
58
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
132 Interfaceとそれを実装するImplの型が決定すると、最低限満たすべきCodeGearのAPIは一意に決定する。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
133 ここで満たすべきCodeGearは、Interfaceで定義したCodeGearと、 Impl側で定義した privateなCodeGearとなる。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
134 例えばStack Interfaceの実装を考えると、各Implで\texttt{pop}, push, shift, isEmptyなどを実装する必要がある。
39
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 38
diff changeset
135
58
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
136 従来はプログラマが手作業でヘッダーファイルの定義を参照しながら\texttt{.cbc}ファイルを作成していた。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
137 手作業での実装のため、 コンパイル時に下記の問題点が多発した。
45
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 44
diff changeset
138
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 44
diff changeset
139 \begin{itemize}
58
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
140 \item CodeGearの入力のフォーマットの不一致
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
141 \item Interfaceの実装のCodeGearの命名規則の不一致
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
142 \item 実装を忘れているCodeGearの発生
45
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 44
diff changeset
143 \end{itemize}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 44
diff changeset
144
48
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 46
diff changeset
145
58
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
146 特にGearsOSの場合はPerlスクリプトによって純粋なCbCに一度変換されてからコンパイルが行われる。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
147 実装の状況とトランスコンパイラの組み合わせによっては、 CbCコンパイラレベルでコンパイルエラーを発生させないケースがある。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
148 この場合は実際に動作させながら、gdb, lldbなどのCデバッガを用いてデバッグをする必要がある。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
149 またCbCコンパイラレベルで検知できても、すでに変換されたコード側でエラーが出る。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
150 このため、 トランスコンパイラの挙動をトレースしながらデバッグをする必要がある。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
151 Interfaceの実装が不十分であることのエラーは、 GearsOSレベル、最低でもCbCコンパイラのレベルで完全に検知したい。
48
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 46
diff changeset
152
58
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
153 \section{Interfaceを満たすコード生成の他言語の対応状況}
48
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 46
diff changeset
154
58
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
155 Interfaceを機能として所持している言語の場合、Interfaceを完全に見たいしているかどうかはコンパイルレベルか実行時レベルで検知される。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
156 例えばJavaの場合はInterfaceを満たしていない場合はコンパイルエラーになる。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
157
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
158
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
159 InterfaceのAPIを完全に実装するのを促す仕組みとして、Interfaceの定義からエディタやツールが満たすべき関数と引数の組を自動生成するツールがある。
45
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 44
diff changeset
160
58
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
161 Javaでは様々な手法でこのツールを実装している。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
162 Microsoftが提唱しているIDEとプログラミング言語のコンパイラをつなぐプロトコルにLanguage Serverがある。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
163 Language Serverはコーディング中のソースコードをコンパイラ自身でパースし、 型推論やエラーの内容などをIDE側に通知するプロトコルである。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
164 主要なJavaのLanguage Serverの実装であるeclipse.jdt.ls\cite{eclipse.jdt.ls}では、 LanguageServerの機能として未実装のメソッドを検知する機能が実装されている。\cite{eclipse_pull322}
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
165 この機能を応用してvscode上から未実装のメソッドを特定し、 雛形を生成する機能がある。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
166 他にもIntelliJ IDEなどの商用IDEでは、 IDEが独自に未実装のメソッドを検知、雛形を生成する機能を実装している。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
167
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
168
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
169 golangの場合は主に\texttt{josharian/impl}\cite{golang_impl}が使われている。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
170 これはインストールすると\texttt{impl}コマンドが使用可能になり、 実装したいInterfaceの型と、 Interfaceを実装するImplの型(レシーバ)を与えることで雛形が生成される。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
171 主要なエディタであるvscodeのgolangの公式パッケージである\texttt{vscode-go}\cite{vscode-go}でも導入されており、 vscodeから呼び出すことが可能である。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
172 vscode以外にもvimなどのエディタからの呼び出しや、 シェル上で呼び出して標準出力の結果を利用することが可能である。
46
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 45
diff changeset
173
58
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
174 \section{GearsOSでのInterfaceを満たすCbCの雛形生成}
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
175 GearsOSでも同様のInterfaceの定義から実装するCodeGearの雛形を生成したい。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
176 LanguageServerの導入も考えられるが、 今回の場合はC言語のLanguageServerをCbC用にまず改良し、 さらにGearsOS用に書き換える必要がある。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
177 現状のGearsOSが持つシンタックスはCbCのシンタックスを拡張しているものではあるが、これはCbCコンパイラ側には組み込まれていない。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
178 LanguageServerをGearsOSに対応する場合、 CbCコンパイラ側にGearsOSの拡張シンタックスを導入する必要がある。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
179 CbCコンパイラ側への機能の実装は、 比較的難易度が高いと考えらる。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
180 CbCコンパイラ側に手をつけず、 Interfaceの入出力の検査は既存のGearsOSのビルドシステム上に組み込みたい。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
181
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
182 対してgolangの\texttt{impl}コマンドのように、 シェルから呼び出し標準出力に結果を書き込む形式も考えられる。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
183 この場合は実装が比較的容易かつ、 コマンドを呼び出して標準出力の結果を使えるシェルやエディタなどの各プラットフォームで使用可能となる。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
184 先行事例を参考に、コマンドを実行して雛形ファイルを生成するコマンド\texttt{impl2cbc.pl}をGearsOSに導入した。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
185 \texttt{impl2cbc.pl}の処理の概要を図\ref{fig:impl2cbc}に示す。
46
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 45
diff changeset
186
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 45
diff changeset
187
58
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
188 \begin{figure}[hp]
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
189 \begin{center}
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
190 \includegraphics[width=130mm]{drawio/impl2cbc.pdf}
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
191 \end{center}
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
192 \caption{impl2cbcの処理の流れ}
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
193 \label{fig:impl2cbc}
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
194 \end{figure}
48
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 46
diff changeset
195
58
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
196 \subsection{雛形生成の手法}
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
197
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
198
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
199 Interfaceでは入力の引数がImplと揃っている必要があるが、 第一引数は実装自身のインスタンスがくる制約となっている。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
200 実装自身の型は、Interface定義時には不定である。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
201 その為、 GearsOSではInterfaceのAPIの宣言時にデフォルト型変数\texttt{Impl}を実装の型として利用する。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
202 デフォルト型\texttt{Impl}を各実装の型に置換することで自動生成が可能となる。
52
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 51
diff changeset
203
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 51
diff changeset
204
58
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
205 実装すべきCodeGearはInterfaceとImpl側の型を見れば定義されている。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
206 \texttt{\_\_code}で宣言されているものを逐次生成すればよいが、 継続として呼び出されるCodeGearは具体的な実装を持たない。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
207 GearsOSで使われているInterfaceには概ね次の継続である\texttt{next}が登録されている。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
208 \texttt{next}そのものはInterfaceを呼び出す際に、入力として与える。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
209 その為各Interfaceに入力として与えられた\texttt{next}を保存する場所は存在するが、 nextそのものの独自実装は各Interfaceは所持しない。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
210 したがってこれをInterfaceの実装側で明示的に実装することはできない。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
211 雛形生成の際に、入力として与えられるCodeGearを生成してしまうと、プログラマに混乱をもたらしてしまう。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
212
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
213 入力として与えられているCodeGearは、Interfaceに定義されているCodeGearの引数として表現されている。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
214 コードに示す例では、\texttt{whenEmpty}は入力して与えられているCodeGearである。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
215 雛形を生成する場合は、入力として与えられたCodeGearを除外して出力を行う。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
216 順序はInterfaceをまず出力した後に、 Impl側を出力する。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
217
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
218
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
219 \subsection{コンストラクタの自動生成}
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
220 雛形生成では他にコンストラクタの生成も行う。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
221 GearsOSのInterfaceのコンストラクタは、 メモリの確保及び各変数の初期化を行う。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
222 メモリ上に確保するのは主にInterfaceとImplのそれぞれが基本となっている。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
223 Interfaceによっては別のDataGearを内包しているものがある。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
224 その場合は別のDataGearの初期化もコンストラクタ内で行う必要があるが、 自動生成コマンドではそこまでの解析は行わない。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
225
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
226
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
227 コンストラクタのメンバ変数はデフォルトでは変数は0、ポインタの場合はNULLで初期化するように生成する。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
228 このスクリプトで生成されたコンストラクタを使う場合、 CbCファイルから該当する部分を削除すると、\texttt{generate\_stub.pl}内でも自動的に生成される。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
229 自動生成機能を作成すると1CbCファイルあたりの記述量が減る利点がある。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
230
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
231
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
232
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
233 明示的にコンストラクタが書かれていた場合は、 Perlスクリプト内での自動生成は実行しないように実装した。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
234 これはオブジェクト指向言語のオーバーライドに相当する機能と言える。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
235 現状のGearsOSで使われているコンストラクタは、 基本は\texttt{struct Context*}型の変数のみを引数で要求している。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
236 しかしオブジェクトを識別するためにIDを実装側に埋め込みたい場合など、 コンストラクタ経由で値を代入したいケースが存在する。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
237 この場合はコンストラクタの引数を増やす必要や、 受け取った値をインスタンスのメンバに書き込む必要がある。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
238 具体的にどの値を書き込めば良いのかまではPerlスクリプトでは判定することができない。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
239 このような細かな調整をする場合は、 generate\_stub.pl側での自動生成はせずに、 雛形生成されたコンストラクタを変更すれば良い。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
240 あくまで雛形生成スクリプトはプログラマ支援であるため、 いくつかの手動での実装は許容している。
59
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 58
diff changeset
241
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 58
diff changeset
242
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 58
diff changeset
243 \section{Interfaceの引数の検知}
79
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 78
diff changeset
244 GearsOSのノーマルレベルでは、 InterfaceのAPIの呼び出しは\texttt{interface->method(arg)}の呼び出し方であった。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 78
diff changeset
245 \texttt{arg}は引数であり、これはInterfaceで定義したAPIの引数の一致している必要がある。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 78
diff changeset
246 Interfaceの定義の引数は、Implの実装自身が第一引数でくる制約があった。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 78
diff changeset
247 この制約の為に、 厳密にはInterfaceの定義ファイルに書かれているCodeGearの引数と、Interfaceの呼び出しの引数は数が揃ってはいない。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 78
diff changeset
248 generate\_stub.plは第一引数が実装自身の型であるので、union Data型にキャストし、Contextの引数保存場所に書き込むようになっている。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 78
diff changeset
249 問題が第1引数以外の引数が揃っていない場合である。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 78
diff changeset
250 generate\_stub.plを通すと、次の継続はgoto metaに変換されてしまい、引数情報が抜けてしまう。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 78
diff changeset
251 その為引数はすべて適切にcontextに書き込まれている必要があるが、 一部引数が足りず書き込みが出来なかったケースでも、 CbCコンパイラレベルでは引数関係のエラーが発生しない。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 78
diff changeset
252 また上手くInterfaceの入力の数を取得できなかった場合も、generate\_stub.plは止まらずにマクロを生成してしまう。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 78
diff changeset
253 Gearefを通してcontextに書き込む右辺値が抜けているコードなどがよく発生した。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 78
diff changeset
254 この場合は原因を.cファイルと.cbcファイル、Interfaceファイル、contextファイルのすべてを確認しなければならず、デバッグが非常に困難だった。
81
9974be9e2d1c add arg
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 79
diff changeset
255 InterfaceのAPI呼び出し時の引数検知は、 Interfaceの型定義ファイルからCodeGearの入力の数の取得が不十分であるのが主な原因であった。
79
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 78
diff changeset
256
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 78
diff changeset
257
81
9974be9e2d1c add arg
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 79
diff changeset
258 この問題はPerlスクリプトレベルで引数のチェックを十分に行う必要がある。
9974be9e2d1c add arg
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 79
diff changeset
259 すでにInterfaceのパーサーは実装している為、 パーサー経由で呼び出しているAPIを持つInterfaceの情報を取得する。
9974be9e2d1c add arg
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 79
diff changeset
260 パースした結果の情報に、 各CodeGearの引数情報と引数の数を取得できれば、それらとAPI呼び出し時に与えられている引数を比較すればチェックが可能である。
9974be9e2d1c add arg
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 79
diff changeset
261 現状は引数の数が揃っているかどうかで確認をしている。
9974be9e2d1c add arg
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 79
diff changeset
262
9974be9e2d1c add arg
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 79
diff changeset
263 Intefaceの引数を確認し、Gearefマクロを生成しているgenerate\_stub.plの箇所に、引数の確認処理を実装した。(ソースコード\ref{src:parsedArgs})
9974be9e2d1c add arg
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 79
diff changeset
264 ここでAPI呼び出し時の引数は、\texttt{\$tmpArgs}に代入されている。
9974be9e2d1c add arg
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 79
diff changeset
265 CbCの関数呼び出しの引数はカンマで区切るので、2行目でカンマで文字列を分割し、引数を配列\texttt{@args}に変換している。
9974be9e2d1c add arg
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 79
diff changeset
266
9974be9e2d1c add arg
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 79
diff changeset
267 generate\_stub.plはローカル変数のすべての型を記録しているので、6行目でAPI呼び出しをしているインスタンスの名前からInterfaceを特定する。
9974be9e2d1c add arg
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 79
diff changeset
268 特定後、ヘッダファイルの場所を取得し、8行目でInterfaceのパーサーを呼び出している。
9974be9e2d1c add arg
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 79
diff changeset
269 パーサーから取得した情報から、メソッドの引数の数を14行目で取得し、 引数が格納されている配列\texttt{@args}の要素数と比較している。
79
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 78
diff changeset
270 \lstinputlisting[label=src:parsedArgs, caption=Perlレベルでの引数チェック]{src/parsedArgs.pl}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 78
diff changeset
271
81
9974be9e2d1c add arg
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 79
diff changeset
272 Perlスクリプトでエラーを検知すると、 エラーで終了する。
9974be9e2d1c add arg
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 79
diff changeset
273 ソースコード\ref{src:StackTestArg}のInterfaceの\texttt{insertTest1}を呼び出す例題でエラーを発生さる。
9974be9e2d1c add arg
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 79
diff changeset
274 \lstinputlisting[label=src:StackTestArg, caption=StackTestInterfaceの定義]{src/StackTestArg.h}
9974be9e2d1c add arg
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 79
diff changeset
275 ソースコード\ref{src:StackTestArgCbC}でAPIを呼び出しているが、 この呼び出し方法では\texttt{stack}が引数にない。
9974be9e2d1c add arg
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 79
diff changeset
276 \lstinputlisting[label=src:StackTestArgCbC, caption=StackTestInterfaceのAPI呼び出し(引数不足)]{src/StackTestArg.cbc}
9974be9e2d1c add arg
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 79
diff changeset
277 GearsOSのビルドを行うと、ソースコード\ref{src:argErr}のエラーが発生し、以降のビルドが停止する。
9974be9e2d1c add arg
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 79
diff changeset
278 Cmakeはエラーを検知するとビルドを止めるようにMakefileを作製するため、 GearsOSの拡張構文のレベルで停止ができる。
9974be9e2d1c add arg
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 79
diff changeset
279 \lstinputlisting[label=src:argErr, caption=InterfaceのAPI呼び出し時の引数エラー]{src/argError.txt}
9974be9e2d1c add arg
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 79
diff changeset
280
79
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 78
diff changeset
281 generate\_stub.pl側で、出てきたローカル変数と型の組はすべて保存している。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 78
diff changeset
282 Interface側のCodeGearの定義にも当然引数の型と名前は書かれている。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 78
diff changeset
283 このローカル変数の型と、CodeGearの定義の引数の型が、完全に一致しているかどうかのチェックを行うと、さらに強固な引数チェックが可能となる。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 78
diff changeset
284 ただし引数で渡す際に、例えばint型の値の加算処理などを行っていると、その処理の結果がint型になっているかどうかをPerlレベルでチェックする必要が出てしまう。
59
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 58
diff changeset
285
81
9974be9e2d1c add arg
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 79
diff changeset
286
72
951cb9681030 add source code
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 68
diff changeset
287 \section{InterfaceのAPIの未実装の検知}
81
9974be9e2d1c add arg
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 79
diff changeset
288 パースした結果、ヘッダファイルにAPIの定義がなかった場合は11行目の\texttt{unless}に処理が落ち、 エラー終了する。
72
951cb9681030 add source code
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 68
diff changeset
289
951cb9681030 add source code
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 68
diff changeset
290 \section{par goto のInterface経由の呼び出しの対応}