Add host-configurable language service

This commit is contained in:
2026-08-11 22:05:17 +09:00
parent 08603dc4b5
commit bdaccd9803
10 changed files with 308 additions and 4 deletions
+16 -4
View File
@@ -41,9 +41,21 @@ The WebAssembly package is for execution, not syntax highlighting.
## Language tools
Source-level tooling lives in the Rust language tools crate.
Semantic editor integration lives in the host-configurable language service crate.
It depends only on the runtime and accepts the same `HostEnvironment` implementation used by a production application.
A host-specific LSP binary can link this crate with its loader and global schema configuration without reimplementing evaluation rules.
Important paths:
```text
crates/decodal-language-service/
```
Source formatting lives in a separate Rust language tools crate.
Keeping it separate prevents host-specific semantic services from inheriting the formatter's Tree-sitter and WebAssembly dependencies.
This component is responsible for operations that must preserve source text details such as comments and whitespace.
It is an internal crate used by the future Rust LSP and by the CodeMirror package's bundled formatter WebAssembly.
It is used by the CodeMirror package's bundled formatter WebAssembly and can also be used by an LSP adapter for formatting.
Important paths:
@@ -52,7 +64,6 @@ crates/decodal-language-tools/
```
The current language tools crate exposes the formatter.
Future LSP functionality should build on the same source-level tooling layer rather than on the runtime core.
## Web editor components
@@ -112,7 +123,8 @@ Consumers that need syntax information should use the component that matches the
- Rust execution and embedding: `decodal`
- Browser execution: `decodal-wasm`
- Web formatting and editor syntax: Lezer / CodeMirror
- Rust LSP internals: `decodal-language-tools`
- Semantic editor analysis: `decodal-language-service`
- Rust formatting: `decodal-language-tools`
- General editor syntax: Tree-sitter
This avoids having a separate token stream API whose behavior would have to be kept compatible with both runtime parsing and editor grammars.
+42
View File
@@ -140,6 +140,48 @@ It only generates schema construction and typed decoding code.
Both mechanisms share the same runtime evaluator, thunk model, and materialization rules.
## Shared host environment
An embedded application can implement `HostEnvironment` to keep loader creation and global binding setup in one place.
Both production evaluation and semantic editor tooling create their engines from this environment, preventing the editor from drifting onto a separate validation path.
```rust
use decodal::{Engine, HostEnvironment};
struct AppEnvironment;
impl HostEnvironment for AppEnvironment {
type Loader = ContentLoader;
fn create_loader(&self) -> Self::Loader {
ContentLoader::new()
}
fn configure_engine(
&self,
engine: &mut Engine<Self::Loader>,
) -> decodal::Result<()> {
engine.bind_global("Site", site_schema())?;
Ok(())
}
}
let environment = AppEnvironment;
let mut engine = environment.create_engine()?;
```
The semantic service accepts the same environment by value:
```rust
use decodal_language_service::LanguageService;
let service = LanguageService::new(&environment);
let analysis = service.analyze("site.dcdl", "site.dcdl", source);
```
Each analysis uses a fresh engine and runs the normal parse, evaluate, and materialize pipeline.
An environment may create loaders backed by shared filesystem, database, or editor-overlay state when repeated analysis needs a current workspace snapshot.
## Structured imports
`ImportLoader::load` returns either `LoadedImport::Source` or `LoadedImport::Value`.
@@ -23,6 +23,9 @@ materialize
data / diagnostics
```
Production applications and semantic language services can construct this pipeline through the same host-defined `HostEnvironment`.
The environment creates the `ImportLoader` and installs host globals before the root module is registered.
## lexer / parser
lexer / parser は source を AST に変換する。