tur/capability
capability-passing vtables for controlled side-effect injection.
Capability types are structs of C function pointers, passed explicitly to functions that need a side effect. Each is an opaque handle -- FileSystem, Logger, Random, Time -- built by a make-* constructor from four (or two) c-fn callbacks and released by the matching *-free.
The vtable layouts are the ones the stdlib implementations fill: Real-FileSystem (stdlib/io.tur) returns a FileSystem these helpers call, and Real-Time / Mock-Time (the time module) return the same Time.
Since: Phase 16
FileSystem
(defopaque FileSystem : ptr<void>)
opaque handle to a FileSystem capability vtable.
Built by make-FileSystem (or stdlib/io.tur's Real-FileSystem); released by the matching *-free.
Since: Phase 16
Logger
(defopaque Logger : ptr<void>)
opaque handle to a Logger capability vtable (debug/info/warn/error).
Since: Phase 16
Random
(defopaque Random : ptr<void>)
opaque handle to a Random capability vtable (next-int/next-float).
Since: Phase 16
make-FileSystem
(make-FileSystem [read_fn : (c-fn [cstr ptr<u8> i32 ptr<i32>] i32) write_fn : (c-fn [cstr ptr<u8> i32] i32) delete_fn : (c-fn [cstr] i32) list_fn : (c-fn [cstr ptr<void> i32 ptr<i32>] i32)] : FileSystem)
construct a FileSystem capability from four C callbacks.
The callbacks are bare C-ABI function pointers with the vtable's own signatures, so a defn spelled with i32 / ptr<u8> / ptr<i32> parameters (or a C function) can be passed directly.
| read_fn | (path buf buf_len out_len) -> error code | |
| write_fn | (path data data_len) -> error code | |
| delete_fn | (path) -> error code | |
| list_fn | (path entries max_entries out_count) -> error code |
A heap-allocated FileSystem capability; free with FileSystem-free.
(def fs (make-FileSystem my-read my-write my-delete my-list))
Since: Phase 16
FileSystem-free
(FileSystem-free [fs : FileSystem] : nil)
free a FileSystem capability allocated by make-FileSystem.
| fs | FileSystem from make-FileSystem |
(FileSystem-free fs)
Since: Phase 16
make-Logger
(make-Logger [debug_fn : (c-fn [cstr] nil) info_fn : (c-fn [cstr] nil) warn_fn : (c-fn [cstr] nil) error_fn : (c-fn [cstr] nil)] : Logger)
construct a Logger capability from four C callbacks (debug/info/warn/error).
| debug_fn | (msg) -> nil | |
| info_fn | (msg) -> nil | |
| warn_fn | (msg) -> nil | |
| error_fn | (msg) -> nil |
A heap-allocated Logger capability; free with Logger-free.
(def lg (make-Logger on-debug on-info on-warn on-error))
Since: Phase 16
Logger-free
(Logger-free [log : Logger] : nil)
free a Logger capability allocated by make-Logger.
| log | Logger from make-Logger |
(Logger-free lg)
Since: Phase 16
make-Random
(make-Random [next_int_fn : (c-fn [i32 i32] i32) next_float_fn : (c-fn [] i32)] : Random)
construct a Random capability from two C callbacks.
| next_int_fn | (min max) -> an integer in [min, max] | |
| next_float_fn | () -> an integer in [0, 10000) representing a float |
A heap-allocated Random capability; free with Random-free.
(def rng (make-Random my-next-int my-next-float))
Since: Phase 16
Random-free
(Random-free [rng : Random] : nil)
free a Random capability allocated by make-Random.
| rng | Random from make-Random |
(Random-free rng)
Since: Phase 16
make-Time
(make-Time [now_fn : (c-fn [] i64) sleep_fn : (c-fn [i32] nil)] : Time)
construct a Time capability from two C callbacks.
The handle type is the time module's Time, so a Real-Time or Mock-Time handle and one built here are interchangeable.
| now_fn | () -> i64; the current time in milliseconds since the epoch | |
| sleep_fn | (ms) -> nil; sleeps for ms milliseconds |
A heap-allocated Time capability; free with Time-free.
(def clock (make-Time my-now my-sleep))
Since: Phase 16
Time-free
(Time-free [t : Time] : nil)
free a Time capability allocated by make-Time.
| t | Time from make-Time |
(Time-free clock)
Since: Phase 16
with-capability
(with-capability [bindings & body])
bind capabilities and evaluate body with them in scope.
Takes a let-shaped binding vector, like every other with-* form.
| bindings | a binding vector [name cap-expr ...] | |
| body | forms to evaluate with the bindings in scope |
(with-capability [fs (make-FileSystem r w d l)] (fs-delete fs "data.txt"))
Since: Phase 16
default-capability
(default-capability [type_name])
return the default implementation for a capability type (currently always nil).
| type_name | symbolic name of the capability type (unused in v1) |
Since: Phase 16
fs-read
(fs-read [fs : FileSystem path : cstr buf : ptr<void> buf_len : int] : int)
call read_file on a FileSystem capability.
| fs | FileSystem capability | |
| path | file path to read | |
| buf | output buffer | |
| buf_len | size of buf in bytes |
0 on success, non-zero on error (as returned by the underlying read_file fn).
(fs-read fs "data.txt" buf 64) ; => 0
Since: Phase 16
fs-write
(fs-write [fs : FileSystem path : cstr data : ptr<void> data_len : int] : int)
call write_file on a FileSystem capability.
| fs | FileSystem capability | |
| path | file path to write | |
| data | data buffer | |
| data_len | number of bytes to write |
0 on success, non-zero on error.
(fs-write fs "data.txt" buf 5) ; => 0
Since: Phase 16
fs-delete
(fs-delete [fs : FileSystem path : cstr] : int)
call delete on a FileSystem capability.
| fs | FileSystem capability | |
| path | path of the file to delete |
0 on success, non-zero on error.
(fs-delete fs "data.txt") ; => 0
Since: Phase 16
fs-list
(fs-list [fs : FileSystem path : cstr entries : ptr<void> max_entries : int] : int)
call list on a FileSystem capability.
| fs | FileSystem capability | |
| path | directory path to list | |
| entries | output buffer for entry name pointers (char **) | |
| max_entries | capacity of entries buffer |
The underlying list fn's error code (0 on success).
(fs-list fs "." entries 16) ; => 0
Since: Phase 16
log-debug
(log-debug [log : Logger msg : cstr] : nil)
emit a debug-level log message via a Logger capability.
| log | Logger capability | |
| msg | message string to log |
(log-debug lg "starting")
Since: Phase 16
log-info
(log-info [log : Logger msg : cstr] : nil)
emit an info-level log message via a Logger capability.
| log | Logger capability | |
| msg | message string to log |
(log-info lg "ready")
Since: Phase 16
log-warn
(log-warn [log : Logger msg : cstr] : nil)
emit a warning-level log message via a Logger capability.
| log | Logger capability | |
| msg | message string to log |
(log-warn lg "disk nearly full")
Since: Phase 16
log-error
(log-error [log : Logger msg : cstr] : nil)
emit an error-level log message via a Logger capability.
| log | Logger capability | |
| msg | message string to log |
(log-error lg "write failed")
Since: Phase 16
rng-next-int
(rng-next-int [rng : Random min : int max : int] : int)
return a random integer in [min, max] from a Random capability.
| rng | Random capability | |
| min | inclusive lower bound | |
| max | inclusive upper bound |
A random integer in [min, max].
(rng-next-int rng 1 6) ; => 4
Since: Phase 16
rng-next-float
(rng-next-float [rng : Random] : int)
return a random pseudo-float in [0, 10000) from a Random capability.
| rng | Random capability |
Integer in [0, 10000); divide by 10000.0 to get a float in [0.0, 1.0).
(rng-next-float rng) ; => 2500
Since: Phase 16
time-now
(time-now [t : Time] : int)
return the current time in milliseconds since epoch from a Time capability.
| t | Time capability |
Current time as an integer (milliseconds since epoch).
(time-now clock) ; => 1000
Since: Phase 16
time-sleep
(time-sleep [t : Time ms : int] : nil)
sleep for ms milliseconds via a Time capability.
| t | Time capability | |
| ms | duration in milliseconds |
(time-sleep clock 250)
Since: Phase 16