Files
mercury/library/builtin.m
Fergus Henderson 247b1c24b9 Fix various invasions of the user's namespace by `mercury_builtin.m',
Estimated hours taken: 6

Fix various invasions of the user's namespace by `mercury_builtin.m',
by splitting mercury_builtin.m into two modules, called builtin.m and
private_builtin.m, and ensuring that the latter is imported as if
by `:- use_module' rather than `:- import_module'.

library/builtin.m:
library/private_builtin.m:
	Split mercury_builtin.m into two modules, builtin.m,
	which contains stuff intended to be public,
	and private_builtin.m, which contains implementation
	details that are not supposed to be public.

library/mercury_builtin.m:
	Add a comment saying that this module is no longer used, and
	should eventually be removed.  I have not removed it yet, since
	that would prevent bootstrapping with the current compiler.  It
	will be removed as a seperate change later, once all the
	changes have propagated.

compiler/prog_util.m:
	Change the definition of mercury_private_builtin_module/1 and
	mercury_public_builtin_module so that instead of automatically
	importing mercury_builtin.m as if by `import_module', the
	copiler will now automatically import builtin.m as if by
	`import_module' and private_builtin.m as if by `use_module'.

compiler/polymorphism.m:
	Change a call to mercury_private_builtin_module/1 for
	unsafe_promise_unique to instead call mercury_public_builtin_module/1.

compiler/unify_proc.m:
	Avoid hard-coding "mercury_builtin" by instead
	calling one of  mercury_{private,public}_builtin_module/1.

runtime/mercury_type_info.[ch]:
library/term.m:
library/std_util.m:
compiler/code_util.m:
	Change a few hard-coded instances of "mercury_builtin"
	to "builtin" or "private_builtin" as appropriate.

runtime/mercury_trace_util.c:
runtime/mercury_trace_internal.c:
library/prolog.m:
compiler/*.m:
	Update comments that refer to "mercury_builtin" to instead
	refer to either "builtin" or "private_builtin".

doc/Mmakefile:
	Don't include the interface to private_builtin.m in the
	library reference manual.

tools/bootcheck:
	Add `-p'/`--copy-profiler' option.  This is needed to get
	the above changes to bootstrap.

tools/test_mercury:
	Pass `-p' to tools/bootcheck.

tests/term/*.trans_opt_exp:
	s/mercury_builtin/builtin/g
1998-05-25 21:55:28 +00:00

642 lines
18 KiB
Mathematica

%---------------------------------------------------------------------------%
% Copyright (C) 1994-1998 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.
%---------------------------------------------------------------------------%
% File: builtin.m.
% Main author: fjh.
% Stability: low.
% This file is automatically imported into every module.
% It is intended for things that are part of the language,
% but which are implemented just as normal user-level code
% rather than with special coding in the compiler.
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
:- module builtin.
:- interface.
%-----------------------------------------------------------------------------%
% TYPES.
% The types `character', `int', `float', and `string',
% and the types `pred', `pred(T)', `pred(T1, T2)', `pred(T1, T2, T3)', ...
% and `func(T1) = T2', `func(T1, T2) = T3', `func(T1, T2, T3) = T4', ...
% are builtin and are implemented using special code in the
% type-checker. (XXX TODO: report an error for attempts to redefine
% these types.)
% The type c_pointer can be used by predicates which use the C interface.
:- type c_pointer.
%-----------------------------------------------------------------------------%
% INSTS.
% The standard insts `free', `ground', and `bound(...)' are builtin
% and are implemented using special code in the parser and mode-checker.
% So are the standard unique insts `unique', `unique(...)',
% `mostly_unique', `mostly_unique(...)', and `clobbered'.
% The name `dead' is allowed as a synonym for `clobbered'.
% Similarly `mostly_dead' is a synonym for `mostly_clobbered'.
:- inst dead = clobbered.
:- inst mostly_dead = mostly_clobbered.
% The `any' inst used for the constraint solver interface is also builtin.
% Higher-order predicate insts `pred(<modes>) is <detism>'
% and higher-order functions insts `func(<modes>) = <mode> is det'
% are also builtin.
%-----------------------------------------------------------------------------%
% MODES.
% The standard modes.
:- mode unused :: (free -> free).
:- mode output :: (free -> ground).
:- mode input :: (ground -> ground).
:- mode in :: (ground -> ground).
:- mode out :: (free -> ground).
:- mode in(Inst) :: (Inst -> Inst).
:- mode out(Inst) :: (free -> Inst).
:- mode di(Inst) :: (Inst -> clobbered).
:- mode mdi(Inst) :: (Inst -> mostly_clobbered).
% Unique modes. These are still not fully implemented.
% unique output
:- mode uo :: free -> unique.
% unique input
:- mode ui :: unique -> unique.
% destructive input
:- mode di :: unique -> clobbered.
% "Mostly" unique modes (unique except that that may be referenced
% again on backtracking).
% mostly unique output
:- mode muo :: free -> mostly_unique.
% mostly unique input
:- mode mui :: mostly_unique -> mostly_unique.
% mostly destructive input
:- mode mdi :: mostly_unique -> mostly_clobbered.
% Higher-order predicate modes are builtin.
%-----------------------------------------------------------------------------%
% PREDICATES.
% Most of these probably ought to be moved to another
% module in the standard library such as std_util.m.
% copy/2 makes a deep copy of a data structure. The resulting copy is a
% `unique' value, so you can use destructive update on it.
:- pred copy(T, T).
:- mode copy(ui, uo) is det.
:- mode copy(in, uo) is det.
% unsafe_promise_unique/2 is used to promise the compiler that you have a
% `unique' copy of a data structure, so that you can use destructive update.
% It is used to work around limitations in the current support for unique
% modes. `unsafe_promise_unique(X, Y)' is the same as `Y = X' except that
% the compiler will assume that `Y' is unique.
:- pred unsafe_promise_unique(T, T).
:- mode unsafe_promise_unique(in, uo) is det.
% We define !/0 (and !/2 for dcgs) to be equivalent to `true'. This is for
% backwards compatibility with Prolog systems. But of course it only works
% if all your cuts are green cuts.
:- pred ! is det.
:- pred !(T, T).
:- mode !(di, uo) is det.
:- mode !(in, out) is det.
%-----------------------------------------------------------------------------%
% unify(X, Y) is true iff X = Y.
:- pred unify(T::in, T::in) is semidet.
:- type comparison_result ---> (=) ; (<) ; (>).
% compare(Res, X, Y) binds Res to =, <, or >
% depending on wheither X is =, <, or > Y in the
% standard ordering.
:- pred compare(comparison_result, T, T).
:- mode compare(uo, ui, ui) is det.
:- mode compare(uo, ui, in) is det.
:- mode compare(uo, in, ui) is det.
:- mode compare(uo, in, in) is det.
% index(X, N): if X is a discriminated union type, this is
% true iff the top-level functor of X is the (N-1)th functor in its
% type. If X is of type int, then it is true iff N = X.
% Otherwise, it is true iff N = -1.
:- pred index(T::in, int::out) is det.
% In addition, the following predicate-like constructs are builtin:
%
% :- pred (T = T).
% :- pred (T \= T).
% :- pred (pred , pred).
% :- pred (pred ; pred).
% :- pred (\+ pred).
% :- pred (not pred).
% :- pred (pred -> pred).
% :- pred (if pred then pred).
% :- pred (if pred then pred else pred).
% :- pred (pred => pred).
% :- pred (pred <= pred).
% :- pred (pred <=> pred).
%
% (pred -> pred ; pred).
% some Vars pred
% all Vars pred
% call/N
%-----------------------------------------------------------------------------%
:- implementation.
:- import_module require, string, std_util, int, float, char, string, list.
%-----------------------------------------------------------------------------%
!.
!(X, X).
%-----------------------------------------------------------------------------%
:- external(unify/2).
:- external(index/2).
:- external(compare/3).
%-----------------------------------------------------------------------------%
:- pragma c_header_code("#include ""mercury_type_info.h""").
:- pragma c_code("
#ifdef USE_TYPE_LAYOUT
/* base_type_layout definitions */
/* base_type_layout for `int' */
const struct mercury_data___base_type_layout_int_0_struct {
TYPE_LAYOUT_FIELDS
} mercury_data___base_type_layout_int_0 = {
make_typelayout_for_all_tags(TYPELAYOUT_CONST_TAG,
mkbody(TYPELAYOUT_INT_VALUE))
};
/* base_type_layout for `character' */
const struct mercury_data___base_type_layout_character_0_struct {
TYPE_LAYOUT_FIELDS
} mercury_data___base_type_layout_character_0 = {
make_typelayout_for_all_tags(TYPELAYOUT_CONST_TAG,
mkbody(TYPELAYOUT_CHARACTER_VALUE))
};
/* base_type_layout for `string' */
const struct mercury_data___base_type_layout_string_0_struct {
TYPE_LAYOUT_FIELDS
} mercury_data___base_type_layout_string_0 = {
make_typelayout_for_all_tags(TYPELAYOUT_CONST_TAG,
mkbody(TYPELAYOUT_STRING_VALUE))
};
/* base_type_layout for `float' */
const struct mercury_data___base_type_layout_float_0_struct {
TYPE_LAYOUT_FIELDS
} mercury_data___base_type_layout_float_0 = {
make_typelayout_for_all_tags(TYPELAYOUT_CONST_TAG,
mkbody(TYPELAYOUT_FLOAT_VALUE))
};
/* base_type_layout for `void' */
const struct mercury_data___base_type_layout_void_0_struct {
TYPE_LAYOUT_FIELDS
} mercury_data___base_type_layout_void_0 = {
make_typelayout_for_all_tags(TYPELAYOUT_CONST_TAG,
mkbody(TYPELAYOUT_VOID_VALUE))
};
/* base_type_functors definitions */
/* base_type_functors for `int' */
const struct mercury_data___base_type_functors_int_0_struct {
Integer f1;
} mercury_data___base_type_functors_int_0 = {
MR_TYPEFUNCTORS_SPECIAL
};
/* base_type_functors for `character' */
const struct mercury_data___base_type_functors_character_0_struct {
Integer f1;
} mercury_data___base_type_functors_character_0 = {
MR_TYPEFUNCTORS_SPECIAL
};
/* base_type_functors for `string' */
const struct mercury_data___base_type_functors_string_0_struct {
Integer f1;
} mercury_data___base_type_functors_string_0 = {
MR_TYPEFUNCTORS_SPECIAL
};
/* base_type_functors for `float' */
const struct mercury_data___base_type_functors_float_0_struct {
Integer f1;
} mercury_data___base_type_functors_float_0 = {
MR_TYPEFUNCTORS_SPECIAL
};
/* base_type_functors for `void' */
const struct mercury_data___base_type_functors_void_0_struct {
Integer f1;
} mercury_data___base_type_functors_void_0 = {
MR_TYPEFUNCTORS_SPECIAL
};
#endif /* USE_TYPE_LAYOUT */
/* base_type_infos definitions */
/* base_type_info for `int' */
Declare_entry(mercury__builtin_unify_int_2_0);
Declare_entry(mercury__builtin_index_int_2_0);
Declare_entry(mercury__builtin_compare_int_3_0);
MR_STATIC_CODE_CONST struct mercury_data___base_type_info_int_0_struct {
Integer f1;
Code *f2;
Code *f3;
Code *f4;
#ifdef USE_TYPE_LAYOUT
const Word *f5;
const Word *f6;
const Word *f7;
const Word *f8;
#endif
} mercury_data___base_type_info_int_0 = {
((Integer) 0),
MR_MAYBE_STATIC_CODE(ENTRY(mercury__builtin_unify_int_2_0)),
MR_MAYBE_STATIC_CODE(ENTRY(mercury__builtin_index_int_2_0)),
MR_MAYBE_STATIC_CODE(ENTRY(mercury__builtin_compare_int_3_0)),
#ifdef USE_TYPE_LAYOUT
(const Word *) & mercury_data___base_type_layout_int_0,
(const Word *) & mercury_data___base_type_functors_int_0,
(const Word *) string_const(""builtin"", 15),
(const Word *) string_const(""int"", 3)
#endif
};
/* base_type_info for `character' */
Declare_entry(mercury__builtin_unify_character_2_0);
Declare_entry(mercury__builtin_index_character_2_0);
Declare_entry(mercury__builtin_compare_character_3_0);
MR_STATIC_CODE_CONST struct
mercury_data___base_type_info_character_0_struct {
Integer f1;
Code *f2;
Code *f3;
Code *f4;
#ifdef USE_TYPE_LAYOUT
const Word *f5;
const Word *f6;
const Word *f7;
const Word *f8;
#endif
} mercury_data___base_type_info_character_0 = {
((Integer) 0),
MR_MAYBE_STATIC_CODE(ENTRY(mercury__builtin_unify_character_2_0)),
MR_MAYBE_STATIC_CODE(ENTRY(mercury__builtin_index_character_2_0)),
MR_MAYBE_STATIC_CODE(ENTRY(mercury__builtin_compare_character_3_0)),
#ifdef USE_TYPE_LAYOUT
(const Word *) & mercury_data___base_type_layout_character_0,
(const Word *) & mercury_data___base_type_functors_character_0,
(const Word *) string_const(""builtin"", 15),
(const Word *) string_const(""character"", 9)
#endif
};
/* base_type_info for `string' */
Declare_entry(mercury__builtin_unify_string_2_0);
Declare_entry(mercury__builtin_index_string_2_0);
Declare_entry(mercury__builtin_compare_string_3_0);
MR_STATIC_CODE_CONST struct mercury_data___base_type_info_string_0_struct {
Integer f1;
Code *f2;
Code *f3;
Code *f4;
#ifdef USE_TYPE_LAYOUT
const Word *f5;
const Word *f6;
const Word *f7;
const Word *f8;
#endif
} mercury_data___base_type_info_string_0 = {
((Integer) 0),
MR_MAYBE_STATIC_CODE(ENTRY(mercury__builtin_unify_string_2_0)),
MR_MAYBE_STATIC_CODE(ENTRY(mercury__builtin_index_string_2_0)),
MR_MAYBE_STATIC_CODE(ENTRY(mercury__builtin_compare_string_3_0)),
#ifdef USE_TYPE_LAYOUT
(const Word *) & mercury_data___base_type_layout_string_0,
(const Word *) & mercury_data___base_type_functors_string_0,
(const Word *) string_const(""builtin"", 15),
(const Word *) string_const(""string"", 6)
#endif
};
/* base_type_info for `float' */
Declare_entry(mercury__builtin_unify_float_2_0);
Declare_entry(mercury__builtin_index_float_2_0);
Declare_entry(mercury__builtin_compare_float_3_0);
MR_STATIC_CODE_CONST struct mercury_data___base_type_info_float_0_struct {
Integer f1;
Code *f2;
Code *f3;
Code *f4;
#ifdef USE_TYPE_LAYOUT
const Word *f5;
const Word *f6;
const Word *f7;
const Word *f8;
#endif
} mercury_data___base_type_info_float_0 = {
((Integer) 0),
MR_MAYBE_STATIC_CODE(ENTRY(mercury__builtin_unify_float_2_0)),
MR_MAYBE_STATIC_CODE(ENTRY(mercury__builtin_index_float_2_0)),
MR_MAYBE_STATIC_CODE(ENTRY(mercury__builtin_compare_float_3_0)),
#ifdef USE_TYPE_LAYOUT
(const Word *) & mercury_data___base_type_layout_float_0,
(const Word *) & mercury_data___base_type_functors_float_0,
(const Word *) string_const(""builtin"", 15),
(const Word *) string_const(""float"", 5)
#endif
};
/* base_type_info for `void' */
Declare_entry(mercury__unused_0_0);
MR_STATIC_CODE_CONST struct mercury_data___base_type_info_void_0_struct {
Integer f1;
Code *f2;
Code *f3;
Code *f4;
#ifdef USE_TYPE_LAYOUT
const Word *f5;
const Word *f6;
const Word *f7;
const Word *f8;
#endif
} mercury_data___base_type_info_void_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_LAYOUT
(const Word *) & mercury_data___base_type_layout_void_0,
(const Word *) & mercury_data___base_type_functors_void_0,
(const Word *) string_const(""builtin"", 15),
(const Word *) string_const(""void"", 4)
#endif
};
BEGIN_MODULE(builtin_types_module)
BEGIN_CODE
END_MODULE
/*
INIT sys_init_builtin_types_module
*/
extern ModuleFunc builtin_types_module;
extern void mercury__builtin__init(void);
void sys_init_builtin_types_module(void);
void sys_init_builtin_types_module(void) {
builtin_types_module();
/*
** We had better call this init() because we use the
** labels for the special preds of int, float, pred,
** character and string. If they aren't initialized,
** we might initialize the base_type_info with
** garbage
*/
mercury__builtin__init();
MR_INIT_BUILTIN_BASE_TYPE_INFO(
mercury_data___base_type_info_int_0, _int_);
MR_INIT_BUILTIN_BASE_TYPE_INFO(
mercury_data___base_type_info_float_0, _float_);
MR_INIT_BUILTIN_BASE_TYPE_INFO(
mercury_data___base_type_info_character_0, _character_);
MR_INIT_BUILTIN_BASE_TYPE_INFO(
mercury_data___base_type_info_string_0, _string_);
MR_INIT_BASE_TYPE_INFO_WITH_PRED(
mercury_data___base_type_info_void_0, mercury__unused_0_0);
}
").
%-----------------------------------------------------------------------------%
% unsafe_promise_unique/2 is a compiler builtin.
%-----------------------------------------------------------------------------%
/* copy/2
:- pred copy(T, T).
:- mode copy(ui, uo) is det.
:- mode copy(in, uo) is det.
*/
/*************
Using `pragma c_code' doesn't work, due to the lack of support for
aliasing, and in particular the lack of support for `ui' modes.
:- pragma c_code(copy(Value::ui, Copy::uo), "
save_transient_registers();
Copy = deep_copy(Value, TypeInfo_for_T, NULL, NULL);
restore_transient_registers();
").
:- pragma c_code(copy(Value::in, Copy::uo), "
save_transient_registers();
Copy = deep_copy(Value, TypeInfo_for_T, NULL, NULL);
restore_transient_registers();
").
*************/
:- external(copy/2).
:- pragma c_header_code("#include ""mercury_deep_copy.h""").
:- pragma c_code("
Define_extern_entry(mercury__copy_2_0);
Define_extern_entry(mercury__copy_2_1);
MR_MAKE_STACK_LAYOUT_ENTRY(mercury__copy_2_0);
MR_MAKE_STACK_LAYOUT_ENTRY(mercury__copy_2_1);
BEGIN_MODULE(copy_module)
init_entry(mercury__copy_2_0);
init_entry(mercury__copy_2_1);
BEGIN_CODE
#ifdef PROFILE_CALLS
#define fallthru(target, caller) { tailcall((target), (caller)); }
#else
#define fallthru(target, caller)
#endif
Define_entry(mercury__copy_2_0);
fallthru(ENTRY(mercury__copy_2_1), ENTRY(mercury__copy_2_0))
Define_entry(mercury__copy_2_1);
{
Word value, copy, type_info;
type_info = r1;
value = r2;
save_transient_registers();
copy = deep_copy(value, (Word *) type_info, NULL, NULL);
restore_transient_registers();
#ifdef COMPACT_ARGS
r1 = copy;
#else
r3 = copy;
#endif
proceed();
}
END_MODULE
/* Ensure that the initialization code for the above module gets run. */
/*
INIT sys_init_copy_module
*/
extern ModuleFunc copy_module;
void sys_init_copy_module(void);
/* extra declaration to suppress gcc -Wmissing-decl warning */
void sys_init_copy_module(void) {
copy_module();
}
").
%-----------------------------------------------------------------------------%
% The type c_pointer can be used by predicates which use the C interface.
:- pragma c_code("
/*
* c_pointer has a special value reserved for its layout, since it needs to
* be handled as a special case.
*/
#ifdef USE_TYPE_LAYOUT
const struct mercury_data_builtin__base_type_layout_c_pointer_0_struct {
TYPE_LAYOUT_FIELDS
} mercury_data_builtin__base_type_layout_c_pointer_0 = {
make_typelayout_for_all_tags(TYPELAYOUT_CONST_TAG,
mkbody(TYPELAYOUT_C_POINTER_VALUE))
};
const struct
mercury_data_builtin__base_type_functors_c_pointer_0_struct {
Integer f1;
} mercury_data_builtin__base_type_functors_c_pointer_0 = {
MR_TYPEFUNCTORS_SPECIAL
};
#endif
Define_extern_entry(mercury____Unify___builtin__c_pointer_0_0);
Define_extern_entry(mercury____Index___builtin__c_pointer_0_0);
Define_extern_entry(mercury____Compare___builtin__c_pointer_0_0);
MR_MAKE_STACK_LAYOUT_ENTRY(mercury____Unify___builtin__c_pointer_0_0);
MR_MAKE_STACK_LAYOUT_ENTRY(mercury____Index___builtin__c_pointer_0_0);
MR_MAKE_STACK_LAYOUT_ENTRY(mercury____Compare___builtin__c_pointer_0_0);
BEGIN_MODULE(unify_c_pointer_module)
init_entry(mercury____Unify___builtin__c_pointer_0_0);
init_entry(mercury____Index___builtin__c_pointer_0_0);
init_entry(mercury____Compare___builtin__c_pointer_0_0);
BEGIN_CODE
Define_entry(mercury____Unify___builtin__c_pointer_0_0);
/*
** For c_pointer, we assume that equality and comparison
** can be based on object identity (i.e. using address comparisons).
** This is correct for types like io__stream, and necessary since
** the io__state contains a map(io__stream, filename).
** However, it might not be correct in general...
*/
unify_output = (unify_input1 == unify_input2);
proceed();
Define_entry(mercury____Index___builtin__c_pointer_0_0);
index_output = -1;
proceed();
Define_entry(mercury____Compare___builtin__c_pointer_0_0);
compare_output = (compare_input1 == compare_input2 ? COMPARE_EQUAL :
compare_input1 < compare_input2 ? COMPARE_LESS :
COMPARE_GREATER);
proceed();
END_MODULE
/* Ensure that the initialization code for the above module gets run. */
/*
INIT sys_init_unify_c_pointer_module
*/
extern ModuleFunc unify_c_pointer_module;
void sys_init_unify_c_pointer_module(void);
/* duplicate declaration to suppress gcc -Wmissing-decl warning */
void sys_init_unify_c_pointer_module(void) {
unify_c_pointer_module();
}
").
:- end_module builtin.
%-----------------------------------------------------------------------------%