| 1 | # Overview # |
| 2 | |
| 3 | This folder contains a library of useful functions written in VVhitespace. |
| 4 | They are intended to remove the tedium of frequently repeated patterns while |
| 5 | remaining short enough to easily comprehend and modify. |
| 6 | |
| 7 | For those eager to jump right in, all functions have comments in the source |
| 8 | code containing a text description as well as both call and return stacks. |
| 9 | Simply `#include` the relevant file, setup your call stack per the |
| 10 | documentation and then `JSR` to the stdlib function of your choice. |
| 11 | |
| 12 | Some functions, like `deepdup`, `stackrotate` and `stackrotatereverse`, ease |
| 13 | stack manipulations by allowing easy access to elements deep on the stack. |
| 14 | Similarly, `slurp` and `spew` help move bulk data between the stack and heap. |
| 15 | |
| 16 | User interactions were also targeted. The included `printf` function provides a |
| 17 | variety of substitutions to ease user interactions. For user input, `get user |
| 18 | string` and `atoi` allow easy creation of basic user interfaces. |
| 19 | |
| 20 | The library includes a variety of bitwise logic functions as well as heap |
| 21 | manipulation functions and a handful of math functions including a random |
| 22 | number generator. |
| 23 | |
| 24 | |
| 25 | # Instructions # |
| 26 | |
| 27 | Before we can use this library, we must `#include` it in our program. Looking |
| 28 | at the "Entry Points" table below, if we wanted to call `deepdup` we would need |
| 29 | to `#include <stack.pvvs>` in our code, but where? |
| 30 | |
| 31 | Recall that VVhitespace processes our code from top to bottom. Thus, it is |
| 32 | always safe to `#include` files at the bottom, after our program's text. This |
| 33 | way the files are included in our source code but won't be accidentally |
| 34 | executed by the interpreter. For example: |
| 35 | |
| 36 | @ Put two elements on the stack. |
| 37 | SSSTTTTSTSSN | PUSH 244 |
| 38 | SSSTN | PUSH 1 |
| 39 | @ Duplicate the deeper element. |
| 40 | SSSTSN | PUSH 2 (argument to deepdup) |
| 41 | NSTTTSSN | JSR > 1100 (deepdup) |
| 42 | NNN | DIE |
| 43 | #include <stack.pvvs> |
| 44 | |
| 45 | What about that `PUSH 2` instruction that is an argument to `deepdup`? If we |
| 46 | check `stack.pvvs`, we will find the following comment above the `deepdup` |
| 47 | function: |
| 48 | |
| 49 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ |
| 50 | @ Name: |
| 51 | @ deepdup |
| 52 | @ Description: |
| 53 | @ Duplicates an item deep on the stack, placing the duplicate on TOS. |
| 54 | @ By default, maximum depth is 13. |
| 55 | @ True maximum depth is (max depth of stackrotate & stackrotatereverse)-1. |
| 56 | @ Call Stack: |
| 57 | @ stack word n |
| 58 | @ ... |
| 59 | @ stack word 1 |
| 60 | @ dupdepth <-- TOS |
| 61 | @ Return Stack: (dupdepth=3) |
| 62 | @ stack word n |
| 63 | @ ... |
| 64 | @ stack word 1 |
| 65 | @ copy of stack word 3 <-- TOS |
| 66 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ |
| 67 | NSSVTTSSN | Mark: 1100 (deepdup) |
| 68 | ... |
| 69 | |
| 70 | From the "Call Stack" example, we can see that `deepdup` requires a `dupdepth` |
| 71 | argument on the TOS. Since we wanted to duplicate the second item on the stack, |
| 72 | we used `PUSH 2` immediately before calling `deepdup`. |
| 73 | |
| 74 | In addition to the call stack, the code comments also show you what to expect |
| 75 | on the return stack, as well as any other information you might need in order |
| 76 | to use the function. |
| 77 | |
| 78 | |
| 79 | # Resource Reservations # |
| 80 | |
| 81 | Since all labels share a global namespace, the standard library makes the |
| 82 | following reservations: |
| 83 | |
| 84 | |
| 85 | ## Entry Points ## |
| 86 | |
| 87 | The following labels are entry points to stdlib functions. Read the |
| 88 | header comment for each function to learn the call and return stack. |
| 89 | |
| 90 | 000xxx - reserved |
| 91 | 001xxx - core functions |
| 92 | 1000 ----- printf (stdio.pvvs) |
| 93 | 1001 ----- print number from stack (stdio.pvvs) |
| 94 | 1010 ----- stackrotate (stack.pvvs) |
| 95 | 1011 ----- stackrotatereverse (stack.pvvs) |
| 96 | 1100 ----- deepdup (stack.pvvs) |
| 97 | 010xxx - math functions |
| 98 | 10000 ----- random (math.pvvs) |
| 99 | 10001 ----- absolute value (math.pvvs) |
| 100 | 10010 ----- greatest common divisor (math.pvvs) |
| 101 | 011xxx - heap functions |
| 102 | 11000 ----- memset (heap.pvvs) |
| 103 | 11001 ----- memcpy (heap.pvvs) |
| 104 | 11010 ----- memrand (heap.pvvs) |
| 105 | 11011 ----- memcmp (heap.pvvs) |
| 106 | 11100 ----- memsrch (heap.pvvs) |
| 107 | 11101 ----- <empty> |
| 108 | 11110 ----- slurp (heap.pvvs) |
| 109 | 11111 ----- spew (heap.pvvs) |
| 110 | 100xxx - string functions |
| 111 | 100000 ----- strlen (string.pvvs) |
| 112 | 100001 ----- isdigit (string.pvvs) |
| 113 | 100010 ----- get user string (string.pvvs) |
| 114 | 101xxx - logic functions |
| 115 | 101000 ----- not (logic.pvvs) |
| 116 | 101001 ----- and (logic.pvvs) |
| 117 | 101010 ----- or (logic.pvvs) |
| 118 | 101011 ----- xor (logic.pvvs) |
| 119 | 101100 ----- rshift (logic.pvvs) |
| 120 | 101101 ----- lshift (logic.pvvs) |
| 121 | 110xxx - conversion functions |
| 122 | 110000 ----- atoi (convert.pvvs) |
| 123 | 111xxx - debug functions |
| 124 | 111000 ----- dump heap (debug.pvvs) |
| 125 | 111001 ----- dump stack (debug.pvvs) |
| 126 | 111010 ----- print sign (debug.pvvs) |
| 127 | 111011 ----- print magnitude (debug.pvvs) |
| 128 | 111100 ----- print string (debug.pvvs) |
| 129 | 111101 ----- print signed number (debug.pvvs) |
| 130 | 111110 ----- stdlib version (debug.pvvs) |
| 131 | 1xxxxxx - reserved for less common entry points |
| 132 | 1000000 ----- lowbitand (logic.pvvs) |
| 133 | 1000001 ----- <empty> |
| 134 | 1000010 ----- print sign of number (stdio.pvvs) |
| 135 | 1000011 ----- print magnitude of number (stdio.pvvs) |
| 136 | 1000100 ----- print string from stack (stdio.pvvs) |
| 137 | 1000101 ----- print string from heap (stdio.pvvs) |
| 138 | |
| 139 | |
| 140 | ## Labels ## |
| 141 | |
| 142 | 00000000 0xxxxxxx - reserved for stdlib function entry points |
| 143 | 00000000 1xxxxxxx - available for use in user programs |
| 144 | 0xxxxxxx xxxxxxxx - reserved for private use by stdlib |
| 145 | 1xxxxxxx xxxxxxxx - available for use in user programs |
| 146 | |
| 147 | |
| 148 | ## Heap and Pointers ## |
| 149 | |
| 150 | The first 16 heap addresses (`0-15`) are reserved when using the stdlib. |
| 151 | Within that reservation, heap[0] is used by `random` and the block |
| 152 | heap[1]-heap[15] by the stack rotation subroutines which time-share |
| 153 | pseudo-registers between the various stdlib subroutines. |
| 154 | |
| 155 | By convention, chosen since no function other than `random` should use heap[0], |
| 156 | functions which return a pointer will use the address `0` to represent a `NULL` |
| 157 | pointer. |
| 158 | |
| 159 | |
| 160 | # Misc # |
| 161 | |
| 162 | |
| 163 | ## Bitwise Logic Constants ## |
| 164 | |
| 165 | Be cautious when pushing constants in your code for use as bit arrays. Due to |
| 166 | the mismatch between the VVhitespace language's sign-magnitude representation |
| 167 | of integers and the interpreter's internal twos-complement representation, bit |
| 168 | arrays with a leading `1` (i.e. negative numbers) may appear quite different |
| 169 | then expected in your source code. |
| 170 | |
| 171 | For example, to push a 64-bit array of all `1`'s on to the stack we must push |
| 172 | `SSTTN`, or `-1`, not |
| 173 | `SSSTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTN` |
| 174 | (2^65-1). |
| 175 | |
| 176 | |
| 177 | ## Extending Heap Reservation ## |
| 178 | |
| 179 | By default, the stdlib uses the first 16 heap addresses. All heap access (other |
| 180 | than heap[0] as a seed) occurs through `stackrotate` and `stackrotatereverse`. |
| 181 | Edit these functions to increase the stdlib's heap reservation. |
| 182 | |
| 183 | The remainder of the stdlib is written to automatically use the new allocation. |
| 184 | Functions like `printf`, for example, allow more substitutions when the heap |
| 185 | allocation is increased. |
| 186 | |
| 187 | |
| 188 | ## Private Label Space ## |
| 189 | |
| 190 | By convention, each public stdlib label will have 8 bits of private label space |
| 191 | associated with it, formed as follows: |
| 192 | |
| 193 | 00001000 xxxxxxxx - for use by 1000 |
| 194 | 00001001 xxxxxxxx - for use by 1001 |
| 195 | ...etc |
| 196 | |
| 197 | |
| 198 | ## Strings ## |
| 199 | |
| 200 | Strings in VVhitespace are stored as one character per 64-bit word since the |
| 201 | `LOAD` and `STORE` instructions are word length and the heap is word |
| 202 | addressable. |
| 203 | |
| 204 | All strings terminate with an ASCII NUL (`\0`) character. |
| 205 | |
| 206 | |
| 207 | ## Using the C Preprocessor ## |
| 208 | |
| 209 | The standard library uses ordinary include guards of the following form: |
| 210 | |
| 211 | #ifndef FOO |
| 212 | #define FOO |
| 213 | ... |
| 214 | #endif |
| 215 | |
| 216 | This means you can `#include` a file multiple times without problems. To ease |
| 217 | refactoring, I recommend writing the `#include` statements per-function rather |
| 218 | than per-file. See the stdlib for examples. |
| 219 | |
| 220 | Use of the C Preprocessor also means its syntax must be respected as though the |
| 221 | file were C rather than VVhitespace. For example, use of a single apostrophe in |
| 222 | a VVhitespace comment (e.g. don't) throws out a warning: |
| 223 | |
| 224 | warning: missing terminating ' character [-Winvalid-pp-token] |
| 225 | |
| 226 | You won't run into any errors if you copy the stdlib's format but if you |
| 227 | stray I'm sure one could concoct some combination of characters that is both a |
| 228 | comment in VVhitespace and a hard error for `cpp`. |
| 229 | |
| 230 | |
| 231 | ## Whitespace Compatibility ## |
| 232 | |
| 233 | Most of this library will run on most Whitespace interpreters. Some parts, like |
| 234 | the bitwise logic functions, make assumptions about the representation of |
| 235 | integers in the interpreter that may be less portable than the rest of the |
| 236 | library. |
| 237 | |
| 238 | Regardless, tests are included for every stdlib function and can be run though |
| 239 | the Whitespace interpreter of your choice to determine compatibility. |
| 240 | |