Small updates to `rationale.md` for display on Github.
[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. `NSS STSTTTS N`) 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
47 whitespacers/ruby: (c) 2003 by Wayne E. Conrad
48
49 whitespacers/perl: (c) 2003 Micheal Koelbl
50
51 threeifbywhiskey/satan
52
53Both of these methods can be broken using valid Whitespace code:
54
55 * Type A: No 'standalone' label exists. This breaks Method 2.
56
57 By programmer's intent, this should print a '!' before infinite '.' lines.
58
59 * Type B: Hidden label before 'standalone' label. This breaks Method 1.
60
61 By programmer's intent, this should print an infinite chain of '.' lines.
62
63This is the Type A program:
64
65 SSSTSSSSTN | Push +33 (ASCII !)
66 NSNSTSTTTSN | JMP>label0
67 NSSTTTTN | MARK label2
68 SSSSN | PUSH +0
69 SNN | DROP
70 SSSTSTTTSN | Push +46 (ASCII .)
71 TNSS | Output character
72 SSSTSTSN | Push +10 (ASCII newline)
73 TNSS | Output character
74 NSNTTTTN | JMP>label2
75
76Append this to turn it into the Type B program:
77
78 NSSSTSTTTSN | MARK label0 (2nd time)
79 NSNTTTTN | JMP>label2
80
81VVhitespace avoids this ambiguity by marking label definitions with a vertical
82tab `[VTab]` immediately before the label.
83
84 Old label: NSS TSTS N
85 New label: NSSV TSTS N
86
87Since Whitespace ignores [VTab] as a comment character, and since the
88Whitespace VM is a superset of the VVhitespace VM, all valid VVhitespace
89programs are also valid Whitespace programs, though the task of locating a
90suitable Whitespace interpreter is left for the reader.
91
92--------------------------------------------------------------------------------
93
94Quoting from the original Whitespace tutorial which I used as language reference:
95
96 The programmer is free to push arbitrary width integers onto the stack.
97
98I have yet to find a Whitespace interpreter which successfully implements that
99statement.
100
101Since I wanted to implement bitwise logic functions, this broad definition
102posed a problem. For example, how many `1`s should be in the output of the
103expression `NOT(0)`? Should the expression `NOT(0) == NOT(0)` always be true?
104
105VVhitespace sidesteps the problem by declaring all integers to be 64-bits wide.
106