%-----------------------------------------------------------------------------% % vim: ft=mercury ts=4 sw=4 et %-----------------------------------------------------------------------------% % Copyright (C) 1996-2006 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: hlds_module.m. % Main authors: fjh, conway. % This module defines the part of the High Level Data Structure or HLDS % that deals with issues that are wider than a single predicate. % The main data structures defined here are the types % % module_info % dependency_info % predicate_table % % There is a separate interface section for each of these. %-----------------------------------------------------------------------------% :- module hlds.hlds_module. :- interface. :- import_module analysis. :- import_module check_hlds.unify_proc. :- import_module hlds.hlds_data. :- import_module hlds.hlds_pred. :- import_module hlds.pred_table. :- import_module hlds.special_pred. :- import_module libs.globals. :- import_module mdbcomp.prim_data. :- import_module parse_tree.module_qual. :- import_module parse_tree.prog_data. :- import_module parse_tree.prog_foreign. :- import_module parse_tree.prog_item. :- import_module recompilation. :- import_module list. :- import_module map. :- import_module maybe. :- import_module multi_map. :- import_module pair. :- import_module relation. :- import_module set. :- implementation. :- import_module hlds.hlds_out. :- import_module transform_hlds.mmc_analysis. :- import_module parse_tree.modules. :- import_module parse_tree.prog_out. :- import_module parse_tree.prog_type. :- import_module parse_tree.prog_util. :- import_module bool. :- import_module int. :- import_module string. :- import_module svmap. :- import_module svmulti_map. %-----------------------------------------------------------------------------% :- interface. :- type module_info. :- type foreign_code_info ---> foreign_code_info( foreign_decl_info, foreign_body_info ). :- type pragma_exported_proc ---> pragma_exported_proc( pred_id, proc_id, string, % the name of the C function prog_context ). % This structure contains the information we need to generate % a type_ctor_info structure for a type defined in this module. :- type type_ctor_gen_info ---> type_ctor_gen_info( type_ctor, module_name, % module name string, % type name int, % type arity import_status, % of the type hlds_type_defn, % defn of type pred_proc_id, % unify procedure pred_proc_id % compare procedure % maybe(pred_proc_id) % prettyprinter, if relevant ). % Map from proc to a list of unused argument numbers. % :- type unused_arg_info == map(pred_proc_id, list(int)). % Map from proc to an indication of whether or not it might throw an % exception. % :- type exception_info == map(pred_proc_id, proc_exception_info). :- type proc_exception_info ---> proc_exception_info( proc_exception_status :: exception_status, proc_maybe_excep_analysis_status :: maybe(analysis_status) ). % Map from proc to an indication of whether or not it modifies the trail. % :- type trailing_info == map(pred_proc_id, proc_trailing_info). :- type proc_trailing_info ---> proc_trailing_info( proc_trailing_status :: trailing_status, proc_maybe_trail_analysis_status :: maybe(analysis_status) ). % List of procedures for which there are user-requested type % specializations, and a list of predicates which should be % processed by higher_order.m to ensure the production of those % versions. :- type type_spec_info ---> type_spec_info( user_req_procs :: set(pred_proc_id), % Procedures for which there are % user-requested type specializations. must_process_preds :: set(pred_id), % Set of predicates which need to be % processed by higher_order.m to % produce those specialized versions. user_to_process_map :: multi_map(pred_id, pred_id), % Map from predicates for which the % user requested a type specialization % to the list of predicates which must % be processed by higher_order.m to % force the production of those % versions. This is used by % dead_proc_elim.m to avoid creating % versions unnecessarily for versions % in imported modules. pragma_map :: multi_map(pred_id, pragma_type) % Type spec pragmas to be placed in % the `.opt' file if a predicate % becomes exported. ). % Maps the full names of procedures (in the sense of % complexity_proc_name in complexity.m) to the number of their slot % in MR_complexity_proc_table. :- type complexity_proc_map == map(string, int). :- type complexity_proc_info ---> complexity_proc_info( complexity_proc_num :: int, % The index of the procedure in the runtime % system's MR_complexity_procs array. complexity_proc_name :: string, % The full name of the procedure, in the form % fqn/arity-modenum, where fqn is the predicate or % function's fully qualified name. complexity_proc_args :: list(complexity_arg_info) ). :- type complexity_arg_info ---> complexity_arg_info( complexity_arg_name :: maybe(string), complexity_arg_kind :: complexity_arg_kind ). :- type complexity_arg_kind ---> complexity_input_variable_size ; complexity_input_fixed_size ; complexity_output. %-----------------------------------------------------------------------------% % % Various predicates for manipulating the module_info data structure % % Create an empty module_info for a given module name (and the % global options). The item_list is passed so that we can % call get_implicit_dependencies to figure out whether to % import `table_builtin', but the items are not inserted into % the module_info. % :- pred module_info_init(module_name::in, item_list::in, globals::in, partial_qualifier_info::in, maybe(recompilation_info)::in, module_info::out) is det. :- pred module_info_get_predicate_table(module_info::in, predicate_table::out) is det. :- pred module_info_set_predicate_table(predicate_table::in, module_info::in, module_info::out) is det. % For an explanation of the proc_requests structure, see unify_proc.m. % :- pred module_info_get_proc_requests(module_info::in, proc_requests::out) is det. :- pred module_info_get_special_pred_map(module_info::in, special_pred_map::out) is det. :- pred module_info_set_special_pred_map(special_pred_map::in, module_info::in, module_info::out) is det. :- pred module_info_get_partial_qualifier_info(module_info::in, partial_qualifier_info::out) is det. :- pred module_info_set_partial_qualifier_info(partial_qualifier_info::in, module_info::in, module_info::out) is det. :- pred module_info_get_type_table(module_info::in, type_table::out) is det. :- pred module_info_set_type_table(type_table::in, module_info::in, module_info::out) is det. :- pred module_info_get_inst_table(module_info::in, inst_table::out) is det. :- pred module_info_set_inst_table(inst_table::in, module_info::in, module_info::out) is det. :- pred module_info_get_mode_table(module_info::in, mode_table::out) is det. :- pred module_info_set_mode_table(mode_table::in, module_info::in, module_info::out) is det. :- pred module_info_get_cons_table(module_info::in, cons_table::out) is det. :- pred module_info_set_cons_table(cons_table::in, module_info::in, module_info::out) is det. :- pred module_info_get_class_table(module_info::in, class_table::out) is det. :- pred module_info_set_class_table(class_table::in, module_info::in, module_info::out) is det. :- pred module_info_get_instance_table(module_info::in, instance_table::out) is det. :- pred module_info_set_instance_table(instance_table::in, module_info::in, module_info::out) is det. :- pred module_info_get_superclass_table(module_info::in, superclass_table::out) is det. :- pred module_info_set_superclass_table(superclass_table::in, module_info::in, module_info::out) is det. :- pred module_info_get_assertion_table(module_info::in, assertion_table::out) is det. :- pred module_info_set_assertion_table(assertion_table::in, module_info::in, module_info::out) is det. :- pred module_info_get_exclusive_table(module_info::in, exclusive_table::out) is det. :- pred module_info_set_exclusive_table(exclusive_table::in, module_info::in, module_info::out) is det. :- pred module_info_get_ctor_field_table(module_info::in, ctor_field_table::out) is det. :- pred module_info_set_ctor_field_table(ctor_field_table::in, module_info::in, module_info::out) is det. :- pred module_info_get_maybe_recompilation_info(module_info::in, maybe(recompilation_info)::out) is det. :- pred module_info_set_maybe_recompilation_info(maybe(recompilation_info)::in, module_info::in, module_info::out) is det. :- pred module_add_imported_module_specifiers(list(module_specifier)::in, module_info::in, module_info::out) is det. :- pred module_info_get_imported_module_specifiers(module_info::in, set(module_specifier)::out) is det. :- pred module_add_indirectly_imported_module_specifiers( list(module_specifier)::in, module_info::in, module_info::out) is det. :- pred module_info_get_indirectly_imported_module_specifiers(module_info::in, set(module_specifier)::out) is det. % The visible modules are the current module, any imported modules, % any ancestor modules and any modules imported by ancestor modules. % It excludes transitively imported modules (those for which we read % `.int2' files). :- pred visible_module(module_name::out, module_info::in) is multi. % This returns all the modules that this module's code depends on, % i.e. all modules that have been used or imported by this module, % directly or indirectly, including parent modules. % :- pred module_info_get_all_deps(module_info::in, set(module_name)::out) is det. %-----------------------------------------------------------------------------% :- pred module_info_get_name(module_info::in, module_name::out) is det. :- pred module_info_get_globals(module_info::in, globals::out) is det. :- pred module_info_set_globals(globals::in, module_info::in, module_info::out) is det. :- pred module_info_contains_foreign_type(module_info::in) is semidet. :- pred module_info_contains_foreign_type(module_info::in, module_info::out) is det. :- pred module_info_get_foreign_decl(module_info::in, foreign_decl_info::out) is det. :- pred module_info_set_foreign_decl(foreign_decl_info::in, module_info::in, module_info::out) is det. :- pred module_info_get_foreign_body_code(module_info::in, foreign_body_info::out) is det. :- pred module_info_set_foreign_body_code(foreign_body_info::in, module_info::in, module_info::out) is det. :- pred module_info_get_foreign_import_module(module_info::in, foreign_import_module_info::out) is det. :- pred module_info_set_foreign_import_module(foreign_import_module_info::in, module_info::in, module_info::out) is det. :- pred module_add_foreign_decl(foreign_language::in, foreign_decl_is_local::in, string::in, prog_context::in, module_info::in, module_info::out) is det. :- pred module_add_foreign_body_code(foreign_language::in, string::in, prog_context::in, module_info::in, module_info::out) is det. :- pred module_add_foreign_import_module(foreign_language::in, module_name::in, prog_context::in, module_info::in, module_info::out) is det. :- pred module_get_fact_table_files(module_info::in, list(string)::out) is det. :- pred module_add_fact_table_file(string::in, module_info::in, module_info::out) is det. % Please see module_info_ensure_dependency_info for the constraints % on this dependency_info. % :- pred module_info_get_maybe_dependency_info(module_info::in, maybe(dependency_info)::out) is det. :- pred module_info_get_num_errors(module_info::in, int::out) is det. :- pred module_info_get_unused_arg_info(module_info::in, unused_arg_info::out) is det. :- pred module_info_get_exception_info(module_info::in, exception_info::out) is det. :- pred module_info_get_trailing_info(module_info::in, trailing_info::out) is det. :- pred module_info_set_proc_requests(proc_requests::in, module_info::in, module_info::out) is det. :- pred module_info_set_unused_arg_info(unused_arg_info::in, module_info::in, module_info::out) is det. :- pred module_info_set_exception_info(exception_info::in, module_info::in, module_info::out) is det. :- pred module_info_set_trailing_info(trailing_info::in, module_info::in, module_info::out) is det. :- pred module_info_set_num_errors(int::in, module_info::in, module_info::out) is det. :- pred module_info_get_pragma_exported_procs(module_info::in, list(pragma_exported_proc)::out) is det. :- pred module_info_set_pragma_exported_procs(list(pragma_exported_proc)::in, module_info::in, module_info::out) is det. :- pred module_info_get_type_ctor_gen_infos(module_info::in, list(type_ctor_gen_info)::out) is det. :- pred module_info_set_type_ctor_gen_infos(list(type_ctor_gen_info)::in, module_info::in, module_info::out) is det. :- pred module_info_get_stratified_preds(module_info::in, set(pred_id)::out) is det. :- pred module_info_set_stratified_preds(set(pred_id)::in, module_info::in, module_info::out) is det. :- pred module_info_get_type_spec_info(module_info::in, type_spec_info::out) is det. :- pred module_info_set_type_spec_info(type_spec_info::in, module_info::in, module_info::out) is det. :- pred module_info_get_no_tag_types(module_info::in, no_tag_type_table::out) is det. :- pred module_info_set_no_tag_types(no_tag_type_table::in, module_info::in, module_info::out) is det. :- pred module_info_get_analysis_info(module_info::in, analysis_info::out) is det. :- pred module_info_set_analysis_info(analysis_info::in, module_info::in, module_info::out) is det. :- pred module_info_get_maybe_complexity_proc_map(module_info::in, maybe(pair(int, complexity_proc_map))::out) is det. :- pred module_info_set_maybe_complexity_proc_map( maybe(pair(int, complexity_proc_map))::in, module_info::in, module_info::out) is det. :- pred module_info_get_complexity_proc_infos(module_info::in, list(complexity_proc_info)::out) is det. :- pred module_info_set_complexity_proc_infos(list(complexity_proc_info)::in, module_info::in, module_info::out) is det. :- pred module_info_new_user_init_pred(sym_name::in, string::out, module_info::in, module_info::out) is det. :- pred module_info_user_init_pred_c_name(module_info::in, sym_name::in, string::out) is det. :- pred module_info_user_init_pred_c_names(module_info::in, list(string)::out) is det. :- pred module_info_new_user_final_pred(sym_name::in, string::out, module_info::in, module_info::out) is det. :- pred module_info_user_final_pred_c_name(module_info::in, sym_name::in, string::out) is det. :- pred module_info_user_final_pred_c_names(module_info::in, list(string)::out) is det. %-----------------------------------------------------------------------------% :- pred module_info_preds(module_info::in, pred_table::out) is det. % Given a pred_id, return the pred_info of the specified pred. % :- pred module_info_pred_info(module_info::in, pred_id::in, pred_info::out) is det. % Given a pred_proc_id, return the proc_info of the specified procedure. % :- pred module_info_proc_info(module_info::in, pred_proc_id::in, proc_info::out) is det. :- pred module_info_proc_info(module_info::in, pred_id::in, proc_id::in, proc_info::out) is det. % Given a pred_id and a proc_id, get the pred_info of that predicate % and the proc_info for that mode of that predicate. % :- pred module_info_pred_proc_info(module_info::in, pred_id::in, proc_id::in, pred_info::out, proc_info::out) is det. :- pred module_info_pred_proc_info(module_info::in, pred_proc_id::in, pred_info::out, proc_info::out) is det. % Return a list of the pred_ids of all the "valid" predicates. % (Predicates whose definition contains a type error, etc. % get removed from this list, so that later passes can rely % on the predicates in this list being type-correct, etc.) % :- pred module_info_predids(module_info::in, list(pred_id)::out) is det. % Reverse the list of pred_ids. % (The list is built up by inserting values at the front, % for efficiency; once we've done so, we reverse the list % so that progress messages and error messages come out % in the expected order.) % :- pred module_info_reverse_predids(module_info::in, module_info::out) is det. % Remove a predicate from the list of pred_ids, to prevent % further processing of this predicate after an error is encountered. % :- pred module_info_remove_predid(pred_id::in, module_info::in, module_info::out) is det. % Completely remove a predicate from a module. % :- pred module_info_remove_predicate(pred_id::in, module_info::in, module_info::out) is det. :- pred module_info_set_preds(pred_table::in, module_info::in, module_info::out) is det. :- pred module_info_set_pred_info(pred_id::in, pred_info::in, module_info::in, module_info::out) is det. :- pred module_info_set_pred_proc_info(pred_id::in, proc_id::in, pred_info::in, proc_info::in, module_info::in, module_info::out) is det. :- pred module_info_set_pred_proc_info(pred_proc_id::in, pred_info::in, proc_info::in, module_info::in, module_info::out) is det. :- pred module_info_typeids(module_info::in, list(type_ctor)::out) is det. :- pred module_info_instids(module_info::in, list(inst_id)::out) is det. :- pred module_info_modeids(module_info::in, list(mode_id)::out) is det. :- pred module_info_consids(module_info::in, list(cons_id)::out) is det. % Please see module_info_ensure_dependency_info for the % constraints on this dependency_info. % :- pred module_info_dependency_info(module_info::in, dependency_info::out) is det. % Please see module_info_ensure_dependency_info for the % constraints on this dependency_info. % :- pred module_info_set_dependency_info(dependency_info::in, module_info::in, module_info::out) is det. :- pred module_info_clobber_dependency_info(module_info::in, module_info::out) is det. :- pred module_info_incr_errors(module_info::in, module_info::out) is det. % The module_info stores a counter which is used to distinguish % lambda predicates which appear on the same line in the same file. % This predicate returns the next number for the given context % and increments the counter for that context. % :- pred module_info_next_lambda_count(prog_context::in, int::out, module_info::in, module_info::out) is det. :- pred module_info_next_model_non_pragma_count(int::out, module_info::in, module_info::out) is det. % Once the module_info has been built, we call module_info_optimize % to attempt to optimize the data structures for lots of accesses % and relatively few insertion/deletions. (This was useful when % we were using unbalanced binary trees, but now that we are using % 234-trees, it is a no-op, except for the mode and inst tables, % where the cached lists of mode_ids and inst_ids are sorted for % efficient conversion to sets in module_qual.m.) % :- pred module_info_optimize(module_info::in, module_info::out) is det. %-----------------------------------------------------------------------------% :- pred predicate_id(module_info::in, pred_id::in, module_name::out, string::out, arity::out) is det. :- func predicate_module(module_info, pred_id) = module_name. :- func predicate_name(module_info, pred_id) = string. :- func predicate_arity(module_info, pred_id) = arity. %-----------------------------------------------------------------------------% :- implementation. :- import_module libs.compiler_util. :- import_module assoc_list. :- import_module counter. :- pred module_info_get_lambdas_per_context(module_info::in, map(prog_context, counter)::out) is det. :- pred module_info_set_lambdas_per_context(map(prog_context, counter)::in, module_info::in, module_info::out) is det. :- pred module_info_get_model_non_pragma_counter(module_info::in, counter::out) is det. :- pred module_info_set_model_non_pragma_counter(counter::in, module_info::in, module_info::out) is det. :- pred module_info_set_maybe_dependency_info(maybe(dependency_info)::in, module_info::in, module_info::out) is det. :- type module_info ---> module_info( sub_info :: module_sub_info, predicate_table :: predicate_table, proc_requests :: proc_requests, special_pred_map :: special_pred_map, partial_qualifier_info :: partial_qualifier_info, type_table :: type_table, inst_table :: inst_table, mode_table :: mode_table, cons_table :: cons_table, class_table :: class_table, instance_table :: instance_table, superclass_table :: superclass_table, assertion_table :: assertion_table, exclusive_table :: exclusive_table, ctor_field_table :: ctor_field_table, maybe_recompilation_info :: maybe(recompilation_info) ). :- type module_sub_info ---> module_sub_info( module_name :: module_name, globals :: globals, contains_foreign_type :: bool, foreign_decl_info :: foreign_decl_info, foreign_body_info :: foreign_body_info, foreign_import_module_info :: foreign_import_module_info, % The names of the files containing fact tables implementing % predicates defined in this module. fact_table_file_names :: list(string), % This dependency info is constrained to be only for between % procedures which have clauses defined for them in this % compilation unit (that includes opt_imported procedures). maybe_dependency_info :: maybe(dependency_info), num_errors :: int, % List of the procs for which there is a pragma export(...) % declaration. pragma_exported_procs :: list(pragma_exported_proc), type_ctor_gen_infos :: list(type_ctor_gen_info), must_be_stratified_preds :: set(pred_id), % Unused argument info about predicates in the current module % which has been exported in .opt files. unused_arg_info :: unused_arg_info, % Exception information about procedures in the current module % NOTE: this includes opt_imported procedures. exception_info :: exception_info, % Information about whether procedures in the current module % modify the trail or not. % NOTE: this includes opt_imported procedures. trailing_info :: trailing_info, % How many lambda expressions there are at different contexts % in the module. This is used to uniquely identify lambda % expressions that appear on the same line of the same file. lambdas_per_context :: map(prog_context, counter), % Used to ensure uniqueness of the structure types defined % so far for model_non foreign_procs. model_non_pragma_counter :: counter, % All the directly imported module specifiers (used during type % checking, and by the MLDS back-end). imported_module_specifiers :: set(module_specifier), % All the indirectly imported modules (used by the MLDS % back-end). indirectly_imported_module_specifiers :: set(module_specifier), % Data used for user-guided type specialization. type_spec_info :: type_spec_info, % Information about no tag types. This information is also % in the type_table, but lookups in this table will be much % faster. no_tag_type_table :: no_tag_type_table, % Information about the procedures we are performing % complexity experiments on. maybe_complexity_proc_map :: maybe(pair(int, complexity_proc_map)), complexity_proc_infos :: list(complexity_proc_info), % Information for the inter-module analysis framework. analysis_info :: analysis_info, % Exported C names for preds appearing in `:- initialise % initpred' directives in this module, in order of appearance. user_init_pred_c_names :: assoc_list(sym_name, string), % Export C names fored pred appearing in `:- finalise % finalpred' directives in this module, in order of % appearance. user_final_pred_c_names :: assoc_list(sym_name, string) ). module_info_init(Name, Items, Globals, QualifierInfo, RecompInfo, ModuleInfo) :- predicate_table_init(PredicateTable), unify_proc.init_requests(Requests), map.init(UnifyPredMap), map.init(Types), inst_table_init(Insts), mode_table_init(Modes), map.init(Ctors), set.init(StratPreds), map.init(UnusedArgInfo), map.init(ExceptionInfo), map.init(TrailingInfo), set.init(TypeSpecPreds), set.init(TypeSpecForcePreds), map.init(SpecMap), map.init(PragmaMap), TypeSpecInfo = type_spec_info(TypeSpecPreds, TypeSpecForcePreds, SpecMap, PragmaMap), map.init(ClassTable), map.init(InstanceTable), map.init(SuperClassTable), % the builtin modules are automatically imported get_implicit_dependencies(Items, Globals, ImportDeps, UseDeps), set.list_to_set(ImportDeps ++ UseDeps, ImportedModules), set.init(IndirectlyImportedModules), assertion_table_init(AssertionTable), exclusive_table_init(ExclusiveTable), map.init(FieldNameTable), map.init(NoTagTypes), ModuleSubInfo = module_sub_info(Name, Globals, no, [], [], [], [], no, 0, [], [], StratPreds, UnusedArgInfo, ExceptionInfo, TrailingInfo, map.init, counter.init(1), ImportedModules, IndirectlyImportedModules, TypeSpecInfo, NoTagTypes, no, [], init_analysis_info(mmc), [], []), ModuleInfo = module_info(ModuleSubInfo, PredicateTable, Requests, UnifyPredMap, QualifierInfo, Types, Insts, Modes, Ctors, ClassTable, SuperClassTable, InstanceTable, AssertionTable, ExclusiveTable, FieldNameTable, RecompInfo). %-----------------------------------------------------------------------------% % % Various predicates which access the module_info data structure % module_info_get_predicate_table(MI, MI ^ predicate_table). module_info_get_proc_requests(MI, MI ^ proc_requests). module_info_get_special_pred_map(MI, MI ^ special_pred_map). module_info_get_partial_qualifier_info(MI, MI ^ partial_qualifier_info). module_info_get_type_table(MI, MI ^ type_table). module_info_get_inst_table(MI, MI ^ inst_table). module_info_get_mode_table(MI, MI ^ mode_table). module_info_get_cons_table(MI, MI ^ cons_table). module_info_get_class_table(MI, MI ^ class_table). module_info_get_instance_table(MI, MI ^ instance_table). module_info_get_superclass_table(MI, MI ^ superclass_table). module_info_get_assertion_table(MI, MI ^ assertion_table). module_info_get_exclusive_table(MI, MI ^ exclusive_table). module_info_get_ctor_field_table(MI, MI ^ ctor_field_table). module_info_get_maybe_recompilation_info(MI, MI ^ maybe_recompilation_info). %-----------------------------------------------------------------------------% % Various predicates which modify the module_info data structure. module_info_set_predicate_table(PT, MI, MI ^ predicate_table := PT). module_info_set_proc_requests(PR, MI, MI ^ proc_requests := PR). module_info_set_special_pred_map(SPM, MI, MI ^ special_pred_map := SPM). module_info_set_partial_qualifier_info(PQ, MI, MI ^ partial_qualifier_info := PQ). module_info_set_type_table(T, MI, MI ^ type_table := T). module_info_set_inst_table(I, MI, MI ^ inst_table := I). module_info_set_mode_table(M, MI, MI ^ mode_table := M). module_info_set_cons_table(C, MI, MI ^ cons_table := C). module_info_set_class_table(C, MI, MI ^ class_table := C). module_info_set_instance_table(I, MI, MI ^ instance_table := I). module_info_set_superclass_table(S, MI, MI ^ superclass_table := S). module_info_set_assertion_table(A, MI, MI ^ assertion_table := A). module_info_set_exclusive_table(PXT, MI, MI ^ exclusive_table := PXT). module_info_set_ctor_field_table(CF, MI, MI ^ ctor_field_table := CF). module_info_set_maybe_recompilation_info(I, MI, MI ^ maybe_recompilation_info := I). %-----------------------------------------------------------------------------% % Various predicates which access the module_sub_info data structure % via the module_info structure. module_info_get_name(MI, MI ^ sub_info ^ module_name). module_info_get_globals(MI, MI ^ sub_info ^ globals). module_info_contains_foreign_type(MI) :- MI ^ sub_info ^ contains_foreign_type = yes. module_info_get_foreign_decl(MI, MI ^ sub_info ^ foreign_decl_info). module_info_get_foreign_body_code(MI, MI ^ sub_info ^ foreign_body_info). module_info_get_foreign_import_module(MI, MI ^ sub_info ^ foreign_import_module_info). module_info_get_maybe_dependency_info(MI, MI ^ sub_info ^ maybe_dependency_info). module_info_get_num_errors(MI, MI ^ sub_info ^ num_errors). module_info_get_pragma_exported_procs(MI, MI ^ sub_info ^ pragma_exported_procs). module_info_get_type_ctor_gen_infos(MI, MI ^ sub_info ^ type_ctor_gen_infos). module_info_get_stratified_preds(MI, MI ^ sub_info ^ must_be_stratified_preds). module_info_get_unused_arg_info(MI, MI ^ sub_info ^ unused_arg_info). module_info_get_exception_info(MI, MI ^ sub_info ^ exception_info). module_info_get_trailing_info(MI, MI ^ sub_info ^ trailing_info). module_info_get_lambdas_per_context(MI, MI ^ sub_info ^ lambdas_per_context). module_info_get_model_non_pragma_counter(MI, MI ^ sub_info ^ model_non_pragma_counter). module_info_get_imported_module_specifiers(MI, MI ^ sub_info ^ imported_module_specifiers). module_info_get_indirectly_imported_module_specifiers(MI, MI ^ sub_info ^ indirectly_imported_module_specifiers). module_info_get_type_spec_info(MI, MI ^ sub_info ^ type_spec_info). module_info_get_no_tag_types(MI, MI ^ sub_info ^ no_tag_type_table). module_info_get_analysis_info(MI, MI ^ sub_info ^ analysis_info). module_info_get_maybe_complexity_proc_map(MI, MI ^ sub_info ^ maybe_complexity_proc_map). module_info_get_complexity_proc_infos(MI, MI ^ sub_info ^ complexity_proc_infos). % XXX There is some debate as to whether duplicate initialise directives % in the same module should constitute an error. Currently it is not, but % we may wish to revisit this code. The reference manual is therefore % deliberately quiet on the subject. % module_info_new_user_init_pred(SymName, CName, MI0, MI) :- InitPredCNames0 = MI0 ^ sub_info ^ user_init_pred_c_names, UserInitPredNo = list.length(InitPredCNames0), module_info_get_name(MI0, ModuleSymName), ModuleName = prog_foreign.sym_name_mangle(ModuleSymName), CName = string.format("%s__user_init_pred_%d", [s(ModuleName), i(UserInitPredNo)]), InitPredCNames = InitPredCNames0 ++ [SymName - CName], MI = MI0 ^ sub_info ^ user_init_pred_c_names := InitPredCNames. module_info_user_init_pred_c_name(MI, SymName, CName) :- InitPredCNames = MI ^ sub_info ^ user_init_pred_c_names, ( assoc_list.search(InitPredCNames, SymName, CName0) -> CName = CName0 ; module_info_get_name(MI, ModuleSymName), ModuleName = sym_name_to_string(ModuleSymName), unexpected(ModuleName, "lookup failure in module_info_user_init_pred_c_name") ). module_info_user_init_pred_c_names(MI, CNames) :- InitPredCNames = MI ^ sub_info ^ user_init_pred_c_names, CNames = assoc_list.values(InitPredCNames). module_info_new_user_final_pred(SymName, CName, MI0, MI) :- FinalPredCNames0 = MI0 ^ sub_info ^ user_final_pred_c_names, UserFinalPredNo = list.length(FinalPredCNames0), module_info_get_name(MI0, ModuleSymName), ModuleName = prog_foreign.sym_name_mangle(ModuleSymName), CName = string.format("%s__user_final_pred_%d", [s(ModuleName), i(UserFinalPredNo)]), FinalPredCNames = FinalPredCNames0 ++ [SymName - CName], MI = MI0 ^ sub_info ^ user_final_pred_c_names := FinalPredCNames. module_info_user_final_pred_c_name(MI, SymName, CName) :- FinalPredCNames = MI ^ sub_info ^ user_final_pred_c_names, ( assoc_list.search(FinalPredCNames, SymName, CName0) -> CName = CName0 ; module_info_get_name(MI, ModuleSymName), ModuleName = sym_name_to_string(ModuleSymName), unexpected(ModuleName, "lookup failure in module_info_user_final_pred_c_name") ). module_info_user_final_pred_c_names(MI, CNames) :- FinalPredCNames = MI ^ sub_info ^ user_final_pred_c_names, CNames = assoc_list.values(FinalPredCNames). %-----------------------------------------------------------------------------% % Various predicates which modify the module_sub_info data structure % via the module_info structure. module_info_set_globals(NewVal, MI, MI ^ sub_info ^ globals := NewVal). module_info_contains_foreign_type(MI, MI ^ sub_info ^ contains_foreign_type := yes). module_info_set_foreign_decl(NewVal, MI, MI ^ sub_info ^ foreign_decl_info := NewVal). module_info_set_foreign_body_code(NewVal, MI, MI ^ sub_info ^ foreign_body_info := NewVal). module_info_set_foreign_import_module(NewVal, MI, MI ^ sub_info ^ foreign_import_module_info := NewVal). module_info_set_maybe_dependency_info(NewVal, MI, MI ^ sub_info ^ maybe_dependency_info := NewVal). module_info_set_num_errors(NewVal, MI, MI ^ sub_info ^ num_errors := NewVal). module_info_set_pragma_exported_procs(NewVal, MI, MI ^ sub_info ^ pragma_exported_procs := NewVal). module_info_set_type_ctor_gen_infos(NewVal, MI, MI ^ sub_info ^ type_ctor_gen_infos := NewVal). module_info_set_stratified_preds(NewVal, MI, MI ^ sub_info ^ must_be_stratified_preds := NewVal). module_info_set_unused_arg_info(NewVal, MI, MI ^ sub_info ^ unused_arg_info := NewVal). module_info_set_exception_info(NewVal, MI, MI ^ sub_info ^ exception_info := NewVal). module_info_set_trailing_info(NewVal, MI, MI ^ sub_info ^ trailing_info := NewVal). module_info_set_lambdas_per_context(NewVal, MI, MI ^ sub_info ^ lambdas_per_context := NewVal). module_info_set_model_non_pragma_counter(NewVal, MI, MI ^ sub_info ^ model_non_pragma_counter := NewVal). module_add_imported_module_specifiers(ModuleSpecifiers, MI, MI ^ sub_info ^ imported_module_specifiers := set.insert_list(MI ^ sub_info ^ imported_module_specifiers, ModuleSpecifiers)). module_add_indirectly_imported_module_specifiers(Modules, MI, MI ^ sub_info ^ indirectly_imported_module_specifiers := set.insert_list(MI ^ sub_info ^ indirectly_imported_module_specifiers, Modules)). module_info_set_type_spec_info(NewVal, MI, MI ^ sub_info ^ type_spec_info := NewVal). module_info_set_no_tag_types(NewVal, MI, MI ^ sub_info ^ no_tag_type_table := NewVal). module_info_set_analysis_info(NewVal, MI, MI ^ sub_info ^ analysis_info := NewVal). module_info_set_maybe_complexity_proc_map(NewVal, MI, MI ^ sub_info ^ maybe_complexity_proc_map := NewVal). module_info_set_complexity_proc_infos(NewVal, MI, MI ^ sub_info ^ complexity_proc_infos := NewVal). %-----------------------------------------------------------------------------% % Various predicates which do simple things that are nevertheless % beyond the capability of an access predicate. module_info_preds(MI, Preds) :- module_info_get_predicate_table(MI, PredTable), predicate_table_get_preds(PredTable, Preds). module_info_pred_info(MI, PredId, PredInfo) :- module_info_preds(MI, Preds), ( map.search(Preds, PredId, PredInfoPrime) -> PredInfo = PredInfoPrime ; pred_id_to_int(PredId, PredInt), string.int_to_string(PredInt, PredStr), string.append("cannot find predicate number ", PredStr, Msg), unexpected(this_file, Msg) ). module_info_proc_info(MI, PPId, ProcInfo) :- module_info_pred_proc_info(MI, PPId, _, ProcInfo). module_info_proc_info(MI, PredId, ProcId, ProcInfo) :- module_info_pred_proc_info(MI, PredId, ProcId, _, ProcInfo). module_info_pred_proc_info(MI, PredId, ProcId, PredInfo, ProcInfo) :- module_info_pred_info(MI, PredId, PredInfo), pred_info_get_procedures(PredInfo, Procs), map.lookup(Procs, ProcId, ProcInfo). module_info_pred_proc_info(MI, proc(PredId, ProcId), PredInfo, ProcInfo) :- module_info_pred_proc_info(MI, PredId, ProcId, PredInfo, ProcInfo). module_info_predids(MI, PredIds) :- module_info_get_predicate_table(MI, PredTable), predicate_table_get_predids(PredTable, PredIds). module_info_reverse_predids(!MI) :- module_info_get_predicate_table(!.MI, PredTable0), predicate_table_reverse_predids(PredTable0, PredTable), module_info_set_predicate_table(PredTable, !MI). module_info_remove_predid(PredId, !MI) :- module_info_get_predicate_table(!.MI, PredTable0), predicate_table_remove_predid(PredId, PredTable0, PredTable), module_info_set_predicate_table(PredTable, !MI). module_info_remove_predicate(PredId, !MI) :- module_info_get_predicate_table(!.MI, PredTable0), predicate_table_remove_predicate(PredId, PredTable0, PredTable), module_info_set_predicate_table(PredTable, !MI). module_info_set_preds(Preds, !MI) :- module_info_get_predicate_table(!.MI, PredTable0), predicate_table_set_preds(Preds, PredTable0, PredTable), module_info_set_predicate_table(PredTable, !MI). module_info_set_pred_info(PredId, PredInfo, !MI) :- module_info_preds(!.MI, Preds0), map.set(Preds0, PredId, PredInfo, Preds), module_info_set_preds(Preds, !MI). module_info_set_pred_proc_info(proc(PredId, ProcId), PredInfo, ProcInfo, !MI) :- module_info_set_pred_proc_info(PredId, ProcId, PredInfo, ProcInfo, !MI). module_info_set_pred_proc_info(PredId, ProcId, PredInfo0, ProcInfo, !MI) :- pred_info_get_procedures(PredInfo0, Procs0), map.set(Procs0, ProcId, ProcInfo, Procs), pred_info_set_procedures(Procs, PredInfo0, PredInfo), module_info_set_pred_info(PredId, PredInfo, !MI). module_info_typeids(MI, TypeCtors) :- module_info_get_type_table(MI, Types), map.keys(Types, TypeCtors). module_info_instids(MI, InstIds) :- module_info_get_inst_table(MI, InstTable), inst_table_get_user_insts(InstTable, UserInstTable), user_inst_table_get_inst_ids(UserInstTable, InstIds). module_info_modeids(MI, ModeIds) :- module_info_get_mode_table(MI, Modes), mode_table_get_mode_ids(Modes, ModeIds). module_info_consids(MI, ConsIds) :- module_info_get_cons_table(MI, Ctors), map.keys(Ctors, ConsIds). module_info_dependency_info(MI, DepInfo) :- module_info_get_maybe_dependency_info(MI, MaybeDepInfo), ( MaybeDepInfo = yes(DepInfoPrime), DepInfo = DepInfoPrime ; MaybeDepInfo = no, unexpected(this_file, "Attempted to access invalid dependency_info") ). module_info_set_dependency_info(DependencyInfo, !MI) :- module_info_set_maybe_dependency_info(yes(DependencyInfo), !MI). module_info_clobber_dependency_info(!MI) :- module_info_set_maybe_dependency_info(no, !MI). module_info_incr_errors(!MI) :- module_info_get_num_errors(!.MI, Errs0), Errs = Errs0 + 1, module_info_set_num_errors(Errs, !MI). module_info_next_lambda_count(Context, Count, !MI) :- module_info_get_lambdas_per_context(!.MI, ContextCounter0), ( map.insert(ContextCounter0, Context, counter.init(2), FoundContextCounter) -> Count = 1, ContextCounter = FoundContextCounter ; map.lookup(ContextCounter0, Context, Counter0), counter.allocate(Count, Counter0, Counter), map.det_update(ContextCounter0, Context, Counter, ContextCounter) ), module_info_set_lambdas_per_context(ContextCounter, !MI). module_info_next_model_non_pragma_count(Count, !MI) :- module_info_get_model_non_pragma_counter(!.MI, Counter0), counter.allocate(Count, Counter0, Counter), module_info_set_model_non_pragma_counter(Counter, !MI). module_info_optimize(!ModuleInfo) :- module_info_get_predicate_table(!.ModuleInfo, Preds0), predicate_table_optimize(Preds0, Preds), module_info_set_predicate_table(Preds, !ModuleInfo), module_info_get_type_table(!.ModuleInfo, Types0), map.optimize(Types0, Types), module_info_set_type_table(Types, !ModuleInfo), module_info_get_inst_table(!.ModuleInfo, InstTable0), inst_table_get_user_insts(InstTable0, Insts0), user_inst_table_optimize(Insts0, Insts), inst_table_set_user_insts(Insts, InstTable0, InstTable), module_info_set_inst_table(InstTable, !ModuleInfo), module_info_get_mode_table(!.ModuleInfo, Modes0), mode_table_optimize(Modes0, Modes), module_info_set_mode_table(Modes, !ModuleInfo), module_info_get_cons_table(!.ModuleInfo, Ctors0), map.optimize(Ctors0, Ctors), module_info_set_cons_table(Ctors, !ModuleInfo). visible_module(VisibleModule, ModuleInfo) :- module_info_get_name(ModuleInfo, ThisModule), module_info_get_imported_module_specifiers(ModuleInfo, ImportedModules), ( VisibleModule = ThisModule ; set.member(VisibleModule, ImportedModules) ; ParentModules = get_ancestors(ThisModule), list.member(VisibleModule, ParentModules) ). module_info_get_all_deps(ModuleInfo, AllImports) :- module_info_get_name(ModuleInfo, ModuleName), Parents = get_ancestors(ModuleName), module_info_get_imported_module_specifiers(ModuleInfo, DirectImports), module_info_get_indirectly_imported_module_specifiers(ModuleInfo, IndirectImports), AllImports = set.union_list([IndirectImports, DirectImports, set.list_to_set(Parents)]). module_add_foreign_decl(Lang, IsLocal, ForeignDecl, Context, !Module) :- module_info_get_foreign_decl(!.Module, ForeignDeclIndex0), % store the decls in reverse order and reverse them later % for efficiency ForeignDeclIndex = [foreign_decl_code(Lang, IsLocal, ForeignDecl, Context) | ForeignDeclIndex0], module_info_set_foreign_decl(ForeignDeclIndex, !Module). module_add_foreign_body_code(Lang, Foreign_Body_Code, Context, !Module) :- module_info_get_foreign_body_code(!.Module, Foreign_Body_List0), % Store the decls in reverse order and reverse them later for efficiency. Foreign_Body_List = [foreign_body_code(Lang, Foreign_Body_Code, Context) | Foreign_Body_List0], module_info_set_foreign_body_code(Foreign_Body_List, !Module). module_add_foreign_import_module(Lang, ModuleName, Context, !Module) :- module_info_get_foreign_import_module(!.Module, ForeignImportIndex0), % Store the decls in reverse order and reverse them later for efficiency. ForeignImportIndex = [foreign_import_module(Lang, ModuleName, Context) | ForeignImportIndex0], module_info_set_foreign_import_module(ForeignImportIndex, !Module). module_get_fact_table_files(Module, FileNames) :- FileNames = Module ^ sub_info ^ fact_table_file_names. module_add_fact_table_file(FileName, !Module) :- FileNames = !.Module ^ sub_info ^ fact_table_file_names, !:Module = !.Module ^ sub_info ^ fact_table_file_names := [FileName | FileNames]. %-----------------------------------------------------------------------------% predicate_id(ModuleInfo, PredId, ModuleName, PredName, Arity) :- module_info_preds(ModuleInfo, Preds), map.lookup(Preds, PredId, PredInfo), ModuleName = pred_info_module(PredInfo), PredName = pred_info_name(PredInfo), Arity = pred_info_orig_arity(PredInfo). predicate_module(ModuleInfo, PredId) = ModuleName :- module_info_preds(ModuleInfo, Preds), map.lookup(Preds, PredId, PredInfo), ModuleName = pred_info_module(PredInfo). predicate_name(ModuleInfo, PredId) = PredName :- module_info_preds(ModuleInfo, Preds), map.lookup(Preds, PredId, PredInfo), PredName = pred_info_name(PredInfo). predicate_arity(ModuleInfo, PredId) = Arity :- module_info_preds(ModuleInfo, Preds), map.lookup(Preds, PredId, PredInfo), Arity = pred_info_orig_arity(PredInfo). %-----------------------------------------------------------------------------% %-----------------------------------------------------------------------------% :- interface. :- type dependency_ordering(T) == list(list(T)). :- type dependency_ordering == dependency_ordering(pred_proc_id). :- type dependency_graph(T) == relation(T). :- type dependency_graph == dependency_graph(pred_proc_id). :- type dependency_info(T). :- type dependency_info == dependency_info(pred_proc_id). :- pred hlds_dependency_info_init(dependency_info(T)::out) is det. :- pred hlds_dependency_info_get_dependency_graph(dependency_info(T)::in, dependency_graph(T)::out) is det. :- pred hlds_dependency_info_get_dependency_ordering(dependency_info(T)::in, dependency_ordering(T)::out) is det. :- pred hlds_dependency_info_set_dependency_graph(dependency_graph(T)::in, dependency_info(T)::in, dependency_info(T)::out) is det. :- pred hlds_dependency_info_set_dependency_ordering( dependency_ordering(T)::in, dependency_info(T)::in, dependency_info(T)::out) is det. %-----------------------------------------------------------------------------% :- implementation. :- type dependency_info(T) ---> dependency_info( dep_graph :: dependency_graph(T), dep_ord :: dependency_ordering(T) ). hlds_dependency_info_init(DepInfo) :- relation.init(DepRel), DepOrd = [], DepInfo = dependency_info(DepRel, DepOrd). hlds_dependency_info_get_dependency_graph(DepInfo, DepInfo ^ dep_graph). hlds_dependency_info_get_dependency_ordering(DepInfo, DepInfo ^ dep_ord). hlds_dependency_info_set_dependency_graph(DepGraph, DepInfo, DepInfo ^ dep_graph := DepGraph). hlds_dependency_info_set_dependency_ordering(DepOrd, DepInfo, DepInfo ^ dep_ord := DepOrd). %-----------------------------------------------------------------------------% :- func this_file = string. this_file = "hlds_module.m". %-----------------------------------------------------------------------------%