152 lines
2.3 KiB
C++
152 lines
2.3 KiB
C++
// Evaluate a user defined function
|
|
|
|
#include "stdafx.h"
|
|
#include "defs.h"
|
|
|
|
#define F p3 // F is the function body
|
|
#define A p4 // A is the formal argument list
|
|
#define B p5 // B is the calling argument list
|
|
#define S p6 // S is the argument substitution list
|
|
|
|
void
|
|
eval_user_function(void)
|
|
{
|
|
int h;
|
|
|
|
// Use "derivative" instead of "d" if there is no user function "d"
|
|
|
|
if (car(p1) == symbol(SYMBOL_D) && get_arglist(symbol(SYMBOL_D)) == symbol(NIL)) {
|
|
eval_derivative();
|
|
return;
|
|
}
|
|
|
|
F = get_binding(car(p1));
|
|
A = get_arglist(car(p1));
|
|
B = cdr(p1);
|
|
|
|
// Undefined function?
|
|
|
|
if (F == car(p1)) {
|
|
h = tos;
|
|
push(F);
|
|
p1 = B;
|
|
while (iscons(p1)) {
|
|
push(car(p1));
|
|
eval();
|
|
p1 = cdr(p1);
|
|
}
|
|
list(tos - h);
|
|
return;
|
|
}
|
|
|
|
// Create the argument substitution list S
|
|
|
|
p1 = A;
|
|
p2 = B;
|
|
h = tos;
|
|
while (iscons(p1) && iscons(p2)) {
|
|
push(car(p1));
|
|
push(car(p2));
|
|
eval();
|
|
p1 = cdr(p1);
|
|
p2 = cdr(p2);
|
|
}
|
|
list(tos - h);
|
|
S = pop();
|
|
|
|
// Evaluate the function body
|
|
|
|
push(F);
|
|
if (iscons(S)) {
|
|
push(S);
|
|
rewrite_args();
|
|
}
|
|
eval();
|
|
}
|
|
|
|
// Rewrite by expanding symbols that contain args
|
|
|
|
int
|
|
rewrite_args(void)
|
|
{
|
|
int h, n = 0;
|
|
save();
|
|
|
|
p2 = pop(); // subst. list
|
|
p1 = pop(); // expr
|
|
|
|
if (istensor(p1)) {
|
|
n = rewrite_args_tensor();
|
|
restore();
|
|
return n;
|
|
}
|
|
|
|
if (iscons(p1)) {
|
|
h = tos;
|
|
push(car(p1)); // Do not rewrite function name
|
|
p1 = cdr(p1);
|
|
while (iscons(p1)) {
|
|
push(car(p1));
|
|
push(p2);
|
|
n += rewrite_args();
|
|
p1 = cdr(p1);
|
|
}
|
|
list(tos - h);
|
|
restore();
|
|
return n;
|
|
}
|
|
|
|
// If not a symbol then done
|
|
|
|
if (!issymbol(p1)) {
|
|
push(p1);
|
|
restore();
|
|
return 0;
|
|
}
|
|
|
|
// Try for an argument substitution first
|
|
|
|
p3 = p2;
|
|
while (iscons(p3)) {
|
|
if (p1 == car(p3)) {
|
|
push(cadr(p3));
|
|
restore();
|
|
return 1;
|
|
}
|
|
p3 = cddr(p3);
|
|
}
|
|
|
|
// Get the symbol's binding, try again
|
|
|
|
p3 = get_binding(p1);
|
|
push(p3);
|
|
if (p1 != p3) {
|
|
push(p2); // subst. list
|
|
n = rewrite_args();
|
|
if (n == 0) {
|
|
pop();
|
|
push(p1); // restore if not rewritten with arg
|
|
}
|
|
}
|
|
|
|
restore();
|
|
return n;
|
|
}
|
|
|
|
int
|
|
rewrite_args_tensor(void)
|
|
{
|
|
int i, n = 0;
|
|
push(p1);
|
|
copy_tensor();
|
|
p1 = pop();
|
|
for (i = 0; i < p1->u.tensor->nelem; i++) {
|
|
push(p1->u.tensor->elem[i]);
|
|
push(p2);
|
|
n += rewrite_args();
|
|
p1->u.tensor->elem[i] = pop();
|
|
}
|
|
push(p1);
|
|
return n;
|
|
}
|