背景
PR #118 の codex レビューで指摘された、hawk-libs desugar の「ファイルごとに個別 gawk プロセスで desugar する」アーキテクチャに起因する2つの制約。
課題1: 複数ファイルにまたがる型宣言(record/type alias)を共有できない
コメント
型宣言(record / type alias)は dsl/check.awk 内のグローバル配列(V2_RECORD_TYPE / V2_RECORD_FIELDS 等)にそのプロセス内でのみ蓄積されるため、ある include ファイルで宣言した型を entry や他の include から参照すると、desugar 時に checker がその型を認識できずエラーになる。
例:
# types.awk
record User { name: Str, age: Int }
# main.awk
@include "types.awk"
let u: User = { name: "a", age: 1 } # types.awk の User が見えず desugar エラー
課題2: 同一 cwd から複数アプリを desugar すると dist 出力パスが衝突する
コメント
entry の出力先は dist/<basename> のみ(src_root の情報を含まない)。そのため、同じ cwd から sites/a/app.awk と sites/b/app.awk のように異なるアプリを desugar すると、どちらも dist/app.awk を取り合い、片方の出力をもう片方が上書きする。旧 mktemp 方式(プロセスごとに一意な一時ファイル)ではこの衝突はなかった。
対応方針の候補
両課題とも、現行の「ファイルごとに desugar → dist/ へ書き出し → @include を dist 接頭に書き換え」という Task 2 の設計(1 entry = 1 cwd 相対 dist ツリーという前提)を見直す規模の変更が必要。
- 課題1: include closure を1回の compile にまとめる(型宣言を共有できる)か、型宣言だけを事前抽出して各ファイルの desugar に注入する仕組みを新設する。
- 課題2: dist 出力パスに
src_root 由来の一意な名前空間を持たせる(entry の rel path が basename だけでなく、区別可能な prefix を持つようにする)。課題1で「include closure を1つの compile unit にする」方式を採る場合、その unit 単位が自然な名前空間になり、課題2も合わせて解決できる可能性がある。
どちらも brainstorming → spec → plan の通常フローが要る規模。
スコープ
wiki 段2(template ブランチ、ファイルベースルーティング)で app/ 配下に複数ページファイルを置き、共通の型を @include で共有する構成が想定される。また将来的に複数アプリを同一ホスト・同一 cwd から動かす運用(例: monorepo 型の複数サイト運用)もあり得る。段2着手前に対応方針を決めておきたい。
課題3: publish の世代混在窓(PR #118 追記)
コメント
PR #118 で publish は「closure 全体成功後の一括 mv」になったが、mv はファイル単位なので、稼働中の hawk-serve の worker が「子は新世代・親は旧世代」の混在状態を読む数 ms の窓が残る。完全解決には generation ディレクトリ(dist/gen-N/ に全ファイルを置き、dist/current symlink の付け替え一発で切り替える等)のような単一スイッチポイントが必要で、dist レイアウト規約(課題2と同じ領域)の再設計に含めて対応する。
課題1への補足: 関数シグネチャも同様にファイル跨ぎで共有できない(PR #118 追記)
コメント
型宣言(record / type alias)だけでなく、関数シグネチャも同じ制約を受ける。include された DSL ファイルが sibling や entry で宣言された関数を呼ぶと、ファイル単位の checker が unknown function で失敗する(gawk 自体は include 跨ぎの関数分割を許容する)。例: a.awk の function a() -> Int { return b() } が b.awk の b() を参照するケース。課題1の解決方式(include closure の一括 compile または宣言の事前抽出+注入)でシグネチャ収集も同時に扱う。
背景
PR #118 の codex レビューで指摘された、
hawk-libs desugarの「ファイルごとに個別 gawk プロセスで desugar する」アーキテクチャに起因する2つの制約。課題1: 複数ファイルにまたがる型宣言(record/type alias)を共有できない
コメント
型宣言(
record/ type alias)はdsl/check.awk内のグローバル配列(V2_RECORD_TYPE/V2_RECORD_FIELDS等)にそのプロセス内でのみ蓄積されるため、ある include ファイルで宣言した型を entry や他の include から参照すると、desugar 時に checker がその型を認識できずエラーになる。例:
課題2: 同一 cwd から複数アプリを desugar すると dist 出力パスが衝突する
コメント
entry の出力先は
dist/<basename>のみ(src_rootの情報を含まない)。そのため、同じ cwd からsites/a/app.awkとsites/b/app.awkのように異なるアプリを desugar すると、どちらもdist/app.awkを取り合い、片方の出力をもう片方が上書きする。旧 mktemp 方式(プロセスごとに一意な一時ファイル)ではこの衝突はなかった。対応方針の候補
両課題とも、現行の「ファイルごとに desugar →
dist/へ書き出し →@includeを dist 接頭に書き換え」という Task 2 の設計(1 entry = 1 cwd 相対 dist ツリーという前提)を見直す規模の変更が必要。src_root由来の一意な名前空間を持たせる(entry の rel path が basename だけでなく、区別可能な prefix を持つようにする)。課題1で「include closure を1つの compile unit にする」方式を採る場合、その unit 単位が自然な名前空間になり、課題2も合わせて解決できる可能性がある。どちらも brainstorming → spec → plan の通常フローが要る規模。
スコープ
wiki 段2(template ブランチ、ファイルベースルーティング)で
app/配下に複数ページファイルを置き、共通の型を@includeで共有する構成が想定される。また将来的に複数アプリを同一ホスト・同一 cwd から動かす運用(例: monorepo 型の複数サイト運用)もあり得る。段2着手前に対応方針を決めておきたい。課題3: publish の世代混在窓(PR #118 追記)
コメント
PR #118 で publish は「closure 全体成功後の一括 mv」になったが、mv はファイル単位なので、稼働中の
hawk-serveの worker が「子は新世代・親は旧世代」の混在状態を読む数 ms の窓が残る。完全解決には generation ディレクトリ(dist/gen-N/に全ファイルを置き、dist/currentsymlink の付け替え一発で切り替える等)のような単一スイッチポイントが必要で、dist レイアウト規約(課題2と同じ領域)の再設計に含めて対応する。課題1への補足: 関数シグネチャも同様にファイル跨ぎで共有できない(PR #118 追記)
コメント
型宣言(record / type alias)だけでなく、関数シグネチャも同じ制約を受ける。include された DSL ファイルが sibling や entry で宣言された関数を呼ぶと、ファイル単位の checker が
unknown functionで失敗する(gawk 自体は include 跨ぎの関数分割を許容する)。例:a.awkのfunction a() -> Int { return b() }がb.awkのb()を参照するケース。課題1の解決方式(include closure の一括 compile または宣言の事前抽出+注入)でシグネチャ収集も同時に扱う。