|
libose
|
Go to the source code of this file.
Macros | |
| #define | OSEVM_WRAP_DECL(name) void osevm_##name(ose_bundle bundle); |
Declare void osevm_<name>(ose_bundle osevm), the VM-level form of the stack operation ose_<name>(). | |
| #define | OSEVM_WRAP_DEFN(name) |
| Define the function OSEVM_WRAP_DECL declares. | |
| #define | OSEVM_WRAP_DEFPRED(name) |
Define osevm_<name>() for a predicate bool ose_<name>(int32_t). | |
| #define | OSEVM_FRAME_MAGIC 0x2346524D /* "#FRM" */ |
The word after #bundle in a frame's header, "#FRM", by which osevm_return tells a frame from anything else on the dump. | |
Enumerations | |
| enum | { OSEVM_FRAME_INPUT = 1 , OSEVM_FRAME_ENV = 2 , OSEVM_FRAME_STACK = 4 , OSEVM_FRAME_CONTROL = 8 , OSEVM_FRAME_STACK_BELOW = 16 } |
Functions | |
| int | osevm_pushFrame (ose_bundle osevm, int32_t which, const char *const env, int32_t envlen) |
| Save registers to the dump as ONE element – whole, or not at all. | |
| void | osevm_exec1 (ose_bundle osevm) |
| Execute a bundle on the stack. | |
| void | osevm_exec2 (ose_bundle osevm) |
| Execute a bundle on the stack. | |
| void | osevm_exec3 (ose_bundle osevm) |
| Execute a bundle on the stack. | |
| void | osevm_exec (ose_bundle osevm) |
| Synonym for osevm_exec2. | |
| void | osevm_if (ose_bundle osevm) |
| Execute one of two bundles, depending on the value of the int in the last message on the stack. | |
| void | osevm_dotimes (ose_bundle osevm) |
| Execute a bundle repeatedly. | |
| void | osevm_copyRegisterToElem (ose_bundle osevm) |
Copy a register onto the stack as one element – the /> instruction. | |
| void | osevm_appendElemToRegister (ose_bundle osevm) |
Append the contents of the top element to a register – /<<. | |
| void | osevm_replaceRegisterWithElem (ose_bundle osevm) |
Replace a register's contents with the top element's – /<. | |
| void | osevm_moveElemToRegister (ose_bundle osevm) |
Move the top element into a register – /-. | |
| void | osevm_copyElemToRegister (ose_bundle osevm) |
| Copy the top element into a register. | |
| void | osevm_apply (ose_bundle osevm) |
Apply the top of the stack – the /! instruction, and the second half of osevm_funcall. | |
| void | osevm_map (ose_bundle osevm) |
Apply a function to each item of a message, or each element of a bundle – /!/map. | |
| void | osevm_return (ose_bundle osevm) |
Pop the topmost frame from the dump and restore what it carried – /!/return, and what the VM runs when the control empties inside a call. | |
| void | osevm_version (ose_bundle osevm) |
Push the library's version – /!/version. | |
| void | osevm_assignStackToRegister (ose_bundle osevm) |
| Gather the stack into the bundle at its bottom, as one message named by the string on top. | |
| void | osevm_assignStackToEnv_impl (ose_bundle osevm, ose_bundle env, int replace, int new_msg_first, char bundle_typetag) |
| Bind everything on the stack, as one message, into a bundle. | |
| void | osevm_assignStackToEnv (ose_bundle osevm) |
Bind the stack into the environment – the /@ instruction, and the default OSEVM_ASSIGN. | |
| void | osevm_lookupInEnv_impl (ose_bundle osevm) |
Look a name up – the /$ instruction, and the default OSEVM_LOOKUP. | |
| void | osevm_lookupInEnv (ose_bundle osevm) |
| Call whatever OSEVM_LOOKUP names. | |
| void | osevm_plookupInEnv_impl (ose_bundle osevm) |
| Does nothing. | |
| void | osevm_plookupInEnv (ose_bundle osevm) |
| Does nothing. | |
| void | osevm_funcall (ose_bundle osevm) |
Look a name up and apply what it finds – the /! instruction on a string, and the default OSEVM_FUNCALL. | |
| void | osevm_makeRegister (ose_bundle osevm) |
Create a register from a size and a name on the stack; the standard library binds it as /o/make/register. | |
| void | osevm_quote (ose_bundle bundle) |
| Does nothing – the ‘/’` instruction, and the default OSEVM_QUOTE. | |
| void | osevm_toType (ose_bundle bundle) |
| Run ose_toType() on the stack; see OSEVM_WRAP_DECL. | |
| void | osevm_toInt32 (ose_bundle bundle) |
Run ose_toInt32() on the stack – the /,/i/ instruction on an address; see OSEVM_WRAP_DECL. | |
| void | osevm_toFloat (ose_bundle bundle) |
| Run ose_toFloat() on the stack; see OSEVM_WRAP_DECL. | |
| void | osevm_toString (ose_bundle bundle) |
| Run ose_toString() on the stack; see OSEVM_WRAP_DECL. | |
| void | osevm_toBlob (ose_bundle bundle) |
| Run ose_toBlob() on the stack; see OSEVM_WRAP_DECL. | |
| void | osevm_appendByte (ose_bundle bundle) |
| Run ose_appendByte() on the stack; see OSEVM_WRAP_DECL. | |
| #define OSEVM_WRAP_DECL | ( | name | ) | void osevm_##name(ose_bundle bundle); |
Declare void osevm_<name>(ose_bundle osevm), the VM-level form of the stack operation ose_<name>().
The declared function takes the machine rather than a bundle: it fetches the stack register with OSEVM_STACK and runs ose_<name>() on it. See OSEVM_WRAP_DEFN for what it does with errno, which is the only thing the wrapper adds. The functions declared with it below (osevm_toInt32(), osevm_toString(), ...) are the ones the VM dispatches for the /,/i/ family of instructions and the ones the standard library binds.
| #define OSEVM_WRAP_DEFN | ( | name | ) |
Define the function OSEVM_WRAP_DECL declares.
Clears errno on the stack register, runs ose_<name>() on it, and if that set errno, moves the value to the machine and clears the register again – so a failure is reported where osevm_run() reads it, and a stale value from earlier is not charged to this call. The block comment above says why.
| #define OSEVM_WRAP_DEFPRED | ( | name | ) |
Define osevm_<name>() for a predicate bool ose_<name>(int32_t).
Pops an int32 from the stack (a wrong type sets errno on the machine, as OSEVM_WRAP_DEFN does), calls the predicate with it, and pushes 1 or 0. Nothing in libose uses this macro today.
| void osevm_appendElemToRegister | ( | ose_bundle | osevm | ) |
Append the contents of the top element to a register – /<<.
With a three-character name on top, /<</_e, the name is dropped and the contents of the element then on top of the stack (a bundle) are appended to the named register, as ose_appendBundle() does. With six characters the second register is the source and the first the destination.
| void osevm_apply | ( | ose_bundle | osevm | ) |
Apply the top of the stack – the /! instruction, and the second half of osevm_funcall.
What happens depends on what is on top:
/</_e already in the saved control, so that osevm_return hands the callee's environment back), the bundle's elements are moved into the input in reverse, and the control is cleared. If the dump has no room, nothing moves and errno is OSE_ERR_RANGE.ose_fn with the machine.#bundle is turned into a bundle element and applied as above./!/name reaches, so it raises rather than asserting. | void osevm_assignStackToEnv | ( | ose_bundle | osevm | ) |
Bind the stack into the environment – the /@ instruction, and the default OSEVM_ASSIGN.
The address is the string on top. If its first OSE_REGISTER_ADDRESS_LEN characters name an existing register (/xy/rest), the rest is bound into that register instead, as ose_addressToRegister() decides. Then osevm_assignStackToEnv_impl with replace set, the message appended last, and bundles stored as blobs. See the registers document in o.se for the convention.
| void osevm_assignStackToEnv_impl | ( | ose_bundle | osevm, |
| ose_bundle | env, | ||
| int | replace, | ||
| int | new_msg_first, | ||
| char | bundle_typetag | ||
| ) |
Bind everything on the stack, as one message, into a bundle.
The top of the stack is a message whose payload is the address to bind. Every element beneath it becomes part of one new message with that address: a message contributes its items, a bundle contributes one item of type bundle_typetag holding the bundle whole. The stack is cleared afterwards. This is osevm_assignStackToEnv without its register handling, for callers that choose the target bundle themselves.
| osevm | The machine. |
| env | The bundle to write the message into – the environment, or any other bundle. |
| replace | If nonzero, every message already in env with the same address is removed first. |
| new_msg_first | If nonzero the message is put at the start of env; otherwise at the end. |
| bundle_typetag | The typetag a bundle on the stack is stored under, OSETT_BLOB normally. |
env cannot grow by the size of the new message, ose_incSize() sets errno on env and the function returns with the stack still holding what it held. | void osevm_assignStackToRegister | ( | ose_bundle | osevm | ) |
Gather the stack into the bundle at its bottom, as one message named by the string on top.
The first element of the stack must be a bundle. Everything above it and below the topmost message is pushed into that bundle (bundles as blobs), then the string on top becomes the address of the message and it is pushed too. With exactly two elements – the bundle and one message – the message is pushed after its string, if it has one, is moved to the address.
| void osevm_copyElemToRegister | ( | ose_bundle | osevm | ) |
Copy the top element into a register.
As osevm_moveElemToRegister, with ose_copyElem() in place of ose_moveElem(): the element stays on the stack. No instruction sigil dispatches to this one; the standard library binds it.
| void osevm_copyRegisterToElem | ( | ose_bundle | osevm | ) |
Copy a register onto the stack as one element – the /> instruction.
The top of the stack is a message holding one string, a register name. />/_e copies the whole environment onto the stack as a bundle element. Six characters name two registers, source then destination: the first is copied as an element onto the end of the second rather than onto the stack. On success the name is dropped.
Otherwise nothing is moved, the name stays on the stack, and errno on the machine says why: OSE_ERR_ELEM_TYPE (not a message), OSE_ERR_ITEM_TYPE (not a string), OSE_ERR_ITEM_COUNT (wrong length) or OSE_ERR_UNKNOWN_CONTEXT_BUNDLE (no such register).
| void osevm_dotimes | ( | ose_bundle | osevm | ) |
Execute a bundle repeatedly.
This function causes a bundle in the second to last position to be executed n times, where n is an integer in the last message of the bundle.
| void osevm_exec | ( | ose_bundle | osevm | ) |
Synonym for osevm_exec2.
| void osevm_exec1 | ( | ose_bundle | osevm | ) |
Execute a bundle on the stack.
This function copies the current execution context (input, control, environment, and the stack), and executes the bundle on top of the stack.
The environment is not changed: the bundle runs in whatever environment is already current. osevm_exec2 installs a new one; that single difference is all that separates the two.
/o/finalize/toplevelexec exists, and why a host with re-entrant input needs a finalize hook of its own. | void osevm_exec2 | ( | ose_bundle | osevm | ) |
Execute a bundle on the stack.
This function copies the current execution context (input, control, environment, and the stack), and executes the last bundle on the stack with the second to last as the environment.
Identical to osevm_exec1 except that the bundle below the one being executed is installed as the environment for the duration.
| void osevm_exec3 | ( | ose_bundle | osevm | ) |
Execute a bundle on the stack.
This function copies the current execution context (input, control, environment, and the stack), and executes the last bundle on the stack with the second to last as the environment, and the third to last as the stack.
Identical to osevm_exec2 except that the executed bundle's contents are unpacked onto the stack rather than left packed.
| void osevm_funcall | ( | ose_bundle | osevm | ) |
Look a name up and apply what it finds – the /! instruction on a string, and the default OSEVM_FUNCALL.
OSEVM_LOOKUP followed by osevm_apply. If the lookup finds nothing, the name is still on top and apply leaves it there (a message that is not a pointer or a bundle applies to itself), so with the default lookup an unbound call is silent.
| void osevm_if | ( | ose_bundle | osevm | ) |
Execute one of two bundles, depending on the value of the int in the last message on the stack.
This function expects three elements on the stack: the last element is the test, which must be a message containing a single integer. If the integer value is non-zero, the second to last bundle will be executed, otherwise the third to last bundle will be executed. The execution of the bundle proceeds according to osevm_exec1.
| void osevm_lookupInEnv | ( | ose_bundle | osevm | ) |
Call whatever OSEVM_LOOKUP names.
osevm_lookupInEnv_impl unless a build has overridden the hook. This is the one the standard library binds, so a program that calls lookup by name reaches the lookup the host chose.
| void osevm_lookupInEnv_impl | ( | ose_bundle | osevm | ) |
Look a name up – the /$ instruction, and the default OSEVM_LOOKUP.
The top of the stack is a message holding an address. If the address begins with the name of an existing register, that register is searched first for the remainder; then the environment is searched for the whole address. The first element whose address matches – by ose_getFirstOffsetForMatch(), so OSC pattern matching applies – replaces the name on the stack with a copy of itself. If nothing matches, the name is left on the stack and errno is not set; a host that wants an unbound name to raise supplies its own OSEVM_LOOKUP.
| void osevm_makeRegister | ( | ose_bundle | osevm | ) |
Create a register from a size and a name on the stack; the standard library binds it as /o/make/register.
The name is on top and the size beneath it. Calls ose_pushContextMessage() with them and, if it succeeds, drops the name.
ut_ose_preconditions pins the refusal. | void osevm_map | ( | ose_bundle | osevm | ) |
Apply a function to each item of a message, or each element of a bundle – /!/map.
The function is on top of the stack and the sequence beneath it. One step is taken per call: the next item (or element) and the function are arranged on the stack, /!/apply and /!/map are pushed onto the control, and the call returns, so the machine's own loop drives the iteration and results accumulate on the stack. When the sequence is exhausted both the sequence and the function are dropped.
OSE_CONF_DEBUG, unchecked otherwise.| void osevm_moveElemToRegister | ( | ose_bundle | osevm | ) |
Move the top element into a register – /-.
/-/_i drops the name and moves the element then on top of the stack onto the end of the input register, as ose_moveElem() does: the element itself, not its contents, so a bundle stays a bundle. Six characters name source and destination registers.
| void osevm_plookupInEnv | ( | ose_bundle | osevm | ) |
| void osevm_plookupInEnv_impl | ( | ose_bundle | osevm | ) |
| int osevm_pushFrame | ( | ose_bundle | osevm, |
| int32_t | which, | ||
| const char *const | env, | ||
| int32_t | envlen | ||
| ) |
Save registers to the dump as ONE element – whole, or not at all.
| osevm | The machine. |
| which | Which registers to save: any of OSEVM_FRAME_INPUT, OSEVM_FRAME_ENV, OSEVM_FRAME_STACK, OSEVM_FRAME_CONTROL. A register named here but EMPTY is omitted, and a register not named is omitted too; osevm_return restores an omitted register as empty. That is how osevm_exec1 says "the stack slot is the callee's" – it has already moved the top of the stack into the input. |
| env | Bytes to put in the environment slot INSTEAD of /_e, as one OSC element – size word first. A client whose frames do not carry the whole environment puts the one binding its own repair needs here. NULL for the usual case. Ignored when OSEVM_FRAME_ENV is in which. |
| envlen | The length of env, its size word included. |
Asks ose_spaceAvailable() rather than trying the grow. A refused ose_incSize() sets errno and declines in a release build, and asserts in a debug one, which is right for a size that is already wrong and wrong for a dump that is simply full – and the difference presents as an abort on a desktop and a silent decline on a board.
| void osevm_quote | ( | ose_bundle | bundle | ) |
Does nothing – the ‘/’` instruction, and the default OSEVM_QUOTE.
The VM has already pushed the quoted text as a string before calling this; quoting needs nothing more. The hook exists so a host can give it a meaning.
| void osevm_replaceRegisterWithElem | ( | ose_bundle | osevm | ) |
Replace a register's contents with the top element's – /<.
/</_e drops the name and makes the environment a copy of the bundle then on top of the stack, as ose_replaceBundle() does; the element is consumed. Six characters name source and destination registers as osevm_appendElemToRegister does.
ut_ose_preconditions pins that a non-address on top sets errno and leaves the environment untouched. | void osevm_return | ( | ose_bundle | osevm | ) |
Pop the topmost frame from the dump and restore what it carried – /!/return, and what the VM runs when the control empties inside a call.
The frame is unpacked in place and each register it carried is put back: the control is replaced; the saved stack, if any, goes underneath whatever the callee left; then the callee's environment is copied onto the stack as a bundle, and the saved environment and input are restored. A register the frame did not carry is restored empty. A frame is written whole by osevm_pushFrame, so the shape here is always the shape that was saved.
ut_ose_preconditions pins that an empty dump is refused this way. | void osevm_version | ( | ose_bundle | osevm | ) |
Push the library's version – /!/version.
Pushes ose_version_string() and ose_date_compiled_string() as two string messages, with ose_debug_string() between them in a build that defines OSE_DEBUG.