For review: declarative debugging back end (2/3)
Mark Anthony BROWN
dougl at cs.mu.OZ.AU
Tue Jul 14 20:05:30 AEST 1998
%-----------------------------------------------------------------------------%
% Copyright (C) 1998 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: evaluation_tree_util.m
% Author: dougl
% Purpose:
% This module provides basic data structures and procedures to
% support the generation of Evaluation Dependency Trees (EDTs) for
% Mercury programs. It is used by:
%
% evaluation_tree_gen.m
% proof_tree.m
%
% This module contains:
%
% - Data structures to support the compiler stage for EDT
% generation, and access procedures for these structures.
% - Hard coded procedures that mimic the contents of
% evaluation_tree.m in the library directory.
% - Data structures to record which variant of the
% transformations is to be used for each procedure.
% - Support predicates that are common to all EDT
% transformations, but too specific to be put in
% goal_util.m
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
:- module evaluation_tree_util.
:- interface.
:- import_module globals, hlds_pred, prog_data, hlds_module, hlds_goal.
:- import_module (inst), hlds_data.
:- import_module std_util, list, term, bool, io, map, varset.
%
% Data structures for the compiler phase.
%
%
% An edt_info contains all the information required by the
% compiler to transform one module. Each edt_info is built
% in one pass of the module, and can then be used for
% transformations to support wrong answer analysis or missing
% answer analysis.
%
:- type edt_info
---> edt_info(
module_name,
globals,
map(pred_proc_id, edt_proc_info),
% Associates each procedure with details
% of its alternative versions.
list(constructor),
% The constructors for evaluation_atoms
% that can be created by this module.
pred_id, % type_to_univ/2.
proc_id, % forward mode of type_to_univ/2.
maybe(pred_proc_id)
% main/2 (if it exists in this module).
).
:- pred edt_info_init(module_info, edt_info).
:- mode edt_info_init(in, out) is det.
:- pred edt_info_get_module_name(edt_info, module_name).
:- mode edt_info_get_module_name(in, out) is det.
:- pred edt_info_get_globals(edt_info, globals).
:- mode edt_info_get_globals(in, out) is det.
:- pred edt_info_get_atom_ctors(edt_info, list(constructor)).
:- mode edt_info_get_atom_ctors(in, out) is det.
:- pred edt_info_add_atom_ctor(edt_info, constructor, edt_info).
:- mode edt_info_add_atom_ctor(in, in, out) is det.
:- pred edt_info_get_proc_map(edt_info, map(pred_proc_id, edt_proc_info)).
:- mode edt_info_get_proc_map(in, out) is det.
:- pred edt_info_add_proc(edt_info, pred_proc_id, edt_proc_info, edt_info).
:- mode edt_info_add_proc(in, in, in, out) is det.
:- pred edt_info_univ_pred_proc_id(edt_info, pred_id, proc_id).
:- mode edt_info_univ_pred_proc_id(in, out, out) is det.
:- pred edt_info_set_main_pred_proc_id(edt_info, pred_id, proc_id, edt_info).
:- mode edt_info_set_main_pred_proc_id(in, in, in, out) is det.
:- pred maybe_write_edt_info(bool, module_info, edt_info, io__state,
io__state).
:- mode maybe_write_edt_info(in, in, in, di, uo) is det.
%-----------------------------------------------------------------------------%
%
% An edt_proc_info contains data that applies to just one
% procedure. This information is collected in the first pass
% and is used by subsequent passes.
%
:- type edt_proc_info
---> edt_proc_info(
pred_id, % Id of the wrong answer version.
proc_id,
maybe(pred_proc_id), % Id of the missing answer version,
% if it exists.
cons_id, % The constructor for initial atoms
% of this procedure.
cons_id, % The constructor for final atoms of
% this procedure.
atom_descriptor % How the node arguments are built.
).
:- pred edt_proc_info_init(pred_id, proc_id, cons_id, cons_id, atom_descriptor,
edt_proc_info).
:- mode edt_proc_info_init(in, in, in, in, in, out) is det.
:- pred edt_proc_info_get_wrong_proc(edt_proc_info, pred_id, proc_id).
:- mode edt_proc_info_get_wrong_proc(in, out, out) is det.
:- pred edt_proc_info_get_miss_proc(edt_proc_info, pred_id, proc_id).
:- mode edt_proc_info_get_miss_proc(in, out, out) is semidet.
:- pred edt_proc_info_get_atom_descriptor(edt_proc_info, atom_descriptor).
:- mode edt_proc_info_get_atom_descriptor(in, out) is det.
:- pred edt_proc_info_initial_cons_id(edt_proc_info, cons_id).
:- mode edt_proc_info_initial_cons_id(in, out) is det.
:- pred edt_proc_info_final_cons_id(edt_proc_info, cons_id).
:- mode edt_proc_info_final_cons_id(in, out) is det.
:- pred write_edt_proc_info(module_info, pair(pred_proc_id, edt_proc_info),
io__state, io__state).
:- mode write_edt_proc_info(in, in, di, uo) is det.
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
%
% Hard coded data.
%
% The evaluation tree transformation adds to the HLDS references to
% fixed modules that are part of the library. This section
% hard codes the constants that are used.
%
% The information here corresponds to the contents of
% library/evaluation_tree. Any changes made to this section should
% be reflected there, and vice versa.
%
%
% Name of the module that defines the back end interface
% (library/evaluation_tree.m).
%
:- pred evaluation_tree_interface_module(module_specifier).
:- mode evaluation_tree_interface_module(out) is det.
%
% Types defined in the library module.
%
:- pred evaluation_tree_type_id(type_id).
:- mode evaluation_tree_type_id(out) is det.
:- pred proof_tree_type_id(type_id).
:- mode proof_tree_type_id(out) is det.
:- pred miss_tree_type_id(type_id).
:- mode miss_tree_type_id(out) is det.
:- pred evaluation_atom_type(module_name, (type)).
:- mode evaluation_atom_type(in, out) is det.
:- pred evaluation_atom_type_name(module_name, sym_name).
:- mode evaluation_atom_type_name(in, out) is det.
%
% Constructors for evaluation_tree/1.
%
:- pred evaluation_tree_ctor_analyse_wrong(cons_id).
:- mode evaluation_tree_ctor_analyse_wrong(out) is det.
:- pred evaluation_tree_ctor_analyse_miss(cons_id).
:- mode evaluation_tree_ctor_analyse_miss(out) is det.
:- pred evaluation_tree_ctor_implicit_wrong(cons_id).
:- mode evaluation_tree_ctor_implicit_wrong(out) is det.
:- pred evaluation_tree_ctor_implicit_miss(cons_id).
:- mode evaluation_tree_ctor_implicit_miss(out) is det.
:- pred evaluation_tree_ctor_interface_wrong(cons_id).
:- mode evaluation_tree_ctor_interface_wrong(out) is det.
:- pred evaluation_tree_ctor_interface_miss(cons_id).
:- mode evaluation_tree_ctor_interface_miss(out) is det.
:- pred evaluation_tree_ctor_assumed(cons_id).
:- mode evaluation_tree_ctor_assumed(out) is det.
%
% Constructors for proof_tree/1.
%
:- pred proof_tree_ctor_local_call(cons_id).
:- mode proof_tree_ctor_local_call(out) is det.
:- pred proof_tree_ctor_conj(cons_id).
:- mode proof_tree_ctor_conj(out) is det.
:- pred proof_tree_ctor_disj(cons_id).
:- mode proof_tree_ctor_disj(out) is det.
:- pred proof_tree_ctor_switch(cons_id).
:- mode proof_tree_ctor_switch(out) is det.
:- pred proof_tree_ctor_if_then(cons_id).
:- mode proof_tree_ctor_if_then(out) is det.
:- pred proof_tree_ctor_else(cons_id).
:- mode proof_tree_ctor_else(out) is det.
:- pred proof_tree_ctor_not(cons_id).
:- mode proof_tree_ctor_not(out) is det.
:- pred proof_tree_ctor_trivial(cons_id).
:- mode proof_tree_ctor_trivial(out) is det.
%
% Constructors for miss_tree/1.
%
:- pred miss_tree_ctor_local_call(cons_id).
:- mode miss_tree_ctor_local_call(out) is det.
:- pred miss_tree_ctor_conj(cons_id).
:- mode miss_tree_ctor_conj(out) is det.
:- pred miss_tree_ctor_disj(cons_id).
:- mode miss_tree_ctor_disj(out) is det.
:- pred miss_tree_ctor_switch(cons_id).
:- mode miss_tree_ctor_switch(out) is det.
:- pred miss_tree_ctor_if_then(cons_id).
:- mode miss_tree_ctor_if_then(out) is det.
:- pred miss_tree_ctor_else(cons_id).
:- mode miss_tree_ctor_else(out) is det.
:- pred miss_tree_ctor_not(cons_id).
:- mode miss_tree_ctor_not(out) is det.
:- pred miss_tree_ctor_trivial(cons_id).
:- mode miss_tree_ctor_trivial(out) is det.
%
% Constructors for analysis/1.
%
:- pred analysis_ctor_nondet_wrong(cons_id).
:- mode analysis_ctor_nondet_wrong(out) is det.
:- pred analysis_ctor_unavailable(cons_id).
:- mode analysis_ctor_unavailable(out) is det.
%
% Some fixed types in the library.
%
:- pred library_type_univ(type).
:- mode library_type_univ(out) is det.
%
% Constructors for list:list/1.
%
:- pred library_ctor_list_cons(cons_id).
:- mode library_ctor_list_cons(out) is det.
:- pred library_ctor_list_nil(cons_id).
:- mode library_ctor_list_nil(out) is det.
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
%
% This is used to store how the module represents atoms.
%
:- type atom_descriptor == list(atom_arg_descriptor).
:- type atom_arg_descriptor
---> direct_var(int, var, (type))
; univ_var(int, var, (type))
; io_state_di(int, var)
; io_state_uo(int, var).
:- pred write_atom_descriptor(varset, atom_descriptor, io__state, io__state).
:- mode write_atom_descriptor(in, in, di, uo) is det.
%
% This is used to specify the transformation that will be
% performed on a call inside a goal.
%
:- type analysis
---> no_analysis
; wrong_answer_analysis(pred_id, proc_id)
; full_analysis(pred_id, proc_id, pred_id, proc_id).
:- pred edt_info_proc_analysis(edt_info, pred_id, proc_id, analysis).
:- mode edt_info_proc_analysis(in, in, in, out) is det.
%
% Hard coded strategies of the transformations.
%
:- pred wrong_answer_sym_name_mangle(sym_name, sym_name).
:- mode wrong_answer_sym_name_mangle(in, out) is det.
:- pred wrong_answer_name_mangle(string, string).
:- mode wrong_answer_name_mangle(in, out) is det.
:- pred wrong_analysis_pred_sym_name(module_name, sym_name).
:- mode wrong_analysis_pred_sym_name(in, out) is det.
:- pred local_evaluation_tree_type(module_name, (type)).
:- mode local_evaluation_tree_type(in, out) is det.
:- pred local_evaluation_atom_type(module_name, (type)).
:- mode local_evaluation_atom_type(in, out) is det.
:- pred local_evaluation_atom_sym_name(module_name, sym_name).
:- mode local_evaluation_atom_sym_name(in, out) is det.
:- pred local_analysis_type(module_name, (type)).
:- mode local_analysis_type(in, out) is det.
:- pred local_analysis_inst((inst)).
:- mode local_analysis_inst(out) is det.
%
% This is the context we will use for any code added by the
% transformations.
%
:- pred generated_code_context(term__context).
:- mode generated_code_context(out) is det.
:- pred dummy_type_id(type_id).
:- mode dummy_type_id(out) is det.
:- pred ground_inst(inst).
:- mode ground_inst(out) is det.
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
%
% New types in the transformed program. These types depend on
% the module being debugged, hence they must be passed an
% edt_info.
%
:- pred edt_info_evaluation_tree_type(edt_info, (type)).
:- mode edt_info_evaluation_tree_type(in, out) is det.
:- pred edt_info_proof_tree_type(edt_info, (type)).
:- mode edt_info_proof_tree_type(in, out) is det.
:- pred edt_info_miss_tree_type(edt_info, (type)).
:- mode edt_info_miss_tree_type(in, out) is det.
:- pred edt_info_evaluation_atom_type(edt_info, (type)).
:- mode edt_info_evaluation_atom_type(in, out) is det.
:- pred edt_info_analysis_type(edt_info, (type)).
:- mode edt_info_analysis_type(in, out) is det.
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
%
% HLDS manipulation predicates. These can be used to support
% transformations for both wrong answer analysis and missing
% answer analysis.
%
:- pred make_final_atom_construction(edt_info, edt_proc_info, proc_info,
proc_info, var, hlds_goals).
:- mode make_final_atom_construction(in, in, in, out, out, out) is det.
:- pred make_evaluation_atom_type_defn(edt_info, tvarset, type_defn).
:- mode make_evaluation_atom_type_defn(in, out, out) is det.
:- pred make_simple_construction(var, cons_id, list(var), hlds_goal).
:- mode make_simple_construction(in, in, in, out) is det.
:- pred make_simple_deconstruction(var, cons_id, list(var), hlds_goal).
:- mode make_simple_deconstruction(in, in, in, out) is det.
:- pred make_closure_construction(var, sym_name, pred_id, proc_id, var,
list(var), determinism, hlds_goal_expr).
:- mode make_closure_construction(in, in, in, in, in, in, in, out) is det.
:- pred make_to_univ_call(edt_info, var, var, hlds_goal).
:- mode make_to_univ_call(in, in, in, out) is det.
:- pred make_from_univ_call(edt_info, var, var, hlds_goal).
:- mode make_from_univ_call(in, in, in, out) is det.
%
% Procedures to create new variables in the transformed part
% of the HLDS. Those procedures which take an hlds_goal_info
% as an input argument add the new variable (say V) to the
% set of nonlocals, and add {V -> ground} to the instmap_delta.
%
:- pred create_evaluation_tree_head_var(edt_info, proc_info, proc_info,
hlds_goal_info, hlds_goal_info, var).
:- mode create_evaluation_tree_head_var(in, in, out, in, out, out) is det.
:- pred create_evaluation_tree_var(edt_info, proc_info, proc_info,
hlds_goal_info, hlds_goal_info, var).
:- mode create_evaluation_tree_var(in, in, out, in, out, out) is det.
:- pred create_evaluation_atom_var(edt_info, proc_info, proc_info, var).
:- mode create_evaluation_atom_var(in, in, out, out) is det.
:- pred create_proof_tree_var(edt_info, proc_info, proc_info, hlds_goal_info,
hlds_goal_info, var).
:- mode create_proof_tree_var(in, in, out, in, out, out) is det.
:- pred create_miss_tree_var(edt_info, proc_info, proc_info, hlds_goal_info,
hlds_goal_info, var).
:- mode create_miss_tree_var(in, in, out, in, out, out) is det.
:- pred create_proof_tree_list_var(edt_info, proc_info, proc_info, var).
:- mode create_proof_tree_list_var(in, in, out, out) is det.
:- pred create_closure_var(edt_info, proc_info, proc_info, var).
:- mode create_closure_var(in, in, out, out) is det.
:- pred create_int_var(proc_info, var, proc_info).
:- mode create_int_var(in, out, out) is det.
:- pred create_univ_var(proc_info, var, proc_info).
:- mode create_univ_var(in, out, out) is det.
%
% Some basic manipulation routines for the HLDS.
%
:- pred prepend_goal_to_rev_goal_list(hlds_goal, hlds_goals, hlds_goals).
:- mode prepend_goal_to_rev_goal_list(in, in, out) is det.
:- pred goal_info_add_nonlocal(hlds_goal_info, var, hlds_goal_info).
:- mode goal_info_add_nonlocal(in, in, out) is det.
:- pred goal_info_set_nonlocal_grounded(hlds_goal_info, var, hlds_goal_info).
:- mode goal_info_set_nonlocal_grounded(in, in, out) is det.
:- pred goal_info_set_var_new_inst(hlds_goal_info, var, (inst),
hlds_goal_info).
:- mode goal_info_set_var_new_inst(in, in, in, out) is det.
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
:- implementation.
:- import_module type_util, prog_out, mercury_to_mercury, hlds_out, instmap.
:- import_module string, require, set.
edt_info_init(Module, EDTInfo) :-
module_info_name(Module, ModuleName),
module_info_globals(Module, Globals),
map__init(Map),
module_info_get_predicate_table(Module, PredTable),
StdUtil = unqualified("std_util"),
(
predicate_table_search_pred_m_n_a(PredTable, StdUtil,
"type_to_univ", 2, TypeToUnivPredIds),
TypeToUnivPredIds = [TypeToUnivPredId0 | _]
->
TypeToUnivPredId = TypeToUnivPredId0,
proc_id_to_int(TypeToUnivProcId, 0)
% XXX That should not be hard coded
;
error("edt_info_init: std_util:type_to_univ/2 not found")
),
EDTInfo = edt_info(ModuleName, Globals, Map, [], TypeToUnivPredId,
TypeToUnivProcId, no).
%-----------------------------------------------------------------------------%
% :- type edt_info
% ---> edt_info(
% A module_name, % module name
% B globals, % global compiler options
% C map(pred_proc_id, proc_proof_info),
% % Associates each procedure with details
% % of its alternative versions.
% D list(constructor),
% % The constructors for evaluation_atoms
% % that can be created by this module.
% E pred_id, % type_to_univ/2
% F proc_id, % forward mode of type_to_univ/2.
% G maybe(pred_proc_id)
% % main/2 (if it exists in this module).
% ).
%-----------------------------------------------------------------------------%
%
% Predicates which access the edt_info data structure.
%
edt_info_get_module_name(EDTInfo, A) :-
EDTInfo = edt_info(A, _, _, _, _, _, _).
edt_info_get_globals(EDTInfo, B) :-
EDTInfo = edt_info(_, B, _, _, _, _, _).
edt_info_get_proc_map(EDTInfo, C) :-
EDTInfo = edt_info(_, _, C, _, _, _, _).
edt_info_get_atom_ctors(EDTInfo, D) :-
EDTInfo = edt_info(_, _, _, D, _, _, _).
edt_info_univ_pred_proc_id(EDTInfo, E, F) :-
EDTInfo = edt_info(_, _, _, _, E, F, _).
%
% Predicates which modify the edt_info structure.
%
edt_info_add_atom_ctor(EDTInfo0, AtomCtor, EDTInfo) :-
EDTInfo0 = edt_info(A, B, C, D0, E, F, G),
D = [AtomCtor | D0],
EDTInfo = edt_info(A, B, C, D, E, F, G).
edt_info_add_proc(EDTInfo0, PredProcId, EDTProcInfo, EDTInfo) :-
EDTInfo0 = edt_info(A, B, Map0, D, E, F, G),
map__det_insert(Map0, PredProcId, EDTProcInfo, Map),
EDTInfo = edt_info(A, B, Map, D, E, F, G).
edt_info_set_main_pred_proc_id(EDTInfo0, PredId, ProcId, EDTInfo) :-
EDTInfo0 = edt_info(A, B, C, D, E, F, _),
EDTInfo = edt_info(A, B, C, D, E, F, yes(proc(PredId, ProcId))).
maybe_write_edt_info(no, _, _) -->
[].
maybe_write_edt_info(yes, Module, EDTInfo) -->
{ EDTInfo = edt_info(Name, _Globals, Map, Ctors, _UnivPred,
_UnivProc, _MaybeMain) },
io__write_string("% EDT Info for module "),
prog_out__write_sym_name(Name),
io__write_string(":\n"),
io__write_string("% edt_proc_infos:\n"),
{ map__to_assoc_list(Map, EDTProcInfos) },
list__foldl(write_edt_proc_info(Module), EDTProcInfos),
io__write_string("% Constructors:\n"),
{ varset__init(TypeVars) },
list__foldl(write_atom_constructor(TypeVars), Ctors).
:- pred write_atom_constructor(varset, constructor, io__state, io__state).
:- mode write_atom_constructor(in, in, di, uo) is det.
write_atom_constructor(TypeVars, Ctor) -->
io__write_string("% "),
mercury_output_ctor(Ctor, TypeVars),
io__nl.
edt_proc_info_init(PredId, ProcId, InitialConsId, FinalConsId, AtomDesc,
EDTProcInfo) :-
EDTProcInfo = edt_proc_info(PredId, ProcId, no, InitialConsId,
FinalConsId, AtomDesc).
edt_proc_info_get_wrong_proc(EDTProcInfo, PredId, ProcId) :-
EDTProcInfo = edt_proc_info(PredId, ProcId, _, _, _, _).
edt_proc_info_get_miss_proc(EDTProcInfo, PredId, ProcId) :-
EDTProcInfo = edt_proc_info(_, _, yes(proc(PredId, ProcId)), _, _, _).
edt_proc_info_get_atom_descriptor(EDTProcInfo, AtomDesc) :-
EDTProcInfo = edt_proc_info(_, _, _, _, _, AtomDesc).
edt_proc_info_initial_cons_id(EDTProcInfo, ConsId) :-
EDTProcInfo = edt_proc_info(_, _, _, ConsId, _, _).
edt_proc_info_final_cons_id(EDTProcInfo, ConsId) :-
EDTProcInfo = edt_proc_info(_, _, _, _, ConsId, _).
write_edt_proc_info(Module, PredProcId - EDTProcInfo) -->
{ PredProcId = proc(PredId, ProcId) },
{ EDTProcInfo = edt_proc_info(_, _, _, _, _, AtomDesc) },
{ module_info_pred_info(Module, PredId, PredInfo) },
{ pred_info_arg_types(PredInfo, VarSet, _, _) },
io__write_string("% "),
hlds_out__write_pred_proc_id(Module, PredId, ProcId),
io__write_string(":\n"),
write_atom_descriptor(VarSet, AtomDesc).
%-----------------------------------------------------------------------------%
evaluation_tree_interface_module(unqualified("evaluation_tree")).
evaluation_tree_type_id(SymName - Arity) :-
evaluation_tree_interface_module(Module),
SymName = qualified(Module, "evaluation_tree"),
Arity = 1.
proof_tree_type_id(SymName - Arity) :-
evaluation_tree_interface_module(Module),
SymName = qualified(Module, "proof_tree"),
Arity = 1.
evaluation_atom_type(Module, AtomType) :-
evaluation_atom_type_name(Module, SymName),
construct_type(SymName - 0, [], AtomType).
evaluation_atom_type_name(Module, SymName) :-
SymName = qualified(Module, "atom").
miss_tree_type_id(SymName - Arity) :-
evaluation_tree_interface_module(Module),
SymName = qualified(Module, "miss_tree"),
Arity = 1.
evaluation_tree_ctor_analyse_wrong(cons(SymName, Arity)) :-
Arity = 2,
evaluation_tree_interface_module(LibModule),
SymName = qualified(LibModule, "analyse_wrong").
evaluation_tree_ctor_analyse_miss(cons(SymName, Arity)) :-
Arity = 2,
evaluation_tree_interface_module(LibModule),
SymName = qualified(LibModule, "analyse_miss").
evaluation_tree_ctor_implicit_wrong(cons(SymName, Arity)) :-
Arity = 1,
evaluation_tree_interface_module(LibModule),
SymName = qualified(LibModule, "implicit_wrong").
evaluation_tree_ctor_implicit_miss(cons(SymName, Arity)) :-
Arity = 1,
evaluation_tree_interface_module(LibModule),
SymName = qualified(LibModule, "implicit_miss").
evaluation_tree_ctor_interface_wrong(cons(SymName, Arity)) :-
Arity = 1,
evaluation_tree_interface_module(LibModule),
SymName = qualified(LibModule, "interface_wrong").
evaluation_tree_ctor_interface_miss(cons(SymName, Arity)) :-
Arity = 1,
evaluation_tree_interface_module(LibModule),
SymName = qualified(LibModule, "interface_miss").
evaluation_tree_ctor_assumed(cons(SymName, Arity)) :-
Arity = 0,
evaluation_tree_interface_module(LibModule),
SymName = qualified(LibModule, "assumed").
proof_tree_ctor_local_call(cons(SymName, Arity)) :-
Arity = 1,
evaluation_tree_interface_module(LibModule),
SymName = qualified(LibModule, "local_call").
proof_tree_ctor_conj(cons(SymName, Arity)) :-
Arity = 1,
evaluation_tree_interface_module(LibModule),
SymName = qualified(LibModule, "conj").
proof_tree_ctor_switch(cons(SymName, Arity)) :-
Arity = 2,
evaluation_tree_interface_module(LibModule),
SymName = qualified(LibModule, "switch").
proof_tree_ctor_disj(cons(SymName, Arity)) :-
Arity = 2,
evaluation_tree_interface_module(LibModule),
SymName = qualified(LibModule, "disj").
proof_tree_ctor_not(cons(SymName, Arity)) :-
Arity = 1,
evaluation_tree_interface_module(LibModule),
SymName = qualified(LibModule, "not").
proof_tree_ctor_if_then(cons(SymName, Arity)) :-
Arity = 2,
evaluation_tree_interface_module(LibModule),
SymName = qualified(LibModule, "if_then").
proof_tree_ctor_else(cons(SymName, Arity)) :-
Arity = 2,
evaluation_tree_interface_module(LibModule),
SymName = qualified(LibModule, "else").
proof_tree_ctor_trivial(cons(SymName, Arity)) :-
Arity = 0,
evaluation_tree_interface_module(LibModule),
SymName = qualified(LibModule, "trivial").
miss_tree_ctor_local_call(cons(SymName, Arity)) :-
Arity = 1,
evaluation_tree_interface_module(LibModule),
SymName = qualified(LibModule, "local_call").
miss_tree_ctor_conj(cons(SymName, Arity)) :-
Arity = 1,
evaluation_tree_interface_module(LibModule),
SymName = qualified(LibModule, "conj").
miss_tree_ctor_switch(cons(SymName, Arity)) :-
Arity = 2,
evaluation_tree_interface_module(LibModule),
SymName = qualified(LibModule, "switch").
miss_tree_ctor_disj(cons(SymName, Arity)) :-
Arity = 2,
evaluation_tree_interface_module(LibModule),
SymName = qualified(LibModule, "disj").
miss_tree_ctor_not(cons(SymName, Arity)) :-
Arity = 1,
evaluation_tree_interface_module(LibModule),
SymName = qualified(LibModule, "not").
miss_tree_ctor_if_then(cons(SymName, Arity)) :-
Arity = 2,
evaluation_tree_interface_module(LibModule),
SymName = qualified(LibModule, "if_then").
miss_tree_ctor_else(cons(SymName, Arity)) :-
Arity = 2,
evaluation_tree_interface_module(LibModule),
SymName = qualified(LibModule, "else").
miss_tree_ctor_trivial(cons(SymName, Arity)) :-
Arity = 0,
evaluation_tree_interface_module(LibModule),
SymName = qualified(LibModule, "trivial").
analysis_ctor_nondet_wrong(cons(SymName, Arity)) :-
Arity = 1,
evaluation_tree_interface_module(LibModule),
SymName = qualified(LibModule, "nondet_wrong").
analysis_ctor_unavailable(cons(SymName, Arity)) :-
Arity = 0,
evaluation_tree_interface_module(LibModule),
SymName = qualified(LibModule, "unavailable").
library_type_univ(UnivType) :-
StdUtil = unqualified("std_util"),
UnivTypeId = qualified(StdUtil, "univ") - 0,
construct_type(UnivTypeId, [], UnivType).
library_ctor_list_cons(cons(SymName, Arity)) :-
Arity = 2,
Module = unqualified("list"),
SymName = qualified(Module, ".").
library_ctor_list_nil(cons(SymName, Arity)) :-
Arity = 0,
Module = unqualified("list"),
SymName = qualified(Module, "[]").
%-----------------------------------------------------------------------------%
write_atom_descriptor(VarSet, AtomDesc) -->
io__write_string("% "),
(
{ AtomDesc = [Arg | Args] }
->
io__write_char('['),
write_atom_argument(VarSet, Arg),
write_atom_arguments(VarSet, Args),
io__write_string("]\n")
;
io__write_string("[]\n")
).
:- pred write_atom_arguments(varset, list(atom_arg_descriptor), io__state,
io__state).
:- mode write_atom_arguments(in, in, di, uo) is det.
write_atom_arguments(_, []) -->
[].
write_atom_arguments(VarSet, [Arg | Args]) -->
io__write_string(", "),
write_atom_argument(VarSet, Arg),
write_atom_arguments(VarSet, Args).
:- pred write_atom_argument(varset, atom_arg_descriptor, io__state, io__state).
:- mode write_atom_argument(in, in, di, uo) is det.
write_atom_argument(VarSet, direct_var(_Pos, _Var, Type)) -->
io__write_string("direct("),
mercury_output_term(Type, VarSet, no),
io__write_char(')').
write_atom_argument(VarSet, univ_var(_Pos, _Var, Type)) -->
io__write_string("univ("),
mercury_output_term(Type, VarSet, no),
io__write_char(')').
write_atom_argument(_VarSet, io_state_di(_, _)) -->
io__write_string("io_di").
write_atom_argument(_VarSet, io_state_uo(_, _)) -->
io__write_string("io_uo").
%-----------------------------------------------------------------------------%
edt_info_proc_analysis(EDTInfo, PredId, ProcId, Analysis) :-
edt_info_get_proc_map(EDTInfo, ProcMap),
(
map__search(ProcMap, proc(PredId, ProcId), EDTProcInfo)
->
edt_proc_info_get_wrong_proc(EDTProcInfo, WrongPredId,
WrongProcId),
(
edt_proc_info_get_miss_proc(EDTProcInfo, MissPredId,
MissProcId)
->
Analysis = full_analysis(WrongPredId, WrongProcId,
MissPredId, MissProcId)
;
Analysis = wrong_answer_analysis(WrongPredId,
WrongProcId)
)
;
Analysis = no_analysis
).
%-----------------------------------------------------------------------------%
%
% For the moment, this will be a very simple transformation.
%
wrong_answer_name_mangle(Name0, Name) :-
string__append(Name0, "_wrong", Name).
wrong_answer_sym_name_mangle(SymName0, SymName) :-
(
SymName0 = unqualified(Name0),
wrong_answer_name_mangle(Name0, Name),
SymName = unqualified(Name)
;
SymName0 = qualified(Module, Name0),
wrong_answer_name_mangle(Name0, Name),
SymName = qualified(Module, Name)
).
wrong_analysis_pred_sym_name(ModuleName, SymName) :-
SymName = qualified(ModuleName, "atom_to_wrong_analysis").
local_evaluation_tree_type(Module, TreeType) :-
local_evaluation_atom_type(Module, AtomType),
evaluation_tree_type_id(TypeId),
construct_type(TypeId, [AtomType], TreeType).
local_evaluation_atom_type(Module, AtomType) :-
local_evaluation_atom_sym_name(Module, SymName),
construct_type(SymName - 0, [], AtomType).
local_evaluation_atom_sym_name(ModuleName, SymName) :-
SymName = qualified(ModuleName, "evaluation_atom").
local_analysis_type(Module, AnalysisType) :-
local_evaluation_atom_type(Module, AtomType),
evaluation_tree_interface_module(LibModule),
SymName = qualified(LibModule, "analysis"),
construct_type(SymName - 1, [AtomType], AnalysisType).
local_analysis_inst(AnalysisInst) :-
evaluation_tree_interface_module(LibModule),
SymName = qualified(LibModule, "analysis"),
InstName = user_inst(SymName, []),
AnalysisInst = defined_inst(InstName).
generated_code_context(Context) :-
term__context_init(Context).
dummy_type_id(unqualified("") - 0).
ground_inst(ground(shared, no)).
%-----------------------------------------------------------------------------%
edt_info_evaluation_tree_type(EDTInfo, Type) :-
evaluation_tree_type_id(EDTTypeId),
edt_info_evaluation_atom_type(EDTInfo, AtomType),
construct_type(EDTTypeId, [AtomType], Type).
edt_info_proof_tree_type(EDTInfo, Type) :-
proof_tree_type_id(ProofTreeTypeId),
edt_info_evaluation_atom_type(EDTInfo, AtomType),
construct_type(ProofTreeTypeId, [AtomType], Type).
edt_info_miss_tree_type(EDTInfo, Type) :-
miss_tree_type_id(MissTreeTypeId),
edt_info_evaluation_atom_type(EDTInfo, AtomType),
construct_type(MissTreeTypeId, [AtomType], Type).
edt_info_evaluation_atom_type(EDTInfo, Type) :-
edt_info_get_module_name(EDTInfo, Module),
local_evaluation_atom_type(Module, Type).
edt_info_analysis_type(EDTInfo, Type) :-
edt_info_get_module_name(EDTInfo, Module),
local_analysis_type(Module, Type).
%-----------------------------------------------------------------------------%
make_final_atom_construction(EDTInfo, EDTProcInfo, ProcInfo0, ProcInfo,
AtomVar, Goals) :-
edt_proc_info_get_atom_descriptor(EDTProcInfo, AtomDesc),
make_atom_cons_args(EDTInfo, AtomDesc, ArgVars, ProcInfo0, ProcInfo1,
[], Goals0),
create_evaluation_atom_var(EDTInfo, ProcInfo1, ProcInfo, AtomVar),
edt_proc_info_final_cons_id(EDTProcInfo, ConsId),
make_simple_construction(AtomVar, ConsId, ArgVars, ExtraGoal),
list__append(Goals0, [ExtraGoal], Goals).
:- pred make_atom_cons_args(edt_info, atom_descriptor, list(var), proc_info,
proc_info, hlds_goals, hlds_goals).
:- mode make_atom_cons_args(in, in, out, in, out, in, out) is det.
make_atom_cons_args(_EDTInfo, [], [], ProcInfo, ProcInfo, Goals, Goals).
make_atom_cons_args(EDTInfo, [AtomArg | AtomArgs], ArgVars, ProcInfo0,
ProcInfo, Goals0, Goals) :-
make_atom_cons_arg(EDTInfo, AtomArg, MaybeArgVar, ProcInfo0, ProcInfo1,
Goals0, Goals1),
make_atom_cons_args(EDTInfo, AtomArgs, ArgVars0, ProcInfo1, ProcInfo,
Goals1, Goals),
(
MaybeArgVar = yes(ArgVar)
->
ArgVars = [ArgVar | ArgVars0]
;
ArgVars = ArgVars0
).
:- pred make_atom_cons_arg(edt_info, atom_arg_descriptor, maybe(var),
proc_info, proc_info, hlds_goals, hlds_goals).
:- mode make_atom_cons_arg(in, in, out, in, out, in, out) is det.
make_atom_cons_arg(_EDTInfo, direct_var(_, Var, _), yes(Var), Proc, Proc,
Goals, Goals).
make_atom_cons_arg(EDTInfo, univ_var(_, Var, _), yes(UnivVar), Proc0, Proc,
Goals0, Goals) :-
create_univ_var(Proc0, UnivVar, Proc),
make_to_univ_call(EDTInfo, Var, UnivVar, Goal),
Goals = [Goal | Goals0].
make_atom_cons_arg(_EDTInfo, io_state_di(_, _), no, Proc, Proc, Goals, Goals).
make_atom_cons_arg(_EDTInfo, io_state_uo(_, _), no, Proc, Proc, Goals, Goals).
make_evaluation_atom_type_defn(EDTInfo, TVarSet, TypeDefn) :-
edt_info_get_atom_ctors(EDTInfo, Ctors),
edt_info_get_module_name(EDTInfo, Module),
local_evaluation_atom_sym_name(Module, SymName),
TypeDefn = du_type(SymName, [], Ctors, no),
varset__init(TVarSet).
make_simple_construction(LVar, ConsId, Args, Goal) :-
Ground = ground(shared, no),
UnifyRHS = functor(ConsId, Args),
UnifyMode = ((free -> Ground) - (Ground -> Ground)),
UniMode = ((free - Ground) -> (Ground - Ground)),
list__length(Args, Arity),
list__duplicate(Arity, UniMode, UniModes),
Unification = construct(LVar, ConsId, Args, UniModes),
Context = unify_context(explicit, []),
GoalExpr = unify(LVar, UnifyRHS, UnifyMode, Unification, Context),
set__list_to_set([LVar | Args], NonLocals),
instmap_delta_from_assoc_list([LVar - Ground], InstMapDelta),
Detism = det,
goal_info_init(NonLocals, InstMapDelta, Detism, GoalInfo),
Goal = GoalExpr - GoalInfo.
make_simple_deconstruction(LVar, ConsId, Args, Goal) :-
Ground = ground(shared, no),
UnifyRHS = functor(ConsId, Args),
UnifyMode = ((Ground -> Ground) - (free -> Ground)),
UniMode = ((Ground - free) -> (Ground - Ground)),
list__length(Args, Arity),
list__duplicate(Arity, UniMode, UniModes),
Unification = deconstruct(LVar, ConsId, Args, UniModes, cannot_fail),
Context = unify_context(explicit, []),
GoalExpr = unify(LVar, UnifyRHS, UnifyMode, Unification, Context),
set__list_to_set([LVar | Args], NonLocals),
Map = lambda([Var::in, VarInst::out] is det,
(VarInst = Var - Ground)
),
list__map(Map, Args, InstMapAssocList),
instmap_delta_from_assoc_list(InstMapAssocList, InstMapDelta),
Detism = det,
goal_info_init(NonLocals, InstMapDelta, Detism, GoalInfo),
Goal = GoalExpr - GoalInfo.
make_closure_construction(LVar, SymName, PredId, ProcId, LambdaVar, ArgVars,
Detism, GoalExpr) :-
ground_inst(Ground),
list__append(ArgVars, [LambdaVar], CallArgs),
LambdaGoalExpr = call(PredId, ProcId, CallArgs, not_builtin, no,
SymName),
set__list_to_set(CallArgs, NonLocals),
instmap_delta_from_assoc_list([LambdaVar - Ground], InstMapDelta),
goal_info_init(NonLocals, InstMapDelta, Detism, LambdaGoalInfo),
LambdaGoal = LambdaGoalExpr - LambdaGoalInfo,
UnifyRHS = lambda_goal(predicate, ArgVars, [LambdaVar],
[(free -> Ground)], nondet, LambdaGoal),
UnifyMode = ((free -> Ground) - (Ground -> Ground)),
UniMode = ((Ground - Ground) -> (Ground - Ground)),
list__length(ArgVars, Arity),
list__duplicate(Arity, UniMode, UniModes),
ConsId = pred_const(PredId, ProcId),
Unification = construct(LVar, ConsId, ArgVars, UniModes),
Context = unify_context(explicit, []),
GoalExpr = unify(LVar, UnifyRHS, UnifyMode, Unification, Context).
make_to_univ_call(EDTInfo, LVar, RVar, Goal) :-
proc_id_to_int(ProcId, 1),
make_univ_call(EDTInfo, ProcId, LVar, RVar, RVar, Goal).
make_from_univ_call(EDTInfo, LVar, RVar, Goal) :-
proc_id_to_int(ProcId, 2),
make_univ_call(EDTInfo, ProcId, LVar, RVar, LVar, Goal).
:- pred make_univ_call(edt_info, proc_id, var, var, var, hlds_goal).
:- mode make_univ_call(in, in, in, in, in, out) is det.
make_univ_call(EDTInfo, ProcId, Var, UnivVar, BoundVar, GoalExpr - GoalInfo) :-
edt_info_univ_pred_proc_id(EDTInfo, PredId, _),
Args = [Var, UnivVar],
BuiltinState = not_builtin,
SymName = unqualified("type_to_univ"),
GoalExpr = call(PredId, ProcId, Args, BuiltinState, no, SymName),
set__list_to_set(Args, NonLocals),
Ground = ground(shared, no),
instmap_delta_from_assoc_list([BoundVar - Ground], InstMapDelta),
Detism = det,
goal_info_init(NonLocals, InstMapDelta, Detism, GoalInfo).
create_evaluation_tree_head_var(EDTInfo, ProcInfo0, ProcInfo, GoalInfo0,
GoalInfo, EDTVar) :-
create_evaluation_tree_var(EDTInfo, ProcInfo0, ProcInfo1, GoalInfo0,
GoalInfo1, EDTVar),
goal_info_add_nonlocal(GoalInfo1, EDTVar, GoalInfo),
proc_info_headvars(ProcInfo1, HeadVars0),
proc_info_argmodes(ProcInfo1, ArgModes0),
proc_info_varset(ProcInfo1, VarSet0),
list__append(HeadVars0, [EDTVar], HeadVars),
ground_inst(Ground),
EDTMode = (free -> Ground),
list__append(ArgModes0, [EDTMode], ArgModes),
varset__name_var(VarSet0, EDTVar, "HeadEDT", VarSet),
proc_info_set_headvars(ProcInfo1, HeadVars, ProcInfo2),
proc_info_set_argmodes(ProcInfo2, ArgModes, ProcInfo3),
proc_info_set_varset(ProcInfo3, VarSet, ProcInfo).
create_evaluation_tree_var(EDTInfo, ProcInfo0, ProcInfo, GoalInfo0, GoalInfo,
EDTVar) :-
edt_info_evaluation_tree_type(EDTInfo, EDTType),
create_new_variable(EDTType, "EDT", ProcInfo0, ProcInfo, GoalInfo0,
GoalInfo, EDTVar).
create_evaluation_atom_var(EDTInfo, ProcInfo0, ProcInfo, AtomVar) :-
edt_info_evaluation_atom_type(EDTInfo, AtomType),
proc_info_create_var_from_type(ProcInfo0, AtomType, AtomVar,
ProcInfo1),
proc_info_varset(ProcInfo1, VarSet0),
varset__name_var(VarSet0, AtomVar, "Atom", VarSet),
proc_info_set_varset(ProcInfo1, VarSet, ProcInfo).
create_proof_tree_var(EDTInfo, ProcInfo0, ProcInfo, GoalInfo0, GoalInfo,
ProofVar) :-
edt_info_proof_tree_type(EDTInfo, ProofType),
create_new_variable(ProofType, "Proof", ProcInfo0, ProcInfo,
GoalInfo0, GoalInfo, ProofVar).
create_miss_tree_var(EDTInfo, ProcInfo0, ProcInfo, GoalInfo0, GoalInfo,
MissTreeVar) :-
edt_info_miss_tree_type(EDTInfo, MissTreeType),
create_new_variable(MissTreeType, "MissTree", ProcInfo0, ProcInfo,
GoalInfo0, GoalInfo, MissTreeVar).
create_proof_tree_list_var(EDTInfo, ProcInfo0, ProcInfo, ProofListVar) :-
edt_info_proof_tree_type(EDTInfo, ProofType),
ListSymName = qualified(unqualified("list"), "list"),
ListArity = 1,
ListTypeId = ListSymName - ListArity,
construct_type(ListTypeId, [ProofType], ProofListType),
proc_info_create_var_from_type(ProcInfo0, ProofListType, ProofListVar,
ProcInfo1),
proc_info_varset(ProcInfo1, VarSet0),
varset__name_var(VarSet0, ProofListVar, "Proofs", VarSet),
proc_info_set_varset(ProcInfo1, VarSet, ProcInfo).
create_closure_var(EDTInfo, ProcInfo0, ProcInfo, ClosureVar) :-
edt_info_evaluation_tree_type(EDTInfo, EDTType),
generated_code_context(Context),
ClosureType = term__functor(term__atom("pred"), [EDTType], Context),
proc_info_create_var_from_type(ProcInfo0, ClosureType, ClosureVar,
ProcInfo).
:- pred create_new_variable((type), string, proc_info, proc_info,
hlds_goal_info, hlds_goal_info, var).
:- mode create_new_variable(in, in, in, out, in, out, out) is det.
create_new_variable(VarType, VarName, ProcInfo0, ProcInfo, GoalInfo0, GoalInfo,
NewVar) :-
proc_info_create_var_from_type(ProcInfo0, VarType, NewVar, ProcInfo1),
proc_info_varset(ProcInfo1, VarSet0),
varset__name_var(VarSet0, NewVar, VarName, VarSet),
proc_info_set_varset(ProcInfo1, VarSet, ProcInfo),
goal_info_set_nonlocal_grounded(GoalInfo0, NewVar, GoalInfo).
create_int_var(ProcInfo0, IntVar, ProcInfo) :-
IntTypeId = qualified(unqualified("mercury_builtin"), "int") - 0,
construct_type(IntTypeId, [], IntType),
proc_info_create_var_from_type(ProcInfo0, IntType, IntVar, ProcInfo1),
proc_info_varset(ProcInfo1, VarSet0),
varset__name_var(VarSet0, IntVar, "ArmId", VarSet),
proc_info_set_varset(ProcInfo1, VarSet, ProcInfo).
create_univ_var(ProcInfo0, UnivVar, ProcInfo) :-
UnivTypeId = qualified(unqualified("std_util"), "univ") - 0,
construct_type(UnivTypeId, [], UnivType),
proc_info_create_var_from_type(ProcInfo0, UnivType, UnivVar,
ProcInfo1),
proc_info_varset(ProcInfo1, VarSet0),
varset__name_var(VarSet0, UnivVar, "Univ", VarSet),
proc_info_set_varset(ProcInfo1, VarSet, ProcInfo).
prepend_goal_to_rev_goal_list(Goal0, Goals0, Goals) :-
(
Goal0 = conj(SubGoals) - _
->
list__reverse(SubGoals, RevSubGoals),
list__append(RevSubGoals, Goals0, Goals)
;
Goals = [Goal0 | Goals0]
).
goal_info_add_nonlocal(GoalInfo0, NewVar, GoalInfo) :-
goal_info_get_nonlocals(GoalInfo0, NonLocals0),
set__insert(NonLocals0, NewVar, NonLocals),
goal_info_set_nonlocals(GoalInfo0, NonLocals, GoalInfo).
goal_info_set_nonlocal_grounded(GoalInfo0, NewVar, GoalInfo) :-
goal_info_add_nonlocal(GoalInfo0, NewVar, GoalInfo1),
ground_inst(NewInst),
goal_info_set_var_new_inst(GoalInfo1, NewVar, NewInst, GoalInfo).
goal_info_set_var_new_inst(GoalInfo0, Var, NewInst, GoalInfo) :-
goal_info_get_instmap_delta(GoalInfo0, InstMapDelta0),
instmap_delta_insert(InstMapDelta0, Var, NewInst, InstMapDelta),
goal_info_set_instmap_delta(GoalInfo0, InstMapDelta, GoalInfo).
:- end_module evaluation_tree_util.
More information about the developers
mailing list