164 lines
4.6 KiB
Markdown
164 lines
4.6 KiB
Markdown
# 制約と default
|
|
|
|
constraint は、値が満たすべき範囲を表す。
|
|
|
|
```dcdl
|
|
Int
|
|
String
|
|
>= 1
|
|
<= 65535
|
|
/Hello! .*/
|
|
```
|
|
|
|
constraint は `&` で合成できる。
|
|
|
|
```dcdl
|
|
Port = Int & >= 1 & <= 65535;
|
|
NarrowedPort = Port & > 443;
|
|
```
|
|
|
|
合成結果は両辺を同時に満たす範囲になる。
|
|
両立しない constraint は conflict になる。
|
|
|
|
```dcdl
|
|
Int & String # conflict
|
|
> 10 & < 5 # conflict
|
|
Int & > 10 & < 11 # conflict: integer candidate does not exist
|
|
```
|
|
|
|
## Primitive and comparison constraints
|
|
|
|
組み込みの primitive range は次の通りである。
|
|
|
|
```dcdl
|
|
String
|
|
Int
|
|
Float
|
|
Bool
|
|
```
|
|
|
|
異なる primitive type を `&` で合成すると conflict になる。
|
|
数値比較 constraint は上下限として合成され、空の範囲になる場合は conflict になる。
|
|
|
|
```dcdl
|
|
Int & >= 1 & <= 65535 & > 443
|
|
```
|
|
|
|
`Int` の比較 constraint は integer literal を使う。
|
|
`Float` の比較 constraint は integer または float literal を使える。
|
|
|
|
## Unknown
|
|
|
|
`Unknown` はすべての Decodal value を含む最上位 range である。
|
|
検査を無効化して具体値の情報を消す `Any` ではなく、値の範囲がまだ絞られていないことを表す。
|
|
|
|
```dcdl
|
|
Int & Unknown # Int
|
|
42 as Unknown # 42
|
|
Unknown as Int # conflict
|
|
```
|
|
|
|
`Unknown` 自体は concrete value を持たないため materialize できない。
|
|
concrete value で絞り込むか `default` を指定する必要がある。
|
|
|
|
```dcdl
|
|
Unknown default {}
|
|
```
|
|
|
|
## Regex constraints
|
|
|
|
regex literal は string constraint である。
|
|
|
|
```dcdl
|
|
Host = /^api-[0-9]+$/;
|
|
```
|
|
|
|
複数の regex constraint を合成した場合、concrete string はすべてに一致する必要がある。
|
|
|
|
```dcdl
|
|
String & /^a/ & /z$/
|
|
```
|
|
|
|
regex constraint 同士の交差は合成時には判定されない。
|
|
そのため、次の範囲は合成時には conflict にならず、concrete value の検証時に失敗する。
|
|
|
|
```dcdl
|
|
String & /^a$/ & /^b$/
|
|
```
|
|
|
|
Rust runtime では regex engine を `regex` feature で有効にする。
|
|
feature が無効な場合、regex constraint の concrete value 検証は unsupported feature diagnostic になる。
|
|
|
|
## Array constraints
|
|
|
|
array constraint は `[...T]` と書き、すべての要素へ `T` を適用する。
|
|
要素 constraint は必須である。
|
|
|
|
```dcdl
|
|
Names = [...String];
|
|
PositiveInts = [...(Int & > 0)];
|
|
```
|
|
|
|
concrete array と合成した場合、各要素は `T` に対して `as` と同じ規則で絞り込まれる。
|
|
空 array は任意の array constraint を満たす。
|
|
|
|
要素 constraint が object range の場合、右辺にだけある field は abstract のまま各要素へ残る。
|
|
左辺にしかない field は右辺の field domain 外なので conflict になる。
|
|
|
|
## Associative-array and object rest constraints
|
|
|
|
associative-array constraint は `{...T}` と書き、object の任意の field value へ `T` を適用する。
|
|
|
|
```dcdl
|
|
Services = {...{
|
|
port = Int;
|
|
enabled = Bool default true;
|
|
}};
|
|
```
|
|
|
|
key は列挙されず、空 object も許容される。
|
|
named field を持つ object の末尾へ `...T` を書くと、列挙されていない field だけに `T` を適用できる。
|
|
|
|
```dcdl
|
|
{
|
|
enabled = Bool default true;
|
|
...Unknown
|
|
}
|
|
```
|
|
|
|
rest constraint は field を生成しない。
|
|
実在する追加 field の検証にだけ使われる。
|
|
|
|
## default
|
|
|
|
`default` は constraint ではない。
|
|
materialize 時に concrete value がない場合だけ使われる fallback である。
|
|
|
|
```dcdl
|
|
Port = Int & >= 1 & <= 65535;
|
|
|
|
Service = {
|
|
port = Port default 8080;
|
|
};
|
|
```
|
|
|
|
明示値が合成された場合は明示値が使われ、`default` は評価されない。
|
|
|
|
```dcdl
|
|
Config = {
|
|
port = 9000;
|
|
} as Service;
|
|
```
|
|
|
|
明示値がない場合、materialize 時に `8080` が採用され、`Port` を満たすか検証される。
|
|
|
|
## default composition
|
|
|
|
- `&` で片方だけが `default` を持つ場合、その `default` は保持される。
|
|
- `&` で両辺が異なる `default` を持つ場合は conflict になる。
|
|
- constraint と concrete value の `&` が成功した場合、結果は concrete value になり `default` は残らない。
|
|
- `//` は右辺優先なので、同じ field では右辺の値または `default` が左辺を置き換える。
|
|
- `as` は右辺の `default` を左辺へ注入しない。ただし右辺にだけ存在する field は、その field が持つ `default` とともに abstract なまま結果へ残る。
|
|
|
|
`default` expression は materialize 時に必要になった時点で評価され、同じ range の constraint を満たす必要がある。
|