mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-16 18:03:36 +00:00
compiler/prog_type_construct.m:
New module for constructing types.
compiler/prog_type_repn.m:
New module for testing things related to type representation.
compiler/prog_type_scan.m:
New module for gather type vars in types.
compiler/prog_type_test.m:
New module containing simple tests on types.
compiler/prog_type_unify.m:
New module for testing whether two types unify, or whether
one type subsumes another.
compiler/prog_type.m:
Delete the code moved to the new modules.
compiler/parse_tree.m:
Include the new modules.
compiler/notes/compiler_design.html:
Document the new modules.
compiler/*.m:
Conform to the changes above, by adjusting imports as needed,
and by deleting any explicit module qualifications that
this diff makes obsolete.
256 lines
9.5 KiB
Mathematica
256 lines
9.5 KiB
Mathematica
%---------------------------------------------------------------------------%
|
|
% vim: ft=mercury ts=4 sw=4 et
|
|
%---------------------------------------------------------------------------%
|
|
% Copyright (C) 2023 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.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
% 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.
|
|
%
|
|
:- 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.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
:- import_module check_hlds.
|
|
:- import_module check_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).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
:- end_module hlds.var_table_hlds.
|
|
%---------------------------------------------------------------------------%
|