Emit valid Java for MLexn and MLaxiom (#6)#13
Open
cedretaber wants to merge 2 commits into
Open
Conversation
MLexn and MLaxiom were printed OCaml-style ((error "...")), which is not valid Java. Both mark places execution must never reach, so route them to the existing generic error() helper in class Main, with a proper Java string literal escaper (Pp.qs escapes for OCaml, not Java). Constructs the main extraction pipeline never produces, or that we refuse to extract for now, become explicit extraction-time errors instead of invalid Java output: deep Pcons patterns (previously bound fields positionally while silently ignoring the sub-patterns) and the four primitive constructs MLuint/MLfloat/MLstring/MLparray (previously emitted Haskell's Prelude.error). MLdummy is intentionally left as-is: it is a benign placeholder produced by Prop erasure that is passed around and applied at runtime, so unlike MLexn/MLaxiom it must not become a throwing expression. Making it valid Java needs a self-returning applicable value plus type-strategy decisions, and is deferred to a dedicated PR. New scripted test cases: absurd_match (empty-inductive match reaches the explicit "absurd case" error at runtime) and axiom (an unrealized axiom fails class initialization with the AXIOM TO BE REALIZED message). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
cedretaber
commented
Jul 15, 2026
| Extraction Language Java. | ||
| Set Extraction Output Directory "misc/java-extraction/_generated/absurd_match". | ||
|
|
||
| Inductive empty : Set := . |
cedretaber
commented
Jul 15, 2026
| Definition from_shape (s : shape) : result := | ||
| match s with | ||
| | Leaf => Ok | ||
| | Wrap e => match e with end |
Author
There was a problem hiding this comment.
match は全てのコンストラクタを網羅していないといけないけど、 empty 型はコンストラクタが0個なので、これで有効な match 式になる。
そして爆発律によってあらゆる型になれる( ex falso quodlibet )。
cedretaber
commented
Jul 15, 2026
| is not a valid lambda parameter name on every supported JDK. *) | ||
| Inductive shape := | ||
| | Leaf : shape | ||
| | Wrap : empty -> shape. |
Author
There was a problem hiding this comment.
empty 型にはコンストラクタが無いから、 Rocq の世界では、そもそも Wrap は作れないはず。
cedretaber
commented
Jul 15, 2026
|
|
||
| // A [match] on an empty inductive type has no branches; reaching it must | ||
| // raise the explicit absurd-case error, not an accidental exception. | ||
| Main.shape absurd = new Main.Wrap(new Main.empty() {}); |
Author
There was a problem hiding this comment.
Rocq の世界では存在しないものを、テストのために、 Java の世界で無理矢理作り出す。
cedretaber
commented
Jul 15, 2026
Comment on lines
+147
to
+149
| str "__" (* TODO: define a benign applicable [__] value (separate PR); | ||
| an [MLdummy] is passed around and applied at runtime, so | ||
| it must NOT become a throwing expression. *) |
cedretaber
commented
Jul 15, 2026
Comment on lines
141
to
+145
| | MLexn s -> | ||
| (* An [MLexn] may be applied, but I don't really care. *) | ||
| paren (str "error " ++ qs s) | ||
| (* Applied arguments are dropped: [error] throws before any | ||
| application could happen, and the surrounding context supplies the | ||
| expected result type for the generic return. *) | ||
| str "error" ++ paren (pp_java_string s) |
Author
There was a problem hiding this comment.
コード上は出現するが到達不可能。
(テストを見るとどういう場合に出てくるか分かりやすいかも。)
cedretaber
commented
Jul 15, 2026
Comment on lines
+106
to
+107
| let pp_gen_pat table = function | ||
| | Pusual r -> pp_global_name table Cons r |
Author
There was a problem hiding this comment.
Pusual 以外出てこないはずなのでかなり簡素化できている。
hiroshi-cl
reviewed
Jul 15, 2026
| let buf = Buffer.create (String.length s + 2) in | ||
| Buffer.add_char buf '"'; | ||
| String.iter (fun c -> match c with | ||
| | '"' -> Buffer.add_string buf "\\\"" |
There was a problem hiding this comment.
Buffer.add_charありそうだからそれを使ったほうが素直そう
Author
There was a problem hiding this comment.
確かに、下手にエスケープして見辛くなるよりそちらの方がいいかも?
hiroshi-cl
reviewed
Jul 15, 2026
| | c when Char.code c < 0x20 -> | ||
| Buffer.add_string buf (Printf.sprintf "\\u%04x" (Char.code c)) | ||
| | c -> Buffer.add_char buf c) s; | ||
| Buffer.add_char buf '"'; |
Review feedback on #13: the double-escaped OCaml literals ("\\\"", "\\n", ...) needed mental unescaping to see the Java escape sequence they emit. With {|...|} quoted strings the source shows the emitted sequence verbatim. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
概要
issue #6(および 優先度再評価レポート の No.4 前半 + No.9 前半 + No.12)への対応です。
MLexn/MLaxiomは現在 OCaml バックエンドのコピーのまま(error "absurd case")という Java として不正な出力を生成していました。両者は「実行が到達してはいけない場所」を表すので、#11 で導入したclass Mainの汎用ヘルパーerror()(この合流を見越して命名)への合流が正しい意味論です。変更内容
MLexn→error("absurd case")などの有効な Java 式(適用引数は従来どおり捨てる:error()は適用前に throw するので健全。.applyを付けると receiver 位置は poly context でないため型推論が壊れる)MLaxiom→error("AXIOM TO BE REALIZED (axiom.mystery)")pp_java_string新設: Java 文字列リテラル用エスケープ(Pp.qsは OCaml 用エスケープなので不可)Pcons(深いパターン) →user_errによる抽出時の明示エラー。従来はサブパターンを無視して位置束縛するため「黙って間違った Java」を生成し得ました。main extraction に構築箇所がない effectively-dead 構文(レポート No.12)なので実装せずエラー化が正解ですMLuint/MLfloat/MLstring/MLparray→user_err(レポート No.9 前半)。従来は Haskell のPrelude.errorをコピーした不正 Java を出力していましたMLdummy を本 PR に含めなかった理由
Issue / レポートは「共通の式位置 fail ヘルパーで
MLexn/MLaxiom/MLdummyの3構文すべてを解決する」という処方ですが、MLdummyにはこの処方が当てはまりません。MLdummyは Prop 消去の跡地に残るプレースホルダで、正常実行中に引き回され・適用までされる無害な値です。他バックエンドの実装がこれを裏付けます:let __ = let rec f _ = Obj.repr f in Obj.repr f(適用すると自分を返す値)(define __ (lambda (_) __))(同上)__ = Prelude.error "..."(エラーだが遅延評価なので触れない限り無害)Java は正格評価かつ static フィールドは即時初期化なので、
MLdummyを throw 式にすると Prop を使うほぼすべてのプログラムがクラスロード時に死にます(現状のコンパイルエラーより発見しにくい壊れ方への悪化)。正しい対応は OCaml/Scheme 型の「適用可能で自分を返す値」を定義することで、型整合(レポート No.5)・キャスト戦略(No.8)・条件付きプリアンブル出力(他バックエンドのusf.mldummy相当)を含む設計タスクになるため、専用の PR に分離しました。本 PR ではstr "__"のまま据え置き、TODO コメントで経緯を明記しています。テスト
新規2ケース(
sh test-suite/misc/java-extraction.shで全6ケース PASS、既存 golden への diff なし):MLexn "absurd case")。driver で実行時に素のRuntimeException("absurd case")(偶発的な例外でない)ことを検証。なお、パラメータを直接 absurd match すると未使用引数がダミー束縛_として抽出され、_をラムダ引数に使えるのは JDK 22+ のため CI で javac が通らない恐れがあります。コンストラクタ2つの型で包んで absurd match を分岐内に置く形にし、.vにコメントで理由を残していますMLaxiom)。static 初期化子が throw するため、driver はExceptionInInitializerErrorを catch して cause がRuntimeException("AXIOM TO BE REALIZED (axiom.mystery)")であることを検証user_err経路(primitives /Pcons)は「抽出が失敗すること」を期待するケースをハーネスがサポートしていないため自動テスト化していません(ハーネス拡張は別タスク)。primitives は手動確認済みです:🤖 Generated with Claude Code