Added `shoot` function to Hunt the Wumpus (and updated README path).
[vvhitespace] / rationale.md
... / ...
CommitLineData
1While considering methods for further obfuscating Whitespace code, I realized
2that the Whitespace language reference didn't enforce any particular alignment
3or grouping for code execution. In theory this means one could create a
4sequence of Whitespace trits which represents different sequences of commands
5depending on exactly where execution begins.
6
7One implementation of this idea is the creation of a 'hidden' label. For
8example, the command sequence
9
10 PUSH 0; DROP; PUSH 46
11
12assembles as
13
14 SSSSN SNN SSSTSTTTSN
15
16which can be visually regrouped as
17
18 SSSSNSN NSSSTSTTTSN
19
20and contains the `MARK label0` command (i.e. `NSSSTSTTTSN`) used in the next
21set of examples.
22
23Additionally, since `PUSH 0; DROP` is effectively a `NOP`, 'hijacking' the code
24at this location allows one to insert their own integer on the stack in place
25of the `PUSH 46` command, sneakily substituting it as an input to any
26downstream processing.
27
28I decided to investigate the behavior of specific Whitespace interpreters,
29discovering that they broke down into two methods for locating labels.
30
31 * **Method 1** Scan from the start of the file for the first occurence of the
32 mark-label bytestring and jump.
33
34 Examples:
35
36 whitespacers/c: (c) meth0dz
37
38 * **Method 2** Scan from the start of the file, looking for a mark-label
39 bytestring, but 'parsing' one bytestring at a time, and jumping to the
40 first 'standalone' mark-label bytestring. Note that this is different than
41 executing the program, particularly when user-input commands are present.
42
43 Examples:
44
45 whitespacers/haskell: (c) 2003 Edwin Brady
46 whitespacers/ruby: (c) 2003 by Wayne E. Conrad
47 whitespacers/perl: (c) 2003 Micheal Koelbl
48 threeifbywhiskey/satan
49
50Both of these methods can be broken using valid Whitespace code:
51
52 * **Type A**: No 'standalone' label exists. This breaks Method 2.
53
54 By programmer's intent, this should print a `!` before infinite `.` lines.
55
56 * **Type B**: Hidden label before 'standalone' label. This breaks Method 1.
57
58 By programmer's intent, this should print an infinite chain of `.` lines.
59
60This is the Type A program:
61
62 SSSTSSSSTN | Push +33 (ASCII '!')
63 NSNSTSTTTSN | JMP > 0101110 (label0)
64 NSSTTTTN | MARK: 1111 (label2)
65 SSSSN | PUSH 0
66 SNN | DROP
67 SSSTSTTTSN | Push +46 (ASCII '.')
68 TNSS | Output character
69 SSSTSTSN | Push +10 (ASCII '\n')
70 TNSS | Output character
71 NSNTTTTN | JMP > 1111 (label2)
72
73Append this to turn it into the Type B program:
74
75 NSSSTSTTTSN | MARK: 0101110 (label0) (2nd time)
76 NSNTTTTN | JMP > 1111 (label2)
77
78VVhitespace avoids this ambiguity by marking label definitions with a vertical
79tab `[VTab]` immediately before the label.
80
81 Old label: NSS TSTS N
82 New label: NSSV TSTS N
83
84Since Whitespace ignores [VTab] as a comment character, and since the
85Whitespace VM is a superset of the VVhitespace VM, all valid VVhitespace
86programs are also valid Whitespace programs, though the task of locating a
87suitable Whitespace interpreter is left for the reader.
88
89--------------------------------------------------------------------------------
90
91Quoting from the original Whitespace tutorial which I used as language reference:
92
93 The programmer is free to push arbitrary width integers onto the stack.
94
95I have yet to find a Whitespace interpreter which successfully implements that
96statement.
97
98Since I wanted to implement bitwise logic functions, this broad definition
99posed a problem. For example, how many `1`s should be in the output of the
100expression `NOT(0)`? Should the expression `NOT(0) == NOT(0)` always be true?
101
102VVhitespace sidesteps the problem by declaring all integers to be 64-bits wide.
103