/*
** Copyright (C) 2003-2006 The University of Melbourne.
** This file may only be copied under the terms of the GNU Library General
** Public License - see the file COPYING.LIB in the Mercury distribution.
*/

/* mercury_proc_id.h - definitions for recording procedure ids */

#ifndef MERCURY_PROC_ID_H
#define MERCURY_PROC_ID_H

#include "mercury_types.h"		/* for MR_ConstString etc */
#include "mercury_tags.h"		/* for MR_DEFINE_BUILTIN_ENUM_CONST */

/*
** The MR_PredFunc type indicates whether a procedure came from a predicate
** or a function.  The constants defined by this enum should have values
** that correspond directly to the values in the representation of the
** `pred_or_func' type in mdbcomp/prim_data.m, so that it is possible to
** cast to/from MR_Word in order to interface with Mercury code.
*/

typedef	enum {
	MR_DEFINE_BUILTIN_ENUM_CONST(MR_PREDICATE),
	MR_DEFINE_BUILTIN_ENUM_CONST(MR_FUNCTION)
} MR_PredFunc;

/*
** This value should be distinct from any of the values in MR_PredFuncEnum.
** It is used in MR_ProcId in the place where an MR_PredFunc field would be,
** and indicates that no proc id exists.
*/

#define MR_NO_PROC_ID -1

/*
** MR_ProcId is a union. The first alternative identifies ordinary
** procedures, while the second alternative identifies automatically generated
** unification, comparison, index and initialisation procedures.  The third
** alternative indicates that no proc id exists.  The meanings of the fields
** in the first two forms are the same as in procedure labels.  The runtime
** system can figure out if a proc id exists by using the macro
** MR_PROC_ID_EXISTS, and it can figure out which form is present by using
** the macro MR_PROC_ID_IS_UCI, which will return true only if the proc id
** exists and the procedure is of the second type.
**
** The compiler generates MR_UserProcId and MR_UCIProcId structures
** in order to avoid having to initialize the MR_ProcId union through the
** inapplicable alternative, since the C standard in widespread use now
** doesn't support that.
**
** The places that know about the structure of procedure ids include
** browser/dl.m and besides all the places that refer to the C types below.
*/

struct MR_UserProcId_Struct {
	MR_PredFunc		MR_user_pred_or_func;
	MR_ConstString		MR_user_decl_module;
	MR_ConstString		MR_user_def_module;
	MR_ConstString		MR_user_name;
	MR_int_least16_t	MR_user_arity;
	MR_int_least16_t	MR_user_mode;
};

struct MR_UCIProcId_Struct {
	MR_ConstString		MR_uci_type_name;
	MR_ConstString		MR_uci_type_module;
	MR_ConstString		MR_uci_def_module;
	MR_ConstString		MR_uci_pred_name;
	MR_int_least16_t	MR_uci_type_arity;
	MR_int_least16_t	MR_uci_mode;
};

struct MR_NoProcId_Struct {
	/*
	** This field should align with the first field of MR_UserProcId_Struct,
	** which means that it should have the same size as MR_PredFunc.
	** Its value should always be equal to MR_NO_PROC_ID.
	*/
	int			MR_no_proc_id_flag;
};

union MR_ProcId_Union {
	MR_UserProcId		MR_proc_user;
	MR_UCIProcId		MR_proc_uci;
	MR_NoProcId		MR_proc_none;
};

#define MR_PROC_ID_EXISTS(proc_id)					\
	((proc_id).MR_proc_none.MR_no_proc_id_flag != MR_NO_PROC_ID)

#define	MR_PROC_ID_IS_UCI(proc_id)					\
	((MR_Unsigned) (proc_id).MR_proc_user.MR_user_pred_or_func > MR_FUNCTION)

#endif /* not MERCURY_PROC_ID_H */
