mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-21 20:33:55 +00:00
083d376e6598628362ee91c2da170febd83590f4
5 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
8355718b16 |
Allow pred pragmas to specify pred_or_func.
Pragmas that apply to a pred_info have traditionally specified that
pred_info by a symname/arity pair. However, this can be ambiguous
if there is both a predicate and a function with that symname/arity pair.
This diff therefore allows pragmas that previously took "symname/arity"
to also take "pred(symname/arity)" and "func(symname/arity").
If e.g. there is both a pred foo/2 and a func foo/2 accessible from
the current module, the old form applied to both, while the new forms
apply to just one.
Later, we could change the behavior of the old form to insist on a
unique match, but before we do, we should have a mechanism that allows
programmers to resolve the ambiguity. (They could rename either the
pred or the func, but it is less intrusive for the compiler not to
insist on that.) This is that mechanism.
In the process of implementing this change, I had to update lots of code
that dealt with arities, since one main difference between predicates
and functions is that for the latter, the user visible arity and
the internal compiler arity are different, in that the former does not
count the return value, and the latter does. The existing "arity" type
is an equivalence to int, and thus does not indicate which notion is meant.
I therefore added two notag types, user_arity and pred_form_arity,
for the two notions above respectively, and made a start on using them,
though for now, only in the code sections affected by the main change above.
compiler/prog_item.m:
Change the types that represent the specifications of predicates
(in the sense of pred_infos) and functions to allow the representation
of not just "symname/arity," but also "pred(symname/arity)" and
"func(symname/arity"). There is one exception: for the oisu (order
independent state update) pragma, require the presence of either
a pred() vs func() wrapper. This is not a breaking change, since oisu
pragmas are neither publicly documented or really implemented.
Pragmas that allow the representation of argument modes implicitly
specify pred vs func by taking the mode list either as
(m1, m2, ... mn) or as (m1, m2, ...) = mn. Encode this invariant
in the representation type. Make this type also include an arity
only in the absence of a mode list, to make unrepresentable
any inconsistent state in which the stated arity and the length
of the mode list disagree.
Give the new types used for these updated representations names
that state whether they specify a pred_info or a proc_info
(or in one case that we should later fix, that they can specify either).
Put the pred or func indication before the symname and arity
both in these new types, and in some old types. Do this both because
the pred or func indication comes before the name in Mercury declarations,
and to help the compiler find all the places where code using the old
forms had to be revisited and checked for any needed updates.
Provide utility operations on the new types involved in the
updated representations.
compiler/prog_data.m:
Add the user_arity and pred_form_arity types, as mentioned above.
Add a type that is mostly used in item representations, but is also
useful elsewhere.
compiler/parse_pragma.m:
compiler/parse_pragma_analysis.m:
compiler/parse_pragma_foreign.m:
compiler/parse_pragma_tabling.m:
compiler/parse_util.m:
Accept the pred() or func() wrappers mentioned above, and generate
the updated representations when parsing terms containing pragmas.
compiler/parse_tree_out_pragma.m:
Accept the updated representations of pragmas when printing them out.
compiler/add_pragma.m:
compiler/add_pragma_tabling.m:
compiler/add_pragma_type_spec.m:
Use the updated representations when adding pragmas to the HLDS.
compiler/error_util.m:
Provide mechanisms for use above when printing references to pred_infos
using user arities, to complement the existing mechanisms which use
arities that they treat as pred form arities. The latter is what
you want when generating error messages about pred_infos that
already included functions' return types in the argument list;
the former is what you want when generating error messages
about user input that has not yet been subject to that treatment,
such as a pragma that has just been read in. (The difference is
only in what form of arity these mechanisms take as *input*;
the output is always user arity, which after all is what users
are interested in.)
compiler/hlds_error_util.m:
Provide a user_arity equivalent to a piece of existing pred_form_arity
functionality, for use by the modules above.
Provide utility functions used when generating error messages.
compiler/fact_table.m:
Replace most uses of the "arity" type with the "user_arity" type.
Done mostly in the process of figuring out which kind of arity
the top predicates took as arguments.
Put argument lists into a sensible order.
compiler/prog_out.m:
compiler/prog_util.m:
Add utility functionality needed above.
compiler/add_mutable_aux_preds.m:
compiler/convert_parse_tree.m:
compiler/equiv_type.m:
compiler/get_dependencies.m:
compiler/intermod.m:
compiler/item_util.m:
compiler/make_hlds_passes.m:
compiler/module_qual.qualify_items.m:
compiler/recompilation.usage.m:
compiler/recompilation.version.m:
compiler/typecheck_errors.m:
compiler/unused_args.m:
Conform to the changes above.
compiler/hlds_pred.m:
Add an XXX.
compiler/notes/order_indep_state_update:
Fix typos.
tests/hard_coded/bad_direct_reuse.m:
tests/hard_coded/bad_indirect_reuse.m:
tests/hard_coded/bitmap_simple.m:
tests/hard_coded/constraint_order.m:
tests/hard_coded/equality_pred_which_requires_boxing.m:
tests/hard_coded/fact_table_test_1.m:
tests/hard_coded/float_consistency.m:
tests/hard_coded/foreign_enum_rtti.m:
tests/hard_coded/foreign_enum_switch.m:
tests/hard_coded/foreign_import_module_2.m:
tests/hard_coded/gh72.m:
tests/hard_coded/gh72a.m:
tests/hard_coded/heap_ref_mask_tag.m:
tests/hard_coded/intermod_multimode.m:
tests/hard_coded/mode_check_clauses.m:
tests/hard_coded/multimode_addr.m:
tests/hard_coded/type_spec_ho_term.m:
tests/hard_coded/user_defined_equality2.m:
Add pred() or func() wrappers to symname/arity pairs in pragmas,
to test whether the parser accepts them.
Fix deviations from our current coding standards.
tests/hard_coded/oisu_check_db.m:
tests/invalid/oisu_check_add_pragma_errors.{m,err_exp}:
tests/invalid/oisu_check_semantic_errors.m:
Add the pred() wrappers now required in oisu pragmas.
Expect the improved wording of an error message.
|
||
|
|
d23c4f74a3 | Update the style of more tests. | ||
|
|
33eb3028f5 |
Clean up the tests in half the test directories.
tests/accumulator/*.m:
tests/analysis_*/*.m:
tests/benchmarks*/*.m:
tests/debugger*/*.{m,exp,inp}:
tests/declarative_debugger*/*.{m,exp,inp}:
tests/dppd*/*.m:
tests/exceptions*/*.m:
tests/general*/*.m:
tests/grade_subdirs*/*.m:
tests/hard_coded*/*.m:
Make these tests use four-space indentation, and ensure that
each module is imported on its own line. (I intend to use the latter
to figure out which subdirectories' tests can be executed in parallel.)
These changes usually move code to different lines. For the debugger tests,
specify the new line numbers in .inp files and expect them in .exp files.
|
||
|
|
459847a064 |
Move the univ, maybe, pair and unit types from std_util into their own
Estimated hours taken: 18 Branches: main Move the univ, maybe, pair and unit types from std_util into their own modules. std_util still contains the general purpose higher-order programming constructs. library/std_util.m: Move univ, maybe, pair and unit (plus any other related types and procedures) into their own modules. library/maybe.m: New module. This contains the maybe and maybe_error types and the associated procedures. library/pair.m: New module. This contains the pair type and associated procedures. library/unit.m: New module. This contains the types unit/0 and unit/1. library/univ.m: New module. This contains the univ type and associated procedures. library/library.m: Add the new modules. library/private_builtin.m: Update the declaration of the type_ctor_info struct for univ. runtime/mercury.h: Update the declaration for the type_ctor_info struct for univ. runtime/mercury_mcpp.h: runtime/mercury_hlc_types.h: Update the definition of MR_Univ. runtime/mercury_init.h: Fix a comment: ML_type_name is now exported from type_desc.m. compiler/mlds_to_il.m: Update the the name of the module that defines univs (which are handled specially by the il code generator.) library/*.m: compiler/*.m: browser/*.m: mdbcomp/*.m: profiler/*.m: deep_profiler/*.m: Conform to the above changes. Import the new modules where they are needed; don't import std_util where it isn't needed. Fix formatting in lots of modules. Delete duplicate module imports. tests/*: Update the test suite to confrom to the above changes. |
||
|
|
0a58be4096 |
Fix several performance problems that arose when compiling predicates defined
Estimated hours taken: 10
Branches: main
Fix several performance problems that arose when compiling predicates defined
by lots of facts, e.g. 16000 facts of the edge relation used in my recent
paper with Kostis on tabling. We couldn't use fact tables because they return
solutions in a different order, which would be OK semantically but which
invalidated the performance comparison we tried to make. I had to either fix
fact tables to use standard order or fix the performance problems of the usual
path of compilation. The latter is more generally useful, and reduces the
chances of any similar surprises.
The first performance problem was the quadratic complexity of always adding
clauses at the end of the clause list. The fix is to keep the list in reverse
order while it is being added to. This takes the time to read in the 16000-fact
predicate from 80+s to ~1s.
The second performance problem was our use of generate/test to check whether
any clause had impure code when copying the clauses to procs. Since we don't
have tail recursion for model_non code, this couldn't reuse stack frames, and
as a result ran at memory speed, not cache speed. The fix is to use an explicit
recursive predicate. (A better fix would be to implement proper tail recursion
for model_non code, but that would take significantly longer.) This fix
doesn't make much difference in the usual grades, but makes a significant
difference in debug grades.
The third performance problem is the quadratic or worse behavior of the mode
checker when merging the instmaps of disjuncts at the ends of large
disjunctions. With our old setup, this was inevitable, since given a bunch of
facts of the form
edge(1, 2).
edge(2, 3).
edge(3, 4).
...
etc, the instmap delta the mode checker builds for HeadVar__1 for the
disjunction of clauses is free -> bound(1; 2; 3; ...). The solution to that
is to add a new pragma, mode_check_clauses, that causes the mode checker
to check each clause individually, and to create a simple free -> ground
(or whatever the declared mode calls for) instmap delta for HeadVar__1.
We should consider making this pragma be implied for predicates defined
by lots of facts, but this diff does not do that. This change takes the
time to modecheck that 16000-fact predicate from ~360s to ~5s.
Theoretically, another way of tackling the problem would have been to
introduce widening, in which any list of functors inside "bound()" whose
length was above the threshold would be replaced by "ground", if the arguments
of the functors themselves were bound. However, that change would be much more
complex, and its behavior would be hard for users to predict. In a future
constraint-based mode system with separate passes for computing
producers/consumers and for computing the set of function symbols a
variable can be bound to, we could simply disable the latter pass
for predicates like this.
There are at least three other performance problems left. The fourth is
the same as the third, except for unique mode checking. The fifth is in
simplification, and the sixth is in equiv_type_hlds. I'll work on those next.
compiler/hlds_pred.m:
Instead of exposing the clause list part of the clause_info, make it
an abstract type. Make the abstract type keep the reverse list when
adding clauses to the list, the forward list when the later parts
of the compiler manipulate the clause list, and both when it is
convenient to do so. Add the predicates necessary to manipulate
this more complex representation. Move the code manipulating
clauses_infos into its own implementation section, next to its
declarations.
Add a new mode_check_clauses predicate marker, which records the
presence of the new pragma.
Fix departures from our coding standard.
compiler/clause_to_proc.m:
Replace the generate/test code with an explicit loop, as
mentioned above.
compiler/prog_data.m:
Add the new pragma.
compiler/prog_io_pragma.m:
Recognize the new pragma.
compiler/modes.m:
Implement separate mode checking of clauses.
Convert the file to use four-space indentation to reduce the number of
bad line breaks. Give some predicates more meaningful names.
Use error_util to print some error messages. Fix departures from
our coding standard.
compiler/make_hlds.m:
compiler/hlds_out.m:
compiler/intermod.m:
compiler/mercury_to_mercury.m:
compiler/module_qual.m:
compiler/modules.m:
compiler/recompilation.version.m:
Handle the new pragma.
compiler/*.m:
Conform to the change in hlds_pred.m and/or prog_data.m.
In some cases, convert files to four-space indentation.
tests/hard_coded/mode_check_clauses.{m,exp}:
A new test case to check that the mode_check_clauses pragma works
correctly.
tests/hard_coded/Mmakefile:
Enable the new test case.
|