/*
 * GNOME Basic Expressions
 *
 * Author:
 *    Jody Goldberg (jgoldberg@home.com)
 *
 * Copyright 2000, Helix Code, Inc.
 */

#ifndef GB_EXPR_H
#define GB_EXPR_H

#include <gb/gb.h>
#include <gb/gb-main.h>
#include <gb/gb-value.h>

/*
 * If you update this, don't forget to update gb_expr_print.
 */
typedef enum {
    /* Arrays and function calls */
    /* TODO : parameters .... */
  
    /* Values */
    GB_EXPR_VALUE,

    GB_EXPR_OBJREF,

    /* Unary */
    GB_EXPR_POSITIVE,
    GB_EXPR_NEGATIVE,
    GB_EXPR_NOT,
    GB_EXPR_PAREN,

    /* Binary */
    GB_EXPR_CONCAT,
    GB_EXPR_AND,
    GB_EXPR_OR,
    GB_EXPR_XOR,
    GB_EXPR_GT,
    GB_EXPR_GE,
    GB_EXPR_EQ,
    GB_EXPR_NE,
    GB_EXPR_LE,
    GB_EXPR_LT,
    GB_EXPR_SUB,
    GB_EXPR_ADD,
    GB_EXPR_MULT,
    GB_EXPR_DIV,
    GB_EXPR_INT_DIV,
    GB_EXPR_POW,
    GB_EXPR_EQV,
    GB_EXPR_IMP
} GBExprType;

/* These will eventualy be simplified to a few bitmasks by assigning
   better enumeration values */
#define GB_EXPR_UNARY(t)          (((t) == GB_EXPR_POSITIVE) | \
                                   ((t) == GB_EXPR_NEGATIVE)   | \
                                   ((t) == GB_EXPR_NOT)   | \
                                   ((t) == GB_EXPR_PAREN))

#define GB_EXPR_BINARY(t)         (((t) == GB_EXPR_CONCAT) | \
                                   ((t) == GB_EXPR_AND) | \
                                   ((t) == GB_EXPR_OR) | \
                                   ((t) == GB_EXPR_XOR) | \
                                   ((t) == GB_EXPR_GT) | \
                                   ((t) == GB_EXPR_GE) | \
                                   ((t) == GB_EXPR_EQ) | \
                                   ((t) == GB_EXPR_NE) | \
                                   ((t) == GB_EXPR_LE) | \
                                   ((t) == GB_EXPR_LT) | \
                                   ((t) == GB_EXPR_SUB) | \
                                   ((t) == GB_EXPR_ADD) | \
                                   ((t) == GB_EXPR_MULT) | \
                                   ((t) == GB_EXPR_DIV) | \
                                   ((t) == GB_EXPR_INT_DIV) | \
                                   ((t) == GB_EXPR_POW) | \
                                   ((t) == GB_EXPR_EQV) | \
                                   ((t) == GB_EXPR_IMP))

#define GB_EXPR_COMPARE(t)        (((t) == GB_EXPR_GT)   | \
                                   ((t) == GB_EXPR_GE)   | \
                                   ((t) == GB_EXPR_EQ)   | \
                                   ((t) == GB_EXPR_NE)   | \
                                   ((t) == GB_EXPR_LE)   | \
                                   ((t) == GB_EXPR_LT))   

#define GB_EXPR_BINARY_NUMERIC(t) (GB_EXPR_COMPARE(t)    | \
                                   ((t) == GB_EXPR_SUB)  | \
                                   ((t) == GB_EXPR_ADD)  | \
                                   ((t) == GB_EXPR_MULT) | \
                                   ((t) == GB_EXPR_DIV)  | \
                                   ((t) == GB_EXPR_INT_DIV) | \
                                   ((t) == GB_EXPR_POW)  | \
                                   ((t) == GB_EXPR_EQV))

struct _GBExpr {
	GBExprType type;
	union {
		/* slist of GBObjRef */
		GSList   *objref;

		GBValue  *value;
		
		struct {
			const GBExpr *left;
			const GBExpr *right;
		} binary;
		
		struct {
			const GBExpr *sub;
		} unary;
	} parm;
};

struct _GBObjRef {   
	gboolean    method; /* This flags a_func () */
	char const *name;
	GBExprList *parms;
};

struct _GBArgDesc {
	char    *name;
	char    *type_name;
	GBExpr  *def_value;
	guint8   by_value:1;
	guint8   optional:1;
};

GBArgDesc    *gb_arg_desc_new (const char   *name,
			       const char   *type_name,
			       const GBExpr *def_value,
			       gboolean      by_value,
			       gboolean      optional);

/* Master value function */
const GBExpr *gb_expr_new_value     (GBValue *v);

/* Helper value functions */
const GBExpr *gb_expr_new_boolean   (GBBoolean bool);
const GBExpr *gb_expr_new_int       (int val);
const GBExpr *gb_expr_new_float     (double val);
const GBExpr *gb_expr_new_string    (char const * str);
const GBExpr *gb_expr_new_frx       (char const * str);

const GBExpr *gb_expr_new_unary     (GBExprType type, const GBExpr *sub);
const GBExpr *gb_expr_new_binary    (const GBExpr *left, GBExprType type,
				     const GBExpr *right);
const GBExpr *gb_expr_new_obj_list      (GSList *objref);
const GBExpr *gb_expr_new_obj_list_call (GSList *objref);

void gb_expr_destroy (const GBExpr *expr);
void gb_expr_print (FILE * sink, const GBExpr *expr);

/* FuncCall helper functions */
GBObjRef        *gb_obj_ref_new     (const char *name, gboolean method,
				     GBExprList *parms);
void             gb_obj_ref_print   (FILE *sink, const GBObjRef *objref);
void             gb_obj_ref_destroy (const GBObjRef *obj);

/* ObjRef helper functions */
void             gb_objref_print      (FILE *sink, const GBExpr *e);

#endif /* GB_EXPR_H */
