mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-15 01:13:30 +00:00
compiler/inst_lookup.m:
compiler/inst_mode_type_prop.m:
compiler/inst_test.m:
compiler/inst_util.m:
compiler/mode_util.m:
compiler/type_util.m:
Move these modules from the check_hlds package to the hlds package.
The reason is that all the content of five of these modules, and
most of the content of one module (inst_util.m) is not used
exclusively during semantic checking passes. (A later diff
should deal with the exception.) Some are used by the pass that
builds the initial HLDS, and all are used by middle-end and backend
passes. The move therefore reduces the number of inappropriate imports
of the check_hlds package.
compiler/check_hlds.m:
compiler/hlds.m:
Effect the transfer.
compiler/*.m:
Conform to the changes above.
307 lines
12 KiB
Mathematica
307 lines
12 KiB
Mathematica
%---------------------------------------------------------------------------%
|
|
% vim: ft=mercury ts=4 sw=4 et
|
|
%---------------------------------------------------------------------------%
|
|
% Copyright (C) 2023, 2025 The Mercury team
|
|
% This file may only be copied under the terms of the GNU General
|
|
% Public License - see the file COPYING in the Mercury distribution.
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
% File: var_table_hlds.m.
|
|
% Main author: zs.
|
|
%
|
|
% This module defines operations on var_tables that require access
|
|
% to the HLDS. (The var_table type itself, and most other operations on it,
|
|
% are defined in var_table.m, which is in the parse_tree package, which
|
|
% does not have access to the HLDS.)
|
|
%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- module hlds.var_table_hlds.
|
|
|
|
:- interface.
|
|
|
|
:- import_module hlds.hlds_module.
|
|
:- import_module parse_tree.
|
|
:- import_module parse_tree.prog_data.
|
|
:- import_module parse_tree.var_table.
|
|
:- import_module parse_tree.vartypes.
|
|
|
|
:- import_module assoc_list.
|
|
:- import_module list.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
% These two predicates convert <varset, vartypes> pairs to var_tables,
|
|
% and vice versa. They are used by
|
|
%
|
|
% - ancient compiler passes (such as mode_constraints.) that could use
|
|
% var_tables but don't (because they were written way before var_tables),
|
|
% and
|
|
%
|
|
% - by code that constructs new clauses (such as unify/compare predicates
|
|
% and stubs) from HLDS code.
|
|
%
|
|
% The former will never be worth converting to use var_tables. The latter
|
|
% *could* be so converted, but it would require the code that now constructs
|
|
% clause_infos to construct HLDS predicates instead. This is definitely
|
|
% possible, since all the code that now constructs clause_infos should be
|
|
% able to figure out the exact types of all the variables in those clauses,
|
|
% but would require new code to explicitly materialize those types, instead of
|
|
% just leaving that job to the typechecker.
|
|
%
|
|
|
|
% Create a var_table from a varset/vartypes pair.
|
|
%
|
|
:- pred make_var_table(module_info::in, prog_varset::in, vartypes::in,
|
|
var_table::out) is det.
|
|
|
|
% Split up a var_table into a varset/vartypes pair.
|
|
%
|
|
:- pred split_var_table(var_table::in, prog_varset::out, vartypes::out) is det.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
% Create a var_table from a varset and a list of variables
|
|
% with their types.
|
|
%
|
|
% The typechecking pass uses these predicates to record its results
|
|
% in pred_infos.
|
|
%
|
|
:- pred vars_types_to_var_table(module_info::in, prog_varset::in,
|
|
assoc_list(prog_var, mer_type)::in, var_table::out) is det.
|
|
:- pred corresponding_vars_types_to_var_table(module_info::in, prog_varset::in,
|
|
list(prog_var)::in, list(mer_type)::in, var_table::out) is det.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred create_fresh_named_var(module_info::in, string::in, mer_type::in,
|
|
prog_var::out, var_table::in, var_table::out) is det.
|
|
|
|
:- pred create_fresh_var(module_info::in, mer_type::in,
|
|
prog_var::out, var_table::in, var_table::out) is det.
|
|
|
|
:- pred create_fresh_vars(module_info::in, list(mer_type)::in,
|
|
list(prog_var)::out, var_table::in, var_table::out) is det.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
:- import_module hlds.type_util.
|
|
:- import_module parse_tree.builtin_lib_types.
|
|
:- import_module parse_tree.prog_type.
|
|
|
|
:- import_module counter.
|
|
:- import_module int.
|
|
:- import_module map.
|
|
:- import_module pair.
|
|
:- import_module require.
|
|
:- import_module term.
|
|
:- import_module varset.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
make_var_table(ModuleInfo, VarSet, VarTypes, VarTable) :-
|
|
vartypes_to_sorted_assoc_list(VarTypes, VarTypesAL),
|
|
make_var_table_loop(ModuleInfo, VarSet, 1, VarTypesAL,
|
|
[], RevVarTableAL0),
|
|
(
|
|
RevVarTableAL0 = [],
|
|
LastAllocVarNum0 = 0
|
|
;
|
|
RevVarTableAL0 = [Var - _ | _],
|
|
LastAllocVarNum0 = var_to_int(Var)
|
|
),
|
|
MaxVarInVarSet = varset.max_var(VarSet),
|
|
MaxVarNumInVarSet = var_to_int(MaxVarInVarSet),
|
|
( if MaxVarNumInVarSet > LastAllocVarNum0 then
|
|
LastAllocVarNum = MaxVarNumInVarSet,
|
|
extend_var_table_loop(VarSet, LastAllocVarNum0 + 1, LastAllocVarNum,
|
|
RevVarTableAL0, RevVarTableAL)
|
|
else
|
|
LastAllocVarNum = LastAllocVarNum0,
|
|
RevVarTableAL = RevVarTableAL0
|
|
),
|
|
counter.init(LastAllocVarNum + 1, Counter),
|
|
map.from_rev_sorted_assoc_list(RevVarTableAL, VarTableMap),
|
|
construct_var_table(Counter, VarTableMap, VarTable).
|
|
|
|
:- pred make_var_table_loop(module_info::in, prog_varset::in, int::in,
|
|
assoc_list(prog_var, mer_type)::in,
|
|
assoc_list(prog_var, var_table_entry)::in,
|
|
assoc_list(prog_var, var_table_entry)::out) is det.
|
|
|
|
make_var_table_loop(_, _, _, [], !RevVarTableAL).
|
|
make_var_table_loop(ModuleInfo, VarSet, CurVarNum, [Var - Type | VarsTypes0],
|
|
!RevVarTableAL) :-
|
|
VarNum = term.var_to_int(Var),
|
|
( if CurVarNum = VarNum then
|
|
( if varset.search_name(VarSet, Var, NamePrime) then
|
|
Name = NamePrime
|
|
else
|
|
Name = ""
|
|
),
|
|
IsDummy = is_type_a_dummy(ModuleInfo, Type),
|
|
Entry = vte(Name, Type, IsDummy),
|
|
!:RevVarTableAL = [Var - Entry | !.RevVarTableAL],
|
|
VarsTypes = VarsTypes0
|
|
else if CurVarNum < VarNum then
|
|
record_untyped_var(VarSet, CurVarNum, !RevVarTableAL),
|
|
% We did not Process Var in this iteration.
|
|
VarsTypes = [Var - Type | VarsTypes0]
|
|
else
|
|
unexpected($pred, "CurVarNum > VarNum")
|
|
),
|
|
make_var_table_loop(ModuleInfo, VarSet, CurVarNum + 1,
|
|
VarsTypes, !RevVarTableAL).
|
|
|
|
:- pred extend_var_table_loop(prog_varset::in, int::in, int::in,
|
|
assoc_list(prog_var, var_table_entry)::in,
|
|
assoc_list(prog_var, var_table_entry)::out) is det.
|
|
|
|
extend_var_table_loop(VarSet, CurVarNum, MaxVarNum, !RevVarTableAL) :-
|
|
( if CurVarNum =< MaxVarNum then
|
|
record_untyped_var(VarSet, CurVarNum, !RevVarTableAL),
|
|
extend_var_table_loop(VarSet, CurVarNum + 1, MaxVarNum, !RevVarTableAL)
|
|
else
|
|
true
|
|
).
|
|
|
|
% Record a variable number that was allocated in the varset,
|
|
% but whose type was not recorded.
|
|
%
|
|
% Before we started using var_tables, a lookup of such a variable
|
|
% would succeed in the varset but fail in the vartypes.
|
|
%
|
|
% The var_table we are constructing will have valid info for the name,
|
|
% but dummy info for the type.
|
|
%
|
|
:- pred record_untyped_var(prog_varset::in, int::in,
|
|
assoc_list(prog_var, var_table_entry)::in,
|
|
assoc_list(prog_var, var_table_entry)::out) is det.
|
|
|
|
record_untyped_var(VarSet, VarNum, !RevVarTableAL) :-
|
|
Var = force_construct_var(VarNum),
|
|
( if varset.search_name(VarSet, Var, NamePrime) then
|
|
Name = NamePrime
|
|
else
|
|
Name = ""
|
|
),
|
|
VarEntry = vte(Name, void_type, is_dummy_type),
|
|
!:RevVarTableAL = [Var - VarEntry | !.RevVarTableAL].
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
split_var_table(VarTable, VarSet, VarTypes) :-
|
|
deconstruct_var_table(VarTable, Counter, VarTableMap),
|
|
map.to_sorted_assoc_list(VarTableMap, VarsEntries),
|
|
split_var_table_loop(VarsEntries, [], RevVarTypes, [], RevVarNames),
|
|
vartypes_from_rev_sorted_assoc_list(RevVarTypes, VarTypes),
|
|
map.from_rev_sorted_assoc_list(RevVarNames, VarNameMap),
|
|
(
|
|
RevVarTypes = [],
|
|
LastVarNum = 0
|
|
;
|
|
RevVarTypes = [Var - _ | _],
|
|
LastVarNum = var_to_int(Var)
|
|
),
|
|
counter.allocate(NextVarNum, Counter, _),
|
|
expect(unify(LastVarNum + 1, NextVarNum), $pred,
|
|
"LastVarNum + 1 != NextVarNum"),
|
|
construct_varset(LastVarNum, VarNameMap, VarSet).
|
|
|
|
:- pred split_var_table_loop(assoc_list(prog_var, var_table_entry)::in,
|
|
assoc_list(prog_var, mer_type)::in, assoc_list(prog_var, mer_type)::out,
|
|
assoc_list(prog_var, string)::in, assoc_list(prog_var, string)::out)
|
|
is det.
|
|
|
|
split_var_table_loop([], !RevVarTypes, !RevVarNames).
|
|
split_var_table_loop([Var - Entry | VarsEntries],
|
|
!RevVarTypes, !RevVarNames) :-
|
|
Entry = vte(Name, Type, _IsDummy),
|
|
!:RevVarTypes = [Var - Type | !.RevVarTypes],
|
|
( if Name = "" then
|
|
true
|
|
else
|
|
!:RevVarNames = [Var - Name | !.RevVarNames]
|
|
),
|
|
split_var_table_loop(VarsEntries, !RevVarTypes, !RevVarNames).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
vars_types_to_var_table(ModuleInfo, VarSet, VarsTypes, VarTable) :-
|
|
vars_types_to_vars_entries(ModuleInfo, VarSet, VarsTypes, [], VarsEntries),
|
|
list.sort(VarsEntries, SortedVarsEntries),
|
|
var_table_from_sorted_assoc_list(SortedVarsEntries, VarTable).
|
|
|
|
:- pred vars_types_to_vars_entries(module_info::in, prog_varset::in,
|
|
assoc_list(prog_var, mer_type)::in,
|
|
assoc_list(prog_var, var_table_entry)::in,
|
|
assoc_list(prog_var, var_table_entry)::out) is det.
|
|
|
|
vars_types_to_vars_entries(_, _, [], !VarsEntries).
|
|
vars_types_to_vars_entries(ModuleInfo, VarSet, [Var - Type | VarsTypes],
|
|
!VarsEntries) :-
|
|
( if varset.search_name(VarSet, Var, Name0) then
|
|
Name = Name0
|
|
else
|
|
Name = ""
|
|
),
|
|
IsDummy = is_type_a_dummy(ModuleInfo, Type),
|
|
Entry = vte(Name, Type, IsDummy),
|
|
!:VarsEntries = [Var - Entry | !.VarsEntries],
|
|
vars_types_to_vars_entries(ModuleInfo, VarSet, VarsTypes, !VarsEntries).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
corresponding_vars_types_to_var_table(ModuleInfo, VarSet, Vars, Types,
|
|
VarTable) :-
|
|
corresponding_vars_types_to_vars_entries(ModuleInfo, VarSet, Vars, Types,
|
|
[], VarsEntries),
|
|
list.sort(VarsEntries, SortedVarsEntries),
|
|
var_table_from_sorted_assoc_list(SortedVarsEntries, VarTable).
|
|
|
|
:- pred corresponding_vars_types_to_vars_entries(module_info::in,
|
|
prog_varset::in, list(prog_var)::in, list(mer_type)::in,
|
|
assoc_list(prog_var, var_table_entry)::in,
|
|
assoc_list(prog_var, var_table_entry)::out) is det.
|
|
|
|
corresponding_vars_types_to_vars_entries(_, _, [], [], !VarsEntries).
|
|
corresponding_vars_types_to_vars_entries(_, _, [], [_ | _], !VarsEntries) :-
|
|
unexpected($pred, "length mismatch").
|
|
corresponding_vars_types_to_vars_entries(_, _, [_ | _], [], !VarsEntries) :-
|
|
unexpected($pred, "length mismatch").
|
|
corresponding_vars_types_to_vars_entries(ModuleInfo, VarSet,
|
|
[Var | Vars], [Type | Types], !VarsEntries) :-
|
|
( if varset.search_name(VarSet, Var, Name0) then
|
|
Name = Name0
|
|
else
|
|
Name = ""
|
|
),
|
|
IsDummy = is_type_a_dummy(ModuleInfo, Type),
|
|
Entry = vte(Name, Type, IsDummy),
|
|
!:VarsEntries = [Var - Entry | !.VarsEntries],
|
|
corresponding_vars_types_to_vars_entries(ModuleInfo, VarSet, Vars, Types,
|
|
!VarsEntries).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
create_fresh_named_var(ModuleInfo, Name, Type, Var, !VarTable) :-
|
|
IsDummy = is_type_a_dummy(ModuleInfo, Type),
|
|
Entry = vte(Name, Type, IsDummy),
|
|
add_var_entry(Entry, Var, !VarTable).
|
|
|
|
create_fresh_var(ModuleInfo, Type, Var, !VarTable) :-
|
|
IsDummy = is_type_a_dummy(ModuleInfo, Type),
|
|
Entry = vte("", Type, IsDummy),
|
|
add_var_entry(Entry, Var, !VarTable).
|
|
|
|
create_fresh_vars(_, [], [], !VarTable).
|
|
create_fresh_vars(ModuleInfo, [Type | Types], [Var | Vars], !VarTable) :-
|
|
create_fresh_var(ModuleInfo, Type, Var, !VarTable),
|
|
create_fresh_vars(ModuleInfo, Types, Vars, !VarTable).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
:- end_module hlds.var_table_hlds.
|
|
%---------------------------------------------------------------------------%
|