OLD | NEW |
| (Empty) |
1 | |
2 /* | |
3 * Copyright 2011 Google Inc. | |
4 * | |
5 * Use of this source code is governed by a BSD-style license that can be | |
6 * found in the LICENSE file. | |
7 */ | |
8 #include "Forth.h" | |
9 #include "SkString.h" | |
10 | |
11 class Reporter { | |
12 public: | |
13 int fFailureCount; | |
14 | |
15 Reporter() : fFailureCount(0) {} | |
16 void reportFailure(const char expression[], const char file[], int line); | |
17 void reportFailure(const char msg[]); | |
18 }; | |
19 | |
20 typedef void (*ForthWordTestProc)(ForthWord*, ForthEngine*, Reporter*); | |
21 | |
22 #define FORTH_ASSERT(reporter, expression) \ | |
23 do { \ | |
24 if (!(expression)) { \ | |
25 reporter->reportFailure(#expression, __FILE__, __LINE__); \ | |
26 } \ | |
27 } while (0) | |
28 | |
29 static void drop_test0(ForthWord* word, ForthEngine* fe, Reporter* reporter) { | |
30 fe->push(-17); | |
31 word->exec(fe); | |
32 FORTH_ASSERT(reporter, 0 == fe->depth()); | |
33 } | |
34 | |
35 static void drop_test1(ForthWord* word, ForthEngine* fe, Reporter* reporter) { | |
36 fe->push(-17); | |
37 fe->push(93); | |
38 word->exec(fe); | |
39 FORTH_ASSERT(reporter, 1 == fe->depth()); | |
40 FORTH_ASSERT(reporter, -17 == fe->peek(0)); | |
41 } | |
42 | |
43 static void dup_test(ForthWord* word, ForthEngine* fe, Reporter* reporter) { | |
44 fe->push(-17); | |
45 word->exec(fe); | |
46 FORTH_ASSERT(reporter, 2 == fe->depth()); | |
47 FORTH_ASSERT(reporter, -17 == fe->peek(0)); | |
48 FORTH_ASSERT(reporter, -17 == fe->peek(1)); | |
49 } | |
50 | |
51 static void swap_test(ForthWord* word, ForthEngine* fe, Reporter* reporter) { | |
52 fe->push(-17); | |
53 fe->push(42); | |
54 word->exec(fe); | |
55 FORTH_ASSERT(reporter, 2 == fe->depth()); | |
56 FORTH_ASSERT(reporter, -17 == fe->peek(0)); | |
57 FORTH_ASSERT(reporter, 42 == fe->peek(1)); | |
58 } | |
59 | |
60 static void over_test(ForthWord* word, ForthEngine* fe, Reporter* reporter) { | |
61 fe->push(1); | |
62 fe->push(2); | |
63 word->exec(fe); | |
64 FORTH_ASSERT(reporter, 3 == fe->depth()); | |
65 FORTH_ASSERT(reporter, 1 == fe->peek(0)); | |
66 FORTH_ASSERT(reporter, 2 == fe->peek(1)); | |
67 FORTH_ASSERT(reporter, 1 == fe->peek(2)); | |
68 } | |
69 | |
70 static void rot_test(ForthWord* word, ForthEngine* fe, Reporter* reporter) { | |
71 fe->push(1); | |
72 fe->push(2); | |
73 fe->push(3); | |
74 word->exec(fe); | |
75 FORTH_ASSERT(reporter, 3 == fe->depth()); | |
76 FORTH_ASSERT(reporter, 2 == fe->peek(2)); | |
77 FORTH_ASSERT(reporter, 3 == fe->peek(1)); | |
78 FORTH_ASSERT(reporter, 1 == fe->peek(0)); | |
79 } | |
80 | |
81 static void rrot_test(ForthWord* word, ForthEngine* fe, Reporter* reporter) { | |
82 fe->push(1); | |
83 fe->push(2); | |
84 fe->push(3); | |
85 word->exec(fe); | |
86 FORTH_ASSERT(reporter, 3 == fe->depth()); | |
87 FORTH_ASSERT(reporter, 2 == fe->peek(0)); | |
88 FORTH_ASSERT(reporter, 1 == fe->peek(1)); | |
89 FORTH_ASSERT(reporter, 3 == fe->peek(2)); | |
90 } | |
91 | |
92 static void swap2_test(ForthWord* word, ForthEngine* fe, Reporter* reporter) { | |
93 fe->push(1); | |
94 fe->push(2); | |
95 fe->push(3); | |
96 fe->push(4); | |
97 word->exec(fe); | |
98 FORTH_ASSERT(reporter, 4 == fe->depth()); | |
99 FORTH_ASSERT(reporter, 2 == fe->peek(0)); | |
100 FORTH_ASSERT(reporter, 1 == fe->peek(1)); | |
101 FORTH_ASSERT(reporter, 4 == fe->peek(2)); | |
102 FORTH_ASSERT(reporter, 3 == fe->peek(3)); | |
103 } | |
104 | |
105 static void dup2_test(ForthWord* word, ForthEngine* fe, Reporter* reporter) { | |
106 fe->push(1); | |
107 fe->push(2); | |
108 word->exec(fe); | |
109 FORTH_ASSERT(reporter, 4 == fe->depth()); | |
110 FORTH_ASSERT(reporter, 1 == fe->peek(3)); | |
111 FORTH_ASSERT(reporter, 2 == fe->peek(2)); | |
112 FORTH_ASSERT(reporter, 1 == fe->peek(1)); | |
113 FORTH_ASSERT(reporter, 2 == fe->peek(0)); | |
114 } | |
115 | |
116 static void over2_test(ForthWord* word, ForthEngine* fe, Reporter* reporter) { | |
117 fe->push(1); | |
118 fe->push(2); | |
119 fe->push(3); | |
120 fe->push(4); | |
121 word->exec(fe); | |
122 FORTH_ASSERT(reporter, 6 == fe->depth()); | |
123 FORTH_ASSERT(reporter, 1 == fe->peek(5)); | |
124 FORTH_ASSERT(reporter, 2 == fe->peek(4)); | |
125 FORTH_ASSERT(reporter, 3 == fe->peek(3)); | |
126 FORTH_ASSERT(reporter, 4 == fe->peek(2)); | |
127 FORTH_ASSERT(reporter, 1 == fe->peek(1)); | |
128 FORTH_ASSERT(reporter, 2 == fe->peek(0)); | |
129 } | |
130 | |
131 static void drop2_test(ForthWord* word, ForthEngine* fe, Reporter* reporter) { | |
132 fe->push(1); | |
133 fe->push(2); | |
134 fe->push(3); | |
135 fe->push(4); | |
136 word->exec(fe); | |
137 FORTH_ASSERT(reporter, 2 == fe->depth()); | |
138 FORTH_ASSERT(reporter, 1 == fe->peek(1)); | |
139 FORTH_ASSERT(reporter, 2 == fe->peek(0)); | |
140 } | |
141 | |
142 ////////////////////////////////////////////////////////////////////////////// | |
143 | |
144 static void iadd_test(ForthWord* word, ForthEngine* fe, Reporter* reporter) { | |
145 fe->push(35); | |
146 fe->push(99); | |
147 word->exec(fe); | |
148 FORTH_ASSERT(reporter, 1 == fe->depth()); | |
149 FORTH_ASSERT(reporter, 134 == fe->top()); | |
150 fe->push(-135); | |
151 word->exec(fe); | |
152 FORTH_ASSERT(reporter, 1 == fe->depth()); | |
153 FORTH_ASSERT(reporter, -1 == fe->top()); | |
154 } | |
155 | |
156 static void isub_test(ForthWord* word, ForthEngine* fe, Reporter* reporter) { | |
157 fe->push(35); | |
158 fe->push(99); | |
159 word->exec(fe); | |
160 FORTH_ASSERT(reporter, 1 == fe->depth()); | |
161 FORTH_ASSERT(reporter, 35-99 == fe->top()); | |
162 } | |
163 | |
164 static void imul_test(ForthWord* word, ForthEngine* fe, Reporter* reporter) { | |
165 fe->push(15); | |
166 fe->push(-20); | |
167 word->exec(fe); | |
168 FORTH_ASSERT(reporter, 1 == fe->depth()); | |
169 FORTH_ASSERT(reporter, -300 == fe->top()); | |
170 fe->push(0); | |
171 word->exec(fe); | |
172 FORTH_ASSERT(reporter, 1 == fe->depth()); | |
173 FORTH_ASSERT(reporter, 0 == fe->top()); | |
174 } | |
175 | |
176 static void idiv_test(ForthWord* word, ForthEngine* fe, Reporter* reporter) { | |
177 fe->push(100); | |
178 fe->push(25); | |
179 word->exec(fe); | |
180 FORTH_ASSERT(reporter, 1 == fe->depth()); | |
181 FORTH_ASSERT(reporter, 4 == fe->top()); | |
182 fe->setTop(10); | |
183 fe->push(-3); | |
184 word->exec(fe); | |
185 FORTH_ASSERT(reporter, 1 == fe->depth()); | |
186 FORTH_ASSERT(reporter, -3 == fe->top()); | |
187 fe->setTop(-1); | |
188 fe->push(-1); | |
189 word->exec(fe); | |
190 FORTH_ASSERT(reporter, 1 == fe->depth()); | |
191 FORTH_ASSERT(reporter, 1 == fe->top()); | |
192 } | |
193 | |
194 static void imod_test(ForthWord* word, ForthEngine* fe, Reporter* reporter) { | |
195 fe->push(10); | |
196 fe->push(3); | |
197 word->exec(fe); | |
198 FORTH_ASSERT(reporter, 1 == fe->depth()); | |
199 FORTH_ASSERT(reporter, 1 == fe->top()); | |
200 fe->push(5); | |
201 word->exec(fe); | |
202 FORTH_ASSERT(reporter, 1 == fe->depth()); | |
203 FORTH_ASSERT(reporter, 1 == fe->top()); | |
204 } | |
205 | |
206 static void idivmod_test(ForthWord* word, ForthEngine* fe, Reporter* reporter) { | |
207 fe->push(10); | |
208 fe->push(3); | |
209 word->exec(fe); | |
210 FORTH_ASSERT(reporter, 2 == fe->depth()); | |
211 FORTH_ASSERT(reporter, 1 == fe->peek(1)); | |
212 FORTH_ASSERT(reporter, 3 == fe->peek(0)); | |
213 } | |
214 | |
215 static void idot_test(ForthWord* word, ForthEngine* fe, Reporter* reporter) { | |
216 fe->push(1); | |
217 fe->push(2); | |
218 word->exec(fe); | |
219 FORTH_ASSERT(reporter, 1 == fe->depth()); | |
220 FORTH_ASSERT(reporter, 1 == fe->top()); | |
221 } | |
222 | |
223 static void iabs_test(ForthWord* word, ForthEngine* fe, Reporter* reporter) { | |
224 fe->push(10); | |
225 word->exec(fe); | |
226 FORTH_ASSERT(reporter, 1 == fe->depth()); | |
227 FORTH_ASSERT(reporter, 10 == fe->top()); | |
228 fe->setTop(-10); | |
229 word->exec(fe); | |
230 FORTH_ASSERT(reporter, 1 == fe->depth()); | |
231 FORTH_ASSERT(reporter, 10 == fe->top()); | |
232 } | |
233 | |
234 static void inegate_test(ForthWord* word, ForthEngine* fe, Reporter* reporter) { | |
235 fe->push(10); | |
236 word->exec(fe); | |
237 FORTH_ASSERT(reporter, 1 == fe->depth()); | |
238 FORTH_ASSERT(reporter, -10 == fe->top()); | |
239 fe->setTop(-10); | |
240 word->exec(fe); | |
241 FORTH_ASSERT(reporter, 1 == fe->depth()); | |
242 FORTH_ASSERT(reporter, 10 == fe->top()); | |
243 } | |
244 | |
245 static void imin_test(ForthWord* word, ForthEngine* fe, Reporter* reporter) { | |
246 fe->push(10); | |
247 fe->push(3); | |
248 word->exec(fe); | |
249 FORTH_ASSERT(reporter, 1 == fe->depth()); | |
250 FORTH_ASSERT(reporter, 3 == fe->top()); | |
251 fe->push(-10); | |
252 word->exec(fe); | |
253 FORTH_ASSERT(reporter, 1 == fe->depth()); | |
254 FORTH_ASSERT(reporter, -10 == fe->top()); | |
255 } | |
256 | |
257 static void imax_test(ForthWord* word, ForthEngine* fe, Reporter* reporter) { | |
258 fe->push(10); | |
259 fe->push(3); | |
260 word->exec(fe); | |
261 FORTH_ASSERT(reporter, 1 == fe->depth()); | |
262 FORTH_ASSERT(reporter, 10 == fe->top()); | |
263 fe->push(-10); | |
264 word->exec(fe); | |
265 FORTH_ASSERT(reporter, 1 == fe->depth()); | |
266 FORTH_ASSERT(reporter, 10 == fe->top()); | |
267 } | |
268 | |
269 /////////////////////////////////////////////////////////////////////////////// | |
270 | |
271 static void logical_and_test(ForthWord* word, ForthEngine* fe, Reporter* reporte
r) { | |
272 const static int data[] = { | |
273 0, 0, 0, | |
274 2, 0, 0, | |
275 0, -1, 0, | |
276 1, 5, -1 | |
277 }; | |
278 for (size_t i = 0; i < SK_ARRAY_COUNT(data)/3; i++) { | |
279 fe->push(data[i*3 + 0]); | |
280 fe->push(data[i*3 + 1]); | |
281 word->exec(fe); | |
282 FORTH_ASSERT(reporter, 1 == fe->depth()); | |
283 FORTH_ASSERT(reporter, data[i*3 + 2] == fe->top()); | |
284 fe->pop(); | |
285 } | |
286 } | |
287 | |
288 static void logical_or_test(ForthWord* word, ForthEngine* fe, Reporter* reporter
) { | |
289 const static int data[] = { | |
290 0, 0, 0, | |
291 2, 0, -1, | |
292 0, -1, -1, | |
293 1, 5, -1 | |
294 }; | |
295 for (size_t i = 0; i < SK_ARRAY_COUNT(data)/3; i++) { | |
296 fe->push(data[i*3 + 0]); | |
297 fe->push(data[i*3 + 1]); | |
298 word->exec(fe); | |
299 FORTH_ASSERT(reporter, 1 == fe->depth()); | |
300 FORTH_ASSERT(reporter, data[i*3 + 2] == fe->top()); | |
301 fe->pop(); | |
302 } | |
303 } | |
304 | |
305 static void logical_not_test(ForthWord* word, ForthEngine* fe, Reporter* reporte
r) { | |
306 const static int data[] = { | |
307 0, -1, | |
308 5, 0, | |
309 -1, 0 | |
310 }; | |
311 for (size_t i = 0; i < SK_ARRAY_COUNT(data)/2; i++) { | |
312 fe->push(data[i*2 + 0]); | |
313 word->exec(fe); | |
314 FORTH_ASSERT(reporter, 1 == fe->depth()); | |
315 FORTH_ASSERT(reporter, data[i*2 + 1] == fe->top()); | |
316 fe->pop(); | |
317 } | |
318 } | |
319 | |
320 static void if_dup_test(ForthWord* word, ForthEngine* fe, Reporter* reporter) { | |
321 fe->push(10); | |
322 word->exec(fe); | |
323 FORTH_ASSERT(reporter, 2 == fe->depth()); | |
324 FORTH_ASSERT(reporter, 10 == fe->peek(1)); | |
325 FORTH_ASSERT(reporter, 10 == fe->peek(0)); | |
326 fe->pop(); | |
327 fe->pop(); | |
328 fe->push(0); | |
329 word->exec(fe); | |
330 FORTH_ASSERT(reporter, 1 == fe->depth()); | |
331 FORTH_ASSERT(reporter, 0 == fe->top()); | |
332 } | |
333 | |
334 static const struct { | |
335 const char* fName; | |
336 ForthWordTestProc fProc; | |
337 } gRecs[] = { | |
338 { "DROP", drop_test0 }, { "DROP", drop_test1 }, | |
339 { "DUP", dup_test }, | |
340 { "SWAP", swap_test }, | |
341 { "OVER", over_test }, | |
342 { "ROT", rot_test }, | |
343 { "-ROT", rrot_test }, | |
344 { "2SWAP", swap2_test }, | |
345 { "2DUP", dup2_test }, | |
346 { "2OVER", over2_test }, | |
347 { "2DROP", drop2_test }, | |
348 | |
349 { "+", iadd_test }, | |
350 { "-", isub_test }, | |
351 { "*", imul_test }, | |
352 { "/", idiv_test }, | |
353 { "MOD", imod_test }, | |
354 { "/MOD", idivmod_test }, | |
355 | |
356 // { ".", idot_test }, | |
357 { "ABS", iabs_test }, | |
358 { "NEGATE", inegate_test }, | |
359 { "MIN", imin_test }, | |
360 { "MAX", imax_test }, | |
361 | |
362 { "AND", logical_and_test }, | |
363 { "OR", logical_or_test }, | |
364 { "0=", logical_not_test }, | |
365 { "?DUP", if_dup_test }, | |
366 }; | |
367 | |
368 /////////////////////////////////////////////////////////////////////////////// | |
369 | |
370 void Reporter::reportFailure(const char expression[], const char file[], | |
371 int line) { | |
372 SkDebugf("failed %s:%d: %s\n", file, line, expression); | |
373 fFailureCount += 1; | |
374 } | |
375 | |
376 void Reporter::reportFailure(const char msg[]) { | |
377 SkDebugf("%s\n"); | |
378 fFailureCount += 1; | |
379 } | |
380 | |
381 void Forth_test_stdwords(bool verbose); | |
382 void Forth_test_stdwords(bool verbose) { | |
383 ForthEnv env; | |
384 Reporter reporter; | |
385 | |
386 for (size_t i = 0; i < SK_ARRAY_COUNT(gRecs); i++) { | |
387 ForthEngine engine(NULL); | |
388 | |
389 ForthWord* word = env.findWord(gRecs[i].fName); | |
390 if (NULL == word) { | |
391 SkString str; | |
392 str.printf("--- can't find stdword %d", gRecs[i].fName); | |
393 reporter.reportFailure(str.c_str()); | |
394 } else { | |
395 if (verbose) { | |
396 SkDebugf("--- testing %s %p\n", gRecs[i].fName, word); | |
397 } | |
398 gRecs[i].fProc(word, &engine, &reporter); | |
399 } | |
400 } | |
401 | |
402 if (0 == reporter.fFailureCount) { | |
403 SkDebugf("--- success!\n"); | |
404 } else { | |
405 SkDebugf("--- %d failures\n", reporter.fFailureCount); | |
406 } | |
407 } | |
OLD | NEW |