mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-21 04:13:46 +00:00
The purpose of this diff is to allow Mercury programs to contain
impure Mercury code without the compiler changing its behavior
inappropriately, while still allowing the compiler to aggressively
optimize pure code. To do this, we require impure predicates to be so
declared, and calls to impure predicates to be flagged as such. We
also allow predicates implemented in terms of impure predicates to be
promised to be pure; lacking such a promise, any predicate that calls
an impure predicate is assumed to be impure.
At the moment, we don't allow impure functions (only predicates),
though some of the work necessary to support them has been done.
Note that to make the operators work properly, the precedence of the
`pred' and `func' operators has been changed from 1199 to 800.
Estimated hours taken: 150
compiler/purity.m:
New compiler pass for purity checking.
compiler/hlds_goal.m:
Add `impure' and `semipure' to the goal_feature enum.
compiler/hlds_out.m:
compiler/typecheck.m:
compiler/special_pred.m:
Fixed code that prints predicate name to write something more
helpful for special (compiler-generated) predicates. Added
code to print new markers. Added purity argument to
mercury_output_pred_type. New public predicate
special_pred_description/2 provides an english description for
each compiler-generated predicate.
compiler/hlds_pred.m:
Add `impure' and `semipure' to marker enum. Added new
public predicates to get predicate purity and whether or not
it's promised to be pure.
compiler/prog_data.m:
compiler/mercury_to_mercury.m:
compiler/prog_io.m:
compiler/prog_io_goal.m:
compiler/prog_io_pragma.m:
compiler/prog_io_dcg.m:
compiler/prog_util.m:
compiler/equiv_type.m:
compiler/intermod.m:
compiler/mercury_to_c.m:
compiler/module_qual.m:
Add purity argument to pred and func items. Add new `impure'
and `semipure' operators. Add promise_pure pragma. Add
purity/2 wrapper to goal_expr type.
compiler/make_hlds.m:
compiler/mercury_to_goedel.m:
Added purity argument to module_add_{pred,func},
clauses_info_add_pragma_c_code, and to pred and func items.
Handle promise_pure pragma. Handle purity/2 wrapper used to
handle user-written impurity annotations on goals.
compiler/mercury_compile.m:
Add purity checking pass between type and mode checking.
compiler/mode_errors.m:
Distinguish mode errors caused by impure goals preventing
goals being delayed.
compiler/modes.m:
Don't delay impure goals, and ensure before scheduling an
impure goal that no goals are delayed. Actually, we go ahead
and try to schedule goals even if impurity causes a problem,
and then if it still doesn't mode check, then we report an
ordinary mode error. Only if the clause would be mode correct
except for an impure goal do we report it as an impurity problem.
compiler/simplify.m:
Don't optimize away non-pure duplicate calls. We could do
better and still optimize duplicate semipure goals without an
intervening impure goal, but it's probably not worth the
trouble. Also don't eliminate impure goals on a failing branch.
compiler/notes/compiler_design.html:
Documented purity checking pass.
doc/reference_manual.texi:
Document purity system.
doc/transition_guide.texi:
library/nc_builtin.nl:
library/ops.m:
library/sp_builtin.nl:
New operators and new precdence for `pred' and `func'
operators.
tests/hard_coded/purity.m
tests/hard_coded/purity.exp
tests/hard_coded/Mmakefile:
tests/invalid/purity.m
tests/invalid/purity_nonsense.m
tests/invalid/purity.err_exp
tests/invalid/purity_nonsense.err_exp
tests/invalid/Mmakefile:
Test cases for purity.
120 lines
1.9 KiB
Mathematica
120 lines
1.9 KiB
Mathematica
:- module purity.
|
|
|
|
%----------------------------------------------------------------
|
|
% Needed for later tests.
|
|
|
|
:- type foo ---> a ; b.
|
|
|
|
:- impure pred imp is det.
|
|
:- pragma c_code(imp, will_not_call_mercury, ";").
|
|
|
|
:- semipure pred semi is semidet.
|
|
:- pragma c_code(semi, will_not_call_mercury, "SUCCESS_INDICATOR=0;").
|
|
|
|
:- pred in(foo).
|
|
:- mode in(in) is semidet.
|
|
in(a).
|
|
|
|
:- impure pred imp1(foo).
|
|
:- mode imp1(in) is semidet.
|
|
:- pragma c_code(imp1(_X::in), will_not_call_mercury, "SUCCESS_INDICATOR=0;").
|
|
|
|
|
|
|
|
%----------------------------------------------------------------
|
|
% Warnings
|
|
|
|
|
|
:- impure pred w1 is det.
|
|
|
|
w1.
|
|
|
|
:- semipure pred w2 is det.
|
|
|
|
w2.
|
|
|
|
:- impure pred w3 is semidet.
|
|
|
|
w3 :- semipure semi.
|
|
|
|
:- pred w4 is det.
|
|
:- pragma promise_pure(w4/0).
|
|
|
|
w4.
|
|
|
|
:- impure pred w5 is det.
|
|
:- pragma promise_pure(w5/0).
|
|
|
|
w5 :- impure imp.
|
|
|
|
:- semipure pred w6 is semidet.
|
|
:- pragma promise_pure(w6/0).
|
|
|
|
w6 :- semipure semi.
|
|
|
|
|
|
%----------------------------------------------------------------
|
|
% Errors
|
|
|
|
:- pred e1 is det.
|
|
|
|
e1 :- impure imp.
|
|
|
|
|
|
:- pred e2 is semidet.
|
|
|
|
e2 :- semipure semi.
|
|
|
|
:- semipure pred e3 is det.
|
|
|
|
e3 :- impure imp.
|
|
|
|
:- impure pred e4 is det.
|
|
|
|
e4 :- imp.
|
|
|
|
:- semipure pred e5 is semidet.
|
|
|
|
e5 :- semi.
|
|
|
|
:- impure pred e6 is semidet.
|
|
|
|
e6 :-
|
|
in(X),
|
|
impure imp,
|
|
X = a.
|
|
|
|
:- impure pred e7 is semidet.
|
|
|
|
e7 :-
|
|
impure imp1(X),
|
|
X = a.
|
|
|
|
:- type e8 ---> e8(foo) where equality is imp2.
|
|
|
|
:- impure pred imp2(e8, e8).
|
|
:- mode imp2(in, in) is semidet.
|
|
|
|
:- pragma c_code(imp2(_X::in, _Y::in), will_not_call_mercury,
|
|
"SUCCESS_INDICATOR=0;").
|
|
|
|
:- type e9 ---> e9(foo) where equality is semi2.
|
|
|
|
:- semipure pred semi2(e9, e9).
|
|
:- mode semi2(in, in) is semidet.
|
|
|
|
:- pragma c_code(semi2(_X::in, _Y::in), will_not_call_mercury,
|
|
"SUCCESS_INDICATOR=0;").
|
|
|
|
:- pred e10 is semidet.
|
|
|
|
e10 :-
|
|
Goal1 = lambda([] is semidet, imp1(b)),
|
|
call(Goal1).
|
|
|
|
:- pred e11 is semidet.
|
|
|
|
e11 :-
|
|
Goal2 = lambda([] is semidet, semi),
|
|
call(Goal2).
|