- 入力した.cbcファイル、Interfaceのヘッダファイルを元に.cのファイルを作成する
- 別にcbc->cに変換するわけではなく、マクロや
*_stub
CodeGearを生成する
#
%var
1
2
3
4
5
6
7
8
9
10
11
|
if (/^\s*(.*)\s+(\w+);$/ ) {
my $ttype = $1;
my $tname = $2;
if ($ttype =~ /^(union|struct|const)?\s*(\w+)/) {
if ($1 ne 'const') {
$ttype = $2;
} else {
$ttype = "const $2";
}
}
$var{$name}->{$tname} = $ttype;
|
__code
の引数で使う変数がこの%var
に登録される
- Interfaceのフィードにあるかないかで生成されるマクロが異なる
- ここで
%var
には $name
と$tname(変数名)
, $ttype(型名)
が登録される
$ttype
はstruct|union
は外された状態で登録される
- これらは
typedef
で外された型名でも使えるので、そちらで生成している
- そのため
Gearef
のマクロではstructを外した状態で書かれる
- constの場合は
const char
で1つの型なので、constが来ていたらconstを戻している
- いずれにせよポインタの
*
はここでは落とさなければならない
if ($ttype =~ /^(union|struct|const)?\s*(\w+)/)
の正規表現でポインタを外している
#
TODO
#
OutPutDataGearが2つ存在するケース
Stackのinterfaceで言うところのget2
とpop2
のケース
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
typedef struct Stack<Type, Impl>{
union Data* stack;
union Data* data;
union Data* data1;
/* Type* stack; */
/* Type* data; */
/* Type* data1; */
__code whenEmpty(...);
__code clear(Impl* stack,__code next(...));
__code push(Impl* stack,Type* data, __code next(...));
__code pop(Impl* stack, __code next(Type* data, ...));
__code pop2(Impl* stack, __code next(Type* data, Type* data1, ...));
__code isEmpty(Impl* stack, __code next(...), __code whenEmpty(...));
__code get(Impl* stack, __code next(Type* data, ...));
__code get2(Impl* stack, __code next(Type* data, Type* data1, ...));
__code next(...);
} Stack;
|
pop2
とget2
はそれぞれ__code next
に2つの出力が存在する
- これを取り出して来るのは
pop2
などの呼び出し元が設定したContinuationによって異なる
例えばRedBlackTreeの例題では、このように呼び出している
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
__code insertCase3(struct RedBlackTree* tree) {
struct Stack* nodeStack = tree->nodeStack;
struct Node* uncle;
if (tree->grandparent->left == tree->parent) {
uncle = tree->grandparent->right;
} else {
uncle = tree->grandparent->left;
}
if (uncle && (uncle->color == Red)) {
// do insertcase1 on grandparent, stack must be pop by two
tree->parent->color = Black;
uncle->color = Black;
tree->grandparent->color = Red;
tree->current = tree->grandparent;
goto nodeStack->pop2(insertCase1);
}
goto insertCase4();
}
|
上の例題では goto nodeStack->pop2(insertCase1);
の部分が相当する
- Stackの実装はnodeStack
- pop2に渡している継続は
insertCase1
この場合、insertCase1はstubでStackのInterfaceから値を2つ取り出す必要がある
- 現状のgenerate_stubはこの出力に対応していないので、👇のようなstubを静的に書いている
1
2
3
4
5
6
|
__code insertCase1_stub(struct Context* context) {
goto insertCase1(context,
&Gearef(context, Tree)->tree->Tree.tree->RedBlackTree,
&context->data[D_Stack]->Stack.data->Node,
&context->data[D_Stack]->Stack.data1->Node);
}
|
#
やりたいこと
- 呼び出すAPIの出力に応じて、継続先のstubをいい感じに整形する
- 呼び出した先のInterfaceがなんであるかを判定する必要がありそう