Files
mercury/library/term.m
Fergus Henderson 14728289fa Remove support for NU-Prolog and SICStus Prolog.
Estimated hours taken: 5

Remove support for NU-Prolog and SICStus Prolog.

The reasons for this are:
(a) We now have a proper working debugger, so we don't need to use
    NU-Prolog or SICStus Prolog for debugging.
(b) The Prolog support was only ever a hack, not a proper solution;
    Mercury language features like functions or mode reordering
    were never supported.
(c) It was a maintenance problem.

compiler/make_hlds.m:
	Warn that NU-Prolog `when' declarations are deprecated.

compiler/prog_io.m:
	Update a comment to say that NU-Prolog `when' declarations
	are now deprecated.

library/*.m:
	Delete `when' declarations.

configure.in:
bindist/bindist.configure.in:
	Delete the autoconf tests for NU-Prolog and SICStus Prolog.
	Delete the stuff for generating the NU-Prolog and SICStus Prolog
	scripts.

tools/bootcheck:
	Delete the options for testing using SICStus Prolog.

library/Mmakefile:
	Delete the rules for building NU-Prolog and SICStus Prolog stuff.

library/library.nu.nl.in:
	library/swi_*.m:
	library/*.nu.nl:
library/array.nu.nl:
library/assoc_list.nu.nl:
library/char.nu.nl:
library/float.nu.nl:
library/int.nu.nl:
library/io.nu.nl:
library/library.nu.nl.in:
library/map.nu.nl:
library/mercury_builtin.nu.nl:
library/nc_builtin.nl:
library/require.nu.nl:
library/sp_builtin.nl:
library/sp_lib.nl:
library/std_util.nu.nl:
library/store.nu.nl:
library/string.nu.nl:
library/swi_builtin.m:
library/swi_lib.m:
library/term_io.nu.nl:
	Delete these files.

scripts/mnc.in:
scripts/mnp.in:
scripts/mnl.in:
scripts/msc.in:
scripts/msl.in:
scripts/msp.in:
	Delete these files.

doc/user_guide.texi:
	Delete the documentation about the Prolog support.

NEWS:
w3/news/newsdb.inc:
        Mention that we've removed the Prolog support.
1999-03-15 08:48:36 +00:00

1116 lines
38 KiB
Mathematica

%---------------------------------------------------------------------------%
% Copyright (C) 1993-1999 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: term.m.
% Main author: fjh.
% Stability: medium.
% This file provides a type `term' used to represent Prolog terms,
% and various predicates to manipulate terms and substitutions.
% Terms are polymorphic so that terms representing different kinds of
% thing can be made to be of different types so they don't get mixed up.
%-----------------------------------------------------------------------------%
:- module term.
:- interface.
:- import_module list, map, std_util.
%-----------------------------------------------------------------------------%
:- type term(T) ---> term__functor(
const,
list(term(T)),
term__context
)
; term__variable(var(T)).
:- type const ---> term__atom(string)
; term__integer(int)
; term__string(string)
; term__float(float).
:- type term__context ---> term__context(string, int).
% file name, line number.
:- type var(T).
:- type var_supply(T).
:- type generic
---> generic.
:- type term == term(generic).
:- type var == var(generic).
%-----------------------------------------------------------------------------%
% The following predicates can convert values of (almost)
% any type to the type `term' and back again.
:- type term_to_type_result(T, U)
---> ok(T)
; error(term_to_type_error(U)).
:- type term_to_type_result(T) == term_to_type_result(T, generic).
:- pred term__try_term_to_type(term(U), term_to_type_result(T, U)).
:- mode term__try_term_to_type(in, out) is det.
% term__try_term_to_type(Term, Result):
% Try to convert the given term to a ground value of type T.
% If successful, return `ok(X)' where X is the converted value.
% If Term is not ground, return `mode_error(Var, Context)',
% where Var is a variable occurring in Term.
% If Term is not a valid term of the specified type, return
% `type_error(SubTerm, ExpectedType, Context, ArgContexts)',
% where SubTerm is a sub-term of Term and ExpectedType is
% the type expected for that part of Term.
% Context specifies the file and line number where the
% offending part of the term was read in from, if available.
% ArgContexts specifies the path from the root of the term
% to the offending subterm.
:- type term_to_type_error(T)
---> type_error(term(T), type_info, term__context,
term_to_type_context)
; mode_error(var(T), term_to_type_context).
:- type term_to_type_context == list(term_to_type_arg_context).
:- type term_to_type_arg_context
---> arg_context(
const, % functor
int, % argument number (starting from 1)
term__context % filename & line number
).
:- pred term__term_to_type(term(U), T).
:- mode term__term_to_type(in, out) is semidet.
% term_to_type(Term, Type) :- try_term_to_type(Term, ok(Type)).
:- pred term__det_term_to_type(term(_), T).
:- mode term__det_term_to_type(in, out) is det.
% like term_to_type, but calls error/1 rather than failing.
:- pred term__type_to_term(T, term(_)).
:- mode term__type_to_term(in, out) is det.
% converts a value to a term representation of that value
:- pred term__univ_to_term(univ, term(_)).
:- mode term__univ_to_term(in, out) is det.
% calls term__type_to_term on the value stored in the univ
% (as distinct from the univ itself).
%-----------------------------------------------------------------------------%
:- pred term__vars(term(T), list(var(T))).
:- mode term__vars(in, out) is det.
% term__vars(Term, Vars)
% Vars is the list of variables contained in Term, in the order
% obtained by traversing the term depth first, left-to-right.
:- pred term__vars_2(term(T), list(var(T)), list(var(T))).
:- mode term__vars_2(in, in, out) is det.
% As above, but with an accumulator.
:- pred term__vars_list(list(term(T)), list(var(T))).
:- mode term__vars_list(in, out) is det.
% term__vars_list(TermList, Vars)
% Vars is the list of variables contained in TermList, in the
% order obtained by traversing the list of terms depth-first,
% left-to-right.
:- pred term__contains_var(term(T), var(T)).
:- mode term__contains_var(in, in) is semidet.
:- mode term__contains_var(in, out) is nondet.
% term__contains_var(Term, Var)
% True if Term contains Var. (On backtracking returns all the
% variables contained in Term.)
:- pred term__contains_var_list(list(term(T)), var(T)).
:- mode term__contains_var_list(in, in) is semidet.
:- mode term__contains_var_list(in, out) is nondet.
% term__contains_var_list(TermList, Var)
% True if TermList contains Var. (On backtracking returns all the
% variables contained in Term.)
:- type substitution(T) == map(var(T), term(T)).
:- type substitution == substitution(generic).
:- pred term__unify(term(T), term(T), substitution(T), substitution(T)).
:- mode term__unify(in, in, in, out) is semidet.
% term__unify(Term1, Term2, Bindings0, Bindings)
% unify (with occur check) two terms with respect to a set
% of bindings and possibly update the set of bindings
:- pred term__substitute(term(T), var(T), term(T), term(T)).
:- mode term__substitute(in, in, in, out) is det.
% term__substitute(Term0, Var, Replacement, Term) :
% replace all occurrences of Var in Term0 with Replacement,
% and return the result in Term.
:- pred term__substitute_list(list(term(T)), var(T), term(T), list(term(T))).
:- mode term__substitute_list(in, in, in, out) is det.
% as above, except for a list of terms rather than a single term
:- pred term__substitute_corresponding(list(var(T)), list(term(T)),
term(T), term(T)).
:- mode term__substitute_corresponding(in, in, in, out) is det.
% term__substitute_corresponding(Vars, Repls, Term0, Term).
% replace all occurrences of variables in Vars with
% the corresponding term in Repls, and return the result in Term.
% If Vars contains duplicates, or if Vars is not the same
% length as Repls, the behaviour is undefined and probably
% harmful.
:- pred term__substitute_corresponding_list(list(var(T)), list(term(T)),
list(term(T)), list(term(T))).
:- mode term__substitute_corresponding_list(in, in, in, out) is det.
% term__substitute_corresponding_list(Vars, Repls, TermList0, TermList).
% As above, except applies to a list of terms rather than a
% single term.
:- pred term__apply_rec_substitution(term(T), substitution(T), term(T)).
:- mode term__apply_rec_substitution(in, in, out) is det.
% term__apply_rec_substitution(Term0, Substitution, Term) :
% recursively apply substitution to Term0 until
% no more substitions can be applied, and then
% return the result in Term.
:- pred term__apply_rec_substitution_to_list(list(term(T)), substitution(T),
list(term(T))).
:- mode term__apply_rec_substitution_to_list(in, in, out) is det.
:- pred term__apply_substitution(term(T), substitution(T), term(T)).
:- mode term__apply_substitution(in, in, out) is det.
% term__apply_substitution(Term0, Substitution, Term) :
% apply substitution to Term0 and return the result in Term.
:- pred term__apply_substitution_to_list(list(term(T)), substitution(T),
list(term(T))).
:- mode term__apply_substitution_to_list(in, in, out) is det.
% term__apply_substitution_to_list(TermList0, Substitution, TermList) :
% as above, except for a list of terms rather than a single term
:- pred term__occurs(term(T), var(T), substitution(T)).
:- mode term__occurs(in, in, in) is semidet.
% term__occurs(Term0, Var, Substitution) :
% true iff Var occurs in the term resulting after
% applying Substitution to Term0.
:- pred term__occurs_list(list(term(T)), var(T), substitution(T)).
:- mode term__occurs_list(in, in, in) is semidet.
% as above, except for a list of terms rather than a single term
:- pred term__relabel_variable(term(T), var(T), var(T), term(T)).
:- mode term__relabel_variable(in, in, in, out) is det.
% term__relabel_variable(Term0, OldVar, NewVar, Term) :
% replace all occurences of OldVar in Term0 with
% NewVar and put the result in Term.
:- pred term__relabel_variables(list(term(T)), var(T), var(T), list(term(T))).
:- mode term__relabel_variables(in, in, in, out) is det.
% term__relabel_variables(Terms0, OldVar, NewVar, Terms) :
% same as term__relabel_variable but for a list of terms.
:- pred term__apply_variable_renaming(term(T), map(var(T), var(T)), term(T)).
:- mode term__apply_variable_renaming(in, in, out) is det.
% same as term__relabel_variable, except relabels
% multiple variables. If a variable is not in the
% map, it is not replaced.
:- pred term__apply_variable_renaming_to_list(list(term(T)),
map(var(T), var(T)), list(term(T))).
:- mode term__apply_variable_renaming_to_list(in, in, out) is det.
% applies term__apply_variable_renaming to a list of terms.
:- pred term__is_ground(term(T), substitution(T)).
:- mode term__is_ground(in, in) is semidet.
% term__is_ground(Term, Bindings) is true iff no variables contained
% in Term are non-ground in Bindings.
:- pred term__is_ground(term(T)).
:- mode term__is_ground(in) is semidet.
% term__is_ground(Term) is true iff Term contains no variables.
%-----------------------------------------------------------------------------%
% To manage a supply of variables, use the following 2 predicates.
% (We might want to give these a unique mode later.)
:- pred term__init_var_supply(var_supply(T)).
:- mode term__init_var_supply(out) is det.
:- mode term__init_var_supply(in) is semidet. % implied
% term__init_var_supply(VarSupply) :
% returns a fresh var_supply for producing fresh variables.
:- pred term__create_var(var_supply(T), var(T), var_supply(T)).
:- mode term__create_var(in, out, out) is det.
% term__create_var(VarSupply0, Variable, VarSupply) :
% create a fresh variable (var) and return the
% updated var_supply.
:- pred term__var_to_int(var(T), int).
:- mode term__var_to_int(in, out) is det.
% Convert a variable to an int.
% Different variables map to different ints.
% Other than that, the mapping is unspecified.
%-----------------------------------------------------------------------------%
% Given a term context, return the source line number.
:- pred term__context_line(term__context, int).
:- mode term__context_line(in, out) is det.
% Given a term context, return the source file.
:- pred term__context_file(term__context, string).
:- mode term__context_file(in, out) is det.
% Used to initialize the term context when reading in
% (or otherwise constructing) a term.
:- pred term__context_init(term__context).
:- mode term__context_init(out) is det.
:- pred term__context_init(string, int, term__context).
:- mode term__context_init(in, in, out) is det.
% Convert a list of terms which are all vars into a list
% of vars. Abort (call error/1) if the list contains
% any non-variables.
:- pred term__term_list_to_var_list(list(term(T)), list(var(T))).
:- mode term__term_list_to_var_list(in, out) is det.
% Convert a list of terms which are all vars into a list
% of vars (or vice versa).
:- pred term__var_list_to_term_list(list(var(T)), list(term(T))).
:- mode term__var_list_to_term_list(in, out) is det.
:- mode term__var_list_to_term_list(out, in) is semidet.
%-----------------------------------------------------------------------------%
% term__generic_term(Term) is true iff `Term' is a term of type
% `term' ie `term(generic)'.
% It is useful because in some instances it doesn't matter what
% the type of a term is, and passing it to this predicate will
% ground the type avoiding unbound type variable warnings.
:- pred term__generic_term(term).
:- mode term__generic_term(in) is det.
% Coerce a term of type `T' into a term of type `U'.
:- pred term__coerce(term(T), term(U)).
:- mode term__coerce(in, out) is det.
% Coerce a var of type `T' into a var of type `U'.
:- pred term__coerce_var(var(T), var(U)).
:- mode term__coerce_var(in, out) is det.
% Coerce a var_supply of type `T' into a var_supply of type `U'.
:- pred term__coerce_var_supply(var_supply(T), var_supply(U)).
:- mode term__coerce_var_supply(in, out) is det.
%-----------------------------------------------------------------------------%
:- implementation.
% Everything below here is not intended to be part of the public interface,
% and will not be included in the Mercury library reference manual.
%-----------------------------------------------------------------------------%
:- interface.
% This predidicate is being phased out, because of the problem
% mentioned in the "BEWARE:" below.
:- pragma obsolete(term__compare/4).
:- pred term__compare(comparison_result, term(T), term(T), substitution(T)).
:- mode term__compare(out, in, in, in) is semidet.
% term__compare(Comparison, Term1, Term2, Bindings) is true iff
% there is a binding of Comparison to <, =, or > such
% that the binding holds for the two ground terms Term1
% and Term2 with respect to the bindings in Bindings.
% Fails if Term1 or Term2 is not ground (with respect to
% the bindings in Bindings).
% BEWARE: the comparison does not ignore the term__contexts
% in the terms.
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
:- implementation.
:- import_module std_util, require, array, int, string.
%-----------------------------------------------------------------------------%
:- type var_supply(T)
---> var_supply(int).
:- type var(T)
---> var(int).
%-----------------------------------------------------------------------------%
term__term_to_type(Term, Val) :-
term__try_term_to_type(Term, ok(Val)).
term__try_term_to_type(Term, Result) :-
term__try_term_to_univ(Term, type_of(ValTypedVar), UnivResult),
(
UnivResult = ok(Univ),
det_univ_to_type(Univ, Val),
same_type(Val, ValTypedVar),
Result = ok(Val)
;
UnivResult = error(Error),
Result = error(Error)
).
:- pred term__try_term_to_univ(term(T)::in, type_info::in,
term_to_type_result(univ, T)::out) is det.
term__try_term_to_univ(Term, Type, Result) :-
term__try_term_to_univ_2(Term, Type, [], Result).
:- pred term__try_term_to_univ_2(term(T)::in, type_info::in,
term_to_type_context::in,
term_to_type_result(univ, T)::out) is det.
term__try_term_to_univ_2(term__variable(Var), _Type, Context,
error(mode_error(Var, Context))).
term__try_term_to_univ_2(Term, Type, Context, Result) :-
Term = term__functor(Functor, ArgTerms, TermContext),
(
type_ctor_and_args(Type, TypeCtor, TypeArgs),
term__term_to_univ_special_case(
type_ctor_module_name(TypeCtor),
type_ctor_name(TypeCtor),
TypeArgs, Term, Type, Context, SpecialCaseResult)
->
Result = SpecialCaseResult
;
Functor = term__atom(FunctorName),
list__length(ArgTerms, Arity),
find_functor(Type, FunctorName, Arity, FunctorNumber, ArgTypes),
term__term_list_to_univ_list(ArgTerms, ArgTypes,
Functor, 1, Context, TermContext, ArgsResult)
->
(
ArgsResult = ok(ArgValues),
( Value = construct(Type, FunctorNumber, ArgValues) ->
Result = ok(Value)
;
error("term_to_type: construct/3 failed")
)
;
ArgsResult = error(Error),
Result = error(Error)
)
;
% the arg contexts are built up in reverse order,
% so we need to reverse them here
list__reverse(Context, RevContext),
Result = error(type_error(Term, Type, TermContext, RevContext))
).
:- pred term__term_to_univ_special_case(string::in, string::in,
list(type_info)::in,
term(T)::in(bound(term__functor(ground, ground, ground))),
type_info::in, term_to_type_context::in,
term_to_type_result(univ, T)::out) is semidet.
/*
** XXX the following clauses for mercury_builtin:* are
** for bootstrapping only, and should eventually be deleted
*/
term__term_to_univ_special_case("mercury_builtin", "character", [],
Term, _, _, ok(Univ)) :-
Term = term__functor(term__atom(FunctorName), [], _),
string__first_char(FunctorName, Char, ""),
type_to_univ(Char, Univ).
term__term_to_univ_special_case("mercury_builtin", "int", [],
Term, _, _, ok(Univ)) :-
Term = term__functor(term__integer(Int), [], _),
type_to_univ(Int, Univ).
term__term_to_univ_special_case("mercury_builtin", "string", [],
Term, _, _, ok(Univ)) :-
Term = term__functor(term__string(String), [], _),
type_to_univ(String, Univ).
term__term_to_univ_special_case("mercury_builtin", "float", [],
Term, _, _, ok(Univ)) :-
Term = term__functor(term__float(Float), [], _),
type_to_univ(Float, Univ).
term__term_to_univ_special_case("builtin", "character", [],
Term, _, _, ok(Univ)) :-
Term = term__functor(term__atom(FunctorName), [], _),
string__first_char(FunctorName, Char, ""),
type_to_univ(Char, Univ).
term__term_to_univ_special_case("builtin", "int", [],
Term, _, _, ok(Univ)) :-
Term = term__functor(term__integer(Int), [], _),
type_to_univ(Int, Univ).
term__term_to_univ_special_case("builtin", "string", [],
Term, _, _, ok(Univ)) :-
Term = term__functor(term__string(String), [], _),
type_to_univ(String, Univ).
term__term_to_univ_special_case("builtin", "float", [],
Term, _, _, ok(Univ)) :-
Term = term__functor(term__float(Float), [], _),
type_to_univ(Float, Univ).
term__term_to_univ_special_case("array", "array", [ElemType], Term, _Type,
PrevContext, Result) :-
%
% arrays are represented as terms of the form
% array([elem1, elem2, ...])
%
Term = term__functor(term__atom("array"), [ArgList], TermContext),
% To convert such terms back to arrays, we first
% convert the term representing the list of elements back to a list,
% and then (if successful) we just call the array/1 function.
%
has_type(Elem, ElemType),
ListType = type_of([Elem]),
ArgContext = arg_context(term__atom("array"), 1, TermContext),
NewContext = [ArgContext | PrevContext],
term__try_term_to_univ_2(ArgList, ListType, NewContext, ArgResult),
(
ArgResult = ok(ListUniv),
has_type(Elem2, ElemType),
same_type(List, [Elem2]),
det_univ_to_type(ListUniv, List),
Array = array(List),
Result = ok(univ(Array))
;
ArgResult = error(Error),
Result = error(Error)
).
term__term_to_univ_special_case("builtin", "c_pointer", _, _, _,
_, _) :-
fail.
term__term_to_univ_special_case("std_util", "univ", _, _, _, _, _) :-
% Implementing this properly would require keeping a
% global table mapping from type names to type_infos
% for all of the types in the program...
% so for the moment, we don't allow it.
fail.
term__term_to_univ_special_case("std_util", "type_info", _, _, _, _, _) :-
% ditto
fail.
:- pred term__term_list_to_univ_list(list(term(T))::in, list(type_info)::in,
term__const::in, int::in, term_to_type_context::in,
term__context::in, term_to_type_result(list(univ), T)::out)
is semidet.
term__term_list_to_univ_list([], [], _, _, _, _, ok([])).
term__term_list_to_univ_list([ArgTerm|ArgTerms], [Type|Types],
Functor, ArgNum, PrevContext, TermContext, Result) :-
ArgContext = arg_context(Functor, ArgNum, TermContext),
NewContext = [ArgContext | PrevContext],
term__try_term_to_univ_2(ArgTerm, Type, NewContext, ArgResult),
(
ArgResult = ok(Arg),
term__term_list_to_univ_list(ArgTerms, Types, Functor,
ArgNum + 1, PrevContext, TermContext, RestResult),
(
RestResult = ok(Rest),
Result = ok([Arg | Rest])
;
RestResult = error(Error),
Result = error(Error)
)
;
ArgResult = error(Error),
Result = error(Error)
).
:- pred term__find_functor(type_info::in, string::in, int::in, int::out,
list(type_info)::out) is semidet.
term__find_functor(Type, Functor, Arity, FunctorNumber, ArgTypes) :-
N = num_functors(Type),
term__find_functor_2(Type, Functor, Arity, N, FunctorNumber, ArgTypes).
:- pred term__find_functor_2(type_info::in, string::in, int::in, int::in,
int::out, list(type_info)::out) is semidet.
term__find_functor_2(TypeInfo, Functor, Arity, Num, FunctorNumber, ArgTypes) :-
Num >= 0,
Num1 = Num - 1,
(
get_functor(TypeInfo, Num1, Functor, Arity, ArgTypes1)
->
ArgTypes = ArgTypes1,
FunctorNumber = Num1
;
term__find_functor_2(TypeInfo, Functor, Arity, Num1,
FunctorNumber, ArgTypes)
).
term__det_term_to_type(Term, X) :-
( term__term_to_type(Term, X1) ->
X = X1
; \+ term__is_ground(Term) ->
error("term__det_term_to_type failed, because the term wasn't ground")
;
string__append_list([
"term__det_term_to_type failed, due to a type error:\n",
"the term wasn't a valid term for type `",
type_name(type_of(X)),
"'"], Message),
error(Message)
).
%-----------------------------------------------------------------------------%
term__type_to_term(Val, Term) :- type_to_univ(Val, Univ),
term__univ_to_term(Univ, Term).
term__univ_to_term(Univ, Term) :-
term__context_init(Context),
Type = univ_type(Univ),
% NU-Prolog barfs on `num_functors(Type) < 0'
( num_functors(Type) = N, N < 0 ->
(
type_ctor_and_args(Type, TypeCtor, TypeArgs),
TypeName = type_ctor_name(TypeCtor),
ModuleName = type_ctor_module_name(TypeCtor),
term__univ_to_term_special_case(ModuleName, TypeName,
TypeArgs, Univ, Context, SpecialCaseTerm)
->
Term = SpecialCaseTerm
;
string__append_list(
["term__type_to_term: unknown type `",
type_name(univ_type(Univ)),
"'"],
Message),
error(Message)
)
;
deconstruct(Univ, FunctorString, _FunctorArity, FunctorArgs),
term__univ_list_to_term_list(FunctorArgs, TermArgs),
Term = term__functor(term__atom(FunctorString), TermArgs,
Context)
).
:- pred term__univ_to_term_special_case(string::in, string::in,
list(type_info)::in, univ::in, term__context::in,
term(T)::out) is semidet.
/*
** XXX the following clauses for mercury_builtin:* are
** for bootstrapping only, and should eventually be deleted
*/
term__univ_to_term_special_case("mercury_builtin", "int", [], Univ, Context,
term__functor(term__integer(Int), [], Context)) :-
det_univ_to_type(Univ, Int).
term__univ_to_term_special_case("mercury_builtin", "float", [], Univ, Context,
term__functor(term__float(Float), [], Context)) :-
det_univ_to_type(Univ, Float).
term__univ_to_term_special_case("mercury_builtin", "character", [], Univ,
Context, term__functor(term__atom(CharName), [], Context)) :-
det_univ_to_type(Univ, Character),
string__char_to_string(Character, CharName).
term__univ_to_term_special_case("mercury_builtin", "string", [], Univ, Context,
term__functor(term__string(String), [], Context)) :-
det_univ_to_type(Univ, String).
term__univ_to_term_special_case("builtin", "int", [], Univ, Context,
term__functor(term__integer(Int), [], Context)) :-
det_univ_to_type(Univ, Int).
term__univ_to_term_special_case("builtin", "float", [], Univ, Context,
term__functor(term__float(Float), [], Context)) :-
det_univ_to_type(Univ, Float).
term__univ_to_term_special_case("builtin", "character", [], Univ,
Context, term__functor(term__atom(CharName), [], Context)) :-
det_univ_to_type(Univ, Character),
string__char_to_string(Character, CharName).
term__univ_to_term_special_case("builtin", "string", [], Univ, Context,
term__functor(term__string(String), [], Context)) :-
det_univ_to_type(Univ, String).
term__univ_to_term_special_case("std_util", "type_info", [], Univ, Context,
term__functor(term__atom("type_info"), [Term], Context)) :-
det_univ_to_type(Univ, TypeInfo),
type_info_to_term(Context, TypeInfo, Term).
term__univ_to_term_special_case("std_util", "univ", [], Univ, Context, Term) :-
Term = term__functor(term__atom("univ"),
% XXX what operator should we use for type
% qualification?
[term__functor(term__atom(":"), % TYPE_QUAL_OP
[ValueTerm, TypeTerm],
Context)], Context),
type_info_to_term(Context, univ_type(Univ), TypeTerm),
UnivValue = univ_value(Univ),
term__type_to_term(UnivValue, ValueTerm).
term__univ_to_term_special_case("array", "array", [ElemType], Univ, Context,
Term) :-
Term = term__functor(term__atom("array"), [ArgsTerm], Context),
has_type(Elem, ElemType),
same_type(List, [Elem]),
det_univ_to_type(Univ, Array),
array__to_list(Array, List),
term__type_to_term(List, ArgsTerm).
:- pred same_type(T::unused, T::unused) is det.
same_type(_, _).
:- pred term__univ_list_to_term_list(list(univ)::in,
list(term(T))::out) is det.
term__univ_list_to_term_list([], []).
term__univ_list_to_term_list([Value|Values], [Term|Terms]) :-
term__univ_to_term(Value, Term),
term__univ_list_to_term_list(Values, Terms).
% given a type_info, return a term that represents the name of that type.
:- pred type_info_to_term(term__context::in, type_info::in,
term(T)::out) is det.
type_info_to_term(Context, TypeInfo, Term) :-
type_ctor_and_args(TypeInfo, TypeCtor, ArgTypes),
TypeName = type_ctor_name(TypeCtor),
ModuleName = type_ctor_name(TypeCtor),
list__map(type_info_to_term(Context), ArgTypes, ArgTerms),
/*
** XXX the test for mercury_builtin is for bootstrapping only,
** and should eventually be deleted
*/
( (ModuleName = "mercury_builtin" ; ModuleName = "builtin") ->
Term = term__functor(term__atom(TypeName), ArgTerms, Context)
;
Term = term__functor(term__atom(":"),
[term__functor(term__atom(ModuleName), [], Context),
term__functor(term__atom(TypeName),
ArgTerms, Context)], Context)
).
:- pred require_equal(T::in, T::in) is det.
require_equal(X, Y) :-
( X = Y ->
true
;
error("require_equal failed")
).
%-----------------------------------------------------------------------------%
% term__vars(Term, Vars) is true if Vars is the list of variables
% contained in Term obtained by depth-first left-to-right traversal
% in that order.
term__vars(Term, Vars) :-
term__vars_2(Term, [], Vars).
term__vars_list(Terms, Vars) :-
term__vars_2_list(Terms, [], Vars).
term__vars_2(term__variable(V), Vs, [V|Vs]).
term__vars_2(term__functor(_,Args,_), Vs0, Vs) :-
term__vars_2_list(Args, Vs0, Vs).
:- pred term__vars_2_list(list(term(T)), list(var(T)), list(var(T))).
:- mode term__vars_2_list(in, in, out) is det.
term__vars_2_list([], Vs, Vs).
term__vars_2_list([T|Ts], Vs0, Vs) :-
term__vars_2_list(Ts, Vs0, Vs1),
term__vars_2(T, Vs1, Vs).
%-----------------------------------------------------------------------------%
% term__contains_var(Term, Var) is true if Var occurs in Term.
term__contains_var(term__variable(V), V).
term__contains_var(term__functor(_, Args, _), V) :-
term__contains_var_list(Args, V).
term__contains_var_list([T|_], V) :-
term__contains_var(T, V).
term__contains_var_list([_|Ts], V) :-
term__contains_var_list(Ts, V).
%-----------------------------------------------------------------------------%
% term__contains_functor(Term, Functor, Args):
% term__functor(Functor, Args, _) is a subterm of Term.
%
% CURRENTLY NOT USED.
:- pred term__contains_functor(term(T), const, list(term(T))).
% :- mode term__contains_functor(in, in, in) is semidet.
:- mode term__contains_functor(in, out, out) is nondet.
term__contains_functor(term__functor(Functor, Args, _), Functor, Args).
term__contains_functor(term__functor(_, Args, _), SubFunctor, SubArgs) :-
list__member(SubTerm, Args),
term__contains_functor(SubTerm, SubFunctor, SubArgs).
%-----------------------------------------------------------------------------%
% term__subterm(Term, SubTerm):
% SubTerm is a subterm of Term.
%
% CURRENTLY NOT USED.
:- pred term__subterm(term(T), term(T)).
:- mode term__subterm(in, in) is semidet.
:- mode term__subterm(in, out) is multidet.
term__subterm(Term, Term).
term__subterm(term__functor(_, Args, _), SubTerm) :-
list__member(Term, Args),
term__subterm(Term, SubTerm).
%-----------------------------------------------------------------------------%
% Access predicates for the term__context data structure.
% Given a term context, return the source line number.
term__context_line(term__context(_, LineNumber), LineNumber).
% Given a term context, return the source file.
term__context_file(term__context(FileName, _), FileName).
% Used to initialize the term context when reading in
% (or otherwise constructing) a term.
term__context_init(term__context("", 0)).
term__context_init(File, LineNumber, term__context(File, LineNumber)).
%-----------------------------------------------------------------------------%
% Unify two terms (with occurs check), updating the bindings of
% the variables in the terms.
term__unify(term__variable(X), term__variable(Y), Bindings0, Bindings) :-
( %%% if some [BindingOfX]
map__search(Bindings0, X, BindingOfX)
->
( %%% if some [BindingOfY]
map__search(Bindings0, Y, BindingOfY)
->
% both X and Y already have bindings - just
% unify the terms they are bound to
term__unify(BindingOfX, BindingOfY, Bindings0, Bindings)
;
% Y is a variable which hasn't been bound yet
term__apply_rec_substitution(BindingOfX, Bindings0,
SubstBindingOfX),
( SubstBindingOfX = term__variable(Y) ->
Bindings = Bindings0
;
\+ term__occurs(SubstBindingOfX, Y, Bindings0),
map__set(Bindings0, Y, SubstBindingOfX,
Bindings)
)
)
;
( %%% if some [BindingOfY2]
map__search(Bindings0, Y, BindingOfY2)
->
% X is a variable which hasn't been bound yet
term__apply_rec_substitution(BindingOfY2, Bindings0,
SubstBindingOfY2),
( SubstBindingOfY2 = term__variable(X) ->
Bindings = Bindings0
;
\+ term__occurs(SubstBindingOfY2, X, Bindings0),
map__set(Bindings0, X, SubstBindingOfY2,
Bindings)
)
;
% both X and Y are unbound variables -
% bind one to the other
( X = Y ->
Bindings = Bindings0
;
map__set(Bindings0, X, term__variable(Y),
Bindings)
)
)
).
term__unify(term__variable(X), term__functor(F, As, C), Bindings0, Bindings) :-
( %%% if some [BindingOfX]
map__search(Bindings0, X, BindingOfX)
->
term__unify(BindingOfX, term__functor(F, As, C), Bindings0,
Bindings)
;
\+ term__occurs_list(As, X, Bindings0),
map__set(Bindings0, X, term__functor(F, As, C), Bindings)
).
term__unify(term__functor(F, As, C), term__variable(X), Bindings0, Bindings) :-
( %%% if some [BindingOfX]
map__search(Bindings0, X, BindingOfX)
->
term__unify(term__functor(F, As, C), BindingOfX, Bindings0,
Bindings)
;
\+ term__occurs_list(As, X, Bindings0),
map__set(Bindings0, X, term__functor(F, As, C), Bindings)
).
term__unify(term__functor(F, AsX, _), term__functor(F, AsY, _)) -->
term__unify_list(AsX, AsY).
:- pred term__unify_list(list(term(T)), list(term(T)),
substitution(T), substitution(T)).
:- mode term__unify_list(in, in, in, out) is semidet.
term__unify_list([], []) --> [].
term__unify_list([X | Xs], [Y | Ys]) -->
term__unify(X, Y),
term__unify_list(Xs, Ys).
%-----------------------------------------------------------------------------%
% term__occurs(Term, Var, Subst) succeeds if Term contains Var,
% perhaps indirectly via the substitution. (The variable must
% not be mapped by the substitution.)
term__occurs(term__variable(X), Y, Bindings) :-
(
X = Y
->
true
;
map__search(Bindings, X, BindingOfX),
term__occurs(BindingOfX, Y, Bindings)
).
term__occurs(term__functor(_F, As, _), Y, Bindings) :-
term__occurs_list(As, Y, Bindings).
term__occurs_list([Term | Terms], Y, Bindings) :-
(
term__occurs(Term, Y, Bindings)
->
true
;
term__occurs_list(Terms, Y, Bindings)
).
%-----------------------------------------------------------------------------%
% term__substitute(Term0, Var, Replacement, Term) :
% replace all occurrences of Var in Term0 with Replacement,
% and return the result in Term.
term__substitute(term__variable(Var), SearchVar, Replacement, Term) :-
(
Var = SearchVar
->
Term = Replacement
;
Term = term__variable(Var)
).
term__substitute(term__functor(Name, Args0, Context), Var, Replacement,
term__functor(Name, Args, Context)) :-
term__substitute_list(Args0, Var, Replacement, Args).
term__substitute_list([], _Var, _Replacement, []).
term__substitute_list([Term0 | Terms0], Var, Replacement, [Term | Terms]) :-
term__substitute(Term0, Var, Replacement, Term),
term__substitute_list(Terms0, Var, Replacement, Terms).
term__substitute_corresponding(Ss, Rs, Term0, Term) :-
map__init(Subst0),
( term__substitute_corresponding_2(Ss, Rs, Subst0, Subst) ->
term__apply_substitution(Term0, Subst, Term)
;
error("term__substitute_corresponding: different length lists")
).
term__substitute_corresponding_list(Ss, Rs, TermList0, TermList) :-
map__init(Subst0),
( term__substitute_corresponding_2(Ss, Rs, Subst0, Subst) ->
term__apply_substitution_to_list(TermList0, Subst, TermList)
;
error(
"term__substitute_corresponding_list: different length lists"
)
).
:- pred term__substitute_corresponding_2(list(var(T)), list(term(T)),
substitution(T), substitution(T)).
:- mode term__substitute_corresponding_2(in, in, in, out) is semidet.
term__substitute_corresponding_2([], [], Subst, Subst).
term__substitute_corresponding_2([S | Ss], [R | Rs], Subst0, Subst) :-
map__set(Subst0, S, R, Subst1),
term__substitute_corresponding_2(Ss, Rs, Subst1, Subst).
%-----------------------------------------------------------------------------%
term__apply_rec_substitution(term__variable(Var), Substitution, Term) :-
(
%some [Replacement]
map__search(Substitution, Var, Replacement)
->
% recursively apply the substition to the replacement
term__apply_rec_substitution(Replacement, Substitution, Term)
;
Term = term__variable(Var)
).
term__apply_rec_substitution(term__functor(Name, Args0, Context), Substitution,
term__functor(Name, Args, Context)) :-
term__apply_rec_substitution_to_list(Args0, Substitution, Args).
term__apply_rec_substitution_to_list([], _Substitution, []).
term__apply_rec_substitution_to_list([Term0 | Terms0], Substitution,
[Term | Terms]) :-
term__apply_rec_substitution(Term0, Substitution, Term),
term__apply_rec_substitution_to_list(Terms0, Substitution, Terms).
%-----------------------------------------------------------------------------%
term__apply_substitution(term__variable(Var), Substitution, Term) :-
(
%some [Replacement]
map__search(Substitution, Var, Replacement)
->
Term = Replacement
;
Term = term__variable(Var)
).
term__apply_substitution(term__functor(Name, Args0, Context), Substitution,
term__functor(Name, Args, Context)) :-
term__apply_substitution_to_list(Args0, Substitution, Args).
term__apply_substitution_to_list([], _Substitution, []).
term__apply_substitution_to_list([Term0 | Terms0], Substitution,
[Term | Terms]) :-
term__apply_substitution(Term0, Substitution, Term),
term__apply_substitution_to_list(Terms0, Substitution, Terms).
%-----------------------------------------------------------------------------%
% create a new supply of variables
term__init_var_supply(var_supply(0)).
% We number variables using sequential numbers,
term__create_var(var_supply(V0), var(V), var_supply(V)) :-
V is V0 + 1.
%-----------------------------------------------------------------------------%
term__var_to_int(var(Var), Var).
%-----------------------------------------------------------------------------%
% substitute a variable name in a term.
term__relabel_variable(term__functor(Const, Terms0, Cont), OldVar, NewVar,
term__functor(Const, Terms, Cont)) :-
term__relabel_variables(Terms0, OldVar, NewVar, Terms).
term__relabel_variable(term__variable(Var0), OldVar, NewVar,
term__variable(Var)) :-
(
Var0 = OldVar
->
Var = NewVar
;
Var = Var0
).
term__relabel_variables([], _, _, []).
term__relabel_variables([Term0|Terms0], OldVar, NewVar, [Term|Terms]):-
term__relabel_variable(Term0, OldVar, NewVar, Term),
term__relabel_variables(Terms0, OldVar, NewVar, Terms).
term__apply_variable_renaming(term__functor(Const, Args0, Cont), Renaming,
term__functor(Const, Args, Cont)) :-
term__apply_variable_renaming_to_list(Args0, Renaming, Args).
term__apply_variable_renaming(term__variable(Var0), Renaming,
term__variable(Var)) :-
(
map__search(Renaming, Var0, NewVar)
->
Var = NewVar
;
Var = Var0
).
term__apply_variable_renaming_to_list([], _, []).
term__apply_variable_renaming_to_list([Term0|Terms0], Renaming, [Term|Terms]) :-
term__apply_variable_renaming(Term0, Renaming, Term),
term__apply_variable_renaming_to_list(Terms0, Renaming, Terms).
%-----------------------------------------------------------------------------%
term__term_list_to_var_list(Terms, Vars) :-
( term__var_list_to_term_list(Vars0, Terms) ->
Vars = Vars0
;
error("term__term_list_to_var_list")
).
term__var_list_to_term_list([], []).
term__var_list_to_term_list([Var | Vars], [term__variable(Var) | Terms]) :-
term__var_list_to_term_list(Vars, Terms).
%-----------------------------------------------------------------------------%
term__is_ground(term__variable(V), Bindings) :-
map__search(Bindings, V, Binding),
term__is_ground(Binding, Bindings).
term__is_ground(term__functor(_, Args, _), Bindings) :-
term__is_ground_2(Args, Bindings).
:- pred term__is_ground_2(list(term(T)), substitution(T)).
:- mode term__is_ground_2(in, in) is semidet.
term__is_ground_2([], _Bindings).
term__is_ground_2([Term|Terms], Bindings) :-
term__is_ground(Term, Bindings),
term__is_ground_2(Terms, Bindings).
%-----------------------------------------------------------------------------%
term__is_ground(term__functor(_, Args, _)) :-
term__is_ground_2(Args).
:- pred term__is_ground_2(list(term(T))).
:- mode term__is_ground_2(in) is semidet.
term__is_ground_2([]).
term__is_ground_2([Term|Terms]) :-
term__is_ground(Term),
term__is_ground_2(Terms).
%-----------------------------------------------------------------------------%
term__compare(Cmp, Term1, Term2, Bindings) :-
term__apply_rec_substitution(Term1, Bindings, TermA),
term__is_ground(TermA, Bindings),
term__apply_rec_substitution(Term2, Bindings, TermB),
term__is_ground(TermB, Bindings),
compare(Cmp, TermA, TermB).
%-----------------------------------------------------------------------------%
term__generic_term(_).
%-----------------------------------------------------------------------------%
term__coerce(term__variable(var(V)), term__variable(var(V))).
term__coerce(term__functor(Cons, Args0, Ctxt),
term__functor(Cons, Args, Ctxt)) :-
list__map(term__coerce, Args0, Args).
term__coerce_var(var(V), var(V)).
term__coerce_var_supply(var_supply(Supply), var_supply(Supply)).