きりかノート 3冊め

おあそびプログラミング

clang という LLVM フロントエンド

objc-lang ML に流れてた etoile の Compiler Fun 経由で LLVM の新しいコンパイラインターフェイス clang ていうものあることを知る。日本語の情報だと、マイコミの「GCCに匹敵するコンパイラ?! LLVM - BSDCan2008」が最近のBSDCan2008での発表を中心に紹介していてよさげ。

個人的に興味あるのは、Objective-C のサポートと IDE との協調のためにいろいろ用意している(これから?)らしいこと。Objective-C はマイナー言語であるために、Apple が提供する Xcode 以外の開発ツールではサポートがビミョウなことが多い。せめて ctags くらいは使えてほしいもの。まだドキュメント読んでいるところだけど、なんとかなりそうな感じ。

また、便利かはわからないけれど、おもしろい機能があったので紹介。clang には rewrite という機能があって、コードを操作することができる。そのサンプルとして、Objective-C のコードを C にするという -rewrite-objc というオプションがある。

たとえば

 #import "ECTAppController.h"
#import "ECTValueTransformers.h"

// 省略

@implementation ECTAppController

+ (void)initialize
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
[self setupDefaults];
[self registerTransformers];
[pool release];
}

- (void)applicationDidFinishLaunching:(id)sender
{
NSNotificationCenter * center;
center = [NSNotificationCenter defaultCenter];
[center addObserver:self selector:@selector(syncDefaults:)
name:NSUserDefaultsDidChangeNotification object:nil];
}

// save defaults in .plist immediately
- (void)syncDefaults:(id)sender
{
[[NSUserDefaults standardUserDefaults] synchronize];
}

@end

 struct objc_selector; struct objc_class;
#ifndef OBJC_SUPER
// 省略
#endif
static __NSConstantStringImpl __NSConstantStringImpl_ECTAppController_m_0 __attribute__ ((section ("__DATA, __cfstring"))) = {__CFConstantStringClassReference,0x000007c8,"CFBundleName",12};
static __NSConstantStringImpl __NSConstantStringImpl_ECTAppController_m_1 __attribute__ ((section ("__DATA, __cfstring"))) = {__CFConstantStringClassReference,0x000007c8,"CFBundleExecutable",18};

#include "ECTAppController.h"
#include "ECTValueTransformers.h"

// 省略

// @implementation ECTAppController


static void _C_ECTAppController_initialize(id self, SEL _cmd) {
NSAutoreleasePool * pool = ((id (*)(id, SEL))(void *)objc_msgSend)((id)((id (*)(id, SEL))(void *)objc_msgSend)(objc_getClass("NSAutoreleasePool"), sel_registerName("alloc")), sel_registerName("init"));
((void (*)(id, SEL))(void *)objc_msgSend)((id)self, sel_registerName("setupDefaults"));
((void (*)(id, SEL))(void *)objc_msgSend)((id)self, sel_registerName("registerTransformers"));
((void (*)(id, SEL))(void *)objc_msgSend)((id)pool, sel_registerName("release"));
}


static void _I_ECTAppController_applicationDidFinishLaunching_(struct ECTAppController * self, SEL _cmd, id sender) {
NSNotificationCenter * center;
center = ((id (*)(id, SEL))(void *)objc_msgSend)(objc_getClass("NSNotificationCenter"), sel_registerName("defaultCenter"));
((void (*)(id, SEL, id, SEL, NSString *, id))(void *)objc_msgSend)((id)center, sel_registerName("addObserver:selector:name:object:"), (id)self, sel_registerName("syncDefaults:"), (NSString *)NSUserDefaultsDidChangeNotification, (id)((void *)0));
}

// save defaults in .plist immediately

static void _I_ECTAppController_syncDefaults_(struct ECTAppController * self, SEL _cmd, id sender) {
((BOOL (*)(id, SEL))(void *)objc_msgSend)((id)((NSUserDefaults *(*)(id, SEL))(void *)objc_msgSend)(objc_getClass("NSUserDefaults"), sel_registerName("standardUserDefaults")), sel_registerName("synchronize"));
}

// @end

// 省略

という、C のコードに変換されて出力される(拡張子はなぜか .cpp)。NSAssert() や NS_DURING などのマクロがあるとうまく動作しないもよう。