Added old `random` function back as `fastrand`.
[vvhitespace] / stdlib / README.md
index 099a70e..6c26770 100644 (file)
@@ -1,32 +1,85 @@
 # Overview #
 
 This folder contains a library of useful functions written in VVhitespace.
 # 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`.
+They are intended to remove the tedium of frequently repeated patterns while
+remaining short enough to easily comprehend and modify.
 
 
-# Reservations #
+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.
 
 
-Since all labels share a global namespace, the standard library makes the
-following reservations:
+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.
 
 
-## Label ##
+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.
 
 
-    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
+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.
 
 
-## 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 heap[15] is used
-by `spewreg`. The remaining 14 locations, heap[1]-heap[14] are used as
-general-purpose registers.
+# 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 <stack.pvvs>` 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 <stack.pvvs>
+
+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.
+
 
 
-By convention, functions which return a pointer will use the address `0` to
-represent a `NULL` pointer.
+# Resource Reservations #
 
 
-# Entry Points #
+
+## 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.
 
 The following labels are entry points to stdlib functions. Read the
 header comment for each function to learn the call and return stack.
@@ -41,6 +94,8 @@ header comment for each function to learn the call and return stack.
          010xxx - math functions
           10000 ----- random                        (math.pvvs)
           10001 ----- absolute value                (math.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)
          011xxx - heap functions
           11000 ----- memset                        (heap.pvvs)
           11001 ----- memcpy                        (heap.pvvs)
@@ -52,6 +107,8 @@ header comment for each function to learn the call and return stack.
           11111 ----- spew                          (heap.pvvs)
          100xxx - string functions
          100000 ----- strlen                        (string.pvvs)
           11111 ----- spew                          (heap.pvvs)
          100xxx - string functions
          100000 ----- strlen                        (string.pvvs)
+         100001 ----- isdigit                       (string.pvvs)
+         100010 ----- get user string               (string.pvvs)
          101xxx - logic functions
          101000 ----- not                           (logic.pvvs)
          101001 ----- and                           (logic.pvvs)
          101xxx - logic functions
          101000 ----- not                           (logic.pvvs)
          101001 ----- and                           (logic.pvvs)
@@ -60,22 +117,123 @@ header comment for each function to learn the call and return stack.
          101100 ----- rshift                        (logic.pvvs)
          101101 ----- lshift                        (logic.pvvs)
          110xxx - conversion functions
          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)
          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
         1xxxxxx - reserved for less common entry points
-        1000000 ----- <empty>
+        1000000 ----- lowbitand                     (logic.pvvs)
         1000001 ----- <empty>
         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)
 
         1000001 ----- <empty>
         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 #
 
 # 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
 
     00001000 xxxxxxxx - for use by 1000
     00001001 xxxxxxxx - for use by 1001
     ...etc
+
+
+## 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.
+
+Regardless, tests are included for every stdlib function and can be run though
+the Whitespace interpreter of your choice to determine compatibility.
+