Updated `rationale.md`, expanding previous notes.
[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 used in the next set of examples.
21
22Additionally, since `PUSH 0; DROP` is effectively a `NOP`, 'hijacking' the code
23at this location allows one to insert their own integer on the stack in place
24of the `PUSH 46` command, sneakily substituting it as an input to any
25downstream processing.
26
27I decided to investigate the behavior of specific Whitespace interpreters,
28discovering that they broke down into two methods for locating labels.
29
30 * **Method 1** Scan from the start of the file for the first occurence of the
31 mark-label bytestring and jump.
32
33 Example: whitespacers/c: (c) meth0dz
34
35 * **Method 2** Scan from the start of the file, looking for a mark-label
36 bytestring, but 'parsing' one bytestring at a time, and jumping to the
37 first 'standalone' mark-label bytestring. Note that this is different than
38 executing the program, particularly when user-input commands are present.
39
40 Example: whitespacers/haskell: (c) 2003 Edwin Brady
41 whitespacers/ruby: (c) 2003 by Wayne E. Conrad
42 whitespacers/perl: (c) 2003 Micheal Koelbl
43 threeifbywhiskey/satan
44
45Both of these methods can be broken using valid Whitespace code:
46
47 * Type A: No 'standalone' label exists. This breaks Method 2.
48
49 By programmer's intent, this should print a '!' before infinite '.' lines.
50
51 * Type B: Hidden label before 'standalone' label. This breaks Method 1.
52
53 By programmer's intent, this should print an infinite chain of '.' lines.
54
55This is the Type A program:
56
57 SSSTSSSSTN | Push +33 (ASCII !)
58 NSNSTSTTTSN | JMP>label0
59 NSSTTTTN | MARK label2
60 SSSSN | PUSH +0
61 SNN | DROP
62 SSSTSTTTSN | Push +46 (ASCII .)
63 TNSS | Output character
64 SSSTSTSN | Push +10 (ASCII newline)
65 TNSS | Output character
66 NSNTTTTN | JMP>label2
67
68Append this to turn it into the Type B program:
69
70 NSSSTSTTTSN | MARK label0 (2nd time)
71 NSNTTTTN | JMP>label2
72
73VVhitespace avoids this ambiguity by marking label definitions with a vertical
74tab `[VTab]` immediately before the label.
75
76 Old label: NSS TSTS N
77 New label: NSSV TSTS N
78
79Since Whitespace ignores [VTab] as a comment character, and since the
80Whitespace VM is a superset of the VVhitespace VM, all valid VVhitespace
81programs are also valid Whitespace programs, though the task of locating a
82suitable Whitespace interpreter is left for the reader.
83
84--------------------------------------------------------------------------------
85
86Quoting from the original Whitespace tutorial which I used as language reference:
87
88 The programmer is free to push arbitrary width integers onto the stack.
89
90I have yet to find a Whitespace interpreter which successfully implements that
91statement.
92
93Since I wanted to implement bitwise logic functions, this broad definition
94posed a problem. For example, how many `1`s should be in the output of the
95expression `NOT(0)`? Should the expression `NOT(0) == NOT(0)` always be true?
96
97VVhitespace sidesteps the problem by declaring all integers to be 64-bits wide.
98