Mercurial > hg-old > index.cgi
comparison lwlib/lw_expr.c @ 335:9f58e3bca6e3
checkpoint
author | lost |
---|---|
date | Thu, 04 Mar 2010 05:13:22 +0000 |
parents | f2173d18c73f |
children | 401587ab6a09 |
comparison
equal
deleted
inserted
replaced
334:f2173d18c73f | 335:9f58e3bca6e3 |
---|---|
94 struct lw_expr_opers *o; | 94 struct lw_expr_opers *o; |
95 | 95 |
96 r = lw_alloc(sizeof(struct lw_expr_priv)); | 96 r = lw_alloc(sizeof(struct lw_expr_priv)); |
97 *r = *E; | 97 *r = *E; |
98 r -> refcount = 1; | 98 r -> refcount = 1; |
99 | 99 r -> operands = NULL; |
100 | |
100 if (E -> type == lw_expr_type_var) | 101 if (E -> type == lw_expr_type_var) |
101 r -> value2 = lw_strdup(E -> value2); | 102 r -> value2 = lw_strdup(E -> value2); |
102 | 103 for (o = E -> operands; o; o = o -> next) |
103 for (o = r -> operands; o; o = o -> next) | |
104 { | 104 { |
105 lw_expr_add_operand(r, lw_expr_deref(lw_expr_deepcopy(o -> p))); | 105 lw_expr_add_operand(r, lw_expr_deref(lw_expr_deepcopy(o -> p))); |
106 } | 106 } |
107 | 107 |
108 return r; | 108 return r; |
109 } | 109 } |
110 | 110 |
111 lw_expr_t lw_expr_build(int exprtype, ...) | 111 lw_expr_t lw_expr_build_aux(int exprtype, va_list args) |
112 { | 112 { |
113 va_list args; | |
114 lw_expr_t r; | 113 lw_expr_t r; |
115 int t; | 114 int t; |
116 void *p; | 115 void *p; |
117 | 116 |
118 lw_expr_t te1, te2; | 117 lw_expr_t te1, te2; |
119 | 118 |
120 r = lw_expr_create(); | 119 r = lw_expr_create(); |
121 va_start(args, exprtype); | |
122 | 120 |
123 switch (exprtype) | 121 switch (exprtype) |
124 { | 122 { |
125 case lw_expr_type_int: | 123 case lw_expr_type_int: |
126 t = va_arg(args, int); | 124 t = va_arg(args, int); |
157 | 155 |
158 default: | 156 default: |
159 lw_error("Invalid expression type specified to lw_expr_build"); | 157 lw_error("Invalid expression type specified to lw_expr_build"); |
160 } | 158 } |
161 | 159 |
160 return r; | |
161 } | |
162 | |
163 lw_expr_t lw_expr_build(int exprtype, ...) | |
164 { | |
165 va_list args; | |
166 lw_expr_t r; | |
167 | |
168 va_start(args, exprtype); | |
169 r = lw_expr_build_aux(exprtype, args); | |
162 va_end(args); | 170 va_end(args); |
163 return r; | 171 return r; |
164 } | 172 } |
165 | 173 |
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 | |
166 void lw_expr_print(lw_expr_t E) | 186 void lw_expr_print(lw_expr_t E) |
167 { | 187 { |
168 struct lw_expr_opers *o; | 188 struct lw_expr_opers *o; |
169 | 189 int c = 0; |
190 | |
170 for (o = E -> operands; o; o = o -> next) | 191 for (o = E -> operands; o; o = o -> next) |
171 { | 192 { |
193 c++; | |
172 lw_expr_print(o -> p); | 194 lw_expr_print(o -> p); |
173 } | 195 } |
174 | 196 |
175 switch (E -> type) | 197 switch (E -> type) |
176 { | 198 { |
177 case lw_expr_type_int: | 199 case lw_expr_type_int: |
178 printf("%d ", E -> value); | 200 printf("%d ", E -> value); |
179 break; | 201 break; |
202 | |
203 case lw_expr_type_var: | |
204 printf("V(%s) ", (char *)(E -> value2)); | |
205 break; | |
206 | |
207 case lw_expr_type_special: | |
208 printf("S(%d,%p) ", E -> value, E -> value2); | |
209 break; | |
210 | |
180 case lw_expr_type_oper: | 211 case lw_expr_type_oper: |
212 printf("[%d]", c); | |
181 switch (E -> value) | 213 switch (E -> value) |
182 { | 214 { |
183 case lw_expr_oper_plus: | 215 case lw_expr_oper_plus: |
184 printf("+ "); | 216 printf("+ "); |
185 break; | 217 break; |
289 { | 321 { |
290 if (E -> type == lw_expr_type_oper && E -> value == oper) | 322 if (E -> type == lw_expr_type_oper && E -> value == oper) |
291 return 1; | 323 return 1; |
292 return 0; | 324 return 0; |
293 } | 325 } |
326 | |
327 | |
328 void lw_expr_simplify_sortconstfirst(lw_expr_t E) | |
329 { | |
330 struct lw_expr_opers *o; | |
331 | |
332 for (o = E -> operands; o; o = o -> next) | |
333 lw_expr_simplify_sortconstfirst(o -> p); | |
334 | |
335 for (o = E -> operands; o; o = o -> next) | |
336 { | |
337 if (o -> p -> type == lw_expr_type_int && o != E -> operands) | |
338 { | |
339 struct lw_expr_opers *o2; | |
340 for (o2 = E -> operands; o2 -> next != o; o2 = o2 -> next) | |
341 /* do nothing */ ; | |
342 o2 -> next = o -> next; | |
343 o -> next = E -> operands; | |
344 E -> operands = o; | |
345 o = o2; | |
346 } | |
347 } | |
348 } | |
349 | |
350 // return 1 if the operand lists match, 0 if not | |
351 // may re-order the argument lists | |
352 int lw_expr_simplify_compareoperandlist(struct lw_expr_opers **ol1, struct lw_expr_opers **ol2) | |
353 { | |
354 struct lw_expr_opers *o1, *o2; | |
355 | |
356 lw_expr_sortoperandlist(ol1); | |
357 lw_expr_sortoperandlist(ol2); | |
358 | |
359 for (o1 = *ol1, o2 = *ol2; o1 && o2; o1 = o1 -> next, o2 = o2 -> next) | |
360 { | |
361 if (!lw_expr_compare(o1 -> p, o2 -> p)) | |
362 return 0; | |
363 } | |
364 if (o1 || o2) | |
365 return 0; | |
366 return 1; | |
367 } | |
368 | |
369 void lw_expr_simplify(lw_expr_t E) | |
370 { | |
371 struct lw_expr_opers *o; | |
372 | |
373 // sort "constants" to the start of each operand list for + and * | |
374 lw_expr_simplify_sortconstfirst(E); | |
375 | |
376 // non-operators have no simplification to do! | |
377 if (E -> type != lw_expr_type_oper) | |
378 return; | |
379 | |
380 if (E -> value == lw_expr_oper_times) | |
381 { | |
382 for (o = E -> operands; o; o = o -> next) | |
383 { | |
384 if (o -> p -> type == lw_expr_type_int && o -> p -> value == 0) | |
385 { | |
386 // one operand of times is 0, replace operation with 0 | |
387 while (E -> operands) | |
388 { | |
389 o = E -> operands; | |
390 E -> operands = o -> next; | |
391 lw_expr_destroy(o -> p); | |
392 lw_free(o); | |
393 } | |
394 E -> type = lw_expr_type_int; | |
395 E -> value = 0; | |
396 return; | |
397 } | |
398 } | |
399 } | |
400 | |
401 // look for like terms and collect them together | |
402 if (E -> value == lw_expr_oper_plus) | |
403 { | |
404 for (o = E -> operands; o; o = o -> next) | |
405 { | |
406 if (o -> p -> type == lw_expr_type_oper && o -> p -> value == lw_expr_oper_times) | |
407 { | |
408 // we have a "times" here | |
409 // find first non-const operand | |
410 struct lw_expr_opers *op1, *op2, *o2; | |
411 for (op1 = o -> p -> operands; op1; op1 = op1 -> next) | |
412 if (op1 -> p -> type != lw_expr_type_int) | |
413 break; | |
414 | |
415 for (o2 = o -> next; o2; o2 = o2 -> next) | |
416 { | |
417 if (o2 -> p -> type == lw_expr_type_oper && o2 -> p -> value == lw_expr_oper_times) | |
418 { | |
419 // another "times" | |
420 for (op2 = o2 -> p -> operands; op2; op2 = op2 -> next) | |
421 if (op2 -> p -> type != lw_expr_type_int) | |
422 break; | |
423 | |
424 if (lw_expr_compareoperandlist(&op1, &op2)) | |
425 { | |
426 // we have like terms here | |
427 // do something about it | |
428 } | |
429 } | |
430 } | |
431 } | |
432 } | |
433 } | |
434 | |
435 | |
436 for (o = E -> operands; o; o = o -> next) | |
437 lw_expr_simplify(o -> p); | |
438 | |
439 if (E -> value == lw_expr_oper_plus) | |
440 { | |
441 int c = 0, t = 0; | |
442 for (o = E -> operands; o; o = o -> next) | |
443 { | |
444 t++; | |
445 if (!(o -> p -> type == lw_expr_type_int && o -> p -> value == 0)) | |
446 { | |
447 c++; | |
448 } | |
449 } | |
450 if (c == 1) | |
451 { | |
452 lw_expr_t r; | |
453 // find the value and "move it up" | |
454 while (E -> operands) | |
455 { | |
456 o = E -> operands; | |
457 if (o -> p -> type != lw_expr_type_int || o -> p -> value != 0) | |
458 { | |
459 r = lw_expr_deepcopy(o -> p); | |
460 } | |
461 E -> operands = o -> next; | |
462 lw_expr_destroy(o -> p); | |
463 lw_free(o); | |
464 } | |
465 *E = *r; | |
466 return; | |
467 } | |
468 else if (c == 0) | |
469 { | |
470 // replace with 0 | |
471 while (E -> operands) | |
472 { | |
473 o = E -> operands; | |
474 E -> operands = o -> next; | |
475 lw_expr_destroy(o -> p); | |
476 lw_free(o); | |
477 } | |
478 E -> type = lw_expr_type_int; | |
479 E -> value = 0; | |
480 return; | |
481 } | |
482 else if (c != t) | |
483 { | |
484 // collapse out zero terms | |
485 struct lw_expr_opers *o2; | |
486 | |
487 for (o = E -> operands; o; o = o -> next) | |
488 { | |
489 if (o -> p -> type == lw_expr_type_int && o -> p -> value == 0) | |
490 { | |
491 if (o == E -> operands) | |
492 { | |
493 E -> operands = o -> next; | |
494 lw_expr_destroy(o -> p); | |
495 lw_free(o); | |
496 o = E -> operands; | |
497 } | |
498 else | |
499 { | |
500 for (o2 = E -> operands; o2 -> next == o; o2 = o2 -> next) | |
501 /* do nothing */ ; | |
502 o2 -> next = o -> next; | |
503 lw_expr_destroy(o -> p); | |
504 lw_free(o); | |
505 o = o2; | |
506 } | |
507 } | |
508 } | |
509 } | |
510 return; | |
511 } | |
512 } |