/***********************************************************************
 *								       *
 *		 A  F U N C T I O N   E V A L U A T O R 	       *
 *								       *
 * Placed in the Public Domain by David Gay, 1988		       *
 *								       *
 ***********************************************************************/

/* Includes to allow the use of lists */
#include <exec/types.h>
#include <exec/lists.h>
#include <proto/exec.h>

typedef struct _value *value;	    /* An expression */

typedef struct List var_list;	    /* A list of variables */

typedef struct {		    /* A variable */
    char *name; 			/* It's name */
    struct var *adr;			/* Cache */
    long key;				/* Cache valid ? */
} variable;

typedef struct List context;	    /* A context */

extern int eval_error;		    /* Last error */

/* The possible errors */
#define SYNTAX 1		    /* Syntax error */
#define OUT_OF_MEM 2		    /* Not enough memory */
#define UNMATCHED 3		    /* Right bracket expected */
#define WANT_LEFT 5		    /* Left bracket expected */
#define NOT_DIFFERENTIABLE 6	    /* Function not differentiable */
#define RECURSIVE 7		    /* Recursion not allowed ... */
#define NOTNUM 8		    /* A numeric expression was expected */

/* The flags for eval */
#define PAT	0x0001		    /* Do pattern based simplification */
#define NICE	0x0002		    /* Only do arithmetic if result integer */
#define VAR	0x0004		    /* Substitute values of variables */
#define REC	0x0008		    /* Idem, but evaluate them */
#define NORED	0x0010		    /* No constant folding */

/* The various routines */
int	init_expr(void);            /* Must be called first */
void	cleanup_expr(void);         /* Once you've finished */

value	compile(char *);            /* "Compile" an expression */
char	*decompile(value, char *, int); /* Reconstruct string from expression */
void	free_expr(value);           /* Free memory used by expression */

value	eval(value, int);           /* Evaluate */
double	quick_eval(value);          /* Evaluate quickly, get a numeric result */

value	differentiate(value, char *);

int	create_var(variable *);
void	free_var(variable *);
int	set_var(variable *, value);
value	get_var(variable *);

int	create_var_name(char *);
void	free_var_name(char *);
value	get_var_name(char *);       /* by name, not through structure */
int	set_var_name(char *, value);

int	create_quick(variable *);   /* Create a numeric variable */
void	free_quick(variable *);
void	set_quick(variable *, double);
double	get_quick(variable *);

var_list *make_var_list(value, var_list *); /* make a list of vars used in expr */
void	free_var_list(var_list *);
int	create_vars(var_list *);    /* Create the vars in a list */
void	free_vars(var_list *);

void	set_context(context *);     /* Set the new context */

#define init_context(cont) NEWLIST(cont) /* Initialise a context */
#define init_var_list(list) NEWLIST(list)
#define NEWLIST(list) \
    { (list)->lh_Head = (struct Node *)&(list)->lh_Tail; \
      (list)->lh_TailPred = (struct Node *)&(list)->lh_Head; \
      (list)->lh_Tail = 0; \
    }

