Add host-structured imports
This commit is contained in:
@@ -32,15 +32,77 @@ result = schema;
|
||||
通常の object literal 内の field は、その object 内の sibling field を暗黙には識別子として参照できない。
|
||||
object 内の値を参照する場合は、外側で束縛された値や明示的な path reference を使う。
|
||||
|
||||
## SourceLoader
|
||||
## ImportLoader
|
||||
|
||||
`import` specifier の解決は処理系 core ではなく host 側の `SourceLoader` が行う。
|
||||
`import` specifier の解決は処理系 core ではなく host 側の `ImportLoader` が行う。
|
||||
CLI では、specifier を現在の module path からの相対 path として解決する。
|
||||
組み込み利用では、resource table や static source map など、filesystem 以外の loader を使える。
|
||||
|
||||
module cache の key は loader が返す安定 key を使う。
|
||||
CLI では canonical path を key とする。
|
||||
|
||||
### 構造化 import
|
||||
|
||||
`ImportLoader::load` は DCDL source または host が構築した `HostValue` を import 結果として返す。
|
||||
Markdown、JSON、TOML などの解釈規則は core に固定せず、loader がファイル種別を判定して構造化する。
|
||||
|
||||
```rust
|
||||
use decodal::{HostValue, ImportLoader, LoadedImport};
|
||||
|
||||
struct ContentLoader;
|
||||
|
||||
impl ImportLoader for ContentLoader {
|
||||
fn load(
|
||||
&mut self,
|
||||
current_key: Option<&str>,
|
||||
specifier: &str,
|
||||
) -> decodal::Result<LoadedImport> {
|
||||
if specifier.ends_with(".md") {
|
||||
let markdown = read_content(current_key, specifier)?;
|
||||
let parsed = parse_frontmatter(&markdown)?;
|
||||
return Ok(LoadedImport::value(
|
||||
parsed.key,
|
||||
HostValue::object([
|
||||
("frontmatter", parsed.frontmatter),
|
||||
("body", HostValue::string(parsed.body)),
|
||||
]),
|
||||
));
|
||||
}
|
||||
|
||||
let source = read_dcdl(current_key, specifier)?;
|
||||
Ok(LoadedImport::source(
|
||||
source.key,
|
||||
specifier,
|
||||
source.text,
|
||||
))
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`read_content` と `parse_frontmatter` は host 独自の処理であり、Decodal core は Markdown や YAML parser に依存しない。
|
||||
上の loader を使うと、DCDL 側から次のように扱える。
|
||||
|
||||
```dcdl
|
||||
Post = {
|
||||
frontmatter = {
|
||||
title = String;
|
||||
draft = Bool default false;
|
||||
};
|
||||
body = String;
|
||||
};
|
||||
|
||||
post = Post & import "./hello.md";
|
||||
title = post.frontmatter.title;
|
||||
body = post.body;
|
||||
```
|
||||
|
||||
`LoadedImport::Value` は通常の concrete runtime value に internalize される。
|
||||
そのため、path reference、object composition、constraint validation、materialize は source 由来の値と同じ規則を使う。
|
||||
安定した `key` が同じ構造化 import は、engine 内で同じ値としてキャッシュされる。
|
||||
|
||||
`load` が唯一の import hook である。
|
||||
loader は拡張子、media type、または host 独自の規則で振り分け、対応する `LoadedImport` variant を直接返す。
|
||||
|
||||
## 循環 import
|
||||
|
||||
モジュール間に循環参照があっても、必要なフィールドの依存関係が循環していなければ評価できる。
|
||||
@@ -93,4 +155,5 @@ Module func
|
||||
- ファイルが読めない。
|
||||
- import 先の構文解析に失敗する。
|
||||
- import 先の評価で必要な値がエラーになる。
|
||||
- host による非 DCDL content の読み込みまたは構造化に失敗する。
|
||||
- 実装が禁止する import 循環に該当する。
|
||||
|
||||
Reference in New Issue
Block a user