|
| 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 |
0 commit comments