%---------------------------------------------------------------------------% % vim: ft=mercury ts=4 sw=4 et %---------------------------------------------------------------------------% % Copyright (C) 2006, 2009, 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: ctgc.datastruct.m. % Main author: nancy. % % Definition of predicates and functions for the manipulation of % datastructures. % %---------------------------------------------------------------------------% :- module transform_hlds.ctgc.datastruct. :- interface. :- import_module hlds. :- import_module hlds.hlds_module. :- import_module parse_tree. :- import_module parse_tree.prog_data. :- import_module parse_tree.prog_data_pragma. :- import_module parse_tree.var_table. :- import_module list. %---------------------------------------------------------------------------% % Create an initial top-datastruct of the given variable. % :- func datastruct_init(prog_var) = datastruct. :- func datastruct_init_with_selector(prog_var, selector) = datastruct. :- func datastruct_init_with_pos(prog_var, cons_id, int) = datastruct. % Verify whether the given datastructs are identical. % :- pred datastruct_equal(datastruct::in, datastruct::in) is semidet. % Check whether the two given datastructs are related to the % same variable or not. % :- pred datastruct_same_vars(datastruct::in, datastruct::in) is semidet. % Verify whether the datastructure represents a top cell, i.e. where % the selector path is an empty path. % :- pred datastruct_refers_to_topcell(datastruct::in) is semidet. % Select a subterm of the given datastructure using the specified selector. % It is assumed that the selector is a valid selector for that % datastructure. % :- func datastruct_termshift(module_info, var_table, selector, datastruct) = datastruct. % Normalize the representation of the datastructure. % (proc_info is needed to obtain the type of the variable of the % datastructure). % The selector of a datastruct is normalized % iff none of the term nodes met on the path to the actual selected % term by the selector has the same type as the selected node. % :- func normalize_datastruct(module_info, var_table, datastruct) = datastruct. :- pred datastruct_subsumed_by_return_selector(module_info::in, var_table::in, datastruct::in, datastruct::in, selector::out) is semidet. :- pred datastruct_subsumed_by(module_info::in, var_table::in, datastruct::in, datastruct::in) is semidet. :- pred datastruct_subsumed_by_list(module_info::in, var_table::in, datastruct::in, list(datastruct)::in) is semidet. :- pred datastructs_subsumed_by_list(module_info::in, var_table::in, list(datastruct)::in, list(datastruct)::in) is semidet. :- pred datastructs_that_are_subsumed_by_list(module_info::in, var_table::in, list(datastruct)::in, list(datastruct)::in, list(datastruct)::out) is det. :- func datastruct_lists_least_upper_bound(module_info, var_table, list(datastruct), list(datastruct)) = list(datastruct). :- pred datastruct_apply_widening(module_info::in, var_table::in, datastruct::in, datastruct::out) is det. :- func datastructs_project(list(prog_var), list(datastruct)) = list(datastruct). :- func datastructs_vars(list(datastruct)) = list(prog_var). %---------------------------------------------------------------------------% :- implementation. :- import_module transform_hlds.ctgc.selector. %---------------------------------------------------------------------------% datastruct_init(V) = datastruct_init_with_selector(V, []). datastruct_init_with_selector(V, Sel) = selected_cel(V, Sel). datastruct_init_with_pos(V, ConsId, Int) = datastruct_init_with_selector(V, selector_init(ConsId, Int)). datastruct_equal(D1, D2) :- D1 = D2. datastruct_same_vars(D1, D2) :- D1 ^ sc_var = D2 ^ sc_var. datastruct_refers_to_topcell(Data):- DSel = Data ^ sc_selector, DSel = []. datastruct_termshift(ModuleInfo, VarTable, Sel, Data0) = Data :- ( Sel = [], Data = Data0 ; Sel = [_ | _], Data0 = selected_cel(Var, DSel), selector_termshift(DSel, Sel, NewSel0), % Keep datastruct seletors normalized. lookup_var_type(VarTable, Var, Type), normalize_selector_with_type_information(ModuleInfo, Type, NewSel0, NewSel), Data = selected_cel(Var, NewSel) ). normalize_datastruct(ModuleInfo, VarTable, Data0) = Data :- Data0 = selected_cel(Var, DSel0), lookup_var_type(VarTable, Var, Type), normalize_selector_with_type_information(ModuleInfo, Type, DSel0, DSel), Data = selected_cel(Var, DSel). datastruct_subsumed_by_return_selector(ModuleInfo, VarTable, Data1, Data2, Extension) :- Data1 = selected_cel(Var, Sel1), Data2 = selected_cel(Var, Sel2), lookup_var_type(VarTable, Var, Type), selector_subsumed_by(ModuleInfo, already_normalized, Sel1, Sel2, Type, Extension). datastruct_subsumed_by(ModuleInfo, VarTable, Data1, Data2) :- datastruct_subsumed_by_return_selector(ModuleInfo, VarTable, Data1, Data2, _). datastruct_subsumed_by_list(ModuleInfo, VarTable, Data0, [Data | Rest]):- ( datastruct_subsumed_by(ModuleInfo, VarTable, Data0, Data) ; datastruct_subsumed_by_list(ModuleInfo, VarTable, Data0, Rest) ). datastructs_subsumed_by_list(ModuleInfo, VarTable, PerhapsSubsumedData, Data) :- all [X] ( list.member(X, PerhapsSubsumedData) => datastructs_subsume_datastruct(ModuleInfo, VarTable, Data, X) ). datastructs_that_are_subsumed_by_list(ModuleInfo, VarTable, PerhapsSubsumedData, Datastructs, SubsumedData) :- list.filter( datastructs_subsume_datastruct(ModuleInfo, VarTable, Datastructs), PerhapsSubsumedData, SubsumedData). :- pred datastructs_subsume_datastruct(module_info::in, var_table::in, list(datastruct)::in, datastruct::in) is semidet. datastructs_subsume_datastruct(ModuleInfo, VarTable, Datastructs, Data):- datastruct_subsumed_by_list(ModuleInfo, VarTable, Data, Datastructs). datastruct_lists_least_upper_bound(ModuleInfo, VarTable, Data1, Data2) = Data :- list.filter( datastructs_subsume_datastruct(ModuleInfo, VarTable, Data1), Data2, _SubsumedData, NotSubsumedData), Data = list.append(NotSubsumedData, Data1). datastruct_apply_widening(ModuleInfo, VarTable, Data0, Data) :- Data0 = selected_cel(Var, Sel0), lookup_var_type(VarTable, Var, Type), selector_apply_widening(ModuleInfo, Type, Sel0, Sel), Data = selected_cel(Var, Sel). datastructs_project(Vars, DataIn) = list.filter( (pred(Data::in) is semidet :- list.member(Data ^ sc_var, Vars)), DataIn). datastructs_vars(Data) = list.map(func(X) = X ^ sc_var, Data). %---------------------------------------------------------------------------% :- end_module transform_hlds.ctgc.datastruct. %---------------------------------------------------------------------------%