99 lines
2.3 KiB
Markdown
99 lines
2.3 KiB
Markdown
# materialize とエラー
|
|
|
|
通常の評価では、制約や default を含む中間値が残ることがある。
|
|
外部へデータとして出力する段階では、materialize を行う。
|
|
|
|
## materialize の責務
|
|
|
|
materialize は以下を行う。
|
|
|
|
- 必要なフィールドを評価する。
|
|
- 明示値がない abstract value に default を適用する。
|
|
- 採用された値が制約を満たすか検証する。
|
|
- default を持たない未解決の abstract value をエラーにする。
|
|
- 未適用の関数など、データとして出力できない値をエラーにする。
|
|
|
|
## 例
|
|
|
|
```dcdl
|
|
MyConfig = {
|
|
host = String;
|
|
port = Int default 8080;
|
|
};
|
|
```
|
|
|
|
`MyConfig` を materialize すると、`host` は具体値も default もないためエラーになる。
|
|
`port` は `8080` が採用される。
|
|
|
|
```dcdl
|
|
Config = MyConfig & {
|
|
host = "localhost";
|
|
};
|
|
```
|
|
|
|
`Config` を materialize すると以下になる。
|
|
|
|
```dcdl
|
|
{
|
|
host = "localhost";
|
|
port = 8080;
|
|
}
|
|
```
|
|
|
|
## default の適用
|
|
|
|
`default` は materialize 時にのみ fallback として採用される。
|
|
|
|
```text
|
|
Abstract {
|
|
constraints: [Int]
|
|
default: 8080
|
|
}
|
|
```
|
|
|
|
この abstract value を materialize すると、`8080` が採用され、`Int` を満たすか検証される。
|
|
|
|
明示値がある場合、default は採用しない。
|
|
明示値は concrete value として表現され、default を保持しない。
|
|
|
|
```text
|
|
Concrete(Int(9000))
|
|
```
|
|
|
|
この値の最終値は `9000` である。
|
|
|
|
## エラー分類
|
|
|
|
代表的なエラー:
|
|
|
|
- 構文エラー
|
|
- 未定義識別子
|
|
- 型不一致
|
|
- 制約違反
|
|
- `&` の conflict
|
|
- `default` の conflict
|
|
- 循環依存
|
|
- import 失敗
|
|
- match の非網羅による失敗
|
|
- materialize 不能な値の出力
|
|
|
|
## match の失敗
|
|
|
|
`match` に fallback 分岐がなく、どの分岐にも一致しなかった場合はエラーになる。
|
|
|
|
```dcdl
|
|
match value {
|
|
>= 10: "large";
|
|
}
|
|
```
|
|
|
|
`value` が `10` 未満であれば失敗する。
|
|
|
|
## エラーは値ではない
|
|
|
|
エラーは runtime value ではなく diagnostic として扱う。
|
|
通常の式はエラー内容に基づいて分岐できない。
|
|
|
|
汎用 `try / catch` は core には含めない。
|
|
fallback は `default`、`match`、および将来的な optional import / optional field access のような限定された仕組みで表現する。
|