This is so that it can become the home of the type currently named
pred_origin in hlds_pred.m, which (after being given new name) will become
a structured representation of predicate names.
The only thing that kept pred_name.m in the parse_tree package was the fact
that parse_pragma.m, which has no access to the hlds package, called it
to create the name of a type-specialized predicate when parsing
type_spec pragmas. The main part of this diff, apart from the trivial
updates to import hlds.pred_name instead parse_tree.pred_name, deals
with this issue.
The problem is how to ensure that the compiler invocations that create
type-specialized predicates (invocations that compile the module containing
the type_spec pragma that calls for this) and the invocations that create
the calls to those predicates (invocations that mostly compile other modules)
agree on the name of the name of the type-specialized predicate.
The old approach was this.
When reading in (say) mod1.m which contains a type_spec pragma,
we construct the name of the type-specialized predicate from
- the name of the module (mod1),
- the name of the predicate to be specialized, and
- the type substitution in the pragma.
We then record this name in the pragma.
If the compiler invocation generates code, we use this name in the
predicate definition. If the compiler invocation creates a .int file,
we record the name in the third argument of the type_spec pragma.
This third argument is NOT allowed to exist in .m files.
Other compiler invocations that read in mod1.int when compiling
another module, e.g. mod2.m, use the specialized name in the third argument
of the type_spec pragma as the name to use in calls.
In this approach, the single-source-of-truth about the name of the
type-specialized predicate is the name constructed when parsing mod1.m,
which is conveyed to compiler invocations on other modules through
the third argument of the type_spec pragma.
The new approach is this:
When reading in (say) mod1.m which contains a type_spec pragma,
we give guaranteed-to-be-unique names to all the anonymous variables
in the type_spec pragma. We also record in the type_spec pragma
the name of the module whose (source or interface) file we read
the pragma from. The name of the predicate to be specialized
was of course already in the pragma.
If the compiler invocation generates code, we construct the name
of the type-specialized version of the predicate when we add the
all-tvars-are-named type_spec pragma to the HLDS. If the compiler
invocation creates a .int file, we write out the all-tvars-are-named
version of the type_spec pragma. The pragma also contains the predicate
name to be specialized. It does not contain the name of the module,
but we will write out type_spec pragmas from module_x.m *only* to
module_x.int, never to any other .int file, so any readers of
the type_spec pragma from mod1.int will also know the name of the
module that the pragma came from.
Other compiler invocations that read in mod1.int when compiling
another module, e.g. mod2.m, therefore get exactly the same
- module name,
- the name of the predicate to be specialized, and
- the type substitution in the pragma
as the compiler invocations on mod1.m. The module name are the
predicate name are never changed by being written out and then
read back in, and *due to the explicit names given to any formerly
anonymous variables*, the type substitution is changed by this either.
This means that the compiler invocations on mod1.m and mod2.m
give the same parameters to the same function, and therefore they are
guaranteed to get the same string as the name of the type-specialized
version of the predicate.
In this approach, the single-source-of-truth about the name of the
type-specialized predicate is the function constructing that name
and its inputs.
compiler/hlds.m:
compiler/parse_tree.m:
compiler/pred_name.m:
Move pred_name.m from the parse_tree package to the hlds package.
compiler/prog_item.m:
Change the representation of type_spec pragmas to
- delete the name of the specialized predicate, and replace it with
- the name of the module the pragma was read in from.
compiler/parse_pragma.m:
Delete the code for parsing the third argument of type_spec pragmas.
Allow them to exist for a short transition period, but ignore them.
(If we read in files containing them, the result will be a link error
if the type substitution contains anonymous variables. In that case,
a rebuild of the program with all modules compiled using the *same
compiler version* will work.)
Give guaranteed-to-be-unique names to all anonymous type variable
in the type substitution part of the type_spec pragma we construct.
compiler/add_pragma_type_spec.m:
Construct the name of the type-specialized predicate as the type_spec
pragma is added to the HLDS.
compiler/parse_tree_out_pragma.m:
Never write out a type_spec par_loop_control with a third argument.
Delete the var_name_print argument of the predicate that writes out
type_spec pragmas. Instead, *always* use print_name_only.
compiler/options.m:
Add a way of testing whether the installed compiler has this change.
compiler/accumulator.m:
compiler/add_pragma_tabling.m:
compiler/add_special_pred.m:
compiler/base_typeclass_info.m:
compiler/check_typeclass.m:
compiler/dep_par_conj.m:
compiler/distance_granularity.m:
compiler/higher_order.m:
compiler/hlds_code_util.m:
compiler/intermod.m:
compiler/lambda.m:
compiler/layout_out.m:
compiler/lco.m:
compiler/loop_inv.m:
compiler/make_hlds_passes.m:
compiler/name_mangle.m:
compiler/opt_debug.m:
compiler/opt_util.m:
compiler/par_loop_control.m:
compiler/parse_tree_out.m:
compiler/pd_info.m:
compiler/prog_rep.m:
compiler/ssdebug.m:
compiler/stm_expand.m:
compiler/structure_reuse.versions.m:
compiler/table_gen.m:
compiler/tupling.m:
compiler/untupling.m:
compiler/unused_args.m:
Mercury
Mercury is a logic/functional programming language which combines the clarity and the expressiveness of declarative programming with advanced static analysis and error detection features.
More information is available on the website's about pages, in other README files in the source code repository, and in the documentation.
Small sample programs written in Mercury can be found in the samples and extras directories of the source code repository.
README files
The Mercury compiler has two different backends and works on different operating systems. Specific information is contained in individual README files:
-
Bootstrapping discusses how to get Mercury installed.
This is important, as the Mercury compiler is written in Mercury.
-
C Low-level backend
This backend works well with GCC but also works with:
-
High-level backend targets
-
Supported operating systems
-
Other platform information
Other information
See the current release notes for the latest stable release. The news file lists any recent changes. The history file is relevant if you want to find out more about the past development of Mercury. The limitations file lists some ways in which the Mercury implementation does not yet meet its goals.
Information for developers
If you are considering contributing to the Mercury project, the website contains some documents that may be helpful. These include a document about contributions in general and specific information about contributing such as coding styles.
Contact
See our contact page.