view paper/generate_code.tex @ 17:9295b0c90a84

update
author mir3636
date Wed, 30 Jan 2019 17:06:49 +0900
parents 6c375f3eef72
children 2f235b4308d2
line wrap: on
line source

\chapter{コードの自動生成}

stub Code Gear などの Meta Code Gear は通常ユーザーレベルからは見ることのできない Meta Data Gear である Context を扱うため、ユーザー自身が記述することは望ましくない。
stub Code Gear は Code Gear 毎に記述する必要があるためユーザーの記述量が多くなる。
また、stub Code Gear でユーザーが Context から Data Gear を参照するためのコードが非常に煩雑である。
このため Meta Code Gear は自動生成されるのが望ましい。
そこで Meta Gear を自動生成するためのスクリプトを導入した。
また、このスクリプトによって Context の参照をユーザーレベルから隠すことができ、
ユーザーレベルの Code Gear もシンプルになった。

\section{Meta Code Gear の生成}

stub Code Gear は Code Gear 間の継続に挟まれる 必要な Data Gear を Context から参照し、
継続する Code Gear へと渡すための Meta Code Gear である。
Code Gear 毎に記述する必要があり、継続する Code Gear の引数を見て取り出す Data Gear を選択する。
stub Code Gear はユーザーが任意に記述することも出来るが、Meta を扱うため自動生成を行いたい。
そのため、stub Code Gear を 自動生成する generate stub を Perl スクリプトで作成した。
これにより Code Gear の記述量を約半分にすることができる。


ソースコード \ref{Gears_code} は ユーザーレベルの Code Gear である。
この Code Gear を generate stub によって変換、
stub Code Gear の生成を行なったコードがソースコード \ref{MetaCodeGear} である。

\begin{lstlisting}[frame=lrbt,label=MetaCodeGear,caption={\footnotesize Stack pop の変換}]

__code popSingleLinkedStack_stub(struct Context* context) {
        SingleLinkedStack* stack = (SingleLinkedStack*)GearImpl(context, Stack, stack);
        enum Code next = Gearef(context, Stack)->next;
        Data** O_data = &Gearef(context, Stack)->data;
        goto popSingleLinkedStack(context, stack, next, O_data);
}

__code popSingleLinkedStack(struct Context *context,struct SingleLinkedStack* stack, enum Code next,union Data **O_data) {
        Data* data = *O_data;
    if (stack->top) {
        data = stack->top->data;
        stack->top = stack->top->next;
    } else {
        data = NULL;
    }
        *O_data = data;
    goto meta(context, next);
}

__code meta(struct Context* context, enum Code next) {
    goto (context->code[next])(context);
}

\end{lstlisting}

生成された stub  Code Gear は、
継続先が引数で指定した Input Code Gear、Output Code Gear を Context から参照している。
Gearef は Context から Data Gear を参照するためのマクロである。
Context には Allocation 等で生成した Data Gear へのポインタが格納されている。
Code Gear が Context にアクセスする際、
ポインタを使用してデータを取り出すため煩雑なコードとなる。
そこで Code Gear がデータを参照するための Gearef というマクロを定義した。
Gearef は Context から Interface の引数格納用の Data Gear を取り出す。
Gearef に Context と Data Gear の型を渡すことでデータの参照が行える。

GearImpl マクロは Interface の方に包まれた Data Gear から
実装の Data Gear を取り出すためのマクロである。
実装の Data Gear を取り出す際も、ポインタでの記述が複雑になってしまうため 同様に GearImpl を定義した。
GearImpl は Context と Data Gear の型、実装の Data Gear 名を指定することで参照する。 

また、Code Gear は継続の際 meta へと goto する。
Context はすべての Code Gear のリストを持っており、継続先の Code Gear のアドレスは
enum で対応付けられた Code Gear のアドレスのリストを参照して継続を行う。
この meta もスクリプトにより自動生成される。

stub Code Gear を生成するために generate\_stub は、
ソースコード上の Code Gear を全て取得し、引数からその Code Gear に必要な Data Gear を選択する。

generate\_stub は stub Code Gear を生成する際、Code Gear の引数と Interface を照らし合わせ、
Code Gear が要求する引数の Data Gear を Context から取り出すための Gearef または GearImpl を決定する。

この時既に stub Code Gear が記述されている Code Gear は stub Code Gear が生成されずに無視される。

generate\_stub は Code Gear の変換も行う。
ソースコード \ref{MetaCodeGear} では、popSingleLinkedStack の引数の Output Data Gear を見て、
Output Data Gear の格納を行うコードが挿入されている。
また、継続のコードが goto meta へと変換されている。

\section{Context の生成}
generate\_context は Context を生成する Perl スクリプトである。
Context は生成する際に Code Gear のリストとアドレスの対応、
引数格納用の Data Gear の生成、

\begin{figure}[ht]
 \begin{center}
  \includegraphics[width=120mm]{./fig/generate_context3.pdf}
 \end{center}
 \caption{generate\_context による Context の生成}
 \label{fig:gc}
\end{figure}

Context は Meta Data Gear に相当し、Code Gear や Data Gear を管理している。

generate\_context は context.h を読み宣言されている Data Gear を取得する。
Code Gear の取得は指定された generate\_stub で生成されたコードから \_\_code 型を見て行う。
取得した Code Gear、Data Gear の enum の定義は enumCode.h、enumData.h に生成される。

Code/Data Gear の名前とポインタの対応は generate\_context によって生成される enum Code、enum Data を指定することで接続を行う。
また、generate context は取得した Code/Data Gear から initContext の生成も行う。

Context には Allocation 等で生成した Data Gear へのポインタが格納されている。
Code Gear は Context を通して Data Gear へアクセスする。
Data Gear の Allocation を行うコードは dataGearInit.cに生成される。