Mercurial > hg-old > index.cgi
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 } |