userfunc.cpp 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. // Evaluate a user defined function
  2. #include "stdafx.h"
  3. #include "defs.h"
  4. #define F p3 // F is the function body
  5. #define A p4 // A is the formal argument list
  6. #define B p5 // B is the calling argument list
  7. #define S p6 // S is the argument substitution list
  8. void
  9. eval_user_function(void)
  10. {
  11. int h;
  12. // Use "derivative" instead of "d" if there is no user function "d"
  13. if (car(p1) == symbol(SYMBOL_D) && get_arglist(symbol(SYMBOL_D)) == symbol(NIL)) {
  14. eval_derivative();
  15. return;
  16. }
  17. F = get_binding(car(p1));
  18. A = get_arglist(car(p1));
  19. B = cdr(p1);
  20. // Undefined function?
  21. if (F == car(p1)) {
  22. h = tos;
  23. push(F);
  24. p1 = B;
  25. while (iscons(p1)) {
  26. push(car(p1));
  27. eval();
  28. p1 = cdr(p1);
  29. }
  30. list(tos - h);
  31. return;
  32. }
  33. // Create the argument substitution list S
  34. p1 = A;
  35. p2 = B;
  36. h = tos;
  37. while (iscons(p1) && iscons(p2)) {
  38. push(car(p1));
  39. push(car(p2));
  40. eval();
  41. p1 = cdr(p1);
  42. p2 = cdr(p2);
  43. }
  44. list(tos - h);
  45. S = pop();
  46. // Evaluate the function body
  47. push(F);
  48. if (iscons(S)) {
  49. push(S);
  50. rewrite_args();
  51. }
  52. eval();
  53. }
  54. // Rewrite by expanding symbols that contain args
  55. int
  56. rewrite_args(void)
  57. {
  58. int h, n = 0;
  59. save();
  60. p2 = pop(); // subst. list
  61. p1 = pop(); // expr
  62. if (istensor(p1)) {
  63. n = rewrite_args_tensor();
  64. restore();
  65. return n;
  66. }
  67. if (iscons(p1)) {
  68. h = tos;
  69. push(car(p1)); // Do not rewrite function name
  70. p1 = cdr(p1);
  71. while (iscons(p1)) {
  72. push(car(p1));
  73. push(p2);
  74. n += rewrite_args();
  75. p1 = cdr(p1);
  76. }
  77. list(tos - h);
  78. restore();
  79. return n;
  80. }
  81. // If not a symbol then done
  82. if (!issymbol(p1)) {
  83. push(p1);
  84. restore();
  85. return 0;
  86. }
  87. // Try for an argument substitution first
  88. p3 = p2;
  89. while (iscons(p3)) {
  90. if (p1 == car(p3)) {
  91. push(cadr(p3));
  92. restore();
  93. return 1;
  94. }
  95. p3 = cddr(p3);
  96. }
  97. // Get the symbol's binding, try again
  98. p3 = get_binding(p1);
  99. push(p3);
  100. if (p1 != p3) {
  101. push(p2); // subst. list
  102. n = rewrite_args();
  103. if (n == 0) {
  104. pop();
  105. push(p1); // restore if not rewritten with arg
  106. }
  107. }
  108. restore();
  109. return n;
  110. }
  111. int
  112. rewrite_args_tensor(void)
  113. {
  114. int i, n = 0;
  115. push(p1);
  116. copy_tensor();
  117. p1 = pop();
  118. for (i = 0; i < p1->u.tensor->nelem; i++) {
  119. push(p1->u.tensor->elem[i]);
  120. push(p2);
  121. n += rewrite_args();
  122. p1->u.tensor->elem[i] = pop();
  123. }
  124. push(p1);
  125. return n;
  126. }