#ifndef __NLSYS_SYMBOL_H_INCLUDED__
#define __NLSYS_SYMBOL_H_INCLUDED__

typedef struct _symbol *symbol_t;

#include "type.h"
#include "objlist.h"
#include "model.h"
#include "value.h"
#include "syntax.h"
#include "area.h"

struct _symbol {
  struct objentry entry;

#define SYMBOL_NAME_AUTO "*"
#define SYMBOL_NAME_NONAME NULL
  char *name;
  int id;

  c_type_t type; /* VARIABLE, LABEL */
  int line;
  c_type_t scope; /* EXTERN, STATIC */
  model_t model;

#define SYMBOL_FLAG_INITFIRST  (1 << 0)
#define SYMBOL_FLAG_READONLY   (1 << 1)
#define SYMBOL_FLAG_LOCATED    (1 << 2)
#define SYMBOL_FLAG_TEMPORARY  (1 << 3)
#define SYMBOL_FLAG_FUNCTION   (1 << 4)
#define SYMBOL_FLAG_FUNCBLOCK  (1 << 5)
#define SYMBOL_FLAG_FUNCVARARG (1 << 6)
#define SYMBOL_FLAG_FUNCNOINIT (1 << 7)
#define SYMBOL_FLAG_BITFIELD   (1 << 8)
  unsigned int flags;

  struct {
    c_type_t type;
    union {
      void *p;
      area_t area;
      symbol_t symbol;
    } base;
    int offset;
  } location;

  value_t value;

  union {
    struct {
      struct {
	int bits;
	int shift;
      } bitfield;
    } variable;
    struct {
      symbol_t variable;
    } label;
  } param;

  union {
    struct {
      objlist_t args;
      objlist_t labels;
      area_t stack;
      syntax_t initlabel;
      syntax_t retlabel;
    } function;
  } obj;
};

/*****************************************************************
 * symbol_t
 */

symbol_t symbol_destroy(symbol_t symbol);
void symbol_free(void *p);
symbol_t symbol_create(c_type_t type, int line, c_type_t scope,
		       char *name, model_t model, unsigned int flags,
		       c_type_t value_type);
void symbol_print_name(symbol_t symbol);
void symbol_print_simple(symbol_t symbol, int indent);
void symbol_print_value_simple(symbol_t symbol, int indent);
void symbol_print(symbol_t symbol, int indent);

/*****************************************************************
 * library
 */

int symbol_is_const_number(symbol_t symbol);
int symbol_is_const_string(symbol_t symbol);
int symbol_is_writable(symbol_t symbol);
symbol_t symbol_locate(symbol_t symbol, objlist_t symbols,
		       area_t static_area, area_t stack_area);
symbol_t symbol_make_cast(symbol_t symbol, model_t model,
			  objlist_t symbols,
			  area_t static_area, area_t stack_area);
symbol_t symbol_change_model(symbol_t symbol, model_t model,
			     objlist_t symbols,
			     area_t static_area, area_t stack_area);
symbol_t symbol_change_model_type(symbol_t symbol, c_type_t type,
				  objlist_t symbols,
				  area_t static_area, area_t stack_area);
symbol_t symbol_sign_extension(symbol_t symbol, objlist_t symbols,
			       area_t static_area, area_t stack_area);
symbol_t symbol_list_search(objlist_t list, char *name);
symbol_t symbol_set_model(symbol_t symbol, model_t model, objlist_t symbols,
			  area_t static_area, area_t stack_area);
symbol_t symbol_read(objlist_t syntax_list,
		     objlist_t defines_list, objlist_t symbols);
objlist_t symbol_define_read(objlist_t syntax_list, objlist_t sentence_list,
			     objlist_t defines_list, objlist_t symbols,
			     area_t static_area, area_t stack_area);

#endif
