Heroes / Examples / 13-lease

examples/gallery/13-lease.hero

Hand a C library text it will keep, and say when you are done with it.

A string lent with .cstr() is C’s to read for one call, and some libraries keep the pointer and read it later. The header cannot say which, so the program does: x: cstr @= s.lease() hands C a copy of the bytes that lives until end_lease(@x) frees it and leaves x empty. Nothing else can write x, and its name may stand only as an argument of a call, so a second end_lease finds it empty and stops the program instead of freeing twice.

A lease nobody ends stops the program when main returns, with the count of what was left open. The C side here is the smallest library that keeps what it is given, 13-lease.h, shown below. It lives beside the program in the repository; if you copy the program elsewhere, take the header with it.

Run it

$ heroes run examples/gallery/13-lease.hero

These files introduce the language one feature at a time. This page shows the program and not a result, because no test compares their output byte for byte yet.

The program

## Text a C library keeps
#
# `s.cstr()` lends a string to C for one call, and the bytes may be gone by the
# next line. Some libraries keep the pointer and read it later — SQLite when it
# is told not to copy, libcurl for the body of a request — and the header cannot
# say which: a parameter that copies and one that keeps are both `const char *`.
#
# A lease is for that case. `x: cstr @= s.lease()` hands C a COPY of the bytes
# that lives until `end_lease(@x)` frees it and empties the cell. The name of a
# lease may stand only as an argument of a call, nothing else writes its cell,
# and a lease nobody ends is counted when `main` returns, so a leak is a loud
# exit rather than a silent one. The C side here is the smallest library that
# keeps what it is given: `13-lease.h`, beside this file.

extern "13-lease.h"
    function keep_label(s: cstr)
    function kept_label_length() -> u64

function main()
    at: i64 @= 0

    while at < 3
        label: cstr @= f"row-{at}-payload".lease()
        keep_label(s: label)
        print(f"C still reads {kept_label_length()} bytes")
        end_lease(@label)
        at @ at + 1
examples/gallery/13-lease.hero, 27 lines

The C side

/* A C side that KEEPS the text it is handed and reads it later. Libraries do
 * this — SQLite's SQLITE_STATIC, libcurl's CURLOPT_POSTFIELDS — and the header
 * cannot say so: both a copying and a keeping parameter are `const char *`. */
#include <string.h>
static const char *label_kept_by_c;
static inline void keep_label(const char *s) { label_kept_by_c = s; }
static inline size_t kept_label_length(void) { return strlen(label_kept_by_c); }
examples/gallery/13-lease.h, 7 lines

fingerprint sha256 5ff3ca27b965 · 2 files · index.json

Next: calculator. All the examples. ← Previous: 12-interpolation

Run one yourself: the four commands. Learn the language, or read the full specification in one file.