tur/r7rs/prelude
the R7RS dialect's prelude: the core procedures.
Auto-loaded, LAST in the stdlib autoload list, when the ENTRY file is #lang r7rs (LangTraits.prelude). Read as R7RS itself so its bodies get Scheme truthiness and the Scheme reader; written in Turmeric's own shapes (defn, [...] parameter vectors, if) because every Turmeric form passes through the Scheme lowering untouched, and a prelude that reads as plainly as the stdlib it adapts is easier to keep honest.
NAMES. Every procedure here is spelled r7rs-<name>, never <name>: a top-level redefinition of an auto-loaded stdlib name (car, list, length, ...) is an error, and list.tur owns those on its carrier list. scheme_lower.c's rename table maps the Scheme spelling to the one here at every unquoted occurrence in a #lang r7rs file, so a Scheme program says (car l) and calls r7rs-car. A procedure added here is added to that table in the same change, or Scheme code cannot reach it.
REPRESENTATION (r7rs-lang-plan D3/D4, R3). Every Scheme type is an ordinary Turmeric type, and its predicate is is? against that type:
pair R7rsPair, a heap struct of two `any` fields (`a`/`d`: the
names `car`/`cdr` would meet the stdlib's `car` in `.field`
method lookup); mutable through `(set! (.a p) v)`, which is
the region-noted field store.
empty list R7rsNull, one process-wide value (r7rs-null-value__).
char R7rsChar, an opaque over the Unicode scalar value -- disjoint
from int, which is what `char?` vs `integer?` needs.
string Turmeric's cstr. R7RS strings are mutable and these are
not: `string-set!`/`string-fill!` are the one R7RS surface
this stage declines, and says so rather than aliasing.
vector (Vec any) -- `#(...)` reads as the same F_VEC `[...]` does.
bytevector R7rsBytevector over a (Vec int) of 0..255.
eof-object R7rsEof, one value.
symbol Sym (stdlib/sym.tur); `string->symbol` interns at runtime
through stdlib/sym-dynamic.tur, loaded below.
values R7rsValues over a Scheme list; `(values x)` is x itself.
quote builds these at runtime through r7rs-list / r7rs-cons / r7rs-vector / r7rs-char__ (scheme_lower.c's datum walker); the static .rodata table D4 wants is deferred with the literal-mutation question.
ADAPTORS, NOT REIMPLEMENTATIONS, on the Saffron prelude's rule: each of these forwards to a typed stdlib operation where one exists. The numeric surface is R5's, ports are R8's, error/raise are R6's.
Since: r7rs-lang-plan R2, R3
R7rsPair
(defstruct R7rsPair :heap [a :any d :any])
---- the types --------------------------------------------------------
R7rsNull
(defstruct R7rsNull [tag :int])
R7rsEof
(defstruct R7rsEof [tag :int])
R7rsChar
(defopaque R7rsChar :int)
R7rsBytevector
(defstruct R7rsBytevector :heap [bytes :(Vec int)])
R7rsValues
(defstruct R7rsValues [items :any])
R7rsError
(defstruct R7rsError :heap [message :any irritants :any kind :int])
the R7RS error object (R6): a message and a list of irritants. Declared here, ahead of display, because a typed parameter's forward declaration needs the struct to exist.
r7rs-error-object?
(r7rs-error-object? [x] :bool)
r7rs-error-object-message
(r7rs-error-object-message [e :R7rsError] :any)
r7rs-error-object-irritants
(r7rs-error-object-irritants [e :R7rsError] :any)
r7rs-error-kind__
(r7rs-error-kind__ [e :R7rsError] :int)
R7: 0 for error/raise, 1 a file error, 2 a read error; file-error? and read-error? answer from it.
r7rs-fail-any__
(r7rs-fail-any__ [msg :cstr] :any)
internal: an "it is an error" condition, in a position that needs an any. It raises an error object with this message, which a program can guard (r7rs-type-errors-are-uncatchable-panics), through r7rs-raise-type__ so that its callers stay out of CPS; the panic is only reached with no hook installed. (A bare (panic ...) in the value position of an any-returning function is emitted as a void return by the compiled back end, hence the helper.) -bool, -int and -cstr are its twins for other positions.
r7rs-signal__
(r7rs-signal__ [msg :cstr] :any)
internal: R10 -- an error a program can guard: raise an error object with this message. For "it is an error" conditions the procedure detects, where r7rs-fail-any__'s panic would end the program.
r7rs-fail-bool__
(r7rs-fail-bool__ [msg :cstr] :bool)
r7rs-type-name__
(r7rs-type-name__ [x])
internal: type-of as an any, so two names compare through the dynamic = (no static cstr equality is autoloaded).
r7rs-null?
(r7rs-null? [p] :bool)
#t for the empty list. The predicates are FUNCTIONS, and the rest of this file tests through them rather than with an inline (is? x T): the inline test narrows x to T in its then-branch, and a narrowed heap value is unique -- a second use of it is TUR-E0201 "cannot copy unique value". A call leaves x an any, and each later use crosses the seam on its own.
r7rs-pair?
(r7rs-pair? [p] :bool)
#t for a pair.
r7rs-cons
(r7rs-cons [a d] :any)
a fresh pair; the cdr may be anything (an improper list). Returns any, as does every procedure that hands out a pair: a statically typed heap struct is a unique value in Turmeric, and a Scheme variable holding one must be usable any number of times.
r7rs-car
(r7rs-car [p :R7rsPair] :any)
the fields. An any argument crosses the seam with one tag check; (car '()) is the checked-cast panic naming both types.
r7rs-cdr
(r7rs-cdr [p :R7rsPair] :any)
r7rs-set-car!
(r7rs-set-car! [p :R7rsPair v] :nil)
the mutators. (set! (.a p) v) is the region-noted field store (CLAUDE.md, Region Store Hooks), so a value built inside a with-region bracket and stored here blocks the rewind.
r7rs-set-cdr!
(r7rs-set-cdr! [p :R7rsPair v] :nil)
R7rsBox
(defstruct R7rsBox :heap [v :any])
internal: the heap cell of a set! variable a lambda captures (r7rs-lang-plan R10). A compiled closure copies the variables it captures, so without the cell (set! sum ...) inside a do loop or a for-each lambda updated the closure's copy and the enclosing procedure still read the old value. scheme_lower.c's assignment conversion binds such a variable to one of these; reads and set!s go through it.
r7rs-box__
(r7rs-box__ [x] :any)
r7rs-unbox__
(r7rs-unbox__ [b :R7rsBox] :any)
r7rs-box-set!__
(r7rs-box-set!__ [b :R7rsBox x] :nil)
r7rs-caar
(r7rs-caar [p] :any)
r7rs-cadr
(r7rs-cadr [p] :any)
r7rs-cdar
(r7rs-cdar [p] :any)
r7rs-cddr
(r7rs-cddr [p] :any)
r7rs-caddr
(r7rs-caddr [p] :any)
r7rs-snoc__
(r7rs-snoc__ [last x] :any)
internal: the (Cons any) cells a variadic any rest parameter arrives packed in, as a Scheme list. T8: the list builders that call no user procedure append at a tail pointer (r7rs-snoc__), so each is a self tail call the compiler lowers to a loop (map, which calls one, reverses instead -- see r7rs-map1__). The natural (R7rsPair x (self ...)) recursion used one C frame per element and overflowed the stack on a list of about a million, at every optimization level and on both back ends. Each builder makes its first pair itself, so no scratch head is allocated (a pair is never freed).
r7rs-chain->list-go__
(r7rs-chain->list-go__ [c :(Cons any) last] :any)
r7rs-chain->list__
(r7rs-chain->list__ [c :(Cons any)] :any)
r7rs-list
(r7rs-list [& xs :any] :any)
(list e ...).
r7rs-list-go__
(r7rs-list-go__ [slow fast] :bool)
#t for a proper list (terminates on a cycle: two cursors).
r7rs-list?
(r7rs-list? [p] :bool)
r7rs-length-go__
(r7rs-length-go__ [p n :int] :int)
the number of elements of a proper list.
r7rs-length
(r7rs-length [p] :int)
r7rs-list-tail
(r7rs-list-tail [p k :int] :any)
the list after its first k elements.
r7rs-list-ref
(r7rs-list-ref [p k :int] :any)
the k-th element, zero-based.
r7rs-append-go__
(r7rs-append-go__ [p b last] :any)
two lists, the first copied (quasiquote's splice).
r7rs-append2__
(r7rs-append2__ [a b] :any)
r7rs-append-all__
(r7rs-append-all__ [c :(Cons any)] :any)
the lists joined, each but the last copied (R7RS 6.4): (append) is (), (append x) is x, and the last may be any object.
r7rs-append
(r7rs-append [& ls :any] :any)
r7rs-reverse-go__
(r7rs-reverse-go__ [p acc] :any)
a reversed copy.
r7rs-reverse
(r7rs-reverse [p] :any)
r7rs-list-copy-go__
(r7rs-list-copy-go__ [p last] :any)
a shallow copy.
r7rs-list-copy
(r7rs-list-copy [p] :any)
r7rs-map1-go__
(r7rs-map1-go__ [f l acc] :any)
apply f to each element, into a fresh list (one list). map builds in reverse and reverses at the end, NOT at a tail pointer: f can capture a continuation, and re-entering it must not change a list map already returned (r7rs-continuations pins this). The accumulator a re-entry resumes from is shared, never mutated, and the final reverse is a fresh list each time.
r7rs-map1__
(r7rs-map1__ [f l] :any)
r7rs-for-each1__
(r7rs-for-each1__ [f l] :nil)
apply f to each element, for effect.
r7rs-any-null__
(r7rs-any-null__ [ls] :bool)
R7: true when any list in ls is exhausted (the multi-list map/for-each stop at the shortest, R7RS 6.10).
r7rs-cars-go__
(r7rs-cars-go__ [ls last] :any)
r7rs-cars__
(r7rs-cars__ [ls] :any)
r7rs-cdrs-go__
(r7rs-cdrs-go__ [ls last] :any)
r7rs-cdrs__
(r7rs-cdrs__ [ls] :any)
r7rs-head-of__
(r7rs-head-of__ [ls k :int] :any)
internal: the car of the k-th (0-based) list of ls.
r7rs-mapn-go__
(r7rs-mapn-go__ [f ls n :int acc] :any)
The many-list map and for-each call f on the heads of the lists INSIDE the loop body (T8). Calling it through r7rs-apply-list__, or any helper, made the step a call into a separate CPS procedure that resumed the loop from inside its own frame, so every element nested a C frame and a million-element (map + a b) overflowed at -O2. n is the number of lists: 1 (string-map and vector-map come here with one) to 8, the dynamic call's argument limit (TUR_FAT_SHIM_MAX_ARITY; apply's is the same, and past it apply packs the rest as a list). Only the CALL of f is spelled per arity; the heads past the fourth come through r7rs-head-of__, an argument, not a resume point (r7rs-map-for-each-at-most-four-sequences).
r7rs-mapn__
(r7rs-mapn__ [f ls] :any)
r7rs-for-eachn-go__
(r7rs-for-eachn-go__ [f ls n :int] :bool)
r7rs-for-eachn__
(r7rs-for-eachn__ [f ls] :nil)
r7rs-map
(r7rs-map [f l & more :any] :any)
(map f list1 list2 ...): R7: any number of lists, stopping at the shortest; the one-list case keeps its direct call.
r7rs-for-each
(r7rs-for-each [f l & more :any] :nil)
(for-each f list1 list2 ...), for effect.
r7rs-same-ref__
(r7rs-same-ref__ [a b] :bool)
internal: identity of two heap values (a pair, a vector, a bytevector, a record) by their carrier word. Inline C on the compiled path, a native under the interpreter; typed helpers per type would each need the seam's pointer cast, and this asks one question of the tagged words directly.
r7rs-same-pair__
(r7rs-same-pair__ [a b] :bool)
r7rs-char-code__
(r7rs-char-code__ [c :R7rsChar] :int)
internal, typed: a char's scalar value.
r7rs-eqv?
(r7rs-eqv? [a b] :bool)
R7RS 6.1: identity on booleans, numbers, characters, symbols and the empty list; pointer identity on pairs, vectors and records; two values of different runtime types are never eqv.
r7rs-eqv-by-value?__
(r7rs-eqv-by-value?__ [a] :bool)
internal: the types eqv? compares by value.
r7rs-eq?
(r7rs-eq? [a b] :bool)
same as eqv? here (chars and ints are immediate, and a bignum is compared by value, which R7RS allows of eq? on numbers).
r7rs-not
(r7rs-not [x] :bool)
#t only for #f (R7RS 6.3).
r7rs-memv
(r7rs-memv [x l])
---- membership and association ----------------------------------------
r7rs-memq
(r7rs-memq [x l])
r7rs-member-by__
(r7rs-member-by__ [x l eq] :any)
r7rs-member
(r7rs-member [x l & cmp :any] :any)
R7: an optional third argument is the equivalence.
r7rs-assv
(r7rs-assv [x l])
r7rs-assq
(r7rs-assq [x l])
r7rs-assoc-by__
(r7rs-assoc-by__ [x l eq] :any)
r7rs-assoc
(r7rs-assoc [x l & cmp :any] :any)
R7: an optional third argument is the equivalence.
r7rs-boolean?
(r7rs-boolean? [x] :bool)
---- type predicates ---------------------------------------------------
r7rs-string?
(r7rs-string? [x] :bool)
r7rs-symbol?
(r7rs-symbol? [x] :bool)
r7rs-procedure?
(r7rs-procedure? [x] :bool)
r7rs-char?
(r7rs-char? [x] :bool)
r7rs-vector?
(r7rs-vector? [x] :bool)
r7rs-bytevector?
(r7rs-bytevector? [x] :bool)
r7rs-eof-object?
(r7rs-eof-object? [x] :bool)
r7rs-values?__
(r7rs-values?__ [x] :bool)
r7rs-eof-object
(r7rs-eof-object)
r7rs-fixnum?__
(r7rs-fixnum?__ [x] :bool)
---- numbers (R5: the tower over int64 and double) --------------------
R7RS 6.2 over three representations: an exact integer is Turmeric's int64 when it fits and an R7rsBig when it does not (T1: exact integers are unbounded), and an inexact real is a double. There are no exact rationals yet (T2), so (/ 7 2) is the inexact 3.5 (not 7/2). The int64 path stays the fast one: +, -, * check for overflow and only then compute on bignums, and a bignum result that fits is an int again, so an R7rsBig is never a number int64 could hold. Exactness is the representation: exact? is an int or a bignum, inexact? a float, and the arithmetic on mixed operands is inexact. No complex numbers: (sqrt -4) is +nan.0.
The lowering routes every + - * / = < > <= >= in call position through the binary helpers here (r7rs-add2__ ...), folding n-ary uses and handling (+), (- x), (/ x); the variadic r7rs-+ ... are what a bare + in value position names, so (apply + xs) and (map + a b) work. The prelude itself is exempt from that rewrite (it is where the raw operators are allowed to appear), so the helpers below may use them. r7rs-fixnum?__ / r7rs-flonum?__ -- the representation tests; integer? is the R7RS predicate (7.0 is an integer) and is not the one to use to pick a printer.
r7rs-flonum?__
(r7rs-flonum?__ [x] :bool)
r7rs-float-nan?__
(r7rs-float-nan?__ [x :float] :bool)
r7rs-float-infinite?__
(r7rs-float-infinite?__ [x :float] :bool)
r7rs-float-integral?__
(r7rs-float-integral?__ [x :float] :bool)
r7rs-int->float__
(r7rs-int->float__ [x :int] :float)
r7rs-float->int__
(r7rs-float->int__ [x :float] :int)
an integral double as an int64, for an argument that must be one (an index, a count, a character code). T0: a double outside int64 is an error, where the C conversion saturated to a silent wrong answer. exact itself goes through r7rs-exact, which makes a bignum.
R7rsBig
(defstruct R7rsBig :heap [digits :cstr])
---- bignums (T1) ---------------------------------------------------------
An R7rsBig holds the canonical decimal spelling of an exact integer outside int64; the arithmetic is the C of stdlib/r7rs/bignum.tur (the interpreter's natives run the same file). r7rs-big-norm__ is the one constructor, so a value that fits is always an int.
r7rs-big?
(r7rs-big? [x] :bool)
r7rs-big-digits__
(r7rs-big-digits__ [b :R7rsBig] :cstr)
r7rs-big-norm__
(r7rs-big-norm__ [s :cstr] :any)
r7rs-big__
(r7rs-big__ [s :cstr] :any)
the reader's constructor: a literal outside int64 reads as (r7rs-big__ "<digits>"), as a char reads as (r7rs-char__ n).
r7rs-exint?
(r7rs-exint? [x] :bool)
an exact integer: an int or a bignum.
r7rs-any-big?__
(r7rs-any-big?__ [a b] :bool)
r7rs-any-exotic?__
(r7rs-any-exotic?__ [a b] :bool)
either operand is a bignum or a ratio: off the int64/double fast paths.
r7rs-dec__
(r7rs-dec__ [x] :cstr)
an exact integer's decimal spelling, for the bignum core.
r7rs-dec-done__
(r7rs-dec-done__ [x s :cstr] :nil)
T8: release what r7rs-dec__ made: an int's spelling is fresh, a bignum's is its own digits.
r7rs-big2__
(r7rs-big2__ [op :int a b] :any)
one bignum-core operation (the R7BN_* codes of bignum.tur) on two exact integers, normalized. The operand spellings are released, and so is the result's when it fits an int (a bignum keeps it).
r7rs-big-cmp-of__
(r7rs-big-cmp-of__ [a b] :int)
two exact integers compared by the core.
r7rs-big-cmp-float-of__
(r7rs-big-cmp-float-of__ [a d :float] :int)
r7rs-big-neg?__
(r7rs-big-neg?__ [x] :bool)
R7rsRatio
(defstruct R7rsRatio :heap [num :any den :any])
---- exact rationals (T2) ---------------------------------------------------
An R7rsRatio is an exact non-integer: numerator and denominator are exact integers (an int or a bignum), in lowest terms, the denominator greater than 1 and the sign on the numerator. r7rs-make-ratio__ is the one constructor, so a ratio is never a number an integer could be, and (/ 6 3) is the integer 2. Tests go through r7rs-ratio?, not a bare is?, which would narrow the value to the (unique) heap struct.
r7rs-ratio?
(r7rs-ratio? [x] :bool)
r7rs-ratio-num__
(r7rs-ratio-num__ [r :R7rsRatio] :any)
r7rs-ratio-den__
(r7rs-ratio-den__ [r :R7rsRatio] :any)
r7rs-exrat?
(r7rs-exrat? [x] :bool)
an exact rational: an exact integer or a ratio.
r7rs-num-of__
(r7rs-num-of__ [x] :any)
an exact rational's parts (an integer is itself over 1).
r7rs-den-of__
(r7rs-den-of__ [x] :any)
r7rs-make-ratio__
(r7rs-make-ratio__ [n d] :any)
n/d in lowest terms; n and d exact integers, d nonzero. An integer when d divides n.
r7rs-ratio-of-str__
(r7rs-ratio-of-str__ [s :cstr] :any)
the value of an "n/d" (or "n") spelling, as the number parser and the exact value of a double produce it.
r7rs-ratio__
(r7rs-ratio__ [s :cstr] :any)
the reader's constructor: an exact non-integer literal reads as (r7rs-ratio__ "<n>/<d>"), as a char reads as (r7rs-char__ n).
r7rs-exint-cmp__
(r7rs-exint-cmp__ [a b] :int)
two exact integers: -1, 0 or 1.
r7rs-rat-arith__
(r7rs-rat-arith__ [op :int a b] :any)
+ - * (op 0 1 2) on two exact rationals.
r7rs-rat-cmp__
(r7rs-rat-cmp__ [a b] :int)
two exact rationals, exactly: -1, 0 or 1 (the denominators are positive, so cross-multiplying keeps the order).
r7rs-cmp-rat-any__
(r7rs-cmp-rat-any__ [a b] :int)
a comparison with a ratio: against a double through the double's exact value; 2 when a double is a NaN.
R7rsComplex
(defstruct R7rsComplex :heap [re :any im :any])
---- complex numbers (T6) ------------------------------------------------
An R7rsComplex is a non-real number: its real and imaginary parts are reals (an int, a bignum, a ratio or a double). r7rs-make-rect__ is the one constructor, so an exact-zero imaginary part is always the real itself (R7RS 6.2.6), and a complex number is exact or inexact as a whole: when either part is inexact, both are. An inexact one keeps a 0.0 imaginary part, so (real? 1.0+0.0i) is #f. Tests go through r7rs-cplx?, not a bare is? (the unique-narrowing reason r7rs-ratio? gives).
r7rs-cplx?
(r7rs-cplx? [x] :bool)
r7rs-cplx-re__
(r7rs-cplx-re__ [z :R7rsComplex] :any)
r7rs-cplx-im__
(r7rs-cplx-im__ [z :R7rsComplex] :any)
r7rs-any-cplx?__
(r7rs-any-cplx?__ [a b] :bool)
r7rs-re-of__
(r7rs-re-of__ [x] :any)
any number's parts; a real's imaginary part is exact 0.
r7rs-im-of__
(r7rs-im-of__ [x] :any)
r7rs-exact-zero?__
(r7rs-exact-zero?__ [x] :bool)
r7rs-make-rect__
(r7rs-make-rect__ [re im] :any)
re + im i, from two reals.
r7rs-complex-of-str__
(r7rs-complex-of-str__ [s :cstr] :any)
the reader's constructor: a non-real literal reads as (r7rs-complex__ "<re> <im>"), each part a real's spelling.
r7rs-complex__
(r7rs-complex__ [s :cstr] :any)
r7rs-ratio-to-float__
(r7rs-ratio-to-float__ [n d] :float)
r7rs-to-float__
(r7rs-to-float__ [x] :float)
r7rs-real?
(r7rs-real? [x] :bool)
r7rs-number?
(r7rs-number? [x] :bool)
r7rs-complex?
(r7rs-complex? [x] :bool)
r7rs-real-finite?__
(r7rs-real-finite?__ [x] :bool)
T6: a complex number is finite when both parts are, infinite or a NaN when either is.
r7rs-finite?
(r7rs-finite? [x] :bool)
r7rs-real-infinite?__
(r7rs-real-infinite?__ [x] :bool)
r7rs-infinite?
(r7rs-infinite? [x] :bool)
r7rs-real-nan?__
(r7rs-real-nan?__ [x] :bool)
r7rs-nan?
(r7rs-nan? [x] :bool)
r7rs-rational?
(r7rs-rational? [x] :bool)
r7rs-integer?
(r7rs-integer? [x] :bool)
r7rs-exact?
(r7rs-exact? [x] :bool)
A complex number is exact or inexact as a whole (r7rs-make-rect__), so its real part answers for it.
r7rs-inexact?
(r7rs-inexact? [x] :bool)
r7rs-exact-integer?
(r7rs-exact-integer? [x] :bool)
r7rs-exact-rational?
(r7rs-exact-rational? [x] :bool)
r7rs-both-int?__
(r7rs-both-int?__ [a b] :bool)
---- exact arithmetic: int64, then bignums (T1) --------------------------
r7rs-big-arith__
(r7rs-big-arith__ [op :int a b] :any)
+ - * (op 0 1 2) with a bignum or ratio operand: inexact when the other one is, exact rationals (T2) when either is a ratio, else the bignum core.
r7rs-cplx-arith__
(r7rs-cplx-arith__ [op :int a b] :any)
T6: + - * on complex numbers, part by part through the real operators.
r7rs-real-arith__
(r7rs-real-arith__ [op :int a b] :any)
r7rs-intflo?__
(r7rs-intflo?__ [x] :bool)
the binary operators the lowering emits. Two ints take the int64 path unless it overflows (T1: then the bignum core, where D8 had a panic); a bignum operand goes to the core; two ints or doubles take the dynamic operator, which promotes a mixed pair to inexact; and anything else is not a number, the raised error ((+ 'a 1)) where the dynamic operator panicked.
r7rs-intflos?__
(r7rs-intflos?__ [a b] :bool)
r7rs-add2__
(r7rs-add2__ [a b] :any)
r7rs-sub2__
(r7rs-sub2__ [a b] :any)
r7rs-mul2__
(r7rs-mul2__ [a b] :any)
r7rs-div-exact__
(r7rs-div-exact__ [a b] :any)
T2: exact on exact operands, a ratio when the quotient is not an integer ((/ 7 2) is 7/2, where it was 3.5), and division by exact zero is an error. Two ints that divide stay on int64 (-1 aside: INT64_MIN / -1 leaves it).
r7rs-div2__
(r7rs-div2__ [a b] :any)
r7rs-cplx-div__
(r7rs-cplx-div__ [a b] :any)
T6: (a+bi)/(c+di) = ((ac+bd) + (bc-ad)i) / (c^2+d^2).
r7rs-cmp-int-float__
(r7rs-cmp-int-float__ [i :int d :float] :int)
R10: an exact integer and an inexact real compare EXACTLY (R7RS 6.2.6 asks comparisons to be transitive): (= 9007199254740992.0 9007199254740993) is #f, where converting the integer to a double made the two equal. r7rs-cmp-int-float__ answers -1, 0 or 1 for i against d, and 2 when d is a NaN (every comparison false).
r7rs-mixed?__
(r7rs-mixed?__ [a b] :bool)
r7rs-cmp-mixed__
(r7rs-cmp-mixed__ [a b] :int)
r7rs-cmp-big__
(r7rs-cmp-big__ [a b] :int)
against a double through the double's exact value -- so (= (- (expt 2 1000) 1) (inexact (expt 2 1000))) is #f. -1, 0 or 1, and 2 when a double is a NaN.
r7rs-cmp-slow__
(r7rs-cmp-slow__ [a b] :int)
r7rs-cmp-cplx__
(r7rs-cmp-cplx__ [a b] :int)
T6: complex numbers are equal part by part and otherwise unordered (2, as a NaN is): < on a non-real is #f.
r7rs-cmp-real__
(r7rs-cmp-real__ [a b] :int)
r7rs-slow?__
(r7rs-slow?__ [a b] :bool)
r7rs-cmp-error__
(r7rs-cmp-error__ [who :cstr a b] :bool)
The comparisons: two ints first, then the exact slow path, then two doubles; anything else is not a number, raised ((< 'a 1)).
r7rs-numeq2__
(r7rs-numeq2__ [a b] :bool)
r7rs-lt2__
(r7rs-lt2__ [a b] :bool)
r7rs-gt2__
(r7rs-gt2__ [a b] :bool)
r7rs-le2__
(r7rs-le2__ [a b] :bool)
r7rs-ge2__
(r7rs-ge2__ [a b] :bool)
r7rs-fold-num__
(r7rs-fold-num__ [f l acc])
The variadic procedures a bare operator names in value position.
r7rs-args__
(r7rs-args__ [xs :(Cons any)] :any)
r7rs-+
(r7rs-+ [& xs :any])
r7rs-*
(r7rs-* [& xs :any])
r7rs--
(r7rs-- [x & xs :any])
r7rs-/
(r7rs-/ [x & xs :any])
r7rs-chain-cmp__
(r7rs-chain-cmp__ [f x l] :bool)
r7rs-=
(r7rs-= [x & xs :any] :bool)
r7rs-<
(r7rs-< [x & xs :any] :bool)
r7rs->
(r7rs-> [x & xs :any] :bool)
r7rs-<=
(r7rs-<= [x & xs :any] :bool)
r7rs->=
(r7rs->= [x & xs :any] :bool)
r7rs-zero?
(r7rs-zero? [x] :bool)
---- predicates, min/max, abs ------------------------------------------- A bignum or a ratio is never zero (a zero is an int); a bignum's sign is its spelling's, a ratio's its numerator's.
r7rs-positive?
(r7rs-positive? [x] :bool)
r7rs-negative?
(r7rs-negative? [x] :bool)
r7rs-int-of__
(r7rs-int-of__ [x who :cstr] :int)
an integer argument that must fit int64 (an index, a count, a character code): a bignum there is the error who.
r7rs-exint-of__
(r7rs-exint-of__ [x who :cstr] :any)
an integer argument as an exact integer (an int or a bignum); an inexact integer converts exactly, anything else (a ratio, T2) is the error who. Raised through r7rs-fail-any__, not raise: this is reachable from = (through the exact comparison of a ratio and a double), and a raise there makes every procedure that compares numbers effectful, which compiles it to CPS and costs the tail-call trampoline (tests/fixtures/r7rs-tail-calls).
r7rs-fail-int__
(r7rs-fail-int__ [msg :cstr] :int)
r7rs-even?
(r7rs-even? [x] :bool)
an inexact integer is tested as a double, so a large one (1e30, which is even) needs no int64 conversion.
r7rs-odd?
(r7rs-odd? [x] :bool)
r7rs-abs
(r7rs-abs [x])
r7rs-min2__
(r7rs-min2__ [a b])
inexact contagion (R7RS 6.2.6): if any argument is inexact the result is inexact.
r7rs-max2__
(r7rs-max2__ [a b])
r7rs-any-inexact?__
(r7rs-any-inexact?__ [l] :bool)
r7rs-contagion__
(r7rs-contagion__ [r l])
r7rs-min
(r7rs-min [x & xs :any])
r7rs-max
(r7rs-max [x & xs :any])
r7rs-idiv-int__
(r7rs-idiv-int__ [op :int x :int y :int] :any)
quotient, remainder or modulo (the bignum core's codes 3, 4, 5) on two integers, exactly: int64 when both are ints (INT64_MIN / -1 is the one quotient that leaves int64, so -1 goes to the core), the bignum core otherwise.
r7rs-idiv-arg__
(r7rs-idiv-arg__ [x who :cstr] :any)
T8: the message is built only on the failing path (it was built, and leaked, on every call).
r7rs-idiv__
(r7rs-idiv__ [op :int a b who :cstr] :any)
r7rs-quotient-i__
(r7rs-quotient-i__ [a b] :any)
r7rs-remainder-i__
(r7rs-remainder-i__ [a b] :any)
r7rs-modulo-i__
(r7rs-modulo-i__ [a b] :any)
r7rs-floor-quotient-i__
(r7rs-floor-quotient-i__ [a b] :any)
r7rs-floor-remainder-i__
(r7rs-floor-remainder-i__ [a b] :any)
r7rs-truncate-quotient-i__
(r7rs-truncate-quotient-i__ [a b] :any)
r7rs-truncate-remainder-i__
(r7rs-truncate-remainder-i__ [a b] :any)
r7rs-idiv-result__
(r7rs-idiv-result__ [r a b] :any)
an inexact argument makes the result inexact (R7RS 6.2.6, (truncate/ -5.0 -2) is 2.0 and -1.0); the -i__ forms above compute on the exact integers.
r7rs-quotient
(r7rs-quotient [a b] :any)
r7rs-remainder
(r7rs-remainder [a b] :any)
r7rs-modulo
(r7rs-modulo [a b] :any)
r7rs-floor-quotient
(r7rs-floor-quotient [a b] :any)
r7rs-floor-remainder
(r7rs-floor-remainder [a b] :any)
r7rs-truncate-quotient
(r7rs-truncate-quotient [a b] :any)
r7rs-truncate-remainder
(r7rs-truncate-remainder [a b] :any)
r7rs-igcd__
(r7rs-igcd__ [a :int b :int] :int)
gcd and lcm on the bignum core (code 6); the answers are non-negative. T2: every ratio operation normalizes through gcd, so two ints (INT64_MIN aside, whose magnitude leaves int64) take Euclid's loop on int64.
r7rs-gcd2__
(r7rs-gcd2__ [a b] :any)
r7rs-gcd-go__
(r7rs-gcd-go__ [l acc] :any)
r7rs-gcd
(r7rs-gcd [& xs :any] :any)
r7rs-lcm2__
(r7rs-lcm2__ [a b] :any)
r7rs-lcm-go__
(r7rs-lcm-go__ [l acc] :any)
r7rs-lcm
(r7rs-lcm [& xs :any] :any)
r7rs-rat-floor__
(r7rs-rat-floor__ [x] :any)
---- rounding and exactness ---------------------------------------------- T2: a ratio rounds exactly to an exact integer: floor is the floor quotient of its parts (the denominator is positive), round takes ties to even.
r7rs-rat-round__
(r7rs-rat-round__ [x] :any)
r7rs-floor
(r7rs-floor [x] :any)
r7rs-ceiling
(r7rs-ceiling [x] :any)
r7rs-truncate
(r7rs-truncate [x] :any)
r7rs-round
(r7rs-round [x] :any)
to the nearest integer, ties to even (rint for a double).
r7rs-exact
(r7rs-exact [x] :any)
a finite double's exact value: an int, a bignum at any size (T1), or the ratio it is (T2: (exact .5) is 1/2; a double is a dyadic fraction, so (exact .3) is 5404319552844595/18014398509481984).
r7rs-exact-real__
(r7rs-exact-real__ [x] :any)
r7rs-inexact
(r7rs-inexact [x] :any)
r7rs-exact->inexact
(r7rs-exact->inexact [x])
r7rs-inexact->exact
(r7rs-inexact->exact [x])
r7rs-num-den__
(r7rs-num-den__ [x :float d :float] :any)
an exact integer is its own numerator over 1, and a ratio (T2) has its parts. R10: an inexact real is a dyadic fraction, so its lowest terms are found by doubling until it is integral -- (numerator 5.5) is 11.0 and (denominator 5.5) 2.0 -- with the answer inexact (R7RS 6.2.6).
r7rs-num-den-of__
(r7rs-num-den-of__ [x] :any)
r7rs-numerator
(r7rs-numerator [x] :any)
r7rs-denominator
(r7rs-denominator [x] :any)
r7rs-square
(r7rs-square [x])
---- powers, roots, transcendental --------------------------------------
r7rs-isqrt__
(r7rs-isqrt__ [n] :any)
floor of the square root of a non-negative exact integer, exact (the bignum core's code 8; Newton's iteration).
r7rs-exact-sqrt?__
(r7rs-exact-sqrt?__ [n] :bool)
exact when the argument is an exact perfect square (T2: or a ratio of two, (sqrt 4/9) is 2/3), else inexact. T6: a negative real has an imaginary root, exact when its negation's root is ((sqrt -4) is +2i), and a complex argument takes the principal root.
r7rs-sqrt
(r7rs-sqrt [x] :any)
r7rs-cf-re__
(r7rs-cf-re__ [z] :float)
---- complex transcendental (T6) -----------------------------------------
On doubles, part by part: r7rs-cf__ builds a+bi from two of them. A complex answer is inexact (R7RS 6.2.6 lets a transcendental function be).
r7rs-cf-im__
(r7rs-cf-im__ [z] :float)
r7rs-cf__
(r7rs-cf__ [a :float b :float] :any)
r7rs-cosh__
(r7rs-cosh__ [x :float] :float)
r7rs-sinh__
(r7rs-sinh__ [x :float] :float)
r7rs-cplx-sqrt__
(r7rs-cplx-sqrt__ [a :float b :float] :any)
the principal root of a+bi: the real part is never negative, and the imaginary part takes b's sign (-0.0 counts as +, so (sqrt -1.0-0.0i) is +1.0i, as the conformance suite has it).
r7rs-cplx-exp__
(r7rs-cplx-exp__ [z] :any)
r7rs-cplx-log__
(r7rs-cplx-log__ [z] :any)
log|z| + i arg z, the principal branch; a negative real lands here too, with arg pi.
r7rs-cplx-sin__
(r7rs-cplx-sin__ [z] :any)
r7rs-cplx-cos__
(r7rs-cplx-cos__ [z] :any)
r7rs-cplx-asin__
(r7rs-cplx-asin__ [z] :any)
asin z = -i log(iz + sqrt(1 - z^2)); acos z = pi/2 - asin z; atan z = (log(1 + iz) - log(1 - iz)) / 2i.
r7rs-cplx-atan__
(r7rs-cplx-atan__ [z] :any)
r7rs-int->string-radix__
(r7rs-int->string-radix__ [x :int radix :int] :cstr)
---- number <-> string ---------------------------------------------------
r7rs-radix-of__
(r7rs-radix-of__ [xs :(Cons any) who :cstr] :int)
r7rs-number->string
(r7rs-number->string [x & xs :any] :cstr)
r7rs-cplx->string__
(r7rs-cplx->string__ [z radix :int] :cstr)
T6: <re><sign><im>i, the imaginary part signed ("+inf.0" and "-2" already are). As chibi writes it, an exact-zero real part is left out and an exact unit imaginary part is bare: +2i, 1-i, +i. An inexact zero real part stays, so 0.0+1.0i reads back inexact.
r7rs-cplx-im-spelling__
(r7rs-cplx-im-spelling__ [im radix :int] :cstr)
the signed imaginary part and its i, fresh.
r7rs-join-fresh__
(r7rs-join-fresh__ [a :cstr sep :cstr b :cstr] :cstr)
T8: a ++ sep ++ b, freeing the fresh a and b (sep is a literal).
r7rs-exact-unit?__
(r7rs-exact-unit?__ [x v :int] :bool)
r7rs-fail-cstr__
(r7rs-fail-cstr__ [msg :cstr] :cstr)
r7rs-number-of__
(r7rs-number-of__ [s :cstr radix :int who :cstr] :any)
internal: T0 -- s read as a number in radix, through the one R7RS number parser (stdlib/r7rs/numsyntax.tur, the source reader's too): the number, #f when s is not number syntax, and an error a program can guard -- who and the reason -- when s IS a number the tower cannot hold. A long integer is a bignum (T1), 1/2 a ratio (T2) and 1+2i a complex number (T6). Never a different number.
r7rs-number-syntax?__
(r7rs-number-syntax?__ [s :cstr] :bool)
internal: s is number syntax at all, refused or not (write bars such a symbol: '|1/2|).
r7rs-string->number
(r7rs-string->number [s0 & xs :any])
#f when the string is not a number in the radix.
r7rs-char__
(r7rs-char__ [c :int] :R7rsChar)
the reader's constructor: #\a reads as (r7rs-char__ 97).
r7rs-char->integer
(r7rs-char->integer [c :R7rsChar] :int)
r7rs-integer->char
(r7rs-integer->char [n :int] :R7rsChar)
r7rs-char=2__
(r7rs-char=2__ [a :R7rsChar b :R7rsChar] :bool)
r7rs-char<2__
(r7rs-char<2__ [a :R7rsChar b :R7rsChar] :bool)
r7rs-char>2__
(r7rs-char>2__ [a :R7rsChar b :R7rsChar] :bool)
r7rs-char<=2__
(r7rs-char<=2__ [a :R7rsChar b :R7rsChar] :bool)
r7rs-char>=2__
(r7rs-char>=2__ [a :R7rsChar b :R7rsChar] :bool)
r7rs-char=?
(r7rs-char=? [a b & xs :any] :bool)
The char comparisons take two or more arguments (R7: they were binary).
r7rs-char<?
(r7rs-char<? [a b & xs :any] :bool)
r7rs-char>?
(r7rs-char>? [a b & xs :any] :bool)
r7rs-char<=?
(r7rs-char<=? [a b & xs :any] :bool)
r7rs-char>=?
(r7rs-char>=? [a b & xs :any] :bool)
r7rs-char-upcase
(r7rs-char-upcase [c :R7rsChar] :R7rsChar)
(scheme char): ASCII answers inline, everything else from the Unicode tables of stdlib/r7rs/unicode.tur (R10; generated, see tools/gen-r7rs-unicode.py).
r7rs-char-downcase
(r7rs-char-downcase [c :R7rsChar] :R7rsChar)
r7rs-char-alphabetic?
(r7rs-char-alphabetic? [c :R7rsChar] :bool)
r7rs-char-numeric?
(r7rs-char-numeric? [c :R7rsChar] :bool)
r7rs-char-whitespace?
(r7rs-char-whitespace? [c :R7rsChar] :bool)
r7rs-blen__
(r7rs-blen__ [s :cstr] :int)
---- strings: the byte-level primitives (inline C with interpreter twins in interpreter_natives.c) ---------------------------------------------------
T3: these count and cut BYTES of a cstr. The prelude uses them on text it built itself (tokens, escapes, number spellings); a Scheme program's strings go through the character-level procedures of the T3 section below. r7rs-blen__ -- a cstr's length in bytes.
r7rs-utf8-count__
(r7rs-utf8-count__ [s :cstr] :int)
T3: the number of characters in UTF-8 text.
r7rs-utf8-at__
(r7rs-utf8-at__ [s :cstr off :int] :int)
T3: the character at byte offset off of UTF-8 text and its width, packed as scalar * 8 + width (a stray byte is itself, width 1).
r7rs-utf8-ref__
(r7rs-utf8-ref__ [s :cstr i :int] :int)
T3: the scalar value of the i-th character of UTF-8 text (a scan from the start: a literal is short, and a program that indexes a long string builds a mutable one).
r7rs-string-ref-code__
(r7rs-string-ref-code__ [s :cstr i :int] :int)
r7rs-cstr-free__
(r7rs-cstr-free__ [s :cstr] :nil)
T8: release a scratch string the caller made and no value holds (a spelling already copied into a port buffer, a decimal spelling the bignum core has read). Never a string a Scheme value owns.
r7rs-string-append2__
(r7rs-string-append2__ [a :cstr b :cstr] :cstr)
r7rs-bsubstring__
(r7rs-bsubstring__ [s :cstr start :int end :int] :cstr)
r7rs-cstr<__
(r7rs-cstr<__ [a :cstr b :cstr] :bool)
r7rs-string-of-code__
(r7rs-string-of-code__ [c :int] :cstr)
r7rs-int->string__
(r7rs-int->string__ [x :int] :cstr)
r7rs-float->string__
(r7rs-float->string__ [x :float] :cstr)
r7rs-range-start__
(r7rs-range-start__ [r] :int)
R7: the optional [start [end]] tail most sequence procedures take, defaulting to 0 and len.
r7rs-range-end__
(r7rs-range-end__ [r len :int] :int)
r7rs-range-check__
(r7rs-range-check__ [who :cstr start :int end :int len :int] :nil)
A range out of bounds raises an error object a program can guard, the start and end its irritants (r7rs-srfi-plan S7; it was a panic, docs/reported/r7rs-type-errors-are-uncatchable-panics.md).
R7rsString
(defstruct R7rsString :heap [cps :(Vec int)])
---- strings (T3): characters, and mutable ones ---------------------------
A Scheme string is one of two things. A literal -- and a string from Turmeric, symbol->string, number->string, the case procedures, read -- is a cstr: immutable UTF-8, which R7RS allows of a literal. A string a procedure newly allocates -- make-string, string, string-copy, substring, string-append, list->string, vector->string, string-map, utf8->string, read-string -- is an R7rsString: its characters as code points in a vector, so string-ref and string-set! are constant time. Every string procedure takes either and counts characters, never bytes: (string-length "\x3BB;") is 1. Turmeric's cstr is unchanged (9.1): an R7rsString crosses into a Turmeric cstr parameter as a fresh UTF-8 copy (the elaborator's Scheme seam calls r7rs-str__, elab_call.c), and mutating a cstr string is the named error. Tests go through r7rs-mstring?, not a bare is?, which would narrow the value to the (unique) heap struct.
r7rs-mstring?
(r7rs-mstring? [x] :bool)
r7rs-mstring-cps__
(r7rs-mstring-cps__ [s :R7rsString] :(Vec int))
r7rs-mk-string__
(r7rs-mk-string__ [v :(Vec int)] :any)
r7rs-cps-go__
(r7rs-cps-go__ [s :cstr off :int n :int v :(Vec int)] :(Vec int))
UTF-8 text's characters as a fresh code-point vector. A cstr is walked by byte offset (r7rs-utf8-at__ answers the character there and its width); a port buffer would do the decoding too, but an R7rsIo is a unique handle, and a loop that reads from it and passes it on uses it twice where a Turmeric entry checks ownership.
r7rs-cps-of-cstr__
(r7rs-cps-of-cstr__ [s :cstr] :(Vec int))
r7rs-cps__
(r7rs-cps__ [s] :(Vec int))
any string's characters: an R7rsString's own vector (read it, do not keep it), a cstr's decoded afresh.
r7rs-str__
(r7rs-str__ [x] :cstr)
characters [a, b) of a code-point vector as UTF-8, by halves (each byte is copied log n times, never n). r7rs-str__ -- any string as a cstr: a cstr is itself, an R7rsString is encoded afresh. The conversion at every seam: the prelude's own C and ports take cstr, and the elaborator calls it where a Scheme call passes a string to a Turmeric cstr parameter.
r7rs-cps-range-go__
(r7rs-cps-range-go__ [v :(Vec int) i :int end :int out :(Vec int)] :(Vec int))
characters [a, b) of a vector as a fresh vector.
r7rs-cps-range__
(r7rs-cps-range__ [v :(Vec int) a :int b :int] :(Vec int))
r7rs-immutable__
(r7rs-immutable__ [who :cstr] :nil)
the named error for mutating a cstr-backed string.
r7rs-fail-nil__
(r7rs-fail-nil__ [msg :cstr] :nil)
r7rs-fail-char__
(r7rs-fail-char__ [msg :cstr] :R7rsChar)
r7rs-string-length
(r7rs-string-length [s] :int)
r7rs-string-ref
(r7rs-string-ref [s i :int] :R7rsChar)
r7rs-string-set!
(r7rs-string-set! [s i :int c :R7rsChar] :nil)
T3: the mutators, on an R7rsString; a cstr-backed string is the named error.
r7rs-fill-go__
(r7rs-fill-go__ [v :(Vec int) i :int end :int c :int] :nil)
r7rs-string-fill!
(r7rs-string-fill! [s c :R7rsChar & r :any] :nil)
r7rs-copy-fwd__
(r7rs-copy-fwd__ [dst :(Vec int) at :int src :(Vec int) i :int end :int] :nil)
string-copy! copies front to back when the destination starts at or before the source and back to front otherwise, so a copy within one string is right when the ranges overlap (R7RS 6.7).
r7rs-copy-bwd__
(r7rs-copy-bwd__ [dst :(Vec int) at :int src :(Vec int) start :int i :int] :nil)
r7rs-string-copy!
(r7rs-string-copy! [to at :int from & r :any] :nil)
r7rs-string-append-go__
(r7rs-string-append-go__ [c :(Cons any) out :(Vec int)] :(Vec int))
r7rs-string-append
(r7rs-string-append [& xs :any] :any)
a new (mutable) string.
r7rs-string-copy
(r7rs-string-copy [s & r :any] :any)
a new (mutable) string of the characters [start, end).
r7rs-substring
(r7rs-substring [s start :int end :int] :any)
r7rs-string<2__
(r7rs-string<2__ [a b] :bool)
The string comparisons take two or more arguments (R7). Characters compare by scalar value, which is UTF-8's byte order, so both sides are compared as UTF-8.
r7rs-string=2__
(r7rs-string=2__ [a b] :bool)
r7rs-string>2__
(r7rs-string>2__ [a b] :bool)
r7rs-string<=2__
(r7rs-string<=2__ [a b] :bool)
r7rs-string>=2__
(r7rs-string>=2__ [a b] :bool)
r7rs-string=?
(r7rs-string=? [a b & xs :any] :bool)
r7rs-string<?
(r7rs-string<? [a b & xs :any] :bool)
r7rs-string>?
(r7rs-string>? [a b & xs :any] :bool)
r7rs-string<=?
(r7rs-string<=? [a b & xs :any] :bool)
r7rs-string>=?
(r7rs-string>=? [a b & xs :any] :bool)
r7rs-string->symbol
(r7rs-string->symbol [s] :Sym)
r7rs-symbol->string
(r7rs-symbol->string [s :Sym] :cstr)
r7rs-string->list-acc__
(r7rs-string->list-acc__ [v :(Vec int) i :int j :int acc] :any)
a loop (see r7rs-snoc__).
r7rs-string->list-go__
(r7rs-string->list-go__ [v :(Vec int) i :int end :int] :any)
r7rs-string->list
(r7rs-string->list [s & r :any] :any)
r7rs-list->string-go__
(r7rs-list->string-go__ [l out :(Vec int)] :(Vec int))
r7rs-list->string
(r7rs-list->string [l] :any)
a new (mutable) string of the chars.
r7rs-vector-from-chain__
(r7rs-vector-from-chain__ [c :(Cons any) v :(Vec any)] :(Vec any))
---- vectors and bytevectors -------------------------------------------
r7rs-vector
(r7rs-vector [& xs :any] :(Vec any))
r7rs-make-vector-go__
(r7rs-make-vector-go__ [n :int fill v :(Vec any)] :(Vec any))
r7rs-make-vector
(r7rs-make-vector [n :int & fill :any] :(Vec any))
r7rs-index-error__
(r7rs-index-error__ [who :cstr v i :int] :any)
An index out of range raises an error object a program can guard (SRFI 64's test-error tests exactly this), where vec-get's own check panics (docs/reported/r7rs-type-errors-are-uncatchable-panics.md).
r7rs-vector-ref
(r7rs-vector-ref [v :(Vec any) i :int] :any)
r7rs-vector-set!
(r7rs-vector-set! [v :(Vec any) i :int x] :nil)
r7rs-vector-length
(r7rs-vector-length [v :(Vec any)] :int)
r7rs-vector->list-acc__
(r7rs-vector->list-acc__ [v :(Vec any) i :int j :int acc] :any)
r7rs-vector->list-go__
(r7rs-vector->list-go__ [v :(Vec any) i :int end :int] :any)
r7rs-vector->list
(r7rs-vector->list [v :(Vec any) & r :any] :any)
r7rs-list->vector-go__
(r7rs-list->vector-go__ [l v :(Vec any)] :(Vec any))
r7rs-list->vector
(r7rs-list->vector [l] :(Vec any))
r7rs-vector-fill-go__
(r7rs-vector-fill-go__ [v :(Vec any) x i :int end :int] :nil)
r7rs-vector-fill!
(r7rs-vector-fill! [v :(Vec any) x & r :any] :nil)
r7rs-byte?__
(r7rs-byte?__ [x] :bool)
A byte outside 0..255, or not an exact integer, raises an error object a program can guard, as an index out of range does (r7rs-srfi-plan S7: SRFI 4 and 66 range-check their octets through these).
r7rs-byte-error__
(r7rs-byte-error__ [who :cstr x] :any)
r7rs-bytes-from-chain__
(r7rs-bytes-from-chain__ [c :(Cons any) v :(Vec int)] :(Vec int))
r7rs-bytevector
(r7rs-bytevector [& xs :any] :any)
r7rs-make-bytevector-go__
(r7rs-make-bytevector-go__ [n :int fill :int v :(Vec int)] :(Vec int))
r7rs-make-bytevector
(r7rs-make-bytevector [n :int & fill :any] :any)
r7rs-bytevector-bytes__
(r7rs-bytevector-bytes__ [b :R7rsBytevector] :(Vec int))
r7rs-bytevector-u8-ref
(r7rs-bytevector-u8-ref [b :R7rsBytevector i :int] :int)
r7rs-bytevector-u8-set!
(r7rs-bytevector-u8-set! [b :R7rsBytevector i :int x] :nil)
r7rs-bytevector-length
(r7rs-bytevector-length [b :R7rsBytevector] :int)
r7rs-values
(r7rs-values [& xs :any])
---- multiple values (plan Section 8, Q1: a carrier over a list) --------
r7rs-values-items__
(r7rs-values-items__ [v :R7rsValues] :any)
r7rs-floor/
(r7rs-floor/ [a b])
R5: the procedures that return two values sit after r7rs-values. (They had to, then: a variadic's forward declaration did not carry its rest parameter. R7 fixed that, so the ordering is now only tidiness.)
r7rs-truncate/
(r7rs-truncate/ [a b])
r7rs-exact-integer-sqrt
(r7rs-exact-integer-sqrt [x])
r7rs-expt-exact__
(r7rs-expt-exact__ [b e] :any)
exact for an exact base and a non-negative exact exponent (the bignum core's code 7, square-and-multiply; T1: any size, where D8 stopped at int64); inexact through pow otherwise. An exponent outside int64 is refused unless the base is 0, 1 or -1: the answer could not be stored.
r7rs-expt
(r7rs-expt [b e] :any)
T2: an exact base to a negative exact integer power is the exact reciprocal, (expt 2 -10) is 1/1024.
r7rs-cplx-expt?__
(r7rs-cplx-expt?__ [b e] :bool)
T6: a complex base or exponent, or a negative base to a non-integer power, is complex: square-and-multiply for an exact complex base and a fixnum exponent ((expt +i 2) is -1), else exp(e log b). Zero to any power is 0 (1 when the power is zero).
r7rs-expt-mul__
(r7rs-expt-mul__ [b e :int acc] :any)
r7rs-cplx-expt__
(r7rs-cplx-expt__ [b e] :any)
r7rs-exp
(r7rs-exp [x] :any)
r7rs-log1__
(r7rs-log1__ [x] :any)
T6: a negative real's logarithm is complex (log|x| + pi i); the two-argument form is the quotient of two logarithms.
r7rs-log
(r7rs-log [x & xs :any] :any)
r7rs-sin
(r7rs-sin [x] :any)
r7rs-cos
(r7rs-cos [x] :any)
r7rs-tan
(r7rs-tan [x] :any)
r7rs-real-unit?__
(r7rs-real-unit?__ [x] :bool)
asin and acos leave the reals outside [-1, 1] (T6: (asin 2) is complex).
r7rs-asin
(r7rs-asin [x] :any)
r7rs-acos
(r7rs-acos [x] :any)
r7rs-atan
(r7rs-atan [y & xs :any] :any)
r7rs-values-ref
(r7rs-values-ref [v i :int] :any)
r7rs-values-rest
(r7rs-values-rest [v i :int] :any)
r7rs-apply-list__
(r7rs-apply-list__ [f l] :any)
call f with the elements of l as its arguments. Up to eight through the dynamic call (emit_dyn_call's helpers carry eight, and the prelude is compiled on both back ends, so the limit is the compiled one); R6: a variadic f is fine -- the dynamic call packs the surplus arguments into its rest list. Past eight, r7rs-apply-long__.
r7rs-apply-long__
(r7rs-apply-long__ [f l n :int] :any)
internal: apply past eight arguments (r7rs-apply-variadic-over-eight-arguments). The dynamic call's helpers carry eight arguments, but a variadic f needs only its fixed ones spread: the rest of the list becomes its rest argument directly. +, max, append, string-append and a program's own (define (f . xs) ...) are all variadic; a fixed-arity f with more than eight parameters is still refused.
r7rs-variadic-fixed__
(r7rs-variadic-fixed__ [f] :int)
internal: a variadic procedure's count of fixed parameters, or -1 (not a registered variadic: emit_module.c's __tur_dyn_reg_variadic table, which every boxed variadic type joins).
r7rs-call-variadic__
(r7rs-call-variadic__ [f fixed :int n :int l] :any)
internal: call the variadic f (fixed fixed parameters, fixed <= 8) on the n elements of the list l: the first fixed as its arguments, the rest packed by the dynamic call's own __tur_dyn_pack_rest into the rest chain.
r7rs-spread-args-go__
(r7rs-spread-args-go__ [l last] :any)
(a b (c d)) to (a b c d): every argument but the last, then the last as the tail.
r7rs-spread-args__
(r7rs-spread-args__ [l] :any)
r7rs-apply
(r7rs-apply [f & args :any] :any)
(apply f a ... l): R7: the leading arguments are consed onto the final list.
r7rs-call-with-values
(r7rs-call-with-values [producer consumer])
r7rs-exit__
(r7rs-exit__ [code :int] :nil)
internal: flush and leave with a status.
r7rs-void
(r7rs-void)
the unspecified value.
r7rs-dyn-ref__
(r7rs-dyn-ref__ [i :int] :any)
---- control (R6) ------------------------------------------------------
Continuations are Turmeric's call/cc -- one-shot, upward, an escape -- wrapped so Scheme sees a procedure (plan D7). dynamic-wind keeps a wind stack that an escape unwinds; exceptions are a handler stack over the same escapes (D10 named effects, but a handle around a dynamic thunk is not lowered by the compiled back end, and the escape encoding is exactly what R7RS 6.11 describes); parameterize binds a parameter's cell under dynamic-wind; a promise is a shared box. ---- the dynamic environment ----------------------------------------------
The wind stack, the handler stack, parameterize's bindings and the value a re-entered continuation delivers belong to the code that is running, not to the program: they live in tur_r7rs_dyn (emit_dk_runtime.c), one per thread and one per fiber (tur_fiber_block_resume swaps it). As process globals, a raise on one thread called a handler another thread had installed, and a pop on one removed another's (docs/archive/r7rs-dynamic-environment-shared-across-threads.md). A slot that was never written is all zero, which reads as the empty list. r7rs-dyn-ref__ -- internal: slot i of the running code's dynamic environment -- 0 the wind stack, 1 the handler stack, 2 the parameter bindings, 3 a re-entry's delivered value.
r7rs-dyn-set__
(r7rs-dyn-set__ [i :int v] :nil)
internal: set slot i. The slot outlives any region bracket, so the word is noted (the region store-hook rule).
r7rs-dyn-unset?__
(r7rs-dyn-unset?__ [v] :bool)
internal: #t for a slot never written (all zero).
r7rs-dyn-list__
(r7rs-dyn-list__ [i :int] :any)
internal: slot i as a Scheme list.
R7rsWind
(defstruct R7rsWind :heap [before :any after :any])
one dynamic-wind frame: its before and after thunks.
r7rs-winders__
(r7rs-winders__ :any)
the wind stack, innermost first, as a Scheme list.
r7rs-winders-set!__
(r7rs-winders-set!__ [v] :nil)
r7rs-wind-after__
(r7rs-wind-after__ [w :R7rsWind] :any)
r7rs-dynamic-wind
(r7rs-dynamic-wind [before thunk after] :any)
run before, thunk, after; the frame is on the wind stack while thunk runs, so an escape out of thunk runs after.
r7rs-rewind-to__
(r7rs-rewind-to__ [saved] :nil)
internal: pop wind frames, running each after, until the stack is the one captured with the continuation. The saved stack is always a tail of the current one for an escape; if it is not reached the continuation is being re-entered, which the underlying escape reports itself.
r7rs-values-of-list__
(r7rs-values-of-list__ [l] :any)
internal: the value a (values ...) denotes: one value is itself, any other count is the R7rsValues carrier.
r7rs-call/ec__
(r7rs-call/ec__ [f] :any)
internal: an ESCAPE-only call/cc (R6, D7). The receiver gets a variadic procedure; invoking it unwinds the wind stack to the capture point and delivers its arguments as the value of the call. Invoking it after the call has returned is the named error "continuation invoked after its call/cc prompt returned". guard and the eval bridge escape through this, which costs nothing per call; the public call/cc below is re-entrant and copies the stack.
r7rs-cont-save-state
(r7rs-cont-save-state [p :ptr<void>] :nil)
---- T5: re-entrant continuations ----------------------------------------
A continuation is a copy of the C stack from the call/cc to the stack's base, taken when call/cc is called, plus the runtime state that tracks the stack (the tail-call trampoline, the CPS driver, the live escapes). Invoking it travels the wind stack to the captured one -- after thunks out, before thunks in -- then copies the stack back and jumps into it, so the call/cc returns again, however many times and whenever. Heap data is shared, as Scheme requires: a continuation restores control, not state. This is the classic copying implementation (SCM, early Guile); it keeps every frame between the call/cc and the base, C frames included, which is what a Scheme continuation is. Where the stack's base cannot be found the public call/cc is the escape above. r7rs-cont-save-state -- internal: record the runtime's per-thread state in a capture: the tail-call trampoline's root and armed callee, the CPS driver's landing and entry depth, and the live escapes.
(No __ suffix: an inline-C __TUR_CNAME_ splice ends at the first __.) This and r7rs-cont-load-state are their own functions, called from the capture through volatile pointers so that no compiler inlines them back: the function that calls setjmp must not touch a thread-local itself. Apple's arm64 clang, after setjmp's second return (a re-entry), stored to a thread-local through a stale address -- a write into the program's text that ended the program -- once the CPS state joined the trampoline's among the thread-locals (docs/archive/dk-reap-list-shared-across-threads.md). Out here each access computes its address afresh.
r7rs-cont-load-state
(r7rs-cont-load-state [p :ptr<void>] :nil)
internal: put a capture's per-thread state back on a re-entry (see r7rs-cont-save-state).
r7rs-cont-capture__
(r7rs-cont-capture__ :ptr<void>)
internal: capture; returns the handle, and returns AGAIN, tagged (low bit set), each time the continuation is re-entered.
r7rs-cont-resumed?__
(r7rs-cont-resumed?__ [c :ptr<void>] :bool)
internal: #t for the tagged handle a re-entry returns.
r7rs-cont-null?__
(r7rs-cont-null?__ [c :ptr<void>] :bool)
internal: #t when no copy could be taken (no stack base on this platform).
r7rs-cont-here?__
(r7rs-cont-here?__ [c :ptr<void>] :bool)
internal: #t when the calling thread is the one that captured the continuation. Its image is a copy of that thread's stack at that thread's addresses, so a jump into it from any other thread would copy one thread's frames over another's.
r7rs-cont-check-here__
(r7rs-cont-check-here__ [c :ptr<void>] :nil)
internal: raise an error object, one a program can guard, when a continuation is invoked on a thread other than the one that captured it. Checked before the wind travel, so no before or after thunk runs for a jump that is refused.
r7rs-cont-resumable?__
(r7rs-cont-resumable?__ [c :ptr<void>] :bool)
internal: #f when the (scheme eval) evaluator cannot resume its side of the continuation: one captured inside a host call made from a text being evaluated ((eval '(f 1)), as against an applied procedure) can be re-entered only while that evaluation is still in progress -- its frames end with the eval, and resumed after it returned they would finish the evaluation a second time.
r7rs-cont-check-resumable__
(r7rs-cont-check-resumable__ [c :ptr<void>] :nil)
internal: the error object a program can guard for that case. Checked before the wind travel, with the thread check.
r7rs-cont-restore__
(r7rs-cont-restore__ [c :ptr<void>] :nil)
internal: copy the captured stack back and jump in.
r7rs-cont-hooks-install__
(r7rs-cont-hooks-install__ [capture :ptr<void> resumable :ptr<void> restore :ptr<void> resumed :ptr<void>] :bool)
internal: point the capture above at the (scheme eval) evaluator's continuation hooks (src/turi/r7rs_embed.h): capture, resumable, restore, resumed. Run once, at startup, by stdlib/r7rs/eval.tur; the interpreter's twin does nothing, since its capture reaches the evaluator directly.
r7rs-cont-delivered__
(r7rs-cont-delivered__ :any)
the value an invoked continuation hands its call/cc; set just before the jump, read just after it, on one thread.
r7rs-cont-deliver!__
(r7rs-cont-deliver!__ [v] :nil)
r7rs-run-toplevel-thunk
(r7rs-run-toplevel-thunk [thunk] :nil)
internal: call a top-level form's thunk. Its own function so the runner below can call it by C name from inline C.
r7rs-run-toplevel-thunk-ptr
(r7rs-run-toplevel-thunk-ptr [p :ptr<void>] :nil)
internal: the trampoline r7k_run_form calls, void (*)(void *), over the thunk's address.
r7rs-toplevel__
(r7rs-toplevel__ [thunk] :nil)
internal: run one top-level form under its own prompt (r7rs-toplevel-reentry-reruns-forms). The Scheme lowering wraps every statement of a program in it. A continuation captured inside the form copies the stack only up to the mark r7k_run_form takes (r7k_measure), so a re-entry from a later form restores this form's frames over that form's -- every statement is called from the same depth, so the mark is the same address for each -- finishes this form, and returns into the runner frame of the INVOKING form, which carries on after it: the way chibi's loader and Racket's per-form prompt behave. The mark lives in r7k_run_form, reached through a volatile function pointer so that no compiler folds that frame into the program's main (see its comment).
r7rs-wind-depth__
(r7rs-wind-depth__ [l] :int)
internal: a wind stack's length.
r7rs-wind-drop__
(r7rs-wind-drop__ [l n :int] :any)
r7rs-wind-common__
(r7rs-wind-common__ [a b] :any)
internal: the longest common tail of two wind stacks.
r7rs-wind-before__
(r7rs-wind-before__ [w :R7rsWind] :any)
r7rs-rewind-into__
(r7rs-rewind-into__ [target common] :nil)
internal: enter the frames of target above common, outermost first: each before runs, then its frame is pushed.
r7rs-travel-to__
(r7rs-travel-to__ [target] :nil)
internal: R7RS 6.10 -- leave the current extent to the common ancestor (each after, innermost first), then enter the target's (each before, outermost first).
r7rs-call/cc
(r7rs-call/cc [f] :any)
r7rs-read-error?
(r7rs-read-error? [x] :bool)
R7: an error object of that kind; (scheme file) raises file errors, the reader's arrive with R8.
r7rs-file-error?
(r7rs-file-error? [x] :bool)
r7rs-handlers__
(r7rs-handlers__ :any)
the exception handler stack, innermost first.
r7rs-handlers-set!__
(r7rs-handlers-set!__ [v] :nil)
r7rs-with-exception-handler
(r7rs-with-exception-handler [handler thunk] :any)
install handler for the extent of thunk. The install and the uninstall are wind frames, so an escape out of thunk leaves the stack as it found it.
r7rs-raise-continuable
(r7rs-raise-continuable [obj] :any)
call the innermost handler with obj, with the outer handlers installed while it runs (R7RS 6.11); its value is the value of the raise.
r7rs-raise
(r7rs-raise [obj] :any)
like raise-continuable, but a handler that returns is an error: a secondary exception is raised to the outer handlers.
r7rs-error
(r7rs-error [msg & irritants :any] :any)
R7RS error: raise a fresh error object.
r7rs-type-error-message__
(r7rs-type-error-message__ [who :cstr what :cstr] :cstr)
internal: a value of the wrong type reached a typed prelude procedure -- (car 5). Raise an error object, "car: not a pair" with the value as its irritant, where the checked cast at the seam used to panic (docs/archive/r7rs-type-errors-are-uncatchable-panics.md). who is the procedure ("" when the cast has none to name), what the expected type in Scheme's words ("" makes who the whole message, with no irritant: the r7rs-fail-* helpers' shape). The compiled back end calls it through the hook below, from the raising cast check; the interpreter calls it by name. It never returns: the raise escapes to a handler, and an unhandled one ends the program.
r7rs-type-error__
(r7rs-type-error__ [who :cstr what :cstr x] :any)
r7rs-type-error-hook-install__
(r7rs-type-error-hook-install__ :bool)
internal: point the raising cast check (__tur_any_cast_check_r7, which the emitter writes into any unit with a Scheme cast) at r7rs-type-error__. Run once, at startup, by the def below. The interpreter's twin does nothing: it finds the procedure by name.
r7rs-raise-type__
(r7rs-raise-type__ [who :cstr what :cstr x] :bool)
internal: r7rs-type-error__, called through the hook from C. For the "it is an error" checks on the hottest paths (arithmetic, comparison, the r7rs-fail-* helpers): a direct raise there makes every procedure that reaches it effectful, which compiles it to CPS and costs the tail-call trampoline (tests/fixtures/r7rs-tail-calls), while a call into C is opaque to that analysis. An empty what makes who the whole message, with no irritant. Returns (false) only when no hook is installed; the caller then panics as it did before.
r7rs-num-error__
(r7rs-num-error__ [who :cstr a b] :any)
internal: an arithmetic operator given a non-number; the irritant is the operand that is not one.
R7rsParam
(defstruct R7rsParam :heap [value :any converter :any])
a parameter object's cell: its global value and converter. parameterize does not write the cell: it binds it in the running code's dynamic environment (slot 2), so no other thread or fiber sees the value.
R7rsPBind
(defstruct R7rsPBind :heap [cell :any value :any])
one parameterize binding of a cell, in slot 2's list.
R7rsParamMarker
(defstruct R7rsParamMarker [tag :int])
the private argument that asks a parameter for its cell.
r7rs-param-get__
(r7rs-param-get__ [c :R7rsParam] :any)
r7rs-param-conv__
(r7rs-param-conv__ [c :R7rsParam] :any)
r7rs-param-set__
(r7rs-param-set__ [c :R7rsParam v] :nil)
r7rs-pbind-cell__
(r7rs-pbind-cell__ [b :R7rsPBind] :any)
r7rs-pbind-value__
(r7rs-pbind-value__ [b :R7rsPBind] :any)
r7rs-pbind-set__
(r7rs-pbind-set__ [b :R7rsPBind v] :nil)
r7rs-param-binding__
(r7rs-param-binding__ [cell l] :any)
internal: the innermost binding of cell in the binding list l, or the empty list when the cell is not bound there.
r7rs-param-value__
(r7rs-param-value__ [cell] :any)
internal: a parameter's value for the running code: its innermost binding, else the cell's global value.
r7rs-param-assign__
(r7rs-param-assign__ [cell v] :nil)
internal: (p v): the innermost binding when there is one, else the global value.
r7rs-identity__
(r7rs-identity__ [x] :any)
r7rs-make-parameter
(r7rs-make-parameter [init & xs :any] :any)
a parameter is a procedure: (p) reads it, and parameterize reaches its cell through the private marker.
r7rs-param-cell__
(r7rs-param-cell__ [p] :any)
r7rs-params-bind__
(r7rs-params-bind__ [cells vals l] :any)
internal: l with a binding of each cell to its value in front, the first pair innermost.
r7rs-parameterize__
(r7rs-parameterize__ [bindings thunk] :any)
(parameterize ((p v) ...) body...): bindings is the list of (p . v); each new value goes through the parameter's converter. The new bindings go in front of the running code's own, and entering and leaving are wind frames.
R7rsPBox
(defstruct R7rsPBox :heap [done :bool value :any])
a promise shares its box with the promise a delay-force chain yields, the R7RS 7.3 reference shape.
R7rsPromise
(defstruct R7rsPromise :heap [box :any])
r7rs-promise?
(r7rs-promise? [x] :bool)
r7rs-pbox__
(r7rs-pbox__ [p :R7rsPromise] :any)
r7rs-pbox-done__
(r7rs-pbox-done__ [b :R7rsPBox] :bool)
r7rs-pbox-value__
(r7rs-pbox-value__ [b :R7rsPBox] :any)
r7rs-pbox-set__
(r7rs-pbox-set__ [b :R7rsPBox done :bool v] :nil)
r7rs-delay-force__
(r7rs-delay-force__ [thunk] :any)
(delay-force expr): thunk yields a promise.
r7rs-make-promise
(r7rs-make-promise [v] :any)
a promise already forced to v (a promise is itself).
r7rs-force
(r7rs-force [p] :any)
iterative: each step runs the pending thunk and, unless that forced the promise already, adopts the resulting promise's state and makes the two share one box, so a delay-force loop runs in constant space (the self call is a tail call).
r7rs-boolean=2__
(r7rs-boolean=2__ [a b] :bool)
---- R7: the rest of (scheme base) that is not a port -----------------
r7rs-boolean=?
(r7rs-boolean=? [a b & xs :any] :bool)
#t when every argument is #t, or every one is #f.
r7rs-symbol=2__
(r7rs-symbol=2__ [a b] :bool)
r7rs-symbol=?
(r7rs-symbol=? [a b & xs :any] :bool)
#t when every argument is the same symbol.
r7rs-list-set!
(r7rs-list-set! [l k :int x] :nil)
store x as the k-th element.
r7rs-make-list-go__
(r7rs-make-list-go__ [k :int x acc] :any)
r7rs-make-list
(r7rs-make-list [k :int & fill :any] :any)
k elements, each fill (default #f).
r7rs-make-string-go__
(r7rs-make-string-go__ [v :(Vec int) k :int c :int] :(Vec int))
a new (mutable) string of k copies of char (default #\space).
r7rs-make-string
(r7rs-make-string [k :int & c :any] :any)
r7rs-string
(r7rs-string [& cs :any] :any)
a new (mutable) string of the given chars.
r7rs-string->vector
(r7rs-string->vector [s & r :any] :any)
r7rs-vector->string
(r7rs-vector->string [v :(Vec any) & r :any] :any)
r7rs-seq-lists__
(r7rs-seq-lists__ [conv first rest :(Cons any)] :any)
the list form of each sequence in a chain, through conv (string->list / vector->list): the multi-sequence map/for-each below run over lists.
r7rs-string-list1__
(r7rs-string-list1__ [s] :any)
r7rs-vector-list1__
(r7rs-vector-list1__ [v] :any)
r7rs-string-map
(r7rs-string-map [f s & ss :any] :any)
(string-map f s1 s2 ...): f's results are chars.
r7rs-string-for-each
(r7rs-string-for-each [f s & ss :any] :nil)
r7rs-vector-map
(r7rs-vector-map [f v & vs :any] :any)
r7rs-vector-for-each
(r7rs-vector-for-each [f v & vs :any] :nil)
r7rs-vec-push-range__
(r7rs-vec-push-range__ [out :(Vec any) v :(Vec any) i :int end :int] :nil)
r7rs-vector-append-go__
(r7rs-vector-append-go__ [out :(Vec any) c :(Cons any)] :(Vec any))
r7rs-vector-append
(r7rs-vector-append [& vs :any] :any)
a fresh vector of every argument's elements.
r7rs-vector-copy
(r7rs-vector-copy [v :(Vec any) & r :any] :any)
a fresh vector of [start, end).
r7rs-vec-store-list__
(r7rs-vec-store-list__ [to :(Vec any) at :int l] :nil)
r7rs-vector-copy!
(r7rs-vector-copy! [to :(Vec any) at :int from :(Vec any) & r :any] :nil)
copy [start, end) of from into to at at; the source range is read out first, so overlapping ranges copy correctly.
r7rs-bytes-push-range__
(r7rs-bytes-push-range__ [out :(Vec int) v :(Vec int) i :int end :int] :nil)
r7rs-bytevector-append-go__
(r7rs-bytevector-append-go__ [out :(Vec int) c :(Cons any)] :(Vec int))
r7rs-bytevector-append
(r7rs-bytevector-append [& bs :any] :any)
r7rs-bytevector-copy
(r7rs-bytevector-copy [bv & r :any] :any)
r7rs-bytes-read-acc__
(r7rs-bytes-read-acc__ [v :(Vec int) i :int j :int acc] :any)
r7rs-bytes-read-range__
(r7rs-bytes-read-range__ [v :(Vec int) i :int end :int] :any)
r7rs-bytes-store-list__
(r7rs-bytes-store-list__ [to :(Vec int) at :int l] :nil)
r7rs-bytevector-copy!
(r7rs-bytevector-copy! [to at :int from & r :any] :nil)
r7rs-utf8-bytes-go__
(r7rs-utf8-bytes-go__ [s :cstr i :int end :int out :(Vec int)] :(Vec int))
the UTF-8 bytes of characters [start, end) (T3: start and end count characters, as every string procedure does).
r7rs-string->utf8
(r7rs-string->utf8 [s & r :any] :any)
r7rs-utf8-cont__
(r7rs-utf8-cont__ [v :(Vec int) i :int end :int] :int)
r7rs-utf8-go__
(r7rs-utf8-go__ [v :(Vec int) i :int end :int out :(Vec int)] :(Vec int))
decode the bytes, checking the encoding: a string is built from code points, so an invalid sequence is an error, not garbage. T8: straight into code points; it appended one character at a time, a quadratic that leaked every intermediate string.
r7rs-utf8->string
(r7rs-utf8->string [bv & r :any] :any)
r7rs-features
(r7rs-features :any)
the feature identifiers cond-expand tests (scheme_lower.c R7RS_FEATURES, then srfi-N for every SRFI_LIBS row that is here, in table order). tests/check-r7rs-srfi-sync.sh fails when this list and that one differ, and tests/fixtures/r7rs-features-agree asks cond-expand about each (r7rs-srfi-plan D4). exact-closed: + - * on exact integers are exact (or signal); only / may be inexact. ratios: / of exact integers is exact.
r7rs-simplest-pos__
(r7rs-simplest-pos__ [lo hi] :any)
the simplest rational within y of x (R7RS 6.2.6), by the continued-fraction walk. T2: the walk is written over the generic operators, so exact arguments give the exact answer ((rationalize (exact .3) 1/10) is 1/3) and an inexact one the inexact answer, from one definition.
r7rs-simplest__
(r7rs-simplest__ [lo hi] :any)
r7rs-rationalize
(r7rs-rationalize [x y] :any)
r7rs-char-upper-case?
(r7rs-char-upper-case? [c :R7rsChar] :bool)
case mapping ---------------------------------
Chars are Unicode scalar values. R10: non-ASCII answers come from the Unicode tables (stdlib/r7rs/unicode.tur): a char's simple case mapping, the Uppercase/Lowercase properties, Nd digits, and a string's FULL case mapping ((string-upcase "\xDF;") is "SS"). Strings stay byte strings, so the string procedures map the UTF-8 in place rather than per char.
r7rs-char-lower-case?
(r7rs-char-lower-case? [c :R7rsChar] :bool)
r7rs-char-foldcase
(r7rs-char-foldcase [c :R7rsChar] :R7rsChar)
r7rs-digit-value
(r7rs-digit-value [c :R7rsChar] :any)
the value of a decimal digit (any Nd), #f otherwise.
r7rs-fold-code__
(r7rs-fold-code__ [c] :int)
r7rs-char-ci=2__
(r7rs-char-ci=2__ [a b] :bool)
r7rs-char-ci<2__
(r7rs-char-ci<2__ [a b] :bool)
r7rs-char-ci>2__
(r7rs-char-ci>2__ [a b] :bool)
r7rs-char-ci<=2__
(r7rs-char-ci<=2__ [a b] :bool)
r7rs-char-ci>=2__
(r7rs-char-ci>=2__ [a b] :bool)
r7rs-char-ci=?
(r7rs-char-ci=? [a b & xs :any] :bool)
r7rs-char-ci<?
(r7rs-char-ci<? [a b & xs :any] :bool)
r7rs-char-ci>?
(r7rs-char-ci>? [a b & xs :any] :bool)
r7rs-char-ci<=?
(r7rs-char-ci<=? [a b & xs :any] :bool)
r7rs-char-ci>=?
(r7rs-char-ci>=? [a b & xs :any] :bool)
r7rs-case-map__
(r7rs-case-map__ [who :cstr s r :(Cons any) op :int] :cstr)
string-upcase and string-downcase take SRFI 13's optional [start, end) too, and then map just those characters: a compatible extension, so (srfi 13) re-exports these rather than giving the names a second meaning next to (scheme char) (r7rs-srfi-plan D5).
r7rs-string-upcase
(r7rs-string-upcase [s & r :any] :cstr)
r7rs-string-downcase
(r7rs-string-downcase [s & r :any] :cstr)
r7rs-string-foldcase
(r7rs-string-foldcase [s] :cstr)
r7rs-string-ci=2__
(r7rs-string-ci=2__ [a b] :bool)
r7rs-string-ci<2__
(r7rs-string-ci<2__ [a b] :bool)
r7rs-string-ci>2__
(r7rs-string-ci>2__ [a b] :bool)
r7rs-string-ci<=2__
(r7rs-string-ci<=2__ [a b] :bool)
r7rs-string-ci>=2__
(r7rs-string-ci>=2__ [a b] :bool)
r7rs-string-ci=?
(r7rs-string-ci=? [a b & xs :any] :bool)
r7rs-string-ci<?
(r7rs-string-ci<? [a b & xs :any] :bool)
r7rs-string-ci>?
(r7rs-string-ci>? [a b & xs :any] :bool)
r7rs-string-ci<=?
(r7rs-string-ci<=? [a b & xs :any] :bool)
r7rs-string-ci>=?
(r7rs-string-ci>=? [a b & xs :any] :bool)
r7rs-caaar
(r7rs-caaar [p] :any)
the three- and four-deep compositions ----------
r7rs-caadr
(r7rs-caadr [p] :any)
r7rs-cadar
(r7rs-cadar [p] :any)
r7rs-cdaar
(r7rs-cdaar [p] :any)
r7rs-cdadr
(r7rs-cdadr [p] :any)
r7rs-cddar
(r7rs-cddar [p] :any)
r7rs-cdddr
(r7rs-cdddr [p] :any)
r7rs-caaaar
(r7rs-caaaar [p] :any)
r7rs-caaadr
(r7rs-caaadr [p] :any)
r7rs-caadar
(r7rs-caadar [p] :any)
r7rs-caaddr
(r7rs-caaddr [p] :any)
r7rs-cadaar
(r7rs-cadaar [p] :any)
r7rs-cadadr
(r7rs-cadadr [p] :any)
r7rs-caddar
(r7rs-caddar [p] :any)
r7rs-cadddr
(r7rs-cadddr [p] :any)
r7rs-cdaaar
(r7rs-cdaaar [p] :any)
r7rs-cdaadr
(r7rs-cdaadr [p] :any)
r7rs-cdadar
(r7rs-cdadar [p] :any)
r7rs-cdaddr
(r7rs-cdaddr [p] :any)
r7rs-cddaar
(r7rs-cddaar [p] :any)
r7rs-cddadr
(r7rs-cddadr [p] :any)
r7rs-cdddar
(r7rs-cdddar [p] :any)
r7rs-cddddr
(r7rs-cddddr [p] :any)
r7rs-real-part
(r7rs-real-part [x] :any)
---- (scheme complex) -----------------------------------------------------
T6: over R7rsComplex (above). A real's imaginary part is exact 0.
r7rs-imag-part
(r7rs-imag-part [x] :any)
r7rs-magnitude
(r7rs-magnitude [x] :any)
|z|: exact for an exact complex number whose squared magnitude is a perfect square ((magnitude 3+4i) is 5).
r7rs-angle
(r7rs-angle [x] :any)
arg z; for a real, 0 when non-negative and pi when negative.
r7rs-make-rectangular
(r7rs-make-rectangular [re im] :any)
r7rs-make-polar
(r7rs-make-polar [m a] :any)
m e^(ia); exact m when the angle is exact zero.
R7rsIo
(defopaque R7rsIo :ptr<void>)
---- R8: ports ------------------------------------------------------------
A port is an R7rsPort over an R7rsIo: one C byte buffer with a read position and, for a file port, the FILE it reads or writes. A string or bytevector port is the buffer alone; an input file port fills the buffer from its FILE on demand (so peeking a multi-byte character needs no ungetc) and reclaims it once it is drained; an output file port writes straight through. The primitives are inline C with interpreter twins in interpreter_natives.c (keep them equal). Text is UTF-8: a char is read by decoding, written by encoding.
The current ports are parameter objects (R7RS 6.13.1), so parameterize and with-output-to-file rebind them with the R6 machinery. R7rsIo -- the C buffer behind a port.
R7rsIdTab
(defopaque R7rsIdTab :ptr<void>)
an identity hash table from a heap value to an int: the printer's datum-label bookkeeping and the reader's patch walk. Keys are compared by address and never dereferenced, and a table lives for one write or read call, so no key outlives the value it names.
r7rs-io-new__
(r7rs-io-new__ :R7rsIo)
an empty in-memory buffer.
r7rs-io-std__
(r7rs-io-std__ [k :int] :R7rsIo)
the buffer over stdin (0), stdout (1) or stderr (2).
r7rs-io-open__
(r7rs-io-open__ [path :cstr mode :cstr] :R7rsIo)
a buffer over fopen(path, mode); r7rs-io-ok?__ says whether the open succeeded.
r7rs-io-ok?__
(r7rs-io-ok?__ [io :R7rsIo] :bool)
r7rs-io-add__
(r7rs-io-add__ [io :R7rsIo s :cstr] :nil)
write a string: through to the FILE, or onto the buffer. stdout is flushed before anything goes to stderr, so the two interleave in program order.
r7rs-io-add-byte__
(r7rs-io-add-byte__ [io :R7rsIo x :int] :nil)
write one byte.
r7rs-io-add-code__
(r7rs-io-add-code__ [io :R7rsIo c :int] :nil)
T8: a code point, UTF-8 encoded, byte by byte (no scratch string per character).
r7rs-cps-encode__
(r7rs-cps-encode__ [v :(Vec int) i :int end :int io :R7rsIo] :nil)
T8: encoded into one buffer. It was a divide-and-conquer of appends, every intermediate string leaked: O(n log n) bytes of garbage per conversion, and every seam crossing of a mutable string converts.
r7rs-cps->cstr__
(r7rs-cps->cstr__ [v :(Vec int) a :int b :int] :cstr)
r7rs-io-peek__
(r7rs-io-peek__ [io :R7rsIo k :int] :int)
the byte k places past the read position, or -1 at end of input. A file buffer is filled from its FILE as far as needed; stdout is flushed before stdin is read, so a prompt shows.
r7rs-io-skip__
(r7rs-io-skip__ [io :R7rsIo k :int] :nil)
advance the read position by k bytes (after a peek).
r7rs-io-str__
(r7rs-io-str__ [io :R7rsIo] :cstr)
the buffer's bytes as a fresh string.
r7rs-io-len__
(r7rs-io-len__ [io :R7rsIo] :int)
r7rs-io-byte-ref__
(r7rs-io-byte-ref__ [io :R7rsIo i :int] :int)
r7rs-io-flush__
(r7rs-io-flush__ [io :R7rsIo] :nil)
r7rs-io-close__
(r7rs-io-close__ [io :R7rsIo] :nil)
close a file buffer's FILE (never a standard stream).
r7rs-io-free__
(r7rs-io-free__ [io :R7rsIo] :nil)
release a scratch buffer (a string builder).
r7rs-io-take-str__
(r7rs-io-take-str__ [io :R7rsIo] :cstr)
a builder's contents, and the builder released.
r7rs-idtab-new__
(r7rs-idtab-new__ :R7rsIdTab)
the identity table (open addressing, key 0 empty). A missing key reads as -2.
r7rs-idtab-get__
(r7rs-idtab-get__ [tab :R7rsIdTab x] :int)
r7rs-idtab-put__
(r7rs-idtab-put__ [tab :R7rsIdTab x v :int] :nil)
r7rs-idtab-count__
(r7rs-idtab-count__ [tab :R7rsIdTab] :int)
r7rs-idtab-free__
(r7rs-idtab-free__ [tab :R7rsIdTab] :nil)
r7rs-uf-add__
(r7rs-uf-add__ [x tab :R7rsIdTab parent :(Vec int)] :int)
structural on pairs, vectors and bytevectors, eqv? on everything else, and it TERMINATES ON CYCLES (R7RS 6.1). T8: the pairs and vectors under comparison are merged into classes (union-find, as in Adams and Dybvig's "Efficient nondestructive equality checking for trees and graphs"): two nodes already in one class are assumed equal, the coinductive reading the standard specifies. Any difference makes the whole answer #f, so an assumption that turns out wrong is never kept. Linear, where the list of pairs under comparison it replaces made two equal lists of 10^5 elements take half a minute; and a cycle through vectors now terminates too.
r7rs-uf-id-of__
(r7rs-uf-id-of__ [x tab :R7rsIdTab parent :(Vec int) i :int] :int)
r7rs-uf-id__
(r7rs-uf-id__ [x tab :R7rsIdTab parent :(Vec int)] :int)
r7rs-uf-find__
(r7rs-uf-find__ [parent :(Vec int) i :int] :int)
r7rs-uf-same?__
(r7rs-uf-same?__ [a b tab :R7rsIdTab parent :(Vec int)] :bool)
#t when a and b are already one class; else joins them.
r7rs-equal-go__
(r7rs-equal-go__ [a b tab :R7rsIdTab parent :(Vec int)] :bool)
r7rs-equal-vec__
(r7rs-equal-vec__ [a :(Vec any) b :(Vec any) i :int tab :R7rsIdTab parent :(Vec int)] :bool)
r7rs-equal-bytes__
(r7rs-equal-bytes__ [a :(Vec int) b :(Vec int) i :int] :bool)
r7rs-equal?
(r7rs-equal? [a b] :bool)
r7rs-fx-and__
(r7rs-fx-and__ [a :int b :int] :int)
---- fixnum bits (r7rs-srfi-plan S7: SRFI 60) -----------------------------
SRFI 60's fast path: two fixnums (Scheme's int-carried exact integers) in two's complement, which is what the SRFI specifies for negatives too. Bignums take the SRFI's arithmetic formulation in stdlib/srfi/60.scm, as they are base-1e9 limbs, not bits. Plain Turmeric, the same on both back ends. r7rs-fx-and__ -- internal: the bitwise AND of two fixnums.
r7rs-fx-ior__
(r7rs-fx-ior__ [a :int b :int] :int)
internal: the bitwise inclusive OR of two fixnums.
r7rs-fx-xor__
(r7rs-fx-xor__ [a :int b :int] :int)
internal: the bitwise exclusive OR of two fixnums.
r7rs-fx-shr__
(r7rs-fx-shr__ [a :int k :int] :int)
internal: fixnum a shifted right k places, 0 <= k < 64, rounding toward negative infinity. bit-shr is a logical shift, so a negative a is shifted as its complement, which is non-negative.
r7rs-identity-word__
(r7rs-identity-word__ [x] :int)
---- hashing (r7rs-srfi-plan S4: SRFI 69) --------------------------------
Each hash is a non-negative int below 2^30, so a table's arithmetic on it stays in fixnums. r7rs-eqv-hash__ agrees with eqv? (and so with eq?, which is eqv? here): it hashes by value what eqv? compares by value, and by address the rest. r7rs-equal-hash__ agrees with equal?. Only the two primitives are C; the rest is this Turmeric, the same on both back ends. r7rs-identity-word__ -- internal: a value's carrier word: a heap value's address (stable, as the collector does not move), an int's value, a float's bits. Inline C on the compiled path, a native under the interpreter (the payload word r7rs-same-ref__ compares).
r7rs-cstr-hash__
(r7rs-cstr-hash__ [s :cstr ci :bool] :int)
internal: FNV-1a over a string's UTF-8 bytes, folded to 30 bits. With ci, an ASCII letter hashes as its lower case, and a byte outside ASCII answers -1 (the caller folds that string itself).
r7rs-hash-fold__
(r7rs-hash-fold__ [w :int] :int)
internal: a 64-bit word folded to 30 bits.
r7rs-hash-mix__
(r7rs-hash-mix__ [h :int x :int] :int)
internal: one more 30-bit hash folded into h.
r7rs-string-hash__
(r7rs-string-hash__ [s] :int)
SRFI 69's string-hash: agrees with string=?, over a literal and a mutable string alike (the same characters, the same bytes).
r7rs-string-ci-hash__
(r7rs-string-ci-hash__ [s] :int)
SRFI 69's string-ci-hash: agrees with string-ci=?. An ASCII string is folded as it is hashed; any other is folded first, which gives an ASCII one's bytes the same way.
r7rs-float-hash__
(r7rs-float-hash__ [x :float] :int)
internal: an integral float hashes as the exact integer would (so a table keyed by = finds 2 from 2.0), which also puts 0.0 and -0.0 together, as eqv? has them; any other float by its bits.
r7rs-eqv-hash__
(r7rs-eqv-hash__ [x] :int)
SRFI 69's hash-by-identity: agrees with eqv? and eq?.
r7rs-equal-hash__
(r7rs-equal-hash__ [x] :int)
SRFI 69's hash: agrees with equal?. It reads at most 16 elements of a list or vector (and 64 bytes of a bytevector), three levels down, so it is quick on a big key and terminates on a cycle, as equal? does. Values equal? compares by eqv? hash as r7rs-eqv-hash__.
r7rs-equal-hash-go__
(r7rs-equal-hash-go__ [x depth :int] :int)
r7rs-equal-hash-sub__
(r7rs-equal-hash-sub__ [x depth :int] :int)
r7rs-equal-hash-list__
(r7rs-equal-hash-list__ [x depth :int n :int h :int] :int)
r7rs-equal-hash-vec__
(r7rs-equal-hash-vec__ [v :(Vec any) depth :int i :int h :int] :int)
r7rs-equal-hash-bytes__
(r7rs-equal-hash-bytes__ [b :(Vec int) i :int h :int] :int)
R7rsPort
(defstruct R7rsPort :heap [kind :int input :bool output :bool binary :bool open :bool fold :bool io :R7rsIo])
kind 0 is a file, 1 a string, 2 a bytevector. A port is an input port or an output port, never both, so one open flag serves. fold is the port's #!fold-case state, which read keeps (R7RS 2.1: the directive affects later data read from the same port).
r7rs-port?
(r7rs-port? [x] :bool)
r7rs-port-kind__
(r7rs-port-kind__ [p :R7rsPort] :int)
r7rs-port-in__
(r7rs-port-in__ [p :R7rsPort] :bool)
r7rs-port-out__
(r7rs-port-out__ [p :R7rsPort] :bool)
r7rs-port-bin__
(r7rs-port-bin__ [p :R7rsPort] :bool)
r7rs-port-open__
(r7rs-port-open__ [p :R7rsPort] :bool)
r7rs-port-io__
(r7rs-port-io__ [p :R7rsPort] :R7rsIo)
r7rs-port-mark-closed__
(r7rs-port-mark-closed__ [p :R7rsPort] :nil)
r7rs-port-fold__
(r7rs-port-fold__ [p :R7rsPort] :bool)
r7rs-port-set-fold__
(r7rs-port-set-fold__ [p :R7rsPort v :bool] :nil)
r7rs-make-port__
(r7rs-make-port__ [kind :int input :bool binary :bool io :R7rsIo] :any)
r7rs-input-port?
(r7rs-input-port? [x] :bool)
r7rs-output-port?
(r7rs-output-port? [x] :bool)
r7rs-textual-port?
(r7rs-textual-port? [x] :bool)
r7rs-binary-port?
(r7rs-binary-port? [x] :bool)
r7rs-input-port-open?
(r7rs-input-port-open? [p] :bool)
r7rs-output-port-open?
(r7rs-output-port-open? [p] :bool)
r7rs-port-arg__
(r7rs-port-arg__ [rl param] :any)
the optional port argument: the first of rl, or the current port the parameter holds.
r7rs-port-of-chain__
(r7rs-port-of-chain__ [c :(Cons any) param] :any)
T8: the same, read off the rest-argument chain itself, so an I/O call builds no scratch list to find its port.
r7rs-after-port__
(r7rs-after-port__ [rl] :any)
r7rs-out-io__
(r7rs-out-io__ [port] :R7rsIo)
the buffer of an open port of the right direction; anything else is an error a guard can catch.
r7rs-in-io__
(r7rs-in-io__ [port] :R7rsIo)
r7rs-port-put__
(r7rs-port-put__ [port s :cstr] :nil)
internal: a string onto an output port.
r7rs-newline
(r7rs-newline [& r :any] :nil)
(newline [port]).
r7rs-write-char
(r7rs-write-char [c :R7rsChar & r :any] :nil)
(write-char char [port]).
r7rs-write-string
(r7rs-write-string [s & r :any] :nil)
(write-string string [port [start [end]]]); start and end count characters.
r7rs-write-u8
(r7rs-write-u8 [x :int & r :any] :nil)
(write-u8 byte [port]).
r7rs-write-bytes-go__
(r7rs-write-bytes-go__ [io :R7rsIo v :(Vec int) i :int end :int] :nil)
r7rs-write-bytevector
(r7rs-write-bytevector [bv & r :any] :nil)
(write-bytevector bv [port [start [end]]]).
r7rs-flush-output-port
(r7rs-flush-output-port [& r :any] :nil)
(flush-output-port [port]).
r7rs-utf8-width__
(r7rs-utf8-width__ [b :int] :int)
the byte length of the character a lead byte starts.
r7rs-io-cont__
(r7rs-io-cont__ [io :R7rsIo k :int] :int)
r7rs-io-peek-code__
(r7rs-io-peek-code__ [io :R7rsIo] :int)
the next character's scalar value, -1 at the end.
r7rs-io-read-code__
(r7rs-io-read-code__ [io :R7rsIo] :int)
r7rs-in-port-io__
(r7rs-in-port-io__ [r :(Cons any)] :R7rsIo)
r7rs-code->char-or-eof__
(r7rs-code->char-or-eof__ [c :int] :any)
r7rs-read-char
(r7rs-read-char [& r :any] :any)
the next character, or the eof object.
r7rs-peek-char
(r7rs-peek-char [& r :any] :any)
r7rs-read-u8
(r7rs-read-u8 [& r :any] :any)
the next byte, or the eof object.
r7rs-peek-u8
(r7rs-peek-u8 [& r :any] :any)
r7rs-io-ready?__
(r7rs-io-ready?__ [io :R7rsIo] :bool)
internal: whether a read on the buffer would not block (R7RS 6.13.2): a buffered byte, a string or bytevector buffer (its end of input counts as ready), a FILE at end of file, or a FILE whose descriptor has input now (a zero-timeout poll, so a terminal or an empty pipe answers #f). Windows has no poll over a FILE; it answers #t.
r7rs-repl-value__
(r7rs-repl-value__ [x] :any)
internal: a REPL top-level expression's value as an any. A top-level expression's value is its elaborated type's representation (a let yielding a vector is the bare Vec), which the prompt's write cannot read as a Scheme value; passing it through an any parameter widens it the way a procedure's result is (r7rs-repl-toplevel-expression-value-not-widened).
r7rs-char-ready?
(r7rs-char-ready? [& r :any] :bool)
whether a read would not block now. A string or bytevector port is always ready; a file, pipe or console port is asked (r7rs-io-ready?__).
r7rs-u8-ready?
(r7rs-u8-ready? [& r :any] :bool)
r7rs-read-line-go__
(r7rs-read-line-go__ [io :R7rsIo out :R7rsIo] :nil)
the characters up to a line end (LF, CR or CR LF, which is consumed and not included), or the eof object at the end of input.
r7rs-read-line
(r7rs-read-line [& r :any] :any)
r7rs-read-string-go__
(r7rs-read-string-go__ [io :R7rsIo out :R7rsIo k :int] :nil)
(read-string k [port]): up to k characters, or the eof object when none are left.
r7rs-read-string
(r7rs-read-string [k :int & r :any] :any)
r7rs-read-bytes-go__
(r7rs-read-bytes-go__ [io :R7rsIo v :(Vec int) k :int] :(Vec int))
(read-bytevector k [port]): up to k bytes.
r7rs-read-bytevector
(r7rs-read-bytevector [k :int & r :any] :any)
r7rs-read-into-go__
(r7rs-read-into-go__ [io :R7rsIo v :(Vec int) i :int end :int n :int] :int)
(read-bytevector! bv [port [start [end]]]): the number of bytes stored, or the eof object.
r7rs-read-bytevector!
(r7rs-read-bytevector! [bv & r :any] :any)
r7rs-open-input-string
(r7rs-open-input-string [s] :any)
---- string and bytevector ports, closing ---------------------------------
r7rs-open-output-string
(r7rs-open-output-string :any)
r7rs-get-output-string
(r7rs-get-output-string [p] :cstr)
everything written to a string port so far.
r7rs-open-input-bytevector
(r7rs-open-input-bytevector [bv] :any)
r7rs-open-output-bytevector
(r7rs-open-output-bytevector :any)
r7rs-io-bytes-go__
(r7rs-io-bytes-go__ [io :R7rsIo i :int n :int v :(Vec int)] :(Vec int))
r7rs-get-output-bytevector
(r7rs-get-output-bytevector [p] :any)
everything written to a bytevector port.
r7rs-close-port
(r7rs-close-port [p] :nil)
close either direction (closing twice is harmless).
r7rs-close-input-port
(r7rs-close-input-port [p] :nil)
r7rs-close-output-port
(r7rs-close-output-port [p] :nil)
r7rs-call-with-port
(r7rs-call-with-port [p proc] :any)
(proc port), then close it and return proc's value.
r7rs-node?__
(r7rs-node?__ [x] :bool)
---- the printer: display, write, write-shared, write-simple -------------
R7RS 6.13.3: write and display label only the pairs and vectors that are part of a cycle (#0= defines a label, #0# refers back), so they always terminate; write-shared labels every pair and vector that appears more than once; write-simple labels nothing and loops on a cycle. A pre-pass fills an identity table: 1 while a node is on the current path, 2 when done, 3 / 4 for the same states of a node that needs a label. List spines are walked iteratively (a long list is not a deep recursion); only car nesting recurses.
r7rs-cyc-spine__
(r7rs-cyc-spine__ [p tab :R7rsIdTab n :int] :int)
The cycle pre-pass: a node met again while it is still on the path is a back edge, so it gets a label. A spine marks each new pair as on the path, then finishes exactly the pairs it marked.
r7rs-cyc-finish__
(r7rs-cyc-finish__ [p tab :R7rsIdTab n :int] :nil)
r7rs-cyc-vec-go__
(r7rs-cyc-vec-go__ [v :(Vec any) i :int tab :R7rsIdTab] :nil)
r7rs-mark-cycles__
(r7rs-mark-cycles__ [x tab :R7rsIdTab] :nil)
r7rs-shr-spine__
(r7rs-shr-spine__ [p tab :R7rsIdTab] :nil)
The sharing pre-pass: any pair or vector met twice gets a label.
r7rs-shr-vec-go__
(r7rs-shr-vec-go__ [v :(Vec any) i :int tab :R7rsIdTab] :nil)
r7rs-escape-string__
(r7rs-escape-string__ [s :cstr] :cstr)
a string literal: quoted, with \" \\ \a \b \t \n \r and \xHH; for any other control byte.
r7rs-symbol-plain?__
(r7rs-symbol-plain?__ [s :cstr] :bool)
a symbol whose name reads back as itself without bars: not empty, not ., no delimiter, whitespace, control byte or backslash, not starting with #, and not +i/-i or led by a signed inf./nan.. (Names that read as numbers are the caller's.)
r7rs-bar-symbol__
(r7rs-bar-symbol__ [s :cstr] :cstr)
|name|, with | and \ escaped.
r7rs-symbol-spelling__
(r7rs-symbol-spelling__ [s :cstr] :cstr)
r7rs-char-spelling__
(r7rs-char-spelling__ [n :int] :cstr)
#\a, the R7RS names, or #\xHH for the other control characters.
r7rs-atom-spelling__
(r7rs-atom-spelling__ [x quoted :bool] :cstr)
a value that is not a pair, vector or error object.
r7rs-put-fresh__
(r7rs-put-fresh__ [port s :cstr] :nil)
T8: write a spelling made for this write, then free it (port-put copies the bytes).
r7rs-pr-atom__
(r7rs-pr-atom__ [x port quoted :bool] :nil)
an atom's spelling into the port. The spellings made afresh for this write -- a number's, an escaped or re-encoded string -- are freed once written (T8: every printed number leaked its digits); the rest (a literal, a symbol's own name, a cstr string's own bytes) belong to something else and are written as they are.
r7rs-label-put__
(r7rs-label-put__ [port n :int suffix :cstr] :nil)
r7rs-pr__
(r7rs-pr__ [x port quoted :bool tab :R7rsIdTab labels :R7rsIdTab] :nil)
one value. A labelled node prints #n= the first time (numbered in print order) and #n# after.
r7rs-pr-node__
(r7rs-pr-node__ [x port quoted :bool tab :R7rsIdTab labels :R7rsIdTab] :nil)
r7rs-pr-tail__
(r7rs-pr-tail__ [d port quoted :bool tab :R7rsIdTab labels :R7rsIdTab] :nil)
the rest of a list: b c), or . d) for an improper tail or a tail that carries a label.
r7rs-pr-vec__
(r7rs-pr-vec__ [v :(Vec any) i :int port quoted :bool tab :R7rsIdTab labels :R7rsIdTab] :nil)
r7rs-pr-bytes__
(r7rs-pr-bytes__ [v :(Vec int) i :int port] :nil)
r7rs-pr-irritants__
(r7rs-pr-irritants__ [l port tab :R7rsIdTab labels :R7rsIdTab] :nil)
r7rs-print__
(r7rs-print__ [x port quoted :bool mode :int] :nil)
mode 0 labels nothing, 1 labels cycles, 2 labels sharing.
r7rs-out-port-of__
(r7rs-out-port-of__ [r :(Cons any)] :any)
r7rs-display
(r7rs-display [x & r :any] :nil)
(display obj [port]): strings and chars bare, cycles labelled.
r7rs-write
(r7rs-write [x & r :any] :nil)
(write obj [port]): for reading back, cycles labelled.
r7rs-write-simple
(r7rs-write-simple [x & r :any] :nil)
(write-simple obj [port]): no labels (loops on a cycle).
r7rs-display-irritants__
(r7rs-display-irritants__ [l port] :nil)
internal: irritant for each, written.
r7rs-uncaught__
(r7rs-uncaught__ [obj] :any)
internal: no handler is installed. Report on the current error port the way error objects are conventionally shown and exit 70 (EX_SOFTWARE).