/***************************************************************************
  
  gbc_type.h
  
  (c) Benoît Minisini <benoit.minisini@gambas-basic.org>

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2, or (at your option)
  any later version.
  
  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.
  
  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  MA 02110-1301, USA.
  
***************************************************************************/

#ifndef __GBC_TYPE_H
#define __GBC_TYPE_H

#define PROJECT_COMP
#include "gb_type_common.h"

/***************************************************

  Format d'un Type

  F K T T X X X X

  F : Flags (TF_*)
  K : Kind (TK_*)
  T : Type (T_*)
  X : index, pour T_OBJECT, T_ARRAY, T_STRUCT

***************************************************/

/*
typedef
  ulong TYPE;
*/

typedef
  unsigned char TYPE_ID;

typedef
  union {
    struct {
      unsigned char flag;
      TYPE_ID id;
      short value;
      } t;
    uint l;
    }
  TYPE;

typedef
  struct {
    int value;
    TYPE type;
    }
  VALUE;

#define TV_NONE (-1)
#define TV_ME (-2)
#define TV_SUPER (-3)
#define TV_NEW (-4)

#ifndef __GBC_TYPE_C
EXTERN char *TYPE_array_name[]; 
#endif
  
#define TYPE_is_static(type)     ((type).t.flag & TF_STATIC)
#define TYPE_is_public(type)     ((type).t.flag & TF_PUBLIC)

#define TYPE_is_array(type)      (TYPE_get_id(type) == T_ARRAY)
#define TYPE_is_object(type)     ((TYPE_get_id(type) == T_OBJECT) && (TYPE_get_value(type) >= 0))
#define TYPE_is_boolean(type)    (TYPE_get_id(type) == T_BOOLEAN)
#define TYPE_can_be_long(type)   (TYPE_get_id(type) <= T_LONG)

#define TYPE_get_value(type)     ((type).t.value)
#define TYPE_get_kind(type)      ((type).t.flag & 0xF)
#define TYPE_get_id(type)        ((type).t.id)
#define TYPE_is_null(type)       ((type).l == 0)
#define TYPE_is_void(type)       ((type).t.id == 0)

#define TYPE_set_value(type, _value)     ((type)->t.value = (_value))
#define TYPE_set_id(type, _id)           ((type)->t.id = (_id))
#define TYPE_set_kind(type, _kind)       ((type)->t.flag &= ~0xF, (type)->t.flag |= (_kind))
#define TYPE_set_flag(type, _flag)       ((type)->t.flag |= (_flag))
#define TYPE_clear_flag(type, _flag)     ((type)->t.flag &= ~(_flag))
#define TYPE_clear(type)                 ((type)->l = 0)

#define TYPE_make_simple(_id) ({ TYPE _t; _t.t.flag = 0; _t.t.id = (_id); _t.t.value = TV_NONE; _t; })
#define TYPE_make(_id, _value, _flag) ({ TYPE _t; _t.t.flag = (_flag); _t.t.id = (_id); _t.t.value = (_value); _t; })

#define TYPE_must_ref(type)  (TYPE_get_id(type) >= T_STRING)

#define TYPE_are_identical(t1, t2) (t1.l == t2.l)

const char *TYPE_get_short_desc(TYPE type);

char *TYPE_get_desc(TYPE type);
bool TYPE_check_prefix(TYPE type, const char *prefix, int len);

bool TYPE_compare(TYPE t1, TYPE t2);

#endif


