1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
//! # query_lang
//!
//! An incremental computation engine: a database that caches the results of
//! derived queries, tracks what each result was computed from, and recomputes
//! only what a change actually affects.
//!
//! A compiler runs the same computation over and over as source is edited —
//! parse a file, resolve its names, type-check its definitions, lower it to IR.
//! Most edits touch a fraction of that work, yet a naive compiler redoes all of
//! it on every keystroke. The query model, from Rust's own `salsa` and
//! rust-analyzer, turns each step into a *query*: a pure function whose result is
//! memoized and whose dependencies are recorded as it runs. When an input
//! changes, the engine invalidates only the queries that transitively read it,
//! and reuses everything else. query-lang is that engine, and nothing more — it
//! owns no compiler, no IR, no syntax; it is generic over the queries a consumer
//! defines.
//!
//! ## The model
//!
//! Three pieces:
//!
//! - A [`System`] is the definition of your queries: a [`Key`](System::Key) type
//! that names a query, a [`Value`](System::Value) type it produces, and a
//! [`compute`](System::compute) function that derives one from the other.
//! - A [`Database`] holds the [`System`], stores your **inputs**, and caches the
//! **derived** results. It is the engine: you set inputs and get results, and
//! it handles caching, dependency tracking, and invalidation.
//! - A [`get`](Database::get) resolves a query. Called from application code it
//! returns a result; called from inside a `compute` it reads a dependency, and
//! the engine records that edge automatically.
//!
//! An input is any key whose value you [`set`](Database::set) directly; every
//! other key is derived through `compute`. One `Key` type names both, so a query
//! reads an input and another query the same way.
//!
//! ## Example
//!
//! An input string, a query that parses it to a number, and a query that squares
//! that number. Editing the input recomputes the chain; an edit that leaves the
//! parsed number unchanged stops at the parse via early cutoff.
//!
//! ```
//! use query_lang::{Database, System, QueryError};
//!
//! #[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
//! enum Key {
//! Source, // an input: the raw text
//! Parsed, // = Source parsed as i64
//! Squared, // = Parsed * Parsed
//! }
//!
//! struct Pipeline;
//! impl System for Pipeline {
//! type Key = Key;
//! type Value = i64;
//! fn compute(&self, db: &Database<Self>, key: &Key) -> Result<i64, QueryError> {
//! match key {
//! // `Source` is an input; this default only applies if it was unset.
//! Key::Source => Ok(0),
//! Key::Parsed => Ok(db.get(&Key::Source)?),
//! Key::Squared => {
//! let n = db.get(&Key::Parsed)?;
//! Ok(n * n)
//! }
//! }
//! }
//! }
//!
//! let mut db = Database::new(Pipeline);
//! db.set(Key::Source, 12);
//! assert_eq!(db.get(&Key::Squared)?, 144);
//! assert_eq!(db.stats().computed, 2); // Source is a set input; Parsed and Squared ran
//!
//! // Ask again with no edit: a hit, nothing recomputes.
//! assert_eq!(db.get(&Key::Squared)?, 144);
//! assert_eq!(db.stats().hits, 1);
//! # Ok::<(), QueryError>(())
//! ```
//!
//! ## Features
//!
//! - `std` (default) — the standard library. Without it the crate is
//! `#![no_std]` and needs only `alloc`; the engine itself uses no operating-
//! system facilities either way.
//! - `serde` — derives `serde::Serialize` for [`Revision`] and [`Stats`] so a
//! database's version and cache metrics can be logged or inspected.
//!
//! ## Stability
//!
//! The public surface is frozen and stable as of `1.0.0`: it follows Semantic
//! Versioning, with no breaking changes before `2.0`. The full surface, the
//! semantic guarantees, and the SemVer promise are catalogued in
//! [`docs/API.md`](https://github.com/jamesgober/query-lang/blob/main/docs/API.md#stability).
extern crate alloc;
pub use Database;
pub use QueryError;
pub use Revision;
pub use Stats;
pub use System;
/// Compiles and runs the `rust` code blocks in `README.md` and `docs/API.md` as
/// part of `cargo test`, so the published examples cannot drift from the API.
///
/// Present only while collecting doctests (`#[cfg(doctest)]`); it is not part of
/// the public surface and does not appear in the built library or its docs.
;