/* UPE library - code tree operations
 * (c)2000 Stepan Roh
 * see license.txt for copying
 */

#ifndef UPECC_TREE_H
#define UPECC_TREE_H

#include "upecc_ids.h"
#include "upe.h"

/* byte_size from sources */ 
extern int upecc_byte_size;
/* numbers_len from sources */
extern int upecc_num_len;
/* global identifiers table */
extern id_table_t *global_id_table;
/* identifier of ip register */
extern char *upecc_ip_reg;
/* generated processor name */
extern char *upecc_proc_name;

/* tree node types */
typedef enum {
  NODE_NUM, NODE_VAR, NODE_FN, NODE_VAR_DECL, NODE_INSTRUCTION, NODE_NUM_QUOTE, NODE_NUM_BIT_RANGE,
} tree_node_type;

/* parsed input node */
typedef struct tree_node_t {
  tree_node_type type;		/* type */
  union {
    upe_number_t *num;		/* upe number - for NODE_NUM */
    char *id;			/* identifier - for NODE_VAR, NODE_FN */
    struct {			/* var declaration - for NODE_VAR_DECL */
      char *id;			/* var name */
      int len;			/* bit length */
    } var_decl;
    id_table_t *id_table;	/* id table - for NODE_INSTRUCTION */
    struct {			/* num_quote - for NODE_NUM_QUOTE */
      int is_quote;		/* 1 if it's quote, 0 if it's num */
      upe_number_t *num;	/* upe number */
    } num_quote;
    struct {			/* num_bit_range - for NODE_NUM_BIT_RANGE */
      int from, to;		/* boundaries */
    } num_bit_range;
  } x;
  int temp_vars_num;	/* number of needed temporary variables (upe_nums) */
  struct tree_node_t *sons;	/* first son */
  struct tree_node_t *next;	/* first brother */
  int line_num;			/* source file line number */
  char *file_name;		/* source file name */
} tree_node_t;

/* tree node for instructions */
extern tree_node_t *upecc_instructions;

/* id item types */
typedef enum {
  ID_VAR, ID_FN, ID_EXT_FN, ID_BUILTIN_FN, ID_CONST, ID_REG, ID_INSTR_ALIAS,
} id_item_type;

/* built-in functions */
typedef enum {
  BIFN_ADD, BIFN_SUB, BIFN_EQ, BIFN_NE, BIFN_GT, BIFN_GE, BIFN_LT, BIFN_LE,
  BIFN_ASSIGN, BIFN_RETURN, BIFN_NEG, BIFN_AND, BIFN_OR, BIFN_OVERFLOW,
  BIFN_UNDERFLOW, BIFN_BITNEG, BIFN_BITAND, BIFN_BITOR, BIFN_BITXOR,
  BIFN_BIT_LENGTH, BIFN_COND_EXPR, BIFN_BIT_RANGE, BIFN_SHL, BIFN_SHR,
  BIFN_POSTFIX_INC, BIFN_PREFIX_INC, BIFN_POSTFIX_DEC, BIFN_PREFIX_DEC,
  BIFN_FETCH, BIFN_STORE, BIFN_MEM_VIOLATION, BIFN_WHILE, BIFN_DO_WHILE,
  BIFN_IF, BIFN_BREAK, BIFN_CONTINUE, BIFN_FOR, BIFN_FOR_VOID,
  BIFN_ASSIGN_ADD, BIFN_ASSIGN_SUB, BIFN_ASSIGN_BITAND, BIFN_ASSIGN_BITOR,
  BIFN_ASSIGN_BITXOR, BIFN_ASSIGN_SHR, BIFN_ASSIGN_SHL,
} bifn_id;

/* id table record */
typedef struct id_item_t {
  id_item_type type;			/* type */
  union {
    struct {				/* function - for ID_FN and ID_EXT_FN */
      id_table_t *id_table;		/* local id table */
      tree_node_t *args;		/* function arguments - ID_FN only */
      tree_node_t *code;		/* function code - ID_FN only */
      int args_num;			/* number of arguments */
    } fn;
    struct {				/* built-in function - for ID_BUILTIN_FN */
      upe_number_t *(*builtin_fn)(int, upe_number_t **);	/* compile-time evaluator on NULL */
      bifn_id id;			/* function identifier */
    } bifn;
    upe_number_t *num;			/* upe number - for ID_CONST */
    upe_u32_t len;			/* number of bits - for ID_REG */
  } x;
} id_item_t;

tree_node_t *create_tree (void);
void destroy_tree (tree_node_t *tree);
int eval_tree (tree_node_t *tree, upe_number_t **result);

void destroy_id_item (void *item);

upe_number_t *fn_sum_add (int num, upe_number_t **vals);
upe_number_t *fn_sum_sub (int num, upe_number_t **vals);
upe_number_t *fn_sum_and (int num, upe_number_t **vals);
upe_number_t *fn_sum_or (int num, upe_number_t **vals);
upe_number_t *fn_sum_bitand (int num, upe_number_t **vals);
upe_number_t *fn_sum_bitor (int num, upe_number_t **vals);
upe_number_t *fn_sum_bitxor (int num, upe_number_t **vals);
upe_number_t *fn_eq (int num, upe_number_t **vals);
upe_number_t *fn_ne (int num, upe_number_t **vals);
upe_number_t *fn_lt (int num, upe_number_t **vals);
upe_number_t *fn_le (int num, upe_number_t **vals);
upe_number_t *fn_gt (int num, upe_number_t **vals);
upe_number_t *fn_ge (int num, upe_number_t **vals);
upe_number_t *fn_neg (int num, upe_number_t **vals);
upe_number_t *fn_bitneg (int num, upe_number_t **vals);
upe_number_t *fn_cond_expr (int num, upe_number_t **vals);
upe_number_t *fn_bit_range (int num, upe_number_t **vals);
upe_number_t *fn_shl (int num, upe_number_t **vals);
upe_number_t *fn_shr (int num, upe_number_t **vals);

#endif
