/* This file is part of cqual.
   Copyright (C) 2000-2001 The Regents of the University of California.

cqual 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.

cqual 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 cqual; see the file COPYING.  If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */

#ifndef QTYPE_H
#define QTYPE_H

#include "AST.h"
#include "cqual.h"
#include "quals.h"
#include "linkage.h"

EXTERN_C_BEGIN

typedef struct Qtypelist *qtypelist;
typedef qtypelist qtypelist_scanner;
typedef void *field_scanner;

void init_qtype(void);

/*
 * qtypelists
 */

void qtypelist_scan(qtypelist l, qtypelist_scanner *); /* Begin scanning */
qtype qtypelist_next(qtypelist_scanner *); /* continue scanning */

/*
 * Predicates
 */

bool qtype_primitive(qtype qt);
bool qtype_char(qtype qt);
bool qtype_signed_char(qtype qt);
bool qtype_unsigned_char(qtype qt);
bool qtype_int(qtype qt);
bool qtype_unsigned_int(qtype qt);
bool qtype_float(qtype qt);
bool qtype_complex(qtype qt);
bool qtype_aggregate(qtype qt);
bool qtype_struct(qtype qt);
bool qtype_union(qtype qt);
bool qtype_transparent(qtype qt);
bool qtype_void(qtype qt);
bool qtype_pointer(qtype qt);
bool qtype_function(qtype qt);
bool qtype_varargs(qtype qt);
bool qtype_oldstyle(qtype qt);
bool qtype_array(qtype qt);
bool qtype_unsigned(qtype qt);
bool qtype_smallerthanint(qtype qt);
bool qtype_integral(qtype qt); /* Does not include enums */
bool qtype_string(qtype qt);
bool qtype_var(qtype qt);
bool qtype_scheme(qtype qt);

/*
 * Constructors
 */

extern qtype error_qtype;
qtype mkqtype_void(qual);
qtype mkqtype_bool(qual);
qtype mkqtype_char(qual);
qtype mkqtype_int(qual);
qtype mkqtype_unsigned_int(qual);
qtype mkqtype_long(qual);
qtype mkqtype_unsigned_long(qual);
qtype mkqtype_long_long(qual);
qtype mkqtype_unsigned_long_long(qual);
qtype mkqtype_float(qual);
qtype mkqtype_double(qual);
qtype mkqtype_size_t(qual);
qtype mkqtype_ptrdiff_t(qual);
qtype mkqtype_pointer(qual, qtype);
qtype mkqtype_function(qual q, bool varargs, qual vquals, bool oldstyle,
		       qtype ret, qtypelist args);
qtype mkqtype_var(qual q, const char *name);
qtype mkqtype_fresh(void); /* Make a fresh, uniquely named qtype variable */

/*
 * Accessors
 */

/* Operations on qualified types */
qtype complex_base_qtype(qtype qt);/* Return the base type of a complex
				      qtype */
qtype points_to_qtype(qtype qt);   /* Remove one level of ptr from a qtype */
qtype array_of_qtype(qtype qt);    /* Remove one level of array from a qtype */
qtype return_qtype(qtype qt);      /* Get return type of function qtype */
qtypelist arg_qtypes(qtype qt);    /* Get argument types of function qtype */
qual vqual_qtype(qtype qt);        /* Get varargs qualifier, if any */

qtype field_qtype(qtype qt, cstring field);
                                   /* Get the type of a field of an
                                      aggregate.  Returns NULL if no
				      such field exists. */
void field_scan(qtype qt, field_scanner *);  /* Iterate over the fields of
                                                an aggregate.  Returns
					        NULL if no such field
						exists. */
void field_scan_at(qtype qt, cstring field,
		   field_scanner *);     /* Iterate over the fields of an
					     aggregate, starting at field */
qtype field_next(field_scanner *);           
qual qual_qtype(qtype qt);      /* Get the top-level qualifier of qt */
bool has_qual_qtype(qtype qt, qual bound); /* TRUE iff qt's top-level
					      qualifier has bound as
					      an originally-specified
					      qualifier */

/*
 * Qtype manipulation
 */

/* Given a data declaration, assign it a qualified type if it doesn't
   have one already.  Return true iff it didn't already have a
   qualified type.  If generalize is true, make a polymorphic type
   if possible.  Otherwise always make a monomorphic type. */
bool add_ddecl_qtype(data_declaration ddecl, bool generalize);

/* Convert a field declaration to a qtype */
qtype get_fdecl_qtype(const char *tag_name, field_declaration fdecl);

/* Make a qtype from a regular type. */
qtype type_to_qtype(type, const char *, location *loc);

/* Copy qt, making fresh qualifiers everywhere. */
qtype copy_qtype(qtype qt, location *loc);

/* Turn qt into a type scheme, generalizing over all qualifier
   variables in qt.  No checking is done that this is sound. */
qtype generalize_qtype(qtype qt);

/* Make a copy of qt, making fresh qualifiers everywhere, but also
   copying the constraints.  All variables in reachable constraints
   are also copied. */
qtype instantiate_qtype(qtype qt, location *loc);

/* Return TRUE iff qt1 and qt2 have the same shape.  If match_quals is
   not NULL, calls match_quals on every pair of corresponding
   qualifiers (q1 from qt1, q2 from qt2), with extra arg. */
bool match_qtype(qtype qt1, qtype qt2,
		 void (*match_quals)(qual q1, qual q2, void *arg), void *arg);

/* Return TRUE iff t1 and t2 match exactly, i.e., if converting t1 and
   t2 to qtypes would yield exactly the same qtype */
bool match_type(type t1, type t2);

/*
 * Constraint generation
 *
 * These functions return FALSE if adding the constraint was
 * successful (there was no error) and TRUE if adding the constraint
 * was unsuccessful (there was an inconsistency).
 */

bool mkleq_qtype(qtype qt1, qtype qt2, location *loc);/* Assert t1 <= t2 */
bool mkeq_qtype(qtype qt1, qtype qt2, location *loc); /* Assert t1 = t2 */
bool unify_qtype(qtype qt1, qtype qt2, location *loc);/* Assert t1 = t2, plus
							 cannot distinguish
							 t1 and t2 any more */

/* Equate the qualifiers on types qt1 and qt2.  For the levels on
   which qt1 and qt2 have the same shape, the qualifiers are equated
   level by level.  After that point, all qualifiers on the remains
   levels are equated. */
bool mkeq_qtype_cast(qtype qt1, qtype qt2, location *loc);

/* Make fresh qtype lub and have qt1 <= lub, qt2 <= lub. */
bool lub_qtype(qtype qt1, qtype qt2, qtype *lub, location *loc);

/* Return TRUE iff left and right are the same.  Does not generate
   constraints. */
bool eq_qtype(qtype qt1, qtype qt2);

/* Add constraints bewteen all qualifiers of qt and the varargs
   qualifier q.  For each qualifier q' of qt, a copy of q is made
   sharing q's constraints, and then the copy is equated to q'.
   Returns TRUE if an error occurs. */
bool varargs_constrain_quals_qtype(qtype qt, qual q, location *loc);

/*
 * Higher-level qtype manipulation
 *
 * These routines do conversions and tests to support the C type
 * rules.
 */

/* Return TRUE iff qt is a void *. */
bool qtype_void_pointer(qtype qt);

/* Return TRUE iff qt is a char *. */
bool qtype_char_pointer(qtype qt);

/* Convert the qtype as appropriate for appearing in a generic expr
   context.  The logic is duplicated from types.c. */
qtype default_conversion_qtype(qtype qt);

/* Convert pointer qt to a void *, preserving the top qualifier. */
qtype pointer_to_void_pointer_qtype(qtype qt);

/* Convert a pointer to an integer, preserving the top level
qualifiers. */
qtype pointer_to_unsigned_int_qtype(qtype qt);

/*
 * Printing routines
 */

/* Print a qualified type */
int print_qtype(printf_func, qtype);
int print_qtype_raw(printf_func, qtype);
int print_qtype_qf(printf_func, pr_qual_fn, qtype);

/* Return the color markup for a qualified type */
const char *color_qtype(qtype);

EXTERN_C_END

#endif
