Skip to content

Commit 8f8969a

Browse files
committed
docs: Add Runtime Plugins chapter to the Zyn Book
- Document all standard ZRTL plugins (I/O, FS, Time, Thread, Net, Env) - Include symbol tables with signatures for each plugin - Cover building dynamic (.zrtl) and static (.a) libraries - Show grammar integration with @Builtin blocks - Add ZyntaxRuntime usage examples
1 parent 7abcb32 commit 8f8969a

2 files changed

Lines changed: 387 additions & 0 deletions

File tree

book/14-runtime-plugins.md

Lines changed: 386 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,386 @@
1+
# Runtime Plugins (ZRTL)
2+
3+
The Zyntax Runtime Library (ZRTL) provides native functionality to languages built with Zyntax. Rather than implementing I/O, networking, or threading in each language, ZRTL plugins provide a consistent, high-performance native layer that any Zyntax-based language can use.
4+
5+
## Architecture
6+
7+
```
8+
┌─────────────────────────────────────────────────────────┐
9+
│ Your Language │
10+
│ (Haxe, Zig, Custom DSL) │
11+
└─────────────────────────────────────────────────────────┘
12+
13+
14+
┌─────────────────────────────────────────────────────────┐
15+
│ Zyntax Compiler │
16+
│ (Grammar → TypedAST → HIR → Code) │
17+
└─────────────────────────────────────────────────────────┘
18+
19+
20+
┌─────────────────────────────────────────────────────────┐
21+
│ ZRTL Plugins │
22+
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
23+
│ │ I/O │ │ FS │ │ Time │ │ Net │ ... │
24+
│ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │
25+
└─────────────────────────────────────────────────────────┘
26+
27+
28+
┌─────────────────────────────────────────────────────────┐
29+
│ Operating System │
30+
└─────────────────────────────────────────────────────────┘
31+
```
32+
33+
## Plugin Types
34+
35+
ZRTL plugins are built as:
36+
37+
- **Dynamic libraries** (`.zrtl` files) - For JIT execution and runtime loading
38+
- **Static libraries** (`.a` files) - For AOT compilation and standalone binaries
39+
40+
## Standard Plugins
41+
42+
### zrtl_io - Input/Output
43+
44+
Basic I/O operations for console interaction.
45+
46+
| Symbol | Signature | Description |
47+
|--------|-----------|-------------|
48+
| `$IO$print` | `(StringPtr) -> void` | Print string without newline |
49+
| `$IO$println` | `(StringPtr) -> void` | Print string with newline |
50+
| `$IO$print_int` | `(i64) -> void` | Print integer |
51+
| `$IO$print_float` | `(f64) -> void` | Print float |
52+
| `$IO$print_bool` | `(i32) -> void` | Print boolean |
53+
| `$IO$read_line` | `() -> StringPtr` | Read line from stdin |
54+
| `$IO$flush` | `() -> void` | Flush stdout |
55+
| `$IO$eprint` | `(StringPtr) -> void` | Print to stderr |
56+
| `$IO$eprintln` | `(StringPtr) -> void` | Print to stderr with newline |
57+
58+
### zrtl_fs - File System
59+
60+
File and directory operations.
61+
62+
| Symbol | Signature | Description |
63+
|--------|-----------|-------------|
64+
| `$FS$read_file` | `(StringPtr) -> StringPtr` | Read entire file to string |
65+
| `$FS$write_file` | `(StringPtr, StringPtr) -> i32` | Write string to file |
66+
| `$FS$append_file` | `(StringPtr, StringPtr) -> i32` | Append to file |
67+
| `$FS$exists` | `(StringPtr) -> i32` | Check if path exists |
68+
| `$FS$is_file` | `(StringPtr) -> i32` | Check if path is file |
69+
| `$FS$is_dir` | `(StringPtr) -> i32` | Check if path is directory |
70+
| `$FS$mkdir` | `(StringPtr) -> i32` | Create directory |
71+
| `$FS$mkdir_all` | `(StringPtr) -> i32` | Create directory recursively |
72+
| `$FS$remove` | `(StringPtr) -> i32` | Remove file |
73+
| `$FS$remove_dir` | `(StringPtr) -> i32` | Remove empty directory |
74+
| `$FS$remove_dir_all` | `(StringPtr) -> i32` | Remove directory recursively |
75+
| `$FS$rename` | `(StringPtr, StringPtr) -> i32` | Rename/move file |
76+
| `$FS$copy` | `(StringPtr, StringPtr) -> i32` | Copy file |
77+
| `$FS$list_dir` | `(StringPtr) -> ArrayPtr` | List directory contents |
78+
| `$FS$file_size` | `(StringPtr) -> i64` | Get file size in bytes |
79+
80+
### zrtl_time - Time & Duration
81+
82+
Time operations and sleeping.
83+
84+
| Symbol | Signature | Description |
85+
|--------|-----------|-------------|
86+
| `$Time$now_secs` | `() -> i64` | Unix timestamp (seconds) |
87+
| `$Time$now_millis` | `() -> i64` | Unix timestamp (milliseconds) |
88+
| `$Time$now_micros` | `() -> i64` | Unix timestamp (microseconds) |
89+
| `$Time$monotonic_nanos` | `() -> u64` | Monotonic time (nanoseconds) |
90+
| `$Time$sleep_secs` | `(u64) -> void` | Sleep for seconds |
91+
| `$Time$sleep_millis` | `(u64) -> void` | Sleep for milliseconds |
92+
| `$Time$sleep_micros` | `(u64) -> void` | Sleep for microseconds |
93+
| `$Time$instant_now` | `() -> u64` | Create timing instant |
94+
| `$Time$instant_elapsed_nanos` | `(u64) -> u64` | Nanoseconds since instant |
95+
| `$Time$instant_elapsed_millis` | `(u64) -> u64` | Milliseconds since instant |
96+
| `$Time$instant_free` | `(u64) -> void` | Free instant handle |
97+
| `$Time$format_iso8601` | `(i64) -> StringPtr` | Format as ISO 8601 |
98+
99+
### zrtl_thread - Threading & Atomics
100+
101+
Concurrency primitives.
102+
103+
| Symbol | Signature | Description |
104+
|--------|-----------|-------------|
105+
| `$Thread$spawn` | `(fn(i64)->i64, i64) -> u64` | Spawn thread with function |
106+
| `$Thread$spawn_closure` | `(*ZrtlClosure, i64) -> u64` | Spawn with closure |
107+
| `$Thread$join` | `(u64) -> i64` | Wait for thread, get result |
108+
| `$Thread$current_id` | `() -> u64` | Get current thread ID |
109+
| `$Thread$yield_now` | `() -> void` | Yield to scheduler |
110+
| `$Thread$park` | `() -> void` | Park current thread |
111+
| `$Thread$unpark` | `(u64) -> i32` | Unpark thread by handle |
112+
| `$Thread$available_parallelism` | `() -> u32` | Get CPU core count |
113+
| `$Atomic$new` | `(i64) -> u64` | Create atomic i64 |
114+
| `$Atomic$load` | `(u64) -> i64` | Load atomically |
115+
| `$Atomic$store` | `(u64, i64) -> void` | Store atomically |
116+
| `$Atomic$add` | `(u64, i64) -> i64` | Fetch-add |
117+
| `$Atomic$compare_exchange` | `(u64, i64, i64) -> i32` | CAS operation |
118+
| `$Mutex$new` | `() -> u64` | Create mutex |
119+
| `$Mutex$lock` | `(u64) -> i32` | Lock mutex |
120+
| `$Mutex$try_lock` | `(u64) -> i32` | Try lock (non-blocking) |
121+
| `$Mutex$unlock` | `(u64) -> i32` | Unlock mutex |
122+
123+
### zrtl_net - Networking
124+
125+
TCP and UDP socket operations.
126+
127+
| Symbol | Signature | Description |
128+
|--------|-----------|-------------|
129+
| `$Net$tcp_connect` | `(StringPtr) -> u64` | Connect to TCP server |
130+
| `$Net$tcp_connect_timeout` | `(StringPtr, u64) -> u64` | Connect with timeout (ms) |
131+
| `$Net$tcp_read` | `(u64, u32) -> ArrayPtr` | Read bytes from connection |
132+
| `$Net$tcp_write` | `(u64, ArrayPtr) -> i64` | Write bytes |
133+
| `$Net$tcp_write_string` | `(u64, StringPtr) -> i64` | Write string |
134+
| `$Net$tcp_close` | `(u64) -> void` | Close connection |
135+
| `$Net$tcp_listen` | `(StringPtr) -> u64` | Create TCP listener |
136+
| `$Net$tcp_accept` | `(u64) -> u64` | Accept connection |
137+
| `$Net$tcp_listener_close` | `(u64) -> void` | Close listener |
138+
| `$Net$udp_bind` | `(StringPtr) -> u64` | Create UDP socket |
139+
| `$Net$udp_send_to` | `(u64, StringPtr, ArrayPtr) -> i64` | Send UDP packet |
140+
| `$Net$udp_recv` | `(u64, u32) -> ArrayPtr` | Receive UDP packet |
141+
| `$Net$udp_close` | `(u64) -> void` | Close UDP socket |
142+
143+
### zrtl_env - Environment
144+
145+
Environment variables and process information.
146+
147+
| Symbol | Signature | Description |
148+
|--------|-----------|-------------|
149+
| `$Env$get` | `(StringPtr) -> StringPtr` | Get env variable |
150+
| `$Env$set` | `(StringPtr, StringPtr) -> i32` | Set env variable |
151+
| `$Env$remove` | `(StringPtr) -> void` | Remove env variable |
152+
| `$Env$has` | `(StringPtr) -> i32` | Check if env var exists |
153+
| `$Env$args_count` | `() -> i32` | Get argument count |
154+
| `$Env$arg` | `(i32) -> StringPtr` | Get argument at index |
155+
| `$Env$exe_path` | `() -> StringPtr` | Get executable path |
156+
| `$Env$exit` | `(i32) -> !` | Exit process |
157+
| `$Env$pid` | `() -> u32` | Get process ID |
158+
| `$Env$home_dir` | `() -> StringPtr` | Get home directory |
159+
| `$Env$temp_dir` | `() -> StringPtr` | Get temp directory |
160+
| `$Env$current_dir` | `() -> StringPtr` | Get working directory |
161+
| `$Env$os` | `() -> StringPtr` | Get OS name |
162+
| `$Env$arch` | `() -> StringPtr` | Get CPU architecture |
163+
164+
## Building Plugins
165+
166+
### Dynamic Libraries (.zrtl)
167+
168+
```bash
169+
cd plugins
170+
./build_zrtl.sh --release
171+
```
172+
173+
Output in `plugins/target/zrtl/`:
174+
```
175+
zrtl_io.zrtl
176+
zrtl_fs.zrtl
177+
zrtl_time.zrtl
178+
zrtl_thread.zrtl
179+
zrtl_net.zrtl
180+
zrtl_env.zrtl
181+
plugins.json
182+
```
183+
184+
### Static Libraries (.a)
185+
186+
```bash
187+
cd plugins
188+
./build_static.sh --release
189+
190+
# Cross-compile for specific target
191+
./build_static.sh --target aarch64-apple-darwin
192+
193+
# Build for all supported targets
194+
./build_static.sh --all
195+
```
196+
197+
Output in `plugins/target/static/<target>/`:
198+
```
199+
libzrtl_io.a
200+
libzrtl_fs.a
201+
...
202+
libs.json
203+
```
204+
205+
## Using Plugins in Your Language
206+
207+
### Grammar Integration
208+
209+
Map your language's standard library to ZRTL symbols:
210+
211+
```zyn
212+
@builtin {
213+
// I/O
214+
print: "$IO$print",
215+
println: "$IO$println",
216+
readLine: "$IO$read_line",
217+
218+
// File System
219+
readFile: "$FS$read_file",
220+
writeFile: "$FS$write_file",
221+
222+
// Time
223+
now: "$Time$now_millis",
224+
sleep: "$Time$sleep_millis",
225+
}
226+
```
227+
228+
### In Your Language Source
229+
230+
```
231+
// Your custom language
232+
fn main() {
233+
println("Hello from ZRTL!");
234+
235+
let contents = readFile("data.txt");
236+
println(contents);
237+
238+
sleep(1000); // Sleep 1 second
239+
}
240+
```
241+
242+
### Loading at Runtime
243+
244+
```rust
245+
use zyntax_embed::ZyntaxRuntime;
246+
247+
// Create runtime with ZRTL symbols
248+
let symbols = zrtl_io::symbols(); // Get plugin symbols
249+
let mut runtime = ZyntaxRuntime::with_symbols(&symbols)?;
250+
251+
// Compile and run code that uses plugin functions
252+
runtime.compile_source(r#"
253+
fn main() {
254+
println("Hello from ZRTL!");
255+
}
256+
"#)?;
257+
258+
runtime.call::<()>("main", &[])?;
259+
```
260+
261+
### Static Linking (AOT)
262+
263+
For standalone executables, link against static libraries:
264+
265+
```bash
266+
# Compile your language to object file
267+
zyntax compile --source main.mylang --output main.o --aot
268+
269+
# Link with ZRTL static libs
270+
cc main.o \
271+
-L plugins/target/static/aarch64-apple-darwin \
272+
-lzrtl_io -lzrtl_fs -lzrtl_time \
273+
-o main
274+
```
275+
276+
## Memory Management
277+
278+
ZRTL uses specific memory conventions:
279+
280+
### Strings
281+
282+
ZRTL strings have inline length: `[i32 length][utf8 bytes...]`
283+
284+
```rust
285+
// Creating strings
286+
let s: StringPtr = string_new("hello");
287+
288+
// Reading strings
289+
let len = string_length(s);
290+
let data = string_data(s);
291+
292+
// Freeing strings (caller responsibility for returned strings)
293+
string_free(s);
294+
```
295+
296+
### Arrays
297+
298+
ZRTL arrays: `[i32 capacity][i32 length][elements...]`
299+
300+
```rust
301+
let arr: ArrayPtr = array_new::<i32>(10); // capacity 10
302+
array_push(arr, 42);
303+
let val = array_get::<i32>(arr, 0);
304+
array_free(arr);
305+
```
306+
307+
### Handle-based Resources
308+
309+
File handles, sockets, threads, etc. return `u64` handles:
310+
311+
```rust
312+
let handle = tcp_connect(addr); // Returns handle
313+
// ... use handle ...
314+
tcp_close(handle); // Must close when done
315+
```
316+
317+
## Creating Custom Plugins
318+
319+
### Plugin Structure
320+
321+
```rust
322+
// my_plugin/src/lib.rs
323+
use zrtl::{zrtl_plugin, StringPtr, string_new};
324+
325+
#[no_mangle]
326+
pub extern "C" fn my_greet(name: StringPtr) -> StringPtr {
327+
let name_str = unsafe { zrtl::string_as_str(name) }.unwrap_or("World");
328+
string_new(&format!("Hello, {}!", name_str))
329+
}
330+
331+
zrtl_plugin! {
332+
name: "my_plugin",
333+
symbols: [
334+
("$My$greet", my_greet),
335+
]
336+
}
337+
```
338+
339+
### Cargo.toml
340+
341+
```toml
342+
[package]
343+
name = "my_plugin"
344+
version = "0.1.0"
345+
edition = "2021"
346+
347+
[lib]
348+
crate-type = ["cdylib", "staticlib", "rlib"]
349+
350+
[dependencies]
351+
zrtl = { path = "../../sdk/zrtl" }
352+
```
353+
354+
### Adding to Workspace
355+
356+
Add your plugin directory to `plugins/Cargo.toml`:
357+
358+
```toml
359+
[workspace]
360+
members = [
361+
"zrtl_io",
362+
"zrtl_fs",
363+
# ... existing plugins
364+
"my_plugin", # Your new plugin
365+
]
366+
```
367+
368+
The build scripts will automatically discover and build it.
369+
370+
## Symbol Naming Convention
371+
372+
ZRTL uses a hierarchical naming scheme:
373+
374+
```
375+
$Module$function_name
376+
```
377+
378+
Examples:
379+
- `$IO$println` - I/O module, println function
380+
- `$FS$read_file` - File system module, read_file function
381+
- `$Net$tcp_connect` - Network module, tcp_connect function
382+
383+
This allows:
384+
1. Clear organization by domain
385+
2. No conflicts between plugins
386+
3. Easy mapping in grammar `@builtin` blocks

book/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ A comprehensive guide to building language frontends with ZynPEG.
1717
11. [HIR Builder](./11-hir-builder.md) - Building HIR directly for custom backends
1818
12. [Embedding SDK](./12-embedding-sdk.md) - Embedding Zyntax in Rust applications with native calling
1919
13. [Async Runtime](./13-async-runtime.md) - Promise-based async native runtime
20+
14. [Runtime Plugins](./14-runtime-plugins.md) - ZRTL standard library plugins (I/O, FS, Net, Thread, etc.)
2021

2122
## Quick Start
2223

0 commit comments

Comments
 (0)