Mercurial > hg > dmlib
annotate dmeval.c @ 700:6d96d5bf9653
Add output file stream argument to dm_print_optree().
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Tue, 16 Apr 2013 21:29:37 +0300 |
parents | f6cf172a6ef7 |
children | e8224750f576 |
rev | line source |
---|---|
0 | 1 #include "dmeval.h" |
2 #include <stdio.h> | |
3 #include <math.h> | |
4 | |
5 #define DM_MAX_ID_LEN 16 | |
6 #define DM_MAX_BUF 512 | |
7 #define DM_STACK_SIZE 512 | |
8 | |
670 | 9 |
10 /* Function definitions | |
11 */ | |
663
05eb24a608f0
Some minor touches to evaluator code.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
12 static DMValue func_int_clip(DMValue *v) |
05eb24a608f0
Some minor touches to evaluator code.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
13 { |
05eb24a608f0
Some minor touches to evaluator code.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
14 return (*v < -1.0f) ? -1.0f : ((*v > 1.0f) ? 1.0f : *v); |
05eb24a608f0
Some minor touches to evaluator code.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
15 } |
05eb24a608f0
Some minor touches to evaluator code.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
16 |
05eb24a608f0
Some minor touches to evaluator code.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
17 |
05eb24a608f0
Some minor touches to evaluator code.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
18 static DMValue func_sin(DMValue *v) |
0 | 19 { |
663
05eb24a608f0
Some minor touches to evaluator code.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
20 return sin(*v); |
05eb24a608f0
Some minor touches to evaluator code.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
21 } |
05eb24a608f0
Some minor touches to evaluator code.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
22 |
05eb24a608f0
Some minor touches to evaluator code.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
23 |
05eb24a608f0
Some minor touches to evaluator code.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
24 static DMValue func_cos(DMValue *v) |
05eb24a608f0
Some minor touches to evaluator code.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
25 { |
05eb24a608f0
Some minor touches to evaluator code.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
26 return cos(*v); |
05eb24a608f0
Some minor touches to evaluator code.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
27 } |
05eb24a608f0
Some minor touches to evaluator code.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
28 |
05eb24a608f0
Some minor touches to evaluator code.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
29 |
05eb24a608f0
Some minor touches to evaluator code.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
30 static DMValue func_pow(DMValue *v) |
05eb24a608f0
Some minor touches to evaluator code.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
31 { |
05eb24a608f0
Some minor touches to evaluator code.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
32 return pow(v[0], v[1]); |
0 | 33 } |
34 | |
35 | |
36 /* Some basic functions | |
37 */ | |
38 static const DMEvalId dm_eval_basic[] = | |
39 { | |
670 | 40 { "sin", ID_FUNC, 1, func_sin, NULL, 0 }, |
41 { "cos", ID_FUNC, 1, func_cos, NULL, 0 }, | |
42 { "clip", ID_FUNC, 1, func_int_clip, NULL, 0 }, | |
43 { "pow", ID_FUNC, 2, func_pow, NULL, 0 }, | |
44 | |
45 { "pi", ID_CVAR, 0, NULL, NULL, DM_PI }, | |
0 | 46 }; |
47 | |
48 static const int ndm_eval_basic = sizeof(dm_eval_basic) / sizeof(dm_eval_basic[0]); | |
49 | |
50 | |
51 void dm_eval_err_v(DMEvalContext *ev, const char *fmt, va_list ap) | |
52 { | |
53 #if 1 | |
54 char *tmp = dm_strdup_vprintf(fmt, ap); | |
55 | |
56 ev->err = TRUE; | |
57 | |
58 if (ev->errStr != NULL) | |
59 { | |
60 ev->errStr = dm_strdup_printf("%s%s", ev->errStr, tmp); | |
61 dmFree(tmp); | |
62 } | |
63 else | |
64 ev->errStr = tmp; | |
65 #else | |
66 vfprintf(stdout, fmt, ap); | |
67 #endif | |
68 } | |
69 | |
70 | |
71 void dm_eval_err(DMEvalContext *ev, const char *fmt, ...) | |
72 { | |
73 va_list ap; | |
74 va_start(ap, fmt); | |
75 dm_eval_err_v(ev, fmt, ap); | |
76 va_end(ap); | |
77 } | |
78 | |
79 | |
80 DMEvalId *dm_eval_find_id(DMEvalContext *ev, const char *name) | |
81 { | |
82 int i; | |
83 if (ev->ids == NULL) | |
84 return NULL; | |
85 | |
86 for (i = 0; i < ev->nids; i++) | |
670 | 87 { |
0 | 88 if (strcmp(ev->ids[i].name, name) == 0) |
89 return &(ev->ids[i]); | |
670 | 90 } |
0 | 91 |
92 return NULL; | |
93 } | |
94 | |
95 | |
96 static DMEvalId *dm_eval_add_id(DMEvalContext *ev, const char *name, const int type) | |
97 { | |
98 DMEvalId *id = dm_eval_find_id(ev, name); | |
99 if (id != NULL) | |
100 return NULL; | |
101 | |
102 ev->ids = dmRealloc(ev->ids, sizeof(DMEvalId) * (ev->nids + 1)); | |
103 if (ev->ids == NULL) | |
104 { | |
105 dm_eval_err(ev, "Could not reallocate eval ids array (#%d). Fatal error.\n", ev->nids + 1); | |
106 return NULL; | |
107 } | |
108 | |
109 id = &(ev->ids[ev->nids]); | |
110 ev->nids++; | |
111 | |
112 id->name = dm_strdup(name); | |
113 id->type = type; | |
114 id->func = NULL; | |
115 id->var = NULL; | |
670 | 116 |
0 | 117 return id; |
118 } | |
119 | |
120 | |
121 DMEvalId *dm_eval_add_var(DMEvalContext *ev, const char *name, DMValue *var) | |
122 { | |
123 DMEvalId *id = dm_eval_add_id(ev, name, ID_VAR); | |
124 if (id == NULL) | |
125 return NULL; | |
126 | |
127 id->var = var; | |
128 return id; | |
129 } | |
130 | |
131 | |
670 | 132 DMEvalId *dm_eval_add_const(DMEvalContext *ev, const char *name, DMValue value) |
133 { | |
134 DMEvalId *id = dm_eval_add_id(ev, name, ID_CVAR); | |
135 if (id == NULL) | |
136 return NULL; | |
137 | |
138 id->cvalue = value; | |
139 return id; | |
140 } | |
141 | |
142 | |
143 DMEvalId *dm_eval_add_func(DMEvalContext *ev, const char *name, DMValue (*func)(DMValue *), int nargs) | |
0 | 144 { |
145 DMEvalId *id = dm_eval_add_id(ev, name, ID_VAR); | |
146 if (id == NULL) | |
147 return NULL; | |
148 | |
670 | 149 id->func = func; |
150 id->nargs = nargs; | |
0 | 151 return id; |
152 } | |
153 | |
154 | |
155 DMEvalContext *dm_eval_new(void) | |
156 { | |
157 int i; | |
158 DMEvalContext *ev = dmCalloc(1, sizeof(DMEvalContext)); | |
159 | |
160 if (ev == NULL) | |
161 return NULL; | |
162 | |
163 for (i = 0; i < ndm_eval_basic; i++) | |
164 { | |
165 const DMEvalId *id = &dm_eval_basic[i]; | |
166 DMEvalId *nid = dm_eval_add_id(ev, id->name, id->type); | |
670 | 167 nid->nargs = id->nargs; |
168 nid->func = id->func; | |
169 nid->var = id->var; | |
170 nid->cvalue = id->cvalue; | |
0 | 171 } |
172 | |
173 return ev; | |
174 } | |
175 | |
670 | 176 |
0 | 177 void dm_eval_free(DMEvalNode *node) |
178 { | |
179 while (node != NULL) | |
180 { | |
181 DMEvalNode *next = node->next; | |
670 | 182 int i; |
0 | 183 |
670 | 184 for (i = 0; i < DM_MAX_ARGS; i++) |
185 { | |
186 dm_eval_free(node->args[i]); | |
187 node->args[i] = NULL; | |
188 } | |
0 | 189 |
670 | 190 dm_eval_free(node->subexpr); |
687
f3d2b19dbbb7
Set node->subexpr to NULL in free, as we are paranoidly cargo-culting a bit.
Matti Hamalainen <ccr@tnsp.org>
parents:
686
diff
changeset
|
191 node->subexpr = NULL; |
0 | 192 dmFree(node); |
193 node = next; | |
194 } | |
195 } | |
196 | |
197 | |
198 void dm_eval_clear_err(DMEvalContext *ev) | |
199 { | |
200 if (ev == NULL) | |
201 return; | |
202 | |
203 dmFree(ev->errStr); | |
204 ev->err = FALSE; | |
205 ev->errStr = NULL; | |
206 } | |
207 | |
208 | |
209 void dm_eval_close(DMEvalContext *ev) | |
210 { | |
211 int i; | |
212 | |
213 if (ev == NULL) | |
214 return; | |
215 | |
216 for (i = 0; i < ev->nids; i++) | |
217 dmFree(ev->ids[i].name); | |
218 | |
219 dmFree(ev->ids); | |
220 dm_eval_clear_err(ev); | |
221 dmFree(ev); | |
222 } | |
223 | |
224 | |
225 static DMEvalNode *dm_eval_pop_node(DMEvalNode **list) | |
226 { | |
227 DMEvalNode *node; | |
228 | |
229 if (*list == NULL) | |
230 return NULL; | |
231 | |
232 node = (*list)->prev; | |
233 | |
234 if (*list != node) | |
235 { | |
236 node->prev->next = NULL; | |
237 (*list)->prev = node->prev; | |
238 } | |
239 else | |
240 *list = NULL; | |
241 | |
242 return node; | |
243 } | |
244 | |
245 | |
679 | 246 static DMEvalNode *dm_eval_peek_node(DMEvalNode **list) |
247 { | |
248 if (*list == NULL) | |
249 return NULL; | |
250 | |
251 return (*list)->prev; | |
252 } | |
253 | |
254 | |
0 | 255 static DMEvalNode *dm_eval_insert_node(DMEvalNode **list, DMEvalNode *node) |
256 { | |
257 if (*list != NULL) | |
258 { | |
259 node->prev = (*list)->prev; | |
260 (*list)->prev->next = node; | |
261 (*list)->prev = node; | |
262 } | |
263 else | |
264 { | |
265 *list = node; | |
266 node->prev = *list; | |
267 } | |
268 | |
269 node->next = NULL; | |
270 return node; | |
271 } | |
272 | |
273 | |
699 | 274 static DMEvalNode *dm_eval_push_node(DMEvalNode **list, const DMEvalNode *src) |
0 | 275 { |
693
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
276 DMEvalNode *tmp, *node = dmCalloc(1, sizeof(DMEvalNode)); |
670 | 277 int i; |
278 | |
0 | 279 if (node == NULL) |
280 return NULL; | |
281 | |
664 | 282 node->op = src->op; |
283 node->val = src->val; | |
284 node->id = src->id; | |
693
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
285 node->ok = src->ok; |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
286 |
696 | 287 if (src->op == OP_SUBEXPR) |
693
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
288 { |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
289 for (tmp = src->subexpr; tmp != NULL; tmp = tmp->next) |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
290 dm_eval_push_node(&(node->subexpr), tmp); |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
291 } |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
292 |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
293 if (src->op == OP_FUNC) |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
294 { |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
295 for (i = 0; i < src->id->nargs; i++) |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
296 { |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
297 for (tmp = src->args[i]; tmp != NULL; tmp = tmp->next) |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
298 dm_eval_push_node(&(node->args[i]), tmp); |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
299 } |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
300 } |
0 | 301 |
302 return dm_eval_insert_node(list, node); | |
303 } | |
304 | |
305 | |
306 static DMEvalNode *dm_eval_add_node(DMEvalNode **list, const int op) | |
307 { | |
308 DMEvalNode *node = dmCalloc(1, sizeof(DMEvalNode)); | |
309 if (node == NULL) | |
310 return NULL; | |
311 | |
312 node->op = op; | |
313 | |
314 return dm_eval_insert_node(list, node); | |
315 } | |
316 | |
317 | |
318 enum | |
319 { | |
320 PARSE_NONE = 0x0000, | |
321 PARSE_START = 0x1000, | |
322 PARSE_END = 0x2000, | |
323 PARSE_ERROR = 0x8000, | |
324 | |
325 PARSE_IDENT = 0x0001, | |
684
dae4db2512c4
Remove PARSE_WS, it's not used anymore.
Matti Hamalainen <ccr@tnsp.org>
parents:
680
diff
changeset
|
326 PARSE_CONST = 0x0002, |
dae4db2512c4
Remove PARSE_WS, it's not used anymore.
Matti Hamalainen <ccr@tnsp.org>
parents:
680
diff
changeset
|
327 PARSE_OPER = 0x0004, // All operators |
dae4db2512c4
Remove PARSE_WS, it's not used anymore.
Matti Hamalainen <ccr@tnsp.org>
parents:
680
diff
changeset
|
328 PARSE_OPER2 = 0x0008, // '-' only |
dae4db2512c4
Remove PARSE_WS, it's not used anymore.
Matti Hamalainen <ccr@tnsp.org>
parents:
680
diff
changeset
|
329 PARSE_SUBEXPR = 0x0010, |
dae4db2512c4
Remove PARSE_WS, it's not used anymore.
Matti Hamalainen <ccr@tnsp.org>
parents:
680
diff
changeset
|
330 PARSE_ARGS = 0x0020, |
670 | 331 |
332 PARSE_NORMAL = PARSE_CONST | PARSE_IDENT | PARSE_SUBEXPR | PARSE_OPER2, | |
0 | 333 }; |
334 | |
335 #define DM_CHECK(x) { if (mode & PARSE_ ## x ) { if (str[0]) strcat(str, " or "); strcat(str, # x ); } } | |
336 | |
337 static char *dm_get_mode(int mode) | |
338 { | |
339 char str[128] = ""; | |
340 | |
341 DM_CHECK(START); | |
342 DM_CHECK(END); | |
343 DM_CHECK(IDENT); | |
344 DM_CHECK(CONST); | |
345 DM_CHECK(OPER); | |
670 | 346 DM_CHECK(OPER2); |
0 | 347 DM_CHECK(SUBEXPR); |
670 | 348 DM_CHECK(ARGS); |
0 | 349 |
350 return dm_strdup(str); | |
351 } | |
352 | |
353 | |
354 static void dm_set_mode(DMEvalContext *ev, const int mode) | |
355 { | |
670 | 356 if (mode != PARSE_ERROR && |
357 mode != PARSE_START && | |
0 | 358 ev->expect != PARSE_NONE && |
359 (mode & ev->expect) == 0) | |
360 { | |
361 char *tmp1 = dm_get_mode(ev->expect), | |
362 *tmp2 = dm_get_mode(mode); | |
363 | |
364 dm_eval_err(ev, "Expected [%s], got %s.\n", tmp1, tmp2); | |
365 dmFree(tmp1); | |
366 dmFree(tmp2); | |
367 } | |
368 | |
369 ev->prev = ev->mode; | |
370 ev->mode = mode; | |
371 } | |
372 | |
373 | |
374 static int dm_eval_parse_expr_do(DMEvalContext *ev, DMEvalNode **list, char **str, int depth) | |
375 { | |
376 char *c = *str; | |
377 char tmpStr[DM_MAX_BUF + 2]; | |
670 | 378 int tmpStrLen = 0, argIndex; |
0 | 379 DMEvalNode *node = NULL, *func = NULL; |
380 BOOL first = FALSE, decimal = FALSE; | |
381 | |
670 | 382 ev->expect = PARSE_NORMAL; |
0 | 383 ev->mode = PARSE_START; |
384 | |
385 while (ev->mode != PARSE_ERROR && ev->mode != PARSE_END) | |
386 switch (ev->mode) | |
387 { | |
388 case PARSE_SUBEXPR: | |
389 { | |
390 char *tmp = c + 1; | |
391 | |
670 | 392 ev->expect = PARSE_NORMAL; |
0 | 393 |
670 | 394 if ((node = dm_eval_add_node(list, OP_SUBEXPR)) == NULL) |
395 dm_set_mode(ev, PARSE_ERROR); | |
396 else | |
397 if (dm_eval_parse_expr_do(ev, &(node->subexpr), &tmp, depth + 1) != 0) | |
0 | 398 { |
670 | 399 dm_eval_err(ev, "Subexpression starting at '%s' contained errors.\n", c); |
400 dm_set_mode(ev, PARSE_ERROR); | |
0 | 401 } |
670 | 402 |
0 | 403 if (ev->mode != PARSE_ERROR) |
404 { | |
405 dm_set_mode(ev, PARSE_START); | |
406 ev->expect = PARSE_OPER | PARSE_END; | |
407 c = tmp; | |
408 } | |
409 } | |
410 break; | |
670 | 411 |
412 case PARSE_ARGS: | |
413 { | |
414 char *tmp = c + 1; | |
415 for (argIndex = 0; argIndex < func->id->nargs; argIndex++) | |
416 { | |
417 if (dm_eval_parse_expr_do(ev, &(func->args[argIndex]), &tmp, depth + 1) != 0) | |
418 { | |
419 dm_eval_err(ev, "Function argument subexpression starting at '%s' contained errors.\n", c); | |
420 dm_set_mode(ev, PARSE_ERROR); | |
421 } | |
422 } | |
423 | |
424 func = NULL; | |
425 | |
426 if (ev->mode != PARSE_ERROR) | |
427 { | |
428 dm_set_mode(ev, PARSE_START); | |
429 ev->expect = PARSE_OPER | PARSE_END; | |
430 c = tmp; | |
431 } | |
432 } | |
433 break; | |
434 | |
0 | 435 case PARSE_START: |
436 // Start | |
437 if (*c == 0) | |
438 dm_set_mode(ev, PARSE_END); | |
439 | |
670 | 440 // Skip whitespace |
0 | 441 else if (isspace(*c)) |
670 | 442 c++; |
0 | 443 |
670 | 444 else if (*c == ')' || *c == ',') |
0 | 445 { |
446 if (depth > 0) | |
447 dm_set_mode(ev, PARSE_END); | |
448 else | |
449 { | |
450 dm_eval_err(ev, "Invalid nesting near '%s' (depth %d).\n", c, depth); | |
451 dm_set_mode(ev, PARSE_ERROR); | |
452 } | |
453 c++; | |
454 } | |
670 | 455 |
0 | 456 else if (*c == '(') |
670 | 457 dm_set_mode(ev, func != NULL ? PARSE_ARGS : PARSE_SUBEXPR); |
458 | |
671
e5e56d16597e
And another fix to parsing.
Matti Hamalainen <ccr@tnsp.org>
parents:
670
diff
changeset
|
459 else if (*c == '-') |
672 | 460 dm_set_mode(ev, (ev->prev == PARSE_START || ev->prev == PARSE_OPER) ? PARSE_OPER2 : PARSE_OPER); |
671
e5e56d16597e
And another fix to parsing.
Matti Hamalainen <ccr@tnsp.org>
parents:
670
diff
changeset
|
461 |
e5e56d16597e
And another fix to parsing.
Matti Hamalainen <ccr@tnsp.org>
parents:
670
diff
changeset
|
462 else if (strchr("+*/<>%&|!^", *c)) |
0 | 463 dm_set_mode(ev, PARSE_OPER); |
464 | |
465 else if (isdigit(*c) || *c == '.') | |
466 dm_set_mode(ev, PARSE_CONST); | |
467 | |
468 else if (isalpha(*c) || *c == '_') | |
469 dm_set_mode(ev, PARSE_IDENT); | |
470 | |
471 else | |
472 { | |
473 dm_eval_err(ev, "Syntax error near '%s' (depth %d).\n", c, depth); | |
474 dm_set_mode(ev, PARSE_ERROR); | |
475 } | |
476 | |
477 first = TRUE; | |
478 break; | |
479 | |
480 case PARSE_CONST: | |
481 if (first) | |
482 { | |
483 first = FALSE; | |
484 decimal = FALSE; | |
485 tmpStrLen = 0; | |
486 | |
487 if (isdigit(*c) || *c == '-' || *c == '+' || *c == '.') | |
488 { | |
489 if (*c == '.') | |
490 decimal = TRUE; | |
491 tmpStr[tmpStrLen++] = *c++; | |
492 } | |
493 else | |
494 { | |
495 dm_eval_err(ev, "Invalid constant expression near '%s'.\n", c); | |
496 dm_set_mode(ev, PARSE_ERROR); | |
497 } | |
498 } | |
499 else | |
500 { | |
501 if (isdigit(*c) || (*c == '.' && !decimal)) | |
502 { | |
503 if (*c == '.') | |
504 decimal = TRUE; | |
505 tmpStr[tmpStrLen++] = *c++; | |
506 } | |
507 else | |
508 { | |
509 tmpStr[tmpStrLen] = 0; | |
510 | |
511 if ((node = dm_eval_add_node(list, OP_CONST)) == NULL) | |
512 { | |
513 dm_set_mode(ev, PARSE_ERROR); | |
514 } | |
697
48321a711bec
Work towards plugging memory leaks.
Matti Hamalainen <ccr@tnsp.org>
parents:
696
diff
changeset
|
515 else |
48321a711bec
Work towards plugging memory leaks.
Matti Hamalainen <ccr@tnsp.org>
parents:
696
diff
changeset
|
516 { |
48321a711bec
Work towards plugging memory leaks.
Matti Hamalainen <ccr@tnsp.org>
parents:
696
diff
changeset
|
517 node->val = atof(tmpStr); |
48321a711bec
Work towards plugging memory leaks.
Matti Hamalainen <ccr@tnsp.org>
parents:
696
diff
changeset
|
518 dm_set_mode(ev, PARSE_START); |
48321a711bec
Work towards plugging memory leaks.
Matti Hamalainen <ccr@tnsp.org>
parents:
696
diff
changeset
|
519 ev->expect = PARSE_OPER | PARSE_END; |
48321a711bec
Work towards plugging memory leaks.
Matti Hamalainen <ccr@tnsp.org>
parents:
696
diff
changeset
|
520 } |
0 | 521 } |
522 } | |
523 break; | |
524 | |
525 case PARSE_OPER: | |
670 | 526 case PARSE_OPER2: |
0 | 527 { |
528 int op = OP_NONE; | |
529 | |
530 switch (*c) | |
531 { | |
532 case '+': op = OP_ADD; c++; break; | |
533 case '-': op = OP_SUB; c++; break; | |
534 case '*': op = OP_MUL; c++; break; | |
535 case '/': op = OP_DIV; c++; break; | |
536 case '%': op = OP_MOD; c++; break; | |
537 case '&': op = OP_AND; c++; break; | |
538 case '|': op = OP_OR; c++; break; | |
539 case '>': | |
540 if (c[1] == '>') | |
541 { | |
542 c += 2; | |
543 op = OP_RSHIFT; | |
544 } | |
545 else | |
546 { | |
547 dm_eval_err(ev, "Syntax error near '%s'.\n", c); | |
548 dm_set_mode(ev, PARSE_ERROR); | |
549 } | |
550 break; | |
551 | |
552 case '<': | |
553 if (c[1] == '<') | |
554 { | |
555 c += 2; | |
556 op = OP_LSHIFT; | |
557 } | |
558 else | |
559 { | |
560 dm_eval_err(ev, "Syntax error near '%s'.\n", c); | |
561 dm_set_mode(ev, PARSE_ERROR); | |
562 } | |
563 break; | |
564 | |
565 default: | |
566 dm_eval_err(ev, "Unknown operator '%c'.\n", *c); | |
567 dm_set_mode(ev, PARSE_ERROR); | |
568 } | |
569 | |
570 if (op != OP_NONE) | |
571 { | |
676 | 572 if (ev->mode == PARSE_OPER2 && op == OP_SUB && |
573 (node = dm_eval_add_node(list, op)) != NULL) | |
574 { | |
575 ev->expect = PARSE_NORMAL; | |
576 dm_set_mode(ev, PARSE_START); | |
577 } | |
670 | 578 else |
676 | 579 if (ev->mode == PARSE_OPER && |
580 (node = dm_eval_add_node(list, op)) != NULL) | |
0 | 581 { |
670 | 582 ev->expect = PARSE_NORMAL | PARSE_OPER2; |
0 | 583 dm_set_mode(ev, PARSE_START); |
584 } | |
585 else | |
586 dm_set_mode(ev, PARSE_ERROR); | |
587 } | |
588 } | |
589 break; | |
590 | |
591 case PARSE_IDENT: | |
592 if (isalnum(*c) || *c == '_') | |
593 { | |
594 if (first) | |
595 { | |
596 tmpStrLen = 0; | |
597 first = FALSE; | |
598 } | |
599 | |
600 if (tmpStrLen < DM_MAX_ID_LEN) | |
601 tmpStr[tmpStrLen++] = *c++; | |
602 else | |
603 { | |
604 tmpStr[tmpStrLen] = 0; | |
605 dm_eval_err(ev, "Identifier too long! ('%s')\n", tmpStr); | |
606 } | |
607 } | |
608 else | |
609 { | |
610 tmpStr[tmpStrLen] = 0; | |
611 DMEvalId *id = dm_eval_find_id(ev, tmpStr); | |
612 if (id != NULL) | |
613 { | |
614 if ((node = dm_eval_add_node(list, id->type == ID_FUNC ? OP_FUNC : OP_VAR)) != NULL) | |
615 { | |
616 node->id = id; | |
617 if (id->type == ID_FUNC) | |
618 { | |
619 func = node; | |
670 | 620 ev->expect = PARSE_ARGS; |
0 | 621 } |
622 else | |
623 ev->expect = PARSE_END | PARSE_OPER; | |
624 | |
625 dm_set_mode(ev, PARSE_START); | |
626 } | |
627 else | |
628 dm_set_mode(ev, PARSE_ERROR); | |
629 } | |
630 else | |
631 { | |
632 dm_eval_err(ev, "No such identifier '%s'.\n", tmpStr); | |
633 dm_set_mode(ev, PARSE_ERROR); | |
634 } | |
635 } | |
636 break; | |
637 } | |
638 | |
639 *str = c; | |
640 | |
641 return (ev->mode == PARSE_ERROR) ? -1 : 0; | |
642 } | |
643 | |
644 | |
645 int dm_eval_parse_expr(DMEvalContext *ev, char *expr, DMEvalNode **result) | |
646 { | |
647 int ret; | |
648 | |
649 if (ev == NULL || result == NULL) | |
650 return -1; | |
651 | |
670 | 652 ev->prev = PARSE_START; |
0 | 653 ret = dm_eval_parse_expr_do(ev, result, &expr, 0); |
654 | |
655 return ret; | |
656 } | |
657 | |
658 | |
659 static const char *dm_oper_names[OP_NOPERS] = | |
660 { | |
661 "NONE", | |
662 "+", | |
663 "-", | |
664 "*", | |
665 "/", | |
666 "%", | |
667 | |
668 "<<", | |
669 ">>", | |
670 | |
671 "&", | |
672 "|", | |
673 "^", | |
674 | |
675 "FUNC", | |
676 "VAR", | |
677 "SUBEXPR", | |
678 "CONST" | |
679 }; | |
680 | |
681 | |
700
6d96d5bf9653
Add output file stream argument to dm_print_optree().
Matti Hamalainen <ccr@tnsp.org>
parents:
699
diff
changeset
|
682 static void dm_print_optree_do(FILE *out, DMEvalContext *ev, DMEvalNode *node, const int level) |
0 | 683 { |
670 | 684 int i; |
0 | 685 while (node != NULL) |
686 { | |
687 switch (node->op) | |
688 { | |
689 case OP_FUNC: | |
700
6d96d5bf9653
Add output file stream argument to dm_print_optree().
Matti Hamalainen <ccr@tnsp.org>
parents:
699
diff
changeset
|
690 fprintf(out, "%s(", node->id != NULL ? node->id->name : "?ERROR"); |
670 | 691 for (i = 0; i < node->id->nargs; i++) |
692 { | |
700
6d96d5bf9653
Add output file stream argument to dm_print_optree().
Matti Hamalainen <ccr@tnsp.org>
parents:
699
diff
changeset
|
693 dm_print_optree_do(out, ev, node->args[i], level + 1); |
670 | 694 if (i < node->id->nargs - 1) |
700
6d96d5bf9653
Add output file stream argument to dm_print_optree().
Matti Hamalainen <ccr@tnsp.org>
parents:
699
diff
changeset
|
695 fprintf(out, ","); |
670 | 696 } |
700
6d96d5bf9653
Add output file stream argument to dm_print_optree().
Matti Hamalainen <ccr@tnsp.org>
parents:
699
diff
changeset
|
697 fprintf(out, ")"); |
0 | 698 break; |
699 | |
700 case OP_VAR: | |
700
6d96d5bf9653
Add output file stream argument to dm_print_optree().
Matti Hamalainen <ccr@tnsp.org>
parents:
699
diff
changeset
|
701 fprintf(out, "%s", node->id != NULL ? node->id->name : "?ERROR"); |
0 | 702 break; |
703 | |
704 case OP_CONST: | |
700
6d96d5bf9653
Add output file stream argument to dm_print_optree().
Matti Hamalainen <ccr@tnsp.org>
parents:
699
diff
changeset
|
705 fprintf(out, "%.1f", node->val); |
0 | 706 break; |
707 | |
708 case OP_SUBEXPR: | |
700
6d96d5bf9653
Add output file stream argument to dm_print_optree().
Matti Hamalainen <ccr@tnsp.org>
parents:
699
diff
changeset
|
709 fprintf(out, "("); |
0 | 710 if (node->subexpr != NULL) |
700
6d96d5bf9653
Add output file stream argument to dm_print_optree().
Matti Hamalainen <ccr@tnsp.org>
parents:
699
diff
changeset
|
711 dm_print_optree_do(out, ev, node->subexpr, level + 1); |
0 | 712 else |
700
6d96d5bf9653
Add output file stream argument to dm_print_optree().
Matti Hamalainen <ccr@tnsp.org>
parents:
699
diff
changeset
|
713 fprintf(out, "?ERROR"); |
6d96d5bf9653
Add output file stream argument to dm_print_optree().
Matti Hamalainen <ccr@tnsp.org>
parents:
699
diff
changeset
|
714 fprintf(out, ")"); |
0 | 715 break; |
716 | |
717 default: | |
718 if (node->op > 0 && node->op < OP_NOPERS) | |
700
6d96d5bf9653
Add output file stream argument to dm_print_optree().
Matti Hamalainen <ccr@tnsp.org>
parents:
699
diff
changeset
|
719 fprintf(out, "%s", dm_oper_names[node->op]); |
0 | 720 else |
700
6d96d5bf9653
Add output file stream argument to dm_print_optree().
Matti Hamalainen <ccr@tnsp.org>
parents:
699
diff
changeset
|
721 fprintf(out, "ERROR!"); |
0 | 722 break; |
723 } | |
724 node = node->next; | |
725 } | |
726 } | |
727 | |
728 | |
700
6d96d5bf9653
Add output file stream argument to dm_print_optree().
Matti Hamalainen <ccr@tnsp.org>
parents:
699
diff
changeset
|
729 void dm_print_optree(FILE *out, DMEvalContext *ev, DMEvalNode *node) |
0 | 730 { |
700
6d96d5bf9653
Add output file stream argument to dm_print_optree().
Matti Hamalainen <ccr@tnsp.org>
parents:
699
diff
changeset
|
731 dm_print_optree_do(out, ev, node, 0); |
6d96d5bf9653
Add output file stream argument to dm_print_optree().
Matti Hamalainen <ccr@tnsp.org>
parents:
699
diff
changeset
|
732 fprintf(out, "\n"); |
0 | 733 } |
734 | |
735 | |
736 /* | |
737 operator precedence: | |
738 HIGHEST | |
739 "()" | |
740 | |
741 "*" | |
742 "/" | |
743 "%" | |
744 | |
745 "+" | |
746 "-" | |
747 | |
748 "<<" | |
749 ">>" | |
750 | |
751 "&" | |
752 "^" | |
753 "|" | |
754 LOWEST | |
755 */ | |
756 | |
699 | 757 static int dm_eval_reorder_pass0(DMEvalContext *ev, const DMEvalNode *node, DMEvalNode **result) |
0 | 758 { |
693
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
759 DMEvalNode *tmp, *sub; |
679 | 760 int i, res; |
0 | 761 |
693
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
762 for (; node != NULL; node = node->next) |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
763 switch (node->op) |
0 | 764 { |
693
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
765 case OP_SUB: |
697
48321a711bec
Work towards plugging memory leaks.
Matti Hamalainen <ccr@tnsp.org>
parents:
696
diff
changeset
|
766 if ((tmp = dm_eval_peek_node(result)) == NULL || tmp->op <= OP_FUNC) |
693
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
767 { |
679 | 768 // Add subexpression node |
697
48321a711bec
Work towards plugging memory leaks.
Matti Hamalainen <ccr@tnsp.org>
parents:
696
diff
changeset
|
769 if ((sub = dm_eval_add_node(result, OP_SUBEXPR)) == NULL) |
679 | 770 return -3; |
771 | |
772 // Add this operator into subexpression | |
773 dm_eval_add_node(&(sub->subexpr), node->op); | |
0 | 774 |
679 | 775 // Next node |
776 node = node->next; | |
777 if (node == NULL) | |
778 return -72; | |
779 | |
693
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
780 dm_eval_push_node(&(sub->subexpr), node); |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
781 } |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
782 else |
697
48321a711bec
Work towards plugging memory leaks.
Matti Hamalainen <ccr@tnsp.org>
parents:
696
diff
changeset
|
783 if (dm_eval_push_node(result, node) == NULL) |
693
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
784 return -32; |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
785 |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
786 break; |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
787 |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
788 case OP_FUNC: |
697
48321a711bec
Work towards plugging memory leaks.
Matti Hamalainen <ccr@tnsp.org>
parents:
696
diff
changeset
|
789 if ((tmp = dm_eval_push_node(result, node)) == NULL) |
693
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
790 return -1; |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
791 |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
792 for (i = 0; i < node->id->nargs; i++) |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
793 { |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
794 if ((res = dm_eval_reorder(ev, node->args[i], &(tmp->args[i]))) != 0) |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
795 return res; |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
796 } |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
797 break; |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
798 |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
799 case OP_SUBEXPR: |
697
48321a711bec
Work towards plugging memory leaks.
Matti Hamalainen <ccr@tnsp.org>
parents:
696
diff
changeset
|
800 if ((tmp = dm_eval_push_node(result, node)) == NULL) |
693
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
801 return -1; |
679 | 802 |
693
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
803 if ((res = dm_eval_reorder(ev, node->subexpr, &(tmp->subexpr))) != 0) |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
804 return res; |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
805 break; |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
806 |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
807 default: |
697
48321a711bec
Work towards plugging memory leaks.
Matti Hamalainen <ccr@tnsp.org>
parents:
696
diff
changeset
|
808 if (dm_eval_push_node(result, node) == NULL) |
693
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
809 return -32; |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
810 break; |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
811 } |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
812 |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
813 return 0; |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
814 } |
679 | 815 |
693
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
816 |
699 | 817 static int dm_eval_reorder_pass1(DMEvalContext *ev, const DMEvalNode *node, DMEvalNode **result) |
693
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
818 { |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
819 DMEvalNode *tmp, *sub; |
679 | 820 |
693
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
821 for (; node != NULL; node = node->next) |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
822 switch (node->op) |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
823 { |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
824 case OP_MUL: |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
825 case OP_DIV: |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
826 case OP_MOD: |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
827 if (node->ok) |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
828 { |
697
48321a711bec
Work towards plugging memory leaks.
Matti Hamalainen <ccr@tnsp.org>
parents:
696
diff
changeset
|
829 if (dm_eval_push_node(result, node) == NULL) |
0 | 830 return -32; |
693
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
831 break; |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
832 } |
679 | 833 |
693
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
834 // Pop previous node, f.e. 5*3 -> 5 |
697
48321a711bec
Work towards plugging memory leaks.
Matti Hamalainen <ccr@tnsp.org>
parents:
696
diff
changeset
|
835 if ((tmp = dm_eval_pop_node(result)) == NULL) |
693
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
836 return -24; |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
837 |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
838 // Add subexpression node |
697
48321a711bec
Work towards plugging memory leaks.
Matti Hamalainen <ccr@tnsp.org>
parents:
696
diff
changeset
|
839 if ((sub = dm_eval_add_node(result, OP_SUBEXPR)) == NULL) |
693
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
840 return -3; |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
841 |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
842 // Add popped node into subexpression |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
843 dm_eval_push_node(&(sub->subexpr), tmp); |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
844 |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
845 // Add this operator into subexpression |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
846 DMEvalNode *foo = dm_eval_add_node(&(sub->subexpr), node->op); |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
847 foo->ok = TRUE; |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
848 |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
849 // Next node |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
850 node = node->next; |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
851 if (node == NULL) |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
852 return -72; |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
853 |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
854 dm_eval_push_node(&(sub->subexpr), node); |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
855 break; |
692 | 856 |
693
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
857 default: |
697
48321a711bec
Work towards plugging memory leaks.
Matti Hamalainen <ccr@tnsp.org>
parents:
696
diff
changeset
|
858 if (dm_eval_push_node(result, node) == NULL) |
693
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
859 return -32; |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
860 break; |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
861 } |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
862 |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
863 return 0; |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
864 } |
692 | 865 |
699 | 866 static int dm_eval_reorder_pass2(DMEvalContext *ev, const DMEvalNode *node, DMEvalNode **result) |
693
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
867 { |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
868 DMEvalNode *tmp, *sub; |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
869 |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
870 for (; node != NULL; node = node->next) |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
871 switch (node->op) |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
872 { |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
873 case OP_SUB: |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
874 case OP_ADD: |
694
b8c8cf55c761
Improve reordering some more, produce less nesting.
Matti Hamalainen <ccr@tnsp.org>
parents:
693
diff
changeset
|
875 if (node->ok) |
b8c8cf55c761
Improve reordering some more, produce less nesting.
Matti Hamalainen <ccr@tnsp.org>
parents:
693
diff
changeset
|
876 { |
697
48321a711bec
Work towards plugging memory leaks.
Matti Hamalainen <ccr@tnsp.org>
parents:
696
diff
changeset
|
877 if (dm_eval_push_node(result, node) == NULL) |
694
b8c8cf55c761
Improve reordering some more, produce less nesting.
Matti Hamalainen <ccr@tnsp.org>
parents:
693
diff
changeset
|
878 return -32; |
b8c8cf55c761
Improve reordering some more, produce less nesting.
Matti Hamalainen <ccr@tnsp.org>
parents:
693
diff
changeset
|
879 break; |
b8c8cf55c761
Improve reordering some more, produce less nesting.
Matti Hamalainen <ccr@tnsp.org>
parents:
693
diff
changeset
|
880 } |
b8c8cf55c761
Improve reordering some more, produce less nesting.
Matti Hamalainen <ccr@tnsp.org>
parents:
693
diff
changeset
|
881 |
693
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
882 // Pop previous node, f.e. 5*3 -> 5 |
697
48321a711bec
Work towards plugging memory leaks.
Matti Hamalainen <ccr@tnsp.org>
parents:
696
diff
changeset
|
883 if ((tmp = dm_eval_pop_node(result)) == NULL) |
693
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
884 return -24; |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
885 |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
886 // Add subexpression node |
697
48321a711bec
Work towards plugging memory leaks.
Matti Hamalainen <ccr@tnsp.org>
parents:
696
diff
changeset
|
887 if ((sub = dm_eval_add_node(result, OP_SUBEXPR)) == NULL) |
693
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
888 return -3; |
692 | 889 |
693
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
890 // Add popped node into subexpression |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
891 dm_eval_push_node(&(sub->subexpr), tmp); |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
892 |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
893 // Add this operator into subexpression |
694
b8c8cf55c761
Improve reordering some more, produce less nesting.
Matti Hamalainen <ccr@tnsp.org>
parents:
693
diff
changeset
|
894 DMEvalNode *foo = dm_eval_add_node(&(sub->subexpr), node->op); |
b8c8cf55c761
Improve reordering some more, produce less nesting.
Matti Hamalainen <ccr@tnsp.org>
parents:
693
diff
changeset
|
895 foo->ok = TRUE; |
693
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
896 |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
897 // Next node |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
898 node = node->next; |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
899 if (node == NULL) |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
900 return -72; |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
901 |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
902 dm_eval_push_node(&(sub->subexpr), node); |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
903 break; |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
904 |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
905 default: |
697
48321a711bec
Work towards plugging memory leaks.
Matti Hamalainen <ccr@tnsp.org>
parents:
696
diff
changeset
|
906 if (dm_eval_push_node(result, node) == NULL) |
693
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
907 return -32; |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
908 break; |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
909 } |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
910 |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
911 return 0; |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
912 } |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
913 |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
914 |
699 | 915 static int dm_eval_reorder_pass3(DMEvalContext *ev, const DMEvalNode *node, DMEvalNode **result) |
693
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
916 { |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
917 DMEvalNode *tmp, *sub; |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
918 int res; |
692 | 919 |
693
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
920 while (node != NULL) |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
921 switch (node->op) |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
922 { |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
923 case OP_LSHIFT: |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
924 case OP_RSHIFT: |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
925 // Bitshift operator precedence is .. different |
697
48321a711bec
Work towards plugging memory leaks.
Matti Hamalainen <ccr@tnsp.org>
parents:
696
diff
changeset
|
926 if (dm_eval_push_node(result, node) == NULL) |
693
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
927 return -32; |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
928 |
697
48321a711bec
Work towards plugging memory leaks.
Matti Hamalainen <ccr@tnsp.org>
parents:
696
diff
changeset
|
929 if ((sub = dm_eval_add_node(result, OP_SUBEXPR)) == NULL) |
693
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
930 return -3; |
692 | 931 |
697
48321a711bec
Work towards plugging memory leaks.
Matti Hamalainen <ccr@tnsp.org>
parents:
696
diff
changeset
|
932 if (node->next == NULL) |
693
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
933 return -14; |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
934 |
697
48321a711bec
Work towards plugging memory leaks.
Matti Hamalainen <ccr@tnsp.org>
parents:
696
diff
changeset
|
935 if ((res = dm_eval_reorder_pass3(ev, node->next, &(sub->subexpr))) != 0) |
693
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
936 return res; |
0 | 937 |
693
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
938 node = NULL; |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
939 break; |
692 | 940 |
693
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
941 default: |
697
48321a711bec
Work towards plugging memory leaks.
Matti Hamalainen <ccr@tnsp.org>
parents:
696
diff
changeset
|
942 if (dm_eval_push_node(result, node) == NULL) |
693
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
943 return -32; |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
944 |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
945 node = node->next; |
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
946 break; |
0 | 947 } |
948 | |
949 return 0; | |
950 } | |
951 | |
952 | |
680 | 953 int dm_eval_reorder(DMEvalContext *ev, DMEvalNode *node, DMEvalNode **result) |
954 { | |
693
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
955 DMEvalNode *tmp1 = NULL, *tmp2 = NULL, *tmp3 = NULL; |
680 | 956 int res; |
957 | |
697
48321a711bec
Work towards plugging memory leaks.
Matti Hamalainen <ccr@tnsp.org>
parents:
696
diff
changeset
|
958 res = dm_eval_reorder_pass0(ev, node, &tmp1); |
48321a711bec
Work towards plugging memory leaks.
Matti Hamalainen <ccr@tnsp.org>
parents:
696
diff
changeset
|
959 |
48321a711bec
Work towards plugging memory leaks.
Matti Hamalainen <ccr@tnsp.org>
parents:
696
diff
changeset
|
960 if (res != 0) |
48321a711bec
Work towards plugging memory leaks.
Matti Hamalainen <ccr@tnsp.org>
parents:
696
diff
changeset
|
961 { |
48321a711bec
Work towards plugging memory leaks.
Matti Hamalainen <ccr@tnsp.org>
parents:
696
diff
changeset
|
962 dm_eval_free(tmp1); |
680 | 963 return res; |
697
48321a711bec
Work towards plugging memory leaks.
Matti Hamalainen <ccr@tnsp.org>
parents:
696
diff
changeset
|
964 } |
680 | 965 |
697
48321a711bec
Work towards plugging memory leaks.
Matti Hamalainen <ccr@tnsp.org>
parents:
696
diff
changeset
|
966 res = dm_eval_reorder_pass1(ev, tmp1, &tmp2); |
48321a711bec
Work towards plugging memory leaks.
Matti Hamalainen <ccr@tnsp.org>
parents:
696
diff
changeset
|
967 dm_eval_free(tmp1); |
48321a711bec
Work towards plugging memory leaks.
Matti Hamalainen <ccr@tnsp.org>
parents:
696
diff
changeset
|
968 |
48321a711bec
Work towards plugging memory leaks.
Matti Hamalainen <ccr@tnsp.org>
parents:
696
diff
changeset
|
969 if (res != 0) |
48321a711bec
Work towards plugging memory leaks.
Matti Hamalainen <ccr@tnsp.org>
parents:
696
diff
changeset
|
970 { |
48321a711bec
Work towards plugging memory leaks.
Matti Hamalainen <ccr@tnsp.org>
parents:
696
diff
changeset
|
971 dm_eval_free(tmp2); |
692 | 972 return res; |
697
48321a711bec
Work towards plugging memory leaks.
Matti Hamalainen <ccr@tnsp.org>
parents:
696
diff
changeset
|
973 } |
692 | 974 |
697
48321a711bec
Work towards plugging memory leaks.
Matti Hamalainen <ccr@tnsp.org>
parents:
696
diff
changeset
|
975 res = dm_eval_reorder_pass2(ev, tmp2, &tmp3); |
48321a711bec
Work towards plugging memory leaks.
Matti Hamalainen <ccr@tnsp.org>
parents:
696
diff
changeset
|
976 dm_eval_free(tmp2); |
48321a711bec
Work towards plugging memory leaks.
Matti Hamalainen <ccr@tnsp.org>
parents:
696
diff
changeset
|
977 if (res != 0) |
48321a711bec
Work towards plugging memory leaks.
Matti Hamalainen <ccr@tnsp.org>
parents:
696
diff
changeset
|
978 { |
48321a711bec
Work towards plugging memory leaks.
Matti Hamalainen <ccr@tnsp.org>
parents:
696
diff
changeset
|
979 dm_eval_free(tmp3); |
693
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
980 return res; |
697
48321a711bec
Work towards plugging memory leaks.
Matti Hamalainen <ccr@tnsp.org>
parents:
696
diff
changeset
|
981 } |
693
837ad9dcc348
More work on evaluator reordering pass.
Matti Hamalainen <ccr@tnsp.org>
parents:
692
diff
changeset
|
982 |
697
48321a711bec
Work towards plugging memory leaks.
Matti Hamalainen <ccr@tnsp.org>
parents:
696
diff
changeset
|
983 res = dm_eval_reorder_pass3(ev, tmp3, result); |
48321a711bec
Work towards plugging memory leaks.
Matti Hamalainen <ccr@tnsp.org>
parents:
696
diff
changeset
|
984 dm_eval_free(tmp3); |
48321a711bec
Work towards plugging memory leaks.
Matti Hamalainen <ccr@tnsp.org>
parents:
696
diff
changeset
|
985 |
48321a711bec
Work towards plugging memory leaks.
Matti Hamalainen <ccr@tnsp.org>
parents:
696
diff
changeset
|
986 return res; |
680 | 987 } |
988 | |
989 | |
699 | 990 static int dm_eval_get(DMEvalContext *ev, const DMEvalNode *node, DMValue *result) |
0 | 991 { |
992 if (node == NULL) | |
993 return -32; | |
994 | |
995 switch (node->op) | |
996 { | |
997 case OP_VAR: | |
670 | 998 if (node->id->type == ID_VAR) |
999 *result = *(node->id->var); | |
1000 else | |
1001 *result = node->id->cvalue; | |
0 | 1002 break; |
1003 | |
1004 case OP_CONST: | |
1005 *result = node->val; | |
1006 break; | |
1007 | |
1008 case OP_SUBEXPR: | |
678 | 1009 return dm_eval_exec(ev, node->subexpr, result); |
0 | 1010 |
1011 case OP_FUNC: | |
670 | 1012 { |
678 | 1013 DMValue tmp[DM_MAX_ARGS]; |
1014 int i; | |
1015 for (i = 0; i < node->id->nargs; i++) | |
1016 { | |
1017 if (dm_eval_exec(ev, node->args[i], &tmp[i]) != 0) | |
1018 return -1; | |
1019 } | |
1020 | |
1021 *result = node->id->func(tmp); | |
670 | 1022 } |
0 | 1023 break; |
1024 | |
1025 default: | |
1026 return -16; | |
1027 } | |
1028 | |
1029 return 0; | |
1030 } | |
1031 | |
1032 | |
1033 int dm_eval_exec(DMEvalContext *ev, DMEvalNode *tree, DMValue *presult) | |
1034 { | |
677
4b7cccaa62c0
Set result variables to zero.
Matti Hamalainen <ccr@tnsp.org>
parents:
676
diff
changeset
|
1035 DMValue result = 0; |
0 | 1036 DMEvalNode *node = tree; |
1037 | |
1038 while (node != NULL) | |
1039 { | |
677
4b7cccaa62c0
Set result variables to zero.
Matti Hamalainen <ccr@tnsp.org>
parents:
676
diff
changeset
|
1040 DMValue tmp = 0; |
0 | 1041 |
1042 switch (node->op) | |
1043 { | |
1044 case OP_LSHIFT: | |
1045 case OP_RSHIFT: | |
1046 | |
1047 case OP_AND: | |
1048 case OP_XOR: | |
1049 case OP_OR: | |
1050 | |
1051 case OP_MUL: | |
1052 case OP_DIV: | |
1053 case OP_MOD: | |
1054 if (dm_eval_get(ev, node->next, &tmp) != 0) | |
1055 return -6; | |
1056 | |
1057 switch (node->op) | |
1058 { | |
1059 case OP_DIV: | |
1060 if (tmp == 0) | |
1061 { | |
1062 dm_eval_err(ev, "Division by zero.\n"); | |
1063 return -1; | |
1064 } | |
1065 result /= tmp; | |
1066 break; | |
1067 | |
1068 case OP_MUL: result *= tmp; break; | |
1069 | |
1070 case OP_MOD: | |
1071 if (tmp == 0) | |
1072 { | |
1073 dm_eval_err(ev, "Division by zero.\n"); | |
1074 return -1; | |
1075 } | |
1076 result = DMCONVTYPE result % DMCONVTYPE tmp; | |
1077 break; | |
1078 | |
694
b8c8cf55c761
Improve reordering some more, produce less nesting.
Matti Hamalainen <ccr@tnsp.org>
parents:
693
diff
changeset
|
1079 case OP_LSHIFT: |
b8c8cf55c761
Improve reordering some more, produce less nesting.
Matti Hamalainen <ccr@tnsp.org>
parents:
693
diff
changeset
|
1080 if (tmp > 31) |
b8c8cf55c761
Improve reordering some more, produce less nesting.
Matti Hamalainen <ccr@tnsp.org>
parents:
693
diff
changeset
|
1081 dm_eval_err(ev, "Left shift count >= width of type"); |
b8c8cf55c761
Improve reordering some more, produce less nesting.
Matti Hamalainen <ccr@tnsp.org>
parents:
693
diff
changeset
|
1082 result = DMCONVTYPE result << DMCONVTYPE tmp; break; |
b8c8cf55c761
Improve reordering some more, produce less nesting.
Matti Hamalainen <ccr@tnsp.org>
parents:
693
diff
changeset
|
1083 |
b8c8cf55c761
Improve reordering some more, produce less nesting.
Matti Hamalainen <ccr@tnsp.org>
parents:
693
diff
changeset
|
1084 case OP_RSHIFT: |
b8c8cf55c761
Improve reordering some more, produce less nesting.
Matti Hamalainen <ccr@tnsp.org>
parents:
693
diff
changeset
|
1085 if (tmp > 31) |
b8c8cf55c761
Improve reordering some more, produce less nesting.
Matti Hamalainen <ccr@tnsp.org>
parents:
693
diff
changeset
|
1086 dm_eval_err(ev, "Right shift count >= width of type"); |
b8c8cf55c761
Improve reordering some more, produce less nesting.
Matti Hamalainen <ccr@tnsp.org>
parents:
693
diff
changeset
|
1087 result = DMCONVTYPE result >> DMCONVTYPE tmp; break; |
0 | 1088 |
1089 case OP_AND: result = DMCONVTYPE result & DMCONVTYPE tmp; break; | |
1090 case OP_OR: result = DMCONVTYPE result | DMCONVTYPE tmp; break; | |
1091 case OP_XOR: result = DMCONVTYPE result ^ DMCONVTYPE tmp; break; | |
1092 } | |
1093 | |
1094 node = node->next; | |
1095 break; | |
1096 | |
1097 case OP_ADD: | |
1098 case OP_SUB: | |
1099 if (dm_eval_get(ev, node->next, &tmp) != 0) | |
1100 return -6; | |
1101 | |
1102 switch (node->op) | |
1103 { | |
1104 case OP_ADD: result += tmp; break; | |
1105 case OP_SUB: result -= tmp; break; | |
1106 } | |
1107 | |
1108 node = node->next; | |
1109 break; | |
1110 | |
1111 default: | |
1112 if (dm_eval_get(ev, node, &result) != 0) | |
1113 { | |
1114 dm_eval_err(ev, "Invalid opcode %d in node %p.\n", node->op, node); | |
1115 return -4; | |
1116 } | |
1117 } | |
1118 node = node->next; | |
1119 } | |
1120 | |
1121 *presult = result; | |
1122 return 0; | |
1123 } |