#ifndef CAMV_GEX_H
#define CAMV_GEX_H

#include <genvector/vtd0.h>

#include "gex.tab.h"

typedef enum {
	PUSH_NUM,   /* payload is the number to push */
	PUSH_PARAM, /* push a $N parameter supplied by the caller; payload is the parameter idx */
	SET,        /* payload is destination param number, [TOP] is the value */

	/* these remove [TOP] and [TOP-1], and push the result */
	ADD,
	SUB,
	MUL,
	DIV
} gexi_t;

typedef struct ge_expr_prg_s ge_expr_prg_t;
struct ge_expr_prg_s {
	gexi_t inst;
	double payload;
	ge_expr_prg_t *next;
};

typedef enum {
	GEEE_SUCCESS = 0,
	GEEE_STACK_OVERFLOW,
	GEEE_STACK_UNDERFLOW,
	GEEE_DIV0,
	GEEE_INTERNAL
} ge_expr_err_t;


typedef struct ge_expr_prglist_s {
	ge_expr_prg_t *first;
	ge_expr_prg_t *last;
	void *parent;
} ge_expr_prglist_t;

extern int gexlex(YYSTYPE *dummy, ge_expr_prglist_t *ctx);
extern int gexerror(ge_expr_prglist_t *ctx, const char *msg);

void gex_append(ge_expr_prglist_t *ctx, gexi_t inst, double payload);
void gex_append_idx(ge_expr_prglist_t *ctx, gexi_t inst, int payload);

ge_expr_err_t gex_eval(ge_expr_prg_t *prg, vtd0_t *params, double *res);

void gex_free_prg(ge_expr_prg_t *prg);


#endif
