The osen reference
Every name the language binds, in alphabetical order: what every host
has. Each entry gives what the name takes and what it answers, in the
form (arguments) -> answer, and an example with what it answered. A
sequence is a bundle (1, 2, 3) or a list [1, 2, 3], and a name
that holds one works wherever a literal does. What a host adds of its
own – sockets, files, a console, a patch – is on that host’s page.
For how any of this is called – what (), {}, [] and a trailing
colon do – see Calling C from osen.
The names
/o/abs
(x) -> x without its sign
(-5) /o/abs # -> : 5
/o/add
(a, b) -> their sum
Two ints or two floats; a mixed pair is refused as the wrong type of item.
(1, 2) /o/add # -> : 3
/o/all
(sequence, predicate) -> 1 if the predicate answers non-zero for every item, else 0
((1, 2, 3), ({ (/x, 0) /o/gt }, ["/x"]) /o/defn) /o/all
# -> : 1
/o/and
(a, b) -> 1 if both ints are non-zero, else 0
(1, 0) /o/and # -> : 0
/o/any
(sequence, predicate) -> 1 if the predicate answers non-zero for any item, else 0
((1, 2, 3), ({ (/x, 2) /o/gt }, ["/x"]) /o/defn) /o/any
# -> : 1
/o/apply
(function, arguments) -> the function's result
A pointer is called on the spot; a function written in osen takes the frame road through /o/execlambdaapp. An evaluator step, emitted by the parser; a program has no reason to call it.
/o/assign
(bundle, value, "/address") -> a copy of the bundle with the value bound at that address
Replaces the element already at the address, or appends one. The bundle may be a literal or a name read.
((/y : 42), 99, "/y") /o/assign # -> ( /y : 99 )
((/y : 42), 99, "/z") /o/assign # -> ( /y : 42, /z : 99 )
/o/assign/toreg
("/_r", value, "/address") -> nothing; binds the value at that address in that register
The only way for a program to write into a register other than its own environment.
("/_x", 1, "/y") /o/assign/toreg, /y
# -> : [] : 1
/o/backtrace
(machine) -> a list: what each open frame still had to do, then what the machine itself was about to do
After /x : 10, (/x, /z) /o/add halts, with the machine the host held as /m:
(/m) /o/backtrace -> : [ { : "/!/o/finalize/toplevelexec", : "/!/drop" }, { : "/!/os/F" }, { : "/!/os/E", : "", : "/!/os/C2", : "/o/add" } ]
/o/bind
("/name", value) -> nothing; the name bound in the environment
What a statement /name : value becomes. An evaluator step, emitted by the parser; a program has no reason to call it.
/o/bound
("/name") -> 1 if the name exists and carries a value, else 0
("/o/add") /o/bound
# -> : 1
/o/bundleitem/tobundleelem
(x) -> x as a bundle element if it arrived as a bundle item; anything else unchanged
A bundle read through a name arrives as one item of a message; this is the normalisation every sequence verb does, exposed.
(10) /o/bundleitem/tobundleelem # -> : 10
/o/butlast
(sequence) -> the sequence without its last item
((1, 2, 3)) /o/butlast # -> ( : 1, : 2 )
/o/concat/blobs
(blob, blob) -> one blob, the second's bytes after the first's
((5) /o/toblob/fromitem, (6) /o/toblob/fromitem) /o/concat/blobs # -> : "/,/b/\x00\x00\x00\x05\x00\x00\x00\x06"
/o/concat/elems
(a, b) -> one sequence: a's items followed by b's
Two lists make a list; two bundles make a bundle.
([1, 2], [3, 4]) /o/concat/elems # -> : [ 1, 2, 3, 4 ]
((/a : 1), (/b : 2)) /o/concat/elems # -> ( /a : 1, /b : 2 )
/o/concat/strings
(string, string) -> one string, the second after the first
("ab", "cd") /o/concat/strings
# -> : "abcd"
/o/count/elems
(x) -> 1
It counts the elements of the stack beneath it, which is what libose’s COUNTELEMS does, and once the argument bundle is unpacked that is always one. /o/length is the verb that counts what a sequence holds.
((1, 2, 3)) /o/count/elems # -> : 1
/o/count/items
(sequence) -> how many items it holds; the same function as /o/length
((/a : 1, /b : 2)) /o/count/items # -> : 2
/o/db
(machine) -> one bundle showing it: /frames, /aboutto, /stack, /env, /pending, and /andyoucan
The whole of a halted machine at once; the prompt prints it like any other value, and the next line is ordinary osen against the same machine.
(() /o/machine/new) /o/db
/o/decat/blob/fromstart
(blob, n) -> [its first n bytes, the rest]
((5) /o/toblob/fromitem, 1) /o/decat/blob/fromstart # -> : [ "/,/b/\x00", "/,/b/\x00\x00\x05" ]
/o/decat/string/fromstart
(string, n) -> [its first n characters, the rest]
("hello", 2) /o/decat/string/fromstart
# -> : [ "he", "llo" ]
/o/defn
({ body }, ["/params"...]) -> a function
The body is a brace bundle and the parameters a list of names; calling the function binds the arguments to those names and runs the body. The named form ( /body : { }, /args : [ ] ) is the same call. The optional named slots are /name, what the function calls itself; /captured, the names to close over now; and /ambient.
/f : ({ (/a, /b) /o/add }, ["/a", "/b"]) /o/defn, (1, 2) /f
# -> : 3
/y : 10, /f : ({ (/x, /y) /o/add }, ["/x"], /captured : ["/y"]) /o/defn, (5) /f
# -> : 15
/o/div
(a, b) -> a divided by b
Two ints divide as ints.
(7, 2) /o/div # -> : 3
/o/drain
() -> nothing; what /o/out staged in the output register moves to the input and runs
The o.se prompt drains after every line by itself.
() /o/drain # -> ()
/o/each
(sequence, function) -> 0, after calling the function on each item for its effect
((1, 2, 3), ({ (/x) /o/println }, ["/x"]) /o/defn) /o/each
# -> : 1 : 2 : 3 : 0
/o/eql
(a, b) -> 1 if equal, else 0
Ints, floats, strings, lists and bundles compare; an int and a float with the same value are not equal.
(1, 1) /o/eql # -> : 1
/o/eval
("source") -> what the host's evaluator makes of it
The host decides what evaluating is: a prompt hands the string to its own read-eval-print, a host without one to its evaluator. In the browser host (“(1, 2) /o/add”) /o/eval answers 3.
("(1, 2) /o/add") /o/eval
/o/exec
(bundle) -> a bundle of what its elements produced
Executing a bundle produces a bundle; an empty one stays empty. An evaluator step, emitted by the parser; a program has no reason to call it.
/o/exec/blob
(blob) -> a bundle of what the bundle inside the blob produced
An eager bracket the parser left encoded, converted and executed in one step. An evaluator step, emitted by the parser; a program has no reason to call it.
/o/exec/toplevel
(bundle) -> its elements run as a line at the top level
An evaluator step, the way the prompt runs a parsed line; a program has no reason to call it.
/o/exec2
(bundle) -> its elements run, by the instruction language's exec2
An evaluator step; a program has no reason to call it.
/o/execbranch
(branch) -> the branch running, as /o/if runs one
The same execution as /o/exec with /o/finalize/branch at the end. An evaluator step, emitted by the parser; a program has no reason to call it.
/o/execlambdaapp
(function, arguments) -> the body running in a new frame
Opens the frame a function call runs in. An evaluator step, emitted by the parser; a program has no reason to call it.
/o/exists
("/name") -> 1 if a message with that address is anywhere the lookup searches, else 0
Present with no value still counts; /o/bound asks for the value too.
("/o/add") /o/exists
# -> : 1
("/nope") /o/exists
# -> : 0
/o/false
a value -> false, the F type
answers 1: the logical verbs read ints, not these.
(/o/false) /o/typeof1 # -> : "/-/F"
/o/fill
({ body }) -> the body with each /%/name replaced by that name's value now
What a brace bundle does to its /%/ holes when it is written; this is the same fill as a verb, for a body held in a value.
/x : 5, /t : ({ (/%/x, 1) /o/add }) /o/fill, /x : 100, ({ 0 }, /t, 1) /o/if
# -> : 6
/o/fill/all
({ body }) -> the body with every free name replaced by its value now
What %{ } does when it is written: every name that resolves is filled, except the vocabulary under /o/ and /prim/, which the receiver has. As a verb on a body already written with { } it fills in the browser host and not at the o.se prompt, which answers 101 for the second line below.
/x : 5, /t : %{ (/x, 1) /o/add }, /x : 100, ({ 0 }, /t, 1) /o/if
# -> : 6
/x : 5, /t : ({ (/x, 1) /o/add }) /o/fill/all, /x : 100, ({ 0 }, /t, 1) /o/if
/o/filter
(sequence, predicate) -> a list of the items the predicate answers non-zero for
The predicate is a function of one argument.
((1, 2, 3, 4), ({ (/x, 2) /o/gt }, ["/x"]) /o/defn) /o/filter
# -> : [ 3, 4 ]
/o/finalize/branch
(a branch that has run) -> its values, unwrapped, on the caller's stack
A branch is part of the expression around it, so what it produced comes back as values rather than sealed in a bundle. An evaluator step, emitted by the parser; a program has no reason to call it.
/o/finalize/elem
(an element that has been evaluated) -> its value, bound if it was named
A statement /x : 5 binds after this step; a bare value stays on the stack. An evaluator step, emitted by the parser; a program has no reason to call it.
/o/finalize/exec
(a frame that has run) -> its results, the frame closed
Separates what the body produced from the environment beneath it and restores the caller’s. An evaluator step, emitted by the parser; a program has no reason to call it.
/o/finalize/execlambdaapp
(a function body that has run) -> its last value, the frame closed
A function answers with one value: the last the body produced, or nothing for an empty body. An evaluator step, emitted by the parser; a program has no reason to call it.
/o/finalize/toplevelexec
(a line that has run) -> its values, ready for the prompt to print
An evaluator step, emitted by the parser; a program has no reason to call it.
/o/find
(sequence, predicate) -> the first item the predicate answers non-zero for
((1, 2, 3, 4), ({ (/x, 2) /o/gt }, ["/x"]) /o/defn) /o/find
# -> : 3
/o/first
(sequence) -> its first item
A sequence is a bundle, (1, 2, 3), or a list, [1, 2, 3]; a name read works too.
((1, 2, 3)) /o/first # -> : 1
/o/fold
(sequence, init, fn) -> the last accumulator
fn is called as (acc, item) fn for each item, and its answer is the next accumulator; init is the first.
((1, 2, 3), 10, /o/add) /o/fold # -> : 16
/o/foldrest
(a fold in progress) -> its next round
An evaluator step: /o/fold schedules it after each call of the step function. A program has no reason to call it.
/o/format
(x) -> x, and its printed form as a string
The form the prompt prints, one line, without a newline.
(5) /o/format # -> : [ 5, ": 5" ]
/o/formatln
(x) -> x, and its printed form as a string ending in a newline
((1, 2, 3)) /o/formatln # -> : [ ( : 1, : 2, : 3 ), "( : 1, : 2, : 3 ) " ]
/o/frame
(machine, k) -> frame k: what it saved, in the order /_i, /_e, /_s, /_c, omitting registers that were empty
After a halt, with the machine the host held as /m:
(/m, 0) /o/frame -> ( ( : "/!/o/finalize/toplevelexec", : "/!/drop" ) )
/o/frames
(machine) -> how many frames it has open
(() /o/machine/new) /o/frames # -> : 0
/o/funcall
(function, arguments) -> the function's result, from a quoted call
What a quoted call in a callback list resolves to. An evaluator step, emitted by the parser; a program has no reason to call it.
/o/gather
(bundle, "/address") -> a list of two bundles: the elements whose address matches, and the rest
((/a : 1, /b : 2), "/a") /o/gather # -> : [ ( /a : 1 ), ( /b : 2 ) ]
/o/get
(bundle, (step, ...)) -> the value at the end of the path
Each step is an address, looked up, or an index, counted from 0.
((/a : (/b : 5)), ("/a", "/b")) /o/get
# -> : 5
((1, 2, 3), (1)) /o/get # -> : 2
/o/get/addresses
(bundle) -> a list of its elements' addresses, in order
((/a : 1, /b : 2)) /o/get/addresses # -> : [ "/a", "/b" ]
/o/gt
(a, b) -> 1 if a is greater than b, else 0
(1, 2) /o/gt # -> : 0
/o/gte
(a, b) -> 1 if a is at least b, else 0
(2, 2) /o/gte # -> : 1
/o/if
({ iffalse }, { iftrue }, condition) -> what the chosen branch produced
The branches are brace bundles and the condition an int, 0 choosing the first. What the branch left comes back as values, not wrapped in a bundle.
({ 0 }, { 1 }, 1) /o/if
# -> : 1
/o/infinitum
a value -> infinitum, the I type
(/o/infinitum) /o/typeof1 # -> : "/-/I"
/o/insert/fromend
(target, item, "/key") -> the same, reading the target as descending
(((/due : 30), (/due : 10)), (/due : 20), "/due") /o/insert/fromend # -> ( ( /due : 30 ), ( /due : 20 ), ( /due : 10 ) )
/o/insert/fromstart
(target, item, "/key") -> a copy of the target with the item placed by the number at /key, reading the target as ascending
Every element of the target carries a number at /key. Equal keys keep their arrival order. An item with no such key, or a non-number there, is refused.
(((/due : 10), (/due : 30)), (/due : 20), "/due") /o/insert/fromstart # -> ( ( /due : 10 ), ( /due : 20 ), ( /due : 30 ) )
/o/inspect
(x) -> its printed form as a string, with nothing collapsed
The prompt’s printer with the collapse off, answering a string a program can hold, compare or send.
((1, 2, 3)) /o/inspect # -> : "( : 1, : 2, : 3 )"
/o/is/closure
(value) -> 1 if it is a function carrying captured bindings, else 0
/y : 10, /f : ({ (/x, /y) /o/add }, ["/x"], /captured : ["/y"]) /o/defn, (/f) /o/is/closure
# -> : 1
/o/is/lambda
(value) -> 1 if it is a function, else 0
A function is a bundle declaring /_i and /_p, as /o/defn makes one.
(/o/add) /o/is/lambda # -> : 1
/o/is/machine
(value) -> 1 if it is a machine, else 0
A machine is a bundle declaring the five registers, whatever their order.
(() /o/machine/new) /o/is/machine # -> : 1
/o/is/thunk
(value) -> 1 if it is a thunk, else 0
A thunk is a bundle declaring /_i and nothing else: a body with no parameters. A brace bundle held in a name is a blob, not a thunk, and answers 0.
((/_i : { 1 })) /o/is/thunk
# -> : 1
/o/is/type/string
(x) -> x, and 1 if it is a string, else 0
("a") /o/is/type/string
# -> : [ "a", 1 ]
/o/last
(sequence) -> its last item
((1, 2, 3)) /o/last # -> : 3
/o/length
(sequence) -> how many items it holds
A bundle’s elements or a list’s items; a literal and a name read count the same. /o/count/items is the same function.
((1, 2, 3)) /o/length # -> : 3
/x : (1, 2, 3), (/x) /o/length # -> : 3
/o/length/item
(string) -> how many characters it has
("hello") /o/length/item
# -> : 5
/o/listen
(port, handler) -> nothing; the handler is called with each bundle that arrives on the port
The handler is a function of one argument and receives the arrival as data, not run. Needs a host with sockets.
/arrived : ({ ((/b) /o/length) /o/println }, ["/b"]) /o/defn, (9999, /arrived) /o/listen
/o/lookup
(bundle, "/address") -> the message at that address, or the empty message
The bundle may be a literal or a name read; a name that is not there answers the empty message rather than raising.
((/a : 1, /b : 2), "/b") /o/lookup # -> : 2
((/a : 1, /b : 2), "/c") /o/lookup # -> : []
/o/lookup/inenv
("/name") -> the message the name is bound to, searched the way a name read is
Raises if the name is not bound; /o/exists asks without raising.
/x : 3, ("/x") /o/lookup/inenv
# -> : 3
/o/lt
(a, b) -> 1 if a is less than b, else 0
Numbers only; two strings are refused as the wrong type of item.
(1, 2) /o/lt # -> : 1
/o/lte
(a, b) -> 1 if a is at most b, else 0
(2, 2) /o/lte # -> : 1
/o/machine/bind
(machine, value, "/name") -> the machine with the name bound in every one of its environments
Unconditional: a frame that already had the name gets the new value, so use it for a name that is unbound everywhere. After the line the machine as /m:
/x : 10, (/x, /z) /o/add, (/z, 100) /o/add halts and the host holds
(((/m, 5, "/z") /o/machine/bind, 5) /o/machine/store/value, ("/_s")) /o/get -> : ( : 15, : 105 )
/o/machine/new
() -> an empty machine, as a value
Five empty registers in a bundle, a value like any other: put things in it with /o/put, send it, or hand it to a host that runs machines.
(() /o/machine/new) /o/is/machine # -> : 1
/o/make/register
(size, "/_r") -> nothing; a register of that many bytes made under that name
A name already in use is refused.
(1024, "/_z") /o/make/register # -> : []
/o/map
(sequence, function) -> a list of the function's answers, one per item
Addresses are not kept: a bundle of named elements maps to a plain list.
((1, 2, 3), ({ (/x, 10) /o/mul }, ["/x"]) /o/defn) /o/map
# -> : [ 10, 20, 30 ]
/o/match
("/address", "/pattern") -> [the address, the pattern, 1 if the pattern matches the whole address, else 0]
("/a/b", "/a/*") /o/match
# -> : [ "/a/b", "/a/*", 0 ]
/o/max
(a, b) -> the larger
(1, 2) /o/max # -> : 2
/o/min
(a, b) -> the smaller
(1, 2) /o/min # -> : 1
/o/mod
(a, b) -> the remainder of a divided by b
(7, 3) /o/mod # -> : 1
/o/mul
(a, b) -> their product
(3, 4) /o/mul # -> : 12
/o/neg
(x) -> x with its sign flipped
(5) /o/neg # -> : -5
/o/neq
(a, b) -> 1 if they differ, else 0
(1, 2) /o/neq # -> : 1
/o/nfill
(x, n) -> a list of n copies of x
(7, 3) /o/nfill # -> : [ 7, 7, 7 ]
/o/nil
a value -> nil, the N type
(/o/nil) /o/typeof1 # -> : "/-/N"
/o/not
(x) -> 1 if the int is 0, else 0
(0) /o/not # -> : 1
/o/nth
(sequence, n) -> item n, counting from 0
((10, 20, 30), 1) /o/nth # -> : 20
/o/or
(a, b) -> 1 if either int is non-zero, else 0
(1, 0) /o/or # -> : 1
/o/out
("/channel", value...) -> nothing; appends /channel : value... to the output register
The register is /_o, a bundle of messages addressed by channel; emitting appends, so repeated channels keep their order. What the host does with a channel is its own: at the o.se prompt the register is drained into the input, so (“/println”, 1) /o/out prints 1. The register must exist, and one is made with (65536, “/_o”) /o/make/register.
("/println", 1) /o/out
/o/parse
("source") -> [the program the source parses to, 0]
The program is a bundle of what the parser emitted, not yet run. A syntax error raises instead.
("(1, 2) /o/add") /o/parse
# -> : [ ( : <thunk> ), 0 ]
/o/pmatch
("/address", "/pattern") -> [what is left of the address after the match, the pattern, 1 if the address was fully matched, 1 if the pattern was]
A partial match: the pattern may match a prefix of the address.
("/a/b/c", "/a") /o/pmatch
# -> : [ "/b/c", "/a", 0, 1 ]
/o/pop
(sequence) -> [the sequence without its last item, that item]
((1, 2, 3)) /o/pop # -> : [ ( : 1, : 2 ), 3 ]
/o/pop/all/drop/bundle
(sequence) -> a bundle of its items, last first
((1, 2, 3)) /o/pop/all/drop/bundle # -> ( : 3, : 2, : 1 )
/o/pow
(a, b) -> a to the power b
(2, 10) /o/pow # -> : 1024
/o/print
(x) -> x, printed without a newline
Prints the last argument in the form the prompt uses.
("hi") /o/print
# -> : "hi"
/o/println
(x) -> x, printed with a newline
("hi") /o/println
# -> : "hi"
/o/push
(sequence, x) -> the sequence with x appended
((1, 2), 3) /o/push # -> ( : 1, : 2, : 3 )
/o/put
(bundle, value, (step, ...)) -> a copy of the bundle with the value at the end of the path
The write side of /o/get; the same steps.
((/a : (/b : 5)), 9, ("/a", "/b")) /o/put
# -> ( /a : { /b : 9 } )
((1, 2, 3), 9, (1)) /o/put # -> ( : 1, : 9, : 3 )
/o/range
(end), (start, end) or (start, end, step) -> the list of ints from start up to but not including end
Start is 0 and step is 1 when not given; a negative step counts down.
(3) /o/range # -> : [ 0, 1, 2 ]
(2, 5) /o/range # -> : [ 2, 3, 4 ]
(0, 10, 3) /o/range # -> : [ 0, 3, 6, 9 ]
/o/register/flags
("/_r") -> a bundle of that register's flags, each 0 or 1
("/_x") /o/register/flags
# -> ( /flag/local : 1, /flag/temp : 0 )
/o/register/flags/set
("/_r", (/flag/name : 0 or 1, ...)) -> how many of the flag names it understood
An unknown flag name is ignored, not an error, so a program can tell a host that predates the flag from one that set it.
(1024, "/_z") /o/make/register, ("/_z", (/flag/temp : 1)) /o/register/flags/set
# -> : [] : 1
/o/rest
(sequence) -> the sequence without its first item
A bundle stays a bundle and a list a list.
((1, 2, 3)) /o/rest # -> ( : 2, : 3 )
/o/reverse
(sequence) -> the sequence with its items in the opposite order
((1, 2, 3)) /o/reverse # -> ( : 3, : 2, : 1 )
/o/route
(bundle, "/address") -> a bundle of two: the matching elements with the matched part taken off their addresses, then the rest
((/a : 1, /b : 2), "/a") /o/route # -> ( ( : 1 ), ( /b : 2 ) )
/o/select
(bundle, ["/address", ...]) -> a bundle of one bundle per address, last address first, and the unmatched rest at the end
((/a : 1, /b : 2, /c : 3), ["/a", "/c"]) /o/select # -> ( ( /c : 3 ), ( /a : 1 ), ( /b : 2 ) )
/o/send
(arguments...) -> whatever the host's send answers
Late bound: a host without a send of its own answers through its unbound-name handler.
/o/set/nth
(sequence, new, n) -> a copy of the sequence with item n replaced by new
Counts from 0. The write side of /o/nth.
((10, 20, 30), 99, 1) /o/set/nth # -> ( : 10, : 99, : 30 )
/o/sort
(list) -> the list with its items in ascending order
Ints, floats or strings; a bundle of elements comes back as it was.
([3, 1, 2]) /o/sort # -> : [ 1, 2, 3 ]
/o/sortidxs
(list) -> the positions its items would be taken from to sort it
([3, 1, 2]) /o/sortidxs # -> : [ 1, 2, 0 ]
/o/split/string/fromend
(string, separator) -> [the tail from the last separator, the head before it, the separator]
A separator that does not occur answers [the string, the separator].
("a.b.c", ".") /o/split/string/fromend
# -> : [ ".c", "a.b", "." ]
/o/sub
(a, b) -> a minus b
(5, 2) /o/sub # -> : 3
/o/toblob/fromelem
(element) -> the element's bytes as a blob
A bundle so encoded prints in braces; /o/toelem/fromblob decodes it.
((1, 2)) /o/toblob/fromelem
# -> : { : 1, : 2 }
/o/toblob/fromitem
(item) -> the item's bytes as a blob
(5) /o/toblob/fromitem # -> : "/,/b/\x00\x00\x00\x05"
/o/todouble
(number) -> the same number as a double
(3) /o/todouble # -> : 3.000000
/o/toelem/fromblob
(blob) -> the bundle element the blob's bytes encode
The inverse of /o/toblob/fromelem.
(((1, 2)) /o/toblob/fromelem) /o/toelem/fromblob # -> ( : 1, : 2 )
/o/tofloat
(number) -> the same number as a float
(3) /o/tofloat # -> : 3.0
/o/toint16
(number) -> the same number as an int16
The prompt has no printer for this type; /o/typeof1 shows what came back.
((300) /o/toint16) /o/typeof1 # -> : "/-/u"
/o/toint32
(number or "digits") -> the same as an int32
A float is truncated.
(3.7) /o/toint32 # -> : 3
/o/toint64
(number) -> the same number as an int64
((3) /o/toint64) /o/typeof1 # -> : "/-/h"
/o/toint8
(number) -> the same number as an int8
((300) /o/toint8) /o/typeof1 # -> : "/-/c"
/o/tostring
(x) -> its text as a string
(42) /o/tostring # -> : "42"
/o/tosymbol
(x) -> its text as a symbol
(42) /o/tosymbol # -> : "/,/S/42"
/o/totimetag
(int) -> that many seconds from 1900, as a timetag
(42) /o/totimetag # -> : "/,/t/1900-01-01T00:00:42.000000Z"
/o/touint16
(number) -> the same number as a uint16
((3) /o/touint16) /o/typeof1 # -> : "/-/U"
/o/touint32
(number) -> the same number as a uint32
((3) /o/touint32) /o/typeof1 # -> : "/-/k"
/o/touint64
(number) -> the same number as a uint64
((3) /o/touint64) /o/typeof1 # -> : "/-/H"
/o/touint8
(number) -> the same number as a uint8
((3) /o/touint8) /o/typeof1 # -> : "/-/C"
/o/true
a value -> true, the T type
Not a function: reading the name gives the value.
(/o/true) /o/typeof1 # -> : "/-/T"
/o/typeof0
(x) -> "/-" for a message, "/|" for a bundle
((1, 2)) /o/typeof0 # -> : "/|"
/o/typeof1
(x) -> its type one level down: the element's kind, then its items' typetags
(1) /o/typeof1 # -> : "/-/i"
(["a", 1, 2.5]) /o/typeof1 # -> : "/-/sif"
/o/typeof2
(x) -> its type to full depth
(("a", 1, 2.5)) /o/typeof2
# -> : "/|/-/s/-/i/-/f"
/o/typetag/set
(item, code) -> the item with its typetag replaced by the character code; the bytes stay
A reinterpretation, not a conversion: 105 is ‘i’, and 1.5’s bits read as an int.
(1.5, 105) /o/typetag/set # -> : 1069547520
/o/unpack/drop
(bundle) -> its elements, each on the stack by itself
((1, 2, 3)) /o/unpack/drop # -> : [ 1, 2, 3 ]
/o/unwrap
two names on the stack, an instruction and the /o/ name to bind -> nothing; the /o/ name bound as the instruction with the argument bundle unpacked first
The bootstrap the generated wrappers are written with, at the instruction level, as the line below binds /o/eval.
/,/s//!/eval /,/s//o/eval /!/o/unwrap
/o/whence
("/name") -> the register the name resolves in, or "" if nowhere
The name is a string and is not looked up, so asking never moves a program elsewhere.
("/o/add") /o/whence
# -> : "/_x"
/o/zipwith
((sequence, ...), fn) -> a list of fn applied across the sequences, item by item
The sequences travel as one bundle; fn takes one argument per sequence.
(((1, 2, 3), (4, 5, 6)), /o/add) /o/zipwith # -> : [ 5, 7, 9 ]
/o/zipwithrest
(a zipwith in progress) -> its next round
An evaluator step: /o/zipwith schedules it between calls of the function it is applying. A program has no reason to call it.
Implementation — for embedders and module authors
Implementation
osen-stdlib.tsv says a name exists and where its binding comes from.
This says what it is built out of.
Where a C body makes exactly one libose call, that call’s
denotational spec is its meaning – the last column names the spec
block in libose’s ose_stackops.c; build libose’s docs with make
doc and read that function’s entry. Where it makes several, the
meaning is the composition and no single spec covers it. A wrapper
written in osen or ose is listed by the instructions it runs.
| name | defined in | implemented as | spec |
|---|---|---|---|
/o/backtrace |
higher.osen | (higher.osen) | |
/o/db |
higher.osen | (higher.osen) | |
/o/frame |
higher.osen | (higher.osen) | |
/o/frames |
higher.osen | (higher.osen) | |
/o/machine/bind |
higher.osen | (higher.osen) | |
/o/set/nth |
C:registered | ose_peekType, ose_unpackDrop, ose_peekType, ose_peekMessageArgType, ose_popInt32, ose_drop, ose_popInt32, ose_swap, ose_swap, ose_getLastBundleElemOffset, ose_getBundleElemCount, ose_readInt32, ose_getBundleElemType, ose_readInt32, ose_readInt32, ose_readInt32, ose_copyElemAtOffset, ose_copyElemAtOffset, ose_pushInt32, ose_bundleFromTop, ose_swap, ose_drop, ose_swap, ose_drop |
|
/o/abs |
C:OSEN_PUSHFN | macro OSEN_WRAP_BUILTIN_BINOP |
\fnunop{ABS} |
/o/add |
C:OSEN_PUSHFN | macro OSEN_WRAP_BUILTIN_BINOP |
\fnbinop{ADD} |
/o/all |
higher.osen | (higher.osen) | |
/o/and |
C:OSEN_PUSHFN | macro OSEN_WRAP_BUILTIN_BINOP |
\fnbinop{AND} |
/o/any |
higher.osen | (higher.osen) | |
/o/apply |
C:registered | (C:registered) | |
/o/assign |
C:OSEN_PUSHFN+prelude.ose | /!/unpack/drop /!/assign |
|
/o/assign/toreg |
C:registered | ose_peekType, ose_unpackDrop, ose_peekType, ose_peekMessageArgType, ose_rot, ose_peekType, ose_peekMessageArgType, ose_getBundlePtr, ose_drop, ose_copyBundle, ose_rrot, ose_assign, ose_replaceBundle |
|
/o/bind |
C:registered | (C:registered) | |
/o/bound |
higher.osen | (higher.osen) | |
/o/bundleitem/tobundleelem |
host module | (host module) | |
/o/butlast |
C:OSEN_PUSHFN | ose_pop, ose_nip, ose_pop, ose_drop |
|
/o/concat/blobs |
generated | /!/unpack/drop /!/push /!/concat/blobs |
|
/o/concat/elems |
C:registered | ose_peekType, ose_unpackDrop, ose_swap, ose_swap, ose_concatenateElems |
|
/o/concat/strings |
generated | /!/unpack/drop /!/push /!/concat/strings |
|
/o/count/elems |
C:registered | ose_peekType, ose_unpackDrop, ose_countElems, ose_nip |
|
/o/count/items |
C:registered | ose_peekType, ose_unpackDrop, ose_countItems, ose_nip |
|
/o/decat/blob/fromstart |
generated | /!/unpack/drop /!/decat/blob/fromstart |
|
/o/decat/string/fromstart |
generated | /!/unpack/drop /!/decat/string/fromstart |
|
/o/defn |
C:OSEN_PUSHFN | ose_getLastBundleElemOffset, ose_getBundleElemElemCount, ose_elemToBlob, ose_readInt32, ose_readInt32, ose_getBundleElemType, ose_readString, ose_getBundlePtr, ose_getBundleElemType, ose_pstrlen, ose_getBundlePtr, ose_getBundleElemType, ose_pstrlen, ose_pnbytes, ose_copyElemAtOffset, ose_copyElemAtOffset, ose_copyElemAtOffset, ose_copyElemAtOffset, ose_copyElemAtOffset, ose_pushInt32, ose_bundleFromTop, ose_elemToBlob, ose_getBundleElemType, ose_getBundlePtr, ose_readInt32, ose_copyElemAtOffset, ose_push, ose_elemToBlob, ose_push, ose_pushMessage, ose_readInt32, ose_getBundleElemType, ose_pushMessage, ose_push, ose_copyElemAtOffset, ose_pushInt32, ose_bundleFromTop, ose_nip, ose_elemToBlob |
|
/o/div |
C:OSEN_PUSHFN | macro OSEN_WRAP_BUILTIN_BINOP |
\fnbinop{DIV} |
/o/drain |
C:OSEN_PUSHFN | ose_getContextMessageOffset, ose_enter, ose_getBundlePtr, ose_moveElem |
|
/o/each |
higher.osen | (higher.osen) | |
/o/eql |
C:OSEN_PUSHFN+prelude.ose | /!/unpack/drop /!/eql |
|
/o/eval |
prelude.ose | /!/unpack/drop /!/eval |
|
/o/exec |
C:registered | (C:registered) | |
/o/exec/blob |
C:registered | (C:registered) | |
/o/exec/toplevel |
generated | /!/exec1 /!/drop /!/o/finalize/toplevelexec |
|
/o/exec2 |
generated | /!/unpack/drop /!/exec2 |
|
/o/execbranch |
C:registered | (C:registered) | |
/o/execlambdaapp |
C:registered | (C:registered) | |
/o/exists |
higher.osen | (higher.osen) | |
/o/false |
C:registered | (C:registered) | |
/o/filter |
higher.osen | (higher.osen) | |
/o/fill |
C:OSEN_PUSHFN | (no libose call) | |
/o/fill/all |
C:registered | (no libose call) | |
/o/finalize/branch |
C:registered | (C:registered) | |
/o/finalize/elem |
C:registered | (C:registered) | |
/o/finalize/exec |
C:registered | (C:registered) | |
/o/finalize/execlambdaapp |
C:registered | (C:registered) | |
/o/finalize/toplevelexec |
C:registered | (C:registered) | |
/o/find |
higher.osen | (higher.osen) | |
/o/first |
C:OSEN_PUSHFN | ose_pop, ose_nip, ose_popAllDropBundle, ose_pop, ose_nip |
|
/o/fold |
C:OSEN_PUSHFN | ose_peekType, ose_getBundleElemCount, ose_unpackDrop, ose_getBundleElemCount, ose_pop, ose_countItems, ose_pop, ose_reverse, ose_rot, ose_peekType, osevm_assignStackToEnv_impl, ose_reverse, ose_rot |
|
/o/foldrest |
C:registered | (no libose call) | |
/o/format |
host module | (host module) | |
/o/formatln |
host module | (host module) | |
/o/funcall |
C:registered | (C:registered) | |
/o/gather |
C:OSEN_PUSHFN | ose_peekType, ose_unpackDrop, ose_peekType, ose_swap, ose_swap, ose_swap, ose_gather |
|
/o/get |
higher.osen | (higher.osen) | |
/o/get/addresses |
C:registered | ose_peekType, ose_unpackDrop, ose_getAddresses, ose_nip |
|
/o/gt |
C:OSEN_PUSHFN | macro OSEN_WRAP_BUILTIN_BINOP |
\fnbinop{GT} |
/o/gte |
C:OSEN_PUSHFN | macro OSEN_WRAP_BUILTIN_BINOP |
\fnbinop{GTE} |
/o/if |
C:OSEN_PUSHFN | ose_unpackDrop, ose_peekMessageArgType, osevm_toInt32, ose_pushInt32, ose_neq, ose_roll, ose_drop, ose_peekType, ose_peekMessageArgType, ose_setTypetag_impl, ose_blobToElem, ose_unpackDrop, ose_peekType, ose_countItems, ose_popInt32, ose_unpackDrop, ose_pushString, ose_swap |
|
/o/infinitum |
C:registered | (C:registered) | |
/o/insert/fromend |
C:registered | (no libose call) | |
/o/insert/fromstart |
C:registered | (no libose call) | |
/o/is/closure |
C:registered | (C:registered) | |
/o/is/lambda |
C:registered | (C:registered) | |
/o/is/machine |
C:registered | (C:registered) | |
/o/is/thunk |
C:registered | (C:registered) | |
/o/is/type/string |
generated | /!/unpack/drop /!/is/type/string |
|
/o/last |
C:OSEN_PUSHFN | ose_pop, ose_nip, ose_pop, ose_nip |
|
/o/length |
C:registered | ose_peekType, ose_unpackDrop, ose_countItems, ose_nip |
|
/o/length/item |
generated | /!/unpack/drop /!/length/item /!/nip |
|
/o/whence |
prelude.ose | /!/unpack/drop /!/whence |
|
/o/listen |
higher.osen | (higher.osen) | |
/o/lookup |
generated | ose_peekType, ose_unpackDrop, ose_peekType, ose_lookup, ose_peekMessageArgType, ose_swap, ose_swap, ose_swap, ose_lookup, ose_nip |
|
/o/lookup/inenv |
generated | /!/unpack/drop /!/lookup/inenv |
|
/o/machine/new |
higher.osen | (higher.osen) | |
/o/lt |
C:OSEN_PUSHFN | macro OSEN_WRAP_BUILTIN_BINOP |
\fnbinop{LT} |
/o/lte |
C:OSEN_PUSHFN | macro OSEN_WRAP_BUILTIN_BINOP |
\fnbinop{LTE} |
/o/make/register |
generated | /!/unpack/drop /!/make/register |
|
/o/map |
higher.osen | (higher.osen) | |
/o/match |
generated | /!/unpack/drop /!/match |
|
/o/max |
C:OSEN_PUSHFN | macro OSEN_WRAP_BUILTIN_BINOP |
\fnbinop{MAX} |
/o/min |
C:OSEN_PUSHFN | macro OSEN_WRAP_BUILTIN_BINOP |
\fnbinop{MIN} |
/o/mod |
C:OSEN_PUSHFN | macro OSEN_WRAP_BUILTIN_BINOP |
\fnbinop{MOD} |
/o/mul |
C:OSEN_PUSHFN | macro OSEN_WRAP_BUILTIN_BINOP |
\fnbinop{MUL} |
/o/neg |
C:OSEN_PUSHFN | macro OSEN_WRAP_BUILTIN_BINOP |
\fn{NEG} |
/o/neq |
C:OSEN_PUSHFN | macro OSEN_WRAP_BUILTIN_BINOP |
\fnbinop{NEQ} |
/o/nfill |
C:OSEN_PUSHFN | ose_peekType, ose_unpackDrop, ose_peekType, ose_peekMessageArgType, ose_popInt32, ose_peekType, ose_getBundlePtr, ose_getLastBundleElemOffset, ose_getNthPayloadItem, ose_readByte, ose_getPayloadItemSize, ose_pnbytes, ose_readSize, ose_pnbytes, ose_incSize, ose_writeInt32, ose_writeByte, ose_writeByte, ose_nip |
|
/o/nil |
C:registered | (C:registered) | |
/o/not |
C:OSEN_PUSHFN | macro OSEN_WRAP_BUILTIN_BINOP |
\fnunop{NOT} |
/o/nth |
C:OSEN_PUSHFN | ose_peekType, ose_unpackDrop, ose_peekType, ose_nth, ose_getLastBundleElemOffset, ose_getNthPayloadItem, ose_readByte, ose_swap, ose_swap, ose_nth, ose_nth, ose_nth, ose_peekType, ose_getBundleElemElemCount, ose_getLastBundleElemOffset, ose_unpackDrop |
|
/o/or |
C:OSEN_PUSHFN | macro OSEN_WRAP_BUILTIN_BINOP |
\fnbinop{OR} |
/o/out |
C:OSEN_PUSHFN | ose_peekType, ose_getContextMessageOffset, ose_enter, ose_getBundleElemCount, ose_unpackDrop, ose_getBundleElemCount, ose_peekType, ose_elemToBlob, ose_swap, ose_peekType, ose_elemToBlob, ose_swap, ose_concatenateElems, ose_swap, ose_peekType, ose_peekMessageArgType, ose_peekString, ose_drop, ose_pushString, ose_concatenateElems, ose_moveStringToAddress, ose_moveElem, osevm_run, ose_pushMessage, ose_pushMessage |
|
/o/parse |
host module | (host module) | |
/o/pmatch |
generated | /!/unpack/drop /!/pmatch |
|
/o/pop |
generated | /!/unpack/drop /!/pop |
|
/o/pop/all/drop/bundle |
generated | /!/unpack/drop /!/pop/all/drop/bundle |
|
/o/pow |
C:OSEN_PUSHFN | macro OSEN_WRAP_BUILTIN_BINOP |
\fnbinop{POW} |
/o/print |
prelude.ose | /!/unpack/drop /!/osen/format /!/print |
|
/o/println |
prelude.ose | /!/unpack/drop /!/osen/format /!/println |
|
/o/inspect |
osen_print.c | the value printer with the collapse off |
|
/o/push |
generated | /!/unpack/drop /!/push |
|
/o/put |
higher.osen | (higher.osen) | |
/o/range |
C:OSEN_PUSHFN | ose_peekType, ose_countElems, ose_getBundleElemCount, ose_unpackDrop, ose_getBundleElemCount, ose_peekType, ose_peekMessageArgType, ose_popInt32, ose_pushMessage, ose_pushInt32, ose_push |
|
/o/register/flags |
C:registered | ose_peekType, ose_unpackDrop, ose_getBundlePtr, ose_context_get_flags, ose_drop, ose_pushBundle, ose_pushMessage, ose_push |
|
/o/register/flags/set |
C:registered | ose_peekType, ose_unpackDrop, ose_peekType, ose_getLastBundleElemOffset, ose_readInt32, ose_readInt32, ose_getBundleElemType, ose_readString, ose_peekMessageArgTypeAtOffset, ose_readInt32, ose_getBundleElemPayloadOffset, ose_drop, ose_getBundlePtr, ose_context_set_flags, ose_drop, ose_pushInt32 |
|
/o/rest |
C:OSEN_PUSHFN | ose_pop, ose_nip, ose_pushInt32, ose_decatenateElemFromStart, ose_nip |
|
/o/reverse |
C:OSEN_PUSHFN | ose_peekType, ose_unpackDrop, ose_reverse |
|
/o/route |
C:OSEN_PUSHFN | ose_typechk2, ose_typechk2, ose_unpackDrop, ose_peekType, ose_unpackDrop, ose_peekType, ose_swap, ose_swap, ose_swap, ose_routeWithDelegation |
|
/o/select |
C:OSEN_PUSHFN | ose_typechk2, ose_typechk2, ose_unpackDrop, ose_peekType, ose_unpackDrop, ose_peekType, ose_swap, ose_swap, ose_swap, ose_selectWithDelegation |
|
/o/send |
prelude.ose | /!/unpack/drop /!/send |
|
/o/sort |
C:OSEN_PUSHFN | (no libose call) | |
/o/sortidxs |
C:OSEN_PUSHFN | (no libose call) | |
/o/split/string/fromend |
generated | /!/unpack/drop /!/split/string/fromend |
|
/o/sub |
C:OSEN_PUSHFN | macro OSEN_WRAP_BUILTIN_BINOP |
\fnbinop{SUB} |
/o/toblob/fromelem |
generated | /!/unpack/drop /!/toblob/fromelem |
|
/o/toblob/fromitem |
generated | /!/unpack/drop /!/toblob/fromitem |
|
/o/todouble |
generated | /!/unpack/drop /!/todouble |
|
/o/toelem/fromblob |
C:registered | macro OSEN_WRAP_BUILTIN |
|
/o/tofloat |
generated | /!/unpack/drop /!/tofloat |
|
/o/toint16 |
generated | /!/unpack/drop /!/toint16 |
|
/o/toint32 |
generated | /!/unpack/drop /!/toint32 |
|
/o/toint64 |
generated | /!/unpack/drop /!/toint64 |
|
/o/toint8 |
generated | /!/unpack/drop /!/toint8 |
|
/o/tostring |
generated | /!/unpack/drop /!/tostring |
|
/o/tosymbol |
generated | /!/unpack/drop /!/tosymbol |
|
/o/totimetag |
generated | /!/unpack/drop /!/totimetag |
|
/o/touint16 |
generated | /!/unpack/drop /!/touint16 |
|
/o/touint32 |
generated | /!/unpack/drop /!/touint32 |
|
/o/touint64 |
generated | /!/unpack/drop /!/touint64 |
|
/o/touint8 |
generated | /!/unpack/drop /!/touint8 |
|
/o/true |
C:registered | (C:registered) | |
/o/typeof0 |
generated | /!/unpack/drop /!/typeof0 |
|
/o/typeof1 |
generated | /!/unpack/drop /!/typeof1 |
|
/o/typeof2 |
generated | /!/unpack/drop /!/typeof2 |
|
/o/typetag/set |
generated | /!/unpack/drop /!/typetag/set |
|
/o/unpack/drop |
generated | /!/unpack/drop /!/unpack/drop |
|
/o/unwrap |
prelude.ose | (prelude.ose) | |
/o/zipwith |
C:OSEN_PUSHFN | ose_unpackDrop, ose_swap, ose_swap, ose_peekType, ose_swap, ose_getBundlePtr, ose_getLastBundleElemOffset, ose_readInt32, ose_readInt32, ose_pushMessage, ose_pstrlen, ose_pstrlen, ose_pushMessage, ose_readInt32, ose_pushBundle, ose_pushMessage, ose_push, ose_swap, ose_push, ose_swap, ose_push |
|
/o/zipwithrest |
C:registered | ose_blobToElem — one call; its libose spec is the meaning |
Coverage
140 names. 98 have an implementation derived from the code; 42 are left pointing at their origin, which is where a human has to look.