blob: 7b9dd5b7feb77a63f16663cc986f17bbaaa33bee [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
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 */
reed@android.come50025a2009-09-01 21:00:44 +00008#include "Forth.h"
9#include "SkString.h"
10
11class Reporter {
12public:
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
20typedef 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
29static 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
35static 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
43static 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
51static 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
60static 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
70static 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
81static 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
92static 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
105static 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
116static 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
131static 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
reed@android.comde2e7fb2009-09-02 02:07:32 +0000142//////////////////////////////////////////////////////////////////////////////
143
144static 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
156static 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
164static 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
176static 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
194static 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
206static 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
215static 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
223static 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
234static 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
245static 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
257static 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
271static void logical_and_test(ForthWord* word, ForthEngine* fe, Reporter* reporter) {
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
288static 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
305static void logical_not_test(ForthWord* word, ForthEngine* fe, Reporter* reporter) {
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
320static 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
reed@android.come50025a2009-09-01 21:00:44 +0000334static 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 },
reed@android.comde2e7fb2009-09-02 02:07:32 +0000348
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 },
reed@android.come50025a2009-09-01 21:00:44 +0000366};
367
368///////////////////////////////////////////////////////////////////////////////
369
370void 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
376void Reporter::reportFailure(const char msg[]) {
377 SkDebugf("%s\n");
378 fFailureCount += 1;
379}
380
reed@android.comde2e7fb2009-09-02 02:07:32 +0000381void Forth_test_stdwords(bool verbose);
382void Forth_test_stdwords(bool verbose) {
reed@android.come50025a2009-09-01 21:00:44 +0000383 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 {
reed@android.comde2e7fb2009-09-02 02:07:32 +0000395 if (verbose) {
396 SkDebugf("--- testing %s %p\n", gRecs[i].fName, word);
397 }
reed@android.come50025a2009-09-01 21:00:44 +0000398 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}
408