| 1 | # Overview # |
| 2 | |
| 3 | This example starts with the `Hello, world!` example from Wikipedia's |
| 4 | Whitespace page, gradually rewriting it to use the ASCII string feature of the |
| 5 | VVhitespace compiler and the `printf` subroutine from the stdlib. |
| 6 | |
| 7 | # Code Commentary # |
| 8 | |
| 9 | Wikipedia's `Hello, World!` example is reproduced below. It follows a simple |
| 10 | form, pushing an integer corresponding to an ASCII character onto the stack and |
| 11 | then printing it with an IO instruction, repeating this two part process for |
| 12 | each character before terminating with the final instruction. |
| 13 | |
| 14 | SSSTSSTSSSN | Push +72 (ASCII H) |
| 15 | TNSS | Output character |
| 16 | SSSTTSSTSTN | Push +101 (ASCII e) |
| 17 | TNSS | Output character |
| 18 | SSSTTSTTSSN | Push +108 (ASCII l) |
| 19 | TNSS | Output character |
| 20 | SSSTTSTTSSN | Push +108 (ASCII l) |
| 21 | TNSS | Output character |
| 22 | SSSTTSTTTTN | Push +111 (ASCII o) |
| 23 | TNSS | Output character |
| 24 | SSSTSTTSSN | Push +44 (ASCII ,) |
| 25 | TNSS | Output character |
| 26 | SSSTSSSSSN | Push +32 (ASCII space) |
| 27 | TNSS | Output character |
| 28 | SSSTTTSTTTN | Push +119 (ASCII w) |
| 29 | TNSS | Output character |
| 30 | SSSTTSTTTTN | Push +111 (ASCII o) |
| 31 | TNSS | Output character |
| 32 | SSSTTTSSTSN | Push +114 (ASCII r) |
| 33 | TNSS | Output character |
| 34 | SSSTTSTTSSN | Push +108 (ASCII l) |
| 35 | TNSS | Output character |
| 36 | SSSTTSSTSSN | Push +100 (ASCII d) |
| 37 | TNSS | Output character |
| 38 | SSSTSSSSTN | Push +33 (ASCII !) |
| 39 | TNSS | Output character |
| 40 | SSSTSTSN | Push +10 (ASCII '\n') |
| 41 | TNSS | Output character |
| 42 | NNN | Terminate program |
| 43 | |
| 44 | If we push the string onto the stack in reverse order we can rearrange the |
| 45 | code as shown below. Now we're first pushing all the ASCII characters onto the |
| 46 | stack, then printing them all at once. |
| 47 | |
| 48 | SSSTSTSN | Push +10 (ASCII '\n') |
| 49 | SSSTSSSSTN | Push +33 (ASCII !) |
| 50 | SSSTTSSTSSN | Push +100 (ASCII d) |
| 51 | SSSTTSTTSSN | Push +108 (ASCII l) |
| 52 | SSSTTTSSTSN | Push +114 (ASCII r) |
| 53 | SSSTTSTTTTN | Push +111 (ASCII o) |
| 54 | SSSTTTSTTTN | Push +119 (ASCII w) |
| 55 | SSSTSSSSSN | Push +32 (ASCII space) |
| 56 | SSSTSTTSSN | Push +44 (ASCII ,) |
| 57 | SSSTTSTTTTN | Push +111 (ASCII o) |
| 58 | SSSTTSTTSSN | Push +108 (ASCII l) |
| 59 | SSSTTSTTSSN | Push +108 (ASCII l) |
| 60 | SSSTTSSTSTN | Push +101 (ASCII e) |
| 61 | SSSTSSTSSSN | Push +72 (ASCII H) |
| 62 | TNSS | Output character |
| 63 | TNSS | Output character |
| 64 | TNSS | Output character |
| 65 | TNSS | Output character |
| 66 | TNSS | Output character |
| 67 | TNSS | Output character |
| 68 | TNSS | Output character |
| 69 | TNSS | Output character |
| 70 | TNSS | Output character |
| 71 | TNSS | Output character |
| 72 | TNSS | Output character |
| 73 | TNSS | Output character |
| 74 | TNSS | Output character |
| 75 | TNSS | Output character |
| 76 | NNN | Terminate program |
| 77 | |
| 78 | As a convenience, the VVhitespace compiler will accept `A""` syntax, generating |
| 79 | a sequence of `PUSH` instructions, just like the prior examples, that places a |
| 80 | null-terminated ASCII string on the stack. This allows us to shorten the |
| 81 | program. Like before, the start of the string is closest to the top of the |
| 82 | stack. Unlike before, there is now a null terminator at the end of the string. |
| 83 | For now, we'll just leave that on the stack when the program terminates. |
| 84 | |
| 85 | A"Hello, world!\n" |
| 86 | TNSS | Output character |
| 87 | TNSS | Output character |
| 88 | TNSS | Output character |
| 89 | TNSS | Output character |
| 90 | TNSS | Output character |
| 91 | TNSS | Output character |
| 92 | TNSS | Output character |
| 93 | TNSS | Output character |
| 94 | TNSS | Output character |
| 95 | TNSS | Output character |
| 96 | TNSS | Output character |
| 97 | TNSS | Output character |
| 98 | TNSS | Output character |
| 99 | TNSS | Output character |
| 100 | NNN | Terminate program |
| 101 | |
| 102 | Finally, we will use `printf` from the stdlib to shorten that mass of IO |
| 103 | instructions. Every stdlib subroutine includes a text description as well as |
| 104 | diagrams of the call and return stack. From `stdio.pvvs` we see the call stack |
| 105 | for `printf` reproduced below. |
| 106 | |
| 107 | Call Stack: |
| 108 | ACSII '\0' |
| 109 | string word n |
| 110 | ... |
| 111 | string word 1 |
| 112 | substitution n |
| 113 | ... |
| 114 | substitution 1 |
| 115 | number of substitutions <-- TOS |
| 116 | |
| 117 | The text description for `printf` also informs us that, if we are printing a |
| 118 | static string (i.e. no substitutions like '%d'), the `number of substitutions` |
| 119 | should be `0` and it should be immediately followed by `string word 1`. Looking |
| 120 | at the call stack, that makes sense since we have no substitutions to place |
| 121 | between those two things. |
| 122 | |
| 123 | Note the ASCII `\0` on the call stack. That corresponds to the null terminator |
| 124 | at the end of our string that was automatically placed by the `A""` syntax. |
| 125 | |
| 126 | Don't forget to `#include` the relevant stdlib files. This is done at the |
| 127 | bottom of the file since VVhitespace files are executed from top to bottom. You |
| 128 | wouldn't want to accidentally start executing random library code! |
| 129 | |
| 130 | Putting all that together, we discover a greatly simplified program. |
| 131 | |
| 132 | A"Hello, world!\n" |
| 133 | SSSSN | PUSH 0 (number of substitutions) |
| 134 | NSTTSSSN | JSR > 1000 (stdlib:printf) |
| 135 | NNN | Terminate program |
| 136 | #include <stdio.pvvs> |
| 137 | |
| 138 | This is already saved in `hello.pvvs` which you can execute with `make run`. |
| 139 | |
| 140 | # Example Output # |
| 141 | |
| 142 | vvhitespace/examples/basic-user-interaction % make run |
| 143 | Hello, world! |
| 144 | |