Estimated hours taken: 12
Four loosely related changes to improve mode inference.
--------------------
(1) Fix a problem with inference of unique modes.
Previously it was sufficient to just look at the final insts of the
mode and check whether they were `clobbered' or not in order to tell
which arguments will be dead on exit from this procedure. However,
that doesn't work for inferred modes, where the final inst will
initially be `not_reached'. Previously mode inference just assumed that
all arguments to a predicate were live, but that prevents it from being
able to infer `di' modes. So I've added a new field to the proc_info
to record which arguments are required to be dead on exit.
I've also changed mode analysis so that it checks that such
arguments really are dead. This means you can declare both `di' and
`ui' modes of a predicate, and so long as you declare the `di' one
first, mode checking should handle this overloading. It also means
that errors such as passing a variable which is live to a procedure with
a `di' mode argument are caught earlier, with a potentially better
error message; mode checking may also be able to reorder such calls,
so that the `di' mode pred is scheduled last. Mode inference now
notices if an argument is dead, and if so will try infering a `di'
mode.
hlds_pred.m:
Add a new field to the proc_info, the `maybe_arglives', of type
`maybe(list(is_live))'. If set, this records whether or not the
arguments are required to be dead after the procedure or not.
Add an access predicate which checks whether this is set,
and returns either the value set, or if no value special value
is set, looks up a value based on the modes by calling get_arg_lives
from mode_util.m.
make_hlds.m:
Add a MaybeArgLives parameter to add_new_pred.
(Also change the error messages about pragmas to reflect
the new pragma syntax.)
clause_to_proc.m, unify_proc.m:
Pass MaybeArgLives = no to add_new_pred.
modes.m, mode_errors.m:
Use the new arglives field. When mode-checking a call (or
higher-order call), check that all the variables which are
required to be dead really are dead.
unique_modes.m:
Use the new arglives field.
mode_util.m:
Add predicate `get_arg_lives', for use by modes.m and hlds_pred.m.
--------------------
(2) Fix a problem with mode inference looping.
It was checking whether a fixpoint had been reached by comparing the
(un-normalised) inferred final insts with the previously recorded final
insts (which had been normalised). Instead, it has to normalise the
insts before the comparison.
modes.m:
When doing mode analysis of an inferred mode, normalise the insts
before checking whether they've changed, rather than vice versa.
--------------------
(3) Fix a problem with the computation of liveness for mode-analysis
of if-then-elses that was detected when I tried to bootcheck the above
changes.
modes.m, unique_modes.m:
When mode-checking if-then-elses, the variables in the "else"
should not be considered live when checking the condition.
(They're nondet-live, but not live with regard to forward execution.)
--------------------
(4) Reduce the occurrence of mode inference inferring spurious
`in(not_reached)' modes.
modes.m:
If the top-level inst of a variable becomes `not_reached', set
the whole instmap to `unreachable'.
Estimated hours taken: 4
compiler/{mode_errors.m,mode_info.m,modes.m,unique_modes.m}:
Fix the handling of error message contexts for mode errors
so that it does say `in call to predicate foo/2' when it
means `in call to function foo/1'.
Estimated hours taken: 24
Add preliminary support for mode inference.
hlds_pred.m, hlds_out.m:
Add a new pred marker `infer_modes'.
make_hlds.m:
If there are no declared modes for a predicate,
set the `infer_modes' marker in the pred_info.
modes.m:
Implement mode inference.
When we see a call to a predicate with the `infer_modes' marker
set, then if the call does not match any of the modes we've
already inferred for the predicate, create a new inferred mode;
the initial insts are set to the normalised argument insts, and
the final insts are initially set to not_reached. When
analysing such a predicate, rather than checking whether the
inferred final insts match the declared final insts, just
replace the old final insts with the normalised version of the
newly inferred insts. Change the top-level to repeat mode
analysis until a fixpoint is reached. We need to "normalise"
insts to a bounded approximation avoid non-termination due to
infinite expansion.
Also fix a bug which meant that using `inst constrained == any.'
didn't work - the checks for `any' weren't calling `inst_expand'.
mode_util.m:
Change the predicates `inst_is_ground', `inst_is_unique', etc.
so that they consider `not_reached' insts to satisfy the
condition.
mode_errors.m:
Change the message for predicates with no mode declaration.
Add code for printing out inferred mode declarations.
clause_to_proc.m:
Add a new predicate copy_module_clauses_to_procs
to call copy_clauses_to_procs for a list of pred_ids.
We call this from modes.m at the start of each fixpoint iteration.
Estimated hours taken: 12
Implement higher-order functions.
Add higher-order function terms
(function lambda expressions, e.g. `Func = (func(X) = Y :- Y is 2 * X)'
and higher-order function calls (apply/N, e.g. `Z = apply(Func, 42)').
Add higher-order function insts and modes.
hlds_goal.m:
Add a new field pred_or_func to lambda_goal.
prog_data.m:
Add a new field pred_or_func to pred_inst_info.
prog_io.m:
Add support for parsing higher-order function terms and
higher-order function insts and modes.
make_hlds.m:
Add support for parsing higher-order function terms.
typecheck.m:
Add support for type-checking higher-order function calls
and higher-order function terms.
modes.m, mode_errors.m:
Add support for mode-checking higher-order function calls
and higher-order function terms.
higher_order.m:
Handle higher-order function types and insts.
hlds_pred.m:
Add new predicate pred_args_to_func_args, for extracting the
function arguments and function return from the arguments
of a predicate that is really a function.
*.m:
Minor changes to handle new pred_or_func field in lambda_goals
and pred_inst_infos.
Estimated hours taken: 24
Treat higher-order predicate calls as a new sort of goal,
rather than as calls to the special predicate call/N, in order to
remove the fixed limit on the number of arguments and on the modes
for call/N.
Also, remove the restriction on output arguments preceding input arguments
in lambda expressions.
hlds_goal.m:
Add new functor higher_order_call/6 to the hlds__goal type.
*.m:
Handle new functor higher_order_call/6.
arg_info.m:
Abstract things a bit more: the argument passing convention
for a procedure may be affected by that procedure's types,
modes, and code_model, as well as the arg_method.
follow_vars.m:
Pass down the args_method, since it is now needed for figuring
out the arg_info for unifications and higher-order calls.
follow_code.m:
Treat complicated unifications in the same way as calls.
lambda.m:
When creating lambda predicates, permute the arguments so
that all input arguments come before all output arguments.
call_gen.m:
When generating higher-order predicate calls, don't abort
if outputs precede inputs; instead, generate code assuming
that the called predicate's args have been permuted so that
the inputs to come before all the outputs.
Estimated hours taken: 8
options.m:
Rename branch_delay_slot to have_delay_slot.
Set optimize_delay_slot in -O2 only if have_delay_slot was set earlier.
This is possible now because the default optimization level is now
set in mc.
mercury_compile:
Change verbose output a bit to be more consistent.
dead_proc_elim:
Export the predicates that will eventually be needed by inlining.m.
inlining.m:
Use the information about the number of times each procedure is called
to inline local nonrecursive procedures that are called exactly once.
EXCEPT that this is turned off at the moment, since the inlining of
parse_dcg_goal_2 in prog_io, which this change enables, causes the
compiler to emit incorrect code.
prog_io:
Moved the data type definitions to prog_data. (Even though prog_io.m
is ten times the size of prog_data.m, the sizes of the .c files are
not too dissimilar.)
Estimated hours taken: 3
A bunch of cleanups: improve error messages, tidy up the code.
Also, do some work towards supporting higher-order functions.
type_util.m:
Add new predicate type_is_higher_order/3 for checking
whether a type is a higher-order type. This recognizes
both higher-order predicate types and also higher-order
function types.
code_info.m, modes.m, polymorphism.m, shapes.m:
Use type_is_higher_order/3.
make_hlds.m:
Fix another error message to do the right thing when
reporting errors for functions.
mercury_to_mercury:
List `func' in the table of operators, so that it gets
parenthesized correctly.
modes.m, mode_errors.m:
Improve the error message for attempted higher-order unifications:
spit out some context, and if verbose_errors is enabled, spit
out a long description.
Estimated hours taken: 10
hlds, hlds_module, hlds_pred, hlds_goal, hlds_data:
Divided the old hlds.m into four files:
hlds_module.m defines the data structures that deal with issues
that are wider than a single predicate. These data structures are
the module_info structure, dependency_info, the predicate table
and the shape table.
hlds_pred.m defined pred_info and proc_info, pred_id and proc_id.
hlds_goal.m defines hlds__goal, hlds__goal_{expr,info}, and the
other parts of goal structures.
hlsd_data.m defines the HLDS types that deal with issues related
to data and its representation: function symbols, types, insts, modes.
It also defines the types related to determinism.
hlds.m is now an empty module. I have not removed it from CVS
because we may need the name hlds.m again, and CVS does not like
the reuse of a name once removed.
other modules:
Import the necessary part of hlds.
det_analysis:
Define a type that was up to now improperly defined in hlds.m.
prog_io:
Move the definition of type determinism to hlds_data. This decision
may need to be revisited when prog_io is broken up.
dnf, lambda:
Simplify the task of defining predicates.
llds:
Fix some comments.
mercury_compile:
If the option -d all is given, dump all HLDS stages.
shape, unused_args:
Fix formatting.
Estimated hours taken: 1.5
Undo dylan's changes in the names of some library entities,
by applying the following sed script
s/term_atom/term__atom/g
s/term_string/term__string/g
s/term_integer/term__integer/g
s/term_float/term__float/g
s/term_context/term__context/g
s/term_functor/term__functor/g
s/term_variable/term__variable/g
s/_term__/_term_/g
s/std_util__bool_/bool__/g
to all the `.m' and `.pp' files in the compiler and library directories.
The reason for undoing these changes was to minimize incompatibilities
with 0.4 (and besides, the changes were not a really good idea in the first
place).
I also moved `bool' to a separate module.
The main reason for that change is to ensure that the `__' prefix is
only used when it genuinely represents a module qualifier.
(That's what dylan's changes were trying to acheive, but `term__'
does genuinely represent a module qualifier.)
compiler/*.m:
Apply sed script above;
where appropriate, add `bool' to the list of imported modules.
Estimated hours taken: _2___
Change names with badly placed double underscores (ie where the part of
a name before a double underscore is not the same as the module name.)
Reflect changes in the library interface.
compiler/*:
Use the newer, more correct form of the term and bool names.
Predicates "bool__" are now "std_util__bool" and labels of
the term ADT are now "term_" instead of "term__".
compiler/vn*.m:
change all names "vn__*" to a correct module prefix. All the
names remain qualified.
compiler/hlds.m:
s/\<is_builtin__/hlds__is_builtin_/g
s/\<dependency_info__/hlds__dependency_info_/g
compiler/unify_proc.m:
s/\<unify_proc_info__/unify_proc__info_/g
compiler/transform.m:
s/\<reschedule__conj/transform__reschedule_conj/g
excess:
A new pass to remove unnecessary assignment unifications.
mercury_compile:
Call the new excess assignment module.
options:
Add a new option, excess_assign, to control the new optimization.
Add another, num-real-regs, to specify how many of r1, r2 etc are
actually real registers. The default is now set to 5 for kryten;
later it should be supplied by the mc script, with a value determined
at configuration time.
tag_switch:
Use num-real-regs to figure out whether it is likely to be worthwhile
to eliminate the common subexpression of taking the primary tag of
a variable. Also fix an old performance bug: the test for when a
jump table is worthwhile was reversed.
value_number, vn_block:
Do value numbering on extended basic blocks, not basic blocks.
vn_debug:
Modify an information message.
labelopt:
Clean up an export an internal predicate for value numbering. Replace
bintree_set with set.
middle_rec:
Prepare for the generalization of middle recursion optimization
to include predicates with an if-then-else structure.
cse_detection:
Fix a bug: when hoisting a common desconstruction X = f(Yi), create
new variables for the Yi. This avoids problems with any of the Yis
appearing in other branches of the code.
goal_util:
Add a new predicate for use by cse_detection.
common:
Fix a bug: recompute instmap deltas, since they may be affected by the
optimization of common structures.
code_info:
Make an error message more explicit.
det_analysis:
Restrict import list to the needed modules.
*.m:
Import assoc_list.
compiler/mode_errors.m:
Change the heuristic for reporting mode errors, so that
it will hopefully pick the right error to report more
often. This change is in response to a bug report from
Philip Dart.
modes.m, mode_errors.m, mode_util.m:
Finish implementing mode checking of lambda expressions.
inst_match.m:
Mode checking of higher-order pred modes was slightly
too strict - relax it a little.
modes.m, mode_errors.m, mode_info.m:
For mode errors that occur in predicate calls,
record the argument number that they occurred in,
and print it out in mode error messages.
(This also fixes a bug where some of the determinism
error messages would say "in argument 0 of call to pred ...").
polymorphism.m:
A couple of minor simplifications.
options:
Cleanup of the option set. Main change is making linking the default,
and the replacement of -g, --compile and --link by -e, -C and -c.
WARNING: this makes the compiler inconsistent with the standard mmake
configuration, so don't do a cvs update yet unless you know what you
are doing.
conf:
Find out at configuration time how many bits the --tags low option
uses.
mercury_compile:
With the help of conf, we now make sure --tags and --num-tag-bits
are consistent. We use the new set of options. We also generate
program-specific .clean rules in .dep files.
make_tags:
Mercury_compile now makes sure that --tags and --num-tag-bits are
consistent, so make_tags need not do it.
mode_errors:
Use the new set of options.
llds:
Changes to introduce the new option use_macro_for_redo_fail and
change --mod-comments into --auto-comments.
cse_detection:
We now print the messages about redoing mode analysis, switch detection
and cse detection only if very verbose is on.
typecheck:
The error message for wrong number of arguments now gives the actual
number and the right number(s).
value_number:
Tighten the sanity check; theold version wasn't tight enough for
the code generated for prof.m.
hlds.m and lots of other files:
Change the type of the first two arguments of unify/5 in
hlds__goal_expr from `term, term' to `var, unify_rhs'
where unify_rhs is given by
:- type unify_rhs
---> var(var)
; functor(const, list(var))
; lambda_goal(list(var), hlds__goal).
This change was for two reasons: firstly, it simplifies the
code in a lot of places, and secondly, it is a step towards
implementing lambda closures and higher-order predicates
properly.
compiler/*:
Add copyright messages.
Change all occurences of *.nl in comments to *.m.
compiler/mercury_compile.pp:
Change the output to the .dep files to use *.m rather than *.nl.
(NOTE: this means that `mmake' will not work any more if you
call your files *.nl!!!)
Makefile.common:
Add new targets `mercury_compile.sicstus' (the Mercury compiler
compiled with Sicstus) and `mercury_compile.sicstus.debug'
(debugging version of the above).
*.nl:
Use Sicstus-compatible char and string escapes.
Avoid the use of explicit existential quantification.
Various other hacks to get things to parse correctly under Sicstus.
prog_io.nl:
Don't allow (A -> B) in DCGs, since NU-Prolog and Mercury give
it different semantics to Sicstus.
sp_builtin.nl, sp_lib.nl:
Split sp_builtin.nl into sp_builtin.nl and sp_lib.nl.
sp_conv.sed:
Add sed script which converts some character escapes so that
they work with Sicstus.
term_io.nl:
Remove term_io__prefix_op etc. since they aren't used anymore.
Makefile.common:
Add some targets for compiling the compiler and the library.
type_util.nl, dense_switch.nl, switch_gen.nl, polymorphism.nl:
Rename inttype, chartype, etc. as int_type, char_type, etc.
Add polymorphic_type.
modes.nl, mode_errors.nl:
Report an error for direct attempts to unify higher-order pred types.
(Of course, we don't catch indirect attempts via polymorphic types -
that would require global analysis. For them, we report the error
at runtime.)
modes.nl:
Remove unreachable code from conjuctions.
(XXX also should do this for if-then-else.)
options.nl:
Turn -p off by default. I'll turn it on again when it works ;-)
modes.nl:
Fix a couple of newly introduced bugs.
Update a few of the comments.
Change it so that `ground' does _not_ match `bound(...)'
(still not quite right, since there are some cases when it
should match, but this fix should be enough for the moment).
modes.nl, mode_errors.nl:
Fix mode declarations to comply with the above change.
builtins.nl, call_gen.nl, code_util.nl, mercury_compile.nl, modes.nl:
Remove the "detect builtins" pass.
Instead, determing which predicate calls are builtins
happens during the mode analysis pass. modes.nl calls
code_util__is_builtin.
io.nl, io.nu.nl:
Move io__get/set_globals from io.nu.nl to io.nl.
modes.nl, mode_errors.nl:
Warn about predicates which have no modes.
arg_info.nl:
Generate correct arg_info for all predicates, including
imported predicates and predicates with no clauses.
typecheck.nl:
Don't warn about predicate having no clauses if the
the predicate is a builtin.
modes.nl, mode_errors.nl:
Did some work towards implementing implied modes. We still
don't implement them yet, but at least we know report an error if
you try (and you also used --generate-code).
*Makefile*:
Ensure that Makefile.mercury can be used as a generic
Makefile for Mercury programs. It now gets included by the
Makefiles in the tests/ directory.
(It's highly likely that these changes have broken something.)
code_util.nl, peephole.nl, code_info.nl:
Move peephole__neg_rval to code_util.nl, so that it can
also be used by code_info.nl. Improve it a bit.
disj_gen.nl:
Minor stylistic changes.
peephole.nl:
Use bintree_set(label) rather than map(label, bool).
ite_gen.nl:
Implement non-deterministic if-then-elses.
mercury_compile.nl:
Change the action in the automatically generated .dep makefile
to use `$(MNL)' rather than `$(NC)' to link the `.no' files
together.
mode_util.nl, mode_info.nl:
Fix some (recently detected) determinism errors.
options.nl:
Rearrange the options into a vaguely meaninful order and
add a couple of comments.
*.nl:
Rename globals__lookup*option as globals__io_lookup*option.
Create new globals__lookup*option predicates.
Fix up the option handling in the code generator.
bintree.nl, map.nl, varset.nl:
Remove map__search_insert; it's not needed and it's not
really useful.
bintree.nl:
Fix determinism problem in bintree__from_list_2.
options.nl, det_analysis.nl, make_hlds.nl:
Add options to suppress determinism warnings.
det_analysis.nl, hlds.nl, modes.nl:
Allow the delta-instmap to be `unreachable'.
hlds_out.nl:
Output the delta-instmap.
Output conjunctions differently in verbose mode.
llds.nl:
Fix determinism problem.
Change GOTO(LABEL(...)) into GOTO_LABEL(...) which can be
more efficient.
map.nl:
Add map__overlay/3.
typecheck.nl, modes.nl, mode_errors.nl, options.nl, hlds_out.nl.
Split the old `debug' option into debug-types and debug-modes.
Change the default for the `modecheck' option to `yes'.
Add a new verbose-dump-hlds option, and use that instead
of the very-verbose option in hlds_out.nl.
mode_util.nl:
Export mode_get_insts/4.
Add instmap_lookup_var (moved from modes.nl).
Add apply_instmap_delta.
modes.nl, term.nl, prog_util.nl:
Add determinism annotations.
term.nl, prog_io.nl:
Fix bugs in when declarations.
std_util.nl, prog_io.nl:
Add a maybe(T) type to std_util.nl.
Rename the maybe(T) type in prog_io.nl as maybe1(T).
mercury_builtin.nl:
Use det_pred(...), semidet_pred(...), nondet_pred(...)
rather than call_pred(...) for the higher-order predicate modes.
prog_io.nl, io.nl, varset.nl, etc.
Add determinism annotations.
hlds.nl, make_hlds.nl, LOTS of other files:
Reorganize the way the predicate table works.
Make hlds.nl a bit more modular.
Change call/4 to call/5.
Remove all/2 from the hlds.
Changed pred_id to an integer.
Added pred_call_id which is similar to the old pred_id.
Makefile:
Add a rule for creating *.hlds_dump.
array.nl:
Fix determinism error.
det_analysis.nl:
Fix a bug in printing determinism warnings.
fix_errors.sed:
Modify this so it allows all the `inferred nondet' determinism
errors but none of the `inferred semidet' ones.
llds.nl:
Rename llds__pred_mode_id as llds__proc_id.
mode_errors.nl:
Finally got around to implementing Zoltan's suggestions
about the error messages from the mode analysis.
If an error occurs in a conjunction, only one error message
is printed out - the first error which doesn't relate to
a head unification.
modes.nl:
Handle X = f(X) properly. NB: determinism analysis and code
generation still get it wrong!
undef_modes, undef_insts:
I've broken the error message code, since it's not easy
to print pred_ids. I just changed it so that it didn't
print the pred_ids out. Should fix this properly at some stage...
builtins.nl, hlds.nl, det_analysis.nl, hlds_out.nl:
Change case/3 to case/2.
char.nl, mode_info.nl:
Add some determinism declarations.
hlds.nl:
Change the `liveness' field to a `delta_liveness' field.
Add goal_to_conj_list/2 and goal_to_disj_list/2.
hlds_out.nl:
Export hlds_out__write_goal.
make_hlds.nl:
Warn about missing determinism annotations.
mercury_to_mercury.nl, hlds_out.nl:
Fix the problem where determinism annotations were
not being output correctly for zero-arity predicates
in interface files.
mercury_to_mercury.nl, mode_errors.nl:
Remove mercury_output_hlds_goal (it's been replaced by
hlds_out__write_goal).
parser.nl:
Minor change.
switch_detection.nl:
Fix this. It now works!
toplevel.nl:
Call switch_detection.nl.
Makefile, doit.nl:
Add switch_detection.nl.
modes.nl, mode_errors.nl, delay_info.nl, mode_info.nl, undef_modes.nl:
Break modes.nl up into separate modules.
toplevel.nl (plus LOTS of other files):
Change the way module imports are handled. Fix the resulting missing
import problems found in most of the modules.
mode_util.nl:
Add predicate inst_is_bound_to_functors/3.
switch_detection.nl:
New file. Still very incomplete.
meta.nl:
Remove. This file was old junk.