#ifndef __NLSYS_MODEL_H_INCLUDED__
#define __NLSYS_MODEL_H_INCLUDED__

typedef struct _model_modifier *model_modifier_t;
typedef struct _model *model_t;

#include "type.h"
#include "struct.h"
#include "union.h"
#include "enum.h"
#include "typedef.h"
#include "area.h"

#define MODEL_FUNCTION_ARGS_NUM 16
#define MODEL_MODIFIER_NUM 8

struct _model_modifier { /* * or [] */
  c_type_t type; /* POINTER, ARRAY */
  union {
    struct {
      int number;
    } array;
  } param;
};

struct _model {
  c_type_t type; /* CHAR/SHORT/INT/LONG/STRUCT/UNION/ENUM/TYPEDEF/FUNCTION */
#define MODEL_FLAG_UNSIGNED   (1 << 0)
#define MODEL_FLAG_FUNCVARARG (1 << 1)
#define MODEL_FLAG_TYPETYPE   (1 << 2)
#define MODEL_FLAG_TYPESYMBOL (1 << 3)
  unsigned int flags;
  union {
    void *p;
    struct_t _struct;
    union_t _union;
    enum_t _enum;
    typedef_t _typedef;
  } custom;

  struct {
    int number;
    struct _model_modifier modifier[MODEL_MODIFIER_NUM];
  } modifiers;

  struct {
    model_t retval;
    struct {
      int number;
      model_t arg[MODEL_FUNCTION_ARGS_NUM];
    } args;
  } function;
};

/*****************************************************************
 * model_t
 */

model_t model_destroy(model_t model);
model_t model_create(c_type_t type);
model_modifier_t model_get_modifier_first(model_t model);
model_modifier_t model_get_modifier_last(model_t model);
int model_get_modifier_number(model_t model);
int model_add_modifier_pointer(model_t model);
int model_add_modifier_array(model_t model, int number);
int model_insert_modifier_pointer(model_t model);
int model_insert_modifier_array(model_t model, int number);
int model_del_modifier(model_t model);
int model_is_pointer(model_t model);
int model_is_array(model_t model);
int model_is_address(model_t model);
model_t model_add_function_args(model_t model, model_t arg);
model_t model_copy(model_t model);
int model_cmp(model_t model1, model_t model2);
void model_print(model_t model, int indent);

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

int model_get_size(model_t model);
int model_get_pointer_size(model_t model);
int model_get_align(model_t model);
int model_get_level(model_t model);
int model_pointer_to_array(model_t model, int number);
int model_array_to_pointer(model_t model);
long model_change_number(model_t new_model, model_t old_model, long number);
model_t model_deploy_typedef(model_t model);

#endif
