mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-14 21:35:49 +00:00
compiler/superhomogeneous.m:
Record a unification between X and f(Yi) as possibly leading to
an occurs check warning only if f is known to be a data constructor,
either user defined or the builtin tuple constructor.
compiler/hlds_cons.m:
Add a version of the search_cons_table predicate that does not construct
the list of hlds_cons_defns that match the given cons_id. The new code
in superhomogeneous.m needs to know whether a cons_id is a known data
constructor, but it does not need to know its matching definitions,
and constructing that list is reasonably expensive when it has to be
executed for every single function symbol in every clause.
Add some documentation of the existing predicates, and separate their
implementations from each other with lines.
tests/warnings/occurs.{m,exp}:
Extend this test case both with a unifications we should warn about
(a circular unification whose top level cons_id is a tuple constructor)
and one we should not warn about (when the cons_is is NOT a data
constructor of any kind).
compiler/implementation_defined_literals.m:
compiler/prog_data.m:
Clarify related documentation.
245 lines
9.8 KiB
Mathematica
245 lines
9.8 KiB
Mathematica
%-----------------------------------------------------------------------------%
|
|
% vim: ft=mercury ts=4 sw=4 et
|
|
%-----------------------------------------------------------------------------%
|
|
% Copyright (C) 2008-2012 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.
|
|
%-----------------------------------------------------------------------------%
|
|
%
|
|
% File: implementation_defined_literals.m.
|
|
% Author: wangp.
|
|
%
|
|
% This module replaces implementation-defined literals such as $file and $line
|
|
% by real constants. We transform clauses rather than procedures because
|
|
% currently, clauses rather than procedures are written out to `.opt' files,
|
|
% and $file and $line must be substituted before being written out.
|
|
%
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- module check_hlds.implementation_defined_literals.
|
|
:- interface.
|
|
|
|
:- import_module hlds.
|
|
:- import_module hlds.hlds_module.
|
|
|
|
:- pred subst_impl_defined_literals(module_info::in, module_info::out) is det.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
:- import_module hlds.hlds_clauses.
|
|
:- import_module hlds.hlds_goal.
|
|
:- import_module hlds.hlds_out.
|
|
:- import_module hlds.hlds_out.hlds_out_util.
|
|
:- import_module hlds.hlds_pred.
|
|
:- import_module hlds.make_goal.
|
|
:- import_module libs.
|
|
:- import_module libs.compute_grade.
|
|
:- import_module mdbcomp.
|
|
:- import_module mdbcomp.sym_name.
|
|
:- import_module parse_tree.
|
|
:- import_module parse_tree.prog_data.
|
|
|
|
:- import_module list.
|
|
:- import_module map.
|
|
:- import_module require.
|
|
:- import_module term.
|
|
|
|
:- type subst_literals_info
|
|
---> subst_literals_info(
|
|
module_info,
|
|
pred_info,
|
|
pred_id
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
subst_impl_defined_literals(!ModuleInfo) :-
|
|
module_info_get_preds(!.ModuleInfo, Preds0),
|
|
map.map_values(subst_literals_in_pred(!.ModuleInfo), Preds0, Preds),
|
|
module_info_set_preds(Preds, !ModuleInfo).
|
|
|
|
:- pred subst_literals_in_pred(module_info::in, pred_id::in, pred_info::in,
|
|
pred_info::out) is det.
|
|
|
|
subst_literals_in_pred(ModuleInfo, PredId, PredInfo0, PredInfo) :-
|
|
pred_info_get_clauses_info(PredInfo0, ClausesInfo0),
|
|
clauses_info_get_clauses_rep(ClausesInfo0, ClausesRep0, ItemNumbers),
|
|
get_clause_list_for_replacement(ClausesRep0, Clauses0),
|
|
Info = subst_literals_info(ModuleInfo, PredInfo0, PredId),
|
|
list.map(subst_literals_in_clause(Info), Clauses0, Clauses),
|
|
set_clause_list(Clauses, ClausesRep),
|
|
clauses_info_set_clauses_rep(ClausesRep, ItemNumbers,
|
|
ClausesInfo0, ClausesInfo),
|
|
pred_info_set_clauses_info(ClausesInfo, PredInfo0, PredInfo).
|
|
|
|
:- pred subst_literals_in_clause(subst_literals_info::in, clause::in,
|
|
clause::out) is det.
|
|
|
|
subst_literals_in_clause(Info, Clause0, Clause) :-
|
|
Body0 = Clause0 ^ clause_body,
|
|
subst_literals_in_goal(Info, Body0, Body),
|
|
Clause = Clause0 ^ clause_body := Body.
|
|
|
|
:- pred subst_literals_in_goal(subst_literals_info::in, hlds_goal::in,
|
|
hlds_goal::out) is det.
|
|
|
|
subst_literals_in_goal(Info, Goal0, Goal) :-
|
|
Goal0 = hlds_goal(GoalExpr0, GoalInfo0),
|
|
(
|
|
GoalExpr0 = unify(Var, RHS0, Mode, Kind, UnifyContext),
|
|
(
|
|
RHS0 = rhs_functor(ConsId, _, _),
|
|
(
|
|
ConsId = impl_defined_const(Name),
|
|
Context = goal_info_get_context(GoalInfo0),
|
|
make_impl_defined_literal(Var, Name, Context, Info, Goal1),
|
|
Goal1 = hlds_goal(GoalExpr, _),
|
|
Goal = hlds_goal(GoalExpr, GoalInfo0)
|
|
;
|
|
( ConsId = cons(_, _, _)
|
|
; ConsId = tuple_cons(_)
|
|
; ConsId = closure_cons(_, _)
|
|
; ConsId = int_const(_)
|
|
; ConsId = uint_const(_)
|
|
; ConsId = int8_const(_)
|
|
; ConsId = uint8_const(_)
|
|
; ConsId = int16_const(_)
|
|
; ConsId = uint16_const(_)
|
|
; ConsId = int32_const(_)
|
|
; ConsId = uint32_const(_)
|
|
; ConsId = int64_const(_)
|
|
; ConsId = uint64_const(_)
|
|
; ConsId = float_const(_)
|
|
; ConsId = char_const(_)
|
|
; ConsId = string_const(_)
|
|
; ConsId = type_ctor_info_const(_, _, _)
|
|
; ConsId = base_typeclass_info_const(_, _, _, _)
|
|
; ConsId = type_info_cell_constructor(_)
|
|
; ConsId = typeclass_info_cell_constructor
|
|
; ConsId = type_info_const(_)
|
|
; ConsId = typeclass_info_const(_)
|
|
; ConsId = ground_term_const(_, _)
|
|
; ConsId = tabling_info_const(_)
|
|
; ConsId = deep_profiling_proc_layout(_)
|
|
; ConsId = table_io_entry_desc(_)
|
|
),
|
|
Goal = Goal0
|
|
)
|
|
;
|
|
RHS0 = rhs_lambda_goal(LambdaPurity, Groundness, PredOrFunc,
|
|
EvalMethod, LambdaNonLocals, LambdaQuantVars,
|
|
LambdaModes, LambdaDetism, LambdaGoal0),
|
|
subst_literals_in_goal(Info, LambdaGoal0, LambdaGoal),
|
|
RHS = rhs_lambda_goal(LambdaPurity, Groundness, PredOrFunc,
|
|
EvalMethod, LambdaNonLocals, LambdaQuantVars,
|
|
LambdaModes, LambdaDetism, LambdaGoal),
|
|
GoalExpr = unify(Var, RHS, Mode, Kind, UnifyContext),
|
|
Goal = hlds_goal(GoalExpr, GoalInfo0)
|
|
;
|
|
RHS0 = rhs_var(_),
|
|
Goal = Goal0
|
|
)
|
|
;
|
|
GoalExpr0 = negation(SubGoal0),
|
|
subst_literals_in_goal(Info, SubGoal0, SubGoal),
|
|
GoalExpr = negation(SubGoal),
|
|
Goal = hlds_goal(GoalExpr, GoalInfo0)
|
|
;
|
|
GoalExpr0 = scope(Reason, SubGoal0),
|
|
% Implementation-defined literals may appear in
|
|
% from_ground_term_construct scopes.
|
|
subst_literals_in_goal(Info, SubGoal0, SubGoal),
|
|
GoalExpr = scope(Reason, SubGoal),
|
|
Goal = hlds_goal(GoalExpr, GoalInfo0)
|
|
;
|
|
GoalExpr0 = conj(ConjType, Goals0),
|
|
list.map(subst_literals_in_goal(Info), Goals0, Goals),
|
|
GoalExpr = conj(ConjType, Goals),
|
|
Goal = hlds_goal(GoalExpr, GoalInfo0)
|
|
;
|
|
GoalExpr0 = disj(Goals0),
|
|
list.map(subst_literals_in_goal(Info), Goals0, Goals),
|
|
GoalExpr = disj(Goals),
|
|
Goal = hlds_goal(GoalExpr, GoalInfo0)
|
|
;
|
|
GoalExpr0 = switch(Var, CanFail, Cases0),
|
|
list.map(subst_literals_in_case(Info), Cases0, Cases),
|
|
GoalExpr = switch(Var, CanFail, Cases),
|
|
Goal = hlds_goal(GoalExpr, GoalInfo0)
|
|
;
|
|
GoalExpr0 = if_then_else(Vars, Cond0, Then0, Else0),
|
|
subst_literals_in_goal(Info, Cond0, Cond),
|
|
subst_literals_in_goal(Info, Then0, Then),
|
|
subst_literals_in_goal(Info, Else0, Else),
|
|
GoalExpr = if_then_else(Vars, Cond, Then, Else),
|
|
Goal = hlds_goal(GoalExpr, GoalInfo0)
|
|
;
|
|
GoalExpr0 = shorthand(Shorthand0),
|
|
(
|
|
Shorthand0 = bi_implication(A0, B0),
|
|
subst_literals_in_goal(Info, A0, A),
|
|
subst_literals_in_goal(Info, B0, B),
|
|
Shorthand = bi_implication(A, B)
|
|
;
|
|
Shorthand0 = atomic_goal(GoalType, OuterVars, InnerVars,
|
|
OutputVars, MainGoal0, OrElseGoals0, OrElseInners),
|
|
subst_literals_in_goal(Info, MainGoal0, MainGoal),
|
|
list.map(subst_literals_in_goal(Info), OrElseGoals0, OrElseGoals),
|
|
Shorthand = atomic_goal(GoalType, OuterVars, InnerVars,
|
|
OutputVars, MainGoal, OrElseGoals, OrElseInners)
|
|
;
|
|
Shorthand0 = try_goal(MaybeIOVars, ResultVar, TryGoal0),
|
|
subst_literals_in_goal(Info, TryGoal0, TryGoal),
|
|
Shorthand = try_goal(MaybeIOVars, ResultVar, TryGoal)
|
|
),
|
|
GoalExpr = shorthand(Shorthand),
|
|
Goal = hlds_goal(GoalExpr, GoalInfo0)
|
|
;
|
|
( GoalExpr0 = call_foreign_proc(_, _, _, _, _, _, _)
|
|
; GoalExpr0 = generic_call(_, _, _, _, _)
|
|
; GoalExpr0 = plain_call(_, _, _, _, _, _)
|
|
),
|
|
Goal = Goal0
|
|
).
|
|
|
|
:- pred subst_literals_in_case(subst_literals_info::in, case::in, case::out)
|
|
is det.
|
|
|
|
subst_literals_in_case(Info, Case0, Case) :-
|
|
Case0 = case(MainConsId, OtherConsIds, Goal0),
|
|
subst_literals_in_goal(Info, Goal0, Goal),
|
|
Case = case(MainConsId, OtherConsIds, Goal).
|
|
|
|
:- pred make_impl_defined_literal(prog_var::in, string::in,
|
|
term.context::in, subst_literals_info::in, hlds_goal::out) is det.
|
|
|
|
make_impl_defined_literal(Var, Name, Context, Info, Goal) :-
|
|
Context = term.context(File, Line),
|
|
Info = subst_literals_info(ModuleInfo, PredInfo, PredId),
|
|
( if Name = "file" then
|
|
make_string_const_construction(Context, Var, File, Goal)
|
|
else if Name = "line" then
|
|
make_int_const_construction(Context, Var, Line, Goal)
|
|
else if Name = "module" then
|
|
ModuleName = pred_info_module(PredInfo),
|
|
Str = sym_name_to_string(ModuleName),
|
|
make_string_const_construction(Context, Var, Str, Goal)
|
|
else if Name = "pred" then
|
|
Str = pred_id_to_string(ModuleInfo, PredId),
|
|
make_string_const_construction(Context, Var, Str, Goal)
|
|
else if Name = "grade" then
|
|
module_info_get_globals(ModuleInfo, Globals),
|
|
grade_directory_component(Globals, Grade),
|
|
make_string_const_construction(Context, Var, Grade, Goal)
|
|
else
|
|
% These should have been caught during type checking.
|
|
unexpected($pred, "unknown literal")
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
:- end_module check_hlds.implementation_defined_literals.
|
|
%-----------------------------------------------------------------------------%
|