ANSI C で Objective-C の @encode() コンパイラ ディレクティブに似たものを実装するにはどうすればよいでしょうか?

StackOverflow https://stackoverflow.com/questions/2255637

質問

@encode ディレクティブは、渡されたデータ型のさまざまな要素のコード化された型記述子である const char * を返します。例は次のとおりです。

struct test
{ int ti ;
  char tc ;
} ;

printf( "%s", @encode(struct test) ) ;
// returns "{test=ic}"

sizeof() を使用してプリミティブ型を決定することができました。また、それが完全なオブジェクトであれば、クラス メソッドを使用してイントロスペクションを行うことができました。

しかし、不透明な構造体の各要素はどのように決定されるのでしょうか?

役に立ちましたか?

解決

@Lotharsの答えは「冷笑的」かもしれませんが、残念ながらかなり的を得ています。次のようなものを実装するには @encode(), 、型情報を抽出するには本格的なパーサーが必要です。まあ、少なくとも「些細なこと」以外のことに関しては @encode() ステートメント (すなわち、 @encode(char *))。最新のコンパイラには通常、2 つまたは 3 つの主要コンポーネントがあります。

  • フロントエンド。
  • 中間端 (一部のコンパイラの場合)。
  • バックエンド。

フロントエンドはすべてのソース コードを解析する必要があり、基本的にソース コード テキストを内部の「マシンで使用可能な」形式に変換します。

バックエンドは、内部の「マシンで使用可能な」形式を実行可能コードに変換します。

「中間エンド」を持つコンパイラーは、通常、次のような必要があるためにそれを行います。それらは、おそらく完全に異なる言語で構成される複数の「フロントエンド」をサポートします。もう 1 つの理由は、最適化を簡素化するためです。すべての最適化パスは同じ中間表現に対して機能します。の gcc コンパイラ スイートは、「3 ステージ」コンパイラの例です。 llvm 「中間およびバックエンド」段階のコンパイラと考えることができます。「低レベル仮想マシン」は中間表現であり、すべての最適化はこの形式で行われます。 llvm また、最後の 1 秒までこの中間表現に保持することもできます。これにより、「リンク時間の最適化」が可能になります。の clang コンパイラは実際には、(事実上) 出力を行う「フロントエンド」です。 llvm 中間表現。

それで、追加したい場合は、 @encode() 「既存の」コンパイラに機能を追加するには、おそらく「ソース間」の「コンパイラ/プリプロセッサ」として実行する必要があります。これが、元の Objective-C および C++ コンパイラの作成方法でした。入力ソース テキストを解析して、それを「プレーン C」に変換し、標準 C コンパイラに送り込みました。これを行うにはいくつかの方法があります。

自分で巻いてください

  • 使用 yacc そして lex ANSI-C パーサーを組み立てます。文法が必要になります- ANSI C 文法 (Yacc) 良いスタートです。実は、はっきり言っておきますと、 yacc, 、本当に言いたいのは バイソン そして flex. 。また、大まかに言うと、その他のさまざまな yacc そして lex C ベースのツールと同様: レモン, dパーサー, 、など...
  • 使用 perlヤップ または EYapp, 、これは擬似的なものです。yacc クローンの perl. 。おそらく、C ベースと比較して、アイデアのプロトタイプを迅速に作成するのに適しています。 yacc そして lex- その perl 結局:正規表現、連想配列、メモリ管理なしなど。
  • パーサーを構築する アントラー. 。私はこのツールチェーンを使用した経験がありませんが、これも Java 開発者向けに作られた (ように見える) 別の「コンパイラ コンパイラ」ツールです。無料で利用できる C および Objective-C 文法があるようです。

別のツールをハックする

注記: 私はこれらのツールを使用して追加などのことを行った個人的な経験はありません。 @encode(), 、しかし、それらは大きな助けになると思います。

  • CIL - このツールの個人的な使用経験はありませんが、C ソース コードを解析し、それを使って「何かを行う」ために設計されています。ドキュメントから収集した情報によると、このツールを使用すると、必要な型情報を抽出できるはずです。
  • まばらな - 一見の価値はありますが、わかりません。
  • カラン - この目的で使用したことはありませんが、伝えられるところによると、目的の 1 つは、この種の目的で「簡単にハッキングできる」ようにすることでした。特に (繰り返しになりますが、個人的な経験はありませんが) すべての解析の「重労働」を行うことで、「興味深い」部分に集中できます。この場合、コンテキストと構文に依存する型情報を抽出し、それを変換することになります。プレーンな C 文字列に変換します。
  • gcc プラグイン - プラグインは gcc 4.5 (コンパイラの現在のアルファ/ベータ バージョン) の機能であり、コンパイラに簡単に接続して必要な型情報を抽出できるようにする「可能性があります」。プラグインのアーキテクチャがこの種のことを可能にするかどうかはわかりません。

その他

  • コクシネレ - 「後で見る」ために最近これをブックマークしました。これは、あなたが望むことを実現できる「かもしれない」し、それほど努力せずにそれを実現できる「かもしれない」。
  • メタC - 最近これもブックマークしました。これがどれほど役立つかわかりません。
  • mygcc - あなたが望むことを「できるかもしれません」。興味深いアイデアですが、必要なものに直接適用できるわけではありません。Web ページから:「Mygcc を使用すると、プログラマは構文、制御フロー、データ フロー情報を考慮した独自のチェックを追加できます。」

リンク。

編集 #1、ボーナスリンク。

@Lothar はコメントで良い点を指摘しています。本当は入れるつもりだったんだけど lcc, しかし途中で道に迷ってしまったようです。

  • LCC - lcc Cコンパイラ。これは、少なくともソース コード サイズの点で特に小さい C コンパイラです。また 本を持っています, 、強くお勧めします。
  • tcc - tcc Cコンパイラ。それほど教育的ではありません lcc, 、しかし間違いなくまだ見る価値があります。
  • ポク - poc Objective-C コンパイラ。これは「ソースからソースへ」の Objective-C コンパイラです。Objective-C ソース コードを解析し、C ソース コードを出力し、それを次の関数に渡します。 gcc (まあ、普通は gcc)。Objective-C では利用できない多数の Objective-C 拡張機能/機能が備わっています。 gcc. 。間違いなく一見の価値があります。

他のヒント

あなたは最初のANSI Cコンパイラを実装することで、これを実装し、それにいくつかの実装固有のプラグマや機能を追加することになります。

はい、私は、これは皮肉な答えは知っていると私はdownvotesを受け入れます。

これを行う方法の1つは、リテラル対応する文字列で...型定義のためのソースコードを読み取り、また@encodeを置き換えプリプロセッサを書くことになります。

あなたのプログラムが-gでコンパイルされている場合、

別のアプローチは、実行時にプログラムのデバッグ情報から型定義を読み込む関数を記述、またはあなたのためにそれを読むためにgdbまたは別のプログラムを使用し、それを再フォーマットすることです望んだ通りに。 gdbptypeコマンドは、特定のタイプの定義を印刷するために使用される(またはそれが不十分な場合にも、あなたはおそらくしたいことよりも、はるかに多くの情報を印刷することを確認されmaint print type、そこにある)ことができます。

あなたはプラグインする(例えばGCC 4.5)をサポートするコンパイラを使用している場合は、

、それがかもしれませんまた、このためのコンパイラプラグインを書くことが可能であること。あなたのプラグインは、コンパイラが既に解析された型情報を利用することができます。明らかに、このアプローチは非常にコンパイラ固有のだろう。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top