comparison lwlib/lw_expr.c @ 337:04c80c51b16a

Checkpoint development
author lost
date Fri, 12 Mar 2010 06:01:38 +0000
parents 401587ab6a09
children 7b4123dce741
comparison
equal deleted inserted replaced
336:401587ab6a09 337:04c80c51b16a
29 #include "lw_alloc.h" 29 #include "lw_alloc.h"
30 #include "lw_expr.h" 30 #include "lw_expr.h"
31 #include "lw_error.h" 31 #include "lw_error.h"
32 #include "lw_string.h" 32 #include "lw_string.h"
33 33
34 static lw_expr_t (*evaluate_special)(int t, void *ptr) = NULL;
35 static lw_expr_t (*evaluate_var)(char *var) = NULL;
36
37 void lw_expr_set_special_handler(lw_expr_t (*fn)(int t, void *ptr))
38 {
39 evaluate_special = fn;
40 }
41
42 void lw_expr_set_var_handler(lw_expr_t (*fn)(char *var))
43 {
44 evaluate_var = fn;
45 }
46
34 lw_expr_t lw_expr_create(void) 47 lw_expr_t lw_expr_create(void)
35 { 48 {
36 lw_expr_t r; 49 lw_expr_t r;
37 50
38 r = lw_alloc(sizeof(struct lw_expr_priv)); 51 r = lw_alloc(sizeof(struct lw_expr_priv));
39 r -> refcount = 1;
40 r -> operands = NULL; 52 r -> operands = NULL;
41 53
42 return r; 54 return r;
43 } 55 }
44 56
45 /* useful for constant expression construction */ 57 void lw_expr_destroy(lw_expr_t E)
46 /* lw_expr_deref(lw_expr_create(...)) */ 58 {
47 /* use of this function on an expression that is not already referenced by the caller */ 59 struct lw_expr_opers *o;
48 lw_expr_t lw_expr_deref(lw_expr_t r) 60 for (o = E -> operands; o; o = o -> next)
49 { 61 lw_expr_destroy(o -> p);
50 r -> refcount--; 62 if (E -> type == lw_expr_type_var)
63 lw_free(E -> value2);
64 lw_free(E);
65 }
66
67 /* actually duplicates the entire expression */
68 void lw_expr_add_operand(lw_expr_t E, lw_expr_t O);
69 lw_expr_t lw_expr_copy(lw_expr_t E)
70 {
71 lw_expr_t r, t;
72 struct lw_expr_opers *o;
73
74 r = lw_alloc(sizeof(struct lw_expr_priv));
75 *r = *E;
76 r -> operands = NULL;
77
78 if (E -> type == lw_expr_type_var)
79 r -> value2 = lw_strdup(E -> value2);
80 for (o = E -> operands; o; o = o -> next)
81 {
82 lw_expr_add_operand(r, lw_expr_copy(o -> p));
83 }
84
51 return r; 85 return r;
52 }
53
54 void lw_expr_destroy(lw_expr_t E)
55 {
56 E -> refcount--;
57 if (E -> refcount <= 0)
58 {
59 struct lw_expr_opers *o;
60 for (o = E -> operands; o; o = o -> next)
61 lw_expr_destroy(o -> p);
62 if (E -> type == lw_expr_type_var)
63 lw_free(E -> value2);
64 lw_free(E);
65 }
66 }
67
68 lw_expr_t lw_expr_copy(lw_expr_t E)
69 {
70 E -> refcount++;
71 return E;
72 } 86 }
73 87
74 void lw_expr_add_operand(lw_expr_t E, lw_expr_t O) 88 void lw_expr_add_operand(lw_expr_t E, lw_expr_t O)
75 { 89 {
76 struct lw_expr_opers *o, *t; 90 struct lw_expr_opers *o, *t;
85 t -> next = o; 99 t -> next = o;
86 else 100 else
87 E -> operands = o; 101 E -> operands = o;
88 } 102 }
89 103
90 /* actually duplicates the entire expression */
91 lw_expr_t lw_expr_deepcopy(lw_expr_t E)
92 {
93 lw_expr_t r, t;
94 struct lw_expr_opers *o;
95
96 r = lw_alloc(sizeof(struct lw_expr_priv));
97 *r = *E;
98 r -> refcount = 1;
99 r -> operands = NULL;
100
101 if (E -> type == lw_expr_type_var)
102 r -> value2 = lw_strdup(E -> value2);
103 for (o = E -> operands; o; o = o -> next)
104 {
105 lw_expr_add_operand(r, lw_expr_deref(lw_expr_deepcopy(o -> p)));
106 }
107
108 return r;
109 }
110
111 lw_expr_t lw_expr_build_aux(int exprtype, va_list args) 104 lw_expr_t lw_expr_build_aux(int exprtype, va_list args)
112 { 105 {
113 lw_expr_t r; 106 lw_expr_t r;
114 int t; 107 int t;
115 void *p; 108 void *p;
134 127
135 case lw_expr_type_special: 128 case lw_expr_type_special:
136 t = va_arg(args, int); 129 t = va_arg(args, int);
137 p = va_arg(args, char *); 130 p = va_arg(args, char *);
138 r -> type = lw_expr_type_special; 131 r -> type = lw_expr_type_special;
132 r -> value = t;
139 r -> value2 = p; 133 r -> value2 = p;
140 break; 134 break;
141 135
142 case lw_expr_type_oper: 136 case lw_expr_type_oper:
143 t = va_arg(args, int); 137 t = va_arg(args, int);
169 r = lw_expr_build_aux(exprtype, args); 163 r = lw_expr_build_aux(exprtype, args);
170 va_end(args); 164 va_end(args);
171 return r; 165 return r;
172 } 166 }
173 167
174 lw_expr_t lw_expr_build_noref(int exprtype, ...)
175 {
176 va_list args;
177 lw_expr_t r;
178
179 va_start(args, exprtype);
180 r = lw_expr_build_aux(exprtype, args);
181 r -> refcount--;
182 va_end(args);
183 return r;
184 }
185
186 void lw_expr_print(lw_expr_t E) 168 void lw_expr_print(lw_expr_t E)
187 { 169 {
188 struct lw_expr_opers *o; 170 struct lw_expr_opers *o;
189 int c = 0; 171 int c = 0;
190 172
373 355
374 void lw_expr_simplify(lw_expr_t E) 356 void lw_expr_simplify(lw_expr_t E)
375 { 357 {
376 struct lw_expr_opers *o; 358 struct lw_expr_opers *o;
377 359
378 // sort "constants" to the start of each operand list for + and * 360 again:
379 lw_expr_simplify_sortconstfirst(E); 361 // try to resolve non-constant terms to constants here
380 362 if (E -> type == lw_expr_type_special && evaluate_special)
363 {
364 lw_expr_t te;
365
366 te = evaluate_special(E -> value, E -> value2);
367 if (te)
368 {
369 for (o = E -> operands; o; o = o -> next)
370 lw_expr_destroy(o -> p);
371 if (E -> type == lw_expr_type_var)
372 lw_free(E -> value2);
373 *E = *te;
374 E -> operands = NULL;
375
376 if (te -> type == lw_expr_type_var)
377 E -> value2 = lw_strdup(te -> value2);
378 for (o = te -> operands; o; o = o -> next)
379 {
380 lw_expr_add_operand(E, lw_expr_copy(o -> p));
381 }
382 lw_expr_destroy(te);
383 goto again;
384 }
385 return;
386 }
387
388 if (E -> type == lw_expr_type_var && evaluate_var)
389 {
390 lw_expr_t te;
391
392 te = evaluate_var(E -> value2);
393 if (te)
394 {
395 for (o = E -> operands; o; o = o -> next)
396 lw_expr_destroy(o -> p);
397 if (E -> type == lw_expr_type_var)
398 lw_free(E -> value2);
399 *E = *te;
400 E -> operands = NULL;
401
402 if (te -> type == lw_expr_type_var)
403 E -> value2 = lw_strdup(te -> value2);
404 for (o = te -> operands; o; o = o -> next)
405 {
406 lw_expr_add_operand(E, lw_expr_copy(o -> p));
407 }
408 lw_expr_destroy(te);
409 goto again;
410 }
411 return;
412 }
413
381 // non-operators have no simplification to do! 414 // non-operators have no simplification to do!
382 if (E -> type != lw_expr_type_oper) 415 if (E -> type != lw_expr_type_oper)
383 return; 416 return;
417
418 // sort "constants" to the start of each operand list for + and *
419 lw_expr_simplify_sortconstfirst(E);
420
421 // simplify operands
422 for (o = E -> operands; o; o = o -> next)
423 lw_expr_simplify(o -> p);
424
425 for (o = E -> operands; o; o = o -> next)
426 {
427 if (o -> p -> type != lw_expr_type_int)
428 break;
429 }
430
431 if (!o)
432 {
433 // we can do the operation here!
434 int tr = -42424242;
435
436 switch (E -> value)
437 {
438 case lw_expr_oper_neg:
439 tr = -(E -> operands -> p -> value);
440 break;
441
442 case lw_expr_oper_com:
443 tr = ~(E -> operands -> p -> value);
444 break;
445
446 case lw_expr_oper_plus:
447 tr = E -> operands -> p -> value;
448 for (o = E -> operands -> next; o; o = o -> next)
449 tr += o -> p -> value;
450 break;
451
452 case lw_expr_oper_minus:
453 tr = E -> operands -> p -> value;
454 for (o = E -> operands -> next; o; o = o -> next)
455 tr -= o -> p -> value;
456 break;
457
458 case lw_expr_oper_times:
459 tr = E -> operands -> p -> value;
460 for (o = E -> operands -> next; o; o = o -> next)
461 tr *= o -> p -> value;
462 break;
463
464 case lw_expr_oper_divide:
465 tr = E -> operands -> p -> value / E -> operands -> next -> p -> value;
466 break;
467
468 case lw_expr_oper_mod:
469 tr = E -> operands -> p -> value % E -> operands -> next -> p -> value;
470 break;
471
472 case lw_expr_oper_intdiv:
473 tr = E -> operands -> p -> value / E -> operands -> next -> p -> value;
474 break;
475
476 case lw_expr_oper_bwand:
477 tr = E -> operands -> p -> value & E -> operands -> next -> p -> value;
478 break;
479
480 case lw_expr_oper_bwor:
481 tr = E -> operands -> p -> value | E -> operands -> next -> p -> value;
482 break;
483
484 case lw_expr_oper_bwxor:
485 tr = E -> operands -> p -> value ^ E -> operands -> next -> p -> value;
486 break;
487
488 case lw_expr_oper_and:
489 tr = E -> operands -> p -> value && E -> operands -> next -> p -> value;
490 break;
491
492 case lw_expr_oper_or:
493 tr = E -> operands -> p -> value || E -> operands -> next -> p -> value;
494 break;
495
496 }
497
498 while (E -> operands)
499 {
500 o = E -> operands;
501 E -> operands = o -> next;
502 lw_expr_destroy(o -> p);
503 lw_free(o);
504 }
505 E -> type = lw_expr_type_int;
506 E -> value = tr;
507 return;
508 }
384 509
385 if (E -> value == lw_expr_oper_times) 510 if (E -> value == lw_expr_oper_times)
386 { 511 {
387 for (o = E -> operands; o; o = o -> next) 512 for (o = E -> operands; o; o = o -> next)
388 { 513 {
436 } 561 }
437 } 562 }
438 } 563 }
439 564
440 565
441 for (o = E -> operands; o; o = o -> next)
442 lw_expr_simplify(o -> p);
443
444 if (E -> value == lw_expr_oper_plus) 566 if (E -> value == lw_expr_oper_plus)
445 { 567 {
446 int c = 0, t = 0; 568 int c = 0, t = 0;
447 for (o = E -> operands; o; o = o -> next) 569 for (o = E -> operands; o; o = o -> next)
448 { 570 {
459 while (E -> operands) 581 while (E -> operands)
460 { 582 {
461 o = E -> operands; 583 o = E -> operands;
462 if (o -> p -> type != lw_expr_type_int || o -> p -> value != 0) 584 if (o -> p -> type != lw_expr_type_int || o -> p -> value != 0)
463 { 585 {
464 r = lw_expr_deepcopy(o -> p); 586 r = lw_expr_copy(o -> p);
465 } 587 }
466 E -> operands = o -> next; 588 E -> operands = o -> next;
467 lw_expr_destroy(o -> p); 589 lw_expr_destroy(o -> p);
468 lw_free(o); 590 lw_free(o);
469 } 591 }