Decisions 2 and 5. slurp allocates, which is why it waited for Vec, and it follows spec-memory.md's rule exactly: no allocating operation returns an error, so there is no Result here and no out-parameter. A failure to allocate is StorageExhausted under retry; a failure to read is FileError under retry and use-value. The two guards nest rather than merge, because they are two different failures with two different answerable questions — the handler that grows an arena is not the handler that supplies another path. The restarts are the pair Common Lisp establishes for a file-error. use-value is a typed restart, the other thing that landed this session, and this is the first one the compiler itself emits with a parameter. Its parameter *is* the path slot the attempt reads, so the clause body is empty: emit.ml's bind_params stores the invoker's argument into the slot, the clause falls through, and the loop re-attempts against the new path. Everything is inside that loop, so a use-value naming a different file re-measures it and re-allocates for its size; the Vec is freed at the top of each turn, which is why a retry does not leak. The host ABI grows by three calls and one reason reader: flan_file_size, flan_file_read, flan_file_write, flan_file_fail_reason. They are POSIX-shaped and Vec-ignorant — no handle crosses the boundary and nothing is held between calls — so a second target implements three functions. flan_slurp_into is runtime glue on this side of the ABI rather than a fourth call. These do touch paths, which is the widening plan.org names as the #1 portability risk and which decision 2 took knowingly; embed is the answer that does not touch them at all.
11 lines
447 B
Plaintext
11 lines
447 B
Plaintext
;;;; A missing file with nothing handling it. spec-conditions.md §2: `error` is
|
|
;;;; the diverging variant, so the program stops on the frame that erred rather
|
|
;;;; than carrying on with a Vec that was never filled. The restarts are
|
|
;;;; offered whether or not anyone takes them — a break loop lists both.
|
|
(defn main [] i32
|
|
(println "before")
|
|
(let [v (slurp "programs/assets/does-not-exist")]
|
|
(println "unreachable")
|
|
(free v))
|
|
0)
|