right_fork->checkAndSet
はInterfaceのAPI呼び出し__code pickup_rfork(struct PhilsImpl* phils, __code next(...)) {
struct AtomicT_int* right_fork = phils->Rightfork;
goto right_fork->checkAndSet(-1, phils->self, pickup_lfork, pickup_rfork);
}
ノーマルレベルのCodeGearの継続は、contextとCodeGearの番号のみ指定する
CodeGearの継続は直接行かず、MetaCodeGearを経由して継続する
goto meta
に変更されている
next
に代入されている番号で決まるdata
は引数でもらったアドレスに書き込まれる
__code popSingleLinkedStack(struct Context *context,struct SingleLinkedStack* stack,
enum Code next,union Data **O_data) {
Data* data __attribute__((unused)) = *O_data;
if (stack->top) {
data = stack->top->data;
stack->top = stack->top->next;
} else {
data = NULL;
}
*O_data = data;
goto meta(context, next);
}
goto right_fork->checkAndSet()
なので、Interfaceを使った継続
right_fork->checkAndSet
には数値が入ってる__code pickup_rforkPhilsImpl(struct Context *context,struct PhilsImpl* phils, enum Code next) {
struct AtomicT_int* right_fork = phils->Rightfork;
Gearef(context, AtomicT_int)->atomicT_int = (union Data*) right_fork;
Gearef(context, AtomicT_int)->oldData = -1;
Gearef(context, AtomicT_int)->newData = phils->self;
Gearef(context, AtomicT_int)->next = C_pickup_lforkPhilsImpl;
(cGearefontext, AtomicT_int)->fail = C_pickup_rforkPhilsImpl;
goto meta(context, right_fork->checkAndSet);
}
__code pickup_rfork(struct PhilsImpl* phils, __code next(...)) {
struct AtomicT_int* right_fork = phils->Rightfork;
goto right_fork->checkAndSet(-1, phils->self, pickup_lfork, pickup_rfork);
}
__code pickup_rforkPhilsImpl(struct Context *context,struct PhilsImpl* phils, enum Code next) {
struct AtomicT_int* right_fork = phils->Rightfork;
Gearef(context, AtomicT_int)->atomicT_int = (union Data*) right_fork;
Gearef(context, AtomicT_int)->oldData = -1;
Gearef(context, AtomicT_int)->newData = phils->self;
Gearef(context, AtomicT_int)->next = C_pickup_lforkPhilsImpl;
(cGearefontext, AtomicT_int)->fail = C_pickup_rforkPhilsImpl;
goto meta(context, right_fork->checkAndSet);
}
typedef struct Stack<>{
__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;
goto interface->method
で呼び出せる__code pickup_rforkPhilsImpl_stub(struct Context* context) {
PhilsImpl* phils = (PhilsImpl*)GearImpl(context, Phils, phils);
enum Code next = Gearef(context, Phils)->next;
goto pickup_rforkPhilsImpl(context, phils, next);
}
#include "../../../context.h"
#interface "Stack.h"
...
__code push(struct SingleLinkedStack* stack, union Data* data, __code next(...)) {
Element* element = new Element();
element->next = stack->top;
element->data = data;
stack->top = element;
goto next(...);
}
goto interfaceName->method()
のようにAPIを呼び出す
goto meta()
に書き直すgoto meta
はcontextから引数を取り出すMetaCodeGearに継続させるものtypedef struct Stack<Type, Impl>{
union Data* stack;
union Data* data;
union Data* 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;
Impl
の後ろに書く実装名.h
の命名規則 (PhilsImp.h
)typedef struct PhilsImpl <> impl Phils {
int self;
struct AtomicT_int* Leftfork;
struct AtomicT_int* Rightfork;
__code next(...);
} PhilsImpl;
__code pickup_lforkPhilsImpl(struct PhilsImpl* phils, __code next(...)) {
struct AtomicT_int* left_fork = phils->Leftfork;
goto left_fork->checkAndSet(-1, phils->self, pickup_rforkPhilsImpl, eatingPhilsImpl);
}
__code pickup_lfork(struct PhilsImpl* phils, __code next(...)) {
struct AtomicT_int* left_fork = phils->Leftfork;
goto left_fork->checkAndSet(-1, phils->self, pickup_rfork, eating);
}
__code pickup_lfork(struct PhilsImpl* phils, __code next(...)) {
struct AtomicT_int* left_fork = phils->Leftfork;
goto left_fork->checkAndSet(-1, phils->self, pickup_rfork, eating);
}
__code pickup_lforkPhilsImpl(struct Context *context,struct PhilsImpl* phils, enum Code next) {
struct AtomicT_int* left_fork = phils->Leftfork;
Gearef(context, AtomicT_int)->atomicT_int = (union Data*) left_fork;
Gearef(context, AtomicT_int)->oldData = -1;
Gearef(context, AtomicT_int)->newData = phils->self;
Gearef(context, AtomicT_int)->next = C_pickup_rforkPhilsImpl;
Gearef(context, AtomicT_int)->fail = C_eatingPhilsImpl;
goto meta(context, left_fork->checkAndSet);
}
項目 | 従来 | 今回の修論 |
---|---|---|
実装の型ファイル | 無し | 新たに導入 |
union Dataの定義 | 手書き | 自動生成 |
実装のCodeGearの型名 | 手書き | 自動生成 |
実装のCbCファイル | 手書き | 雛形を自動生成 |
別のInterfaceの出力を取得するStub | 手書き | 自動生成 |
Interfaceの未実装の場合の警告 | 無し | 新たに導入 |
Interfaceのparser | スクリプトに埋め込み | モジュール化 |
MetaCodeGearの差し替え処理 | 手書き | meta.pmによって自動化 |
$perl too/impl2cbc.pl SingleLinkedStack.h
[ 33%] Generating c/examples/DPP2/PhilsImpl.c
[ERROR] Not define eating at examples/DPP2/PhilsImpl.cbc
make[3]: *** [CMakeFiles/DPP2.dir/build.make:101: c/examples/DPP2/PhilsImpl.c] Error 25
make[2]: *** [CMakeFiles/Makefile2:442: CMakeFiles/DPP2.dir/all] Error 2
make[1]: *** [CMakeFiles/Makefile2:450: CMakeFiles/DPP2.dir/rule] Error 2
make: *** [Makefile:293: DPP2] Error 2
union Data {
struct Stack {
...
} Stack;
struct SingleLinkedStack {
...
} SingleLinkedStack;
}
data
とdata1
を受け取ろうとする例
__code pop2Test(struct StackTestImpl3* stackTest, struct Stack* stack, __code next(...)) {
goto stack->pop2(pop2Test1);
}
__code pop2Test1(struct StackTestImpl3* stackTest, union Data* data, union Data* data1, struct Stack* stack, __code next(...)) {
String* str = (String*)data;
String* str2 = (String*)data1;
printf("%d\n", str->size);
printf("%d\n", str2->size);
goto 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);
}
goto interface->method()
している箇所を読み取る
interface
がどのInterfaceなのかをPerlトランスパイラで特定させた__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);
}