/* $Id: expr.h,v 1.68 2009/01/27 15:40:22 potyra Exp $ 
 *
 * Copyright (C) 2007-2009 FAUcc Team <info@faumachine.org>.
 * This program is free software. You can redistribute it and/or modify it
 * under the terms of the GNU General Public License, either version 2 of
 * the License, or (at your option) any later version. See COPYING.
 */

#ifndef __EXPR_H_INCLUDED
#define __EXPR_H_INCLUDED

#include "type.h"
#include "scope.h"

/*
 * Types
 */
struct expr {
	struct expr *prev;
	struct expr *next;
	enum {
		EXPR_NONE,
		EXPR_INTEGER,
		EXPR_REAL,
		EXPR_STRING,
		EXPR_IDENTIFIER,
		EXPR_BRACES,
		EXPR_SIZEOF_TYPE,
		EXPR_SIZEOF_EXPR,
		EXPR_BUILTIN_CONSTANT_P,
		EXPR_BUILTIN_OFFSETOF,
		EXPR_BUILTIN_VA_ARG,
		EXPR_TYPE_CONVERSION,
		EXPR_STAR,
		EXPR_AMPHERSAND,
		EXPR_PRE_INC,
		EXPR_PRE_DEC,
		EXPR_POST_INC,
		EXPR_POST_DEC,
		EXPR_NEG,
		EXPR_INV,
		EXPR_NOT,
		EXPR_LEFT,
		EXPR_RIGHT,
		EXPR_EQUAL,
		EXPR_NOT_EQUAL,
		EXPR_LESS,
		EXPR_GREATER,
		EXPR_LESS_EQUAL,
		EXPR_GREATER_EQUAL,
		EXPR_ADD,
		EXPR_SUB,
		EXPR_MUL,
		EXPR_DIV,
		EXPR_MOD,
		EXPR_AND,
		EXPR_OR,
		EXPR_XOR,
		EXPR_SHORT_OR,
		EXPR_SHORT_AND,
		EXPR_LIST,
		EXPR_DOT,
		EXPR_ARROW,
		EXPR_ARRAY,
		EXPR_FUNC,
		EXPR_CONDITION,
		EXPR_ASSIGN,
		EXPR_LEFT_ASSIGN,
		EXPR_RIGHT_ASSIGN,
		EXPR_ADD_ASSIGN,
		EXPR_SUB_ASSIGN,
		EXPR_MUL_ASSIGN,
		EXPR_DIV_ASSIGN,
		EXPR_MOD_ASSIGN,
		EXPR_AND_ASSIGN,
		EXPR_OR_ASSIGN,
		EXPR_XOR_ASSIGN,
	} type;
	unsigned long long integer;
	long double real;
	unsigned int string_len;
	const char *string;
	const char *member;
	struct declaration *declaration;
	struct type *type_name;
	struct expr *expr0;
	struct expr *expr1;
	struct expr *expr2;
	struct expr *first;
	struct expr *last;
};

/*
 * Functions
 */
extern void
expr_rename_structunionenum(
	struct expr *e,
	enum type_type type,
	const char *old,
	const char *new);

extern struct type *
expr_typeof(struct scope *s, struct expr *e);

extern int
expr_is_constant(struct expr *e);

extern struct expr *
expr_new(void);

extern struct expr *
expr_integer(int n);
extern struct expr *
expr_identifier(struct declaration *dion);
extern struct expr *
expr_sizeof_expr(struct expr *e0);
extern struct expr *
expr_sizeof_type(struct type *t);
extern struct expr *
expr_offsetof(struct type *ts, const char *mem);
extern struct expr *
expr_amphersand(struct expr *e0);
extern struct expr *
expr_star(struct expr *e0);
extern struct expr *
expr_arrow(struct expr *e0, const char *mem);
extern struct expr *
expr_not(struct expr *e0);
extern struct expr *
expr_left(struct expr *e0, struct expr *e1);
extern struct expr *
expr_right(struct expr *e0, struct expr *e1);
extern struct expr *
expr_add(struct expr *e0, struct expr *e1);
extern struct expr *
expr_sub(struct expr *e0, struct expr *e1);
extern struct expr *
expr_mul(struct expr *e0, struct expr *e1);
extern struct expr *
expr_div(struct expr *e0, struct expr *e1);
extern struct expr *
expr_mod(struct expr *e0, struct expr *e1);
extern struct expr *
expr_and(struct expr *e0, struct expr *e1);
extern struct expr *
expr_or(struct expr *e0, struct expr *e1);
extern struct expr *
expr_xor(struct expr *e0, struct expr *e1);
extern struct expr *
expr_short_and(struct expr *e0, struct expr *e1);
extern struct expr *
expr_short_or(struct expr *e0, struct expr *e1);
extern struct expr *
expr_equal(struct expr *e0, struct expr *e1);
extern struct expr *
expr_not_equal(struct expr *e0, struct expr *e1);
extern struct expr *
expr_less(struct expr *e0, struct expr *e1);
extern struct expr *
expr_less_equal(struct expr *e0, struct expr *e1);
extern struct expr *
expr_greater(struct expr *e0, struct expr *e1);
extern struct expr *
expr_greater_equal(struct expr *e0, struct expr *e1);
extern struct expr *
expr_assign(struct expr *e0, struct expr *e1);
extern struct expr *
expr_add_assign(struct expr *e0, struct expr *e1);
extern struct expr *
expr_cast(struct type *t, struct expr *e0);
extern struct expr *
expr_cast_ptrdiff(struct expr *e0);

extern struct expr *
expr_dup(struct expr *e);
extern void
expr_cp(struct expr *oe, struct expr *ne);

extern void
expr_free(struct expr *e);

extern int
expr_simplify(struct scope *s, struct declaration *dion);
extern int
expr_optimize(struct scope *s, struct declaration *dion);

#endif /* __EXPR_H_INCLUDED */
