X-Git-Url: http://git.subgeniuskitty.com/vvhitespace/.git/blobdiff_plain/ae1f85a178241c826a0b6a72ace12049b9907561..d5a0b33775da13d1589252f75f2f86b81ffff599:/stdlib/README.md diff --git a/stdlib/README.md b/stdlib/README.md index c64be4b..6c26770 100644 --- a/stdlib/README.md +++ b/stdlib/README.md @@ -1,41 +1,101 @@ # Overview # This folder contains a library of useful functions written in VVhitespace. -Standard include guards are used with `cpp` to include the stdlib in user -programs. For an example, see `examples/hello-stdlib`. - -# Reservations # - -Since all labels share a global namespace, the standard library makes the -following reservations: - -## Label ## - - 00000000 0xxxxxxx - reserved for stdlib function entry points - 00000000 1xxxxxxx - unassigned - 0xxxxxxx xxxxxxxx - reserved for private use by stdlib - 1xxxxxxx xxxxxxxx - available for use in user programs - -## Heap and Pointers ## - -The first 16 heap addresses (`0-15`) are reserved when using the stdlib. - -By convention, functions which return a pointer will use the address `0` to -represent a `NULL` pointer. - -# Entry Points # +They are intended to remove the tedium of frequently repeated patterns while +remaining short enough to easily comprehend and modify. + +For those eager to jump right in, all functions have comments in the source +code containing a text description as well as both call and return stacks. +Simply `#include` the relevant file, setup your call stack per the +documentation and then `JSR` to the stdlib function of your choice. + +Some functions, like `deepdup`, `stackrotate` and `stackrotatereverse`, ease +stack manipulations by allowing easy access to elements deep on the stack. +Similarly, `slurp` and `spew` help move bulk data between the stack and heap. + +User interactions were also targeted. The included `printf` function provides a +variety of substitutions to ease user interactions. For user input, `get user +string` and `atoi` allow easy creation of basic user interfaces. + +The library includes a variety of bitwise logic functions as well as heap +manipulation functions and a handful of math functions including a random +number generator. + + +# Instructions # + +Before we can use this library, we must `#include` it in our program. Looking +at the "Entry Points" table below, if we wanted to call `deepdup` we would need +to `#include ` in our code, but where? + +Recall that VVhitespace processes our code from top to bottom. Thus, it is +always safe to `#include` files at the bottom, after our program's text. This +way the files are included in our source code but won't be accidentally +executed by the interpreter. For example: + + @ Put two elements on the stack. + SSSTTTTSTSSN | PUSH 244 + SSSTN | PUSH 1 + @ Duplicate the deeper element. + SSSTSN | PUSH 2 (argument to deepdup) + NSTTTSSN | JSR > 1100 (deepdup) + NNN | DIE + #include + +What about that `PUSH 2` instruction that is an argument to `deepdup`? If we +check `stack.pvvs`, we will find the following comment above the `deepdup` +function: + + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + @ Name: + @ deepdup + @ Description: + @ Duplicates an item deep on the stack, placing the duplicate on TOS. + @ By default, maximum depth is 13. + @ True maximum depth is (max depth of stackrotate & stackrotatereverse)-1. + @ Call Stack: + @ stack word n + @ ... + @ stack word 1 + @ dupdepth <-- TOS + @ Return Stack: (dupdepth=3) + @ stack word n + @ ... + @ stack word 1 + @ copy of stack word 3 <-- TOS + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + NSSVTTSSN | Mark: 1100 (deepdup) + ... + +From the "Call Stack" example, we can see that `deepdup` requires a `dupdepth` +argument on the TOS. Since we wanted to duplicate the second item on the stack, +we used `PUSH 2` immediately before calling `deepdup`. + +In addition to the call stack, the code comments also show you what to expect +on the return stack, as well as any other information you might need in order +to use the function. + + +# Resource Reservations # + + +## Entry Points ## The following labels are entry points to stdlib functions. Read the header comment for each function to learn the call and return stack. 000xxx - reserved - 001xxx - print functions - 1000 ----- print string from stack (stdio.pvvs) - 1001 ----- print string from heap (stdio.pvvs) - 1010 ----- print number from stack (stdio.pvvs) + 001xxx - core functions + 1000 ----- printf (stdio.pvvs) + 1001 ----- print number from stack (stdio.pvvs) + 1010 ----- stackrotate (stack.pvvs) + 1011 ----- stackrotatereverse (stack.pvvs) + 1100 ----- deepdup (stack.pvvs) 010xxx - math functions 10000 ----- random (math.pvvs) 10001 ----- absolute value (math.pvvs) + 10010 ----- greatest common divisor (math.pvvs) + 10011 ----- fastrand (math.pvvs) 011xxx - heap functions 11000 ----- memset (heap.pvvs) 11001 ----- memcpy (heap.pvvs) @@ -47,32 +107,133 @@ header comment for each function to learn the call and return stack. 11111 ----- spew (heap.pvvs) 100xxx - string functions 100000 ----- strlen (string.pvvs) - 101xxx - unassigned + 100001 ----- isdigit (string.pvvs) + 100010 ----- get user string (string.pvvs) + 101xxx - logic functions + 101000 ----- not (logic.pvvs) + 101001 ----- and (logic.pvvs) + 101010 ----- or (logic.pvvs) + 101011 ----- xor (logic.pvvs) + 101100 ----- rshift (logic.pvvs) + 101101 ----- lshift (logic.pvvs) 110xxx - conversion functions + 110000 ----- atoi (convert.pvvs) 111xxx - debug functions 111000 ----- dump heap (debug.pvvs) 111001 ----- dump stack (debug.pvvs) + 111010 ----- print sign (debug.pvvs) + 111011 ----- print magnitude (debug.pvvs) + 111100 ----- print string (debug.pvvs) + 111101 ----- print signed number (debug.pvvs) + 111110 ----- stdlib version (debug.pvvs) 1xxxxxx - reserved for less common entry points - 1000000 ----- slurp registers (heap.pvvs) - 1000001 ----- spew registers (heap.pvvs) + 1000000 ----- lowbitand (logic.pvvs) + 1000001 ----- 1000010 ----- print sign of number (stdio.pvvs) 1000011 ----- print magnitude of number (stdio.pvvs) + 1000100 ----- print string from stack (stdio.pvvs) + 1000101 ----- print string from heap (stdio.pvvs) + + +## Labels ## + +Since all labels share a global namespace, the standard library makes the +following reservations: + + 00000000 0xxxxxxx - reserved for stdlib function entry points + 00000000 1xxxxxxx - available for use in user programs + 0xxxxxxx xxxxxxxx - reserved for private use by stdlib + 1xxxxxxx xxxxxxxx - available for use in user programs + + +## Heap and Pointers ## + +The first 16 heap addresses (`0-15`) are reserved when using the stdlib. +Within that reservation, heap[0] is used by `random` and the block +heap[1]-heap[15] by the stack rotation subroutines which time-share +pseudo-registers between the various stdlib subroutines. + +By convention, chosen since no function other than `random` should use heap[0], +functions which return a pointer will use the address `0` to represent a `NULL` +pointer. + # Misc # -By convention, each public stdlib label will have 8 bits of -private label space associated with it, formed as follows: + +## Bitwise Logic Constants ## + +Be cautious when pushing constants in your code for use as bit arrays. Due to +the mismatch between the VVhitespace language's sign-magnitude representation +of integers and the interpreter's internal twos-complement representation, bit +arrays with a leading `1` (i.e. negative numbers) may appear quite different +then expected in your source code. + +For example, to push a 64-bit array of all `1`'s on to the stack we must push +`SSTTN`, or `-1`. + + +## Extending Heap Reservation ## + +By default, the stdlib uses the first 16 heap addresses. All heap access (other +than heap[0] as a seed) occurs through `stackrotate` and `stackrotatereverse`. +Edit these functions to increase the stdlib's heap reservation. + +The remainder of the stdlib is written to automatically use the new allocation. +Functions like `printf`, for example, allow more substitutions when the heap +allocation is increased. + + +## Private Label Space ## + +By convention, each public stdlib label will have 8 bits of private label space +associated with it, formed as follows: 00001000 xxxxxxxx - for use by 1000 00001001 xxxxxxxx - for use by 1001 ...etc -# Slurp and Spew # -The stdlib uses heap[1] to heap[15] as registers. +## Strings ## + +Strings in VVhitespace are stored as one character per 64-bit word since the +`LOAD` and `STORE` instructions are word length and the heap is word +addressable. + +All strings terminate with an ASCII NUL (`\0`) character. + + +## Using the C Preprocessor ## + +The standard library uses ordinary include guards of the following form: + + #ifndef FOO + #define FOO + ... + #endif + +This means you can `#include` a file multiple times without problems. To ease +refactoring, I recommend writing the `#include` statements per-function rather +than per-file. See the stdlib for examples. + +Use of the C Preprocessor also means its syntax must be respected as though the +file were C rather than VVhitespace. For example, use of a single apostrophe in +a VVhitespace comment (e.g. don't) throws out a warning: + + warning: missing terminating ' character [-Winvalid-pp-token] + +You won't run into any errors if you copy the stdlib's format but if you +stray I'm sure one could concoct some combination of characters that is both a +comment in VVhitespace and a hard error for `cpp`. + + +## Whitespace Compatibility ## + +Most of this library will run on most Whitespace interpreters. Some parts, like +the bitwise logic functions, make assumptions about the representation of +integers in the interpreter that may be less portable than the rest of the +library. -The `slurpreg` and `spewreg` functions facilitate this by `spew`ing the stack -onto the heap's pseudo-registers or `slurp`ing the pseudo-registers back to the -stack. The functions preserve order in complementary fashion. +Regardless, tests are included for every stdlib function and can be run though +the Whitespace interpreter of your choice to determine compatibility. -The `spewreg` function uses `heap[0]` for storage.