Files
mercury/browser/term_rep.m
Zoltan Somogyi 9047bdbf05 Improve programming style in the browser directory.
browser/declarative_analyser.m:
browser/declarative_debugger.m:
browser/declarative_oracle.m:
browser/declarative_tree.m:
browser/declarative_user.m:
browser/interactive_query.m:
browser/listing.m:
browser/parse.m:
browser/util.m:
    Rename some predicates to avoid ambiguity.

    Factor out common code.

    If some versions of a field of a structure have names in a predicate
    (by being stored in a named variable), then give all *other* versions
    of that field in that structure names in that predicate as well.

    If a field of a structure is used more than once in a predicate,
    then again, store it in a named variable.

    Reorder predicate arguments to put state variables last.

    Use io.format instead of sequences of calls to io.write_string.

    In declarative_user.m, note a probable bug (in a position where
    it is probably rarely stumbled upon).

    In listing.m, use a consistent naming scheme to differentiate
    between Mercury streams and their C counterparts.

    Replace if-then-else chains with switches where possible.

browser/name_mangle.m:
    Note bit rot.

browser/browse.m:
    Conform to the changes above.

library/io.m:
    Improve predicate and variable names.

browser/mdb.m:
browser/mer_browser.m:
browser/percent_encoding.m:
browser/term_rep.m:
browser/tree234_cc.m:
library/library.m:
    Improve comments.
2022-07-03 13:55:54 +10:00

196 lines
6.1 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 its 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(pred(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(pred(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
).
%---------------------------------------------------------------------------%
:- end_module mdb.term_rep.
%---------------------------------------------------------------------------%