mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-10 19:33:11 +00:00
Discussion of these changes can be found on the Mercury developers
mailing list archives from June 2018.
COPYING.LIB:
Add a special linking exception to the LGPL.
*:
Update references to COPYING.LIB.
Clean up some minor errors that have accumulated in copyright
messages.
192 lines
5.9 KiB
Mathematica
192 lines
5.9 KiB
Mathematica
%---------------------------------------------------------------------------%
|
|
% vim: ft=mercury ts=4 sw=4 et
|
|
%---------------------------------------------------------------------------%
|
|
% Copyright (C) 1999-2007 The University of Melbourne.
|
|
% Copyright (C) 2015, 2017-2018 The Mercury team.
|
|
% This file is distributed under the terms specified in COPYING.LIB.
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
% File: term_rep.m.
|
|
% Author: Ian MacLarty.
|
|
%
|
|
% This module implements an abstract type, term_rep, values of which are the
|
|
% representation of some other value. Constructing a representation from a
|
|
% term is cc_multi, but then doing comparisons on the representation is
|
|
% deterministic.
|
|
%
|
|
% This is useful when we only want to consider the representation of a term
|
|
% and don't care about it's actual value.
|
|
%
|
|
%---------------------------------------------------------------------------%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- module mdb.term_rep.
|
|
:- interface.
|
|
|
|
:- import_module mdbcomp.
|
|
:- import_module mdbcomp.program_representation.
|
|
|
|
:- import_module univ.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- type term_rep.
|
|
|
|
:- pred univ_to_rep(univ::in, term_rep::out) is cc_multi.
|
|
|
|
:- pred rep_to_univ(term_rep::in, univ::out) is det.
|
|
|
|
:- pred deref_path(term_rep::in, term_path::in, term_rep::out) is semidet.
|
|
|
|
% argument(Term, N, Subterm):
|
|
%
|
|
% True iff Subterm is the Nth argument of Term.
|
|
%
|
|
:- pred argument(term_rep::in, int::in, term_rep::out) is semidet.
|
|
|
|
% field_pos(FieldName, Term, N):
|
|
%
|
|
% True iff argument N of Term has the name FieldName.
|
|
%
|
|
:- pred field_pos(string::in, term_rep::in, int::out) is semidet.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
:- import_module mdb.declarative_debugger.
|
|
|
|
:- import_module construct.
|
|
:- import_module deconstruct.
|
|
:- import_module exception.
|
|
:- import_module int.
|
|
:- import_module list.
|
|
:- import_module maybe.
|
|
:- import_module type_desc.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- type term_rep
|
|
---> term_rep(univ)
|
|
where
|
|
equality is term_rep_equal,
|
|
comparison is term_rep_compare.
|
|
|
|
:- pred term_rep_equal(term_rep::in, term_rep::in) is semidet.
|
|
:- pragma terminates(term_rep_equal/2).
|
|
|
|
term_rep_equal(Rep1, Rep2) :-
|
|
promise_equivalent_solutions [Result] (
|
|
comp_rep_2(Rep1, Rep2, Result)
|
|
),
|
|
Result = (=).
|
|
|
|
:- pred comp_rep_2(term_rep::in, term_rep::in, builtin.comparison_result::uo)
|
|
is cc_multi.
|
|
|
|
comp_rep_2(Rep1, Rep2, Result) :-
|
|
builtin.compare_representation(Result, Rep1, Rep2).
|
|
|
|
:- pred term_rep_compare(builtin.comparison_result::uo, term_rep::in,
|
|
term_rep::in) is det.
|
|
:- pragma terminates(term_rep_compare/3).
|
|
|
|
term_rep_compare(Result, Rep1, Rep2) :-
|
|
promise_equivalent_solutions [Result] (
|
|
comp_rep_2(Rep1, Rep2, Result)
|
|
).
|
|
|
|
univ_to_rep(Univ0, term_rep(Univ)) :-
|
|
cc_multi_equal(Univ0, Univ).
|
|
|
|
rep_to_univ(Rep, Univ) :-
|
|
promise_equivalent_solutions [Univ] (
|
|
Rep = term_rep(Univ)
|
|
).
|
|
|
|
deref_path(Term, Path, SubTerm):-
|
|
(
|
|
Path = [],
|
|
SubTerm = Term
|
|
;
|
|
Path = [Head | Tail],
|
|
argument(Term, Head, NextSubTerm),
|
|
deref_path(NextSubTerm, Tail, SubTerm)
|
|
).
|
|
|
|
argument(Term, N, Arg) :-
|
|
% There is only one representation of a subterm, given
|
|
% the representation of the containing term and a term path.
|
|
promise_equivalent_solutions [MaybeArg] (
|
|
rep_to_univ(Term, Univ),
|
|
% Argument indexes in the term path start from one, but the argument
|
|
% function wants argument indexes to start from zero.
|
|
arg_cc(univ_value(Univ), N - 1, MaybeSubUniv),
|
|
(
|
|
MaybeSubUniv = arg(SubValue),
|
|
univ_to_rep(univ(SubValue), Arg0),
|
|
MaybeArg = yes(Arg0)
|
|
;
|
|
MaybeSubUniv = no_arg,
|
|
MaybeArg = no
|
|
)
|
|
),
|
|
MaybeArg = yes(Arg).
|
|
|
|
field_pos(FieldName, Term, Pos) :-
|
|
% There is only one or zero positions of a field
|
|
% given a representation of a term and the field name.
|
|
promise_equivalent_solutions [MaybePos] (
|
|
rep_to_univ(Term, Univ),
|
|
Value = univ_value(Univ),
|
|
deconstruct(Value, include_details_cc, Functor, Arity, _Args),
|
|
Type = type_of(Value),
|
|
( if NumFunctors = num_functors(Type) then
|
|
find_functor(1, NumFunctors, Type, Functor, Arity,
|
|
MaybeFunctorNum)
|
|
else
|
|
MaybeFunctorNum = no
|
|
),
|
|
(
|
|
MaybeFunctorNum = yes(FunctorNum),
|
|
( if
|
|
get_functor_with_names(Type, FunctorNum - 1,
|
|
_FunctorName, _Arity, _ArgTypes, ArgNames)
|
|
then
|
|
( if
|
|
list.index1_of_first_occurrence(ArgNames, yes(FieldName),
|
|
Pos0)
|
|
then
|
|
MaybePos = yes(Pos0)
|
|
else
|
|
MaybePos = no
|
|
)
|
|
else
|
|
throw(internal_error("field_pos",
|
|
"get_functor_with_names couldn't find functor"))
|
|
)
|
|
;
|
|
MaybeFunctorNum = no,
|
|
throw(internal_error("field_pos",
|
|
"find_functor couldn't find functor"))
|
|
)
|
|
),
|
|
MaybePos = yes(Pos).
|
|
|
|
:- pred find_functor(int::in, int::in, type_desc::in, string::in, int::in,
|
|
maybe(int)::out) is det.
|
|
|
|
find_functor(Current, NumFunctors, Type, FunctorName, Arity,
|
|
MaybeFunctorNum) :-
|
|
( if Current =< NumFunctors then
|
|
( if get_functor(Type, Current - 1, FunctorName, Arity, _) then
|
|
MaybeFunctorNum = yes(Current)
|
|
else
|
|
find_functor(Current + 1, NumFunctors, Type,
|
|
FunctorName, Arity, MaybeFunctorNum)
|
|
)
|
|
else
|
|
MaybeFunctorNum = no
|
|
).
|