annotate paper/chapter/04-interface.tex @ 151:9ae59ed5c53a

update
author anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
date Tue, 16 Feb 2021 14:33:25 +0900
parents 4c0d2a58f6e5
children c9fb8f47a921
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の改良}
84
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 82
diff changeset
2 GearsOSのモジュール化の仕組みであるInterfaceは、 GearsOSの中心的な機能である。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 82
diff changeset
3 Interfaceの取り扱いには様々なメタ計算が含まれ、 このメタ計算はPerlスクリプトによって生成される。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 82
diff changeset
4
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 82
diff changeset
5 InterfaceをGearsOSで使ったプログラミングをするにつれて、様々な不足している機能や、改善すべき点が見つかった。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 82
diff changeset
6 またPerlスクリプトがInterfaceを適切に取り扱う為のAPIも必要となることが分かった。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 82
diff changeset
7 本章では本研究で行ったGearsOSのInterfaceの改良について述べる。
51
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 48
diff changeset
8
91
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 90
diff changeset
9 \section{GearsOSのInterfaceの構文の改良\label{sec:newInterface}}
16
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
10 GearsOSのInterfaceでは、 従来はDataGearとCodeGearを分離して記述していた。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
11 CodeGearの入出力をDataGearとして列挙する必要があった。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
12 CodeGearの入出力として\texttt{\_\_code()}の間に記述したDataGearの一覧と、Interface上部で記述したDataGearの集合が一致している必要がある。
53
1a4d4e64f0b8 add Stack Interface code
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 52
diff changeset
13 ソースコード\ref{src:old-stack}はStackのInterfaceの例である。
1a4d4e64f0b8 add Stack Interface code
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 52
diff changeset
14 \lstinputlisting[label=src:old-stack, caption=従来のStack Interface]{src/old-stack.h}
16
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
15
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
16 従来の分離している記法の場合、 このDataGearの宣言が一致していないケースが多々発生した。
58
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
17 またInterfaceの入力としてのDataGearではなく、 フィールド変数としてDataGearを使うプログラミングスタイルを取るケースも見られた。
16
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
18 GearsOSでは、 DataGearやフィールド変数をオブジェクトに格納したい場合、 Interface側ではなくImpl側に変数を保存する必要がある。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
19 Interface側に記述してしまう原因は複数考えられる。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
20 GearsOSのプログラミングスタイルに慣れていないことも考えられるが、構文によるところも考えられる。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
21 CodeGearとDataGearはInterfaceの場合は密接な関係性にあるが、 分離して記述してしまうと「DataGearの集合」と「CodeGearの集合」を別個で捉えてしまう。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
22 あくまでInterfaceで定義するCodeGearとDataGearはInterfaceのAPIである。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
23 これをユーザーに強く意識させる必要がある。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
24
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
25 golangにもInterfaceの機能が実装されている。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
26 golangの場合はInterfaceは関数の宣言部分のみを記述するルールになっている。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
27 変数名は含まれていても含まなくても問題ない。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
28
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
29 \begin{lstlisting}[frame=lrbt,label=src:golang_interface,caption={golangのinterface宣言}]
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
30 type geometry interface {
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
31 area() float64
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
32 perim() float64
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
33 }
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
34 \end{lstlisting}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
35
53
1a4d4e64f0b8 add Stack Interface code
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 52
diff changeset
36 GearsOSのInterfaceは入力と出力のAPIを定義するものであるので、 golangのInterfaceのように、関数のAPIを並べて記述するほうが簡潔であると考えた。
54
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 53
diff changeset
37 改良したInterfaceの構文でStackを定義したものをソースコード\ref{src:stack}に示す。
53
1a4d4e64f0b8 add Stack Interface code
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 52
diff changeset
38 \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
39
54
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 53
diff changeset
40
58
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
41 従来のInterfaceでは\texttt{<Type, Impl>}キーワードが含まれていた。
54
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 53
diff changeset
42 これはジェネリクスの機能を意識して導入された構文である。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 53
diff changeset
43 \texttt{Impl}キーワードは実装自身の型を示す型変換として使われていた。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 53
diff changeset
44 しかし基本Interfaceの定義を行う際にGearsOSのシステム上、CodeGearの第一引数は\texttt{Impl}型のポインタが来る。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 53
diff changeset
45 これはオブジェクト指向言語で言う\texttt{self}に相当するものであり、 自分自身のインスタンスを示すポインタである。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 53
diff changeset
46 Implキーワードは共通して使用されるために、 宣言部分からは取り外し、デフォルトの型キーワードとして定義した。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 53
diff changeset
47 \texttt{Type}キーワードは型変数としての利用を意識して導入されていたが、現在までのGearsOSの例題では導入されていなかった。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 53
diff changeset
48 ジェネリクスとしての型変数の利用の場合は\texttt{T}などの1文字変数がよく使われる。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 53
diff changeset
49 変更後の構文ではのちのジェネリクス導入のことを踏まえて、\texttt{Type}キーワードは削除した。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 53
diff changeset
50
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 53
diff changeset
51
56
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
52
53
1a4d4e64f0b8 add Stack Interface code
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 52
diff changeset
53 構文を変更するには、 GearsOSのビルドシステム上でInterfaceを利用している箇所を修正する必要がある。
1a4d4e64f0b8 add Stack Interface code
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 52
diff changeset
54 Interfaceはgenerate\_stub.plで読み込まれ、 CodeGearと入出力のDataGearの数え上げが行われる。
1a4d4e64f0b8 add Stack Interface code
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 52
diff changeset
55 この処理はInterfaceのパースに相当するものである。
84
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 82
diff changeset
56 パース対象のInterfaceの構文は、変更前の構文にしか対応していなかった。
150
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 142
diff changeset
57 新しい構文に対応させるために、generate\_stub.plが利用するInterfaceの解析ルーチンの書き直しを行っている。
53
1a4d4e64f0b8 add Stack Interface code
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 52
diff changeset
58
150
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 142
diff changeset
59 またInterfaceを使って定義されたデータ構造はすでに多数存在していた。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 142
diff changeset
60 これらの定義ファイルをすべてこの文法に対応させるのは煩雑である。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 142
diff changeset
61 その為、従来の定義ファイルの書式でも対応可能なように後方互換性を維持したまま解析処理を実装した。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 142
diff changeset
62 これによって従来のGearsOSの資源をそのまま利用することが可能となっている。
53
1a4d4e64f0b8 add Stack Interface code
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 52
diff changeset
63
91
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 90
diff changeset
64 \section{Implementの型定義ファイルの導入}\label{sec:implType}
56
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
65 Interfaceを使う言語では、 Interfaceが決まるとこれを実装するクラスや型が生まれる。
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
66 GearsOSもInterfaceに対応する実装が存在する。
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
67 例えばStack Interfaceの実装はSingleLinkedStackであり、 Queueの実装はSingleLinkedQueueやSynchronizedQueueが存在する。
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
68
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
69 このSynchronizedQueueはGearsOSではDataGearとして扱われる。
58
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
70 Interfaceの定義と同等な型定義ファイルが、 実装の型については存在しなかった。
151
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
71 従来はソースコード\ref{src:singleContext.h}に示すように、 context.hのDataGearの宣言部分に、構造体の形式で表現したものを手で記述していた。
56
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
72 \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
73
58
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
74 CbCファイルからはcontext.hをインクルードすることで問題なく型の使用は可能である。
91
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 90
diff changeset
75 Perlのトランスパイラであるgenerate\_stub.plはInterfaceの型定義ファイルをパースしていた。
58
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
76 しかし型定義ファイルの存在の有無がInterfaceと実装で異なっている為に、 generate\_stub.plでImplementの型に関する操作ができない。
56
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
77 Implementの型も同様に定義ファイルを作製すれば、generate\_stub.plで型定義を用いた様々な処理が可能となり、ビルドシステムが柔軟な挙動が可能となる。
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
78 また型定義は一貫して\texttt{*.h}に記述すれば良くなるため、 プログラマの見通しも良くなる。
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
79 本研究では新たにImplementの型定義ファイルを考案する。
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 GearsOSではすでにInterfaceの型定義ファイルを持っている。
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
82 Implementの型定義ファイルも、 Interfaceの型定義ファイルと似たシンタックスにしたい。
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
83 Implementの型定義ファイルで持たなければいけないのは、 どのInterfaceを実装しているかの情報である。
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
84 この情報は他言語ではInterfaceの実装を持つ型の宣言時に記述するケースと、型名の記述はせずに言語システムが実装しているかどうかを確認するケースが存在する。
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
85 Javaでは\texttt{implements}キーワードを用いてどのInterfaceを実装しているかを記述する。\cite{javaimpl}
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
86 ソースコード\ref{src:javaimpl}では、\texttt{Pig}クラスは\texttt{Animal} Interfaceを実装している。
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
87 \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
88 golangではInterfaceの実装は特にキーワードを指定せずに、 そのInterfaceで定義しているメソッドを、Implementに相当する構造体がすべて実装しているかどうかでチェックされる。
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
89 これはgolangはクラスを持たず、構造体を使ってInterfaceの実装を行う為に、 構造体の定義にどのInterfaceの実装であるかの情報をシンタックス上書けない為である。
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
90 GearsOSでは型定義ファイルを持つことができるために、 golangのような実行時チェックは行わず、 Javaに近い形で表現したい。
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
91
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
92 導入した型定義でSynchronizedQueueを定義したものをソースコード\ref{src:syncqueue}に示す。
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
93 大まかな定義方法はInterface定義のものと同様である。
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
94 違いとして\texttt{impl}キーワードを導入した。
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
95 これはJavaの\texttt{implements}に相当する機能であり、 実装したInterfaceの名前を記述する。
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
96 現状のGearsOSではImplが持てるInterfaceは1つのみであるため、\texttt{impl}の後ろにはただ1つの型が書かれる。
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
97 型定義の中では独自に定義したCodeGearを書いてもいい。
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
98 これはJavaのプライベートメソッドに相当するものである。
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
99 特にプライベートメソッドがない場合は、 実装側で所持したい変数定義を記述する。
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
100 SynchronizedQueueの例では\texttt{top}などが実装側で所持している変数である。
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
101 \lstinputlisting[label=src:syncqueue, caption=SynchronizedQueueの定義ファイル]{src/SynchronizedQueue.h}
84
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 82
diff changeset
102 従来context.hに直接記述していたすべてのDataGearの定義は、 スクリプトで機械的にInterfaceおよびImplementの型定義ファイルに変換を行った。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 82
diff changeset
103
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 82
diff changeset
104 context.hからInterfaceおよびImplementの型定義をファイルに分割することができた。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 82
diff changeset
105 しかしGearsOSのContextはすべてのDataGearの型定義を持つ必要がある。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 82
diff changeset
106 この為、context.hには分割した型定義ファイルをもとに、CbCのメタレベルに変換された型情報を書き込む必要がある。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 82
diff changeset
107 この処理はgenerate\_context.pl内でビルド時に行うようにした。
56
3a8c21a37bf1 interface
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 54
diff changeset
108
37
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 25
diff changeset
109 \section{Implementの型をいれたことによる間違ったGearsプログラミング}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 25
diff changeset
110 Implementの型を導入したが、 GearsOSのプログラミングをするにつれていくつかの間違ったパターンがあることがわかった。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 25
diff changeset
111 自動生成されるStubCodeGearは、 goto metaから遷移するのが前提であるため、 引数をContextから取り出す必要がある。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 25
diff changeset
112 Contextから取り出す場合は、 実装しているInterfaceに対応している置き場所からデータを取り出す。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 25
diff changeset
113 この置き場所は\texttt{data}配列であり、 配列の添え字は\texttt{enum Data}と対応している。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 25
diff changeset
114 また各CodeGearからgotoする際に、 遷移先のInterfaceに値を書き込みに行く。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 25
diff changeset
115
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 25
diff changeset
116
94
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 91
diff changeset
117 ImplementのCodeGearから内部でgotoするCodeGearの場合は引数としてImpl内部のデータ型は取り出すことができない。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 91
diff changeset
118 GearsOSではgoto文は、すべて\texttt{goto meta}に書き変わる。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 91
diff changeset
119 goto metaが発行されるとStub Code Gearに継続するが、現在のシステムではInterfaceから値をStubで取得する。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 91
diff changeset
120 Implementの内部の引数はこの時点ではStubから取得することはできず、 実装側のCodeGearの内部から取り出す必要がある。
66
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 60
diff changeset
121
44
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 43
diff changeset
122
94
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 91
diff changeset
123 StubからImpl内部のデータを取得しようと、 ImplをInterfaceと見立ててGearsOSのプログラミングをしたことがあった。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 91
diff changeset
124 ソースコード\ref{src:fsImpl}では、fs Interfaceに対する実装のfs\_implを、 あたかもInterfaceのように見せるハックである。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 91
diff changeset
125 generate\_stub.plはコンストラクタがあり、\texttt{\#interface}構文で呼ばれていたら、対象のDataGearがInterfaceであると判断する。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 91
diff changeset
126 この場合はコンストラクタに対応する文字列をコメントとして書いている為、StubCodeGearはImplをInterfaceだと思い込む。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 91
diff changeset
127 よって、 StubでContext内部のImplの置き場所から値を取得するようになった。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 91
diff changeset
128 しかし、この誤魔化しはメタレベルとノーマルレベルの分離どころではなく、GearsOSの設計に反する記述であった。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 91
diff changeset
129 \lstinputlisting[label=src:fsImpl, caption=ImplをInterfaceのようにふるまわせる為に、コンストラクタを偽装した例]{src/fsImpl.cbc}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 91
diff changeset
130
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 91
diff changeset
131
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 91
diff changeset
132 これはそもそも、Implの内部で持つ値はDataGearではなく、DataGearに含まれる値であるということを意識出来なかった為である。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 91
diff changeset
133 GearsOSはデータの単位はDataGearで行われる。
150
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 142
diff changeset
134 Interfaceの呼び出し時に使われる引数はDataGearとして処理されるが、ImplはそもそもImpl全体が1つのDataGearであるため、Stub経由で値をとるのは間違っていた。
94
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 91
diff changeset
135 Implの値をCodeGearの内部で使う場合は、第一引数で与えられる自分自身のDataGearの参照から取り出す必要がある。
150
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 142
diff changeset
136 この制約は現在はトランスパイラ・コンパイラ側での調査、エラー処理は行っておらず、GearsOSのプログラミング時のコーディングスタイルのルールのような扱いとなっている。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 142
diff changeset
137
91
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 90
diff changeset
138 \section{Interfaceのパーサーの構築}\label{sec:interfaceParser}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 90
diff changeset
139 従来のGearsOSのトランスパイラでは、 generate\_stub.plがInterfaceファイルを開き、情報を解析していた。
78
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 72
diff changeset
140 この情報解析はgetDataGear関数で行われていた。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 72
diff changeset
141 しかしこの関数は、CbCファイルのCodeGear、DataGearの解析で使用するルーチンと同じものである。
84
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 82
diff changeset
142 この為Interface特有のパースが出来ていなかった。
78
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 72
diff changeset
143
84
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 82
diff changeset
144 また、開いたヘッダファイルがInterfaceのファイルでも、そうでないCのヘッダファイルでも同様の解析をしてしまう。
78
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 72
diff changeset
145 Interfaceの定義ファイルの構文はすでに統一されたものを使用している。
84
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 82
diff changeset
146 Interfaceの定義の構文で実装されていないInterfaceファイルを読み込んだ場合は、 エラーとして処理したい。
78
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 72
diff changeset
147 また、Interfaceが満たすべきCodeGearの種類やInputDataGearの数の管理も行いたい。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 72
diff changeset
148 さらにInterfaceではなく、Implementの定義ファイルも同様にパースし、情報を解析したい。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 72
diff changeset
149
84
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 82
diff changeset
150 これらを実現するには、今までgenerate\_stub.plで使っていた情報解析ルーチンをもとに、最初からInterfaceに特化したパーサーが必要となる。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 82
diff changeset
151 本研究ではGears::InterfaceモジュールとしてInterfaceのパーサーを実装した。
78
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 72
diff changeset
152
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 72
diff changeset
153 \subsection{Gears::Interfaceの構成}
84
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 82
diff changeset
154 Gears::InterfaceはPerlのモジュールであるが、 実際はパーサー用のAPIを提供しているサブルーチンのまとまりである。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 82
diff changeset
155 その為オブジェクトを作らずに直接メソッドを呼び出して利用する。
85
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 84
diff changeset
156 Gears::Interfaceは2種類のAPIを提供している。
84
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 82
diff changeset
157
86
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 85
diff changeset
158 \subsection{パースAPI}
85
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 84
diff changeset
159 1つは\texttt{parse}メソッドである。これはパースしたいファイル名を与えると、Interfaceであった場合にヘッダファイルをパースして情報を返すAPIである。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 84
diff changeset
160 parseAPIでStack Interfaceをパースした結果の値をソースコード\ref{src:parsedStack1}に示す。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 84
diff changeset
161 これはPerlの連想配列のリファレンスで表現されている。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 84
diff changeset
162 \lstinputlisting[label=src:parsedStack1, caption=parseAPIでパースしたStack Interface]{src/parsedStack1.pl}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 84
diff changeset
163 contentが持つ要素は配列であり、 これはInterfaceをCbCの構造体に変換した際の内容である。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 84
diff changeset
164 file\_nameにはパースしたファイルのパスが入る。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 84
diff changeset
165 inner\_code\_gearsは、 Interfaceが継続として受け取るCodeGearの集合が入っている。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 84
diff changeset
166 StackではnextとwhenEmptyは入力で受け取るため、 inner\_code\_gearsに格納されている。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 84
diff changeset
167 nameはファイルパスではなく、 Interfaceの名前が格納されている。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 84
diff changeset
168
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 84
diff changeset
169 ImplファイルであるSingleLinkedStack.hをパースした結果をソースコード\ref{src:parsedSingleStack}に示す。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 84
diff changeset
170 \lstinputlisting[label=src:parsedSingleStack, caption=parseAPIでパースしたSingleLinkedStack]{src/parsedSingleLinkedStack.pl}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 84
diff changeset
171 ほとんど返す値はInterfaceの時のものと同様であるが、 Implの場合はisaキーに、実装しているInterfaceの名前が格納される。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 84
diff changeset
172
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 84
diff changeset
173 この情報はパース対象がInterface、もしくはImplementでなければ返さない。
151
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
174 ソースコード\ref{src:IsInterface}に示す記述で、 パーサーはInterfaceであるかどうかを、構文の正規表現にマッチするかどうかで確認をする。
84
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 82
diff changeset
175 \lstinputlisting[label=src:IsInterface, caption=Interfaceであるかどうかの確認]{src/IsInterface.pm}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 82
diff changeset
176
86
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 85
diff changeset
177 \subsection{詳細なパースAPI}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 85
diff changeset
178 parse APIはシンプルな結果を返していたが、 Interfaceに定義しているCodeGearの引数など、詳細な情報を取得したいケースがある。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 85
diff changeset
179 Gears::Interfaceに、詳細なパース用のAPIである\texttt{detailed\_parse} APIを用意した。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 85
diff changeset
180 先ほどのStack Interfaceをパースした結果をソースコード\ref{src:parsedStackDetail}に示す。
151
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
181 新たな情報としてcodeNameが連想配列の要素に追加されている(ソースコード2行目)。
86
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 85
diff changeset
182 codeNameはCodeGearの名前がキーになっており、valueとして引数の文字列情報が\texttt{args}に、、 Interfaceの呼び出し時に必要な引数の個数が\texttt{argc}に設定される。
151
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
183 これらの情報は配列codesからもアクセス可能となっている(ソースコード48行目)。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
184 Interfaceが持つDataGearの一覧は、配列dataに格納される(ソースコード62行目)。
86
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 85
diff changeset
185
151
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
186 OutputDataGearがあるCodeGearの一覧が、 hasOutputArgsに格納される(ソースコード68行目)。
86
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 85
diff changeset
187 codeNameと同様に、CodeGearの名前がキーとなっている。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 85
diff changeset
188 対応する値は、 出力する変数の名前と、その型の組のリストになっている。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 85
diff changeset
189
87
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 86
diff changeset
190 この詳細なパースの結果は、以下に例を示す用途で使われる。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 86
diff changeset
191 \begin{itemize}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 86
diff changeset
192 \item implementのCodeGearの名前の保管
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 86
diff changeset
193 \item InterfaceのCodeGearの定義と実装の対応の確認
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 86
diff changeset
194 \item OutputDataGearがあるAPI呼び出しであるかの確認
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 86
diff changeset
195 \item API呼び出し時の引数のチェック
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 86
diff changeset
196 \end{itemize}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 86
diff changeset
197
86
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 85
diff changeset
198 \lstinputlisting[label=src:parsedStackDetail, caption=Stack Interfaceの詳細なパース]{src/StackParseDetail.pl}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 85
diff changeset
199
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 85
diff changeset
200
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 85
diff changeset
201
84
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 82
diff changeset
202 \subsection{Interfaceパーサーの呼び出し}
87
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 86
diff changeset
203 定義したパーサーは都度呼ぶこともできるが、ヘッダファイルのパスを入力で与える必要がある。
88
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 87
diff changeset
204 generate\_stub.plは実行時のコマンドライン引数としてヘッダファイルは与えられないので、スクリプト中で探索する必要がある。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 87
diff changeset
205 毎回パースしたいInterface名の探索をするのは煩雑である。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 87
diff changeset
206
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 87
diff changeset
207 基本的にgenerate\_stub.plではInterfaceの名前がすでに判明しており、そのInterfaceのパースした結果を取得したいのがほとんどである。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 87
diff changeset
208 ここからスクリプト内部で、 Interfaceの名前とパースした結果を対応させる連想配列を実装した。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 87
diff changeset
209 generate\_stub.plでは、スクリプト起動時に連想配列を変換処理を行う前に作製する。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 87
diff changeset
210 ソースコード\ref{src:createHeaderName2Info}のサブルーチンが連想配列を作り出す処理である。
87
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 86
diff changeset
211 このサブルーチンでは、ヘッダファイルを起動時に全探査し、 すべてパースを行う。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 86
diff changeset
212 4行目でGears::UtilのAPI呼び出しをしているが、 このAPIはGearsOSで使うヘッダファイルを、指定されたパスから再帰的に探索するものである。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 86
diff changeset
213
151
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
214 なお同名のヘッダファイルが見つかった場合は、 変換をしているCbCファイルと同じディレクトリにあるヘッダファイルが優先される(ソースコード 13行目)。
84
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 82
diff changeset
215 \lstinputlisting[label=src:createHeaderName2Info, caption=ヘッダファイルの名前とInterfaceのパース結果の対応リストの作製]{src/createHeaderName2Info.pl}
78
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 72
diff changeset
216
109
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 107
diff changeset
217 \section{Interface定義ファイル内でのincludeのサポート}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 107
diff changeset
218 Interfaceで定義したAPIの引数として、別のヘッダファイルに含まれる構造体を使いたい場合がある。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 107
diff changeset
219 DataGearに変換するのが望ましいが、実装が煩雑になることが予想される場合などで、一度構造体を引数として利用するケースがあった。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 107
diff changeset
220 従来はInterfaceの定義ファイルの中身はgenerate\_stub.plがAPIの解析しか使っておらず、ここでC言語の\texttt{\#include}マクロを使っても情報が落とされてしまっていた。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 107
diff changeset
221 この為Interfaceで別のヘッダファイルの型を使いたい場合は、手動でcontext.hに\texttt{\#include}文を書く必要があった。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 107
diff changeset
222
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 107
diff changeset
223 これらのinclude処理を、Perlトランスパイラ側で自動で行うように実装を行った。
151
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
224 これに伴い、Interface、Implの定義ファイルで使いたいヘッダファイルをinclude文で指定することが可能となった(ソースコード\ref{src:SingleLinkedQueueInc})。
109
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 107
diff changeset
225 \lstinputlisting[label=src:SingleLinkedQueueInc, caption=Include文を書けるようになったImplementの宣言]{src/MCWorker.h}
68
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 66
diff changeset
226
91
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 90
diff changeset
227 \section{Interfaceの実装のCbCファイルへの構文の導入} \label{sec:newInterfaceInCbC}
82
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 81
diff changeset
228 今までのGearsOSではマクロに似た\texttt{\#interface}構文で使用するInterfce名を指定した。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 81
diff changeset
229 しかしInterfaceを実装する場合も、 InterfaceのAPIを利用する際も同じシンタックスであった。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 81
diff changeset
230 この2つは意味が異なっている為、 シンタックスを分離したい。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 81
diff changeset
231 Implementの型定義ファイルを導入したので、Interfaceの実装をする場合に別のシンタックスを導入する。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 81
diff changeset
232
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 81
diff changeset
233 導入された構文をソースコード\ref{src:implHeader}に示す。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 81
diff changeset
234 この例ではStack Interfaceの実装としてSingleLinkedStackを定義する宣言である。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 81
diff changeset
235
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 81
diff changeset
236 Implementの宣言の構文では、 まず\texttt{\#impl}の後ろに実装したいIntefaceの名前を入れる。
90
a93c2401753b s/for/as/
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 89
diff changeset
237 続く\texttt{as}キーワードの後ろに、 Implementの型名を記述する。
82
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 81
diff changeset
238 宣言はgenerate\_stub.plが読み取り、 変換した後のCbCファイルからは該当する行が削除される。
106
0512c7f88417 add src
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 105
diff changeset
239 \lstinputlisting[label=src:implHeader, caption=DataGearの使用の宣言]{src/implHeader.h}
0512c7f88417 add src
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 105
diff changeset
240
37
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 25
diff changeset
241
88
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 87
diff changeset
242
105
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 104
diff changeset
243 \section{内部データ構造に利用するDataGearの使用構文の導入}
106
0512c7f88417 add src
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 105
diff changeset
244 InterfaceおよびImplmentで使うDataGearは、通常引数の形でCodeGearに入力される。
0512c7f88417 add src
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 105
diff changeset
245 これ以外で、CodeGearの内部でデータ構造の表現の為に利用されるDataGearが存在する。
0512c7f88417 add src
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 105
diff changeset
246 例えばSingleLinkedStackの実装では、Stackにいれる値の表現としてElementDataGearを使う。
0512c7f88417 add src
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 105
diff changeset
247 Elementは入力で受け取ったunion Data型を使って、CodeGer内部で作製している。
0512c7f88417 add src
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 105
diff changeset
248 \lstinputlisting[label=src:pushStackCbC, caption=CodeGear内部で作られるElement DataGear]{src/pushStack.cbc}
0512c7f88417 add src
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 105
diff changeset
249
0512c7f88417 add src
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 105
diff changeset
250 意味的にはInterfaceとしてではなく、DataGearそのものを使いたいケースであるため\texttt{\#interface}構文以外の新しいDataGearの使用を宣言する構文を導入したい。
0512c7f88417 add src
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 105
diff changeset
251
0512c7f88417 add src
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 105
diff changeset
252 DataGearを明示的に使うことを宣言する構文として\texttt{\#data}を導入した。
0512c7f88417 add src
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 105
diff changeset
253 これは使用したいDataGearの定義ファイルを\texttt{\#data}の後ろに記述する。
0512c7f88417 add src
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 105
diff changeset
254 SingleLinkedStackの場合の例をソースコード\ref{src:implStackdef}に示す。
0512c7f88417 add src
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 105
diff changeset
255 この例ではNodeとElementを使用している。
0512c7f88417 add src
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 105
diff changeset
256 \lstinputlisting[label=src:implStackdef, caption=DataGearの使用の宣言]{src/implStackDef.cbc}
0512c7f88417 add src
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 105
diff changeset
257
0512c7f88417 add src
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 105
diff changeset
258 この宣言は、使用しているDataGearを調査しcontext.hを作製するgenerate\_context.plが発見できなければならない。
0512c7f88417 add src
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 105
diff changeset
259 しかしgenerate\_context.plは、メタ情報を含む形にgenerate\_stub.plはトランスパイルした後に実行される。
0512c7f88417 add src
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 105
diff changeset
260 GearsOSで拡張したマクロの用なInterface関連の宣言はここで消されてしまう。
0512c7f88417 add src
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 105
diff changeset
261 DataGearの使用の宣言は、コメントの形で変換後のファイルに書き出すようにし、generate\_context.plでも参照可能にした。
0512c7f88417 add src
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 105
diff changeset
262 SingleLinkedStackの例題に対応する変換後のコードを、ソースコード\ref{src:implStackdefAfter}に示す。
0512c7f88417 add src
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 105
diff changeset
263 \lstinputlisting[label=src:implStackdefAfter, caption=DataGearの使用の宣言のPerlによる変換後]{src/IncludeNode.cbc}
0512c7f88417 add src
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 105
diff changeset
264
105
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 104
diff changeset
265
91
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 90
diff changeset
266 \section{Interface APIに対応したCodeGearの名前の自動変換} \label{sec:autoCodeGearName}
89
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 88
diff changeset
267 InterfaceのAPIに対応したCodeGearを実装する際、今までは暗黙にInterface名とImplの型名をつなげた名前で定義していた。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 88
diff changeset
268 例えばStack InterfaceのAPIであるpopをSingleLinkedStackが実装した場合、CodeGearの名前はpopSingleLinkedStackにしていた。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 88
diff changeset
269
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 88
diff changeset
270 CodeGearの名前につけられるImplの名前は、GearsOSのシステムがCodeGearの識別に使うメタな情報と言える。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 88
diff changeset
271 ユーザーレベルではInterfaceのAPIと同じ名前のCodeGearを実装できると、GearsOSのメタなCodeGearの処理と分離可能である。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 88
diff changeset
272 この為Perlスクリプトで、InterfaceのImplementの場合はCodeGearの名前を自動で変換する機能を実装した。
103
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 100
diff changeset
273 ここで変換するCodeGearの名前は、 CodeGearの定義部分と、継続で渡すCodeGearの名前の部分である。
89
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 88
diff changeset
274
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 88
diff changeset
275 generate\_stub.plはソースコードの情報を読み取るフェーズと、変換した情報を書き込むフェーズに別けられる。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 88
diff changeset
276 まずは読み取りの際の処理をソースコード\ref{src:replaceCodeGearName1}に示す。
151
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
277 generate\_stub.plは、CodeGearの宣言時に、自分が今変換しているInterfaceのImplのCbCファイルかどうかをまず確認する(ソースコード6行目)。
89
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 88
diff changeset
278 ImplのCbCファイルであった場合、変数\texttt{\$implInterfaceInfo}に具体的な値が入っているため、if文に進む。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 88
diff changeset
279 if文の中ではInterfaceのパースの結果と、今定義しているCodeGearの名前を比較する。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 88
diff changeset
280 ここでInterfaceのAPIであるCodeGearの名前と、今CbCファイルで定義しているCodeGearの名前が等しい場合、後ろに型名をつけたCodeGearの名前に変換し、スクリプト内で変換したことを記憶する。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 88
diff changeset
281 \lstinputlisting[label=src:replaceCodeGearName1, caption=CodeGearの名前が等しいかどうかの確認]{src/replaceCodeGearName1.pl}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 88
diff changeset
282
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 88
diff changeset
283 CodeGearの宣言は、 Contextを引数に含めるようにすでに書き換えるルーチンで処理されていた。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 88
diff changeset
284 この部分でCodeGearの名前を変更したい。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 88
diff changeset
285 実際に書き出している処理の部分をソースコード\ref{src:replaceCodeGearName2}に示す。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 88
diff changeset
286 この際に書き込むCodeGearの名前は、定義のCodeGear名を正規表現でキャプチャし、変数\texttt{\$currentCodeGearName}に代入している。(5行目)
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 88
diff changeset
287 読み込み時に作製した、名前の変更があることを保存する連想配列\texttt{\$replaceCodeGearNames}に、今書き込もうとしているCodeGearの名前を問い合わせる。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 88
diff changeset
288 連想配列側にCodeGearの名前に対応する値があった場合は書き換え対象なので、 \texttt{\$currentCodeGearName}を、ソースコード\ref{src:replaceCodeGearName1}で作製したCodeGearの名前に変換する。
103
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 100
diff changeset
289 \lstinputlisting[label=src:replaceCodeGearName2, caption=CodeGearの名前の変更]{src/replaceCodeGearName2.pl}
89
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 88
diff changeset
290
103
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 100
diff changeset
291 実際に変換される様子を見る。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 100
diff changeset
292 ソースコード\ref{src:pickupBefore}は、 Phils Interfaceの実装のソースコードの一部である。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 100
diff changeset
293 Phils Interfaceにあるpickup\_lforkと、 eatingのCodeGearの定義をしている。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 100
diff changeset
294 3行目ではcheckAndSetに継続として、 pickup\_rforkとeatingを渡している。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 100
diff changeset
295 これらはそれぞれPhils Interfceに定義があるCodeGearの名前であり、 このファイル中で実装している。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 100
diff changeset
296
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 100
diff changeset
297 \lstinputlisting[label=src:pickupBefore, caption=PhilsInterfaceの実装]{src/pickupBefore.cbc}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 100
diff changeset
298
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 100
diff changeset
299 変換された結果をソースコード\ref{src:pickupAfter}に示す。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 100
diff changeset
300 まずCodeGearの宣言時に名前の末尾に実装の型名であるPhilsImplがついている。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 100
diff changeset
301 Gearefマクロに変換されている為見づらいが、 6行目、7行目でenumの定義に変換されてcontextに書き込まれているのが解る。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 100
diff changeset
302 \lstinputlisting[label=src:pickupAfter, caption=変換されたPhilsInterfaceの実装]{src/pickupAfter.cbc}
88
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 87
diff changeset
303
58
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
304 \section{GearsCbCのInterfaceの実装時の問題}
39
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 38
diff changeset
305
58
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
306 Interfaceとそれを実装するImplの型が決定すると、最低限満たすべきCodeGearのAPIは一意に決定する。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
307 ここで満たすべきCodeGearは、Interfaceで定義したCodeGearと、 Impl側で定義した privateなCodeGearとなる。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
308 例えばStack Interfaceの実装を考えると、各Implで\texttt{pop}, push, shift, isEmptyなどを実装する必要がある。
39
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 38
diff changeset
309
58
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
310 従来はプログラマが手作業でヘッダーファイルの定義を参照しながら\texttt{.cbc}ファイルを作成していた。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
311 手作業での実装のため、 コンパイル時に下記の問題点が多発した。
45
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 44
diff changeset
312
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 44
diff changeset
313 \begin{itemize}
58
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
314 \item CodeGearの入力のフォーマットの不一致
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
315 \item Interfaceの実装のCodeGearの命名規則の不一致
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
316 \item 実装を忘れているCodeGearの発生
45
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 44
diff changeset
317 \end{itemize}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 44
diff changeset
318
48
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 46
diff changeset
319
58
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
320 特にGearsOSの場合はPerlスクリプトによって純粋なCbCに一度変換されてからコンパイルが行われる。
91
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 90
diff changeset
321 実装の状況とトランスパイラの組み合わせによっては、 CbCコンパイラレベルでコンパイルエラーを発生させないケースがある。
58
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
322 この場合は実際に動作させながら、gdb, lldbなどのCデバッガを用いてデバッグをする必要がある。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
323 またCbCコンパイラレベルで検知できても、すでに変換されたコード側でエラーが出る。
91
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 90
diff changeset
324 このため、 トランスパイラの挙動をトレースしながらデバッグをする必要がある。
58
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
325 Interfaceの実装が不十分であることのエラーは、 GearsOSレベル、最低でもCbCコンパイラのレベルで完全に検知したい。
48
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 46
diff changeset
326
58
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
327 \section{Interfaceを満たすコード生成の他言語の対応状況}
48
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 46
diff changeset
328
58
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
329 Interfaceを機能として所持している言語の場合、Interfaceを完全に見たいしているかどうかはコンパイルレベルか実行時レベルで検知される。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
330 例えばJavaの場合はInterfaceを満たしていない場合はコンパイルエラーになる。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
331
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
332
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
333 InterfaceのAPIを完全に実装するのを促す仕組みとして、Interfaceの定義からエディタやツールが満たすべき関数と引数の組を自動生成するツールがある。
45
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 44
diff changeset
334
58
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
335 Javaでは様々な手法でこのツールを実装している。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
336 Microsoftが提唱しているIDEとプログラミング言語のコンパイラをつなぐプロトコルにLanguage Serverがある。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
337 Language Serverはコーディング中のソースコードをコンパイラ自身でパースし、 型推論やエラーの内容などをIDE側に通知するプロトコルである。
142
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 111
diff changeset
338 主要なJavaのLanguage Serverの実装であるeclipse.jdt.ls\cite{eclipse.jdt.ls}では、 LanguageServerの機能として未実装のメソッドを検知する機能が実装されている\cite{eclipse_pull322}。
58
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
339 この機能を応用してvscode上から未実装のメソッドを特定し、 雛形を生成する機能がある。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
340 他にもIntelliJ IDEなどの商用IDEでは、 IDEが独自に未実装のメソッドを検知、雛形を生成する機能を実装している。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
341
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
342
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
343 golangの場合は主に\texttt{josharian/impl}\cite{golang_impl}が使われている。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
344 これはインストールすると\texttt{impl}コマンドが使用可能になり、 実装したいInterfaceの型と、 Interfaceを実装するImplの型(レシーバ)を与えることで雛形が生成される。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
345 主要なエディタであるvscodeのgolangの公式パッケージである\texttt{vscode-go}\cite{vscode-go}でも導入されており、 vscodeから呼び出すことが可能である。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
346 vscode以外にもvimなどのエディタからの呼び出しや、 シェル上で呼び出して標準出力の結果を利用することが可能である。
46
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 45
diff changeset
347
111
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 109
diff changeset
348 \section{GearsOSでのInterfaceを満たすCbCの雛形生成}\label{sec:impl2cbc}
58
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
349 GearsOSでも同様のInterfaceの定義から実装するCodeGearの雛形を生成したい。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
350 LanguageServerの導入も考えられるが、 今回の場合はC言語のLanguageServerをCbC用にまず改良し、 さらにGearsOS用に書き換える必要がある。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
351 現状のGearsOSが持つシンタックスはCbCのシンタックスを拡張しているものではあるが、これはCbCコンパイラ側には組み込まれていない。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
352 LanguageServerをGearsOSに対応する場合、 CbCコンパイラ側にGearsOSの拡張シンタックスを導入する必要がある。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
353 CbCコンパイラ側への機能の実装は、 比較的難易度が高いと考えらる。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
354 CbCコンパイラ側に手をつけず、 Interfaceの入出力の検査は既存のGearsOSのビルドシステム上に組み込みたい。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
355
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
356 対してgolangの\texttt{impl}コマンドのように、 シェルから呼び出し標準出力に結果を書き込む形式も考えられる。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
357 この場合は実装が比較的容易かつ、 コマンドを呼び出して標準出力の結果を使えるシェルやエディタなどの各プラットフォームで使用可能となる。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
358 先行事例を参考に、コマンドを実行して雛形ファイルを生成するコマンド\texttt{impl2cbc.pl}をGearsOSに導入した。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
359 \texttt{impl2cbc.pl}の処理の概要を図\ref{fig:impl2cbc}に示す。
46
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 45
diff changeset
360
88
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 87
diff changeset
361 impl2cbc.plでは、 実行時引数にImplementの型定義ファイルを与える。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 87
diff changeset
362 impl2cbc.plの内部でImplementのパース結果からInterfaceを特定し、 雛形を生成する。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 87
diff changeset
363 Interfaceの定義ファイルが複数見つかった場合、Implementの型定義ファイルがあるディレクトリと同じファイルが優先される。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 87
diff changeset
364 コマンドラインからの呼び出しと、生成した結果をソースコードに示す。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 87
diff changeset
365
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 87
diff changeset
366
46
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 45
diff changeset
367
58
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
368 \begin{figure}[hp]
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
369 \begin{center}
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
370 \includegraphics[width=130mm]{drawio/impl2cbc.pdf}
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
371 \end{center}
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
372 \caption{impl2cbcの処理の流れ}
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
373 \label{fig:impl2cbc}
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
374 \end{figure}
48
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 46
diff changeset
375
88
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 87
diff changeset
376 \lstinputlisting[label=src:callimpl2cbc, caption=impl2cbcの実行方法]{src/callimpl2cbc.sh}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 87
diff changeset
377 \lstinputlisting[label=src:impl2cbcExecuted, caption=生成された雛形ファイル]{src/gneratedPhils.cbc}
58
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
378
88
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 87
diff changeset
379 \subsection{雛形生成の手法}
58
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
380 Interfaceでは入力の引数がImplと揃っている必要があるが、 第一引数は実装自身のインスタンスがくる制約となっている。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
381 実装自身の型は、Interface定義時には不定である。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
382 その為、 GearsOSではInterfaceのAPIの宣言時にデフォルト型変数\texttt{Impl}を実装の型として利用する。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
383 デフォルト型\texttt{Impl}を各実装の型に置換することで自動生成が可能となる。
52
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 51
diff changeset
384
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 51
diff changeset
385
58
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
386 実装すべきCodeGearはInterfaceとImpl側の型を見れば定義されている。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
387 \texttt{\_\_code}で宣言されているものを逐次生成すればよいが、 継続として呼び出されるCodeGearは具体的な実装を持たない。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
388 GearsOSで使われているInterfaceには概ね次の継続である\texttt{next}が登録されている。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
389 \texttt{next}そのものはInterfaceを呼び出す際に、入力として与える。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
390 その為各Interfaceに入力として与えられた\texttt{next}を保存する場所は存在するが、 nextそのものの独自実装は各Interfaceは所持しない。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
391 したがってこれをInterfaceの実装側で明示的に実装することはできない。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
392 雛形生成の際に、入力として与えられるCodeGearを生成してしまうと、プログラマに混乱をもたらしてしまう。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
393
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
394 入力として与えられているCodeGearは、Interfaceに定義されているCodeGearの引数として表現されている。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
395 コードに示す例では、\texttt{whenEmpty}は入力して与えられているCodeGearである。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
396 雛形を生成する場合は、入力として与えられたCodeGearを除外して出力を行う。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
397 順序はInterfaceをまず出力した後に、 Impl側を出力する。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
398
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
399
111
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 109
diff changeset
400 \subsection{コンストラクタの自動生成} \label{sec:autoConst}
58
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
401 雛形生成では他にコンストラクタの生成も行う。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
402 GearsOSのInterfaceのコンストラクタは、 メモリの確保及び各変数の初期化を行う。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
403 メモリ上に確保するのは主にInterfaceとImplのそれぞれが基本となっている。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
404 Interfaceによっては別のDataGearを内包しているものがある。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
405 その場合は別のDataGearの初期化もコンストラクタ内で行う必要があるが、 自動生成コマンドではそこまでの解析は行わない。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
406
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
407
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
408 コンストラクタのメンバ変数はデフォルトでは変数は0、ポインタの場合はNULLで初期化するように生成する。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
409 このスクリプトで生成されたコンストラクタを使う場合、 CbCファイルから該当する部分を削除すると、\texttt{generate\_stub.pl}内でも自動的に生成される。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
410 自動生成機能を作成すると1CbCファイルあたりの記述量が減る利点がある。
82
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 81
diff changeset
411 generate\_stub.pl内で作製する場合は、 すでにメタ情報を含むコードに書き換えたものを作製する。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 81
diff changeset
412 その為厳密には同じコードを生成する訳ではない。
58
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
413
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
414
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
415 明示的にコンストラクタが書かれていた場合は、 Perlスクリプト内での自動生成は実行しないように実装した。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
416 これはオブジェクト指向言語のオーバーライドに相当する機能と言える。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
417 現状のGearsOSで使われているコンストラクタは、 基本は\texttt{struct Context*}型の変数のみを引数で要求している。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
418 しかしオブジェクトを識別するためにIDを実装側に埋め込みたい場合など、 コンストラクタ経由で値を代入したいケースが存在する。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
419 この場合はコンストラクタの引数を増やす必要や、 受け取った値をインスタンスのメンバに書き込む必要がある。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
420 具体的にどの値を書き込めば良いのかまではPerlスクリプトでは判定することができない。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
421 このような細かな調整をする場合は、 generate\_stub.pl側での自動生成はせずに、 雛形生成されたコンストラクタを変更すれば良い。
b1e2bcdd5191 fix order
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 56
diff changeset
422 あくまで雛形生成スクリプトはプログラマ支援であるため、 いくつかの手動での実装は許容している。
59
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 58
diff changeset
423
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 58
diff changeset
424
111
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 109
diff changeset
425 \section{Interfaceの引数の数の確認} \label{sec:argNumber}
79
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 78
diff changeset
426 GearsOSのノーマルレベルでは、 InterfaceのAPIの呼び出しは\texttt{interface->method(arg)}の呼び出し方であった。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 78
diff changeset
427 \texttt{arg}は引数であり、これはInterfaceで定義したAPIの引数の一致している必要がある。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 78
diff changeset
428 Interfaceの定義の引数は、Implの実装自身が第一引数でくる制約があった。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 78
diff changeset
429 この制約の為に、 厳密にはInterfaceの定義ファイルに書かれているCodeGearの引数と、Interfaceの呼び出しの引数は数が揃ってはいない。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 78
diff changeset
430 generate\_stub.plは第一引数が実装自身の型であるので、union Data型にキャストし、Contextの引数保存場所に書き込むようになっている。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 78
diff changeset
431 問題が第1引数以外の引数が揃っていない場合である。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 78
diff changeset
432 generate\_stub.plを通すと、次の継続はgoto metaに変換されてしまい、引数情報が抜けてしまう。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 78
diff changeset
433 その為引数はすべて適切にcontextに書き込まれている必要があるが、 一部引数が足りず書き込みが出来なかったケースでも、 CbCコンパイラレベルでは引数関係のエラーが発生しない。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 78
diff changeset
434 また上手くInterfaceの入力の数を取得できなかった場合も、generate\_stub.plは止まらずにマクロを生成してしまう。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 78
diff changeset
435 Gearefを通してcontextに書き込む右辺値が抜けているコードなどがよく発生した。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 78
diff changeset
436 この場合は原因を.cファイルと.cbcファイル、Interfaceファイル、contextファイルのすべてを確認しなければならず、デバッグが非常に困難だった。
81
9974be9e2d1c add arg
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 79
diff changeset
437 InterfaceのAPI呼び出し時の引数検知は、 Interfaceの型定義ファイルからCodeGearの入力の数の取得が不十分であるのが主な原因であった。
79
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 78
diff changeset
438
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 78
diff changeset
439
81
9974be9e2d1c add arg
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 79
diff changeset
440 この問題はPerlスクリプトレベルで引数のチェックを十分に行う必要がある。
9974be9e2d1c add arg
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 79
diff changeset
441 すでにInterfaceのパーサーは実装している為、 パーサー経由で呼び出しているAPIを持つInterfaceの情報を取得する。
9974be9e2d1c add arg
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 79
diff changeset
442 パースした結果の情報に、 各CodeGearの引数情報と引数の数を取得できれば、それらとAPI呼び出し時に与えられている引数を比較すればチェックが可能である。
9974be9e2d1c add arg
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 79
diff changeset
443 現状は引数の数が揃っているかどうかで確認をしている。
9974be9e2d1c add arg
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 79
diff changeset
444
151
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
445 Intefaceの引数を確認し、Gearefマクロを生成しているgenerate\_stub.plの箇所に、引数の確認処理を実装した(ソースコード\ref{src:parsedArgs})。
81
9974be9e2d1c add arg
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 79
diff changeset
446 ここでAPI呼び出し時の引数は、\texttt{\$tmpArgs}に代入されている。
9974be9e2d1c add arg
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 79
diff changeset
447 CbCの関数呼び出しの引数はカンマで区切るので、2行目でカンマで文字列を分割し、引数を配列\texttt{@args}に変換している。
9974be9e2d1c add arg
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 79
diff changeset
448
9974be9e2d1c add arg
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 79
diff changeset
449 generate\_stub.plはローカル変数のすべての型を記録しているので、6行目でAPI呼び出しをしているインスタンスの名前からInterfaceを特定する。
9974be9e2d1c add arg
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 79
diff changeset
450 特定後、ヘッダファイルの場所を取得し、8行目でInterfaceのパーサーを呼び出している。
9974be9e2d1c add arg
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 79
diff changeset
451 パーサーから取得した情報から、メソッドの引数の数を14行目で取得し、 引数が格納されている配列\texttt{@args}の要素数と比較している。
79
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 78
diff changeset
452 \lstinputlisting[label=src:parsedArgs, caption=Perlレベルでの引数チェック]{src/parsedArgs.pl}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 78
diff changeset
453
81
9974be9e2d1c add arg
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 79
diff changeset
454 Perlスクリプトでエラーを検知すると、 エラーで終了する。
9974be9e2d1c add arg
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 79
diff changeset
455 ソースコード\ref{src:StackTestArg}のInterfaceの\texttt{insertTest1}を呼び出す例題でエラーを発生さる。
9974be9e2d1c add arg
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 79
diff changeset
456 \lstinputlisting[label=src:StackTestArg, caption=StackTestInterfaceの定義]{src/StackTestArg.h}
9974be9e2d1c add arg
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 79
diff changeset
457 ソースコード\ref{src:StackTestArgCbC}でAPIを呼び出しているが、 この呼び出し方法では\texttt{stack}が引数にない。
9974be9e2d1c add arg
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 79
diff changeset
458 \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
459 GearsOSのビルドを行うと、ソースコード\ref{src:argErr}のエラーが発生し、以降のビルドが停止する。
9974be9e2d1c add arg
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 79
diff changeset
460 Cmakeはエラーを検知するとビルドを止めるようにMakefileを作製するため、 GearsOSの拡張構文のレベルで停止ができる。
9974be9e2d1c add arg
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 79
diff changeset
461 \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
462
79
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 78
diff changeset
463 generate\_stub.pl側で、出てきたローカル変数と型の組はすべて保存している。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 78
diff changeset
464 Interface側のCodeGearの定義にも当然引数の型と名前は書かれている。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 78
diff changeset
465 このローカル変数の型と、CodeGearの定義の引数の型が、完全に一致しているかどうかのチェックを行うと、さらに強固な引数チェックが可能となる。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 78
diff changeset
466 ただし引数で渡す際に、例えばint型の値の加算処理などを行っていると、その処理の結果がint型になっているかどうかをPerlレベルでチェックする必要が出てしまう。
59
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 58
diff changeset
467
111
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 109
diff changeset
468 \section{InterfaceのAPIにないものを呼び出した場合の検知} \label{sec:apinot}
105
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 104
diff changeset
469 InterfaceAPI呼び出し時に、そもそもInterfaceファイルに定義していないAPIを呼び出してしまうことがある。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 104
diff changeset
470 これもCbCファイルの変換前に処理を行いたい。
82
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 81
diff changeset
471
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 81
diff changeset
472 API呼び出し時の処理は、ソースコード\ref{src:parsedArgs}の処理そのものであるため、この処理の中に未実装のAPIを検知する様にした。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 81
diff changeset
473 呼び出し元のInterfaceの情報パースした結果、ヘッダファイルにAPIの定義がなかった場合は11行目の\texttt{unless}に処理が落ち、 エラー終了する。
104
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 103
diff changeset
474
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 103
diff changeset
475
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 103
diff changeset
476 ソースコード\ref{src:NotFoundDefine.cbc}の例では、 Phils Interfaceに存在しないsleepingを呼び出している。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 103
diff changeset
477 この状態でビルドを実行すると、ソースコード\ref{src:NotFoundDefine.sh}のエラーがMake時に発生し、ビルドが停止する。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 103
diff changeset
478 \lstinputlisting[label=src:NotFoundDefine.cbc, caption=存在しないsleepingの呼び出し]{src/NotFoundDefine.cbc}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 103
diff changeset
479 \lstinputlisting[label=src:NotFoundDefine.sh, caption=存在しないAPIの呼び出し時のエラー]{src/NotFoundDefine.sh}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 103
diff changeset
480
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 103
diff changeset
481
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 103
diff changeset
482
111
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 109
diff changeset
483 \section{InterfaceのAPIを完全に実装していない場合の検知}\label{sec:interfaceNotImpl}
104
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 103
diff changeset
484 InterfaceのAPIで定義したCodeGearは、Impl側はすべて実装している必要がある。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 103
diff changeset
485 しかし、 CodeGearの実装を忘れてしまうケースがある。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 103
diff changeset
486 これをPerlレベルで検知したい。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 103
diff changeset
487
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 103
diff changeset
488 generate\_stub.plは2度CbCファイルを読み込む。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 103
diff changeset
489 書き出しに移る前に、変換しようとしているCbCファイルのCodeGearの情報はすべて取得できている為に、ここで検知可能である。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 103
diff changeset
490 初回のCbCファイルの読み込み終了時に、 検出できたCodeGearの名前と、CbCファイルが実装しようとしているInterfaceの定義を見比べる。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 103
diff changeset
491 CodeGearをすべて満たしていなかった場合はエラーを出したい。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 103
diff changeset
492
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 103
diff changeset
493 ソースコード\ref{src:notDefInterfaceAPI}は、Interfaceが要求しているAPIを実装したかを確認する部分である。
151
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
494 変換しようとしているCbCファイルが何かのInterfaceを実装しようとしている場合、 Interfaecの定義ファイルのパース結果から、満たすべきCodeGearの一覧を取得する(ソースコード1、2行目)。
104
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 103
diff changeset
495 実装していた場合は6行目でマークをつけ、 マークがなかったCodeGearが検知された時点でエラーを発生させる。(12行目)
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 103
diff changeset
496 \lstinputlisting[label=src:notDefInterfaceAPI, caption=InterfaceのAPI呼び出し時の引数エラー]{src/NotDefine.pl}
72
951cb9681030 add source code
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 68
diff changeset
497
103
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 100
diff changeset
498 ソースコード\ref{src:errNotDef}の例では、Phils Interfaceの実装時にeating CodeGearの実装を忘れた際のエラーである。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 100
diff changeset
499 CMakeがエラーを検知し、ビルドが停止するために、 GearsOSの拡張構文レベルでのエラー検知が実現できている。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 100
diff changeset
500 \lstinputlisting[label=src:errNotDef, caption=未実装のInterfaceのAPIがあることを知らせるエラー]{src/errorNotDef.sh}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 100
diff changeset
501
104
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 103
diff changeset
502
111
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 109
diff changeset
503 \section{par goto のInterface経由の呼び出しの対応} \label{sec:interParGoto}
100
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 94
diff changeset
504 従来のpar gotoではInterface経由の呼び出しは想定していなかった。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 94
diff changeset
505 par gotoで継続したいCodeGearはInterfaceのAPIとしてではなく、 Interfaceを入力として受け取るCodeGearとして実装する必要があった。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 94
diff changeset
506 しかし食事する哲学者の問題(Dining Philosophers Problem、 DPP)の検証などでは、特定のInterfaceが並列で動いている必要がある。
107
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 106
diff changeset
507 DPPの例題の場合は、哲学者(Philosopher)のInterfaceは並列で処理される必要がある。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 106
diff changeset
508 GearsOSで実装したDPPの例題で、par gotoを実行している箇所をソースコード\ref{src:pargotoPhil}に示す。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 106
diff changeset
509
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 106
diff changeset
510 \lstinputlisting[label=src:pargotoPhil, caption=5つのPhilosopherInterfaceからのpar goto]{src/ParGoto.cbc}
100
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 94
diff changeset
511
107
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 106
diff changeset
512 この記述はPerlトランスパイラによって、ソースコード\ref{src:pargotoPhil2}のメタ記述に変換される。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 106
diff changeset
513 \lstinputlisting[label=src:pargotoPhil2, caption=5つのPhilosopherInterfaceからのpar gotoのPerl変換後]{src/ParGoto2.cbc}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 106
diff changeset
514 PhilsInterfaceは大本のcontextで作製しているため、par gotoで作製したContextにInterfaceの情報が保存されていなかった。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 106
diff changeset
515 処理を実行するとInterfaceの値をStubCodeGearで取り出す際に、初期化をしていない値をとってしまい、 セグメンテーション違反が発生する。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 106
diff changeset
516 この問題は、Gearefマクロを利用して作製したpar goto用のContextの引数用の保存場所に、それぞれ実装のポインタを書き込むことで解決する。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 106
diff changeset
517
151
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
518 ソースコード\ref{src:pargotoPhil3}では、par goto作製したContextであるcontext{\textgreater}taskに、 Gearefマクロを用いて引数としてPhilsのインスタンスを代入している(ソースコード3、 15行目)。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
519 またthinkingの引数はCodeGearが必要であったので、これもnextに設定している(ソースコード4、 16行目)。
107
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 106
diff changeset
520 この処理は、generate\_stub.plで、 par goto時にInterface呼び出しをしている際のパターンを新たに実装し、Interfaceのパースの結果から得られた引数に書き込む様なルーチンで実現している。
142
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 111
diff changeset
521 \lstinputlisting[label=src:pargotoPhil3, caption=改善されたInterface経由でのpar goto]{src/ParGoto3.cbc}