Files
mercury/runtime/mercury_construct.c
Zoltan Somogyi 43fbf4b956 A step towards RTTI in Mercury.
Estimated hours taken: 40
Branches: main

A step towards RTTI in Mercury.

This step redefines the representation of pseudo-typeinfos inside the compiler
to be identical to the representation we will need for efficient interpretation
of RTTI data structures in Mercury. Later steps will do likewise for
typectorinfos. In the end, we will have two implementations of RTTI:
the current low-level, very efficient one written in C, which will be used
by the C backends (both LLDS and MLDS), and a new, higher-level one
which will use Mercury data structures and Mercury predicates for
interpretation (along the lines of library/rtti_implementation.m)
for the Java and IL backends.

A large part of this change concerns the fact that pseudo-typeinfos can now
contain typeinfos as well as other pseudo-typeinfos, and they do in the
frequent case that the type of an argument is ground. Given that typeinfos
are just special cases of pseudo-typeinfos, the code for handling the two
types is usually similar, with common code factored out when relevant.

In the process of redesigning the data structures concerning (pseudo-)
typeinfos, I also fixed an old naming scheme that has become misleading.
The representation of a (pseudo-) typeinfo depends on whether the principal
type constructor is fixed arity or not. We used to denote this distinction
with the phrases first-order vs higher-order, since at first the only variable
arity type constructors were pred and func. However, this hasn't been true
since we added tuples. I have changed the naming scheme to be fixed-arity vs
variable-arity.

compiler/rtti.m:
	Add new, purely Mercury data structures for representing typeinfos
	and pseudo-typeinfos, designed both for efficient interpretation
	and as a source for the generation of static data structures in C.

compiler/pseudo_type_info.m:
	Delete the type definitions here, since they are superseded by the new
	definitions in rtti.m.

	Add predicates for constructing typeinfos as well as pseudo-typeinfos,
	since now we need those too.

	Conform to the changed data structures for (pseudo-) typeinfos.

compiler/ll_pseudo_type_info.m:
compiler/ml_closure_gen.m:
compiler/rtti_out.m:
compiler/rtti_to_mlds.m:
compiler/opt_debug.m:
compiler/type_ctor_info.m:
	Conform to the changed data structures for (pseudo-) typeinfos.

compiler/mlds.m:
	Since the MLDS now refers to type_infos, add their type
	(mlds__type_info_type) to the list of types the MLDS knows about.

compiler/ml_code_util.m:
compiler/mlds_to_c.m:
compiler/mlds_to_il.m:
compiler/mlds_to_java.m:
	Handle mlds__type_info_type.

compiler/mlds_to_gcc.m:
	Conform to the changed data structures for (pseudo-) typeinfos,
	and handle mlds__type_info_type.

runtime/mercury_bootstrap.h:
	Override the compiler-generated names of the type_ctor_infos of the
	variable arity type constructors. The MLDS backend requires these
	to be module qualified; the LLDS backend requires them to be
	unqualified. This is a problem because the same code now generates
	the compiler's internal representation of pseudo-typeinfos for both
	backends.

	The temporary solution is to have the compiler generate these names
	module qualified, and have these macros convert them to the unqualified
	form. (The long term solution should be to always module qualify
	everything, but doing that is for another change.)

runtime/mercury_type_info.h:
	Change the naming scheme from first order vs higher order to fixed
	arity vs variable arity.

library/construct.m:
library/deconstruct.m:
runtime/mercury.c:
runtime/mercury_construct.c:
runtime/mercury_deconstruct.c:
runtime/mercury_deep_copy_body.h:
runtime/mercury_make_type_info_body.h:
runtime/mercury_ml_expand_body.h:
runtime/mercury_tabling.c:
runtime/mercury_type_desc.c:
runtime/mercury_type_info.c:
runtime/mercury_unify_compare_body.h:
	Conform to the new naming scheme.

runtime/mercury.h:
	Conform to the new naming scheme.

	Declare fixed and variable arity types for typeinfos as well as
	pseudo-typeinfos, since pseudo-typeinfos can now refer to typeinfos.
2002-04-12 01:24:25 +00:00

327 lines
10 KiB
C

/*
** vim:ts=4 sw=4 expandtab
*/
/*
** Copyright (C) 2002 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_construct.c
**
** This file provides utility functions for constructing terms, for use by
** the standard library.
*/
#include "mercury_conf.h"
#ifndef MR_HIGHLEVEL_CODE
#include "mercury_imp.h"
#endif
#include "mercury_type_info.h"
#include "mercury_construct.h"
#include "mercury_misc.h" /* for MR_fatal_error() */
static int MR_get_functor_info(MR_TypeInfo type_info, int functor_number,
MR_Construct_Info *construct_info);
/*
** MR_get_functor_info:
**
** Extract the information for functor number `functor_number',
** for the type represented by type_info.
** We succeed if the type is some sort of discriminated union.
**
** You need to save and restore transient registers around
** calls to this function.
*/
static int
MR_get_functor_info(MR_TypeInfo type_info, int functor_number,
MR_Construct_Info *construct_info)
{
MR_TypeCtorInfo type_ctor_info;
type_ctor_info = MR_TYPEINFO_GET_TYPE_CTOR_INFO(type_info);
construct_info->type_ctor_rep = MR_type_ctor_rep(type_ctor_info);
switch(MR_type_ctor_rep(type_ctor_info)) {
case MR_TYPECTOR_REP_RESERVED_ADDR:
case MR_TYPECTOR_REP_RESERVED_ADDR_USEREQ:
case MR_TYPECTOR_REP_DU:
case MR_TYPECTOR_REP_DU_USEREQ:
{
MR_DuFunctorDesc *functor_desc;
if (functor_number < 0 ||
functor_number >= MR_type_ctor_num_functors(type_ctor_info))
{
MR_fatal_error("MR_get_functor_info: "
"du functor_number out of range");
}
functor_desc = MR_type_ctor_functors(type_ctor_info).
functors_du[functor_number];
construct_info->functor_info.du_functor_desc = functor_desc;
construct_info->functor_name = functor_desc->MR_du_functor_name;
construct_info->arity = functor_desc->MR_du_functor_orig_arity;
construct_info->arg_pseudo_type_infos =
functor_desc->MR_du_functor_arg_types;
construct_info->arg_names =
functor_desc->MR_du_functor_arg_names;
}
break;
case MR_TYPECTOR_REP_ENUM:
case MR_TYPECTOR_REP_ENUM_USEREQ:
{
MR_EnumFunctorDesc *functor_desc;
if (functor_number < 0 ||
functor_number >= MR_type_ctor_num_functors(type_ctor_info))
{
MR_fatal_error("MR_get_functor_info: "
"enum functor_number out of range");
}
functor_desc = MR_type_ctor_functors(type_ctor_info).
functors_enum[functor_number];
construct_info->functor_info.enum_functor_desc = functor_desc;
construct_info->functor_name = functor_desc->MR_enum_functor_name;
construct_info->arity = 0;
construct_info->arg_pseudo_type_infos = NULL;
construct_info->arg_names = NULL;
}
break;
case MR_TYPECTOR_REP_NOTAG:
case MR_TYPECTOR_REP_NOTAG_USEREQ:
case MR_TYPECTOR_REP_NOTAG_GROUND:
case MR_TYPECTOR_REP_NOTAG_GROUND_USEREQ:
{
MR_NotagFunctorDesc *functor_desc;
if (functor_number != 0) {
MR_fatal_error("MR_get_functor_info: "
"notag functor_number out of range");
}
functor_desc = MR_type_ctor_functors(type_ctor_info).functors_notag;
construct_info->functor_info.notag_functor_desc = functor_desc;
construct_info->functor_name = functor_desc->MR_notag_functor_name;
construct_info->arity = 1;
construct_info->arg_pseudo_type_infos =
&functor_desc->MR_notag_functor_arg_type;
construct_info->arg_names =
&functor_desc->MR_notag_functor_arg_name;
}
break;
case MR_TYPECTOR_REP_EQUIV_GROUND:
case MR_TYPECTOR_REP_EQUIV:
return MR_get_functor_info(
MR_create_type_info(
MR_TYPEINFO_GET_FIXED_ARITY_ARG_VECTOR(type_info),
MR_type_ctor_layout(type_ctor_info).layout_equiv),
functor_number, construct_info);
case MR_TYPECTOR_REP_TUPLE:
construct_info->functor_name = "{}";
construct_info->arity = MR_TYPEINFO_GET_VAR_ARITY_ARITY(type_info);
/* Tuple types don't have pseudo-type_infos for the functors. */
construct_info->arg_pseudo_type_infos = NULL;
construct_info->arg_names = NULL;
break;
case MR_TYPECTOR_REP_INT:
case MR_TYPECTOR_REP_CHAR:
case MR_TYPECTOR_REP_FLOAT:
case MR_TYPECTOR_REP_STRING:
case MR_TYPECTOR_REP_FUNC:
case MR_TYPECTOR_REP_PRED:
case MR_TYPECTOR_REP_VOID:
case MR_TYPECTOR_REP_C_POINTER:
case MR_TYPECTOR_REP_TYPEINFO:
case MR_TYPECTOR_REP_TYPECTORINFO:
case MR_TYPECTOR_REP_TYPEDESC:
case MR_TYPECTOR_REP_TYPECTORDESC:
case MR_TYPECTOR_REP_TYPECLASSINFO:
case MR_TYPECTOR_REP_BASETYPECLASSINFO:
case MR_TYPECTOR_REP_ARRAY:
case MR_TYPECTOR_REP_SUCCIP:
case MR_TYPECTOR_REP_HP:
case MR_TYPECTOR_REP_CURFR:
case MR_TYPECTOR_REP_MAXFR:
case MR_TYPECTOR_REP_REDOFR:
case MR_TYPECTOR_REP_REDOIP:
case MR_TYPECTOR_REP_TRAIL_PTR:
case MR_TYPECTOR_REP_TICKET:
return MR_FALSE;
case MR_TYPECTOR_REP_UNKNOWN:
default:
MR_fatal_error(":construct - unexpected type.");
}
return MR_TRUE;
}
/*
** MR_typecheck_arguments:
**
** Given a list of univs (`arg_list'), and a vector of
** type_infos (`arg_vector'), checks that they are all of the
** same type; if so, returns MR_TRUE, otherwise returns MR_FALSE;
** `arg_vector' may contain type variables, these
** will be filled in by the type arguments of `type_info'.
**
** Assumes the length of the list has already been checked.
**
** You need to save and restore transient registers around
** calls to this function.
*/
MR_bool
MR_typecheck_arguments(MR_TypeInfo type_info, int arity, MR_Word arg_list,
const MR_PseudoTypeInfo *arg_pseudo_type_infos)
{
MR_TypeInfo arg_type_info;
MR_TypeInfo list_arg_type_info;
int comp;
int i;
/* Type check list of arguments */
for (i = 0; i < arity; i++) {
if (MR_list_is_empty(arg_list)) {
return MR_FALSE;
}
list_arg_type_info = (MR_TypeInfo) MR_field(MR_UNIV_TAG,
MR_list_head(arg_list), MR_UNIV_OFFSET_FOR_TYPEINFO);
if (MR_TYPE_CTOR_INFO_IS_TUPLE(
MR_TYPEINFO_GET_TYPE_CTOR_INFO(type_info)))
{
arg_type_info =
MR_TYPEINFO_GET_VAR_ARITY_ARG_VECTOR(type_info)[i + 1];
} else {
arg_type_info = MR_create_type_info(
MR_TYPEINFO_GET_FIXED_ARITY_ARG_VECTOR(type_info),
arg_pseudo_type_infos[i]);
}
comp = MR_compare_type_info(list_arg_type_info, arg_type_info);
if (comp != MR_COMPARE_EQUAL) {
return MR_FALSE;
}
arg_list = MR_list_tail(arg_list);
}
/* List should now be empty */
return MR_list_is_empty(arg_list);
}
/*
** MR_get_functors_check_range:
**
** Check that functor_number is in range, and get the functor
** info if it is. Return MR_FALSE if it is out of range, or
** if MR_get_functor_info returns MR_FALSE, otherwise return MR_TRUE.
**
** You need to save and restore transient registers around
** calls to this function.
*/
MR_bool
MR_get_functors_check_range(int functor_number, MR_TypeInfo type_info,
MR_Construct_Info *construct_info)
{
/*
** Check range of functor_number, get functors
** vector
*/
return functor_number < MR_get_num_functors(type_info) &&
functor_number >= 0 &&
MR_get_functor_info(type_info, functor_number, construct_info);
}
/*
** MR_get_num_functors:
**
** Get the number of functors for a type. If it isn't a
** discriminated union, return -1.
**
** You need to save and restore transient registers around
** calls to this function.
*/
int
MR_get_num_functors(MR_TypeInfo type_info)
{
MR_TypeCtorInfo type_ctor_info;
MR_Integer functors;
type_ctor_info = MR_TYPEINFO_GET_TYPE_CTOR_INFO(type_info);
switch(MR_type_ctor_rep(type_ctor_info)) {
case MR_TYPECTOR_REP_DU:
case MR_TYPECTOR_REP_DU_USEREQ:
case MR_TYPECTOR_REP_RESERVED_ADDR:
case MR_TYPECTOR_REP_RESERVED_ADDR_USEREQ:
case MR_TYPECTOR_REP_ENUM:
case MR_TYPECTOR_REP_ENUM_USEREQ:
functors = MR_type_ctor_num_functors(type_ctor_info);
break;
case MR_TYPECTOR_REP_NOTAG:
case MR_TYPECTOR_REP_NOTAG_USEREQ:
case MR_TYPECTOR_REP_NOTAG_GROUND:
case MR_TYPECTOR_REP_NOTAG_GROUND_USEREQ:
case MR_TYPECTOR_REP_TUPLE:
functors = 1;
break;
case MR_TYPECTOR_REP_EQUIV_GROUND:
case MR_TYPECTOR_REP_EQUIV:
functors = MR_get_num_functors(
MR_create_type_info((MR_TypeInfo *) type_info,
MR_type_ctor_layout(type_ctor_info).layout_equiv));
break;
case MR_TYPECTOR_REP_INT:
case MR_TYPECTOR_REP_CHAR:
case MR_TYPECTOR_REP_FLOAT:
case MR_TYPECTOR_REP_STRING:
case MR_TYPECTOR_REP_FUNC:
case MR_TYPECTOR_REP_PRED:
case MR_TYPECTOR_REP_VOID:
case MR_TYPECTOR_REP_C_POINTER:
case MR_TYPECTOR_REP_TYPEINFO:
case MR_TYPECTOR_REP_TYPECTORINFO:
case MR_TYPECTOR_REP_TYPEDESC:
case MR_TYPECTOR_REP_TYPECTORDESC:
case MR_TYPECTOR_REP_TYPECLASSINFO:
case MR_TYPECTOR_REP_BASETYPECLASSINFO:
case MR_TYPECTOR_REP_ARRAY:
case MR_TYPECTOR_REP_SUCCIP:
case MR_TYPECTOR_REP_HP:
case MR_TYPECTOR_REP_CURFR:
case MR_TYPECTOR_REP_MAXFR:
case MR_TYPECTOR_REP_REDOFR:
case MR_TYPECTOR_REP_REDOIP:
case MR_TYPECTOR_REP_TRAIL_PTR:
case MR_TYPECTOR_REP_TICKET:
functors = -1;
break;
case MR_TYPECTOR_REP_UNKNOWN:
default:
MR_fatal_error("MR_get_num_functors: unknown type_ctor_rep");
}
return functors;
}