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