%--------------------------------------------------% % vim: ft=mercury ts=4 sw=4 et %--------------------------------------------------% % Copyright (C) 2002-2007 The University of Melbourne. % Copyright (C) 2014-2015, 2017-2022 The Mercury team. % This file is distributed under the terms specified in COPYING.LIB. %--------------------------------------------------% % % File: deconstruct.m. % Main author: zs. % Stability: low. % %--------------------------------------------------% %--------------------------------------------------% :- module deconstruct. :- interface. :- import_module construct. :- import_module list. :- import_module maybe. :- import_module univ. %--------------------------------------------------% % Values of type noncanon_handling are intended to control how % predicates that deconstruct terms behave when they find that % the term they are about to deconstruct is of a noncanonical type, % i.e. of a type in which a single logical value may have more than one % concrete representation. % % The value `do_not_allow' means that in such circumstances the % predicate should cause a runtime abort. % % The value `canonicalize' means that in such circumstances the % predicate should return a constant giving the identity of the type, % regardless of the actual value of the term. % % The value `include_details_cc' means that in such circumstances % the predicate should proceed as if the term were of a canonical type. % Use of this option requires a committed choice context. :- type noncanon_handling ---> do_not_allow ; canonicalize ; include_details_cc. :- inst do_not_allow for noncanon_handling/0 ---> do_not_allow. :- inst canonicalize for noncanon_handling/0 ---> canonicalize. :- inst include_details_cc for noncanon_handling/0 ---> include_details_cc. :- inst canonicalize_or_do_not_allow for noncanon_handling/0 ---> do_not_allow ; canonicalize. :- inst do_not_allow_or_include_details_cc for noncanon_handling/0 ---> do_not_allow ; include_details_cc. % functor, argument and deconstruct and their variants take any type % (including univ), and return representation information for that type. % % The string representation of the functor that these predicates % return is: % % - for user defined types with standard equality, the functor % that is given in the type definition. For lists, this means % the functors [|]/2 and []/0 are used, even if the list uses % the [....] shorthand. % - for user-defined types with user-defined equality, the % functor will be of the form <<module.type/arity>>, except % with include_details_cc, in which case the type will be % handled as if it had standard equality. % - for integers, the string is a base 10 number; % positive integers have no sign. % - for finite floats, the string is a base 10 floating point number; % positive floating point numbers have no sign; % for infinite floats, the string "infinity" or "-infinity". % - for strings, the string, inside double quotation marks using % backslash escapes if necessary and backslash or octal escapes for % all characters for which char.is_control/1 is true. % - for characters, the character inside single quotation marks using % a backslash escape if necessary and a backslash or octal escape for % for all characters for which char.is_control/1 is true. % - for predicates, the string <<predicate>>, and for functions, % the string <<function>>, except with include_details_cc, % in which case it will be the predicate or function name. % (The predicate or function name will be artificial for % predicate and function values created by lambda expressions.) % - for tuples, the string {}. % - for arrays, the string <<array>>. % - for c_pointers, the string c_pointer(0xXXXX) where XXXX is the % hexadecimal representation of the pointer. % - for foreign types, a string of the form <<foreign(Name, Rep)>> where % Name is the type's Mercury name and Rep is a target language specific % representation of the term's value. % - for bitmaps, the bitmap converted to a length and a % hexadecimal string inside angle brackets and quotes of the % form """<[0-9]:[0-9A-F]*>""". % % The arity that these predicates return is: % % - for user defined types with standard equality, the arity % of the functor. % - for user defined types with user-defined equality, zero, % except with include_details_cc, in which case the type % will be handled as if it had standard equality. % - for integers, zero. % - for floats, zero. % - for strings, zero. % - for characters, zero. % - for predicates and functions, zero, except with % include_details_cc, in which case it will be the number of % arguments hidden in the closure. % - for tuples, the number of elements in the tuple. % - for arrays, the number of elements in the array. % - for c_pointers, zero. % - for foreign types, zero. % - for bitmaps, zero. % % Note that in the current University of Melbourne implementation, % the implementations of these predicates depart from the above % specification in that with --high-level-code, they do not % deconstruct predicate- and function-valued terms even with % include_details_cc; instead, they return <<predicate>> or % <<function>> (in both cases with arity zero) as appropriate. % functor(Data, NonCanon, Functor, Arity) % % Given a data item (Data), binds Functor to a string representation % of the functor and Arity to the arity of this data item. % :- pred functor(T, noncanon_handling, string, int). :- mode functor(in, in(do_not_allow), out, out) is det. :- mode functor(in, in(canonicalize), out, out) is det. :- mode functor(in, in(include_details_cc), out, out) is cc_multi. :- mode functor(in, in, out, out) is cc_multi. % functor_number(Data, FunctorNumber, Arity) % % Given a data item, return the number of the functor, % suitable for use by construct.construct, and the arity. % Fail if the item does not have a discriminated union type. % Cause a runtime abort if the type has user-defined equality. % :- pred functor_number(T::in, functor_number_lex::out, int::out) is semidet. % functor_number_cc(Data, FunctorNumber, Arity) % % Given a data item, return the number of the functor, % suitable for use by construct.construct, and the arity. % Fail if the item does not have a discriminated union type. % Do not cause a runtime abort if the type has user-defined equality. % :- pred functor_number_cc(T::in, functor_number_lex::out, int::out) is cc_nondet. % arg(Data, NonCanon, Index, Argument) % % Given a data item (Data) and an argument index (Index), starting % at 0 for the first argument, binds Argument to that argument of % the functor of the data item. If the argument index is out of range % -- that is, greater than or equal to the arity of the functor or % lower than 0 -- then the call fails. % % Note that this predicate only returns an answer when NonCanon is % do_not_allow or canonicalize. If you need the include_details_cc % behaviour use deconstruct.arg_cc/3. % :- some [ArgT] pred arg(T, noncanon_handling, int, ArgT). :- mode arg(in, in(do_not_allow), in, out) is semidet. :- mode arg(in, in(canonicalize), in, out) is semidet. :- mode arg(in, in(canonicalize_or_do_not_allow), in, out) is semidet. :- type maybe_arg ---> some [T] arg(T) ; no_arg. % arg_cc/3 is similar to arg/4, except that it handles arguments with % non-canonical types. The possible non-existence of an argument is % encoded using a maybe type. % :- pred arg_cc(T::in, int::in, maybe_arg::out) is cc_multi. % named_arg(Data, NonCanon, Name, Argument) % % Same as arg/4, except the chosen argument is specified by giving % its name rather than its position. If Data has no argument with that % name, named_arg fails. % :- some [ArgT] pred named_arg(T, noncanon_handling, string, ArgT). :- mode named_arg(in, in(do_not_allow), in, out) is semidet. :- mode named_arg(in, in(canonicalize), in, out) is semidet. :- mode named_arg(in, in(canonicalize_or_do_not_allow), in, out) is semidet. % named_arg_cc/3 is similar to named_arg/4, except that it handles % arguments with non-canonical types. % :- pred named_arg_cc(T::in, string::in, maybe_arg::out) is cc_multi. % det_arg(Data, NonCanon, Index, Argument) % % Same as arg/4, except that for cases where arg/4 would fail, % det_arg/4 will throw an exception. % :- some [ArgT] pred det_arg(T, noncanon_handling, int, ArgT). :- mode det_arg(in, in(do_not_allow), in, out) is det. :- mode det_arg(in, in(canonicalize), in, out) is det. :- mode det_arg(in, in(include_details_cc), in, out) is cc_multi. :- mode det_arg(in, in, in, out) is cc_multi. % det_named_arg(Data, NonCanon, Name, Argument) % % Same as named_arg/4, except that for cases where named_arg/4 would fail, % det_named_arg/4 will throw an exception. % :- some [ArgT] pred det_named_arg(T, noncanon_handling, string, ArgT). :- mode det_named_arg(in, in(do_not_allow), in, out) is det. :- mode det_named_arg(in, in(canonicalize), in, out) is det. :- mode det_named_arg(in, in(include_details_cc), in, out) is cc_multi. :- mode det_named_arg(in, in, in, out) is cc_multi. % deconstruct(Data, NonCanon, Functor, Arity, Arguments) % % Given a data item (Data), binds Functor to a string representation % of the functor, Arity to the arity of this data item, and Arguments % to a list of arguments of the functor. The arguments in the list % are each of type univ. % % The cost of calling deconstruct depends greatly on how many arguments % Data has. If Data is an array, then each element of the array is % considered one of its arguments. Therefore calling deconstruct % on large arrays can take a very large amount of memory and a very % long time. If you call deconstruct in a situation in which you may % pass it a large array, you should probably use limited_deconstruct % instead. % :- pred deconstruct(T, noncanon_handling, string, int, list(univ)). :- mode deconstruct(in, in(do_not_allow), out, out, out) is det. :- mode deconstruct(in, in(canonicalize), out, out, out) is det. :- mode deconstruct(in, in(include_details_cc), out, out, out) is cc_multi. :- mode deconstruct(in, in, out, out, out) is cc_multi. % deconstruct_du(Data, NonCanon, FunctorNumber, Arity, Arguments) % % Given a data item (Data) which has a discriminated union type, binds % FunctorNumber to the number of the functor in lexicographic order, % Arity to the arity of this data item, and Arguments to a list of % arguments of the functor. The arguments in the list are each of type % univ. % % Fails if Data does not have discriminated union type. % :- pred deconstruct_du(T, noncanon_handling, functor_number_lex, int, list(univ)). :- mode deconstruct_du(in, in(do_not_allow), out, out, out) is semidet. :- mode deconstruct_du(in, in(include_details_cc), out, out, out) is cc_nondet. :- mode deconstruct_du(in, in, out, out, out) is cc_nondet. % limited_deconstruct(Data, NonCanon, MaxArity, % Functor, Arity, Arguments) % % limited_deconstruct works like deconstruct, but if the arity of T is % greater than MaxArity, limited_deconstruct fails. This is useful in % avoiding bad performance in cases where Data may be a large array. % % Note that this predicate only returns an answer when NonCanon is % do_not_allow or canonicalize. If you need the include_details_cc % behaviour use deconstruct.limited_deconstruct_cc/3. % :- pred limited_deconstruct(T, noncanon_handling, int, string, int, list(univ)). :- mode limited_deconstruct(in, in(do_not_allow), in, out, out, out) is semidet. :- mode limited_deconstruct(in, in(canonicalize), in, out, out, out) is semidet. :- pred limited_deconstruct_cc(T::in, int::in, maybe({string, int, list(univ)})::out) is cc_multi. %--------------------------------------------------% %--------------------------------------------------%