Trim open issues to materialization

This commit is contained in:
2026-07-09 02:46:28 +09:00
parent 8e1cb01f52
commit 6d80c66144
18 changed files with 92 additions and 187 deletions
+19 -52
View File
@@ -5,54 +5,47 @@
## 構文
```dcdl
(part: {
greet = String;
target = String;
}) =>
"${part.greet}! ${part.target}"
(value: Int) => value + 1
```
関数呼び出しは通常の呼び出し構文で行う。
```dcdl
mk_hw({
greet = "Hello";
target = "World";
})
let
increment = (value: Int) => value + 1;
in
increment(41)
```
複数引数の構文は候補として以下を想定する。
複数引数も指定できる。
```dcdl
(
input_a: {
hoge = Int & >= 0;
},
input_b: {
fuga = 20;
}
) =>
(input_a: { hoge = Int & >= 0; }, input_b: { fuga = Int; }) =>
{
# ...
hoge = input_a.hoge;
fuga = input_b.fuga;
}
```
## 関数の意味
関数は値として扱える
ただし、最終データとして関数値を出力できるかどうかは別途定める。
設定ファイルを materialize する段階では、未適用の関数値は出力不能な値として扱うのが自然である。
関数は runtime value として扱えるが、最終データとして materialize することはできない
未適用の関数値が materialize 対象に残っている場合は diagnostic になる。
関数値は opaque であり、関数値同士の等価性は提供しない。
`&` で関数値同士を合成すると conflict になる。
## 評価方針
関数は以下の方針を基本とする。
関数は以下の方針で評価する。
- 関数は純粋である。
- 関数はレキシカルスコープを持つ。
- 関数は定義時の環境を参照として保持する。
- 引数は必要になるまで評価ない。
- フィールドに束縛された関数呼び出し結果は、そのフィールド評価結果として memoize される
- 任意の関数呼び出しそのものをグローバルに memoize することは必須ではない
- 引数は thunk として渡され、必要になるまで評価されない。
- 関数呼び出し結果そのものはグローバルには memoize しない
- フィールドに束縛された関数呼び出し結果は、そのフィールド thunk の評価結果として memoize される
- 再帰的な依存は thunk cycle として diagnostic になる。
関数値の内部モデル例:
@@ -63,29 +56,3 @@ Function {
env: EnvRef
}
```
## 関数と重さ
関数の文法・パーサー自体は大きくない。
実装上の重さは、主に評価モデルと意味論から発生する。
注意点:
- クロージャが環境を掴む。
- 引数を lazy にするか strict にするかを決める必要がある。
- 関数呼び出し結果をどこまで memoize するかを決める必要がある。
- 再帰関数を許可するかを決める必要がある。
- 関数値同士の `&` をどう扱うかを決める必要がある。
- 関数値を object に入れたとき、materialize 可能かを決める必要がある。
- import 循環と関数適用が絡んだときの cycle detection が必要になる。
軽量に保つため、初期仕様では以下の制限を検討できる。
- 関数は pure。
- lexical closure は許可。
- 引数は thunk として渡す。
- 関数本体は必要になるまで評価しない。
- 関数値は opaque。
- 関数同士の `&` は、同一関数参照以外は conflict。
- 関数値は最終データとして出力できない。
- 再帰は cycle error として扱う、または v1 では禁止する。