blob: 98e39c028d6d9a095016a6dfbe9cf97a7e3ecbc3 [file] [log] [blame]
reed@android.com289e4fc2009-08-31 18:04:51 +00001#include "Forth.h"
2#include "ForthParser.h"
3#include "SkString.h"
4
reed@android.come50025a2009-09-01 21:00:44 +00005#define BEGIN_WORD(name) \
6 class name##_ForthWord : public ForthWord { \
7 public: \
8 virtual void exec(ForthEngine* fe)
reed@android.com289e4fc2009-08-31 18:04:51 +00009
reed@android.come50025a2009-09-01 21:00:44 +000010#define END_WORD };
reed@android.com289e4fc2009-08-31 18:04:51 +000011
reed@android.come50025a2009-09-01 21:00:44 +000012///////////////////////////////////////////////////////////////////////////////
reed@android.com289e4fc2009-08-31 18:04:51 +000013
reed@android.come50025a2009-09-01 21:00:44 +000014BEGIN_WORD(drop) {
15 (void)fe->pop();
16} END_WORD
reed@android.com289e4fc2009-08-31 18:04:51 +000017
reed@android.come50025a2009-09-01 21:00:44 +000018BEGIN_WORD(over) {
19 fe->push(fe->peek(1));
20} END_WORD
21
22BEGIN_WORD(dup) {
23 fe->push(fe->top());
24} END_WORD
25
26BEGIN_WORD(swap) {
27 intptr_t a = fe->pop();
28 intptr_t b = fe->top();
29 fe->setTop(a);
30 fe->push(b);
31} END_WORD
32
33BEGIN_WORD(rot) {
34 intptr_t c = fe->pop();
35 intptr_t b = fe->pop();
36 intptr_t a = fe->pop();
37 fe->push(b);
38 fe->push(c);
39 fe->push(a);
40} END_WORD
41
42BEGIN_WORD(rrot) {
43 intptr_t c = fe->pop();
44 intptr_t b = fe->pop();
45 intptr_t a = fe->pop();
46 fe->push(c);
47 fe->push(a);
48 fe->push(b);
49} END_WORD
50
51BEGIN_WORD(swap2) {
52 intptr_t d = fe->pop();
53 intptr_t c = fe->pop();
54 intptr_t b = fe->pop();
55 intptr_t a = fe->pop();
56 fe->push(c);
57 fe->push(d);
58 fe->push(a);
59 fe->push(b);
60} END_WORD
61
62BEGIN_WORD(dup2) {
63 fe->push(fe->peek(1));
64 fe->push(fe->peek(1));
65} END_WORD
66
67BEGIN_WORD(over2) {
68 fe->push(fe->peek(3));
69 fe->push(fe->peek(3));
70} END_WORD
71
72BEGIN_WORD(drop2) {
73 (void)fe->pop();
74 (void)fe->pop();
75} END_WORD
76
77///////////////// logicals
78
79BEGIN_WORD(logical_and) {
80 fe->push(-(fe->pop() && fe->pop()));
81} END_WORD
82
83BEGIN_WORD(logical_or) {
84 fe->push(-(fe->pop() || fe->pop()));
85} END_WORD
86
87BEGIN_WORD(logical_not) {
88 fe->setTop(-(!fe->top()));
89} END_WORD
90
91BEGIN_WORD(if_dup) {
92 intptr_t tmp = fe->top();
93 if (tmp) {
94 fe->push(tmp);
reed@android.com289e4fc2009-08-31 18:04:51 +000095 }
reed@android.come50025a2009-09-01 21:00:44 +000096} END_WORD
reed@android.com289e4fc2009-08-31 18:04:51 +000097
98///////////////// ints
99
reed@android.come50025a2009-09-01 21:00:44 +0000100class add_ForthWord : public ForthWord { public:
reed@android.com289e4fc2009-08-31 18:04:51 +0000101 virtual void exec(ForthEngine* fe) {
102 intptr_t tmp = fe->pop();
103 fe->setTop(fe->top() + tmp);
reed@android.come50025a2009-09-01 21:00:44 +0000104 }};
reed@android.com289e4fc2009-08-31 18:04:51 +0000105
reed@android.come50025a2009-09-01 21:00:44 +0000106class sub_ForthWord : public ForthWord { public:
reed@android.com289e4fc2009-08-31 18:04:51 +0000107 virtual void exec(ForthEngine* fe) {
108 intptr_t tmp = fe->pop();
109 fe->setTop(fe->top() - tmp);
reed@android.come50025a2009-09-01 21:00:44 +0000110 }};
reed@android.com289e4fc2009-08-31 18:04:51 +0000111
reed@android.come50025a2009-09-01 21:00:44 +0000112class mul_ForthWord : public ForthWord { public:
reed@android.com289e4fc2009-08-31 18:04:51 +0000113 virtual void exec(ForthEngine* fe) {
114 intptr_t tmp = fe->pop();
115 fe->setTop(fe->top() * tmp);
reed@android.come50025a2009-09-01 21:00:44 +0000116 }};
reed@android.com289e4fc2009-08-31 18:04:51 +0000117
reed@android.come50025a2009-09-01 21:00:44 +0000118class div_ForthWord : public ForthWord { public:
reed@android.com289e4fc2009-08-31 18:04:51 +0000119 virtual void exec(ForthEngine* fe) {
120 intptr_t tmp = fe->pop();
121 fe->setTop(fe->top() / tmp);
reed@android.come50025a2009-09-01 21:00:44 +0000122 }};
reed@android.com289e4fc2009-08-31 18:04:51 +0000123
reed@android.come50025a2009-09-01 21:00:44 +0000124class mod_ForthWord : public ForthWord { public:
125 virtual void exec(ForthEngine* fe) {
126 intptr_t tmp = fe->pop();
127 fe->setTop(fe->top() % tmp);
128 }};
129
130class divmod_ForthWord : public ForthWord { public:
131 virtual void exec(ForthEngine* fe) {
132 intptr_t denom = fe->pop();
133 intptr_t numer = fe->pop();
134 fe->push(numer % denom);
135 fe->push(numer / denom);
136 }};
137
138class dot_ForthWord : public ForthWord { public:
reed@android.com289e4fc2009-08-31 18:04:51 +0000139 virtual void exec(ForthEngine* fe) {
140 SkString str;
141 str.printf("%d ", fe->pop());
142 fe->sendOutput(str.c_str());
reed@android.come50025a2009-09-01 21:00:44 +0000143 }};
reed@android.com289e4fc2009-08-31 18:04:51 +0000144
reed@android.come50025a2009-09-01 21:00:44 +0000145class abs_ForthWord : public ForthWord { public:
reed@android.com289e4fc2009-08-31 18:04:51 +0000146 virtual void exec(ForthEngine* fe) {
147 int32_t value = fe->top();
148 if (value < 0) {
149 fe->setTop(-value);
150 }
reed@android.come50025a2009-09-01 21:00:44 +0000151 }};
reed@android.com289e4fc2009-08-31 18:04:51 +0000152
reed@android.come50025a2009-09-01 21:00:44 +0000153class negate_ForthWord : public ForthWord { public:
154 virtual void exec(ForthEngine* fe) {
155 fe->setTop(-fe->top());
156 }};
157
158class min_ForthWord : public ForthWord { public:
reed@android.com289e4fc2009-08-31 18:04:51 +0000159 virtual void exec(ForthEngine* fe) {
160 int32_t value = fe->pop();
161 if (value < fe->top()) {
162 fe->setTop(value);
163 }
reed@android.come50025a2009-09-01 21:00:44 +0000164 }};
reed@android.com289e4fc2009-08-31 18:04:51 +0000165
166class max_ForthWord : public ForthWord {
167public:
168 virtual void exec(ForthEngine* fe) {
169 int32_t value = fe->pop();
170 if (value > fe->top()) {
171 fe->setTop(value);
172 }
173 }
174};
175
176///////////////// floats
177
178class fadd_ForthWord : public ForthWord {
179public:
180 virtual void exec(ForthEngine* fe) {
181 float tmp = fe->fpop();
182 fe->fsetTop(fe->ftop() + tmp);
183 }
184};
185
186class fsub_ForthWord : public ForthWord {
187public:
188 virtual void exec(ForthEngine* fe) {
189 float tmp = fe->fpop();
190 fe->fsetTop(fe->ftop() - tmp);
191 }
192};
193
194class fmul_ForthWord : public ForthWord {
195public:
196 virtual void exec(ForthEngine* fe) {
197 float tmp = fe->fpop();
198 fe->fsetTop(fe->ftop() * tmp);
199 }
200};
201
202class fdiv_ForthWord : public ForthWord {
203public:
204 virtual void exec(ForthEngine* fe) {
205 float tmp = fe->fpop();
206 fe->fsetTop(fe->ftop() / tmp);
207 }
208};
209
210class fdot_ForthWord : public ForthWord {
211public:
212 virtual void exec(ForthEngine* fe) {
213 SkString str;
214 str.printf("%g ", fe->fpop());
215 fe->sendOutput(str.c_str());
216 }
217};
218
219class fabs_ForthWord : public ForthWord {
220public:
221 virtual void exec(ForthEngine* fe) {
222 float value = fe->ftop();
223 if (value < 0) {
224 fe->fsetTop(-value);
225 }
226 }
227};
228
229class fmin_ForthWord : public ForthWord {
230public:
231 virtual void exec(ForthEngine* fe) {
232 float value = fe->fpop();
233 if (value < fe->ftop()) {
234 fe->fsetTop(value);
235 }
236 }
237};
238
239class fmax_ForthWord : public ForthWord {
240public:
241 virtual void exec(ForthEngine* fe) {
242 float value = fe->fpop();
243 if (value > fe->ftop()) {
244 fe->fsetTop(value);
245 }
246 }
247};
248
249class floor_ForthWord : public ForthWord {
250public:
251 virtual void exec(ForthEngine* fe) {
252 fe->fsetTop(floorf(fe->ftop()));
253 }
254};
255
256class ceil_ForthWord : public ForthWord {
257public:
258 virtual void exec(ForthEngine* fe) {
259 fe->fsetTop(ceilf(fe->ftop()));
260 }
261};
262
263class round_ForthWord : public ForthWord {
264public:
265 virtual void exec(ForthEngine* fe) {
266 fe->fsetTop(floorf(fe->ftop() + 0.5f));
267 }
268};
269
270class f2i_ForthWord : public ForthWord {
271public:
272 virtual void exec(ForthEngine* fe) {
273 fe->setTop((int)fe->ftop());
274 }
275};
276
277class i2f_ForthWord : public ForthWord {
278public:
279 virtual void exec(ForthEngine* fe) {
280 fe->fsetTop((float)fe->top());
281 }
282};
283
reed@android.come50025a2009-09-01 21:00:44 +0000284////////////////////////////// int compares
reed@android.com289e4fc2009-08-31 18:04:51 +0000285
286class eq_ForthWord : public ForthWord { public:
287 virtual void exec(ForthEngine* fe) {
reed@android.come50025a2009-09-01 21:00:44 +0000288 fe->push(-(fe->pop() == fe->pop()));
reed@android.com289e4fc2009-08-31 18:04:51 +0000289 }
290};
291
292class neq_ForthWord : public ForthWord { public:
293 virtual void exec(ForthEngine* fe) {
reed@android.come50025a2009-09-01 21:00:44 +0000294 fe->push(-(fe->pop() != fe->pop()));
reed@android.com289e4fc2009-08-31 18:04:51 +0000295 }
296};
297
298class lt_ForthWord : public ForthWord { public:
299 virtual void exec(ForthEngine* fe) {
300 intptr_t tmp = fe->pop();
reed@android.come50025a2009-09-01 21:00:44 +0000301 fe->setTop(-(fe->top() < tmp));
reed@android.com289e4fc2009-08-31 18:04:51 +0000302 }
303};
304
305class le_ForthWord : public ForthWord { public:
306 virtual void exec(ForthEngine* fe) {
307 intptr_t tmp = fe->pop();
reed@android.come50025a2009-09-01 21:00:44 +0000308 fe->setTop(-(fe->top() <= tmp));
reed@android.com289e4fc2009-08-31 18:04:51 +0000309 }
310};
311
312class gt_ForthWord : public ForthWord { public:
313 virtual void exec(ForthEngine* fe) {
314 intptr_t tmp = fe->pop();
reed@android.come50025a2009-09-01 21:00:44 +0000315 fe->setTop(-(fe->top() > tmp));
reed@android.com289e4fc2009-08-31 18:04:51 +0000316 }
317};
318
319class ge_ForthWord : public ForthWord { public:
320 virtual void exec(ForthEngine* fe) {
321 intptr_t tmp = fe->pop();
reed@android.come50025a2009-09-01 21:00:44 +0000322 fe->setTop(-(fe->top() >= tmp));
reed@android.com289e4fc2009-08-31 18:04:51 +0000323 }
324};
325
reed@android.come50025a2009-09-01 21:00:44 +0000326BEGIN_WORD(lt0) {
327 fe->setTop(fe->top() >> 31);
328} END_WORD
329
330BEGIN_WORD(ge0) {
331 fe->setTop(~(fe->top() >> 31));
332} END_WORD
333
334BEGIN_WORD(gt0) {
335 fe->setTop(-(fe->top() > 0));
336} END_WORD
337
338BEGIN_WORD(le0) {
339 fe->setTop(-(fe->top() <= 0));
340} END_WORD
341
342/////////////////////////////// float compares
343
344/* negative zero is our nemesis, otherwise we could use = and <> from ints */
345
reed@android.com289e4fc2009-08-31 18:04:51 +0000346class feq_ForthWord : public ForthWord { public:
347 virtual void exec(ForthEngine* fe) {
reed@android.come50025a2009-09-01 21:00:44 +0000348 fe->push(-(fe->fpop() == fe->fpop()));
reed@android.com289e4fc2009-08-31 18:04:51 +0000349 }
350};
351
352class fneq_ForthWord : public ForthWord { public:
353 virtual void exec(ForthEngine* fe) {
reed@android.come50025a2009-09-01 21:00:44 +0000354 fe->push(-(fe->fpop() != fe->fpop()));
reed@android.com289e4fc2009-08-31 18:04:51 +0000355 }
356};
357
358class flt_ForthWord : public ForthWord { public:
359 virtual void exec(ForthEngine* fe) {
360 float tmp = fe->fpop();
reed@android.come50025a2009-09-01 21:00:44 +0000361 fe->setTop(-(fe->ftop() < tmp));
reed@android.com289e4fc2009-08-31 18:04:51 +0000362 }
363};
364
365class fle_ForthWord : public ForthWord { public:
366 virtual void exec(ForthEngine* fe) {
367 float tmp = fe->fpop();
reed@android.come50025a2009-09-01 21:00:44 +0000368 fe->setTop(-(fe->ftop() <= tmp));
reed@android.com289e4fc2009-08-31 18:04:51 +0000369 }
370};
371
372class fgt_ForthWord : public ForthWord { public:
373 virtual void exec(ForthEngine* fe) {
374 float tmp = fe->fpop();
reed@android.come50025a2009-09-01 21:00:44 +0000375 fe->setTop(-(fe->ftop() > tmp));
reed@android.com289e4fc2009-08-31 18:04:51 +0000376 }
377};
378
379class fge_ForthWord : public ForthWord { public:
380 virtual void exec(ForthEngine* fe) {
381 float tmp = fe->fpop();
reed@android.come50025a2009-09-01 21:00:44 +0000382 fe->setTop(-(fe->ftop() >= tmp));
reed@android.com289e4fc2009-08-31 18:04:51 +0000383 }
384};
385
386///////////////////////////////////////////////////////////////////////////////
387
reed@android.come50025a2009-09-01 21:00:44 +0000388#define ADD_LITERAL_WORD(sym, name) \
389 this->add(sym, sizeof(sym)-1, new name##_ForthWord)
390
reed@android.com289e4fc2009-08-31 18:04:51 +0000391void ForthParser::addStdWords() {
reed@android.come50025a2009-09-01 21:00:44 +0000392 ADD_LITERAL_WORD("DROP", drop);
393 ADD_LITERAL_WORD("DUP", dup);
394 ADD_LITERAL_WORD("SWAP", swap);
395 ADD_LITERAL_WORD("OVER", over);
396 ADD_LITERAL_WORD("ROT", rot);
397 ADD_LITERAL_WORD("-ROT", rrot);
398 ADD_LITERAL_WORD("2SWAP", swap2);
399 ADD_LITERAL_WORD("2DUP", dup2);
400 ADD_LITERAL_WORD("2OVER", over2);
401 ADD_LITERAL_WORD("2DROP", drop2);
reed@android.com289e4fc2009-08-31 18:04:51 +0000402
403 this->add("+", 1, new add_ForthWord);
404 this->add("-", 1, new sub_ForthWord);
405 this->add("*", 1, new mul_ForthWord);
406 this->add("/", 1, new div_ForthWord);
reed@android.come50025a2009-09-01 21:00:44 +0000407 this->add("MOD", 1, new mod_ForthWord);
408 this->add("/MOD", 1, new divmod_ForthWord);
409
reed@android.com289e4fc2009-08-31 18:04:51 +0000410 this->add(".", 1, new dot_ForthWord);
reed@android.come50025a2009-09-01 21:00:44 +0000411 this->add("ABS", 3, new abs_ForthWord);
412 this->add("NEGATE", 3, new negate_ForthWord);
413 this->add("MIN", 3, new min_ForthWord);
414 this->add("MAX", 3, new max_ForthWord);
415
416 ADD_LITERAL_WORD("AND", logical_and);
417 ADD_LITERAL_WORD("OR", logical_or);
418 ADD_LITERAL_WORD("0=", logical_not);
419 ADD_LITERAL_WORD("?DUP", if_dup);
420
reed@android.com289e4fc2009-08-31 18:04:51 +0000421 this->add("f+", 2, new fadd_ForthWord);
422 this->add("f-", 2, new fsub_ForthWord);
423 this->add("f*", 2, new fmul_ForthWord);
424 this->add("f/", 2, new fdiv_ForthWord);
425 this->add("f.", 2, new fdot_ForthWord);
426 this->add("fabs", 4, new fabs_ForthWord);
427 this->add("fmin", 4, new fmin_ForthWord);
428 this->add("fmax", 4, new fmax_ForthWord);
429 this->add("fmax", 4, new fmax_ForthWord);
430 this->add("floor", 5, new floor_ForthWord);
431 this->add("ceil", 4, new ceil_ForthWord);
432 this->add("round", 5, new round_ForthWord);
433 this->add("f>i", 3, new f2i_ForthWord);
434 this->add("i>f", 3, new i2f_ForthWord);
435
436 this->add("=", 1, new eq_ForthWord);
437 this->add("<>", 2, new neq_ForthWord);
438 this->add("<", 1, new lt_ForthWord);
439 this->add("<=", 2, new le_ForthWord);
440 this->add(">", 1, new gt_ForthWord);
441 this->add(">=", 2, new ge_ForthWord);
reed@android.come50025a2009-09-01 21:00:44 +0000442 ADD_LITERAL_WORD("0<", lt0);
443 ADD_LITERAL_WORD("0>", gt0);
444 ADD_LITERAL_WORD("0<=", le0);
445 ADD_LITERAL_WORD("0>=", ge0);
446
reed@android.com289e4fc2009-08-31 18:04:51 +0000447 this->add("f=", 2, new feq_ForthWord);
448 this->add("f<>", 3, new fneq_ForthWord);
449 this->add("f<", 2, new flt_ForthWord);
450 this->add("f<=", 3, new fle_ForthWord);
451 this->add("f>", 2, new fgt_ForthWord);
452 this->add("f>=", 3, new fge_ForthWord);
453}
454