Drivers
The native drivers that provide the interface, console and network.
Contents
How a Program becomes Rust, in parts. Start with the introduction, then follow each part into the rendered output and the runtime it links against.
- Introduction — what the Rust target is, and how to read the rest of this section.
- Capabilities — which high-level features are possible, built in or through a crate.
- Example — a full program using every keyword, and the Rust it renders to.
- Naming considerations — how Program's dotted names are carried into Rust.
- Entry point — starting a program from
mainwith its drivers. - Drivers — the native drivers that provide the interface, console and network.
- Runtime — the Reactive and Context machinery the rendered code links against.
- Native modules — the hand-written Rust behind
NATIVEfunctions. - Keywords — how each of Program's keywords renders to Rust.
- Project setup — the files and commands to build and run the rendered program.
- Reserved words — the words Rust keeps for itself, and how a colliding name is escaped.
Defining a driver
A driver is a type implementing the Driver trait: it drains one context channel and
reconciles the resources it owns. Here is a console driver — it drains the
Console.Lines channel and prints each line that has changed since the last cycle.
use std::collections::HashMap;
struct ConsoleDriver {
last_by_id: HashMap<i64, String>,
}
impl Driver for ConsoleDriver {
fn channel(&self) -> &str { "Console.Lines" }
fn kind(&self) -> DriverKind { DriverKind::Array }
fn init(&mut self, _add_updates: AddUpdates) {}
fn dispatch(&mut self, emissions: Vec<Line>) {
for line in emissions {
if self.last_by_id.get(&line.id) != Some(&line.text) {
println!("{}", line.text);
self.last_by_id.insert(line.id, line.text);
}
}
}
}
Registering it
A program lists the drivers it uses; the runtime opens a channel for each and never hardcodes one.
fn main() {
Program::Application(Box::new(|| Main()), vec![
Box::new(ConsoleDriver { last_by_id: HashMap::new() }),
]);
}
How the runtime runs it
Each cycle the runtime opens the driver's channel, runs the reactive program (which emits into it),
drains it, and passes the vector to dispatch:
Context::open_array("Console.Lines");
program = Reactive::run(program, updates);
driver.dispatch(Context::drain_array("Console.Lines"));
A driver that produces events — a timer, a network reply, often on its own thread — calls
the add_updates it was given in init, which schedules the next cycle. The
three shapes are the same as everywhere: a tree renderer (the terminal interface), a request set
(network), and a shared ticker.