Odin の文書化¶
Odin ドメインはパッケージ、プロシージャー、型、メンバーに名前付きターゲットを与える。Guidedog は Odin ソースから API ページも生成するが、コンパイラーもパッケージも実行しない。生成したシグネチャにも有用な契約が必要。
オブジェクトの記述¶
パッケージは、Python モジュールのように後続の記述の文脈を定める。
.. odin:package:: core:strings
:synopsis: Procedures to manipulate UTF-8 encoded strings.
:imports: rt=base:runtime
.. odin:procedure:: @(require_results) clone :: proc(s: string, allocator := context.allocator) -> (res: string, err: rt.Allocator_Error) #optional_allocator_error
Clones a string.
:param s: The string to be cloned.
:result res: The cloned string.
:result err: An allocator error, or ``nil``.
.. odin:struct:: Builder :: struct
A dynamic byte buffer.
.. odin:field:: buf: [dynamic]byte
シグネチャは Odin の宣言と同じく一行で書き、そのまま表示する。以下の例は次のように見える。
- shapes.Kind :: enum u8
-
- Circle = 1
- @(require_results) shapes.area :: proc(side: f32, scale: f32 = 1) -> (a: f32, ok: bool) #optional_ok
-
正方形を計測します。
- パラメーター:
side – 一辺の長さ。
- 戻り値:
a – 面積。
ok – 種類が分かっているか。
ディレクティブと受け付けるシグネチャ。
odin:packageとodin:currentpackage-
core:fmtやプロジェクト配下のreaders/sphinxを指定する。オブジェクト名はインポートパスを使う(core:fmt.println)。odin:currentpackageはターゲットを作らず文脈を変え、Noneは解除する。オプションは:synopsis:、:platform:、:deprecated:、:no-index:、:imports:。最後はシグネチャの別名をalias=package(gd=core rst=readers/rst)で指定し、gd.Node_Idをcore.Node_Idに結ぶ。:private:は私有型とプロシージャー群の私有メンバー(State Rules catalog_text)を列挙する。リンク先の説明がないため文字列で表示し、生成ページは自動で列挙する。 odin:procedure(またはodin:proc)-
name :: proc(params) -> results。名前前の属性(@(require_results))、proc前の#force_inline、呼出規約(proc "c" (...))、既定引数(x := 1、x: int = 1)、$T多相引数、..可変長、using、#c_vararg、名前付き結果、タグ(#optional_ok)、where節を扱う。name(params) -> resultsは短縮形。 odin:procgroup-
name :: proc{a, b}:各メンバーは対応するプロシージャーにリンクする。 odin:struct,odin:union,odin:enum,odin:bitset,odin:bitfield,odin:type-
Name :: struct($T: typeid) #packed、Name :: union #no_nil {A, B}、Name :: enum u8、Name :: bit_set[Flag; u8]、Name :: bit_field u32。odin:typeは distinct 型と別名(Handle :: distinct uintptr、Callback :: proc(x: int) -> bool)を扱う。型の内容にメンバーを記述する。 odin:fieldとodin:enumerator-
型の中では
name: Typeにタグ(name: string `json:"n"`)やビット幅(low: u8 | 3)を付けられ、列挙子はNameまたはName = 3。名前はType.memberとなる。 odin:const,odin:var,odin:foreign-
NAME :: 64またはNAME : int : 64、name: Type、name := value、name: Type = value。外部インポートはlibc "system:c"。
全オブジェクトが Sphinx の :no-index:、:no-index-entry:、:no-contents-entry:、:no-typesetting: を受け付ける。独自には :package:(別パッケージで説明)、:private: と :deprecated: message(シグネチャになければ @(private) と @(deprecated="message") を表示)、:availability: Windows, Linux(本文先頭に対応先)、:foreign: libc(外部ブロックの手続き)がある。複数行のシグネチャはターゲットで異なる同じオブジェクトを表し、ID と索引は最初だけに付く。
型の位置にある名前は、まずシグネチャのパッケージと型で、次にそのまま検索してリンクする。組み込み型(int、string、rawptr、typeid、any など)、予約語、多相名($T と以後の T、外側の型を含む)、配列長、既定値、定数、タグ、where 節はそのまま表示し、リンクにしない。
ロールと ID¶
:odin:pkg:、:odin:proc:、:odin:type:(構造体、共用体、列挙、ビット集合・フィールドなど)、:odin:const:、:odin:var:、:odin:field:、:odin:enumerator:、:odin:obj:(全種類)がリンクする。Python 同様 ~ は末尾だけを表示し(:odin:proc:`~core:fmt.println` は println)、先頭の . は名前の末尾を探す。参照元の型とパッケージ、そのままの名前、パスの : や / の後の順に検索する。fmt.println は core:fmt.println、sphinx.Config は readers/sphinx.Config を見つける。Odin と同じ末尾のパッケージ名で、:imports: の別名を優先する。default-domain:: odin または primary_domain = "odin" なら odin: は省ける。
ID は odin- と完全名に Sphinx の make_id を適用する。例は odin-core-fmt.println、odin-readers-sphinx.Config.docname。Python 同様大小文字とドットを保ち、パスの : と / はハイフンになる。URL で読め、ビルド間で安定し、末尾同名のパッケージも区別する。パッケージ ID は odin-package- とパス。索引は「println (procedure in core:fmt)」。objects.inv は odin と種別(odin:procedure、odin:struct、odin:field など)で全オブジェクトを、Sphinx のモジュール同様パッケージを先に列挙する。
内容中の情報フィールドは他のドメイン同様にまとめる。:param name:(:type name: と併用)、名前付き結果の :result name:、:returns:、:rtype:。
ソースからの生成¶
ソースフォルダーからの相対位置でパッケージを指定する。
odin_autoapi_dirs = ["../src"]
odin_collections = {core = "/usr/local/lib/odin/core"} # optional
odin_autoapi_dirs 配下は相対パスで命名する(src/shapes/round は shapes/round)。コレクション内は Odin のインポート名(core:strings)を使う。生成ディレクティブは autodoc と同様に動く。
.. odin:autopackage:: shapes
:members:
:undoc-members:
:member-order: groupwise
.. odin:autoproc:: shapes.area
.. odin:autotype:: Shape
odin:autopackage はパッケージと文書コメントを、:members: で宣言全てまたは指定分も出力する。odin:autoproc、odin:autoprocgroup、odin:autotype、odin:autoconst、odin:autovar は現在のパッケージ名または package.name の宣言一つを出す。オプションは :members:、:undoc-members:、:private-members:(通常除く @(private))、:exclude-members:、:member-order:(既定の source はファイル名と位置順、alphabetical、groupwise は「Types」「Procedures」「Procedure groups」「Constants」「Variables」「Foreign imports」で分類)、:no-index:。
文書コメントは宣言直上の // 行や /* */ ブロック、フィールドや列挙子の行末コメント。プレーンテキストを次の規則で reStructuredText にする。
- 段落は段落に、
- itemの行はリストになる。 - 空行またはコロンで終わる行(
Example:)の後の字下げブロックはcode-block:: odin、Output:の後はtextになる。段落行直後のテキストより深い字下げの行は、その段落を続ける。 Inputs:の- name: text項目は:param name:、Returns:は:result name:(名前なしなら:returns:)になる。Odin のコアライブラリーと同じ書式だ。NOTE:またはWARNING:で始まる行は注記または警告になる。`code`はリテラル。reStructuredText が記法と読む他の文字(*、|、語末の_など)はエスケープし、コメントをそのまま表示して警告を出さない。
API ページ¶
odin_autoapi_dirs を設定すると、各パッケージに sphinx-autoapi のようなページを読み取り時に生成する。api/shapes は odin_autoapi_options 付きの odin:autopackage:: shapes、api/index は各パッケージと概要を含む。toctree、検索、総索引、singlehtml、PDF に入るプロジェクト文書だが、ソースフォルダーには書かない。設定は次の通り。
odin_autoapi_dirs-
ページを作るパッケージのフォルダーをソースからの相対位置で指定する。その配下と
odin_collectionsのファイルだけを読み、外へ向かうリンクは拒否する。 odin_collections-
core:stringsなどの引数に使う、コレクション名とフォルダーの表。これらのパッケージにはページを作らない。 odin_autoapi_root-
ページのフォルダー。既定は
"api"。同名のソース文書があればそちらを残し、警告する。 odin_autoapi_options-
既定は
["members", "undoc-members"]。private-membersも追加できる。 odin_autoapi_member_order-
"source"(既定)、"alphabetical"、"groupwise"。 odin_autoapi_add_toctree_entry-
true(既定):api/indexをルート文書の最初の toctree に加える。 odin_autoapi_generate_api_docs-
true(既定)。falseはディレクティブ用にだけフォルダーを読む。
文書化しないパッケージの型(core:io.Writer)にはリンクできない。-n では nitpick_ignore_regex = [["odin:type", "(core|base):.*"]] で抑制する。Guidedog の docs/api もこの設定を使う。
プラットフォーム¶
Odin と同じファイル判定で、パッケージの全ターゲットを文書化する。*_windows.odin、*_linux_arm64.odin、*_amd64.odin は該当先のみ。#+build linux, darwin、#+build !windows(旧 //+build も)が絞る。ファイルの when ODIN_OS == .Windows が ODIN_OS と ODIN_ARCH の比較だけなら、分岐と else を対応先へ分ける。*_test.odin と #+ignore は除く。全ターゲット共通の宣言は一回、部分対応は「Availability: Windows」などで示す。異なるシグネチャはそれぞれ対応先付きで示し、ID は最初だけ。部分対応のパッケージは :platform: で示す。
再ビルド¶
読んだ各 Odin ファイルはページの依存となる。ソース編集後は、そのパッケージを説明するページだけを再読する。パッケージの追加・削除・概要変更時は索引も再読する。guidedog serve は HTML を返す前に odin_autoapi_dirs と odin_collections の変更時刻を調べる。編集後にブラウザーを更新する。
制約¶
- ソースは解析だけで、コンパイルや型検査はしない。型と定数値はそのまま表示し、100文字超の値は省く。推論もない。
A :: Bの型か定数かは名前で判定し、全大文字でない大文字始まりの名前や組み込み型を型とする。 whenの条件はODIN_OSとODIN_ARCHの比較以外は評価せず、両方の分岐を記載する。- 私有型は文字列で示す。
:private-members:がなければリンク先の項目がないためだ。生成したパッケージは:private:に列挙するので-nでも報告しない。 core:odin/parserは#optional_okとwhereを併用するプロシージャーを拒否する。そのファイルを報告し、読めた部分は文書化する。- Odin のパーサーは深い入れ子で多くのスタックを要し、数百の括弧でスレッドをあふれさせる。実用を大きく超えるファイル(括弧・型が約50段、一連の
elseが約千個)はodin.autodoc.nestingで除き、パッケージの残りは記載する。whenの&&、||、!は64段まで評価し、それ以上は未評価とする。