mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-17 14:57:03 +00:00
Estimated hours taken: 4
Branches: main
Provide a mechanism for declaring foreign types that can be operated on by
compare_representation. The intended use of the mechanism is to declare
a foreign type to represent proc_layouts in the declarative debugger,
as part of the representation of atoms; since atoms are keys in maps
in the oracle, they are input to compare_representation.
Since we don't want the result of compare_representation to change as
execution proceeds, we require an assertion that the foreign value is
stable, i.e. that the value of the foreign type variable completely
determines the data it points to, directly and indirectly. Proc_layouts
are static, so this is not a problem. Being able to do the comparison
requires the foreign type to be an integral type or a pointer, which
is what the existing can_pass_as_mercury_type assertion promises.
The stability is promised by a new assertion.
For foreign types that have both assertions, we use a new type_ctor_rep,
which differs from the existing type_ctor_rep for foreign types by doing
a real comparison instead of an abort in compare_representation.
doc/reference_manual.texi:
Document the new kind of assertion.
compiler/prog_data.m:
Add the new kind of assertion.
compiler/prog_io_pragma.m:
Parse the new kind of assertion.
compiler/rtti.m:
Add the representation of the new type_ctor_rep. Factor out the
stability of c_pointers as well as foreign types.
compiler/type_ctor_info.m:
Generate the new type_ctor_rep for types with both assertions.
compiler/foreign.m:
Export a predicate for use by type_ctor_info.m.
compiler/mercury_to_mercury.m:
Print the new assertion.
compiler/*.m:
Minor changes to conform to the diffs above.
Use state variable notation.
library/rtti_implementation.m:
Handle the new type_ctor_rep.
runtime/mercury_mcpp.h:
runtime/mercury_type_info.h:
java/runtime/TypeCtorRep.java:
Add the new type_ctor_rep to the runtime.
runtime/mercury_mcpp.h:
runtime/mercury_type_info.h:
compiler/type_ctor_info.m:
Increment the rtti version number.
When we rely on the availability of this new capability,
we should add a test for the new rtti version number to configure.in.
runtime/mercury_construct.c:
runtime/mercury_deconstruct.c:
runtime/mercury_ml_expand_body.h:
runtime/mercury_term_size.h:
Handle stable foreign types the same way as other foreign types.
runtime/mercury_deep_copy_body.h:
runtime/mercury_tabling.h:
runtime/mercury_unify_compare_body.h:
Handle stable foreign types in a useful manner, relying on the
assertions behind them.
tests/hard_coded/stable_foreign.{m,exp}:
A test case for the handling of values of a stable foreign type.
tests/hard_coded/Mmakefile:
Enable the new test case.
341 lines
11 KiB
C
341 lines
11 KiB
C
/*
|
|
** vim:ts=4 sw=4 expandtab
|
|
*/
|
|
/*
|
|
** Copyright (C) 2002-2004 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_univ.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);
|
|
|
|
if (! MR_type_ctor_has_valid_rep(type_ctor_info)) {
|
|
MR_fatal_error("MR_get_functor_info: term of unknown representation");
|
|
}
|
|
|
|
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:
|
|
{
|
|
const 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).
|
|
MR_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;
|
|
}
|
|
return MR_TRUE;
|
|
|
|
case MR_TYPECTOR_REP_ENUM:
|
|
case MR_TYPECTOR_REP_ENUM_USEREQ:
|
|
{
|
|
const 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).
|
|
MR_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;
|
|
}
|
|
return MR_TRUE;
|
|
|
|
case MR_TYPECTOR_REP_NOTAG:
|
|
case MR_TYPECTOR_REP_NOTAG_USEREQ:
|
|
case MR_TYPECTOR_REP_NOTAG_GROUND:
|
|
case MR_TYPECTOR_REP_NOTAG_GROUND_USEREQ:
|
|
{
|
|
const 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).
|
|
MR_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;
|
|
}
|
|
return MR_TRUE;
|
|
|
|
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).MR_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;
|
|
return MR_TRUE;
|
|
|
|
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_SUBGOAL:
|
|
case MR_TYPECTOR_REP_VOID:
|
|
case MR_TYPECTOR_REP_C_POINTER:
|
|
case MR_TYPECTOR_REP_STABLE_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:
|
|
case MR_TYPECTOR_REP_FOREIGN:
|
|
case MR_TYPECTOR_REP_STABLE_FOREIGN:
|
|
case MR_TYPECTOR_REP_REFERENCE:
|
|
return MR_FALSE;
|
|
|
|
case MR_TYPECTOR_REP_UNKNOWN:
|
|
MR_fatal_error("MR_get_functor_info: unknown type_ctor_rep");
|
|
}
|
|
|
|
MR_fatal_error("MR_get_functor_info: unexpected fallthrough");
|
|
}
|
|
|
|
/*
|
|
** 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 the 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);
|
|
|
|
if (! MR_type_ctor_has_valid_rep(type_ctor_info)) {
|
|
MR_fatal_error("MR_get_num_functors: term of unknown representation");
|
|
}
|
|
|
|
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:
|
|
return MR_type_ctor_num_functors(type_ctor_info);
|
|
|
|
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:
|
|
return 1;
|
|
|
|
case MR_TYPECTOR_REP_EQUIV_GROUND:
|
|
case MR_TYPECTOR_REP_EQUIV:
|
|
return MR_get_num_functors(
|
|
MR_create_type_info((MR_TypeInfo *) type_info,
|
|
MR_type_ctor_layout(type_ctor_info).MR_layout_equiv));
|
|
|
|
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_SUBGOAL:
|
|
case MR_TYPECTOR_REP_VOID:
|
|
case MR_TYPECTOR_REP_C_POINTER:
|
|
case MR_TYPECTOR_REP_STABLE_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:
|
|
case MR_TYPECTOR_REP_FOREIGN:
|
|
case MR_TYPECTOR_REP_STABLE_FOREIGN:
|
|
case MR_TYPECTOR_REP_REFERENCE:
|
|
return -1;
|
|
|
|
case MR_TYPECTOR_REP_UNKNOWN:
|
|
MR_fatal_error("MR_get_num_functors: unknown type_ctor_rep");
|
|
}
|
|
|
|
MR_fatal_error("MR_get_num_functors: unexpected fallthrough");
|
|
}
|