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