mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-29 08:14:31 +00:00
Estimated hours taken: 50
Add support for nested modules.
- module names may themselves be module-qualified
- modules may contain `:- include_module' declarations
which name sub-modules
- a sub-module has access to all the declarations in the
parent module (including its implementation section).
This support is not yet complete; see the BUGS and LIMITATIONS below.
LIMITATIONS
- source file names must match module names
(just as they did previously)
- mmc doesn't allow path names on the command line any more
(e.g. `mmc --make-int ../library/foo.m').
- import_module declarations must use the fully-qualified module name
- module qualifiers must use the fully-qualified module name
- no support for root-qualified module names
(e.g. `:parent:child' instead of `parent:child').
- modules may not be physically nested (only logical nesting, via
`include_module').
BUGS
- doesn't check that the parent module is imported/used before allowing
import/use of its sub-modules.
- doesn't check that there is an include_module declaration in the
parent for each module claiming to be a child of that parent
- privacy of private modules is not enforced
-------------------
NEWS:
Mention that we support nested modules.
library/ops.m:
library/nc_builtin.nl:
library/sp_builtin.nl:
compiler/mercury_to_mercury.m:
Add `include_module' as a new prefix operator.
Change the associativity of `:' from xfy to yfx
(since this made parsing module qualifiers slightly easier).
compiler/prog_data.m:
Add new `include_module' declaration.
Change the `module_name' and `module_specifier' types
from strings to sym_names, so that module names can
themselves be module qualified.
compiler/modules.m:
Add predicates module_name_to_file_name/2 and
file_name_to_module_name/2.
Lots of changes to handle parent module dependencies,
to create parent interface (`.int0') files, to read them in,
to output correct dependencies information for them to the
`.d' and `.dep' files, etc.
Rewrite a lot of the code to improve the readability
(add comments, use subroutines, better variable names).
Also fix a couple of bugs:
- generate_dependencies was using the transitive implementation
dependencies rather than the transitive interface dependencies
to compute the `.int3' dependencies when writing `.d' files
(this bug was introduced during crs's changes to support
`.trans_opt' files)
- when creating the `.int' file, it was reading in the
interfaces for modules imported in the implementation section,
not just those in the interface section.
This meant that the compiler missed a lot of errors.
library/graph.m:
library/lexer.m:
library/term.m:
library/term_io.m:
library/varset.m:
compiler/*.m:
Add `:- import_module' declarations to the interface needed
by declarations in the interface. (The previous version
of the compiler did not detect these missing interface imports,
due to the above-mentioned bug in modules.m.)
compiler/mercury_compile.m:
compiler/intermod.m:
Change mercury_compile__maybe_grab_optfiles and
intermod__grab_optfiles so that they grab the opt files for
parent modules as well as the ones for imported modules.
compiler/mercury_compile.m:
Minor changes to handle parent module dependencies.
(Also improve the wording of the warning about trans-opt
dependencies.)
compiler/make_hlds.m:
compiler/module_qual.m:
Ignore `:- include_module' declarations.
compiler/module_qual.m:
A couple of small changes to handle nested module names.
compiler/prog_out.m:
compiler/prog_util.m:
Add new predicates string_to_sym_name/3 (prog_util.m) and
sym_name_to_string/{2,3} (prog_out.m).
compiler/*.m:
Replace many occurrences of `string' with `module_name'.
Change code that prints out module names or converts
them to strings or filenames to handle the fact that
module names are now sym_names intead of strings.
Also change a few places (e.g. in intermod.m, hlds_module.m)
where the code assumed that any qualified symbol was
fully-qualified.
compiler/prog_io.m:
compiler/prog_io_goal.m:
Move sym_name_and_args/3, parse_qualified_term/4 and
parse_qualified_term/5 preds from prog_io_goal.m to prog_io.m,
since they are very similar to the parse_symbol_name/2 predicate
already in prog_io.m. Rewrite these predicates, both
to improve maintainability, and to handle the newly
allowed syntax (module-qualified module names).
Rename parse_qualified_term/5 as `parse_implicit_qualified_term'.
compiler/prog_io.m:
Rewrite the handling of `:- module' and `:- end_module'
declarations, so that it can handle nested modules.
Add code to parse `include_module' declarations.
compiler/prog_util.m:
compiler/*.m:
Add new predicates mercury_public_builtin_module/1 and
mercury_private_builtin_module/1 in prog_util.m.
Change most of the hard-coded occurrences of "mercury_builtin"
to call mercury_private_builtin_module/1 or
mercury_public_builtin_module/1 or both.
compiler/llds_out.m:
Add llds_out__sym_name_mangle/2, for mangling module names.
compiler/special_pred.m:
compiler/mode_util.m:
compiler/clause_to_proc.m:
compiler/prog_io_goal.m:
compiler/lambda.m:
compiler/polymorphism.m:
Move the predicates in_mode/1, out_mode/1, and uo_mode/1
from special_pred.m to mode_util.m, and change various
hard-coded definitions to instead call these predicates.
compiler/polymorphism.m:
Ensure that the type names `type_info' and `typeclass_info' are
module-qualified in the generated code. This avoids a problem
where the code generated by polymorphism.m was not considered
type-correct, due to the type `type_info' not matching
`mercury_builtin:type_info'.
compiler/check_typeclass.m:
Simplify the code for check_instance_pred and
get_matching_instance_pred_ids.
compiler/mercury_compile.m:
compiler/modules.m:
Disallow directory names in command-line arguments.
compiler/options.m:
compiler/handle_options.m:
compiler/mercury_compile.m:
compiler/modules.m:
Add a `--make-private-interface' option.
The private interface file `<module>.int0' contains
all the declarations in the module; it is used for
compiling sub-modules.
scripts/Mmake.rules:
scripts/Mmake.vars.in:
Add support for creating `.int0' and `.date0' files
by invoking mmc with `--make-private-interface'.
doc/user_guide.texi:
Document `--make-private-interface' and the `.int0'
and `.date0' file extensions.
doc/reference_manual.texi:
Document nested modules.
util/mdemangle.c:
profiler/demangle.m:
Demangle names with multiple module qualifiers.
tests/general/Mmakefile:
tests/general/string_format_test.m:
tests/general/string_format_test.exp:
tests/general/string__format_test.m:
tests/general/string__format_test.exp:
tests/general/.cvsignore:
Change the `:- module string__format_test' declaration in
`string__format_test.m' to `:- module string_format_test',
because with the original declaration the `__' was taken
as a module qualifier, which lead to an error message.
Hence rename the file accordingly, to avoid the warning
about file name not matching module name.
tests/invalid/Mmakefile:
tests/invalid/missing_interface_import.m:
tests/invalid/missing_interface_import.err_exp:
Regression test to check that the compiler reports
errors for missing `import_module' in the interface section.
tests/invalid/*.err_exp:
tests/warnings/unused_args_test.exp:
tests/warnings/unused_import.exp:
Update the expected diagnostics output for the test cases to
reflect a few minor changes to the warning messages.
tests/hard_coded/Mmakefile:
tests/hard_coded/parent.m:
tests/hard_coded/parent.child.m:
tests/hard_coded/parent.exp:
tests/hard_coded/parent2.m:
tests/hard_coded/parent2.child.m:
tests/hard_coded/parent2.exp:
Two simple tests case for the use of nested modules with
separate compilation.
373 lines
12 KiB
Mathematica
373 lines
12 KiB
Mathematica
%-----------------------------------------------------------------------------%
|
|
% Copyright (C) 1997-1998 The University of Melbourne.
|
|
% This file may only be copied under the terms of the GNU General
|
|
% Public License - see the file COPYING in the Mercury distribution.
|
|
%-----------------------------------------------------------------------------%
|
|
%
|
|
% term_pass1.m
|
|
%
|
|
% Main author: crs.
|
|
% Significant parts rewritten by zs.
|
|
%
|
|
% This file contains the first pass of the termination analysis,
|
|
% whose job is to discover an upper bound on the difference between
|
|
% the sizes of the output arguments of a procedure on the one hand and
|
|
% the sizes of a selected set of input arguments of the procedure
|
|
% on the other hand. We refer to this selected set of input arguments
|
|
% as the "output suppliers".
|
|
%
|
|
% For details, please refer to the papers mentioned in termination.m.
|
|
%
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- module term_pass1.
|
|
|
|
:- interface.
|
|
|
|
:- import_module hlds_module, hlds_pred, term_util, term_errors.
|
|
:- import_module io, list, std_util.
|
|
|
|
:- type arg_size_result
|
|
---> ok(
|
|
list(pair(pred_proc_id, int)),
|
|
% Gives the gamma of each procedure
|
|
% in the SCC.
|
|
used_args
|
|
% Gives the output suppliers of
|
|
% each procedure in the SCC.
|
|
)
|
|
; error(
|
|
list(term_errors__error)
|
|
).
|
|
|
|
:- pred find_arg_sizes_in_scc(list(pred_proc_id)::in, module_info::in,
|
|
pass_info::in, arg_size_result::out, list(term_errors__error)::out,
|
|
io__state::di, io__state::uo) is det.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
:- import_module term_traversal, term_errors, hlds_goal, hlds_data.
|
|
:- import_module mode_util, type_util, lp.
|
|
|
|
:- import_module int, float, char, string, bool, set, bag, map.
|
|
:- import_module term, varset, require.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- type pass1_result
|
|
---> ok(
|
|
list(path_info),
|
|
% One entry for each path through the
|
|
% code.
|
|
used_args,
|
|
% The next output_supplier map.
|
|
list(term_errors__error)
|
|
% There is an entry in this list for
|
|
% each procedure in the SCC in which
|
|
% the set of active vars is not
|
|
% a subset of the input arguments.
|
|
)
|
|
; error(
|
|
list(term_errors__error)
|
|
).
|
|
|
|
find_arg_sizes_in_scc(SCC, Module, PassInfo, ArgSize, TermErrors, S0, S) :-
|
|
init_output_suppliers(SCC, Module, InitOutputSupplierMap),
|
|
find_arg_sizes_in_scc_fixpoint(SCC, Module, PassInfo,
|
|
InitOutputSupplierMap, Result, TermErrors),
|
|
(
|
|
Result = ok(Paths, OutputSupplierMap, SubsetErrors),
|
|
|
|
( SubsetErrors = [_ | _] ->
|
|
ArgSize = error(SubsetErrors),
|
|
S = S0
|
|
; Paths = [] ->
|
|
get_context_from_scc(SCC, Module, Context),
|
|
ArgSize = error([Context - no_eqns]),
|
|
S = S0
|
|
;
|
|
solve_equations(Paths, SCC, MaybeSolution, S0, S),
|
|
(
|
|
MaybeSolution = yes(Solution),
|
|
ArgSize = ok(Solution, OutputSupplierMap)
|
|
;
|
|
MaybeSolution = no,
|
|
get_context_from_scc(SCC, Module, Context),
|
|
ArgSize = error([Context - solver_failed])
|
|
)
|
|
)
|
|
;
|
|
Result = error(Errors),
|
|
ArgSize = error(Errors),
|
|
S = S0
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
% Initialise the output suppliers map.
|
|
% Initially, we consider that no input arguments contribute their size
|
|
% to the output arguments.
|
|
|
|
:- pred init_output_suppliers(list(pred_proc_id)::in, module_info::in,
|
|
used_args::out) is det.
|
|
|
|
init_output_suppliers([], _Module, InitMap) :-
|
|
map__init(InitMap).
|
|
init_output_suppliers([PPId | PPIds], Module, OutputSupplierMap) :-
|
|
init_output_suppliers(PPIds, Module, OutputSupplierMap0),
|
|
PPId = proc(PredId, ProcId),
|
|
module_info_pred_proc_info(Module, PredId, ProcId, _, ProcInfo),
|
|
proc_info_headvars(ProcInfo, HeadVars),
|
|
MapToNo = lambda([_HeadVar::in, Bool::out] is det, (Bool = no)),
|
|
list__map(MapToNo, HeadVars, BoolList),
|
|
map__det_insert(OutputSupplierMap0, PPId, BoolList, OutputSupplierMap).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- pred find_arg_sizes_in_scc_fixpoint(list(pred_proc_id)::in,
|
|
module_info::in, pass_info::in, used_args::in, pass1_result::out,
|
|
list(term_errors__error)::out) is det.
|
|
|
|
find_arg_sizes_in_scc_fixpoint(SCC, Module, PassInfo, OutputSupplierMap0,
|
|
Result, TermErrors) :-
|
|
% unsafe_perform_io(io__write_string("find_arg_sizes_in_scc_pass\n")),
|
|
% unsafe_perform_io(io__write(OutputSupplierMap0)),
|
|
% unsafe_perform_io(io__write_string("\n")),
|
|
find_arg_sizes_in_scc_pass(SCC, Module, PassInfo,
|
|
OutputSupplierMap0, [], [], Result1, [], TermErrors1),
|
|
(
|
|
Result1 = error(_),
|
|
Result = Result1,
|
|
TermErrors = TermErrors1
|
|
;
|
|
Result1 = ok(_, OutputSupplierMap1, _),
|
|
( OutputSupplierMap1 = OutputSupplierMap0 ->
|
|
Result = Result1,
|
|
TermErrors = TermErrors1
|
|
;
|
|
find_arg_sizes_in_scc_fixpoint(SCC, Module,
|
|
PassInfo, OutputSupplierMap1,
|
|
Result, TermErrors)
|
|
)
|
|
).
|
|
|
|
:- pred find_arg_sizes_in_scc_pass(list(pred_proc_id)::in,
|
|
module_info::in, pass_info::in, used_args::in,
|
|
list(path_info)::in, list(term_errors__error)::in, pass1_result::out,
|
|
list(term_errors__error)::in, list(term_errors__error)::out) is det.
|
|
|
|
find_arg_sizes_in_scc_pass([], _, _, OutputSupplierMap, Paths, SubsetErrors,
|
|
Result, TermErrors, TermErrors) :-
|
|
Result = ok(Paths, OutputSupplierMap, SubsetErrors).
|
|
find_arg_sizes_in_scc_pass([PPId | PPIds], Module, PassInfo,
|
|
OutputSupplierMap0, Paths0, SubsetErrors0, Result,
|
|
TermErrors0, TermErrors) :-
|
|
find_arg_sizes_pred(PPId, Module, PassInfo, OutputSupplierMap0,
|
|
Result1, TermErrors1),
|
|
list__append(TermErrors0, TermErrors1, TermErrors2),
|
|
PassInfo = pass_info(_, MaxErrors, _),
|
|
list__take_upto(MaxErrors, TermErrors2, TermErrors3),
|
|
(
|
|
Result1 = error(_),
|
|
Result = Result1,
|
|
TermErrors = TermErrors3
|
|
;
|
|
Result1 = ok(Paths1, OutputSupplierMap1, SubsetErrors1),
|
|
list__append(Paths0, Paths1, Paths),
|
|
list__append(SubsetErrors0, SubsetErrors1, SubsetErrors),
|
|
find_arg_sizes_in_scc_pass(PPIds, Module, PassInfo,
|
|
OutputSupplierMap1, Paths, SubsetErrors, Result,
|
|
TermErrors3, TermErrors)
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- pred find_arg_sizes_pred(pred_proc_id::in, module_info::in,
|
|
pass_info::in, used_args::in, pass1_result::out,
|
|
list(term_errors__error)::out) is det.
|
|
|
|
find_arg_sizes_pred(PPId, Module, PassInfo, OutputSupplierMap0, Result,
|
|
TermErrors) :-
|
|
PPId = proc(PredId, ProcId),
|
|
module_info_pred_proc_info(Module, PredId, ProcId, PredInfo, ProcInfo),
|
|
pred_info_context(PredInfo, Context),
|
|
proc_info_headvars(ProcInfo, Args),
|
|
proc_info_argmodes(ProcInfo, ArgModes),
|
|
proc_info_vartypes(ProcInfo, VarTypes),
|
|
proc_info_goal(ProcInfo, Goal),
|
|
map__init(EmptyMap),
|
|
PassInfo = pass_info(FunctorInfo, MaxErrors, MaxPaths),
|
|
init_traversal_params(Module, FunctorInfo, PPId, Context, VarTypes,
|
|
OutputSupplierMap0, EmptyMap, MaxErrors, MaxPaths, Params),
|
|
|
|
partition_call_args(Module, ArgModes, Args, InVars, OutVars),
|
|
Path0 = path_info(PPId, no, 0, [], OutVars),
|
|
set__singleton_set(PathSet0, Path0),
|
|
Info0 = ok(PathSet0, []),
|
|
traverse_goal(Goal, Params, Info0, Info),
|
|
|
|
(
|
|
Info = ok(Paths, TermErrors),
|
|
set__to_sorted_list(Paths, PathList),
|
|
upper_bound_active_vars(PathList, AllActiveVars),
|
|
map__lookup(OutputSupplierMap0, PPId,
|
|
OutputSuppliers0),
|
|
update_output_suppliers(Args, AllActiveVars,
|
|
OutputSuppliers0, OutputSuppliers),
|
|
map__det_update(OutputSupplierMap0, PPId,
|
|
OutputSuppliers, OutputSupplierMap),
|
|
( bag__is_subbag(AllActiveVars, InVars) ->
|
|
SubsetErrors = []
|
|
;
|
|
SubsetErrors = [Context -
|
|
not_subset(PPId, AllActiveVars, InVars)]
|
|
),
|
|
Result = ok(PathList, OutputSupplierMap, SubsetErrors)
|
|
;
|
|
Info = error(Errors, TermErrors),
|
|
Result = error(Errors)
|
|
).
|
|
|
|
:- pred update_output_suppliers(list(var)::in, bag(var)::in,
|
|
list(bool)::in, list(bool)::out) is det.
|
|
|
|
update_output_suppliers([], _ActiveVars, [], []).
|
|
update_output_suppliers([_ | _], _ActiveVars, [], []) :-
|
|
error("update_output_suppliers: Unmatched variables").
|
|
update_output_suppliers([], _ActiveVars, [_ | _], []) :-
|
|
error("update_output_suppliers: Unmatched variables").
|
|
update_output_suppliers([Arg | Args], ActiveVars,
|
|
[OutputSupplier0 | OutputSuppliers0],
|
|
[OutputSupplier | OutputSuppliers]) :-
|
|
( bag__contains(ActiveVars, Arg) ->
|
|
OutputSupplier = yes
|
|
;
|
|
% This guarantees that the set of output suppliers can only
|
|
% increase, which in turn guarantees that our fixpoint
|
|
% computation is monotonic and therefore terminates.
|
|
OutputSupplier = OutputSupplier0
|
|
),
|
|
update_output_suppliers(Args, ActiveVars,
|
|
OutputSuppliers0, OutputSuppliers).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
% Solve the list of constraints
|
|
|
|
% output is of the form required by lp_solve.
|
|
% which is given the input = [eqn(Const, PPid, [PPidList])]
|
|
% max: .......
|
|
% c1: PPid - (PPidList) > Const;
|
|
% c2: PPid - (PPidList) > Const;
|
|
% where PPid (proc(PredId, ProcId)) is printed as ' aPredId_ProcId - b '
|
|
% The choice of the letter `a' is arbitrary, and is chosen as lp_solve does
|
|
% not allow variables to start with digits.
|
|
% The variable `b' is used as lp_solve will only solve for positive values
|
|
% of variables. replacing each variable occurance with ` a#_# - b ', this
|
|
% avoids the problem of only allowing positive variables as a#_# - b can
|
|
% be negative even when a#_# and b are both positive.
|
|
|
|
:- pred solve_equations(list(path_info)::in, list(pred_proc_id)::in,
|
|
maybe(list(pair(pred_proc_id, int)))::out,
|
|
io__state::di, io__state::uo) is det.
|
|
|
|
solve_equations(Paths, PPIds, Result, S0, S) :-
|
|
(
|
|
convert_equations(Paths, Varset, Equations,
|
|
Objective, PPVars)
|
|
->
|
|
map__values(PPVars, AllVars0),
|
|
list__sort_and_remove_dups(AllVars0, AllVars),
|
|
% unsafe_perform_io(io__write_string("before\n")),
|
|
% unsafe_perform_io(io__write(Equations)),
|
|
% unsafe_perform_io(io__write_string("\n")),
|
|
% unsafe_perform_io(io__write(Objective)),
|
|
% unsafe_perform_io(io__write_string("\n")),
|
|
% unsafe_perform_io(io__write(AllVars)),
|
|
% unsafe_perform_io(io__write_string("\n")),
|
|
lp_solve(Equations, min, Objective, Varset, AllVars, Soln,
|
|
S0, S),
|
|
% unsafe_perform_io(io__write_string("after\n")),
|
|
(
|
|
Soln = unsatisfiable,
|
|
Result = no
|
|
;
|
|
Soln = satisfiable(_ObjVal, SolnVal),
|
|
list__map(lookup_coeff(PPVars, SolnVal), PPIds,
|
|
SolutionList),
|
|
Result = yes(SolutionList)
|
|
)
|
|
;
|
|
Result = no,
|
|
S = S0
|
|
).
|
|
|
|
:- pred convert_equations(list(path_info)::in, varset::out, lp__equations::out,
|
|
objective::out, map(pred_proc_id, var)::out) is semidet.
|
|
|
|
convert_equations(Paths, Varset, Equations, Objective, PPVars) :-
|
|
varset__init(Varset0),
|
|
map__init(PredProcVars0),
|
|
set__init(EqnSet0),
|
|
convert_equations_2(Paths, PredProcVars0, PPVars, Varset0, Varset,
|
|
EqnSet0, EqnSet),
|
|
set__to_sorted_list(EqnSet, Equations),
|
|
map__values(PPVars, Vars),
|
|
Convert = lambda([Var::in, Coeff::out] is det,
|
|
(
|
|
Coeff = Var - 1.0
|
|
)),
|
|
list__map(Convert, Vars, Objective).
|
|
|
|
:- pred convert_equations_2(list(path_info)::in,
|
|
map(pred_proc_id, var)::in, map(pred_proc_id, var)::out,
|
|
varset::in, varset::out,
|
|
set(lp__equation)::in, set(lp__equation)::out) is semidet.
|
|
|
|
convert_equations_2([], PPVars, PPVars, Varset, Varset, Eqns, Eqns).
|
|
convert_equations_2([Path | Paths], PPVars0, PPVars, Varset0, Varset,
|
|
Eqns0, Eqns) :-
|
|
Path = path_info(ThisPPId, _, IntGamma, PPIds, _),
|
|
int__to_float(IntGamma, FloatGamma),
|
|
Eqn = eqn(Coeffs, (>=), FloatGamma),
|
|
pred_proc_var(ThisPPId, ThisVar, Varset0, Varset2, PPVars0, PPVars1),
|
|
Coeffs = [ThisVar - 1.0 | RestCoeffs],
|
|
Convert = lambda([PPId::in, Coeff::out, Pair0::in, Pair::out] is det,
|
|
(
|
|
Pair0 = VS0 - PPV0,
|
|
pred_proc_var(PPId, Var, VS0, VS, PPV0, PPV),
|
|
Coeff = Var - (-1.0),
|
|
Pair = VS - PPV
|
|
)),
|
|
list__map_foldl(Convert, PPIds, RestCoeffs, Varset2 - PPVars1,
|
|
Varset3 - PPVars2),
|
|
set__insert(Eqns0, Eqn, Eqns1),
|
|
convert_equations_2(Paths, PPVars2, PPVars, Varset3, Varset,
|
|
Eqns1, Eqns).
|
|
|
|
:- pred lookup_coeff(map(pred_proc_id, var)::in, map(var, float)::in,
|
|
pred_proc_id::in, pair(pred_proc_id, int)::out) is det.
|
|
|
|
lookup_coeff(PPIds, Soln, PPId, PPId - ICoeff) :-
|
|
map__lookup(PPIds, PPId, Var),
|
|
map__lookup(Soln, Var, Coeff),
|
|
float__ceiling_to_int(Coeff, ICoeff).
|
|
|
|
:- pred pred_proc_var(pred_proc_id::in, var::out, varset::in, varset::out,
|
|
map(pred_proc_id, var)::in, map(pred_proc_id, var)::out) is det.
|
|
|
|
pred_proc_var(PPId, Var, Varset0, Varset, PPVars0, PPVars) :-
|
|
( map__search(PPVars0, PPId, Var0) ->
|
|
Var = Var0,
|
|
Varset = Varset0,
|
|
PPVars = PPVars0
|
|
;
|
|
varset__new_var(Varset0, Var, Varset),
|
|
map__det_insert(PPVars0, PPId, Var, PPVars)
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|