mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-16 06:14:59 +00:00
Estimated hours taken: 400
Smart recompilation. Record version numbers for each item
in interface files. Record which items are used in each compilation.
Only recompile a module if the output file does not exist or
nothing has changed.
There is still some work to do on this:
- it doesn't work with inter-module optimization.
- it doesn't work when the module name doesn't match the file name.
(this problem will go away when mmake functionality is moved into
the compiler.
I'll hold off documenting this change in the NEWS file and
on the web page for a month or so, until I've had a bit more
experience using it.
compiler/options.m:
compiler/handle_options.m:
doc/user_guide.texi:
Add an option `--smart-recompilation', currently off by default.
Add an internal option `--generate-version-numbers' to control
whether version numbers are written to the interface files. If
`--smart-recompilation' is disabled because the module
is being compiled with `--intermodule-optimization' (e.g. in the
standard library), we still want to write the version numbers
to the interface files.
Add an option `--verbose-recompilation' (default off)
to write messages describing why recompilation is needed.
Add an option `--warn-smart-recompilation' (default on)
to control warnings relating to the smart recompilation
system. Warn if smart recompilation will not work with
the output and inter-module optimization options given.
compiler/recompilation.m:
Type declarations for smart recompilation.
Predicates to record program items used by compilation.
compiler/recompilation_version.m:
Compute version numbers for program items in interface files.
compiler/recompilation_usage.m:
Find all items used by a compilation.
compiler/recompilation_check.m:
Check whether recompilation is necessary.
compiler/timestamp.m:
Timestamp ADT for smart recompilation.
compiler/mercury_compile.m:
Invoke the smart recompilation passes.
compiler/modules.m:
compiler/prog_io.m:
Return timestamps for modules read.
When reading a module make sure the current input stream
is reset to its old value, not stdin.
Handle version number items in interface files.
compiler/module_qual.m:
compiler/unify_proc.m:
compiler/make_hlds.m:
Record all items used by local items.
compiler/make_hlds.m:
Process `:- pragma type_spec' declarations in
add_item_list_clauses. The qual_info is needed
when processing `:- pragma type_spec' declarations
so that any equivalence types used by the declaration
can be recorded as used by the predicate or function to
which the `:- pragma type_spec' applies.
compiler/equiv_type.m:
For each imported item, record which equivalence types
are used by that item.
compiler/hlds_module.m:
Add a field to the module_info to store information about
items used during compilation of a module.
compiler/check_typeclass.m:
Make sure any items used in clauses for typeclass method
implementations are recorded in the `.used' file.
compiler/prog_data.m:
compiler/*.m:
Factor out some duplicated code by combining the
pred and func, and pred_mode and func_mode items.
Make it easier to extract the name of a type, inst or mode
from its declaration.
Add an item type to hold the version numbers for an interface file.
Allow warnings to be reported for `nothing' items (used for
reporting when version numbers are written using an
obsolete format).
compiler/prog_io.m:
compiler/prog_io_util.m:
compiler/typecheck.m:
compiler/type_util.m:
compiler/*.m:
Strip contexts from all types, not just those in class constraints.
This makes it possible to use ordinary unification to check
whether items have changed (with the exception of clauses).
Remove code to create types with contexts in typechecking.
Remove code scattered through the compiler to remove contexts
from types in class constraints.
compiler/hlds_pred.m:
compiler/prog_util.m:
Move hlds_pred__adjust_func_arity to prog_util, so that it
can be used by the pre-hlds passes.
compiler/typecheck.m:
compiler/hlds_module.m:
Move typecheck__visible_modules to hlds_module.m, so it can
be used by recompilation_usage.m.
compiler/typecheck.m:
Add a comment telling where updates may be required if the
code to typecheck a var-functor unification changes.
compiler/error_util.m:
Allow writing messages without contexts (used for the verbose
recompilation messages).
Add functions to format sym_name and sym_name_and_arity,
and to add punctuation to the end of an error message
without unwanted line breaks before the punctuation.
scripts/Mmake.rules:
compiler/modules.m:
Don't remove the output file before running the compiler. We need
to leave the old output file intact if smart recompilation detects
that recompilation is not needed.
compiler/notes/compiler_design.html:
Document the new modules.
library/io.m:
NEWS:
Add predicates to find the modification time of files
and input_streams.
library/set.m:
NEWS:
Add a predicate version of set__fold
Don't sort the output of set__filter, it's already sorted.
library/std_util.m:
NEWS:
Add a predicate `std_util__map_maybe/3' and a function
`std_util__map_maybe/2' to apply a predicate or a function to
a value stored in a term of type `std_util__maybe'.
configure.in:
runtime/mercury_conf.h.in:
runtime/RESERVED_MACRO_NAMES:
When checking whether the compiler is recent enough, check for
the --warn-smart-recompilation option.
Check for stat().
library/Mmakefile:
Disable warnings about smart recompilation not working with
`--intermodule-optimization'.
browser/Mmakefile:
Disable warnings about smart recompilation not working when
the module name doesn't match the file name.
runtime/mercury_string.h:
Add a macro MR_make_string_const() which automates computation
of the length of string argument to MR_string_const().
tests/recompilation/Mmakefile:
tests/recompilation/runtests:
tests/recompilation/test_functions:
tests/recompilation/TESTS:
tests/recompilation/README:
A framework for testing smart recompilation.
The option currently only works for the recompilation directory.
tests/recompilation/TEST.m.{1,2}:
tests/recompilation/TEST_2.m.{1,2}:
tests/recompilation/TEST.exp.{1,2}:
tests/recompilation/TEST.err_exp.2:
Test cases, where TEST is one of add_constructor_r, add_instance_r,
add_instance_2_r, add_type_nr, change_class_r, change_instance_r,
change_mode_r, field_r, func_overloading_nr, func_overloading_r,
lambda_mode_r, nested_module_r, no_version_numbers_r,
pragma_type_spec_r, pred_ctor_ambiguity_r, pred_overloading_r,
add_type_re, remove_type_re, type_qual_re.
tests/handle_options:
Add an option `-e' to generate any missing expected output files.
484 lines
18 KiB
Mathematica
484 lines
18 KiB
Mathematica
%-----------------------------------------------------------------------------%
|
|
% Copyright (C) 1994-2001 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.
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
% main author: fjh
|
|
|
|
% various utility predicates acting on the parse tree data
|
|
% structure defined in prog_data.m.
|
|
|
|
:- module prog_util.
|
|
|
|
:- interface.
|
|
|
|
:- import_module prog_data, term.
|
|
:- import_module std_util, list.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
% Returns the name of the module containing public builtins;
|
|
% originally this was "mercury_builtin", but it later became
|
|
% just "builtin", and it may eventually be renamed "std:builtin".
|
|
% This module is automatically imported, as if via `import_module'.
|
|
|
|
:- pred mercury_public_builtin_module(sym_name).
|
|
:- mode mercury_public_builtin_module(out) is det.
|
|
|
|
% Returns the name of the module containing private builtins;
|
|
% traditionally this was "mercury_builtin", but it later became
|
|
% "private_builtin", and it may eventually be renamed
|
|
% "std:private_builtin".
|
|
% This module is automatically imported, as if via `use_module'.
|
|
|
|
:- pred mercury_private_builtin_module(sym_name).
|
|
:- mode mercury_private_builtin_module(out) is det.
|
|
|
|
% Returns the name of the module containing builtins for tabling;
|
|
% originally these were in "private_builtin", but they
|
|
% may soon be moved into a separate module.
|
|
% This module is automatically imported iff tabling is enabled.
|
|
|
|
:- pred mercury_table_builtin_module(sym_name).
|
|
:- mode mercury_table_builtin_module(out) is det.
|
|
|
|
% Returns the name of the module containing the builtins for
|
|
% deep profiling.
|
|
% This module is automatically imported iff deep profiling is
|
|
% enabled.
|
|
:- pred mercury_profiling_builtin_module(sym_name).
|
|
:- mode mercury_profiling_builtin_module(out) is det.
|
|
|
|
% Succeeds iff the specified module is one of the three
|
|
% builtin modules listed above which are automatically imported.
|
|
|
|
:- pred any_mercury_builtin_module(sym_name).
|
|
:- mode any_mercury_builtin_module(in) is semidet.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
% Given a symbol name, return its unqualified name.
|
|
|
|
:- pred unqualify_name(sym_name, string).
|
|
:- mode unqualify_name(in, out) is det.
|
|
|
|
% sym_name_get_module_name(SymName, DefaultModName, ModName):
|
|
% Given a symbol name, return the module qualifier(s).
|
|
% If the symbol is unqualified, then return the specified default
|
|
% module name.
|
|
|
|
:- pred sym_name_get_module_name(sym_name, module_name, module_name).
|
|
:- mode sym_name_get_module_name(in, in, out) is det.
|
|
|
|
% string_to_sym_name(String, Separator, SymName):
|
|
% Convert a string, possibly prefixed with
|
|
% module qualifiers (separated by Separator),
|
|
% into a symbol name.
|
|
%
|
|
:- pred string_to_sym_name(string, string, sym_name).
|
|
:- mode string_to_sym_name(in, in, out) is det.
|
|
|
|
% match_sym_name(PartialSymName, CompleteSymName):
|
|
% succeeds iff there is some sequence of module qualifiers
|
|
% which when prefixed to PartialSymName gives CompleteSymName.
|
|
%
|
|
:- pred match_sym_name(sym_name, sym_name).
|
|
:- mode match_sym_name(in, in) is semidet.
|
|
|
|
% remove_sym_name_prefix(SymName0, Prefix, SymName)
|
|
% succeeds iff
|
|
% SymName and SymName0 have the same module qualifier
|
|
% and the unqualified part of SymName0 has the given prefix
|
|
% and the unqualified part of SymName is the unqualified
|
|
% part of SymName0 with the prefix removed
|
|
:- pred remove_sym_name_prefix(sym_name, string, sym_name).
|
|
:- mode remove_sym_name_prefix(in, in, out) is semidet.
|
|
:- mode remove_sym_name_prefix(out, in, in) is det.
|
|
|
|
% remove_sym_name_suffix(SymName0, Suffix, SymName)
|
|
% succeeds iff
|
|
% SymName and SymName0 have the same module qualifier
|
|
% and the unqualified part of SymName0 has the given suffix
|
|
% and the unqualified part of SymName is the unqualified
|
|
% part of SymName0 with the suffix removed
|
|
:- pred remove_sym_name_suffix(sym_name, string, sym_name).
|
|
:- mode remove_sym_name_suffix(in, in, out) is semidet.
|
|
|
|
% add_sym_name_suffix(SymName0, Suffix, SymName)
|
|
% succeeds iff
|
|
% SymName and SymName0 have the same module qualifier
|
|
% and the unqualified part of SymName is the unqualified
|
|
% part of SymName0 with the suffix added
|
|
:- pred add_sym_name_suffix(sym_name, string, sym_name).
|
|
:- mode add_sym_name_suffix(in, in, out) is det.
|
|
|
|
% insert_module_qualifier(ModuleName, SymName0, SymName):
|
|
% prepend the specified ModuleName onto the module
|
|
% qualifiers in SymName0, giving SymName.
|
|
:- pred insert_module_qualifier(string, sym_name, sym_name).
|
|
:- mode insert_module_qualifier(in, in, out) is det.
|
|
|
|
% Given a possible module qualified sym_name and a list of
|
|
% argument types and a context, construct a term. This is
|
|
% used to construct types.
|
|
|
|
:- pred construct_qualified_term(sym_name, list(term(T)), term(T)).
|
|
:- mode construct_qualified_term(in, in, out) is det.
|
|
|
|
:- pred construct_qualified_term(sym_name, list(term(T)), prog_context, term(T)).
|
|
:- mode construct_qualified_term(in, in, in, out) is det.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
% adjust_func_arity(PredOrFunc, FuncArity, PredArity).
|
|
%
|
|
% We internally store the arity as the length of the argument
|
|
% list including the return value, which is one more than the
|
|
% arity of the function reported in error messages.
|
|
:- pred adjust_func_arity(pred_or_func, int, int).
|
|
:- mode adjust_func_arity(in, in, out) is det.
|
|
:- mode adjust_func_arity(in, out, in) is det.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
% make_pred_name_with_context(ModuleName, Prefix, PredOrFunc, PredName,
|
|
% Line, Counter, SymName).
|
|
%
|
|
% Create a predicate name with context, e.g. for introduced
|
|
% lambda or deforestation predicates.
|
|
:- pred make_pred_name(module_name, string, maybe(pred_or_func),
|
|
string, new_pred_id, sym_name).
|
|
:- mode make_pred_name(in, in, in, in, in, out) is det.
|
|
|
|
% make_pred_name_with_context(ModuleName, Prefix, PredOrFunc, PredName,
|
|
% Line, Counter, SymName).
|
|
%
|
|
% Create a predicate name with context, e.g. for introduced
|
|
% lambda or deforestation predicates.
|
|
:- pred make_pred_name_with_context(module_name, string, pred_or_func,
|
|
string, int, int, sym_name).
|
|
:- mode make_pred_name_with_context(in, in, in, in, in, in, out) is det.
|
|
|
|
:- type new_pred_id
|
|
---> counter(int, int) % Line number, Counter
|
|
; type_subst(tvarset, type_subst)
|
|
.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
% A pred declaration may contains just types, as in
|
|
% :- pred list__append(list(T), list(T), list(T)).
|
|
% or it may contain both types and modes, as in
|
|
% :- pred list__append(list(T)::in, list(T)::in,
|
|
% list(T)::output).
|
|
%
|
|
% This predicate takes the argument list of a pred declaration,
|
|
% splits it into two separate lists for the types and (if present)
|
|
% the modes.
|
|
|
|
:- type maybe_modes == maybe(list(mode)).
|
|
|
|
:- pred split_types_and_modes(list(type_and_mode), list(type), maybe_modes).
|
|
:- mode split_types_and_modes(in, out, out) is det.
|
|
|
|
:- pred split_type_and_mode(type_and_mode, type, maybe(mode)).
|
|
:- mode split_type_and_mode(in, out, out) is det.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
% Perform a substitution on a goal.
|
|
|
|
:- pred prog_util__rename_in_goal(goal, prog_var, prog_var, goal).
|
|
:- mode prog_util__rename_in_goal(in, in, in, out) is det.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
:- import_module mercury_to_mercury, (inst).
|
|
:- import_module bool, string, int, map, varset.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
% We may eventually want to put the standard library into a package "std":
|
|
% mercury_public_builtin_module(M) :-
|
|
% M = qualified(unqualified("std"), "builtin"))).
|
|
% mercury_private_builtin_module(M) :-
|
|
% M = qualified(unqualified("std"), "private_builtin"))).
|
|
mercury_public_builtin_module(unqualified("builtin")).
|
|
mercury_private_builtin_module(unqualified("private_builtin")).
|
|
mercury_table_builtin_module(unqualified("table_builtin")).
|
|
mercury_profiling_builtin_module(unqualified("profiling_builtin")).
|
|
|
|
any_mercury_builtin_module(Module) :-
|
|
( mercury_public_builtin_module(Module)
|
|
; mercury_private_builtin_module(Module)
|
|
; mercury_table_builtin_module(Module)
|
|
; mercury_profiling_builtin_module(Module)
|
|
).
|
|
|
|
unqualify_name(unqualified(PredName), PredName).
|
|
unqualify_name(qualified(_ModuleName, PredName), PredName).
|
|
|
|
sym_name_get_module_name(unqualified(_), ModuleName, ModuleName).
|
|
sym_name_get_module_name(qualified(ModuleName, _PredName), _, ModuleName).
|
|
|
|
construct_qualified_term(qualified(Module, Name), Args, Context, Term) :-
|
|
construct_qualified_term(Module, [], Context, ModuleTerm),
|
|
UnqualifiedTerm = term__functor(term__atom(Name), Args, Context),
|
|
Term = term__functor(term__atom(":"),
|
|
[ModuleTerm, UnqualifiedTerm], Context).
|
|
construct_qualified_term(unqualified(Name), Args, Context, Term) :-
|
|
Term = term__functor(term__atom(Name), Args, Context).
|
|
|
|
|
|
construct_qualified_term(SymName, Args, Term) :-
|
|
term__context_init(Context),
|
|
construct_qualified_term(SymName, Args, Context, Term).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
adjust_func_arity(predicate, Arity, Arity).
|
|
adjust_func_arity(function, Arity - 1, Arity).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
split_types_and_modes(TypesAndModes, Types, MaybeModes) :-
|
|
split_types_and_modes_2(TypesAndModes, yes, Types, Modes, Result),
|
|
(
|
|
Result = yes
|
|
->
|
|
MaybeModes = yes(Modes)
|
|
;
|
|
MaybeModes = no
|
|
).
|
|
|
|
:- pred split_types_and_modes_2(list(type_and_mode), bool,
|
|
list(type), list(mode), bool).
|
|
:- mode split_types_and_modes_2(in, in, out, out, out) is det.
|
|
|
|
% T = type, M = mode, TM = combined type and mode
|
|
split_types_and_modes_2([], Result, [], [], Result).
|
|
split_types_and_modes_2([TM|TMs], Result0, [T|Ts], [M|Ms], Result) :-
|
|
split_type_and_mode(TM, Result0, T, M, Result1),
|
|
split_types_and_modes_2(TMs, Result1, Ts, Ms, Result).
|
|
|
|
% if a pred declaration specifies modes for some but
|
|
% not all of the arguments, then the modes are ignored
|
|
% - should this be an error instead?
|
|
% trd: this should never happen because prog_io.m will detect
|
|
% these cases
|
|
|
|
:- pred split_type_and_mode(type_and_mode, bool, type, mode, bool).
|
|
:- mode split_type_and_mode(in, in, out, out, out) is det.
|
|
|
|
split_type_and_mode(type_only(T), _, T, (free -> free), no).
|
|
split_type_and_mode(type_and_mode(T,M), R, T, M, R).
|
|
|
|
split_type_and_mode(type_only(T), T, no).
|
|
split_type_and_mode(type_and_mode(T,M), T, yes(M)).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
prog_util__rename_in_goal(Goal0 - Context, OldVar, NewVar, Goal - Context) :-
|
|
prog_util__rename_in_goal_expr(Goal0, OldVar, NewVar, Goal).
|
|
|
|
:- pred prog_util__rename_in_goal_expr(goal_expr, prog_var, prog_var,
|
|
goal_expr).
|
|
:- mode prog_util__rename_in_goal_expr(in, in, in, out) is det.
|
|
|
|
prog_util__rename_in_goal_expr((GoalA0, GoalB0), OldVar, NewVar,
|
|
(GoalA, GoalB)) :-
|
|
prog_util__rename_in_goal(GoalA0, OldVar, NewVar, GoalA),
|
|
prog_util__rename_in_goal(GoalB0, OldVar, NewVar, GoalB).
|
|
prog_util__rename_in_goal_expr((GoalA0 & GoalB0), OldVar, NewVar,
|
|
(GoalA & GoalB)) :-
|
|
prog_util__rename_in_goal(GoalA0, OldVar, NewVar, GoalA),
|
|
prog_util__rename_in_goal(GoalB0, OldVar, NewVar, GoalB).
|
|
prog_util__rename_in_goal_expr(true, _Var, _NewVar, true).
|
|
prog_util__rename_in_goal_expr((GoalA0; GoalB0), OldVar, NewVar,
|
|
(GoalA; GoalB)) :-
|
|
prog_util__rename_in_goal(GoalA0, OldVar, NewVar, GoalA),
|
|
prog_util__rename_in_goal(GoalB0, OldVar, NewVar, GoalB).
|
|
prog_util__rename_in_goal_expr(fail, _Var, _NewVar, fail).
|
|
prog_util__rename_in_goal_expr(not(Goal0), OldVar, NewVar, not(Goal)) :-
|
|
prog_util__rename_in_goal(Goal0, OldVar, NewVar, Goal).
|
|
prog_util__rename_in_goal_expr(some(Vars0, Goal0), OldVar, NewVar,
|
|
some(Vars, Goal)) :-
|
|
prog_util__rename_in_vars(Vars0, OldVar, NewVar, Vars),
|
|
prog_util__rename_in_goal(Goal0, OldVar, NewVar, Goal).
|
|
prog_util__rename_in_goal_expr(all(Vars0, Goal0), OldVar, NewVar,
|
|
all(Vars, Goal)) :-
|
|
prog_util__rename_in_vars(Vars0, OldVar, NewVar, Vars),
|
|
prog_util__rename_in_goal(Goal0, OldVar, NewVar, Goal).
|
|
prog_util__rename_in_goal_expr(implies(GoalA0, GoalB0), OldVar, NewVar,
|
|
implies(GoalA, GoalB)) :-
|
|
prog_util__rename_in_goal(GoalA0, OldVar, NewVar, GoalA),
|
|
prog_util__rename_in_goal(GoalB0, OldVar, NewVar, GoalB).
|
|
prog_util__rename_in_goal_expr(equivalent(GoalA0, GoalB0), OldVar, NewVar,
|
|
equivalent(GoalA, GoalB)) :-
|
|
prog_util__rename_in_goal(GoalA0, OldVar, NewVar, GoalA),
|
|
prog_util__rename_in_goal(GoalB0, OldVar, NewVar, GoalB).
|
|
prog_util__rename_in_goal_expr(if_then(Vars0, Cond0, Then0), OldVar, NewVar,
|
|
if_then(Vars, Cond, Then)) :-
|
|
prog_util__rename_in_vars(Vars0, OldVar, NewVar, Vars),
|
|
prog_util__rename_in_goal(Cond0, OldVar, NewVar, Cond),
|
|
prog_util__rename_in_goal(Then0, OldVar, NewVar, Then).
|
|
prog_util__rename_in_goal_expr(if_then_else(Vars0, Cond0, Then0, Else0),
|
|
OldVar, NewVar, if_then_else(Vars, Cond, Then, Else)) :-
|
|
prog_util__rename_in_vars(Vars0, OldVar, NewVar, Vars),
|
|
prog_util__rename_in_goal(Cond0, OldVar, NewVar, Cond),
|
|
prog_util__rename_in_goal(Then0, OldVar, NewVar, Then),
|
|
prog_util__rename_in_goal(Else0, OldVar, NewVar, Else).
|
|
prog_util__rename_in_goal_expr(call(SymName, Terms0, Purity), OldVar, NewVar,
|
|
call(SymName, Terms, Purity)) :-
|
|
term__substitute_list(Terms0, OldVar, term__variable(NewVar),
|
|
Terms).
|
|
prog_util__rename_in_goal_expr(unify(TermA0, TermB0, Purity), OldVar, NewVar,
|
|
unify(TermA, TermB, Purity)) :-
|
|
term__substitute(TermA0, OldVar, term__variable(NewVar),
|
|
TermA),
|
|
term__substitute(TermB0, OldVar, term__variable(NewVar),
|
|
TermB).
|
|
|
|
:- pred prog_util__rename_in_vars(list(prog_var), prog_var, prog_var,
|
|
list(prog_var)).
|
|
:- mode prog_util__rename_in_vars(in, in, in, out) is det.
|
|
|
|
prog_util__rename_in_vars([], _, _, []).
|
|
prog_util__rename_in_vars([Var0 | Vars0], OldVar, NewVar, [Var | Vars]) :-
|
|
( Var0 = OldVar ->
|
|
Var = NewVar
|
|
;
|
|
Var = Var0
|
|
),
|
|
prog_util__rename_in_vars(Vars0, OldVar, NewVar, Vars).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
% This would be simpler if we had a string__rev_sub_string_search/3 pred.
|
|
% With that, we could search for underscores right-to-left,
|
|
% and construct the resulting symbol directly.
|
|
% Instead, we search for them left-to-right, and then call
|
|
% insert_module_qualifier to fix things up.
|
|
|
|
string_to_sym_name(String, ModuleSeparator, Result) :-
|
|
(
|
|
string__sub_string_search(String, ModuleSeparator, LeftLength),
|
|
LeftLength > 0
|
|
->
|
|
string__left(String, LeftLength, ModuleName),
|
|
string__length(String, StringLength),
|
|
string__length(ModuleSeparator, SeparatorLength),
|
|
RightLength is StringLength - LeftLength - SeparatorLength,
|
|
string__right(String, RightLength, Name),
|
|
string_to_sym_name(Name, ModuleSeparator, NameSym),
|
|
insert_module_qualifier(ModuleName, NameSym, Result)
|
|
;
|
|
Result = unqualified(String)
|
|
).
|
|
|
|
insert_module_qualifier(ModuleName, unqualified(PlainName),
|
|
qualified(unqualified(ModuleName), PlainName)).
|
|
insert_module_qualifier(ModuleName, qualified(ModuleQual0, PlainName),
|
|
qualified(ModuleQual, PlainName)) :-
|
|
insert_module_qualifier(ModuleName, ModuleQual0, ModuleQual).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
% match_sym_name(PartialSymName, CompleteSymName):
|
|
% succeeds iff there is some sequence of module qualifiers
|
|
% which when prefixed to PartialSymName gives CompleteSymName.
|
|
|
|
match_sym_name(qualified(Module1, Name), qualified(Module2, Name)) :-
|
|
match_sym_name(Module1, Module2).
|
|
match_sym_name(unqualified(Name), unqualified(Name)).
|
|
match_sym_name(unqualified(Name), qualified(_, Name)).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
remove_sym_name_prefix(qualified(Module, Name0), Prefix,
|
|
qualified(Module, Name)) :-
|
|
string__append(Prefix, Name, Name0).
|
|
remove_sym_name_prefix(unqualified(Name0), Prefix, unqualified(Name)) :-
|
|
string__append(Prefix, Name, Name0).
|
|
|
|
remove_sym_name_suffix(qualified(Module, Name0), Suffix,
|
|
qualified(Module, Name)) :-
|
|
string__remove_suffix(Name0, Suffix, Name).
|
|
remove_sym_name_suffix(unqualified(Name0), Suffix, unqualified(Name)) :-
|
|
string__remove_suffix(Name0, Suffix, Name).
|
|
|
|
add_sym_name_suffix(qualified(Module, Name0), Suffix,
|
|
qualified(Module, Name)) :-
|
|
string__append(Name0, Suffix, Name).
|
|
add_sym_name_suffix(unqualified(Name0), Suffix, unqualified(Name)) :-
|
|
string__append(Name0, Suffix, Name).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
make_pred_name_with_context(ModuleName, Prefix,
|
|
PredOrFunc, PredName, Line, Counter, SymName) :-
|
|
make_pred_name(ModuleName, Prefix, yes(PredOrFunc), PredName,
|
|
counter(Line, Counter), SymName).
|
|
|
|
make_pred_name(ModuleName, Prefix, MaybePredOrFunc, PredName,
|
|
NewPredId, SymName) :-
|
|
(
|
|
MaybePredOrFunc = yes(PredOrFunc),
|
|
(
|
|
PredOrFunc = predicate,
|
|
PFS = "pred"
|
|
;
|
|
PredOrFunc = function,
|
|
PFS = "func"
|
|
)
|
|
;
|
|
MaybePredOrFunc = no,
|
|
PFS = "pred_or_func"
|
|
),
|
|
(
|
|
NewPredId = counter(Line, Counter),
|
|
string__format("%d__%d", [i(Line), i(Counter)], PredIdStr)
|
|
;
|
|
NewPredId = type_subst(VarSet, TypeSubst),
|
|
SubstToString = lambda([SubstElem::in, SubstStr::out] is det, (
|
|
SubstElem = Var - Type,
|
|
varset__lookup_name(VarSet, Var, VarName),
|
|
mercury_type_to_string(VarSet, Type, TypeString),
|
|
string__append_list([VarName, " = ", TypeString],
|
|
SubstStr)
|
|
)),
|
|
list_to_string(SubstToString, TypeSubst, PredIdStr)
|
|
),
|
|
|
|
string__format("%s__%s__%s__%s",
|
|
[s(Prefix), s(PFS), s(PredName), s(PredIdStr)], Name),
|
|
SymName = qualified(ModuleName, Name).
|
|
|
|
:- pred list_to_string(pred(T, string), list(T), string).
|
|
:- mode list_to_string(pred(in, out) is det, in, out) is det.
|
|
|
|
list_to_string(Pred, List, String) :-
|
|
list_to_string_2(Pred, List, Strings, ["]"]),
|
|
string__append_list(["[" | Strings], String).
|
|
|
|
:- pred list_to_string_2(pred(T, string), list(T), list(string), list(string)).
|
|
:- mode list_to_string_2(pred(in, out) is det, in, out, in) is det.
|
|
|
|
list_to_string_2(_, []) --> [].
|
|
list_to_string_2(Pred, [T | Ts]) -->
|
|
{ call(Pred, T, String) },
|
|
[String],
|
|
( { Ts = [] } ->
|
|
[]
|
|
;
|
|
[", "],
|
|
list_to_string_2(Pred, Ts)
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|