/* Provide various operations on values (Create new expressions from old ones) */ /* These could probably be made externally accessible (it would be useful) */ #include "evalint.h" #include "operations.h" #include "variables.h" #include /* Duplicate value */ value id(expr) register value expr; { switch (expr->type) { case cste: return(cst(expr->cte)); case var: return(dup_var(&expr->vr)); case fonc: return(apply_func(expr->fn.func, id(expr->fn.arg))); case op: return(dup_op(expr, id(expr->opr.arg1), id(expr->opr.arg2))); } } /* Create new expression which is the sum of the two others */ value add(arg1, arg2) value arg1, arg2; { register value node; if (arg1 && arg2 && ALLOC_VALUE(node)) { node->type = op; node->opr.op = plus; node->opr.arg1 = arg1; node->opr.arg2 = arg2; return(node); } if (arg1) free_expr(arg1); if (arg2) free_expr(arg2); return(NULL); } value sub(arg1, arg2) value arg1, arg2; { register value node; if (arg1 && arg2 && ALLOC_VALUE(node)) { node->type = op; node->opr.op = minus; node->opr.arg1 = arg1; node->opr.arg2 = arg2; return(node); } if (arg1) free_expr(arg1); if (arg2) free_expr(arg2); return(NULL); } value mult(arg1, arg2) value arg1, arg2; { register value node; if (arg1 && arg2 && ALLOC_VALUE(node)) { node->type = op; node->opr.op = times; node->opr.arg1 = arg1; node->opr.arg2 = arg2; return(node); } if (arg1) free_expr(arg1); if (arg2) free_expr(arg2); return(NULL); } value div(arg1, arg2) value arg1, arg2; { register value node; if (arg1 && arg2 && ALLOC_VALUE(node)) { node->type = op; node->opr.op = divide; node->opr.arg1 = arg1; node->opr.arg2 = arg2; return(node); } if (arg1) free_expr(arg1); if (arg2) free_expr(arg2); return(NULL); } value topow(arg1, arg2) value arg1, arg2; { register value node; if (arg1 && arg2 && ALLOC_VALUE(node)) { node->type = op; node->opr.op = power; node->opr.arg1 = arg1; node->opr.arg2 = arg2; return(node); } if (arg1) free_expr(arg1); if (arg2) free_expr(arg2); return(NULL); } /* Apply function to value */ value apply_func(func, arg) FUNCTION func; value arg; { register value node; if (arg && ALLOC_VALUE(node)) { node->type = fonc; node->fn.func = func; node->fn.arg = arg; return(node); } if (arg) free_expr(arg); return(NULL); } /* Create a constant expression */ value cst(c) double c; { register value node; if (ALLOC_VALUE(node)) { node->type = cste; node->cte = c; } return(node); } /* Make an expression of the form 'x' */ value dup_var(v) variable *v; { register value node; if (ALLOC_VALUE(node)) { node->type = var; node->vr = *v; if (node->vr.name = ALLOCMEM(strlen(v->name) + 1)) { strcpy(node->vr.name, v->name); return(node); } FREE_VALUE(node); } return(NULL); } /* Create an expression of type a /+-* b */ value dup_op(expr, arg1, arg2) value expr, arg1, arg2; { register value node; if (arg1 && arg2 && ALLOC_VALUE(node)) { node->type = op; node->opr.op = expr->opr.op; node->opr.arg1 = arg1; node->opr.arg2 = arg2; return(node); } if (arg1) free_expr(arg1); if (arg2) free_expr(arg2); return(NULL); } /* Are two expressions identical ? */ int same(expr1, expr2) register value expr1, expr2; { if (expr1->type != expr2->type) return(FALSE); else switch(expr1->type) { case cste: return(expr1->cte == expr2->cte); case var: return(strcmp(expr1->vr.name, expr2->vr.name) == 0); case fonc: return(expr1->fn.func == expr2->fn.func && same(expr1->fn.arg, expr2->fn.arg)); case op: return(expr1->opr.op == expr2->opr.op && same(expr1->opr.arg1, expr2->opr.arg1) && same(expr1->opr.arg2, expr2->opr.arg2)); } }