blob: 177dabd5b811332577345ea2ba1ab3c2d7e8482f [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) {
reed@android.comde2e7fb2009-09-02 02:07:32 +000080 intptr_t tmp = fe->pop();
81 fe->setTop(-(tmp && fe->top()));
reed@android.come50025a2009-09-01 21:00:44 +000082} END_WORD
83
84BEGIN_WORD(logical_or) {
reed@android.comde2e7fb2009-09-02 02:07:32 +000085 intptr_t tmp = fe->pop();
86 fe->setTop(-(tmp || fe->top()));
reed@android.come50025a2009-09-01 21:00:44 +000087} END_WORD
88
89BEGIN_WORD(logical_not) {
90 fe->setTop(-(!fe->top()));
91} END_WORD
92
93BEGIN_WORD(if_dup) {
94 intptr_t tmp = fe->top();
95 if (tmp) {
96 fe->push(tmp);
reed@android.com289e4fc2009-08-31 18:04:51 +000097 }
reed@android.come50025a2009-09-01 21:00:44 +000098} END_WORD
reed@android.com289e4fc2009-08-31 18:04:51 +000099
100///////////////// ints
101
reed@android.come50025a2009-09-01 21:00:44 +0000102class add_ForthWord : public ForthWord { public:
reed@android.com289e4fc2009-08-31 18:04:51 +0000103 virtual void exec(ForthEngine* fe) {
104 intptr_t tmp = fe->pop();
105 fe->setTop(fe->top() + tmp);
reed@android.come50025a2009-09-01 21:00:44 +0000106 }};
reed@android.com289e4fc2009-08-31 18:04:51 +0000107
reed@android.come50025a2009-09-01 21:00:44 +0000108class sub_ForthWord : public ForthWord { public:
reed@android.com289e4fc2009-08-31 18:04:51 +0000109 virtual void exec(ForthEngine* fe) {
110 intptr_t tmp = fe->pop();
111 fe->setTop(fe->top() - tmp);
reed@android.come50025a2009-09-01 21:00:44 +0000112 }};
reed@android.com289e4fc2009-08-31 18:04:51 +0000113
reed@android.come50025a2009-09-01 21:00:44 +0000114class mul_ForthWord : public ForthWord { public:
reed@android.com289e4fc2009-08-31 18:04:51 +0000115 virtual void exec(ForthEngine* fe) {
116 intptr_t tmp = fe->pop();
117 fe->setTop(fe->top() * tmp);
reed@android.come50025a2009-09-01 21:00:44 +0000118 }};
reed@android.com289e4fc2009-08-31 18:04:51 +0000119
reed@android.come50025a2009-09-01 21:00:44 +0000120class div_ForthWord : public ForthWord { public:
reed@android.com289e4fc2009-08-31 18:04:51 +0000121 virtual void exec(ForthEngine* fe) {
122 intptr_t tmp = fe->pop();
123 fe->setTop(fe->top() / tmp);
reed@android.come50025a2009-09-01 21:00:44 +0000124 }};
reed@android.com289e4fc2009-08-31 18:04:51 +0000125
reed@android.come50025a2009-09-01 21:00:44 +0000126class mod_ForthWord : public ForthWord { public:
127 virtual void exec(ForthEngine* fe) {
128 intptr_t tmp = fe->pop();
129 fe->setTop(fe->top() % tmp);
130 }};
131
132class divmod_ForthWord : public ForthWord { public:
133 virtual void exec(ForthEngine* fe) {
134 intptr_t denom = fe->pop();
135 intptr_t numer = fe->pop();
136 fe->push(numer % denom);
137 fe->push(numer / denom);
138 }};
139
140class dot_ForthWord : public ForthWord { public:
reed@android.com289e4fc2009-08-31 18:04:51 +0000141 virtual void exec(ForthEngine* fe) {
142 SkString str;
143 str.printf("%d ", fe->pop());
144 fe->sendOutput(str.c_str());
reed@android.come50025a2009-09-01 21:00:44 +0000145 }};
reed@android.com289e4fc2009-08-31 18:04:51 +0000146
reed@android.come50025a2009-09-01 21:00:44 +0000147class abs_ForthWord : public ForthWord { public:
reed@android.com289e4fc2009-08-31 18:04:51 +0000148 virtual void exec(ForthEngine* fe) {
149 int32_t value = fe->top();
150 if (value < 0) {
151 fe->setTop(-value);
152 }
reed@android.come50025a2009-09-01 21:00:44 +0000153 }};
reed@android.com289e4fc2009-08-31 18:04:51 +0000154
reed@android.come50025a2009-09-01 21:00:44 +0000155class negate_ForthWord : public ForthWord { public:
156 virtual void exec(ForthEngine* fe) {
157 fe->setTop(-fe->top());
158 }};
159
160class min_ForthWord : public ForthWord { public:
reed@android.com289e4fc2009-08-31 18:04:51 +0000161 virtual void exec(ForthEngine* fe) {
162 int32_t value = fe->pop();
163 if (value < fe->top()) {
164 fe->setTop(value);
165 }
reed@android.come50025a2009-09-01 21:00:44 +0000166 }};
reed@android.com289e4fc2009-08-31 18:04:51 +0000167
168class max_ForthWord : public ForthWord {
169public:
170 virtual void exec(ForthEngine* fe) {
171 int32_t value = fe->pop();
172 if (value > fe->top()) {
173 fe->setTop(value);
174 }
175 }
176};
177
178///////////////// floats
179
180class fadd_ForthWord : public ForthWord {
181public:
182 virtual void exec(ForthEngine* fe) {
183 float tmp = fe->fpop();
184 fe->fsetTop(fe->ftop() + tmp);
185 }
186};
187
188class fsub_ForthWord : public ForthWord {
189public:
190 virtual void exec(ForthEngine* fe) {
191 float tmp = fe->fpop();
192 fe->fsetTop(fe->ftop() - tmp);
193 }
194};
195
196class fmul_ForthWord : public ForthWord {
197public:
198 virtual void exec(ForthEngine* fe) {
199 float tmp = fe->fpop();
200 fe->fsetTop(fe->ftop() * tmp);
201 }
202};
203
204class fdiv_ForthWord : public ForthWord {
205public:
206 virtual void exec(ForthEngine* fe) {
207 float tmp = fe->fpop();
208 fe->fsetTop(fe->ftop() / tmp);
209 }
210};
211
212class fdot_ForthWord : public ForthWord {
213public:
214 virtual void exec(ForthEngine* fe) {
215 SkString str;
216 str.printf("%g ", fe->fpop());
217 fe->sendOutput(str.c_str());
218 }
219};
220
221class fabs_ForthWord : public ForthWord {
222public:
223 virtual void exec(ForthEngine* fe) {
224 float value = fe->ftop();
225 if (value < 0) {
226 fe->fsetTop(-value);
227 }
228 }
229};
230
231class fmin_ForthWord : public ForthWord {
232public:
233 virtual void exec(ForthEngine* fe) {
234 float value = fe->fpop();
235 if (value < fe->ftop()) {
236 fe->fsetTop(value);
237 }
238 }
239};
240
241class fmax_ForthWord : public ForthWord {
242public:
243 virtual void exec(ForthEngine* fe) {
244 float value = fe->fpop();
245 if (value > fe->ftop()) {
246 fe->fsetTop(value);
247 }
248 }
249};
250
251class floor_ForthWord : public ForthWord {
252public:
253 virtual void exec(ForthEngine* fe) {
254 fe->fsetTop(floorf(fe->ftop()));
255 }
256};
257
258class ceil_ForthWord : public ForthWord {
259public:
260 virtual void exec(ForthEngine* fe) {
261 fe->fsetTop(ceilf(fe->ftop()));
262 }
263};
264
265class round_ForthWord : public ForthWord {
266public:
267 virtual void exec(ForthEngine* fe) {
268 fe->fsetTop(floorf(fe->ftop() + 0.5f));
269 }
270};
271
272class f2i_ForthWord : public ForthWord {
273public:
274 virtual void exec(ForthEngine* fe) {
275 fe->setTop((int)fe->ftop());
276 }
277};
278
279class i2f_ForthWord : public ForthWord {
280public:
281 virtual void exec(ForthEngine* fe) {
282 fe->fsetTop((float)fe->top());
283 }
284};
285
reed@android.come50025a2009-09-01 21:00:44 +0000286////////////////////////////// int compares
reed@android.com289e4fc2009-08-31 18:04:51 +0000287
288class eq_ForthWord : public ForthWord { public:
289 virtual void exec(ForthEngine* fe) {
reed@android.come50025a2009-09-01 21:00:44 +0000290 fe->push(-(fe->pop() == fe->pop()));
reed@android.com289e4fc2009-08-31 18:04:51 +0000291 }
292};
293
294class neq_ForthWord : public ForthWord { public:
295 virtual void exec(ForthEngine* fe) {
reed@android.come50025a2009-09-01 21:00:44 +0000296 fe->push(-(fe->pop() != fe->pop()));
reed@android.com289e4fc2009-08-31 18:04:51 +0000297 }
298};
299
300class lt_ForthWord : public ForthWord { public:
301 virtual void exec(ForthEngine* fe) {
302 intptr_t tmp = fe->pop();
reed@android.come50025a2009-09-01 21:00:44 +0000303 fe->setTop(-(fe->top() < tmp));
reed@android.com289e4fc2009-08-31 18:04:51 +0000304 }
305};
306
307class le_ForthWord : public ForthWord { public:
308 virtual void exec(ForthEngine* fe) {
309 intptr_t tmp = fe->pop();
reed@android.come50025a2009-09-01 21:00:44 +0000310 fe->setTop(-(fe->top() <= tmp));
reed@android.com289e4fc2009-08-31 18:04:51 +0000311 }
312};
313
314class gt_ForthWord : public ForthWord { public:
315 virtual void exec(ForthEngine* fe) {
316 intptr_t tmp = fe->pop();
reed@android.come50025a2009-09-01 21:00:44 +0000317 fe->setTop(-(fe->top() > tmp));
reed@android.com289e4fc2009-08-31 18:04:51 +0000318 }
319};
320
321class ge_ForthWord : public ForthWord { public:
322 virtual void exec(ForthEngine* fe) {
323 intptr_t tmp = fe->pop();
reed@android.come50025a2009-09-01 21:00:44 +0000324 fe->setTop(-(fe->top() >= tmp));
reed@android.com289e4fc2009-08-31 18:04:51 +0000325 }
326};
327
reed@android.come50025a2009-09-01 21:00:44 +0000328BEGIN_WORD(lt0) {
329 fe->setTop(fe->top() >> 31);
330} END_WORD
331
332BEGIN_WORD(ge0) {
333 fe->setTop(~(fe->top() >> 31));
334} END_WORD
335
336BEGIN_WORD(gt0) {
337 fe->setTop(-(fe->top() > 0));
338} END_WORD
339
340BEGIN_WORD(le0) {
341 fe->setTop(-(fe->top() <= 0));
342} END_WORD
343
344/////////////////////////////// float compares
345
346/* negative zero is our nemesis, otherwise we could use = and <> from ints */
347
reed@android.com289e4fc2009-08-31 18:04:51 +0000348class feq_ForthWord : public ForthWord { public:
349 virtual void exec(ForthEngine* fe) {
reed@android.come50025a2009-09-01 21:00:44 +0000350 fe->push(-(fe->fpop() == fe->fpop()));
reed@android.com289e4fc2009-08-31 18:04:51 +0000351 }
352};
353
354class fneq_ForthWord : public ForthWord { public:
355 virtual void exec(ForthEngine* fe) {
reed@android.come50025a2009-09-01 21:00:44 +0000356 fe->push(-(fe->fpop() != fe->fpop()));
reed@android.com289e4fc2009-08-31 18:04:51 +0000357 }
358};
359
360class flt_ForthWord : public ForthWord { public:
361 virtual void exec(ForthEngine* fe) {
362 float tmp = fe->fpop();
reed@android.come50025a2009-09-01 21:00:44 +0000363 fe->setTop(-(fe->ftop() < tmp));
reed@android.com289e4fc2009-08-31 18:04:51 +0000364 }
365};
366
367class fle_ForthWord : public ForthWord { public:
368 virtual void exec(ForthEngine* fe) {
369 float tmp = fe->fpop();
reed@android.come50025a2009-09-01 21:00:44 +0000370 fe->setTop(-(fe->ftop() <= tmp));
reed@android.com289e4fc2009-08-31 18:04:51 +0000371 }
372};
373
374class fgt_ForthWord : public ForthWord { public:
375 virtual void exec(ForthEngine* fe) {
376 float tmp = fe->fpop();
reed@android.come50025a2009-09-01 21:00:44 +0000377 fe->setTop(-(fe->ftop() > tmp));
reed@android.com289e4fc2009-08-31 18:04:51 +0000378 }
379};
380
381class fge_ForthWord : public ForthWord { public:
382 virtual void exec(ForthEngine* fe) {
383 float tmp = fe->fpop();
reed@android.come50025a2009-09-01 21:00:44 +0000384 fe->setTop(-(fe->ftop() >= tmp));
reed@android.com289e4fc2009-08-31 18:04:51 +0000385 }
386};
387
388///////////////////////////////////////////////////////////////////////////////
389
reed@android.come50025a2009-09-01 21:00:44 +0000390#define ADD_LITERAL_WORD(sym, name) \
391 this->add(sym, sizeof(sym)-1, new name##_ForthWord)
392
reed@android.com289e4fc2009-08-31 18:04:51 +0000393void ForthParser::addStdWords() {
reed@android.come50025a2009-09-01 21:00:44 +0000394 ADD_LITERAL_WORD("DROP", drop);
395 ADD_LITERAL_WORD("DUP", dup);
396 ADD_LITERAL_WORD("SWAP", swap);
397 ADD_LITERAL_WORD("OVER", over);
398 ADD_LITERAL_WORD("ROT", rot);
399 ADD_LITERAL_WORD("-ROT", rrot);
400 ADD_LITERAL_WORD("2SWAP", swap2);
401 ADD_LITERAL_WORD("2DUP", dup2);
402 ADD_LITERAL_WORD("2OVER", over2);
403 ADD_LITERAL_WORD("2DROP", drop2);
reed@android.com289e4fc2009-08-31 18:04:51 +0000404
reed@android.comde2e7fb2009-09-02 02:07:32 +0000405 ADD_LITERAL_WORD("+", add);
406 ADD_LITERAL_WORD("-", sub);
407 ADD_LITERAL_WORD("*", mul);
408 ADD_LITERAL_WORD("/", div);
409 ADD_LITERAL_WORD("MOD", mod);
410 ADD_LITERAL_WORD("/MOD", divmod);
reed@android.come50025a2009-09-01 21:00:44 +0000411
reed@android.comde2e7fb2009-09-02 02:07:32 +0000412 ADD_LITERAL_WORD(".", dot);
413 ADD_LITERAL_WORD("ABS", abs);
414 ADD_LITERAL_WORD("NEGATE", negate);
415 ADD_LITERAL_WORD("MIN", min);
416 ADD_LITERAL_WORD("MAX", max);
reed@android.come50025a2009-09-01 21:00:44 +0000417
418 ADD_LITERAL_WORD("AND", logical_and);
419 ADD_LITERAL_WORD("OR", logical_or);
420 ADD_LITERAL_WORD("0=", logical_not);
421 ADD_LITERAL_WORD("?DUP", if_dup);
422
reed@android.com289e4fc2009-08-31 18:04:51 +0000423 this->add("f+", 2, new fadd_ForthWord);
424 this->add("f-", 2, new fsub_ForthWord);
425 this->add("f*", 2, new fmul_ForthWord);
426 this->add("f/", 2, new fdiv_ForthWord);
427 this->add("f.", 2, new fdot_ForthWord);
428 this->add("fabs", 4, new fabs_ForthWord);
429 this->add("fmin", 4, new fmin_ForthWord);
430 this->add("fmax", 4, new fmax_ForthWord);
431 this->add("fmax", 4, new fmax_ForthWord);
432 this->add("floor", 5, new floor_ForthWord);
433 this->add("ceil", 4, new ceil_ForthWord);
434 this->add("round", 5, new round_ForthWord);
435 this->add("f>i", 3, new f2i_ForthWord);
436 this->add("i>f", 3, new i2f_ForthWord);
437
438 this->add("=", 1, new eq_ForthWord);
439 this->add("<>", 2, new neq_ForthWord);
440 this->add("<", 1, new lt_ForthWord);
441 this->add("<=", 2, new le_ForthWord);
442 this->add(">", 1, new gt_ForthWord);
443 this->add(">=", 2, new ge_ForthWord);
reed@android.come50025a2009-09-01 21:00:44 +0000444 ADD_LITERAL_WORD("0<", lt0);
445 ADD_LITERAL_WORD("0>", gt0);
446 ADD_LITERAL_WORD("0<=", le0);
447 ADD_LITERAL_WORD("0>=", ge0);
448
reed@android.com289e4fc2009-08-31 18:04:51 +0000449 this->add("f=", 2, new feq_ForthWord);
450 this->add("f<>", 3, new fneq_ForthWord);
451 this->add("f<", 2, new flt_ForthWord);
452 this->add("f<=", 3, new fle_ForthWord);
453 this->add("f>", 2, new fgt_ForthWord);
454 this->add("f>=", 3, new fge_ForthWord);
455}
456