Mercurial > hg > Papers > 2021 > anatofuz-master
changeset 102:9f5c21b218af
update
author | anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Sat, 06 Feb 2021 10:34:02 +0900 |
parents | cb7fc7356561 |
children | 63801f42ade3 |
files | paper/chapter/05-perl.tex paper/master_paper.pdf paper/src/generateOtherStub.pl paper/src/replaceStubCode.cbc |
diffstat | 4 files changed, 79 insertions(+), 6 deletions(-) [+] |
line wrap: on
line diff
--- a/paper/chapter/05-perl.tex Sat Feb 06 09:52:09 2021 +0900 +++ b/paper/chapter/05-perl.tex Sat Feb 06 10:34:02 2021 +0900 @@ -154,7 +154,8 @@ 例えばモデル検査をGearsOSで実行する場合、 通常のStub CodeGearのほかに状態の保存などを行う必要がある。 この状態の保存に関する一連の処理は明らかにメタ計算であるので、 ノーマルレベルのCodeGearではない箇所で行いたい。 ノーマルレベル以外のCodeGearで実行する場合は、 通常のコード生成だとStubCodeGearの中で行うことになる。 -StubCodeGearは自動生成されてしまうため、 値の取り出し以外のことを行う場合は自分で実装する必要がある。 +StubCodeGearは自動生成され、 基本はContextからのDataGearの取り出しを行う。 +これ以外のことを行う場合は、 DataGearの取り出しを含めてメタ計算を自分で実装する必要がある。 しかしモデル検査に関する処理は様々なCodeGearの後に行う必要があるため、 すべてのCodeGearのStubを静的に実装するのは煩雑である。 これを避けるには、 Stub以外のMeta Code Gearをユーザーが自由に定義でき、任意にそのMetaCodeGearに継続できる必要がある。 従来のGearsOSでは、継続先のMetaCodeGearは\texttt{\_\_code meta}に決め打ちとなっているために、 自在に変更するAPIが必要となる。 @@ -216,9 +217,6 @@ -\section{コンパイルタイムでのコンストラクタの自動生成} - - \section{別Interfaceからの書き出しを取得する必要があるCodeGear} 従来のMetaCodeGearの生成では、 別のInterfaceからの入力を受け取るCodeGearのStubの生成に問題があった。 @@ -329,7 +327,8 @@ 出力があった場合はgenerate\_stub.plの内部変数に出力する変数名と、 Interfaceの名前の登録を行う。 生成するStubは命名規則は、 Stubの本来のCodeGearの名前の末尾に\texttt{\_}に続けて数値をいれる。 \texttt{\_\_code CodeGearStub}の場合は、 \texttt{\_\_code CodeGearStub\_1}となる。 -この数値は変換した回数となるため、 この回数の計算を行う。 +変換するCodeGearは、別のCodeGearのAPI呼び出しによって別に変換される可能性がある。 +この変換を切り分けたいため、一意のIDとして数値を入れている。 27行目で\texttt{\$generateHaveOutputStub}のlist要素に現在のCodeGearの名前と、 出力に関する情報を代入している。 @@ -344,13 +343,37 @@ if文で条件判定をしているが、前者は出力があるケースかどうかのチェックである。 続く条件式はGearsOSのビルドルールとして静的に書いたstubの場合は変更を加えない為に、 静的に書いているかどうかの確認をしている。 変数\texttt{\$pick\_next}で継続先のCodeGearの名前を作製している。 -CodeGearの名前は一度目の解析で確認した継続先に\texttt{\_}とカウント数をつけている。 +CodeGearの名前は一度目の解析で確認した継続先に\texttt{\_}の後ろにIDをつけたものを結合している。 ここで作製したCodeGearの名前を、3行目でcontextに書き込むCbCコードとして生成している。 実際に生成された例題をソースコード\ref{src:replaceenum}に示す。 \lstinputlisting[label=src:replaceenum, caption=enumの番号が差し替えられたCodeGear]{src/replaceenum.cbc} +\subsection{対応するStub Code Gearの作製} +enumの番号に対応するStub CodeGearを次は作製する必要がある。 +StubCodeGearはすでに作製されているオリジナルのStubCodeGearの中身のうち、 OutputDataGearの取得をしている箇所を、別Interfaceから取得するように変更する必要がある。 +Perlスクリプトの文字列置換を使ってこの方法を実装する。 + +generate\_stub.plは、スクリプトでStubCodeGearの中身を文字列として作製し、CbCファイルに書き出していた。 +まず、 StubCodeGearを複製する必要があるため、 中身の文字列を保存するように修正した。 +CbCファイルのすべての行を読み込み、ファイルの変換が終了したタイミングで、 enumの差し替えが行われていた場合に差し替えようのStubCodeGearの作製を行う。 +実際に行っている箇所を、ソースコード\ref{src:generateOtherStub}に示す。 + +この処理では、新たに作成するべきStubCodeGearの名前を変数\texttt{\$createStubName}に5行目で代入している。 +StubCodeGearの名前は、1度目の読み込み時に作製されたものである。 +変換対象の変数と、取得するべきInterfaceの組は、連想配列\texttt{\$replaceArgs}に設定されている。 +StubCodeGearの中身は\texttt{\$replaceStubContent}に7行目で代入し、これを\texttt{\$replaceArgs}の変数とInterfaceの組の分だけ置換する。 +\lstinputlisting[label=src:generateOtherStub, caption=StubCodeGearの生成箇所]{src/generateOtherStub.pl} + +ソースコード\ref{src:replaceStubCode}で\texttt{pop2Test1StackTestImpl3}の本体と、StubCodeGearを確認する。 +\texttt{pop2...Impl3\_stub}はStackTest Interfaceからすべての値を取得している。 +対して\texttt{pop2...Impl3\_1\_stub}は、 Stack Interfaceの継続で渡される為に、値をStackから取り出す必要がある。 +見るとdata、dta1の値を、 Gearefマクロを通してStack Interfaceから取得するように変更されている。 +どちらのStubも継続先は\texttt{pop2Test1StackTestImpl3}であり、引数で渡す値の型と個数は揃っているために、実装側の変更をする必要がない。 +これによって柔軟なメタ計算の生成が可能となった。 + +\lstinputlisting[label=src:replaceStubCode, caption=生成されたStubCodeGearと、もとのCodeGear]{src/replaceStubCode.cbc} \section{ジェネリクスのサポート}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/paper/src/generateOtherStub.pl Sat Feb 06 10:34:02 2021 +0900 @@ -0,0 +1,21 @@ +#Create a stub when the output is a different interface +for my $modifyEnumCodeCodeGear (keys %{$generateHaveOutputStub->{list}}) { + my $outputStubElem = $generateHaveOutputStub->{list}->{$modifyEnumCodeCodeGear}; + my $targetStubName = $outputStubElem->{createStubName}; + my $createStubName = "$outputStubElem->{createStubName}_$outputStubElem->{counter}"; + my $replaceArgs = $outputStubElem->{args}; + my $replaceStubContents = $dataGearName{$targetStubName}; + + #If the stub was handwritten, skip + if ($stub{"${targetStubName}_stub"}->{static}) { + next; + } + + for my $arg (keys %$replaceArgs) { + my $interface = $replaceArgs->{$arg}; + $replaceStubContents =~ s/,(.*)\)->$arg/, $interface)->$arg/; + } + + generateStub($fd,$createStubName,$replaceStubContents); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/paper/src/replaceStubCode.cbc Sat Feb 06 10:34:02 2021 +0900 @@ -0,0 +1,29 @@ +__code pop2Test1StackTestImpl3(struct Context *context,struct StackTestImpl3* stackTest, union Data* data, union Data* data1, struct Stack* stack, enum Code next) { + String* str = (String*)data; + String* str2 = (String*)data1; + + printf("%d\n", str->size); + printf("%d\n", str2->size); + goto meta(context, next); +} + + +__code pop2Test1StackTestImpl3_stub(struct Context* context) { + StackTestImpl3* stackTest = (StackTestImpl3*)GearImpl(context, StackTest, stackTest); + Data* data = Gearef(context, StackTest)->data; + Data* data1 = Gearef(context, StackTest)->data1; + Stack* stack = Gearef(context, StackTest)->stack; + enum Code next = Gearef(context, StackTest)->next; + goto pop2Test1StackTestImpl3(context, stackTest, data, data1, stack, next); +} + + +__code pop2Test1StackTestImpl3_1_stub(struct Context* context) { + StackTestImpl3* stackTest = (StackTestImpl3*)GearImpl(context, StackTest, stackTest); + Data* data = Gearef(context, Stack)->data; + Data* data1 = Gearef(context, Stack)->data1; + Stack* stack = Gearef(context, StackTest)->stack; + enum Code next = Gearef(context, StackTest)->next; + goto pop2Test1StackTestImpl3(context, stackTest, data, data1, stack, next); +} +