Add unknown ranges and open object values

This commit is contained in:
2026-08-14 08:00:22 +09:00
parent 8c50dd202d
commit 848c7f169f
53 changed files with 9047 additions and 6572 deletions
@@ -82,12 +82,27 @@ Int & >= 10 & <= 10 # OK
最小の組み込み制約は以下である。
```dcdl
Unknown
String
Int
Float
Bool
```
`Unknown` はすべてのDecodal値を含む最上位rangeである。検査を無効化する `Any` ではなく、具体的な値またはより狭いrangeがまだ決まっていないことを表す。
```dcdl
Int & Unknown # Int
42 as Unknown # 42
Unknown as Int # エラー
```
`Unknown` 自体は具体値を持たないためmaterializeできない。defaultを与えるか、具体値で絞り込む必要がある。
```dcdl
Unknown default {} # {}
```
追加の述語制約はライブラリまたは組み込みとして提供できる。
```dcdl
@@ -150,7 +165,16 @@ Services = {...{
```
key は schema で列挙せず、空 object も許容する。
固定 object field と任意 key の value constraint を混在させる構文は現在サポートしない
固定 object field と任意 key の value constraint は、末尾の `...T` で混在できる
```dcdl
{
enabled = Bool default true;
...Unknown
}
```
このrest constraintは明示されていないfieldだけに適用され、field自体は生成しない。
## default
+23 -1
View File
@@ -63,4 +63,26 @@ services = {
右辺にしかない field は default の有無にかかわらず abstract のまま残る。
host から渡した object は識別子構文に収まらない文字列 key も保持できるが、DCDL source の object field name は通常の識別子に限られる。
固定 field と任意 key を一つの object schema に混在させる rest-field 構文は、現在サポートしない。
## 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 があればエラーになる。
名前付き field を持たない `{...T}` は従来どおり抽象的な map constraint であり、単独でmaterializeするにはdefaultまたは具体値が必要になる。
@@ -13,4 +13,4 @@ config.feature_hoge.enable
参照先 field は必要になるまで評価されない。
存在しない field への参照は diagnostic になる。
Decodal は unknown / Any のような値を伝播せず、field の有無を曖昧にしない。
明示的な `Unknown` range は存在しないfieldを表さないため、fieldの有無を曖昧にしない。
+3 -1
View File
@@ -71,7 +71,9 @@ literal = string | integer | float | "true" | "false" | regex ;
comparison_operator = "==" | "!=" | "<" | "<=" | ">" | ">=" ;
comparison_constraint = ( "<" | "<=" | ">" | ">=" ) , expression ;
object = "{" , [ field_definition , { ";" , field_definition } , [ ";" ] ] , "}" ;
object = "{" , [ field_definition , { ";" , field_definition }
, [ ";" , object_rest ] , [ ";" ] ] , "}" ;
object_rest = "..." , expression ;
map_constraint = "{" , "..." , expression , "}" ;
field_definition = field_path , "=" , expression ;
field_path = identifier , { "." , identifier } ;
@@ -43,11 +43,11 @@ CLI では canonical path を key とする。
### 構造化 import
`ImportLoader::load` は DCDL source または host が構築した `HostValue` を import 結果として返す。
`ImportLoader::load` は DCDL source または host が構築した `Value` を import 結果として返す。
Markdown、JSON、TOML などの解釈規則は core に固定せず、loader がファイル種別を判定して構造化する。
```rust
use decodal::{HostValue, ImportLoader, LoadedImport};
use decodal::{Value, ImportLoader, LoadedImport};
struct ContentLoader;
@@ -62,9 +62,9 @@ impl ImportLoader for ContentLoader {
let parsed = parse_frontmatter(&markdown)?;
return Ok(LoadedImport::value(
parsed.key,
HostValue::object([
Value::object([
("frontmatter", parsed.frontmatter),
("body", HostValue::string(parsed.body)),
("body", Value::string(parsed.body)),
]),
));
}
+1
View File
@@ -13,6 +13,7 @@ tags = [...String];
```
現在の primitive type は `String``Int``Float``Bool` である。
`Unknown` はprimitive typeではなく、すべてのDecodal値を含む最上位の抽象rangeである。具体値またはdefaultがない `Unknown` はmaterializeできない。
配列は primitive type ではなく、必須の要素制約を持つ `[...T]` で表現する。
各型の個別仕様へのリンクは [Manual Index](../../index.md) に集約する。