Rename Markdown file extension to '.md'.
Chris Pressey
1 year, 6 days ago
0 | ZOWIE version history | |
1 | ===================== | |
2 | ||
3 | Version 1.0 (Dec 29 2009) | |
4 | ------------------------- | |
5 | ||
6 | * Initial release. | |
7 | ||
8 | Version 1.0 revision 2011.1214 | |
9 | ------------------------------ | |
10 | ||
11 | * Trivial tweaks to the documentation's HTML. | |
12 | ||
13 | Version 1.0 revision 2012.0325 | |
14 | ------------------------------ | |
15 | ||
16 | * Converted documentation to Markdown format. | |
17 | * PEP-8 cleanups to `zowie.py`; no functional changes. | |
18 | ||
19 | Version 1.0 revision 2014.0819 | |
20 | ------------------------------ | |
21 | ||
22 | * Added ability to run `zowie.py` under Skulpt, and demo HTML page of this. | |
23 | * Added some rudimentary Falderal tests. | |
24 | * Added UNLICENSE to emphasize the public domain status of these materials. | |
25 | * Made `zowie.py` file executable, using `/usr/bin/env` to find `python`. | |
26 | * More Markdown, whitespace, and PEP-8 cleanups. | |
27 | ||
28 | Version 1.1 | |
29 | ----------- | |
30 | ||
31 | * Made syntax more strict: | |
32 | * Names of commands and registers must be in uppercase. | |
33 | * Previous lax parsing of indirect register references was dropped. | |
34 | * Because this above changed the definition of the language, but not in any | |
35 | jaw-dropping way, the minor version number was bumped. | |
36 | * Uses of regular expressions and old-style classes `zowie.py` were dropped. | |
37 | * Added ability to compile `zowie.py` with RPython from PyPy version 2.3.1. | |
38 | ||
39 | Version 1.1 revision 2019.0122 | |
40 | ------------------------------ | |
41 | ||
42 | * Added example Javascript files demonstrating how zowie.py can be run | |
43 | under Skulpt in a web browser. |
0 | ZOWIE version history | |
1 | ===================== | |
2 | ||
3 | Version 1.0 (Dec 29 2009) | |
4 | ------------------------- | |
5 | ||
6 | * Initial release. | |
7 | ||
8 | Version 1.0 revision 2011.1214 | |
9 | ------------------------------ | |
10 | ||
11 | * Trivial tweaks to the documentation's HTML. | |
12 | ||
13 | Version 1.0 revision 2012.0325 | |
14 | ------------------------------ | |
15 | ||
16 | * Converted documentation to Markdown format. | |
17 | * PEP-8 cleanups to `zowie.py`; no functional changes. | |
18 | ||
19 | Version 1.0 revision 2014.0819 | |
20 | ------------------------------ | |
21 | ||
22 | * Added ability to run `zowie.py` under Skulpt, and demo HTML page of this. | |
23 | * Added some rudimentary Falderal tests. | |
24 | * Added UNLICENSE to emphasize the public domain status of these materials. | |
25 | * Made `zowie.py` file executable, using `/usr/bin/env` to find `python`. | |
26 | * More Markdown, whitespace, and PEP-8 cleanups. | |
27 | ||
28 | Version 1.1 | |
29 | ----------- | |
30 | ||
31 | * Made syntax more strict: | |
32 | * Names of commands and registers must be in uppercase. | |
33 | * Previous lax parsing of indirect register references was dropped. | |
34 | * Because this above changed the definition of the language, but not in any | |
35 | jaw-dropping way, the minor version number was bumped. | |
36 | * Uses of regular expressions and old-style classes `zowie.py` were dropped. | |
37 | * Added ability to compile `zowie.py` with RPython from PyPy version 2.3.1. | |
38 | ||
39 | Version 1.1 revision 2019.0122 | |
40 | ------------------------------ | |
41 | ||
42 | * Added example Javascript files demonstrating how zowie.py can be run | |
43 | under Skulpt in a web browser. |
0 | ZOWIE | |
1 | ===== | |
2 | ||
3 | Introduction | |
4 | ------------ | |
5 | ||
6 | ZOWIE is a programming language where all control flow is both | |
7 | *memory-mapped* and *structured*. It is memory-mapped in the sense that | |
8 | changes in flow are triggered by changes made to memory locations, and | |
9 | it is structured in the sense of structured programming – the programmer | |
10 | never deals with `goto`s, offsets, or labels of any kind. | |
11 | ||
12 | History | |
13 | ------- | |
14 | ||
15 | The primary design goal of ZOWIE was to have memory-mapped structured | |
16 | control flow. This goal was inspired by Jeffry Johnston's unsuccessful | |
17 | attempt to reduce the number of instructions in | |
18 | [BitChanger](http://esolangs.org/wiki/BitChanger) (while retaining | |
19 | Turing-completeness) by memory-mapping the loop operation. | |
20 | ||
21 | I initially thought that the difficulty lay in BitChanger's minimalism. | |
22 | To do memory-mapped flow control in general sounded easy – just start a | |
23 | loop when one memory location is written, and end it when some other | |
24 | location is written, right? But no. It's not that simple, as I attempt | |
25 | to explain below. ZOWIE is the last of several, sometimes painful, | |
26 | attempts over the summer of 2009 to realize this design goal (and it is | |
27 | not clear that the techniques used in ZOWIE could be usefully imported | |
28 | back into BitChanger.) The final, workable idea crystallized at about | |
29 | the time September turned into October. | |
30 | ||
31 | The thing with loop structures is that there is usually some way to jump | |
32 | to a known point in the loop (say, the start, or the end) – really, | |
33 | that's what makes them structured. And to jump to a point in a loop, you | |
34 | have to know where that point is. And if you can analyze the loop | |
35 | structure statically, for example if your semantics are directed by | |
36 | syntax as in almost all high-level languages, then it's not difficult to | |
37 | know where that point is. | |
38 | ||
39 | But if that point is defined by when some *memory* location is changed, | |
40 | it is not in general possible to detect it statically (by Rice's | |
41 | Theorem, which is just a generalization of the Halting Problem.) So it | |
42 | is not, in general, possible to know ahead of time where the loop begins | |
43 | or ends. | |
44 | ||
45 | There are a few things to note about this. | |
46 | ||
47 | One is that by "statically" I do not necessarily mean "at compile-time". | |
48 | Many Brainfuck and Mouse interpreters seek out the end of the loop only | |
49 | when they know they must exit it. However, because they are looking | |
50 | through the program text, it is still a kind of static analysis. | |
51 | ||
52 | Another thing is that it would of course be possible to detect some kind | |
53 | of (fixed) command to change the memory location associated with ending | |
54 | a loop – but that would be cheating! (Also, if memory locations can be | |
55 | computed, it is still not fully general, because we cannot look for all | |
56 | possible computations that would result in that memory location.) | |
57 | ||
58 | Lastly, note that we really don't have a problem detecting the start of | |
59 | a loop. As soon as we execute the start of a loop, we know it's a loop, | |
60 | and we know where it is, so we can record that location. The problem is | |
61 | any other point in the loop, like the end. A little reflection will | |
62 | reveal that this means it will be more difficult to do a "WHILE" loop or | |
63 | a structured conditional ("IF-THEN-ENDIF") than a "REPEAT" loop (where | |
64 | the condition is at the end of the loop.) However, it is widely known | |
65 | that "REPEAT" loops alone are not sufficient for a Turing-complete | |
66 | language. We'll see below that ZOWIE manages to create generalized loops | |
67 | through the use of transactions. | |
68 | ||
69 | The secondary design goal of ZOWIE was to strike the perfect balance | |
70 | between _It's a Mad Mad Mad Mad World_ and _The Party_. It is generally | |
71 | considered a morbid failure in that regard, what with not being a madcap | |
72 | 60's movie and all. | |
73 | ||
74 | Syntax and Semantics | |
75 | -------------------- | |
76 | ||
77 | To mitigate retooling costs, ZOWIE borrows much of its archiecture and | |
78 | instruction repertoire from [SMITH](http://catseye.tc/projects/smith/). | |
79 | There are an unlimited number of registers, numbered from 0 upward; each | |
80 | register contains a non-negative integer value of unbounded extent. The | |
81 | contents of a register before it has ever been written is guaranteed to | |
82 | be 0. | |
83 | ||
84 | There are five instruction forms. The first register is the destination | |
85 | register, and is written to; the second register (or immediate value) is | |
86 | read from. As in SMITH, square brackets indicate indirect register | |
87 | access. All instruction forms are case-sensitive; they must be given | |
88 | using capital letters. | |
89 | ||
90 | MOV register, immediate e.g. MOV R8, 141 | |
91 | MOV register, register MOV R8, R9 | |
92 | MOV [register], register MOV R[R8], R9 | |
93 | MOV register, [register] MOV R8, R[R9] | |
94 | MOV [register], [register] MOV R[R8], R[R9] | |
95 | ||
96 | Not only flow control, but in fact all operations in ZOWIE are | |
97 | memory-mapped. The lowest-numbered nine registers have special behaviour | |
98 | when written to or read from: | |
99 | ||
100 | `R0` | |
101 | ||
102 | When a value is written into R0, the Unicode symbol represented by the | |
103 | value is sent to the standard output channel. | |
104 | ||
105 | Reading from R0 waits until a Unicode symbol is available on the | |
106 | standard input, then offers its value as the value of this register. | |
107 | ||
108 | This is similar to the `TTY` pseudo-register of SMITH. | |
109 | ||
110 | *Note: although implementations should make a best effort, the external | |
111 | encoding and representation of Unicode characters is ultimately | |
112 | implementation-defined, especially on systems which are only capable of | |
113 | accurately displaying a subset of the Unicode character set. For | |
114 | example, on a strict ASCII teletype or other device incapable of | |
115 | displaying the DOWNWARDS ARROW (↓) symbol, it would be reasonable to | |
116 | output `↓` or some similar "escape sequence" when executing | |
117 | `MOV R0, 8595`.* | |
118 | ||
119 | `R1` | |
120 | ||
121 | When a value is written into R1, a **BEGIN TRANSACTION** occurs; | |
122 | conceptually, a copy of the program state, including all registers and | |
123 | the location of the currently executing instruction, is made, and pushed | |
124 | onto a stack. | |
125 | ||
126 | Reading from R1 always offers the value 1. | |
127 | ||
128 | `R2` | |
129 | ||
130 | When a value is written into R2, what happens depends on the value. | |
131 | ||
132 | If the value is greater than zero, the current transaction is | |
133 | **COMMIT**ted; conceptually, the topmost program state is popped from | |
134 | the stack and discarded. | |
135 | ||
136 | If the value is equal to zero, the current transaction is | |
137 | **ROLLBACK**ed. Conceptually, the topmost program state is popped; the | |
138 | contents of all registers are reset to what they were in the popped | |
139 | program state; but the location of the currently executing instruction | |
140 | is unchanged. | |
141 | ||
142 | Reading from R2 always offers the value 2. | |
143 | ||
144 | `R3` | |
145 | ||
146 | When a value is written into R3, what happens depends on the value. | |
147 | ||
148 | If the value is greater than zero, the current transaction is **COMMIT | |
149 | AND REPEAT**ed; conceptually, the topmost program state is popped from | |
150 | the stack; the location of the currently executing instruction is reset | |
151 | to what it was in the program state; and a copy of this new program | |
152 | state is pushed once more onto the stack. | |
153 | ||
154 | If the value is equal to zero, the current transaction is **COMMIT**ed | |
155 | (described previously in R2). | |
156 | ||
157 | Reading from R3 always offers the value 3. | |
158 | ||
159 | `R4` | |
160 | ||
161 | When a value is written into R4, that value is added to the value in R8, | |
162 | and the result is written into R8. Reading from R4 always offers the | |
163 | value 4. | |
164 | ||
165 | `R5` | |
166 | ||
167 | When a value is written into R5, that value is subtracted from the value | |
168 | in R8, and the result is written into R8. If the result would be | |
169 | negative, the result will be zero. Reading from R5 always offers the | |
170 | value 5. | |
171 | ||
172 | `R6` | |
173 | ||
174 | When a value is written into R6, the product of that value and the value | |
175 | in R8 is written into R8. Reading from R6 always offers the value 6. | |
176 | ||
177 | `R7` | |
178 | ||
179 | When a value is written into R7, the boolean negation of that value is | |
180 | written into R7: 1 if the value was 0, and 0 otherwise. Reading from R7 | |
181 | always offers the value 7. | |
182 | ||
183 | `R8` | |
184 | ||
185 | Not really memory-mapped, but used as an "accumulator" by the registers | |
186 | R4 through R7. | |
187 | ||
188 | Because the reading and writing of registers can have side-effects, the | |
189 | order of reads and writes during the execution of a single instruction | |
190 | is strictly defined as follows: | |
191 | ||
192 | - The indirect source register, if any, is read (to discover the | |
193 | direct source register.) | |
194 | - The direct source register is read. | |
195 | - The indirect destination register, if any, is read (to discover the | |
196 | direct destination register.) | |
197 | - The direct destination register is written. | |
198 | ||
199 | Computational Class | |
200 | ------------------- | |
201 | ||
202 | I believe ZOWIE is Turing-complete because the transactions can simulate | |
203 | both "IF" and "REPEAT" control structures, which, taken together, can | |
204 | simulate a "WHILE", which is widely known to be sufficient, along with | |
205 | the usual arithmetical operations on an unbounded number of unbounded | |
206 | integer registers, to have a system that is Turing-complete. | |
207 | ||
208 | For example, a crude translation of Brainfuck into ZOWIE might go like: | |
209 | ||
210 | preamble MOV R10, 100 ; the Brainfuck tape index | |
211 | MOV R11, 101 ; the saved-test-value stack pointer | |
212 | ||
213 | > MOV R8, R10 ; inc tape index by two | |
214 | MOV R4, R2 | |
215 | MOV R10, R8 | |
216 | ||
217 | < MOV R8, R10 ; dec tape index by two | |
218 | MOV R5, R2 | |
219 | MOV R10, R8 | |
220 | ||
221 | + MOV R8, R[R10] ; inc value on tape | |
222 | MOV R4, R1 | |
223 | MOV R[R10], R8 | |
224 | ||
225 | - MOV R8, R[R10] ; dec value on tape | |
226 | MOV R5, R1 | |
227 | MOV R[R10], R8 | |
228 | ||
229 | . MOV R0, R[R10] ; output | |
230 | ||
231 | , MOV R[R10], R0 ; input | |
232 | ||
233 | [ MOV R1, R1 ; BEGIN TRANSACTION for "REPEAT" | |
234 | MOV R8, R11 ; bump up the saved-value stack pointer | |
235 | MOV R4, R2 | |
236 | MOV R11, R8 | |
237 | MOV R[R11], R[R10] ; save the value we are testing | |
238 | MOV R1, R1 ; BEGIN TRANSACTION for "IF" | |
239 | ||
240 | ] MOV R2, R[R11] ; COMMIT if non-zero or ROLLBACK otherwise | |
241 | MOV R12, R11 ; retain a copy of the saved-stack pointer | |
242 | MOV R8, R11 ; bump down the saved-stack pointer | |
243 | MOV R5, R2 | |
244 | MOV R11, R8 | |
245 | MOV R3, R[R12] ; COMMIT AND REPEAT if non-zero | |
246 | ||
247 | Three things to note: | |
248 | ||
249 | - In this translation, the simulated Brainfuck tape and the | |
250 | saved-value stack are interleaved. | |
251 | - It is important to save the value being tested *before* the "IF" | |
252 | transaction is begun – otherwise, the value will be rolled back | |
253 | before it can be tested for the **COMMIT AND REPEAT**. | |
254 | - The input-output behaviour of ZOWIE programs produced by this | |
255 | translation does differ from Brainfuck. If the value on the tape is | |
256 | initially zero, a Brainfuck "while" loop will never be executed at | |
257 | all, whereas a ZOWIE transaction *will* be executed, but afterwards | |
258 | undone – everything, that is, except input and output, because being | |
259 | interactions with the outside world, those can't be undone. This | |
260 | limitation does not affect whether ZOWIE is Turing-complete or not | |
261 | (you could just refrain from outputting anything until the very end | |
262 | of the computation), but it does imply that ZOWIE has limitations on | |
263 | how it can communicate. | |
264 | ||
265 | That's all. | |
266 | ||
267 | Happy *«deleted by black helicopters»*! | |
268 | Chris Pressey | |
269 | December 29th, 2009 CE | |
270 | Evanston, IL |
0 | ZOWIE | |
1 | ===== | |
2 | ||
3 | Introduction | |
4 | ------------ | |
5 | ||
6 | ZOWIE is a programming language where all control flow is both | |
7 | *memory-mapped* and *structured*. It is memory-mapped in the sense that | |
8 | changes in flow are triggered by changes made to memory locations, and | |
9 | it is structured in the sense of structured programming – the programmer | |
10 | never deals with `goto`s, offsets, or labels of any kind. | |
11 | ||
12 | History | |
13 | ------- | |
14 | ||
15 | The primary design goal of ZOWIE was to have memory-mapped structured | |
16 | control flow. This goal was inspired by Jeffry Johnston's unsuccessful | |
17 | attempt to reduce the number of instructions in | |
18 | [BitChanger](http://esolangs.org/wiki/BitChanger) (while retaining | |
19 | Turing-completeness) by memory-mapping the loop operation. | |
20 | ||
21 | I initially thought that the difficulty lay in BitChanger's minimalism. | |
22 | To do memory-mapped flow control in general sounded easy – just start a | |
23 | loop when one memory location is written, and end it when some other | |
24 | location is written, right? But no. It's not that simple, as I attempt | |
25 | to explain below. ZOWIE is the last of several, sometimes painful, | |
26 | attempts over the summer of 2009 to realize this design goal (and it is | |
27 | not clear that the techniques used in ZOWIE could be usefully imported | |
28 | back into BitChanger.) The final, workable idea crystallized at about | |
29 | the time September turned into October. | |
30 | ||
31 | The thing with loop structures is that there is usually some way to jump | |
32 | to a known point in the loop (say, the start, or the end) – really, | |
33 | that's what makes them structured. And to jump to a point in a loop, you | |
34 | have to know where that point is. And if you can analyze the loop | |
35 | structure statically, for example if your semantics are directed by | |
36 | syntax as in almost all high-level languages, then it's not difficult to | |
37 | know where that point is. | |
38 | ||
39 | But if that point is defined by when some *memory* location is changed, | |
40 | it is not in general possible to detect it statically (by Rice's | |
41 | Theorem, which is just a generalization of the Halting Problem.) So it | |
42 | is not, in general, possible to know ahead of time where the loop begins | |
43 | or ends. | |
44 | ||
45 | There are a few things to note about this. | |
46 | ||
47 | One is that by "statically" I do not necessarily mean "at compile-time". | |
48 | Many Brainfuck and Mouse interpreters seek out the end of the loop only | |
49 | when they know they must exit it. However, because they are looking | |
50 | through the program text, it is still a kind of static analysis. | |
51 | ||
52 | Another thing is that it would of course be possible to detect some kind | |
53 | of (fixed) command to change the memory location associated with ending | |
54 | a loop – but that would be cheating! (Also, if memory locations can be | |
55 | computed, it is still not fully general, because we cannot look for all | |
56 | possible computations that would result in that memory location.) | |
57 | ||
58 | Lastly, note that we really don't have a problem detecting the start of | |
59 | a loop. As soon as we execute the start of a loop, we know it's a loop, | |
60 | and we know where it is, so we can record that location. The problem is | |
61 | any other point in the loop, like the end. A little reflection will | |
62 | reveal that this means it will be more difficult to do a "WHILE" loop or | |
63 | a structured conditional ("IF-THEN-ENDIF") than a "REPEAT" loop (where | |
64 | the condition is at the end of the loop.) However, it is widely known | |
65 | that "REPEAT" loops alone are not sufficient for a Turing-complete | |
66 | language. We'll see below that ZOWIE manages to create generalized loops | |
67 | through the use of transactions. | |
68 | ||
69 | The secondary design goal of ZOWIE was to strike the perfect balance | |
70 | between _It's a Mad Mad Mad Mad World_ and _The Party_. It is generally | |
71 | considered a morbid failure in that regard, what with not being a madcap | |
72 | 60's movie and all. | |
73 | ||
74 | Syntax and Semantics | |
75 | -------------------- | |
76 | ||
77 | To mitigate retooling costs, ZOWIE borrows much of its archiecture and | |
78 | instruction repertoire from [SMITH](http://catseye.tc/projects/smith/). | |
79 | There are an unlimited number of registers, numbered from 0 upward; each | |
80 | register contains a non-negative integer value of unbounded extent. The | |
81 | contents of a register before it has ever been written is guaranteed to | |
82 | be 0. | |
83 | ||
84 | There are five instruction forms. The first register is the destination | |
85 | register, and is written to; the second register (or immediate value) is | |
86 | read from. As in SMITH, square brackets indicate indirect register | |
87 | access. All instruction forms are case-sensitive; they must be given | |
88 | using capital letters. | |
89 | ||
90 | MOV register, immediate e.g. MOV R8, 141 | |
91 | MOV register, register MOV R8, R9 | |
92 | MOV [register], register MOV R[R8], R9 | |
93 | MOV register, [register] MOV R8, R[R9] | |
94 | MOV [register], [register] MOV R[R8], R[R9] | |
95 | ||
96 | Not only flow control, but in fact all operations in ZOWIE are | |
97 | memory-mapped. The lowest-numbered nine registers have special behaviour | |
98 | when written to or read from: | |
99 | ||
100 | `R0` | |
101 | ||
102 | When a value is written into R0, the Unicode symbol represented by the | |
103 | value is sent to the standard output channel. | |
104 | ||
105 | Reading from R0 waits until a Unicode symbol is available on the | |
106 | standard input, then offers its value as the value of this register. | |
107 | ||
108 | This is similar to the `TTY` pseudo-register of SMITH. | |
109 | ||
110 | *Note: although implementations should make a best effort, the external | |
111 | encoding and representation of Unicode characters is ultimately | |
112 | implementation-defined, especially on systems which are only capable of | |
113 | accurately displaying a subset of the Unicode character set. For | |
114 | example, on a strict ASCII teletype or other device incapable of | |
115 | displaying the DOWNWARDS ARROW (↓) symbol, it would be reasonable to | |
116 | output `↓` or some similar "escape sequence" when executing | |
117 | `MOV R0, 8595`.* | |
118 | ||
119 | `R1` | |
120 | ||
121 | When a value is written into R1, a **BEGIN TRANSACTION** occurs; | |
122 | conceptually, a copy of the program state, including all registers and | |
123 | the location of the currently executing instruction, is made, and pushed | |
124 | onto a stack. | |
125 | ||
126 | Reading from R1 always offers the value 1. | |
127 | ||
128 | `R2` | |
129 | ||
130 | When a value is written into R2, what happens depends on the value. | |
131 | ||
132 | If the value is greater than zero, the current transaction is | |
133 | **COMMIT**ted; conceptually, the topmost program state is popped from | |
134 | the stack and discarded. | |
135 | ||
136 | If the value is equal to zero, the current transaction is | |
137 | **ROLLBACK**ed. Conceptually, the topmost program state is popped; the | |
138 | contents of all registers are reset to what they were in the popped | |
139 | program state; but the location of the currently executing instruction | |
140 | is unchanged. | |
141 | ||
142 | Reading from R2 always offers the value 2. | |
143 | ||
144 | `R3` | |
145 | ||
146 | When a value is written into R3, what happens depends on the value. | |
147 | ||
148 | If the value is greater than zero, the current transaction is **COMMIT | |
149 | AND REPEAT**ed; conceptually, the topmost program state is popped from | |
150 | the stack; the location of the currently executing instruction is reset | |
151 | to what it was in the program state; and a copy of this new program | |
152 | state is pushed once more onto the stack. | |
153 | ||
154 | If the value is equal to zero, the current transaction is **COMMIT**ed | |
155 | (described previously in R2). | |
156 | ||
157 | Reading from R3 always offers the value 3. | |
158 | ||
159 | `R4` | |
160 | ||
161 | When a value is written into R4, that value is added to the value in R8, | |
162 | and the result is written into R8. Reading from R4 always offers the | |
163 | value 4. | |
164 | ||
165 | `R5` | |
166 | ||
167 | When a value is written into R5, that value is subtracted from the value | |
168 | in R8, and the result is written into R8. If the result would be | |
169 | negative, the result will be zero. Reading from R5 always offers the | |
170 | value 5. | |
171 | ||
172 | `R6` | |
173 | ||
174 | When a value is written into R6, the product of that value and the value | |
175 | in R8 is written into R8. Reading from R6 always offers the value 6. | |
176 | ||
177 | `R7` | |
178 | ||
179 | When a value is written into R7, the boolean negation of that value is | |
180 | written into R7: 1 if the value was 0, and 0 otherwise. Reading from R7 | |
181 | always offers the value 7. | |
182 | ||
183 | `R8` | |
184 | ||
185 | Not really memory-mapped, but used as an "accumulator" by the registers | |
186 | R4 through R7. | |
187 | ||
188 | Because the reading and writing of registers can have side-effects, the | |
189 | order of reads and writes during the execution of a single instruction | |
190 | is strictly defined as follows: | |
191 | ||
192 | - The indirect source register, if any, is read (to discover the | |
193 | direct source register.) | |
194 | - The direct source register is read. | |
195 | - The indirect destination register, if any, is read (to discover the | |
196 | direct destination register.) | |
197 | - The direct destination register is written. | |
198 | ||
199 | Computational Class | |
200 | ------------------- | |
201 | ||
202 | I believe ZOWIE is Turing-complete because the transactions can simulate | |
203 | both "IF" and "REPEAT" control structures, which, taken together, can | |
204 | simulate a "WHILE", which is widely known to be sufficient, along with | |
205 | the usual arithmetical operations on an unbounded number of unbounded | |
206 | integer registers, to have a system that is Turing-complete. | |
207 | ||
208 | For example, a crude translation of Brainfuck into ZOWIE might go like: | |
209 | ||
210 | preamble MOV R10, 100 ; the Brainfuck tape index | |
211 | MOV R11, 101 ; the saved-test-value stack pointer | |
212 | ||
213 | > MOV R8, R10 ; inc tape index by two | |
214 | MOV R4, R2 | |
215 | MOV R10, R8 | |
216 | ||
217 | < MOV R8, R10 ; dec tape index by two | |
218 | MOV R5, R2 | |
219 | MOV R10, R8 | |
220 | ||
221 | + MOV R8, R[R10] ; inc value on tape | |
222 | MOV R4, R1 | |
223 | MOV R[R10], R8 | |
224 | ||
225 | - MOV R8, R[R10] ; dec value on tape | |
226 | MOV R5, R1 | |
227 | MOV R[R10], R8 | |
228 | ||
229 | . MOV R0, R[R10] ; output | |
230 | ||
231 | , MOV R[R10], R0 ; input | |
232 | ||
233 | [ MOV R1, R1 ; BEGIN TRANSACTION for "REPEAT" | |
234 | MOV R8, R11 ; bump up the saved-value stack pointer | |
235 | MOV R4, R2 | |
236 | MOV R11, R8 | |
237 | MOV R[R11], R[R10] ; save the value we are testing | |
238 | MOV R1, R1 ; BEGIN TRANSACTION for "IF" | |
239 | ||
240 | ] MOV R2, R[R11] ; COMMIT if non-zero or ROLLBACK otherwise | |
241 | MOV R12, R11 ; retain a copy of the saved-stack pointer | |
242 | MOV R8, R11 ; bump down the saved-stack pointer | |
243 | MOV R5, R2 | |
244 | MOV R11, R8 | |
245 | MOV R3, R[R12] ; COMMIT AND REPEAT if non-zero | |
246 | ||
247 | Three things to note: | |
248 | ||
249 | - In this translation, the simulated Brainfuck tape and the | |
250 | saved-value stack are interleaved. | |
251 | - It is important to save the value being tested *before* the "IF" | |
252 | transaction is begun – otherwise, the value will be rolled back | |
253 | before it can be tested for the **COMMIT AND REPEAT**. | |
254 | - The input-output behaviour of ZOWIE programs produced by this | |
255 | translation does differ from Brainfuck. If the value on the tape is | |
256 | initially zero, a Brainfuck "while" loop will never be executed at | |
257 | all, whereas a ZOWIE transaction *will* be executed, but afterwards | |
258 | undone – everything, that is, except input and output, because being | |
259 | interactions with the outside world, those can't be undone. This | |
260 | limitation does not affect whether ZOWIE is Turing-complete or not | |
261 | (you could just refrain from outputting anything until the very end | |
262 | of the computation), but it does imply that ZOWIE has limitations on | |
263 | how it can communicate. | |
264 | ||
265 | That's all. | |
266 | ||
267 | Happy *«deleted by black helicopters»*! | |
268 | Chris Pressey | |
269 | December 29th, 2009 CE | |
270 | Evanston, IL |