Add bilingual manual and localized docs routes

This commit is contained in:
2026-08-14 11:16:37 +09:00
parent 3645a2cc2d
commit cda32cc260
85 changed files with 2316 additions and 71 deletions
@@ -0,0 +1,43 @@
# 算術式
Decodal は具体的な数値に対する算術演算をサポートする。
```dcdl
{
workers = 2 + 2;
timeout = 30.0 / 2;
port = 8000 + 80;
negative = -1;
}
```
## 演算子
- `+`: 加算
- `-`: 減算
- `*`: 乗算
- `/`: 除算
- 単項 `-`: 符号反転
`*``/``+``-` より高い優先順位を持つ。
括弧を使ってグループ化を明示できる。
```dcdl
2 + 3 * 4 # 14
(2 + 3) * 4 # 20
```
## 数値の扱い
算術演算には具体的な `Int` または `Float` の operand が必要である。
`Int + Int``Int - Int``Int * Int` は、overflow が発生しない場合に `Int` を返す。
`Int``Float` が混在する演算は `Float` を返す。
除算は常に `Float` を返す。
ゼロ除算と整数 overflow は評価エラーになる。
算術式は、default や数値制約を含め、具体的な数値式が必要な任意の場所で使える。
```dcdl
port = Int & > 4000 + 42 default 8080;
```
@@ -0,0 +1,71 @@
# Array Expression
array expression は、順序付きの値の列を表す。
```dcdl
[1, 2, 3]
["a", "b", "c"]
```
配列リテラルは concrete value であり、要素型を揃える必要はない。
```dcdl
["api", 8080, true]
```
## Array constraint
配列制約は `[` の直後に ellipsis を置き、その後へ要素制約を記述する。
```dcdl
Names = [...String];
Ports = [...(Int & >= 1 & <= 65535)];
```
`[...T]` は、すべての要素が `T` を満たす長さ 0 以上の配列を表す。
空配列は任意の配列制約を満たす。
```dcdl
[...String] & []
[...String] & ["api", "worker"]
```
要素制約は object range にもできる。
右辺だけにある default 付き field は、配列へ制約を合成した時点では abstract のまま各要素に残る。
その配列を後から materialize した場合にだけ default が使われる。
```dcdl
Services = [...{
name = String;
enabled = Bool default true;
}];
Services & [{ name = "api"; }]
```
配列制約を concrete array に適用すると、各要素は要素 range に対して `as` と同じ規則で絞り込まれる。
object の要素 range では左辺にしかない field がエラーになり、右辺にしかない field は abstract のまま残る。
要素制約のない抽象配列型は提供しない。
旧来の `Array` primitive type は使用できず、`[...T]``T` は必須である。
`[String]` は配列制約ではなく、未解決の `String` 制約を 1 要素に持つ concrete array になる。
配列制約は要素範囲だけを表す。長さ制約、位置別の tuple 制約、unique 制約は持たない。
## Array concat
`++` は concrete array 同士を連結する。
```dcdl
base = ["read", "write"];
extra = ["admin"];
roles = base ++ extra;
```
`roles` は以下と同じ値になる。
```dcdl
["read", "write", "admin"]
```
`++` は配列要素を変換しない。
左辺の要素の後に右辺の要素が並ぶ。
@@ -0,0 +1,75 @@
# Range Refinement
`narrower as wider` は、左辺が右辺より具体的で狭い範囲であることを確認し、両者を非対称に合成する演算である。
```dcdl
Int & > 10 as Int & > 0
```
この例は成功し、結果は左辺の狭い範囲 `Int & > 10` のままになる。逆向きの `Int as Int & > 0` は、左辺が右辺を満たすとは限らないため失敗する。
## Object
object では、右辺を field domain として左辺の field を確認する。
- 左辺にしかない field は、右辺の domain 外なのでエラーになる。
- 両側にある field は、左辺が右辺より狭いかを再帰的に確認し、左辺の狭い結果を使う。
- 右辺にしかない field は、default の有無に関係なく未評価のまま結果へ残す。
- 結果の field order は右辺の順序に従う。
```dcdl
partial = {
port = 8080;
} as {
host = String;
port = Int;
enabled = Bool default true;
};
```
`partial.port``8080` に具体化される。`partial.host``partial.enabled` は右辺由来の abstract field のままであり、`as``enabled` の default を選択も force もしない。
その後 `partial` 全体を materialize すれば、通常の materialize 規則が適用される。この例では unresolved な `host` がエラーになり、`host` も具体化されていれば `enabled` の default がその時点で利用される。
## Default
default は範囲包含の根拠ではない。両側に同じ field がある場合、結果には左辺を使うため、右辺の default を左辺へ注入しない。
```dcdl
Int & > 0 as (Int default 1)
```
結果は default のない `Int & > 0` である。一方、右辺だけに残る object field は field 全体を保持するため、その abstract value が元から持つ default も保持される。
## Map and array ranges
`{...T}` は任意の object key を許可し、各 value が `T` より狭いことを確認する。
```dcdl
ports = {
http = 80;
https = 443;
} as {...(Int & >= 1 & <= 65535)};
```
`[...T]` を右辺に使う場合も、すべての array element を `T` に対して絞り込む。
## Concrete right-hand ranges
primitive constraint や合成 constraint は通常どおり値を検証する。
右辺が concrete scalar または array literal の場合は、左辺も同じ値または同じ長さ・要素構造である必要がある。
function は右辺の範囲として使用できない。
左辺は concrete value に限らない。包含関係を判定できる constraint 同士であれば abstract value も使用できる。primitive type、numeric bound、同一 regex / predicate、array/map の要素範囲は包含確認の対象になる。
関数 parameter の `name: range` も、引数が force された時点で `as` と同じ絞り込み規則を使う。
## Precedence
`as``default` より低い、最も低い優先順位を持ち、左結合である。
```dcdl
narrow & overrides as Wider
```
これは `(narrow & overrides) as Wider` と解釈される。
@@ -0,0 +1,27 @@
# Composition Expression
composition expression は、複数の値・制約・構造を合成する式である。
## `&`
`&` は制約を保った合成を行う。
```dcdl
Port = Int & >= 1 & <= 65535;
Config = MyConfig & { port = 8000; };
```
object 同士では片側だけにある field も保持するため、`&` は方向を持たない。
左辺が右辺より狭いことを確認し、右辺を field domain として合成したい場合は [`as`](./ascription.md) を使う。
## `//`
`//` は右辺優先の構造的 patch を行う。
```dcdl
Patched = Base // {
feature_hoge.enable = false;
};
```
詳細は [合成演算子](../operators.md) を参照する。
@@ -0,0 +1,15 @@
# Default Expression
`default` expression は、明示値が存在しない場合に materialize 時に採用される fallback を指定する。
```dcdl
port = Int default 8080;
```
`default` は制約ではない。
詳細は [制約と default](../constraints-and-defaults.md) を参照する。
## 評価
fallback expression は materialize 時に必要になった場合だけ評価される。
明示値がある場合、`default` は評価も採用もされない。
@@ -0,0 +1,14 @@
# Function Call Expression
function call expression は、関数値を引数に適用する式である。
```dcdl
increment(41)
```
## 評価
引数は関数本体から参照された時点で評価される。
同じ引数を複数回参照した場合は評価結果が再利用される。
parameter に range が指定されている場合、引数は `narrower as wider` と同じ規則で絞り込まれる。
parameter 側だけにある field は abstract のまま残り、default はこの時点では選択されない。
@@ -0,0 +1,14 @@
# Function Expression
function expression は、引数を受け取り式を返す値である。
```dcdl
(value: Int) => value + 1
```
関数仕様の詳細は [関数](../functions.md) を参照する。
## 評価
関数は定義された lexical scope の bindings を参照する。
関数本体は、関数値の生成時ではなく呼び出し時に評価される。
@@ -0,0 +1,14 @@
# Identifier Expression
identifier expression は、lexical scope に束縛された名前を参照する式である。
```dcdl
Port
MyConfig
mkConfig
```
## 評価
識別子は対応する binding の値を必要になった時点で評価する。
束縛が存在しない場合は未定義識別子エラーになる。
@@ -0,0 +1,14 @@
# Import Expression
import expression は、ホストが解決した DCDL module または structured value を返す。
```dcdl
import "./config.dcdl"
```
specifier は string literal であり、path や resource name としての解釈はホストが定義する。
詳しくは [モジュールと import](../modules-and-imports.md) を参照する。
## 評価
import 先は遅延評価され、参照されない field は評価されない。
@@ -0,0 +1,26 @@
# Expression
この章では、言語が評価対象として持つ式の分類を定義する。
式は、値・制約・構造・計算を表す基本単位である。
```text
Expr
├─ literal
├─ identifier
├─ path reference
├─ object
├─ map constraint
├─ array
├─ array constraint
├─ function
├─ function call
├─ let
├─ match
├─ import
├─ composition
├─ range refinement (`as`)
└─ default
```
各式の個別仕様へのリンクは [Manual Index](../../index.md) に集約する。
@@ -0,0 +1,16 @@
# Let Expression
let expression は、ローカル束縛を作る。
```dcdl
let
base = 8000;
offset = 80;
in
base + offset
```
## 評価
binding は参照された時点で評価される。
参照されない binding は評価されず、同じ binding を複数回参照した場合は評価結果が再利用される。
@@ -0,0 +1,20 @@
# Literal Expression
literal expression は、ソース上に直接書かれる具体値である。
## 種類
```dcdl
"hello"
123
3.14
true
false
```
## 対応する primitive type
- 文字列リテラルは `String` を満たす。
- 整数リテラルは `Int` を満たす。
- 浮動小数リテラルは `Float` を満たす。
- `true` / `false``Bool` を満たす。
@@ -0,0 +1,41 @@
# 論理式と比較式
Decodal は具体的な `Bool` に対する論理演算と、具体的な scalar value に対する比較をサポートする。
```dcdl
{
is_prod = env == "prod";
high_port = port > 9000;
enabled = is_prod && high_port;
disabled = !enabled;
}
```
## 論理演算子
- `!expr` は具体的な `Bool` を反転する。
- `lhs && rhs` は論理積を返す。
- `lhs || rhs` は論理和を返す。
`&&``||` は短絡評価され、右辺は必要な場合にだけ評価される。
論理演算の operand は具体的な `Bool` へ評価される必要がある。
## 比較演算子
- `==`
- `!=`
- `<`
- `<=`
- `>`
- `>=`
`==``!=` は、`String``Bool``Int``Float` の具体的な scalar value を比較する。
`Int``Float` は数値として相互に比較できる。
順序比較演算子 `<``<=``>``>=` は、具体的な数値だけを比較する。
これらは `> 443` のような prefix comparison constraint とは別のものである。
```dcdl
port = Int & > 443 default 9443;
is_high = port > 9000;
```
@@ -0,0 +1,24 @@
# Match Expression
match expression は、対象値を上から順に pattern と照合し、最初に一致した分岐を採用する。
```dcdl
foo = match inputs.a.hoge {
>= 20: {
value = 200;
};
>= 10: {
value = 100;
};
_: {
value = 300;
};
};
```
`_` は fallback pattern である。
## 順序
分岐は順序付きであり、「最も具体的な pattern」を自動選択しない。
広い条件を先に書くと、後続の狭い条件には到達しない。
@@ -0,0 +1,88 @@
# Object Expression
object expression は、名前付き field の集合を表す。
```dcdl
{
host = "127.0.0.1";
port = 8000;
}
```
object は設定値にもスキーマにも使う。
```dcdl
MyConfig = {
host = String;
port = Int default 8080;
};
```
## Dot-path Field
ネストした field はドットパスでも定義できる。
```dcdl
{
feature_hoge.enable = false;
}
```
これは以下と同じ構造を表す。
```dcdl
{
feature_hoge = {
enable = false;
};
}
```
## Map constraint
連想配列の制約は、object の任意の field value に同じ schema を適用する。
```dcdl
Services = {...{
port = Int;
enabled = Bool default true;
}};
```
`{...T}` は key の集合を固定せず、すべての value が `T` を満たす object を表す。
空 object も許容される。materialize 後は named fields を持つ object と同じ object data になる。
```dcdl
services = {
api = { port = 8080; };
worker = { port = 8081; enabled = false; };
} as Services;
```
各 entry は `as` によって右辺の field domain 内へ絞り込まれるため、左辺に `port``enabled` 以外の field があればエラーになる。
右辺にしかない field は default の有無にかかわらず abstract のまま残る。
host から渡した object は識別子構文に収まらない文字列 key も保持できるが、DCDL source の object field name は通常の識別子に限られる。
## Object rest constraint
固定 field と任意 key の value range は、一つの object に混在できる。
```dcdl
OpenConfig = {
enabled = Bool default true;
...Unknown
};
```
`...T` は明示されていない残余 field にだけ適用する。明示 field にはそれぞれの field range を適用し、rest range を重ねて適用しない。
rest constraint は field を生成せず、materialize 時には実際に存在する追加 field だけを出力する。
```dcdl
{
enabled = false;
plugin = { name = "cache"; };
} as OpenConfig
```
`...T` は object の末尾に一つだけ書ける。省略した object は閉じており、`as` の左辺に未宣言 field があればエラーになる。
named field を持たない `{...T}` は abstract な map constraint であり、単独で materialize するには `default` または concrete value が必要になる。
@@ -0,0 +1,16 @@
# Path Reference Expression
path reference expression は、object のフィールドを参照する式である。
```dcdl
config.host
config.feature_hoge.enable
```
## 評価
左側の式を object として評価し、指定された field を参照する。
参照先 field は必要になるまで評価されない。
存在しない field への参照は diagnostic になる。
明示的な `Unknown` range は存在しないfieldを表さないため、fieldの有無を曖昧にはしない。