ラベル Ruby の投稿を表示しています。 すべての投稿を表示
ラベル Ruby の投稿を表示しています。 すべての投稿を表示

2012年3月19日月曜日

Adlintを読む その4

その3で読んだsingle_module_phasesの中身に入っていく。

最初に実行されるのはcpp/phrase.rbに書かれているCpp::ParsePhrase。contextハッシュに、処理内容をひたすら積んでいってる。
積まれた処理は、次のCpp::EvalPhaseでシステム固有の.h、プロジェクト固有の.h、そして.cへと順に適用される。

各処理は、それぞれ次の順番で処理される。まずPreprocessedSourceで結果のソースファイルを用意し、Preprocesserがプリプロセス処理を実行していく。処理途中に定義されたマクロは、Cpp::MacroTableに格納されていく。

ざっと読む限り、まっとうにCのプリプロセッサをRubyで実装しているようだ。ここだけ切り出したいって要求もあると思う。レガシーなソースだと、#ifdefの嵐でどこが有効か判らなくなることもあって、マクロ展開をせず#ifdefだけ処理するカスタム版のプリプロセッサが欲しいこともあるからだ。時間があったらそっちもトライしてみたい。

2012年3月16日金曜日

AdLintを読む その3

ちょっと開いたけど、続けてSingleModuleAnalyzer#executeを読んでいく。

executeは他のSingleModuleAnalyzerクラスのメソッド同様、analyzer.rbにある。

まずLanguage#ofを呼んで、言語を設定している。ここで言っているのは日本語とか英語とかのことではなく、CとC++の切り替えだ。Languageクラスはlang.rb内にあり、ofは現状ハードコードでCを指定している。まぁC++のパースとか大変だもんな……
実際に返しているのは以下のようなもの。

続けてProgressMonitorのインスタンスを用意しReport#newにブロックを渡して内部で処理をやっている。PhaseContextのインスタンスを作り、ソースのパスとシンボルテーブルを用意してから、Langから取得したモジュール群を、次のようなコードで順にexecuteしていっている。

なかなか実際の中身に入れんなー。

2012年3月11日日曜日

AdLintを読む その2

次に来るのはsmaメソッド。

入力ファイルごとに出力のためのフォルダをsma_output_dpathメソッドで作り、SingleModuleAnalyzerクラスのインスタンスを生成してrunメソッドを呼んでいる。つまりsmaとはSingle Module Analyzerのアクロニムだったわけだ。

SingleModuleAnalyzerの定義はanalyze.rbにあり、Analyzerから継承されている。SingleModuleAnalyzer自体にはnewとprivateメソッド群はあるが、runはsuperのAnalyzerで定義されている。

Analyzerもおなじくanalyzer.rbにある。runメソッドではまずlogの準備をし、Analyzer.currentにselfをセットしてからexecuteを呼び出している。この辺の作りは、なんかrubyっぽくないなー。

次はSingleModuleAnalyzer#executeを追いかければいいということになる。


2012年3月8日木曜日

AdLintを読む その1

adlint も adlintizeと同様、Rubyのbinにあるのはplace holderで、本体はgemの下にある。

コマンドラインを処理した後、AdLintのモジュール関数群を順に呼んで処理を行なっている。具体的には以下の順。


AdLint.setup
AdLint.sma
AdLint.sma_met_fpath
AdLint.cma
正直、最初のやつ以外は関数名だけでは何をしているやらさっぱり。

2012年3月7日水曜日

AdLintを読む その0

せっかくRuby製だしソースも公開されているし、読んでみようかと。

実行順に従って。まずはadlintizeから

コマンドラインから
where adlintize
とすると、Rubyのbinにパスにadlintizeとadlintize.batがいるのが判るが、これらはplace holderで、以下のようなことをして実体を別の所に置いている。


けっきょくlibの下、インストールされたバージョンのgemのbinフォルダのadlintizeを見ればいいことになる。


丁寧なコマンドライン処理の後、環境毎に用意された元ファイル群をERbに通して、ビルド環境の設定ファイルとして出力して終了。

やっぱりadlint本体からが本番らしい。

2012年3月6日火曜日

AdLint

間隔空きすぎ。いくらなんでもLazyにすぎるだろうと。


というわけで、AdLintを軽く試してみる。
このあたりを外部でやってくれるなら、中途でほっぽってあったアレの続きをやってみるかなぁ……

2011年12月20日火曜日

いまさらRails その0

年初からRailsな仕事になるので、ちと予習。はるか昔、Rails1.0ぐらいのタイミングで調べたことはあるけど、プロセス立てられない環境にデプロイする可能性もあったので、その時は採用出来なかったし。

とりあえずWindows上に環境を構築。DBはsqliteでお茶を濁す。

pik
普段はASRの1.9.3を使っているけど、Redmineも試してみたいので1.8.7上に構築する。
pikで複数環境を切り替えられるように。Ruby+gemが入っていれば簡単。
gem install pik
pik_install [pikを置くパス]
pik install ruby -v 1.8.7-p352
pik use 187
ruby -v


rails
上記のようにRedmineも考えてるので2.3系の最新版である2.3.14を使用。
これもgemがあれば一発。

gem install rails -v 2.3.14 -r

動くことを確認。
rails sample
cd sample
ruby script/server
Windowsのコマンドプロンプトはserverスクリプトが実行ファイルだと認識しないので、rubyから起動してやる必要がある。

これでhttp://localhost:3000をブラウザで開くと、Welcomeページが見えている。

楽になってるなぁ。前調べたときは、ここまで来るだけでも一苦労だったのに。

2011年10月3日月曜日

IO#unpack!

String#unpack!の続き。 普通はStringが処理できれば問題ないんだけど、時にはIO(と言うかファイル)を直接パースしたい時がある。特にファイルだとサイズが巨大で、事前に全部読み込んでおくのが現実的でないこともあるし。
ここで問題になるのが、pack文字列の中には読んでみないとデータ長が確定しない場合があること。なので、事前にpack文字列をパースして、判るならば読み込み長を事前に計算する実装にしてみた。以下ソース。 長さがわからなったら、packして実際のデータ長を求め直してからseekするという富豪設計。ちなみにSTDINとかのtellやseekがエラーになるストリームでは使えないので注意。

本来unpackで消費するバイト数が取得できたり、unpack時に1バイト取ってくる動作をカスタマイズできたりすれば、こんなゴマカシは必要ないわけで。この辺はRubyの入出力周り、とくにIOが安易にunixのファイルに準拠した仕様になっている弊害だと思う。

2011年9月30日金曜日

Rubyと型と割れ窓

Rubyは動的型付けの言語だからエラーが予防しづらいとか、大規模開発に向かない、とかよく言われる。有名なところではこの辺とかだろうか。
確かに自分でも身に覚えのある話で、凡ミスで変数にあらぬ型の値が入って謎のエラー発生とか、実際わりとある。構造体とか作らずArrayやHashに突っ込んどくのが悪いんだけど。
にもかかわらず、だから開発しづらいという印象が、不思議なことに無かったりする。これまでは好みや嗜好、あるいは腕の問題かなぁとか漠然と考えていたのだが、もうちょっと説得力のある理由を思いついた。

先に上げたリンク先でも、こんなことが言われている。
ちょっとした脳内のアイディアをコードに落とすのはRuby(やRails)が最速であると胸を張って言える
でもって「ちょっとした脳内のアイディア」には、ささいな修正とか可読性の向上も含まれる。コストが掛かるんだったらわざわざやらないような小さな改良でも、Rubyだったらやっておこうか、となる。小さくても改良されれば開発効率は上がる。上がった効率で小改良はますます安価になり、さらなる改良が行われる。何のことはない、いわゆる割れ窓理論だ。

動的型付けがエラーを呼び込みやすいのは、おそらく事実だと思う。しかしコード変更が十分に安価でメンテナンスが頻繁に行われるなら、その効果は型付けのマイナスを補うこともあるのかもしれない。

2011年9月14日水曜日

String#unpack!

VC++とWindowsで遊ぼうかと思ったら、VC2010のSP1インストールで盛大にトラブってまだ終わらないので、Rubyの小ネタで場をつなぐ。

Rubyでフォーマットのあるバイナリを読み込む場合、String#unpackを使うのがよくあるパターン。とはいえ使いづらい点もあって

  1. フォーマット文字列が長さ情報を持っているのに、何バイト読んだかの情報が取れない
  2. unpack自体はデータを消費しないので、次のデータを読もうとすると自分で進めないといけない

これで、例えばデータ自体の内容によってフォーマットが切り替わるようなデータを処理しようとすると、フォーマットから長さを計算して固定長切り出してフォーマットに従ってunpackして……という鉄板コードが並ぶことに。

やってられないので、こんなのを考えてみた。



unpackした結果をpackし直して長さを求めるという手抜きかつ富豪な実装だけど、これだけでデータ処理コード自体の見通しはだいぶ良くなったりする。