transform.cpp 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. /* Transform an expression using table look-up
  2. The expression and free variable are on the stack.
  3. The argument s is a null terminated list of transform rules.
  4. For example, see itab.cpp
  5. Internally, the following symbols are used:
  6. F input expression
  7. X free variable, i.e. F of X
  8. A template expression
  9. B result expression
  10. C list of conditional expressions
  11. */
  12. #include "stdafx.h"
  13. #include "defs.h"
  14. // p1 and p2 are tmps
  15. #define F p3
  16. #define X p4
  17. #define A p5
  18. #define B p6
  19. #define C p7
  20. void
  21. transform(char **s)
  22. {
  23. int h;
  24. save();
  25. X = pop();
  26. F = pop();
  27. // save symbol context in case eval(B) below calls transform
  28. push(get_binding(symbol(METAA)));
  29. push(get_binding(symbol(METAB)));
  30. push(get_binding(symbol(METAX)));
  31. set_binding(symbol(METAX), X);
  32. // put constants in F(X) on the stack
  33. h = tos;
  34. push_integer(1);
  35. push(F);
  36. push(X);
  37. polyform(); // collect coefficients of x, x^2, etc.
  38. push(X);
  39. decomp();
  40. while (*s) {
  41. scan_meta(*s);
  42. p1 = pop();
  43. A = cadr(p1);
  44. B = caddr(p1);
  45. C = cdddr(p1);
  46. if (f_equals_a(h))
  47. break;
  48. s++;
  49. }
  50. tos = h;
  51. if (*s) {
  52. push(B);
  53. eval();
  54. p1 = pop();
  55. } else
  56. p1 = symbol(NIL);
  57. set_binding(symbol(METAX), pop());
  58. set_binding(symbol(METAB), pop());
  59. set_binding(symbol(METAA), pop());
  60. push(p1);
  61. restore();
  62. }
  63. // search for a METAA and METAB such that F = A
  64. int
  65. f_equals_a(int h)
  66. {
  67. int i, j;
  68. for (i = h; i < tos; i++) {
  69. set_binding(symbol(METAA), stack[i]);
  70. for (j = h; j < tos; j++) {
  71. set_binding(symbol(METAB), stack[j]);
  72. p1 = C; // are conditions ok?
  73. while (iscons(p1)) {
  74. push(car(p1));
  75. eval();
  76. p2 = pop();
  77. if (iszero(p2))
  78. break;
  79. p1 = cdr(p1);
  80. }
  81. if (iscons(p1)) // no, try next j
  82. continue;
  83. push(F); // F = A?
  84. push(A);
  85. eval();
  86. subtract();
  87. p1 = pop();
  88. if (iszero(p1))
  89. return 1; // yes
  90. }
  91. }
  92. return 0; // no
  93. }