git @ Cat's Eye Technologies Matchbox / 6e7382a
Check for errors in interleaved programs before interleaving them. Chris Pressey 7 years ago
2 changed file(s) with 72 addition(s) and 4 deletion(s). Raw diff Collapse all Expand all
136136 and fix?" during phone screens.)
137137
138138 A huge example that is relevant to virtually every programmer is the
139 filesystem. It's a big, shared, mutable store. Some operations, like
140 rename, are often guaranteed to be atomic. But most of them aren't.
139 filesystem. It's a big, shared, mutable store. There are often some
140 operations, like renaming a file, that are guaranteed to be atomic; but
141 most filesystem operations do not have this guarantee.
141142
142143 ### Limitations ###
143144
170171 TODO
171172 ----
172173
173 * strip blank lines and beginning and end of DESC
174 * don't run interleavings if error in either
175174 * better "(can't happen)"
176175 * better output on "Find RCs" -- explain why it failed -- record each
177176 failure in object, iterate over all keys in object
178177
179178 Slightly more advanced TODO items (might not happen before release):
180179
180 * improve error-checking subsystem to report the program and line number
181181 * animation style selector: staggered, black + white, no animation
182182 * when finding a "(can't happen)", strip all further interleavings which
183183 have the same prefix
8989 };
9090
9191 /*
92 * Return an error message string if this Instruction is not well-formed.
93 */
94 this.check = function() {
95 var srcType = this.srcType;
96 var destType = this.destType;
97 if (this.opcode === 'MOV') {
98 if (srcType !== 'I' && srcType !== 'R' && srcType !== 'M') {
99 return "Illegal source reference";
100 }
101 if (destType !== 'R' && destType !== 'M') {
102 return "Illegal destination reference";
103 }
104 return true;
105 } else if (this.opcode === 'INC') {
106 if (srcType !== 'R' && srcType !== 'M') {
107 return "Illegal source reference";
108 }
109 return true;
110 } else if (this.opcode === 'WAIT') {
111 if (srcType !== 'M') {
112 return "Illegal source reference";
113 }
114 if (destType !== 'I') {
115 return "Illegal destination reference";
116 }
117 return true;
118 } else {
119 return "Illegal opcode";
120 }
121 };
122
123 /*
92124 * Given a yoob.Tape that represents shared memory, and an array of
93125 * yoob.Tapes that represent private register contexts, execute this
94126 * Instruction. May return:
157189 };
158190 };
159191
192 /*
193 * Objects of this class can actually represent 2 interleaved programs,
194 * as well as a single program.
195 */
160196 var Program = function() {
161197 this.init = function(cfg) {
162198 cfg = cfg || {};
206242 }
207243
208244 return this;
245 };
246
247 /*
248 * May return:
249 *
250 * true, to indicate that the program checked successfully; or
251 * an error string, to indicate that an instruction was malformed.
252 */
253 this.check = function() {
254 var code = this.code;
255
256 for (var i = 0; i < code.length; i++) {
257 var result = code[i].check();
258 if (typeof result === "string") {
259 return result;
260 }
261 }
262
263 return true;
209264 };
210265
211266 /*
292347 this.code = [];
293348 for (var i = 0; i < lines.length; i++) {
294349 var str = lines[i];
350 if (progNum === 0 && str.trim().length === 0) {
351 continue;
352 }
295353 s.reset(str);
296354 if (s.onType('opcode') && s.token === 'PROG') {
297355 s.scan();
405463 ];
406464 regs[0].style = this.progStyles[0];
407465 var prog1 = this.parse(prog1text).setRegistersIndex(0);
466 var result = prog1.check();
467 if (typeof result === 'string') {
468 this.updateStatus('<span style="color: yellow; background: red;">ERROR</span> ' + result);
469 return;
470 }
408471
409472 regs[1].style = this.progStyles[1];
410473 var prog2 = this.parse(prog2text).setRegistersIndex(1);
474 var result = prog2.check();
475 if (typeof result === 'string') {
476 this.updateStatus('<span style="color: yellow; background: red;">ERROR</span> ' + result);
477 return;
478 }
411479
412480 var $this = this;
413481 this.worker = new Worker(this.workerURL);