fullseye

Fullseye Script — 言語 / ランタイム / ウォッチ IDE 設計仕様(北極星)

目的 = Fullseye Studio の Program を「線形 (op,a,b) パイプラインにスクリプトの皮を被せたもの」から、 HALCON HDevelop 級の本物のプログラミング環境へ進化させる。ユーザー確定の方向性(2026-08-15 対話):

  1. 専用言語(HDevEngine 構文が第一希望、C/C++ 風でも可)で、名前付き変数 + 実 if/for/while(測定値で分岐)+ per-object 反復 + I/O。
  2. Fullseye = 画像処理ライブラリ、言語はそれを呼ぶ層(ロジックを言語に内蔵しない)。
  3. コンパイラ方式が望ましい(インタプリタより)。
  4. 厳密なウォッチ: 変数ウォッチに加え 画像ウォッチ / Region ウォッチ / 画像の特定ドメイン(ROI)ウォッチ
  5. 最終的には Fullseye を DLL 化するのが一番自然。
  6. ロボット制御プログラムまで書けること(知覚→判断→動作のループ)。

外部 AI(Codex read-only)設計コンサルト済(20 項目、本書に反映)。規律=鵜呑み禁止、コードで裏取り


0. 正直な現実(honest reality)と段階戦略

結論(Codex #1): 言語を主、線形パイプラインは「分岐・副作用の無い直列部分集合(LinearSubset)」として残し、進化・高速化・旧 UI に再利用。

★クロスプラットフォーム(Linux)と「独自基盤」の段階(ユーザー指摘 2026-08-15)

ユーザー洞察=「Linux でも使うなら、かなり独自の基盤を作った上に言語を載せる形では?」→ 正しいが、基盤は段階で変わる:

★★中心的な要件定義の分岐: Path A(Python-native IDE)vs Path B(独自言語)(ユーザー指摘 2026-08-15)

ユーザー洞察=「Python 用の開発プラットフォームに画像処理用の便利なウォッチ機能がついている形でも全然あり」。これはむしろ第一目標として賢明。次セッションの要件定義はまずこの A/B を決める。

★インタプリタ vs コンパイラの解決(ユーザー指摘: ウォッチは構造的に難しい / PyBind11 / DLL 現実性)


1. 3 層アーキテクチャ

┌─────────────────────────────────────────────────────────────┐
│ L3  Studio IDE  … エディタ / 実行(debug|run|profile) /       │
│                   ★ウォッチパネル(§4) / ブレークポイント /     │
│                   実行カーソル / Variable & Object 窓          │
├─────────────────────────────────────────────────────────────┤
│ L2  Fullseye Script 言語 … lexer→parser→typed AST→           │
│     bytecode compiler→VM(=コンパイラ)。ソース位置を第一級。   │
│     制御フロー・変数環境・per-object 反復・例外・キャンセル。   │
│     ★ロジックは持たない。L1 を呼ぶだけ(LanguageOperatorSpec)。│
├─────────────────────────────────────────────────────────────┤
│ L1  Fullseye ライブラリ … 実パラメータのビジョン/計測/幾何/     │
│     デバイス関数(read_image/gauss/threshold/connection/        │
│     area_center/…/comm/device/acquire)。numpy/scipy 実装。    │
│     ★将来: ホットパスを C codegen → ネイティブ DLL(C ABI)。  │
│     進化エンジンの正規化ノブ registry とは契約を分離(§3)。    │
└─────────────────────────────────────────────────────────────┘

2. 言語仕様(HDevEngine 風、Codex #2–4)

2b. 増分 1 実装(fscript.py)の確定挙動 —— 仕様と実装を一致させる(2026-09-03 監査で確定)

上の §2 は北極星(設計)。現在の実装が実際にどう振る舞うかは次の表が正本で、tests/test_fscript.py / tests/test_fsruntime.py が 1 項目ずつ固定している。「黙って誤答しない」の規律で、迷う入力は全て FScriptError(行番号つき)。

項目 確定挙動
グレー値の単位 言語のグレー値は 画像の宣言レンジに対する割合(0 = レンジ下端、1 = 上端)。threshold(Image, lo, hi)mean_gray/min_gray/max_gray同じ単位。8-bit 画像の画素 128 は 0.502 と読む。∴ threshold(Image, mean_gray(Image), max_gray(Image)) は 8-bit でも float でも同じ意味(以前は統計だけ生画素値で、8-bit では面積 0 を黙って返した)。
タプル算術 + - * / % と単項 -全て要素ごと(長さ 1↔N ブロードキャスト、N↔N は等長必須、違えばエラー)。[1,2] * 2 = [2,4](Python の繰り返し [1,2,1,2] ではない)。連結は [t1, t2]
文字列の算術 文字列 + 文字列 = 連結のみ。'ab' * 3'a' + 1 はエラー(Python の繰り返し/型混在は言語機能ではない)。
スカラ = 長さ 1 のタプル [1] = 1 は真、if ([0]) は偽、not [0] は真。長さ ≠ 1 のタプルは条件式に置けない(エラー)。比較 < > <= >= でタプルとスカラを混ぜるとエラー、=/# はタプル全体の等価。
添字 t[i] / s[i]i0 以上の整数(2.0 のような整数値の実数は可、1.9・負数・文字列はエラー)。範囲外はエラー(index 3 out of range (length 3))。負の添字は無い。
添字代入 Name[i] := expr を実装(expr はスカラ。タプルは平坦なので入れ子不可)。タプルは値: B := A はコピーで、B[0] := 9A に届かない。images= で渡した Python list も複製され、スクリプトは呼び手のリストを書き換えない。
数値リテラル ASCII 数字のみ: 12 / 1.5 / 1. / .5 / 1e-3 / 2.5E+41.2.3 / 2e / 1e5e3 / (全角)/ ² は構文エラー。1e400 のような無限大に落ちるリテラルもエラー。
文字列リテラル '...'1 行に収まる(行をまたぐと unterminated string)。エスケープは \'\\ だけ。それ以外のバックスラッシュはそのままの文字('<ローカルの作業パス>\images\a.png' はそのまま読める。'<ローカルの作業パス>\dir\'\' がエスケープになり未終端エラー → '<ローカルの作業パス>\dir\\' と書く)。
break / continue ループの外では構文エラー('break' outside loop)。
比較の連鎖 0 <= X <= 10 は禁止(エラー)。括弧で囲んだ比較は明示のオペランドなので (X > 3) = true / (1 < 2) = (2 < 3) は可。
条件ヘッダ if/elseif/while/until の条件は行末まで。if (X = 1) or (Y = 1) は 1 つの条件。(...) で始まるヘッダは and/or でしか続けられず、if (X = 1) -1for I := 0 to 2 X := I(ヘッダ行に文)は unexpected ... after statement
for の境界 start/stop/step は数値(文字列・長さ ≠ 1 のタプルはエラー)。step 0 はエラー。
dilation / erosion / mean_image の半径 0 以上の整数(画素)。0 は恒等(領域をそのまま返す)、負・小数(0.4)はエラー(以前は max(1, int(r)) で全部 1 に化けていた)。
op の引数 数値引数に文字列やタプル(長さ ≠ 1)を渡すと ... must be a number, got string 'x'FScriptError(素の ValueError は出ない)。エラーは必ず呼び出し行を持つ。
read_image のパス base_dir があれば その配下に閉じ込める(相対は base_dir 基準、.. は解決後に判定、絶対パスも配下のみ)。外なら path ... is outside the script's base directorybase_dir 無し(呼び手が明示的に省略)の場合のみそのまま開く。industrial プロファイルの Runtime は read_image を含むレシピをロードで拒否(サイクル内ファイルアクセス禁止 = FSCRIPT_DECISION.md §3.1 R4。フレームは images= で渡す)。
ネストの上限 括弧/単項/ブロックの入れ子と、評価時の式の深さは 200 まで(nesting too deep (limit 200))。1+1+…+1 を 200 項以上連ねた式も同じエラー。Python の RecursionError は外に出ない。check() は決して例外を投げず文字列で返す。
golden の digest(fsruntime) manifest digest は repr() ではなく正準バイト列(型タグ + 長さ + float.hex() / dtype.str + shape + tobytes())。np.printoptions に依存せず、1000 要素超の配列の 1 要素差も検出する。GoldenVector.expect に載せられる型は bool/int/float/str/それらの list・tuple/numpy 配列のみ(他は構築時 TypeError)。旧 digest と互換性は無い(署名済みレシピは sign で再署名)。

3. L1 ライブラリ = 言語演算子仕様(Codex #6–9)


4. ★ウォッチモデル(ユーザー最重要・厳密設計)

ユーザー要件 = 変数ウォッチだけでなく 画像ウォッチ / Region ウォッチ / 画像の特定ドメイン(ROI)ウォッチ。デバッガの中核。


5. 進化の北極星との共存(Codex #16, #17)

6. ロボット制御(Codex #20)


7. サンプル配置(Codex #14–15)

samples/
  scripts/     01_threshold_and_measure.fsh …            # サンプルコード(専用フォルダ)
  images/      parts_01.png defects_scratches.png …       # 合成画像(手続き生成)
  generators/  make_inspection_samples.py                 # 生成器(seed/条件)
  manifests/   samples.json                               # 生成条件・期待結果・ライセンス

8. 段階的ロードマップ(Codex #18 を imgevolve 現実へ調整)

各段階で parser golden tests / 型エラー / 空 object / キャンセル / 同一 seed 画像 / 旧 pipeline parity を回帰化。


9. 現状のプロトタイプ(2026-08-15 実測検証済)

★実測が変えた設計の優先順位

docs/FSCRIPT_MEASUREMENTS.md の結論:

  1. 言語の実行方式(AST インタプリタ)はサイクルタイムに実質影響しない(+0.4〜4.7%)。 → bytecode VM 化の動機は速度ではなくデバッグ体験(step/breakpoint/span/ウォッチ)。正直に区別する。
  2. オブジェクトモデルが 5.8 倍画素カーネルの実装が 23 倍効く。合計 134 倍。 → 優先順位は 型・意味論 → ObjectSet → native カーネル契約 → VM 化
  3. 黙って誤った値を返す欠陥が 5 件(* のコメント誤認 = 修正済、値域の内容依存正規化、Tuple +、 iconic の暗黙真偽化、比較の .any() 潰れ)。すべて 実装言語を変えても残る意味論の問題。 → 「まず型システム、次に VM」。ネイティブ化はその後。