mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-17 06:47:17 +00:00
Move the RTTI-related parts of std_util.m to three new modules in the standard
Estimated hours taken: 8
Branches: main
Move the RTTI-related parts of std_util.m to three new modules in the standard
library, and (in the case of embedded C code) to new modules in the runtime.
The main reason for this is to allow a reorganization of some of the
RTTi-related functionality without breaking backward compatibility. However,
the new arrangement should also be easier to maintain.
Use a separate type_ctor_rep for functions, to distinguish them from predicates
for RTTI code. (At one point, I thought this could avoid the need for the
change to the initialization files mentioned below. It can't, but it is a good
idea in any case.)
library/std_util.m:
Remove the functionality moved to the new modules, and replace them
with type equivalences and forwarding code. There are no changes in
the meanings of the user-visible predicates, with two exceptions.
- First, the true, equivalence-expanded names of what used to be
std_util:type_desc and std_util:type_ctor_desc are now
type_desc:type_desc and type_desc: type_ctor_desc.
- Second, deconstructing a function term now yields
"<<function>>" instead of "<<predicate>>".
The intention is that the RTTI predicates in std_util.m will continue
to work in a backwards-compatible manner for the near future, i.e. as
the new modules are updated, the code in std_util will be updated to
maintain the same functionality, modulo improvements such as avoiding
unwanted exceptions. When the RTTI functionality in the other modules
has stabilised, the RTTI predicates in std_util.m should be marked
obsolete.
The exported but non-documented functionality of std_util has been
moved to one of the new modules without forwarding code, with one
of the moved predicates being turned into the function it should have
been in the first place.
library/construct.m:
library/deconstruct.m:
library/type_desc.m:
Three new modules for the code moved from std_util.m.
library/library.m:
compiler/modules.m:
Record the names of the three new library modules.
runtime/mercury.[ch]:
compiler/mlds_to_il.m:
Record that type_desc is now in type_desc.m, not std_util.m.
compiler/static_term.m:
Import the deconstruct module, since we are using its undocumented
facilities.
runtime/Mmakefile:
Mention the two new modules.
runtime/mercury_construct.[ch]:
runtime/mercury_type_desc.[ch]:
Two new modules holding the C functions that used to be in foreign_code
in std_util, now using MR_ instead of ML_ prefixes, and being more
consistent about indentation.
runtime/mercury_type_info.h:
Add a new type_ctor_rep for functions, separate from predicates.
(It reuses the EQUIV_VAR type_ctor_rep, which hasn't been used
in ages.)
Use type_ctor_reps to distinguish between the type_ctor_infos of
pred/0 and func/0. However, to create higher order typeinfos, we
still need to know the addresses of the type_ctor_infos for
pred/0 and func/0, and we still need to know the address of the
type_ctor_info for tuples to create typeinfos for tuples. Since
these three type_ctor_infos are defined in the library,
we cannot access them directly from the runtime. We therefore need
to access them indirectly in the usual manner, via address_of
variables initialized by mkinit-generated code.
library/builtin.m:
library/private_builtin.m:
library/rtti_implementation.m:
runtime/mercury.c:
runtime/mercury_mcpp.{h,cpp}:
java/TypeCtorRep.java:
Updates to accommondate the new function type_ctor_rep.
runtime/mercury_type_info.[ch]:
Add some functions from foreign_code in std_util that fit in best here.
runtime/mercury_ml_expand_body.h:
runtime/mercury_tabling.h:
runtime/mercury_unify_compare_body.h:
Delete the code for handling EQUIV_VAR, and add code for handling
functions.
runtime/mercury_init.h:
runtime/mercury_wrapper.[ch]:
Add three variables holding the address of the type_ctor_infos
representing functions, predicates and tuples.
util/mkinit.c:
Fill in these three variables.
tests/general/accumulator/construct.{m,exp}:
tests/general/accumulator/deconstruct.{m,exp}:
tests/hard_coded/construct.{m,exp}:
Rename these tests by adding a _test at the ends of their names,
in order to avoid collisions with the names of the new standard library
modules. The test cases have not changed, with the exception of the :-
module declaration of course.
tests/general/accumulator/Mmakefile:
tests/general/accumulator/INTRODUCED:
tests/hard_coded/Mmakefile:
Record the name changes.
tests/hard_coded/existential_float.exp:
Updated the expected output to reflect that deconstructions now print
"<<function>>" instead of "<<predicate>>" when appropriate.
tests/hard_coded/higher_order_type_manip.exp:
Updated the expected output to reflect the new name of what used to be
std_util:type_desc.
trace/mercury_trace_browse.c:
trace/mercury_trace_external.c:
trace/mercury_trace_help.c:
#include type_desc.h instead of std_util.h, since the C functions
we want to call are now defined there.
trace/mercury_trace_vars.c:
Update to account for the movement of type_desc from std_util to
type_desc, and ensure that we don't refer to any type_ctor_infos
in MLDS grades.
This commit is contained in:
321
runtime/mercury_construct.c
Normal file
321
runtime/mercury_construct.c
Normal file
@@ -0,0 +1,321 @@
|
||||
/*
|
||||
** 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_FIRST_ORDER_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_TUPLE_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_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 FALSE;
|
||||
|
||||
case MR_TYPECTOR_REP_UNKNOWN:
|
||||
default:
|
||||
MR_fatal_error(":construct - unexpected type.");
|
||||
}
|
||||
|
||||
return 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 TRUE, otherwise returns 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.
|
||||
*/
|
||||
|
||||
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 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_TUPLE_ARG_VECTOR(type_info)[i + 1];
|
||||
} else {
|
||||
arg_type_info = MR_create_type_info(
|
||||
MR_TYPEINFO_GET_FIRST_ORDER_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 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 FALSE if it is out of range, or
|
||||
** if MR_get_functor_info returns FALSE, otherwise return TRUE.
|
||||
**
|
||||
** You need to save and restore transient registers around
|
||||
** calls to this function.
|
||||
*/
|
||||
|
||||
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_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;
|
||||
}
|
||||
Reference in New Issue
Block a user