cvs diff: type_info code.
Tyson Richard DOWD
trd at hydra.cs.mu.oz.au
Fri Apr 18 16:55:59 AEST 1997
Hi,
Fergus, could you please review this?
===================================================================
Estimated hours taken: 50
Add the type `type_info', which represents the type of a variable.
Implement functions and predicates to deal with type_infos, including
finding what functors they have, getting the arity and type_infos of their
the arguments of a functor, and constructing types.
compiler/base_type_layout.m:
Document the constant used to represent the type ''.
Make sure enumeration vectors are output in the same order for
base_type_layouts and base_type_functors, so that we can
refer to functors by the same functor number.
library/mercury_builtin.m:
Add base_type_* for '', the unnamed type. '' is the type_info
used for unbound type_variables.
library/std_util.m:
Add
function type_of/1
function num_functors/1
predicate get_nth_functor/5
function construct/3
Use MR_DECLARE_STRUCT to declare base_type_* structs
for handwritten code, so less code needs to be changed if this
changes.
Rename `mercury_expand_info' as `Mercury_Expand_Info' (C coding
standard for typedefs).
runtime/type_info.h:
Add a bunch of macros to deal with the various type information
data structures. Eventually all the code that uses these data
strcutures should use these macros.
tests/hard_coded/Mmake:
Add `construct' to the test suite.
hard_coded/construct.m:
hard_coded/construct.exp:
Test of type_of, num_functors, get_nth_functor and construct.
Index: compiler/base_type_layout.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/base_type_layout.m,v
retrieving revision 1.15
diff -u -r1.15 base_type_layout.m
--- base_type_layout.m 1997/03/19 01:37:51 1.15
+++ base_type_layout.m 1997/04/14 04:21:04
@@ -61,7 +61,8 @@
% Tag 0 - CONST Word = 5 - character
% Tag 0 - CONST Word = 6 - univ
% Tag 0 - CONST Word = 7 - pred
-% Words 8 - 1024 reserved for future use
+% Tag 0 - CONST Word = 8 - '' (the unnamed type)
+% Words 9 - 1024 reserved for future use
% Tag 0 - CONST Word = 1024+ - constant(s)
% word is pointer to enum
% vector.
@@ -359,7 +360,7 @@
Enum = yes,
base_type_layout__layout_enum(SortedConsTags,
LayoutInfo1, LayoutInfo2, LayoutTypeData),
- base_type_layout__functors_enum(UnsortedConsTags,
+ base_type_layout__functors_enum(SortedConsTags,
LayoutInfo2, LayoutInfo3, FunctorsTypeData)
;
Enum = no,
Index: library/mercury_builtin.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/library/mercury_builtin.m,v
retrieving revision 1.68
diff -u -r1.68 mercury_builtin.m
--- mercury_builtin.m 1997/02/23 01:13:49 1.68
+++ mercury_builtin.m 1997/04/16 04:47:27
@@ -514,6 +514,15 @@
mkbody(TYPELAYOUT_PREDICATE_VALUE))
};
+ /* The unnamed type - '' */
+
+const struct mercury_data___base_type_layout__0_struct {
+ TYPE_LAYOUT_FIELDS
+} mercury_data___base_type_layout__0 = {
+ make_typelayout_for_all_tags(TYPELAYOUT_CONST_TAG,
+ mkbody(TYPELAYOUT_NO_NAME_VALUE))
+};
+
/* base_type_functors definitions */
const struct mercury_data___base_type_functors_int_0_struct {
@@ -546,6 +555,14 @@
MR_TYPEFUNCTORS_SPECIAL
};
+ /* The unnamed type - '' */
+
+const struct mercury_data___base_type_functors__0_struct {
+ Integer f1;
+} mercury_data___base_type_functors__0 = {
+ MR_TYPEFUNCTORS_SPECIAL
+};
+
#endif /* USE_TYPE_LAYOUT */
Declare_entry(mercury__builtin_unify_int_2_0);
@@ -727,6 +744,38 @@
(const Word *) & mercury_data___base_type_layout_pred_0,
(const Word *) & mercury_data___base_type_functors_pred_0,
(const Word *) string_const(""pred"", 4)
+#endif
+};
+
+ /* The unnamed type - '' */
+
+MR_STATIC_CODE_CONST struct mercury_data___base_type_info__0_struct {
+ Integer f1;
+ Code *f2;
+ Code *f3;
+ Code *f4;
+#ifdef USE_TYPE_TO_TERM
+ Code *f5;
+ Code *f6;
+#endif
+#ifdef USE_TYPE_LAYOUT
+ const Word *f7;
+ const Word *f8;
+ const Word *f9;
+#endif
+} mercury_data___base_type_info__0 = {
+ ((Integer) 0),
+ MR_MAYBE_STATIC_CODE(ENTRY(mercury__unused_0_0)),
+ MR_MAYBE_STATIC_CODE(ENTRY(mercury__unused_0_0)),
+ MR_MAYBE_STATIC_CODE(ENTRY(mercury__unused_0_0)),
+#ifdef USE_TYPE_TO_TERM
+ MR_MAYBE_STATIC_CODE(ENTRY(mercury__unused_0_0)),
+ MR_MAYBE_STATIC_CODE(ENTRY(mercury__unused_0_0))
+#endif
+#ifdef USE_TYPE_LAYOUT
+ (const Word *) & mercury_data___base_type_layout__0,
+ (const Word *) & mercury_data___base_type_functors__0,
+ (const Word *) string_const("""", 4)
#endif
};
Index: library/std_util.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/library/std_util.m,v
retrieving revision 1.75
diff -u -r1.75 std_util.m
--- std_util.m 1997/03/14 05:22:45 1.75
+++ std_util.m 1997/04/16 04:23:47
@@ -113,7 +113,60 @@
%-----------------------------------------------------------------------------%
- % functor, arg and expand take any type (including univ),
+ % The `type_info' type - allows access to type information.
+ %
+ % A type_info represents the type of a variable.
+ %
+ % It is possible for the type of a variable to be an unbound type
+ % variable, this is represented as the unnamed type ''. The
+ % unnamed type '' is considered a special (builtin) type - it is
+ % not a discriminated union, so get_nth_functor/5 and the
+ % function construct/3 will fail if used upon this type.
+
+:- type type_info == c_pointer.
+
+ % TypeInfo = type_info(Data) returns the type_info (TypeInfo) of
+ % the type of Data.
+
+:- func type_of(T) = type_info.
+:- mode type_of(unused) = out is det.
+
+ % num_functors(TypeInfo) returns the number of different
+ %
+ % Functors for the type specified by TypeInfo, or -1 if the type
+ % is not a discriminated union type.
+
+:- func num_functors(type_info) = int.
+:- mode num_functors(in) = out is det.
+
+ % get_nth_functor(Var, N, Functor, Arity, ArgTypes)
+ %
+ % Binds Functor and Arity to the name and arity of the Nth
+ % functor for the specified type, and binds ArgTypes to the
+ % type_infos for the types of the arguments of that functor.
+ % Fails if the type is not a discriminated union type,
+ % or if N is out of range.
+
+:- pred get_nth_functor(type_info::in, int::in, string::out, int::out,
+ list(type_info)::out) is semidet.
+
+ % construct(TypeInfo, N, Args) = Term
+ %
+ % Returns a term of the type specified by TypeInfo (or possibly
+ % an instance thereof, if that type is polymorphic) whose
+ % functor is the Nth functor of TypeInfo, and whose arguments
+ % are given by Args. Fails if the type is not a discriminated
+ % union type, or if N is out of range, or if the number of
+ % arguments doesn't match the arity of the Nth functor of the
+ % type, or if the types of the arguments doesn't match the
+ % expected argument types for that functor.
+
+:- func construct(type_info::in, int::in, list(univ)::in) = (univ::out)
+ is semidet.
+
+%-----------------------------------------------------------------------------%
+
+ % functor, arg and expand take any type (including univ),
% and return representation information for that type.
%
% The string representation of the functor that functor and
@@ -210,9 +263,8 @@
#include ""imp.h""
#include ""deep_copy.h""
-extern const struct
- mercury_data_mercury_builtin__base_type_info_list_1_struct
- mercury_data_mercury_builtin__base_type_info_list_1;
+MR_DECLARE_BASE_TYPE_STRUCT(
+ mercury_data_mercury_builtin__base_type_info_list_1);
Declare_entry(do_call_nondet_closure);
@@ -490,9 +542,7 @@
** the case of higher order types, the arity).
*/
-extern const struct
- mercury_data___base_type_info_pred_0_struct
- mercury_data___base_type_info_pred_0;
+MR_DECLARE_BASE_TYPE_STRUCT(mercury_data___base_type_info_pred_0);
int
mercury_compare_type_info(Word type_info_1, Word type_info_2)
@@ -843,6 +893,553 @@
%-----------------------------------------------------------------------------%
+ % Code for type manipulation.
+
+
+ % Prototypes and type definitions.
+
+:- pragma(c_header_code, "
+
+typedef struct mercury_construct_info {
+ int vector_type;
+ int arity;
+ Word *functors_vector;
+ Word *argument_vector;
+ Word primary_tag;
+ Word secondary_tag;
+ ConstString functor_name;
+} construct_info;
+
+static int get_num_functors(Word type_info);
+static Word copy_argument_typeinfos(int arity, Word type_info,
+ Word *arg_vector);
+static bool get_functors_check_range(int functor_number, Word type_info,
+ construct_info *info);
+static void copy_arguments_from_list_to_vector(int arity, Word arg_list,
+ Word term_vector);
+static int typecheck_arguments(Word type_info, int arity,
+ Word arg_list, Word* arg_vector);
+static int get_functor_info(Word type_info, int functor_number,
+ construct_info *info);
+static Word collapse_equivalences(Word maybe_equiv_type_info);
+").
+
+
+:- pragma c_code(type_of(Type::unused) = (TypeInfo::out),
+ will_not_call_mercury, "
+{
+ /*
+ ** Type isn't used in this c_code, but the compiler
+ ** gives a warning if you don't mention it.
+ */
+
+ save_transient_registers();
+ TypeInfo = collapse_equivalences(TypeInfo_for_T);
+ restore_transient_registers();
+
+}
+").
+
+
+:- pragma c_code(num_functors(TypeInfo::in) = (Functors::out),
+ will_not_call_mercury, "
+{
+ save_transient_registers();
+ Functors = get_num_functors(TypeInfo);
+ restore_transient_registers();
+}
+").
+
+
+:- pragma c_code(get_nth_functor(TypeInfo::in, FunctorNumber::in,
+ FunctorName::out, Arity::out, TypeInfoList::out),
+ will_not_call_mercury, "
+{
+ int i;
+ construct_info info;
+
+ /*
+ ** Get information for this functor number and
+ ** store in info. If this is a discriminated union
+ ** type and if the functor number is in range, we
+ ** succeed.
+ */
+ save_transient_registers();
+ SUCCESS_INDICATOR = get_functors_check_range(FunctorNumber, TypeInfo,
+ &info);
+ restore_transient_registers();
+
+ /*
+ ** Get the functor name and arity, construct the list
+ ** of type_infos for arguments.
+ */
+
+ if (SUCCESS_INDICATOR) {
+ make_aligned_string(FunctorName, (String) (Word)
+ info.functor_name);
+ Arity = info.arity;
+ save_transient_registers();
+ TypeInfoList = copy_argument_typeinfos((int) Arity, TypeInfo,
+ info.argument_vector);
+ restore_transient_registers();
+ }
+
+}
+").
+
+:- pragma c_code(construct(TypeInfo::in, FunctorNumber::in, ArgList::in) =
+ (Term::out), will_not_call_mercury, "
+{
+ Word arg_list, arg_type_info, layout_entry, new_data,
+ term_vector, list_arg_type_info;
+ int i;
+ construct_info info;
+
+ /*
+ ** Check range of FunctorNum, get info for this
+ ** functor.
+ */
+ save_transient_registers();
+ SUCCESS_INDICATOR = get_functors_check_range(FunctorNumber,
+ TypeInfo, &info);
+ restore_transient_registers();
+
+ /*
+ ** Type check list of arguments
+ */
+
+ if (SUCCESS_INDICATOR) {
+ save_transient_registers();
+ SUCCESS_INDICATOR = typecheck_arguments(TypeInfo, info.arity,
+ ArgList, info.argument_vector);
+ restore_transient_registers();
+ }
+
+ /*
+ ** Build the new term.
+ **
+ ** It will be stored in `new_data', and `term_vector' is a
+ ** the argument vector.
+ **
+ */
+ if (SUCCESS_INDICATOR) {
+
+ layout_entry = MR_BASE_TYPEINFO_GET_TYPELAYOUT_ENTRY(
+ MR_TYPEINFO_GET_BASE_TYPEINFO((Word *) TypeInfo),
+ info.primary_tag);
+
+ if (info.vector_type == MR_TYPEFUNCTORS_ENUM) {
+ /*
+ ** Enumeratiors don't have tags or arguments,
+ ** just the enumeration value.
+ */
+ new_data = (Word) info.secondary_tag;
+ } else {
+ /*
+ ** It must be some sort of tagged functor.
+ */
+
+ if (info.vector_type == MR_TYPEFUNCTORS_NO_TAG) {
+
+ /*
+ ** We set term_vector to point to
+ ** new_data so that the argument filling
+ ** loop will fill the argument in.
+ */
+
+ term_vector = (Word) &new_data;
+
+ } else if (tag(layout_entry) ==
+ TYPELAYOUT_COMPLICATED_TAG) {
+
+ /*
+ ** Create arity + 1 words, fill in the
+ ** secondary tag, and the term_vector will
+ ** be the rest of the words.
+ */
+ incr_hp(new_data, info.arity + 1);
+ field(0, new_data, 0) = info.secondary_tag;
+ term_vector = (Word) (new_data + sizeof(Word));
+
+ } else if (tag(layout_entry) == TYPELAYOUT_CONST_TAG) {
+
+ /*
+ ** If it's a du, and this tag is
+ ** constant, it must be a complicated
+ ** constant tag.
+ */
+
+ new_data = mkbody(info.secondary_tag);
+ term_vector = (Word) NULL;
+
+ } else {
+
+ /*
+ ** A simple tagged word, just need to
+ ** create arguments.
+ */
+
+ incr_hp(new_data, info.arity);
+ term_vector = (Word) new_data;
+ }
+
+ /*
+ ** Copy arguments.
+ */
+
+ copy_arguments_from_list_to_vector(info.arity, ArgList,
+ term_vector);
+
+ /*
+ ** Add tag to new_data.
+ */
+ new_data = (Word) mkword(mktag(info.primary_tag),
+ new_data);
+ }
+
+ /*
+ ** Create a univ.
+ */
+
+ incr_hp(Term, 2);
+ field(mktag(0), Term, UNIV_OFFSET_FOR_TYPEINFO) =
+ (Word) TypeInfo;
+ field(mktag(0), Term, UNIV_OFFSET_FOR_DATA) = (Word) new_data;
+ }
+
+}
+").
+
+:- pragma(c_code, "
+
+ /*
+ ** 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.
+ */
+
+int
+get_functor_info(Word type_info, int functor_number, construct_info *info)
+{
+ Word *base_type_functors;
+
+ base_type_functors = MR_BASE_TYPEINFO_GET_TYPEFUNCTORS(
+ MR_TYPEINFO_GET_BASE_TYPEINFO((Word *) type_info));
+
+ info->vector_type = MR_TYPEFUNCTORS_INDICATOR(base_type_functors);
+
+ switch (info->vector_type) {
+
+ case MR_TYPEFUNCTORS_ENUM:
+ info->functors_vector = MR_TYPEFUNCTORS_ENUM_FUNCTORS(
+ base_type_functors);
+ info->arity = 0;
+ info->argument_vector = NULL;
+ info->primary_tag = 0;
+ info->secondary_tag = functor_number - 1;
+ info->functor_name = MR_TYPELAYOUT_ENUM_VECTOR_FUNCTOR_NAME(
+ info->functors_vector, functor_number);
+ break;
+
+ case MR_TYPEFUNCTORS_DU:
+ info->functors_vector = MR_TYPEFUNCTORS_DU_FUNCTOR_N(
+ base_type_functors, functor_number);
+ info->arity = MR_TYPELAYOUT_SIMPLE_VECTOR_ARITY(
+ info->functors_vector);
+ info->argument_vector = MR_TYPELAYOUT_SIMPLE_VECTOR_ARGS(
+ info->functors_vector);
+ info->primary_tag = tag(MR_TYPELAYOUT_SIMPLE_VECTOR_TAG(
+ info->functors_vector));
+ info->secondary_tag = unmkbody(
+ body(MR_TYPELAYOUT_SIMPLE_VECTOR_TAG(
+ info->functors_vector), info->primary_tag));
+ info->functor_name = MR_TYPELAYOUT_SIMPLE_VECTOR_FUNCTOR_NAME(
+ info->functors_vector);
+ break;
+
+ case MR_TYPEFUNCTORS_NO_TAG:
+ info->functors_vector = MR_TYPEFUNCTORS_NO_TAG_FUNCTOR(
+ base_type_functors);
+ info->arity = 1;
+ info->argument_vector = MR_TYPELAYOUT_NO_TAG_VECTOR_ARGS(
+ info->functors_vector);
+ info->primary_tag = 0;
+ info->secondary_tag = 0;
+ info->functor_name = MR_TYPELAYOUT_NO_TAG_VECTOR_FUNCTOR_NAME(
+ info->functors_vector);
+ break;
+
+ case MR_TYPEFUNCTORS_EQUIV:
+ {
+ Word *equiv_type;
+ equiv_type = (Word *) MR_TYPEFUNCTORS_EQUIV_TYPE(
+ base_type_functors);
+ return get_functor_info((Word)
+ create_type_info((Word *) type_info,
+ equiv_type),
+ functor_number, info);
+ }
+ break;
+
+ case MR_TYPEFUNCTORS_SPECIAL:
+ return FALSE;
+ case MR_TYPEFUNCTORS_UNIV:
+ return FALSE;
+ default:
+ fatal_error(""std_util:construct - unexpected type."");
+ }
+
+ return TRUE;
+}
+
+ /*
+ ** typecheck_arguments:
+ **
+ ** Given a list of univs (`arg_list'), and an vector of
+ ** type_infos (`arg_vector'), checks that they are all of the
+ ** same type. `arg_vector' may contain type variables, these
+ ** will be filled in by the type arguments of `type_info' -
+ ** a 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.
+ */
+
+int
+typecheck_arguments(Word type_info, int arity, Word arg_list, Word* arg_vector)
+{
+ int i, success;
+ Word arg_type_info, list_arg_type_info;
+
+ success = TRUE;
+
+ /* Type check list of arguments */
+
+ for (i = 0; success && i < arity; i++) {
+ if (list_is_empty(arg_list)) {
+ success = FALSE;
+ break;
+ }
+ list_arg_type_info = field(0, (list_head(arg_list)),
+ UNIV_OFFSET_FOR_TYPEINFO);
+
+ arg_type_info = (Word) create_type_info(
+ (Word *) type_info, (Word *) arg_vector[i]);
+
+ success = (mercury_compare_type_info(
+ list_arg_type_info, arg_type_info) == COMPARE_EQUAL);
+ arg_list = list_tail(arg_list);
+ }
+
+ /* List should now be empty */
+ if (!list_is_empty(arg_list)) {
+ success = FALSE;
+ }
+
+ return success;
+}
+
+ /*
+ ** copy_arguments_from_list_to_vector:
+ **
+ ** Copy the arguments from a list of univs (`arg_list'),
+ ** into the vector (`term_vector').
+ **
+ ** Assumes the length of the list has already been checked.
+ */
+
+void
+copy_arguments_from_list_to_vector(int arity, Word arg_list, Word term_vector)
+{
+ int i;
+
+ for (i = 0; i < arity; i++) {
+ field(mktag(0), term_vector, i) =
+ field(0, list_head(arg_list), UNIV_OFFSET_FOR_DATA);
+ arg_list = list_tail(arg_list);
+ }
+}
+
+
+ /*
+ ** 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 get_functor_info returns FALSE, otherwise return TRUE.
+ **
+ ** You need to save and restore transient registers around
+ ** calls to this function.
+ */
+
+bool
+get_functors_check_range(int functor_number, Word type_info,
+ construct_info *info)
+{
+ bool success;
+
+ /* Check range of functor_number */
+ success = (functor_number <= get_num_functors(type_info)
+ && functor_number > 0);
+
+ /* Get functors vector, check for specials */
+ if (success) {
+ success = get_functor_info(type_info, functor_number, info);
+ }
+ return success;
+}
+
+
+ /*
+ ** copy_argument_typeinfos:
+ **
+ ** Copy `arity' type_infos from `arg_vector' onto the heap
+ ** in a list.
+ **
+ ** You need to save and restore transient registers around
+ ** calls to this function.
+ */
+
+Word
+copy_argument_typeinfos(int arity, Word type_info, Word *arg_vector)
+{
+ Word type_info_list, *functors;
+
+ type_info_list = list_empty();
+
+ restore_transient_registers();
+ while (--arity >= 0) {
+ Word argument;
+
+ /* Get the argument type_info */
+ argument = arg_vector[arity];
+
+ /* Fill in any polymorphic type_infos */
+ save_transient_registers();
+ argument = (Word) create_type_info(
+ (Word *) type_info, (Word *) argument);
+ restore_transient_registers();
+
+ /* Look past any equivalences */
+ save_transient_registers();
+ argument = collapse_equivalences(argument);
+ restore_transient_registers();
+
+ /* Join the argument to the front of the list */
+ type_info_list = list_cons(argument, type_info_list);
+ }
+ save_transient_registers();
+
+ return type_info_list;
+}
+
+ /*
+ ** collapse_equivalences:
+ **
+ ** Keep looking past equivalences until the there are no more.
+ **
+ ** You need to save and restore transient registers around
+ ** calls to this function.
+ */
+
+Word
+collapse_equivalences(Word maybe_equiv_type_info)
+{
+ Word *functors, equiv_type_info;
+
+ functors = MR_BASE_TYPEINFO_GET_TYPEFUNCTORS(
+ MR_TYPEINFO_GET_BASE_TYPEINFO((Word *)
+ maybe_equiv_type_info));
+
+ /* Look past equivalences */
+ while (MR_TYPEFUNCTORS_INDICATOR(functors) == MR_TYPEFUNCTORS_EQUIV) {
+ equiv_type_info = (Word) MR_TYPEFUNCTORS_EQUIV_TYPE(functors);
+ equiv_type_info = (Word) create_type_info(
+ (Word *) maybe_equiv_type_info,
+ (Word *) equiv_type_info);
+ functors = MR_BASE_TYPEINFO_GET_TYPEFUNCTORS(
+ MR_TYPEINFO_GET_BASE_TYPEINFO((Word *)
+ equiv_type_info));
+ maybe_equiv_type_info = equiv_type_info;
+ }
+
+ return maybe_equiv_type_info;
+}
+
+ /*
+ ** 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
+get_num_functors(Word type_info)
+{
+ Word *base_type_functors;
+ int Functors;
+
+ base_type_functors = MR_BASE_TYPEINFO_GET_TYPEFUNCTORS(
+ MR_TYPEINFO_GET_BASE_TYPEINFO((Word *) type_info));
+
+ switch ((int) MR_TYPEFUNCTORS_INDICATOR(base_type_functors)) {
+
+ case MR_TYPEFUNCTORS_DU:
+ Functors = MR_TYPEFUNCTORS_DU_NUM_FUNCTORS(
+ base_type_functors);
+ break;
+
+ case MR_TYPEFUNCTORS_ENUM:
+ Functors = MR_TYPEFUNCTORS_ENUM_NUM_FUNCTORS(
+ base_type_functors);
+ break;
+
+ case MR_TYPEFUNCTORS_EQUIV:
+ {
+ Word *equiv_type;
+ equiv_type = (Word *) MR_TYPEFUNCTORS_EQUIV_TYPE(
+ base_type_functors);
+ Functors = get_num_functors((Word)
+ create_type_info((Word *) type_info,
+ equiv_type));
+ }
+ break;
+
+ case MR_TYPEFUNCTORS_SPECIAL:
+ Functors = -1;
+ break;
+
+ case MR_TYPEFUNCTORS_NO_TAG:
+ Functors = 1;
+ break;
+
+ case MR_TYPEFUNCTORS_UNIV:
+ fatal_error(""std_util:get_num_functors :""
+ "" found univ"");
+ break;
+
+ default:
+ fatal_error(""std_util:get_num_functors :""
+ "" unknown indicator"");
+ }
+ return Functors;
+}
+
+").
+
+%-----------------------------------------------------------------------------%
+
+
:- pragma(c_header_code, "
/*
@@ -870,31 +1467,30 @@
*/
-typedef struct mercury_expand_info {
+typedef struct Mercury_Expand_Info {
ConstString functor;
int arity;
Word *argument_vector;
Word *type_info_vector;
bool need_functor;
bool need_args;
-} expand_info;
+} Expand_Info;
/* Prototypes */
-void mercury_expand(Word* type_info, Word data_word, expand_info *info);
+void mercury_expand(Word* type_info, Word data_word, Expand_Info *info);
static void mercury_expand_const(Word data_value, Word entry_value,
- expand_info *info);
+ Expand_Info *info);
static void mercury_expand_enum(Word data_value, Word entry_value,
- expand_info *info);
+ Expand_Info *info);
static void mercury_expand_simple(Word data_value, Word* arg_type_infos,
- Word * type_info, expand_info *info);
+ Word * type_info, Expand_Info *info);
static void mercury_expand_builtin(Word data_value, Word entry_value,
- expand_info *info);
+ Expand_Info *info);
static void mercury_expand_complicated(Word data_value, Word entry_value,
- Word * type_info, expand_info *info);
-
+ Word * type_info, Expand_Info *info);
static Word * create_type_info(Word *term_type_info,
Word *arg_pseudo_type_info);
@@ -927,7 +1523,7 @@
*/
void
-mercury_expand(Word* type_info, Word data_word, expand_info *info)
+mercury_expand(Word* type_info, Word data_word, Expand_Info *info)
{
Word *base_type_info, *arg_type_info, *base_type_layout;
Word data_value, entry_value, base_type_layout_entry;
@@ -1035,7 +1631,7 @@
*/
void
-mercury_expand_const(Word data_value, Word entry_value, expand_info *info)
+mercury_expand_const(Word data_value, Word entry_value, Expand_Info *info)
{
#ifdef DEBUG_STD_UTIL__EXPAND
@@ -1060,7 +1656,7 @@
*/
void
-mercury_expand_enum(Word data_value, Word entry_value, expand_info *info)
+mercury_expand_enum(Word data_value, Word entry_value, Expand_Info *info)
{
#ifdef DEBUG_STD_UTIL__EXPAND
@@ -1093,7 +1689,7 @@
*/
void
mercury_expand_simple(Word data_value, Word* arg_type_infos, Word * type_info,
- expand_info *info)
+ Expand_Info *info)
{
int i;
@@ -1136,7 +1732,7 @@
void
mercury_expand_complicated(Word data_value, Word entry_value, Word * type_info,
- expand_info *info)
+ Expand_Info *info)
{
Word new_data_value, new_entry_value, new_entry_body,
new_entry_tag, secondary_tag;
@@ -1158,7 +1754,7 @@
}
void
-mercury_expand_builtin(Word data_value, Word entry_value, expand_info *info)
+mercury_expand_builtin(Word data_value, Word entry_value, Expand_Info *info)
{
switch ((int) entry_value) {
@@ -1279,6 +1875,10 @@
*
* This returns a fully instantiated type_info, a version of the
* arg_pseudo_type_info with all the type variables filled in.
+ * If the substituted type parameters from the term_type_info
+ * were type variables, they will be replaced with references
+ * to the unnamed type (''/0).
+ *
* We allocate memory for a new type_info on the Mercury heap,
* copy the necessary information, and return a pointer to the
* new type_info.
@@ -1297,38 +1897,56 @@
* instead of on the heap.
*/
-Word * create_type_info(Word *term_type_info, Word *arg_pseudo_type_info)
+MR_DECLARE_BASE_TYPE_STRUCT(mercury_data___base_type_info__0);
+
+Word *
+create_type_info(Word *term_type_info, Word *arg_pseudo_type_info)
{
int i, arity;
Word base_type_info;
Word *type_info;
- /* The arg_pseudo_type_info might be a polymorphic variable */
+ /*
+ ** The arg_pseudo_type_info might be a polymorphic variable,
+ ** if so - substitute.
+ */
if ((Word) arg_pseudo_type_info < TYPELAYOUT_MAX_VARINT) {
arg_pseudo_type_info = (Word *)
term_type_info[(Word) arg_pseudo_type_info];
}
+ /*
+ ** If it's still a variable, make it a reference to the
+ ** unnamed type, ''
+ */
+ if ((Word) arg_pseudo_type_info < TYPELAYOUT_MAX_VARINT) {
+ return (Word *) (Word) &mercury_data___base_type_info__0;
+ }
+
base_type_info = arg_pseudo_type_info[0];
/* no arguments - optimise common case */
if (base_type_info == 0) {
-
- /* The only case where we don't allocate memory */
return arg_pseudo_type_info;
}
- arity = ((Word *) base_type_info)[0];
+ arity = MR_BASE_TYPEINFO_GET_TYPE_ARITY(base_type_info);
incr_saved_hp(LVALUE_CAST(Word, type_info), arity + 1);
for (i = 0; i <= arity; i++) {
if (arg_pseudo_type_info[i] < TYPELAYOUT_MAX_VARINT) {
type_info[i] = term_type_info[arg_pseudo_type_info[i]];
+
+ /* It's a variable, make it a reference to the
+ ** unnamed type, ''
+ */
if (type_info[i] < TYPELAYOUT_MAX_VARINT) {
- fatal_error(""Error! Can't instantiate type variable."");
+ type_info[i] = (Word)
+ &mercury_data___base_type_info__0;
}
+
} else {
type_info[i] = arg_pseudo_type_info[i];
}
@@ -1344,7 +1962,7 @@
:- pragma(c_code, functor(Type::in, Functor::out, Arity::out), "
{
- expand_info info;
+ Expand_Info info;
info.need_functor = TRUE;
info.need_args = FALSE;
@@ -1364,7 +1982,7 @@
:- pragma(c_code, arg(ArgumentIndex::in, Type::in, Argument::out), "
{
- expand_info info;
+ Expand_Info info;
Word arg_pseudo_type_info;
info.need_functor = FALSE;
@@ -1415,7 +2033,7 @@
:- pragma(c_code, expand(Type::in, Functor::out, Arity::out, Arguments::out), "
{
- expand_info info;
+ Expand_Info info;
Word arg_pseudo_type_info;
Word Argument, tmp;
int i;
Index: runtime/type_info.h
===================================================================
RCS file: /home/staff/zs/imp/mercury/runtime/type_info.h,v
retrieving revision 1.21
diff -u -r1.21 type_info.h
--- type_info.h 1997/03/04 04:22:40 1.21
+++ type_info.h 1997/04/16 05:00:55
@@ -225,6 +225,13 @@
#endif
/*
+** Declaration for base_type_* structs.
+*/
+
+#define MR_DECLARE_BASE_TYPE_STRUCT(BTS) \
+ extern const struct BTS##_struct BTS
+
+/*
** Typelayouts for builtins are often defined as X identical
** values, where X is the number of possible tag values.
*/
@@ -295,6 +302,7 @@
#define TYPELAYOUT_CHARACTER_VALUE ((Integer) 5)
#define TYPELAYOUT_UNIV_VALUE ((Integer) 6)
#define TYPELAYOUT_PREDICATE_VALUE ((Integer) 7)
+#define TYPELAYOUT_NO_NAME_VALUE ((Integer) 8)
/*
** Highest allowed type variable number
@@ -463,12 +471,233 @@
** base_type_functors.
*/
+/*
+** All type_functors have an indicator.
+*/
+
+#define MR_TYPEFUNCTORS_OFFSET_FOR_INDICATOR ((Integer) 0)
+
+#define MR_TYPEFUNCTORS_INDICATOR(Functors) \
+ ((Functors)[MR_TYPEFUNCTORS_OFFSET_FOR_INDICATOR])
+
+
+/*
+** Values that the indicator can take.
+*/
+
#define MR_TYPEFUNCTORS_DU ((Integer) 0)
#define MR_TYPEFUNCTORS_ENUM ((Integer) 1)
#define MR_TYPEFUNCTORS_EQUIV ((Integer) 2)
#define MR_TYPEFUNCTORS_SPECIAL ((Integer) 3)
#define MR_TYPEFUNCTORS_NO_TAG ((Integer) 4)
#define MR_TYPEFUNCTORS_UNIV ((Integer) 5)
+
+
+ /*
+ ** Macros to access the data in a discriminated union
+ ** type_functors, the number of functors, and the simple_vector
+ ** for functor number N (where N starts at 1).
+ */
+
+#define MR_TYPEFUNCTORS_DU_OFFSET_FOR_NUM_FUNCTORS ((Integer) 1)
+#define MR_TYPEFUNCTORS_DU_OFFSET_FOR_FUNCTORS_VECTOR ((Integer) 2)
+
+#define MR_TYPEFUNCTORS_DU_NUM_FUNCTORS(Functors) \
+ ((Functors)[MR_TYPEFUNCTORS_DU_OFFSET_FOR_NUM_FUNCTORS])
+
+#define MR_TYPEFUNCTORS_DU_FUNCTOR_N(Functor, N) \
+ ((Word *) ((Functor)[ \
+ MR_TYPEFUNCTORS_DU_OFFSET_FOR_FUNCTORS_VECTOR + (N) - 1]))
+
+ /*
+ ** Macros to access the data in a enumeration type_functors, the
+ ** number of functors, and the enumeration vector.
+ */
+
+#define MR_TYPEFUNCTORS_ENUM_OFFSET_FOR_FUNCTORS_VECTOR ((Integer) 1)
+
+#define MR_TYPEFUNCTORS_ENUM_NUM_FUNCTORS(Functors) \
+ MR_TYPELAYOUT_ENUM_VECTOR_NUM_FUNCTORS( \
+ MR_TYPEFUNCTORS_ENUM_FUNCTORS((Functors)))
+
+#define MR_TYPEFUNCTORS_ENUM_FUNCTORS(Functor) \
+ ((Word *) ((Functor)[MR_TYPEFUNCTORS_ENUM_OFFSET_FOR_FUNCTORS_VECTOR]))
+
+ /*
+ ** Macros to access the data in a no_tag type_functors, the
+ ** simple_vector for the functor (there can only be one functor
+ ** with no_tags).
+ */
+
+#define MR_TYPEFUNCTORS_NO_TAG_OFFSET_FOR_FUNCTORS_VECTOR ((Integer) 1)
+
+#define MR_TYPEFUNCTORS_NO_TAG_FUNCTOR(Functors) \
+ ((Word *) ((Functors) \
+ [MR_TYPEFUNCTORS_NO_TAG_OFFSET_FOR_FUNCTORS_VECTOR]))
+
+ /*
+ ** Macros to access the data in an equivalence type_functors,
+ ** the equivalent type of this type.
+ */
+
+#define MR_TYPEFUNCTORS_EQUIV_OFFSET_FOR_TYPE ((Integer) 1)
+
+#define MR_TYPEFUNCTORS_EQUIV_TYPE(Functors) \
+ ((Functors)[MR_TYPEFUNCTORS_EQUIV_OFFSET_FOR_TYPE])
+
+/*---------------------------------------------------------------------------*/
+
+/*
+** Macros and defintions for defining and dealing with the vectors
+** created by base_type_layouts (these are the same vectors referred to
+** by base_type_functors)
+** - the simple_vector, describing a single functor
+** - the enum_vector, describing an enumeration
+** - the no_tag_vector, describing a single functor
+*/
+
+ /*
+ ** Macros for dealing with enum vectors.
+ */
+
+typedef struct {
+ Word enum_or_comp_const;
+ Word num_sharers;
+ ConstString functor1;
+/* other functors follow, num_sharers of them.
+** ConstString functor2;
+** ...
+*/
+} MR_TypeLayout_EnumVector;
+
+#define MR_TYPELAYOUT_ENUM_VECTOR_NUM_FUNCTORS(Vector) \
+ ((MR_TypeLayout_EnumVector *) (Vector))->num_sharers
+
+#define MR_TYPELAYOUT_ENUM_VECTOR_FUNCTOR_NAME(Vector, N) \
+ ((ConstString) (((Word *) \
+ &(((MR_TypeLayout_EnumVector *) (Vector))->functor1)) \
+ [(N) - 1]))
+
+ /*
+ ** Macros for dealing with simple vectors.
+ */
+
+#define MR_TYPELAYOUT_SIMPLE_VECTOR_OFFSET_FOR_ARITY ((Integer) 0)
+#define MR_TYPELAYOUT_SIMPLE_VECTOR_OFFSET_FOR_ARGS ((Integer) 1)
+ /* Note, these offsets are from the end of the args */
+#define MR_TYPELAYOUT_SIMPLE_VECTOR_OFFSET_FOR_FUNCTOR_NAME ((Integer) 1)
+#define MR_TYPELAYOUT_SIMPLE_VECTOR_OFFSET_FOR_FUNCTOR_TAG ((Integer) 2)
+
+#define MR_TYPELAYOUT_SIMPLE_VECTOR_ARITY(V) \
+ ((V)[MR_TYPELAYOUT_SIMPLE_VECTOR_OFFSET_FOR_ARITY])
+
+#define MR_TYPELAYOUT_SIMPLE_VECTOR_ARGS(V) \
+ (V + MR_TYPELAYOUT_SIMPLE_VECTOR_OFFSET_FOR_ARGS)
+
+#define MR_TYPELAYOUT_SIMPLE_VECTOR_FUNCTOR_NAME(V) \
+ ((String) ((V)[MR_TYPELAYOUT_SIMPLE_VECTOR_ARITY(V) + \
+ MR_TYPELAYOUT_SIMPLE_VECTOR_OFFSET_FOR_FUNCTOR_NAME]))
+
+#define MR_TYPELAYOUT_SIMPLE_VECTOR_TAG(V) \
+ ((Word) ((V)[MR_TYPELAYOUT_SIMPLE_VECTOR_ARITY(V) + \
+ MR_TYPELAYOUT_SIMPLE_VECTOR_OFFSET_FOR_FUNCTOR_TAG]))
+
+ /*
+ ** Macros for dealing with no_tag vectors
+ **
+ ** (Note, we know the arity is 1).
+ */
+
+typedef struct {
+ Word arity;
+ Word arg;
+ ConstString name;
+} MR_TypeLayout_NoTagVector;
+
+#define MR_TYPELAYOUT_NO_TAG_VECTOR_ARITY(Vector) \
+ (1)
+#define MR_TYPELAYOUT_NO_TAG_VECTOR_ARGS(Vector) \
+ (&(((MR_TypeLayout_NoTagVector *) (Vector))->arg))
+
+#define MR_TYPELAYOUT_NO_TAG_VECTOR_FUNCTOR_NAME(Vector) \
+ (((MR_TypeLayout_NoTagVector *) (Vector))->name)
+
+/*---------------------------------------------------------------------------*/
+
+ /*
+ ** Macros for retreiving things from type_infos and
+ ** base_type_infos
+ */
+
+#define MR_TYPEINFO_GET_BASE_TYPEINFO(TypeInfo) \
+ ((*TypeInfo) ? ((Word *) *TypeInfo) : TypeInfo)
+
+#define MR_BASE_TYPEINFO_GET_TYPEFUNCTORS(BaseTypeInfo) \
+ ((Word *) (BaseTypeInfo)[OFFSET_FOR_BASE_TYPE_FUNCTORS])
+
+#define MR_BASE_TYPEINFO_GET_TYPELAYOUT(BaseTypeInfo) \
+ ((Word *) (BaseTypeInfo)[OFFSET_FOR_BASE_TYPE_LAYOUT])
+
+#define MR_BASE_TYPEINFO_GET_TYPELAYOUT_ENTRY(BaseTypeInfo, Tag) \
+ (MR_BASE_TYPEINFO_GET_TYPELAYOUT(BaseTypeInfo)[(Tag)])
+
+#define MR_BASE_TYPEINFO_GET_TYPE_ARITY(BaseTypeInfo) \
+ (((Word *) (BaseTypeInfo))[OFFSET_FOR_COUNT])
+
+/*---------------------------------------------------------------------------*/
+
+#if 0
+
+ /* XXX: We should use structs to represent the various
+ ** data structures in the functors and layouts.
+ **
+ ** To implement this:
+ ** 1. The code that uses the data in the library and
+ ** runtime should be modified to use the above access
+ ** macros
+ ** 2. Then we can simplify the ordering of the data
+ ** structures (for example, put variable length fields
+ ** last)
+ ** 3. Then we can create structs for them.
+ **
+ ** Some examples are below, (no guarantees of correctness).
+ */
+
+ /*
+ ** ** IMPORTANT: the layout in memory of the following
+ ** struct must match the way that the Mercury compiler
+ ** generates code for it.
+ */
+
+
+typedef struct {
+ Word arity;
+ Word arg1;
+/* other arguments follow, there are arity of them,
+** then followed by functor name, and functor tag.
+** Word arg2;
+** ...
+** Word argarity;
+** ConstString functorname;
+** Word tag;
+*/
+} MR_TypeLayout_SimpleVector;
+
+
+typedef struct {
+ Word arity;
+ Word arg_pseudo_type_infos[1]; /* variable-sized array */
+ /* actualy length is `arity', not 1 */
+} MR_TypeLayout_part1;
+
+typedef struct {
+ ConstString name;
+ Word arg_layouts[1]; /* variable-sized array */
+ /* actualy length is `arity', not 1 */
+} MR_TypeLayout_part2;
+typedef MR_TypeLayout_part1 MR_TypeLayout;
+
+#endif
/*---------------------------------------------------------------------------*/
Index: tests/hard_coded/Mmake
===================================================================
RCS file: /home/staff/zs/imp/tests/hard_coded/Mmake,v
retrieving revision 1.38
diff -u -r1.38 Mmake
--- Mmake 1997/04/08 02:28:29 1.38
+++ Mmake 1997/04/17 02:26:20
@@ -14,7 +14,7 @@
reverse_arith curry curry2 higher_order_syntax \
ho_func_reg float_reg write expand ho_solns write_reg1 \
ho_univ_to_type elim_special_pred division_test test_imported_no_tag \
- name_mangling
+ name_mangling construct
#-----------------------------------------------------------------------------#
New files: tests/hard_coded/construct.m
===================================================================
% Test case for construct, num_functors, type_of and get_nth_functor.
%
% Author: trd
:- module construct.
:- interface.
:- import_module io.
:- pred main(io__state::di, io__state::uo) is det.
:- implementation.
:- import_module list, int, std_util, term, map, string, require.
:- pred test_builtins(io__state::di, io__state::uo) is det.
:- pred test_discriminated(io__state::di, io__state::uo) is det.
:- pred test_polymorphism(io__state::di, io__state::uo) is det.
:- pred test_other(io__state::di, io__state::uo) is det.
:- pred test_construct(io__state::di, io__state::uo) is det.
:- pred newline(io__state::di, io__state::uo) is det.
:- pred test_num_functors(type_info::in, io__state::di, io__state::uo) is det.
:- pred test_nth_functor(type_info::in, io__state::di, io__state::uo) is det.
:- pred test_all(T::in, io__state::di, io__state::uo) is det.
:- type enum ---> one ; two ; three.
:- type fruit ---> apple(list(int))
; banana(list(enum)).
:- type thingie ---> foo ; bar(int) ; bar(int, int) ; qux(int) ;
quux(int) ; quuux(int, int) ; wombat ;
zoom(int) ; zap(int, float) ; zip(int, int) ;
zop(float, float).
:- type poly(A, B) ---> poly_one(A) ; poly_two(B) ;
poly_three(B, A, poly(B, A));
poly_four(A, B).
:- type no_tag ---> qwerty(int).
%----------------------------------------------------------------------------%
main -->
test_discriminated,
test_polymorphism,
test_builtins,
test_other,
test_construct.
%----------------------------------------------------------------------------%
test_construct -->
% Valid tests.
% Enumerations:
test_construct_2(type_of(one), "three", 0, []),
{ type_to_univ([1, 2, 3], NumList) },
test_construct_2(type_of(apple([])), "apple", 1, [NumList]),
{ type_to_univ([one, two, three], EnumList) },
test_construct_2(type_of(apple([])), "banana", 1, [EnumList]),
% Discriminated union:
% (Simple, complicated and complicated constant tags).
{ type_to_univ(1, One) },
{ type_to_univ(2.1, TwoPointOne) },
test_construct_2(type_of(wombat), "foo", 0, []),
test_construct_2(type_of(wombat), "bar", 1, [One]),
test_construct_2(type_of(wombat), "bar", 2, [One, One]),
test_construct_2(type_of(wombat), "qux", 1, [One]),
test_construct_2(type_of(wombat), "quux", 1, [One]),
test_construct_2(type_of(wombat), "quuux", 2, [One, One]),
test_construct_2(type_of(wombat), "wombat", 0, []),
test_construct_2(type_of(wombat), "zoom", 1, [One]),
test_construct_2(type_of(wombat), "zap", 2, [One, TwoPointOne]),
test_construct_2(type_of(wombat), "zip", 2, [One, One]),
test_construct_2(type_of(wombat), "zop", 2, [TwoPointOne, TwoPointOne]),
% No-tag type:
test_construct_2(type_of(qwerty(7)), "qwerty", 1, [One]),
{ type_to_univ("goodbye", Bye) },
test_construct_2(type_of(poly_four(3, "hello")), "poly_one", 1, [One]),
test_construct_2(type_of(poly_four(3, "hello")), "poly_two", 1, [Bye]),
test_construct_2(type_of(poly_four(3, "hello")), "poly_four", 2,
[One, Bye]).
:- pred test_construct_2(type_info::in, string::in, int::in, list(univ)::in,
io__state::di, io__state::uo) is det.
test_construct_2(TypeInfo, FunctorName, Arity, Args) -->
{ find_functor(TypeInfo, FunctorName, Arity, FunctorNumber) },
io__write_string("About to construct "),
io__write_string(FunctorName),
io__write_string("/"),
io__write_int(Arity),
newline,
(
{ Constructed = construct(TypeInfo, FunctorNumber, Args) }
->
io__write_string("Constructed: "),
io__write(Constructed),
newline
;
io__write_string("Construction failed.\n")
).
:- pred write_thingie(thingie::in, io__state::di, io__state::uo) is det.
write_thingie(foo) --> io__write_string("foo/0").
write_thingie(bar(_)) --> io__write_string("bar/1").
write_thingie(bar(_,_)) --> io__write_string("bar/2").
write_thingie(qux(_)) --> io__write_string("qux/1").
write_thingie(quux(_)) --> io__write_string("quux/1").
write_thingie(quuux(_,_)) --> io__write_string("quuux/2").
write_thingie(wombat) --> io__write_string("wombat/0").
write_thingie(zoom(_)) --> io__write_string("zoom/1").
write_thingie(zap(_,_)) --> io__write_string("zap/2").
write_thingie(zip(_,_)) --> io__write_string("zip/2").
write_thingie(zop(_,_)) --> io__write_string("zop/2").
:- pred write_thingie2(thingie::in, io__state::di, io__state::uo) is det.
:- pragma c_code(write_thingie2(Thingie::in, IO0::di, IO::uo), "
printf(""thingie is: %ld"", (Word) Thingie);
IO = IO0;
").
:- pred write_enum(enum::in, io__state::di, io__state::uo) is det.
write_enum(one) --> io__write_string("one").
write_enum(two) --> io__write_string("two").
write_enum(three) --> io__write_string("three").
:- pred write_enum2(enum::in, io__state::di, io__state::uo) is det.
:- pragma c_code(write_enum2(Enum::in, IO0::di, IO::uo), "
printf(""enum is: %ld"", (Word) Enum);
IO = IO0;
").
:- pred find_functor(type_info::in, string::in, int::in, int::out) is det.
find_functor(TypeInfo, Functor, Arity, FunctorNumber) :-
N = num_functors(TypeInfo),
find_functor2(TypeInfo, Functor, Arity, N, FunctorNumber).
:- pred find_functor2(type_info::in, string::in, int::in, int::in,
int::out) is det.
find_functor2(TypeInfo, Functor, Arity, Num, FunctorNumber) :-
(
Num = 0
->
error("unable to find functor")
;
(
get_nth_functor(TypeInfo, Num, Functor, Arity, _List)
->
FunctorNumber = Num
;
find_functor2(TypeInfo, Functor, Arity, Num - 1,
FunctorNumber)
)
).
%----------------------------------------------------------------------------%
test_all(T) -->
{ TypeInfo = type_of(T) },
test_num_functors(TypeInfo),
test_nth_functor(TypeInfo), newline.
test_num_functors(TypeInfo) -->
{ N = num_functors(TypeInfo) },
io__write_int(N),
io__write_string(" functors in this type"),
newline.
test_nth_functor(TypeInfo) -->
{ N = num_functors(TypeInfo) },
test_all_functors(TypeInfo, N).
:- pred test_all_functors(type_info::in, int::in,
io__state::di, io__state::uo) is det.
test_all_functors(TypeInfo, N) -->
(
{ N =< 0 }
->
[]
;
io__write_int(N),
(
{ get_nth_functor(TypeInfo, N, Name, Arity, _List) }
->
io__write_string(" - "),
io__write_string(Name),
io__write_string("/"),
io__write_int(Arity),
newline
;
io__write_string(" failed "),
newline
),
test_all_functors(TypeInfo, N - 1)
).
%----------------------------------------------------------------------------%
test_discriminated -->
io__write_string("TESTING DISCRIMINATED UNIONS\n"),
% test enumerations
test_all(two), newline,
test_all(one), newline,
test_all(three), newline,
% test simple tags
test_all(apple([9,5,1])), newline,
test_all(banana([three, one, two])), newline,
% test complicated tags
test_all(zop(3.3, 2.03)), newline,
test_all(zip(3, 2)), newline,
test_all(zap(3, -2.111)), newline,
% test complicated constant
test_all(wombat), newline,
test_all(foo), newline,
newline.
test_polymorphism -->
io__write_string("TESTING POLYMORPHISM\n"),
test_all(poly_three(3.33, 4, poly_one(9.11))), newline,
test_all(poly_two(3)), newline,
test_all(poly_one([2399.3])), newline,
newline.
test_builtins -->
io__write_string("TESTING BUILTINS\n"),
% test strings
test_all(""), newline,
test_all("Hello, world\n"), newline,
test_all("Foo%sFoo"), newline,
test_all(""""), newline,
% test characters
test_all('a'), newline,
test_all('&'), newline,
% test floats
test_all(3.14159), newline,
test_all(11.28324983E-22), newline,
test_all(22.3954899E22), newline,
% test integers
test_all(-65), newline,
test_all(4), newline,
% test univ.
%{ type_to_univ(["hi! I'm a univ!"], Univ) },
% test_all(Univ), newline,
% test predicates
test_all(newline), newline,
newline.
% Note: testing abstract types is always going to have results
% that are dependent on the implementation. If someone changes
% the implementation, the results of this test can change.
test_other -->
io__write_string("TESTING OTHER TYPES\n"),
{ term__init_var_supply(VarSupply) },
{ term__create_var(VarSupply, Var, NewVarSupply) },
test_all(Var), newline,
test_all(VarSupply), newline,
test_all(NewVarSupply), newline,
% presently, at least, map is an equivalence and
% an abstract type.
{ map__init(Map) },
test_all(Map), newline,
% a no tag type
test_all(qwerty(4)), newline,
newline.
newline -->
io__write_char('\n').
New files: tests/hard_coded/construct.exp
===================================================================
TESTING DISCRIMINATED UNIONS
3 functors in this type
3 - three/0
2 - two/0
1 - one/0
3 functors in this type
3 - three/0
2 - two/0
1 - one/0
3 functors in this type
3 - three/0
2 - two/0
1 - one/0
2 functors in this type
2 - banana/1
1 - apple/1
2 functors in this type
2 - banana/1
1 - apple/1
11 functors in this type
11 - zop/2
10 - zoom/1
9 - zip/2
8 - zap/2
7 - wombat/0
6 - qux/1
5 - quux/1
4 - quuux/2
3 - foo/0
2 - bar/2
1 - bar/1
11 functors in this type
11 - zop/2
10 - zoom/1
9 - zip/2
8 - zap/2
7 - wombat/0
6 - qux/1
5 - quux/1
4 - quuux/2
3 - foo/0
2 - bar/2
1 - bar/1
11 functors in this type
11 - zop/2
10 - zoom/1
9 - zip/2
8 - zap/2
7 - wombat/0
6 - qux/1
5 - quux/1
4 - quuux/2
3 - foo/0
2 - bar/2
1 - bar/1
11 functors in this type
11 - zop/2
10 - zoom/1
9 - zip/2
8 - zap/2
7 - wombat/0
6 - qux/1
5 - quux/1
4 - quuux/2
3 - foo/0
2 - bar/2
1 - bar/1
11 functors in this type
11 - zop/2
10 - zoom/1
9 - zip/2
8 - zap/2
7 - wombat/0
6 - qux/1
5 - quux/1
4 - quuux/2
3 - foo/0
2 - bar/2
1 - bar/1
TESTING POLYMORPHISM
4 functors in this type
4 - poly_two/1
3 - poly_three/3
2 - poly_one/1
1 - poly_four/2
4 functors in this type
4 - poly_two/1
3 - poly_three/3
2 - poly_one/1
1 - poly_four/2
4 functors in this type
4 - poly_two/1
3 - poly_three/3
2 - poly_one/1
1 - poly_four/2
TESTING BUILTINS
-1 functors in this type
-1 functors in this type
-1 functors in this type
-1 functors in this type
-1 functors in this type
-1 functors in this type
-1 functors in this type
-1 functors in this type
-1 functors in this type
-1 functors in this type
-1 functors in this type
-1 functors in this type
TESTING OTHER TYPES
-1 functors in this type
-1 functors in this type
-1 functors in this type
4 functors in this type
4 - two/4
3 - three/7
2 - four/10
1 - empty/0
1 functors in this type
1 - qwerty/1
About to construct three/0
Constructed: three
About to construct apple/1
Constructed: apple(.(1, .(2, .(3, []))))
About to construct banana/1
Constructed: banana(.(one, .(two, .(three, []))))
About to construct foo/0
Constructed: foo
About to construct bar/1
Constructed: bar(1)
About to construct bar/2
Constructed: bar(1, 1)
About to construct qux/1
Constructed: qux(1)
About to construct quux/1
Constructed: quux(1)
About to construct quuux/2
Constructed: quuux(1, 1)
About to construct wombat/0
Constructed: wombat
About to construct zoom/1
Constructed: zoom(1)
About to construct zap/2
Constructed: zap(1, 2.10000000000000)
About to construct zip/2
Constructed: zip(1, 1)
About to construct zop/2
Constructed: zop(2.10000000000000, 2.10000000000000)
About to construct qwerty/1
Constructed: qwerty(1)
About to construct poly_one/1
Constructed: poly_one(1)
About to construct poly_two/1
Constructed: poly_two("goodbye")
About to construct poly_four/2
Constructed: poly_four(1, "goodbye")
--
Tyson Dowd #
# Sign on refrigerator:
trd at cs.mu.oz.au # Refrigerate after opening.
http://www.cs.mu.oz.au/~trd # - C. J. Owen.
More information about the developers
mailing list