2012-04-04 5 views
10

"assert" OCaml 3.12.1コンストラクト用に生成されたラムダコードを改善したいと思います。ラムダコードの改善OCamlがアサーション用に生成する

let f x = 
    assert (x = 4); 
    assert (2 + x = 6); 
    assert (x - x = 0); 
    exit x 

ファイルlongfilename.mlは、上記Iはラムダコード生成を向上させることを希望れる大OCamlのモジュールの代表的なものである:ここでは一例です。それはにコンパイルします:

$ ocamlopt -S longfilename.ml 
$ cat longfilename.s 
... 
    .data 
    .quad 3072 
_camlLongfilename__2: 
    .quad L100007 
    .quad 9 
    .quad 9 
    .quad 2300 
L100007: .L100007: 
    .ascii "longfilename.ml" 
    .byte 0 
    .data 
    .quad 3072 
_camlLongfilename__3: 
    .quad L100006 
    .quad 7 
    .quad 9 
    .quad 2300 
L100006: .L100006: 
    .ascii "longfilename.ml" 
    .byte 0 
    .data 
    .quad 3072 
_camlLongfilename__4: 
    .quad L100005 
    .quad 5 
    .quad 9 
    .quad 2300 
L100005: .L100005: 
    .ascii "longfilename.ml" 
    .byte 0 
... 

上記はひどく冗長です。各アサーションが発生する可能性のあるソースファイルの名前は複製されます。犯人はbytecomp/translcore.mlように表示されます。

let assert_failed loc = 
    (* [Location.get_pos_info] is too expensive *) 
    let fname = match loc.Location.loc_start.Lexing.pos_fname with 
       | "" -> !Location.input_name 
       | x -> x 
    in 
    let pos = loc.Location.loc_start in 
    let line = pos.Lexing.pos_lnum in 
    let char = pos.Lexing.pos_cnum - pos.Lexing.pos_bol in 
    Lprim(Praise, [Lprim(Pmakeblock(0, Immutable), 
      [transl_path Predef.path_assert_failure; 
      Lconst(Const_block(0, 
       [Const_base(Const_string fname); 
       Const_base(Const_int line); 
       Const_base(Const_int char)]))])]) 
;; 

それの顔には、 Const_base(Const_string fname)に名前を与えるには十分だろう、と 、コンパイルして、それを保存して再利用するように、それが見えますタイムハッシュテーブル。モジュール内最適化では、 (変更単位は、各コンパイル単位でハッシュテーブルがリセットされている限り、 )の管理が可能です。

私はここで少し戸惑っていますが、特に「編集時にはそれぞれのリセットを ユニット」としています。何かヒント?

答えて

8

いくつかの定数を共有するためのOCamlコンパイラのメカニズムが既にあります。asmcomp/compilenv.mlとその使用、特にstructured_constantsの値の使用をasmcomp/cmmgen.mlに示します。私はこのコードに慣れていないので、あなたの特定のユースケースが共有されていない理由はわかりませんが、ラムダコードConst_base (Const_string foo)Const_immstring fooの違いがあるようです。後者は共有され、前者はそうではない可能性があります。

immstringの目的とするセマンティクスがわかりません。メソッドラベル(bytecomp/translclass.ml)をコンパイルするためにコンパイラ内部で使用されているようですが、入力言語には影響されません。

(私は、文字列が変更可能であると思われるので、ユーザーが見える文字列を共有してプログラムの動作を変更することができます)。ユーザが見ることができる文字列はおそらくは互換性のために拒否されるでしょう。

これらの即時文字列が一定の放射コード(asmcomp/cmmgen.ml:emit_constant)によって処理される方法を見ると、それらは通常の文字列のように表されます。コンパイラにimmstringを使用してassert_failedをパッチしても問題はありません。

[OP BY EDIT]

Const_immstring fnameConst_base (Const_string fname)の変更は、わずかに互換性がないが、FRAMA-Cと新しいFRAMA-Cは、その回帰テストを通過しコンパイルするために、OCamlは自身をコンパイルすることを可能にします。元の例では、正確に望ましい結果だった、次のような効果があります

$ cat longfilename.s 
... 
    .data 
    .quad 3072 
_camlLongfilename__2: 
    .quad L100005 
    .quad 9 
    .quad 9 
    .data 
    .quad 3072 
_camlLongfilename__3: 
    .quad L100005 
    .quad 7 
    .quad 9 
    .data 
    .quad 3072 
_camlLongfilename__4: 
    .quad L100005 
    .quad 5 
    .quad 9 
    .quad 2300 
L100005: .L100005: 
    .ascii "longfilename.ml" 
    .byte 0 
+0

私はそれはあなたが単純な答えを受け入れることができたときにコメントを投稿するSOエチケットではないのですけど、私はであなたを祝福したかったですあなたが提供したソリューションよくやった。 –

+0

まあ、ありがとうございます:)これは、[bugtracker](http://caml.inria.fr/mantis/)に変更提案を提出すると、それほど満足のいくものにはならないかもしれません。実際にこのことを知っている人は、悪い考えがあった。 – gasche

+0

私はむしろ少し注意を払うつもりですが、私は解決策を持たない醜さのために問題トラッカーで召喚することができますが、5573で自由に意見を出してください。私がその問題の解決策を見つけたら、 1つは、レビューに値するパッチです。 –