公開 · 技術詳細解説

AS/400(IBM i)モダナイゼーション ― SlimeCL / SlimeRPG でできること・できないこと

正直な、実機 corpus に基づく解説です。以下の数字は実在する公開 IBM i ソース由来で、都合よく選んだ demo ではありません。できない所も公開します ― 透明性こそが moat だからです(競合は multi-target の合格率自体ほとんど公表しません)。

🎛 AI GATE このページの解説を、あなたの解像度で。

手で書き直すと、数値計算や例外の細かな違い(境界条件)で挙動がズレ、その確認(新旧比較テスト)に膨大な人件費がかかります。言語特有のトラップまで忠実に写し、差分テストで「ズレゼロ」を実証、独立した参照実装で裏付け。成果物は人手の UAT でなく機械検証可能な「振る舞い不変の証明書」。誇張せず、対応できない部分は隠しません。

📋 「このレベルで AI に質問」= 選んだ解像度に合った指示つきで、このページの解説をコピーします。お手元の AI(Claude · GPT · Gemini · Grok 等)に貼れば、その目線でさらに深掘りできます。

論旨。 CL は IBM i 現場の「糊」、RPG / COBOL は業務ロジック。これらを可搬な bash単一バイナリ Rust に変換します ― 「移行」ではなく「継続」。本ページは、それが今どこまで動くかを、hang や compile の穴も含めて計測値で示します。

実機ソースで計測(demo ではなく)

1,711
実機 RPG プログラム投入(jariko / OSSILE / noxDB / IBM サンプル)
46
実機 CL プログラム ― 公開「IBM i RPG Free CLP」corpus(.clp / .clle)
0
hang / crash(上記全体。最初に見つけた 10 件の hang は修正済み)

RPG(SlimeRPG → Java/runtime)

段階結果読み方
字句解析(lex)99.4%(1,701 / 1,711)固定形式 RPG/400 含め実機 RPG をほぼ全部読める
emit(出力生成)99.8%crash せず構造化変換
javac compile(標本)約82%正直な穴 ― 周辺 RPG(BIF・cursor 項目)が未完
hang0 / 1,711emitter 無限ループ 10 件を発見・修正(DO-UNTIL / MONITOR / inline データ構造)

CL(SlimeCL → bash / Rust)

段階結果読み方
字句解析(lex)100%(46 / 46)実機 CL を全部読める
emit100%(46 / 46)、hang 0固まらない・落ちない
bash 構文OK100%(46 / 46)CL のコマンド連携的な性質に bash が最も自然
Rust compile100%(46 / 46)この公開 corpus の全プログラムが target に compile

本イテレーション(2026-05-26)、同一 corpus で Rust compile は 69.6% → 100%、bash は 76.1% → 100% に上昇。shim 追加ではなく(未対応コマンドは元々コメントとして compile する)、古い CL の方言 ― 位置パラメータ形式(CHGVAR &X '1'DCL (&X) (*CHAR)・位置形式 IF/THEN)、予約語の変数名(&Type)、部分文字列代入(CHGVAR %SST(&v s l))、記号比較演算子(= > <)、暗黙 DCLF *CHAR フィールド%BIN、特殊値(*YES)、*CHAR*DEC 双方向変換、Rust の所有権(借用 vs move)、そして DDS 前段(DCLF の record フィールド型を .DSPF/.PF 定義から直接読む ― BMS / XMAP map parser と同じ positional 抽出の発想)― への emitter 対応による。各修正は無回帰を確認(29 unit tests + 4/4 bit-exact)。bitexact/measure_compile.sh で再現可能。

実機 IBM i で bit-exact 検証 ✓ 新

原 CL を実機 IBM i(7.5、PUB400.com)でコンパイル・実行し、その出力を SlimeCL が吐いた bash Rust の出力とバイト単位で比較しました。これまで「未公開」としていたマイルストーンです。達成しました。

6 / 6 bit-exact(3者一致)。 下記すべてで 実機 IBM i == SlimeCL bash == SlimeCL Rust がバイト単位で一致。
プログラム実機 IBM iSlimeCL bashSlimeCL Rust
countdown(1..5 の和、*DEC*CHAR)000000000000000000150000000000000000001500000000000000000015PASS
exprdemo(括弧・*AND*CAT)OKOKOKPASS
sstdemo(%SST 部分文字列)HELLOHELLOHELLOPASS
dtaara(データエリア + ALCOBJ/DLCOBJ)HELLOHELLOHELLOPASS
ebcdic('A' *LT 'a' ― EBCDIC 照合)GEGEGEPASS
binconv(%BIN('//') ― big-endian *INT2)…24929…24929…24929PASS

後の2本は compile は通るが実機で裏で揺れる Runtime Gap を封じたもの:*CHAR 比較は EBCDIC 照合(小文字 < 大文字 < 数字 ― ASCII の逆順)を使うので 'A' *LT 'a' は実機で (→ GE)、ASCII 文字列比較の素朴な「真」ではない。%BIN はフィールドのバイトを big-endian 符号付き整数(*INT2/*INT4)として読む(ホストの little-endian ではない)。どちらも IBM i のセマンティクスに束縛し、上記でバイト単位検証済み。

価値があるのは実機が炙り出したもの ― 合成テストでは絶対に出ない fidelity gap を見つけ、修正した点です:

  • 固定長 *CHAR:IBM i の文字フィールドは宣言長まで空白パディングされるため、20 バイトの &MSG *CAT '!'! がフィールド末尾から溢れて消え OK になる。SlimeCL は *CHAR を可変長文字列扱いしていた(OK!)。修正済 ― 両 target が固定長を再現。
  • *DEC*CHAR 変換:パック10進の合計を文字フィールドに代入すると、フィールド全幅へ右詰め・ゼロ詰めされる(00000000000000000015)。SlimeCL は素の 15 を出していた。修正済
  • SNDPGMMSG MSG()*CHAR を要求し、CALL の char↔packed パラメータ型整合は数値を静かに壊し得る。どちらも初回接続で露出し、文書化済。

正直な適用範囲。 これは代表3本であって全 corpus ではありません。要点は手法:各プログラムを実機 IBM i でコンパイル・実行し、出力を両 target と diff する再現可能な harness です。本数の拡大は継続作業。実機・バイト単位の transpiler 検証を公開している競合を我々は知りません。

5250 画面ハーネス ― 実機セッションを丸ごと再現 ✓ 新

バッチ出力の bit-exact に続き、対話画面(5250)も実機で再現できるようにしました。スクリプタブルな 5250 クライアントは既製品が無いため、std のみ・外部ライブラリゼロの Rust(JAVATEL の no-external-lib スタックに整合)でヘッドレス・クライアント s5250 を実装。実機 IBM i(PUB400.com)に対し認証セッションを丸ごと駆動し、各パネルを 24×80 グリッドへ再構成します。

実機で確認した一連の流れ: TELNET ネゴシエーション → サインオン画面の再現 → サインオン(入力欄を SF/FFW から特定) → デバイス Query 応答(RFC 1205 Query Reply) → IBM i メインメニューの再構成 → コマンド行から SIGNOFFクリーンに切断(セッションを放置しない)。
--- 実機 PUB400 から再構成したメインメニュー ---
 MAIN  IBM i Main Menu
          System:  PUB400
 Select one of the following:
      1.User tasks   ...   9.Display a menu
     90.Sign off
 Selection or command
 ===>
 F3=Exit  F4=Prompt  F9=Retrieve  F12=Cancel ...
 (C) COPYRIGHT IBM CORP. 1980, 2021.

プロトコルの実地知見(rigor の裏付け): インバウンドにも 10 バイトの GDS ヘッダが必要 ― 欠落するとホストが先頭バイトをレコード長と誤読して接続を切る。サインオン成功後、メニュー送出の前にホストがデバイス Query を投げるため、Query Reply を返さないと無応答(hang に見える)。サインオン画面の「Server name / Subsystem」等は入力フィールド(SF)ではなく SBA 書きのリテラルで、SF/FFW 解析が入力欄と見出しを切り分ける。QMAXSIGN を尊重 ― 正しい資格情報のみ送出し、形式の検証は資格情報無しの probe で行った。

P1 ― 初の対話画面 bit-exact(L2)。 小さな DCLF プログラム(SNDRCVF で全定数パネルを表示)を s5250 でメニューから CALL し、表示されたパネルを scrape。同じ DDS を SlimeGENBA-LUI が描いたグリッドと、正規化 24×80 テキストで diffPASS(実機の画面 == レンダ、行単位一致)。バッチ出力の 6/6 bit-exact に対応する、画面レベルの bit-exact です。
== P1 L2 screen diff: live DCLF panel (real IBM i) vs DDS render ==
  => PASS  (L2 bit-exact: live panel == DDS render)
 SlimeCL P1 -- DCLF panel
 Rendered from DDS constants.
 Live via s5250 (5250/TELNET).
 Same DDS via SlimeGENBA-LUI.
 Diff = L2 screen bit-exact.
 Press Enter to exit.
P2 ― キーストローク + 複数パネル遷移 3 つの record format(MAIN / PAGE2 / PAGE3)を持つ DCLF プログラムを、s5250 がスクリプトした Enter キーで walk し各パネルを scrape。format ごとにレンダした DDS と L2 比較 → 3/3 パネル一致。さらに F3 ≠ Enter を実証 ― F3 では CL の IF &IN03 RETURN が発火し、PAGE2 ではなくメニューへ早期復帰。キーが別々の意味を正しく運んでいます(空打ちではない)。
== P2 keystroke + multi-panel L2 diff (real IBM i) vs DDS render ==
  panel 0 (MAIN):  => PASS  (L2 bit-exact)
  panel 1 (PAGE2): => PASS  (L2 bit-exact)
  panel 2 (PAGE3): => PASS  (L2 bit-exact)
  == result: 3/3 panels L2 bit-exact ==
P3 ― fixture + 計算されたフィールド値 ここまでの定数パネルに対し、両側が同じ fixture を読む形にしました。実機側は P3DRV が データエリア P3FIX を読んで計算・表示。候補側は SlimeCL が同じ CL を変換し、emit したプログラムが同じ fixture(環境変数で注入)を読んで計算 → フィールド値をダンプ → SlimeGENBA-LUI が DSPF にその値を配置。両者を L2 比較 → 一致。fixture を 42 と 100 で変えても両側が追従(…042/…126、…100/…300)。変換ロジック + DDS レンダ == 実機画面が、計算値込みで成立 ― P1/P2 で保留した部分を埋めました。
== P3 fixture + computed-field L2 diff (fixture P3FIX=42) ==
  => PASS  (L2 bit-exact: live computed panel == DDS render with candidate values)
 SlimeCL P3 -- record count
 Active (RECA):    0000000042   <- fixture 42
 Total  (RECT):    0000000126   <- 42 * 3, computed by the transpiled logic
P4 ― オペレータのフィールド入力 ここまでは出力中心。今度は s5250 が実機の入力欄に打鍵(type:VALUE)し、プログラムがそれを読んで計算(char→dec、×3、dec→char)、結果を表示。候補側は同じ打鍵値を入力 fixture(環境変数で注入)として受け取り、L2 で一致(7→…021、15→…045)。5250 の入力欄は再表示時に内部構造付きで再送され表示桁がずれるという実機特性を発見したので、入力フォーマットと出力専用フォーマット(入力値のエコー + 結果)を分け、整列する出力面で diff しています ― 誤魔化さず正面から。
P4F ― ファイル fixture 物理ファイル(N レコードを投入)を fixture に、実機は RTVMBRD実ファイルの件数を取得・表示。候補側は同じ N レコードの fixture ファイルを数えて表示。両者 L2 一致(5・12 レコードで検証)。正直な適用範囲: これはファイルのメタ(件数)読みです(CL の 1-DCLF 制約下で実機がファイルを読む現実的な形)。レコード単位のフィールド読み(RCVF over DB ファイル)は SlimeTree-VSAM バックエンドで次段
== P4 field-input ==                  == P4F file-fixture ==
  => PASS (typed 7 -> Result …021)      => PASS (5 records -> RTVMBRD …005)

これが解く問題。 オペレータが見る画面こそ、Legacy UI を捨てさせない製品が再現すべきもの。本ハーネスは画面側の半分(実機からの再構成)で、もう半分の SlimeGENBA-LUI(DDS → 2層UI レンダ)と突き合わせ「実機の画面 == 変換後の画面」を画面単位で diff します ― それが上の P1〜P4F です。正直な適用範囲: 画面再構成(P0/P0.5)、L2 bit-exact(P1)、キーストローク+複数パネル(P2)、計算フィールド値(P3)、フィールド入力(P4)、ファイル fixture の件数読み(P4F)まで達成。レコード単位の DB ファイル読みは SlimeTree-VSAM 連携で次段、数値フィールドの DDS 編集コード・属性/色(L3)も次段。DBCS パネルは日本語 CCSID の実機が要る(EBCDIC 照合と同じ blocker)。

Transport の一般化 ― RS-232C のオフコンにも届く ✓ 新

画面の再構成はトランスポート非依存です ― 「端末データストリームを舐めて 24×80 グリッドに直す」だけなので、TCP の外にも伸ばせます。国産オフコン(富士通 ASP、NEC A-VX、日立 …)には、SSH も TCP/IP も無く RS-232C 一本でブロックモード端末をぶら下げているものが現役で残っています。クラウド移行ツールは、工場の片隅でシリアル一本で生きているこうした機械に物理的に到達できません

sserial ― transport を RS-232C に差し替え。 5250-over-TELNET クライアント(上記 s5250)と同じ再構成コアを、生のシリアル回線に載せ替えました。termios(raw 8N1 / baud / アイドルタイムアウト)は 自前の extern "C" 宣言で叩き、libcserialport クレートも使いません(SHA-256 や EBCDIC 表を自前実装する no-external-lib スタックと同じ流儀)。非 tty パスは replay モードで、録ったデータストリームを実機なしで再構成できます。

本物データで transport 非依存を実証。 PUB400 のサインオン画面を TELNET で録った データストリームを、sserial のシリアル/ファイル経路で replay すると、s5250 が TCP で出したのと同一のグリッドに再構成されます ― 同じデータストリーム・別トランスポート・同じ画面。「トランスポートは差し替え可能、画面の意味は一つ」を体現しています。

正直な適用範囲。 実オフコンにはまだ一台も接続していません。 今の dialect は 5250 で、上の実証は TELNET キャプチャの replay までです。各社のブロックモード方言(KEIS/JEF/JIPS のコード系を含む)には RFC が無く、最初の実シリアル回線キャプチャが仕様を決めます。実シリアルでの検証は、DBCS と同じく現物(または回線キャプチャ)を貸してくれる協力先が要る宿題です。骨格(トランスポート + 再構成コア)は出来ており、方言パーサを一つ足すだけで伸ばせる作りにしてあります。

今できること

  • 制御フロー:IF/ELSEDOWHILE/DOUNTIL/DOFORGOTO+ラベル(bash にも安全な Rust にも goto が無いため、プログラムカウンタ状態機械で厳密に再現)。
  • プログラム内サブルーチン(SUBR/CALLSUBR)→ 実関数化。CL の変数はプログラム大域なので忠実にモデル化(Rust=モジュール static + 関数、bash=大域変数上の関数)。
  • :優先順位・括弧を正しく解析。(&A *GT 5) *AND (&B *LT 3)、文字列連結 *CAT、BIF %SST / %SCAN / %LEN / %TRIM / %CHAR / %UPPER / %LOWER
  • 型推論:*DEC → i64/f64、*CHAR → String、*LGL → bool。
  • 古い CL の方言:位置パラメータ形式(CHGVAR &X '1'DCL (&X) (*CHAR))、記号比較演算子(= > < ¬=)、部分文字列代入(CHGVAR %SST(&v s l))、予約語の変数名。
  • OS サービスの runtime shim:データエリア(RTV/CHG/CRT/DLT DTAARA)はプロセス内ストアで実行、オブジェクトロック(ALCOBJ/DLCOBJ)・ファイル上書きは認識済。
  • 単一の静的バイナリ(Rust)― 汎用 x86/Linux で動作、IBM i ランタイム不要、外部ライブラリ不要。

まだできないこと (正直に)

  • 次の課題は compile ではなく挙動検証。 46本すべて compile し、bit-exact は代表6本で検証済(EBCDIC 照合・big-endian %BIN 含む)。OS サービス実行(SBMJOB/RCVMSG は compile するが完全実行は未対応、データエリア・ロックは runtime shim)が正直な残課題。
  • DBCS(日本語2バイト)照合 ― 単バイト EBCDIC 順序は実装・検証済だが、2バイト(IBM 漢字、CCSID 5026/5035)の順序は 日本語 CCSID の IBM i でないと bit-exact 検証できない(検証機は CCSID 273)― 未検証では出さない。
  • 実機 RPG の約18%は compile しない ― BIF 網羅と cursor host 変数の型付け(SQLRPGLE)が未完。
  • 全 corpus の挙動検証 ― 実機 IBM i での bit-exact 検証は代表セットで達成済(6/6、上記参照)。全 corpus への拡大が継続作業。
  • DDS(表示ファイル / 5250):L2 bit-exact(P1)・複数パネル遷移(P2)・計算フィールド値(P3)・フィールド入力(P4)・ファイル fixture の件数読み(P4F)まで達成(上記)。残るはレコード単位の DB ファイル読み(SlimeTree-VSAM 連携)・数値編集コード・属性/色(L3)DB2 for i の埋込 SQL 意味論・QUERY/400 は捕捉済みだが完全実行は未対応。

パイプライン

CL1 lexer  →  CL2 Slot IR + 式パーサ  →  CL6 emitter { bash | Rust }
(COBOL/RPG/PL/I/MUMPS… JAVATEL 変換ファミリ共通の段構成)

例 ― サブルーチンを呼ぶ CL DOFOR ループが idiomatic な Rust に:

i = 1;
while i <= 5 {
    subr_addit();   /* CALLSUBR SUBR(ADDIT) */
    i += 1;
}
fn subr_addit() { unsafe { sum = sum + i; } }   // プログラム大域変数

なぜ「できない所」も公開するか

Micro Focus・Blu Age・AWS MMA 等は target 別の compile 合格率自体ほとんど公表しません。私たちは実機 corpus で lex/emit/compile/hang を数値公開し、穴を名指しし、改善の track record も示します(1 session で hang 10→0)。この透明性こそ差別化です ― 結果を信頼せねばならない金融・公共・SI の評価者にとって、「信じてください 100% です」より「正直で、速く改善している」が効きます。

国産オフコン modernization 共同検証 ― 協力会社募集

富士通 ASP・NEC A‑VX・日立 など 現役の国産オフコンを、止めず・現場の操作を変えずに現代の実行系へ。クラウド移行ツール(AWS MMA・Blu Age 等)は SSH/TCP 前提で、RS‑232C のみの現役機には物理的に届きません。私たちはその現場を対象に、画面・データ・処理を 1 バイト単位で扱う実行系を作っています。

すでに動いている実物:公開 IBM i 実機(PUB400)上で、対話画面の再構成・ファイル全 CRUD・本物のデータ形式(EBCDIC / ゾーン10進 / パック10進 COMP‑3 / 2進 / IEEE 浮動小数 / DECFLOAT decimal64・128)を byte‑exact(メインフレームと 1 バイトも違わず) read/write し、COMMIT/ROLLBACK・OVRDBF・MONMSG・RS‑232C 差替・日本語(DBCS SO/SI)まで検証済み。Rust + WASM・外部ライブラリゼロなので、生成コードも検証ロジックも全部お見せできます(ブラックボックスではありません)。

残るは貴社の実機 1 台。国産オフコン固有の通信フォーマットと日本語コード(KEIS83 / JEF 等)の現物確認だけが最後のピースです。ご協力は立会い・現地でも可 ― 実機への接続、画面/シリアル通信のキャプチャ、または DBCS データのサンプルのいずれかで結構です。

  • 無償(0円):協力会社向けの modernization 共同検証 PoC に費用はいただきません。
  • データ持ち出し不要:現地検証が可能。サンプルも最小限・匿名化で構いません。
  • 現場を変えない:3270 / XMAP / MELT / OLF の端末操作・ブラインドタッチを 100% 維持。必要なら現代 UI を 追加するだけ(「脱却」「移行」ではなく「現場の延命・modernization」)。

富士通 ASP・NEC A‑VX・日立 等の国産オフコンを今も運用・保守されている事業者・SIer 様で、「動いているが人もツールも先細りで将来が不安」「RS‑232C しかなく移行検討がそもそも入口で止まっている」基幹システムをお持ちの方へ。実機が 1 台、開いてくれる協力先が 1 社 ― それで現場は次の 20 年へ進めます。

国産オフコン共同検証を相談する

謝辞

本ページの実機検証 ― bit-exact 6/6、そして 5250 画面ハーネス P0〜P3 ― は、すべて無償で公開されている実機 IBM i PUB400.com(RZKH GmbH 運営)上で行いました。誰もが本物の IBM i に触れて学べる場を無償で提供されていることに、心より感謝します。私たちはその利用規約を尊重し、セッションは短く・クリーンに(必ずサインオフ)、資格情報の試行も最小限に留めています。

SlimeCL 製品ページ early-access PoC を相談 ← リソース一覧