generate_stub.pl

generate_stub.pl

  • 入力した.cbcファイル、Interfaceのヘッダファイルを元に.cのファイルを作成する
    • 別にcbc->cに変換するわけではなく、マクロや *_stubCodeGearを生成する

# %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がなんであるかを判定する必要がありそう
Licensed under CC BY-NC-SA 4.0
comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy