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 }