Next: version_array, Previous: univ, Up: Top [Contents]
%--------------------------------------------------% % vim: ft=mercury ts=4 sw=4 et %--------------------------------------------------% % Copyright (C) 1993-2000,2002-2007, 2009-2011 The University of Melbourne. % Copyright (C) 2014-2024 The Mercury team. % This file is distributed under the terms specified in COPYING.LIB. %--------------------------------------------------% % % File: varset.m. % Main author: fjh. % Stability: low. % % This file provides facilities for manipulating collections of variables, % through the 'varset' abstract data type. These variables are object-level % variables, and are represented as ground terms, so the right way to think % of them is as "variable ids" rather than Prolog-style variables. % % A varset may record a name and/or a value (binding) with each variable. % % Many situations require dealing with several distinct sets of variables % that should never be mixed together. For example, a compiler may handle % both program variables and type variables, and it does not make sense % to a have a single varset containing both program variables and type % variables. The varsets provided by this module are thus parameterized; % the compiler can use e.g. varset(prog_var_type) to hold program variables % and varset(tvar_type) to hold type variables. Since all operations on % two or more varsets require agreement on the argument of the varset/1 % type constructor, any accidental mixup of different instances of varset/1 % is guaranteed to be caught by the compiler. % % In situations in which this is not a concern, programmers may use % the standard generic varset instance. % % Note that varset.m and term.m are strongly coupled together, meaning that % they each need the other. The reason why they have not been merged into % one larger module is that many user modules call predicates and functions % from just one of these two modules, even though, through that one module, % they implicitly depend on the other as well. % %--------------------------------------------------% %--------------------------------------------------% :- module varset. :- interface. :- import_module assoc_list. :- import_module list. :- import_module map. :- import_module maybe. :- import_module set. :- import_module term. %--------------------------------------------------% :- type varset(T). :- type varset == varset(generic). %--------------------------------------------------% % Construct an empty varset. % :- func init = varset(T). :- pred init(varset(T)::out) is det. % Check whether a varset is empty. % :- pred is_empty(varset(T)::in) is semidet. %--------------------------------------------------% % Create a new variable. % :- pred new_var(var(T)::out, varset(T)::in, varset(T)::out) is det. % Create a new named variable. % :- pred new_named_var(string::in, var(T)::out, varset(T)::in, varset(T)::out) is det. % Create a new named variable with a unique (w.r.t. the varset) number % appended to the name. % :- pred new_uniquely_named_var(string::in, var(T)::out, varset(T)::in, varset(T)::out) is det. % Create a new variable, and maybe give it a name. % :- pred new_maybe_named_var(maybe(string)::in, var(T)::out, varset(T)::in, varset(T)::out) is det. % Create multiple new variables. % Throws an exception if a negative number of new variables % is requested. % :- pred new_vars(int::in, list(var(T))::out, varset(T)::in, varset(T)::out) is det. %--------------------------------------------------% % Delete the name and value for a variable. % :- func delete_var(varset(T), var(T)) = varset(T). :- pred delete_var(var(T)::in, varset(T)::in, varset(T)::out) is det. % Delete the names and values for a list of variables. % :- func delete_vars(varset(T), list(var(T))) = varset(T). :- pred delete_vars(list(var(T))::in, varset(T)::in, varset(T)::out) is det. % Delete the names and values for a sorted list of variables. % (If the list is not sorted, the predicate or function will % either throw an exception or return incorrect output.) % :- func delete_sorted_vars(varset(T), list(var(T))) = varset(T). :- pred delete_sorted_vars(list(var(T))::in, varset(T)::in, varset(T)::out) is det. %--------------------------------------------------% % Return a list of all the variables in a varset. % :- func vars(varset(T)) = list(var(T)). :- pred vars(varset(T)::in, list(var(T))::out) is det. %--------------------------------------------------% % Set the name of a variable. % :- func name_var(varset(T), var(T), string) = varset(T). :- pred name_var(var(T)::in, string::in, varset(T)::in, varset(T)::out) is det. % Unset the name of a variable. % :- func unname_var(varset(T), var(T)) = varset(T). :- pred unname_var(var(T)::in, varset(T)::in, varset(T)::out) is det. % Look up the name of a variable; % If it doesn't have one, return a default name consisting of two parts: % "V_" as a prefix, followed by a unique number. This is meant to evoke % "variable number N". % :- func lookup_name(varset(T), var(T)) = string. :- pred lookup_name(varset(T)::in, var(T)::in, string::out) is det. % Look up the name of a variable; % if it doesn't have one, create one using the specified prefix. % :- func lookup_name_default_prefix(varset(T), var(T), string) = string. :- pred lookup_name_default_prefix(varset(T)::in, var(T)::in, string::in, string::out) is det. % The old, now obsolete name for what is now lookup_name_default_prefix. % :- func lookup_name(varset(T), var(T), string) = string. :- pred lookup_name(varset(T)::in, var(T)::in, string::in, string::out) is det. :- pragma obsolete(func(lookup_name/3), [varset.lookup_name_default_prefix/3]). :- pragma obsolete(pred(lookup_name/4), [varset.lookup_name_default_prefix/4]). % Look up the name of a variable; % fail if it doesn't have one. % :- pred search_name(varset(T)::in, var(T)::in, string::out) is semidet. %--------------------------------------------------% % Bind a value to a variable. % This will overwrite any existing binding. % :- func bind_var(varset(T), var(T), term(T)) = varset(T). :- pred bind_var(var(T)::in, term(T)::in, varset(T)::in, varset(T)::out) is det. % Bind a set of terms to a set of variables. % :- func bind_vars(varset(T), substitution(T)) = varset(T). :- pred bind_vars(substitution(T)::in, varset(T)::in, varset(T)::out) is det. % Look up the value of a variable. % :- pred search_var(varset(T)::in, var(T)::in, term(T)::out) is semidet. %--------------------------------------------------% % Get the bindings for all the bound variables. % :- func lookup_vars(varset(T)) = substitution(T). :- pred lookup_vars(varset(T)::in, substitution(T)::out) is det. :- pragma obsolete(func(lookup_vars/1), [varset.get_bindings/1]). :- pragma obsolete(pred(lookup_vars/2), [varset.get_bindings/2]). % Get the bindings for all the bound variables. % :- func get_bindings(varset(T)) = substitution(T). :- pred get_bindings(varset(T)::in, substitution(T)::out) is det. % Set the bindings for all the bound variables. % :- func set_bindings(varset(T), substitution(T)) = varset(T). :- pred set_bindings(substitution(T)::in, varset(T)::in, varset(T)::out) is det. %--------------------------------------------------% % Combine two different varsets, renaming apart: % merge_renaming(VarSet0, NewVarSet, VarSet, Renaming) is true % iff VarSet is the varset that results from joining a suitably renamed % version of NewVarSet to VarSet0. (Any bindings in NewVarSet are ignored.) % Renaming will map each variable in NewVarSet to the corresponding % fresh variable in VarSet. % :- pred merge_renaming(varset(T)::in, varset(T)::in, varset(T)::out, renaming(T)::out) is det. % Same as merge_renaming, except that the names of variables % in NewVarSet are not included in the final varset. % This is useful if create_name_var_map needs to be used % on the resulting varset. % :- pred merge_renaming_without_names(varset(T)::in, varset(T)::in, varset(T)::out, renaming(T)::out) is det. % merge(VarSet0, NewVarSet, Terms0, VarSet, Terms): % % As merge_renaming, except instead of returning the renaming, % this predicate applies it to the given list of terms. % :- pred merge(varset(T)::in, varset(T)::in, list(term(T))::in, varset(T)::out, list(term(T))::out) is det. % Same as merge, except that the names of variables % in NewVarSet are not included in the final varset. % This is useful if create_name_var_map needs to be used % on the resulting varset. % :- pred merge_without_names(varset(T)::in, varset(T)::in, list(term(T))::in, varset(T)::out, list(term(T))::out) is det. %--------------------------------------------------% % Create a map from names to variables. % Each name is mapped to only one variable, even if a name is % shared by more than one variable. Therefore this predicate % is only really useful if it is already known that no two % variables share the same name. % :- func create_name_var_map(varset(T)) = map(string, var(T)). :- pred create_name_var_map(varset(T)::in, map(string, var(T))::out) is det. % Return an association list giving the name of each variable. % Every variable has an entry in the returned association list, % even if it shares its name with another variable. % :- func var_name_list(varset(T)) = assoc_list(var(T), string). :- pred var_name_list(varset(T)::in, assoc_list(var(T), string)::out) is det. % Given a list of variable and varset in which some variables have % no name but some other variables may have the same name, % return another varset in which every variable has a unique name. % If necessary, names will have suffixes added on the end; % the second argument gives the suffix to use. % :- func ensure_unique_names(list(var(T)), string, varset(T)) = varset(T). :- pred ensure_unique_names(list(var(T))::in, string::in, varset(T)::in, varset(T)::out) is det. % Unname all variables whose explicitly given names have the form % of the default names used by lookup_name, i.e. "V_" followed by % an integer. % % This predicate is intended to be used in situations where % a term has been read in after being written out. The process of % writing out the term requires giving every variable a name % that can be written out, even variables that until then did not % have names. If these variables are given names of the default form, then, % after the written-out term is read back in, this predicate will recreate % the original varset, including the variables without names. % :- pred undo_default_names(varset(T)::in, varset(T)::out) is det. %--------------------------------------------------% % Given a varset and a set of variables, remove the names % and values of any other variables stored in the varset. % :- func select(varset(T), set(var(T))) = varset(T). :- pred select(set(var(T))::in, varset(T)::in, varset(T)::out) is det. % Given a varset and a list of variables, construct a new varset % containing one variable for each one in the list, and no others. % Also return a substitution mapping the selected variables in the % original varset into variables in the new varset. The relative % ordering of variables in the original varset is maintained. % :- pred squash(varset(T)::in, list(var(T))::in, varset(T)::out, renaming(T)::out) is det. % Coerce the types of the variables in a varset. % :- func coerce(varset(T)) = varset(U). :- pred coerce(varset(T)::in, varset(U)::out) is det. %--------------------------------------------------% %--------------------------------------------------%
Next: version_array, Previous: univ, Up: Top [Contents]