/*
	type.h

	type system

	Copyright (C) 2001 Bill Currie <bill@taniwha.org>

	Author: Bill Currie <bill@taniwha.org>
	Date: 2001/12/11

	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
	of the License, 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:

		Free Software Foundation, Inc.
		59 Temple Place - Suite 330
		Boston, MA  02111-1307, USA

*/

#ifndef __type_h
#define __type_h

#include "QF/pr_comp.h"

#include "def.h"

typedef struct ty_func_s {
	struct type_s *type;
	int         num_params;
	struct type_s *param_types[MAX_PARMS];
} ty_func_t;

typedef struct ty_fldptr_s {
	struct type_s *type;
} ty_fldptr_t;

typedef struct ty_array_s {
	struct type_s *type;
	int         base;
	int         size;
} ty_array_t;

typedef enum {
	ty_none,				///< func/field/pointer or not used
	ty_struct,
	ty_union,
	ty_enum,
	ty_array,
	ty_class,
} ty_meta_e;

typedef struct type_s {
	etype_t     type;		///< ev_invalid means structure/array etc
	const char *name;
	/// function/pointer/array/struct types are more complex
	ty_meta_e   meta;
	union {
		ty_func_t   func;
		ty_fldptr_t fldptr;
		ty_array_t  array;
		struct symtab_s *symtab;
		struct class_s *class;
	} t;
	struct type_s *next;
	int         freeable;
	const char *encoding;	///< Objective-QC encoding
	struct def_s *type_def;	///< offset of qfo encodoing
} type_t;

typedef struct {
	type_t     *type;
	struct param_s *params;
	storage_class_t storage;
	unsigned    multi_type:1;
	unsigned    multi_store:1;
	unsigned    is_signed:1;
	unsigned    is_unsigned:1;
	unsigned    is_short:1;
	unsigned    is_long:1;
	unsigned    is_typedef:1;
	unsigned    is_overload:1;
} specifier_t;

extern	type_t	type_invalid;
extern	type_t	type_void;
extern	type_t	type_string;
extern	type_t	type_float;
extern	type_t	type_vector;
extern	type_t	type_entity;
extern	type_t	type_field;
extern	type_t	type_function;
extern	type_t	type_pointer;
extern	type_t	type_floatfield;
extern	type_t	type_quaternion;
extern	type_t	type_integer;
extern	type_t	type_uinteger;
extern	type_t	type_short;

extern	type_t	*type_nil;		// for passing nil into ...
extern	type_t	*type_default;	// default type (float or int)

extern	type_t	type_va_list;
extern	type_t	type_param;
extern	type_t	type_zero;

extern struct symtab_s *vector_struct;
extern struct symtab_s *quaternion_struct;

struct dstring_s;

etype_t low_level_type (type_t *type);
type_t *new_type (void);
void free_type (type_t *type);
void chain_type (type_t *type);

/**	Append a type to the end of a type chain.

	The type chain must be made up of only field, pointer, function and array
	types, as other types do not have auxiliary type fields.

	\param type		The type chain to which the type will be appended.
	\param new		The type to be appended. May be any type.
	\return			The type chain with the type appended at the deepest
					level.
*/
type_t *append_type (type_t *type, type_t *new);
type_t *find_type (type_t *new);
void new_typedef (const char *name, type_t *type);
type_t *field_type (type_t *aux);
type_t *pointer_type (type_t *aux);
type_t *array_type (type_t *aux, int size);
type_t *based_array_type (type_t *aux, int base, int top);
void print_type_str (struct dstring_s *str, type_t *type);
void print_type (type_t *type);
const char *encode_params (type_t *type);
void encode_type (struct dstring_s *encoding, type_t *type);
int is_enum (type_t *type);
int is_integral (type_t *type);
int is_float (type_t *type);
int is_scalar (type_t *type);
int is_math (type_t *type);
int is_struct (type_t *type);
int is_class (type_t *type);
int is_array (type_t *type);
int type_assignable (type_t *dst, type_t *src);
int type_size (type_t *type);

void init_types (void);
void chain_initial_types (void);

void clear_typedefs (void);

#endif//__type_h
