Files
mercury/compiler/parse_pragma_tabling.m
Zoltan Somogyi 9d38b252bf Separate marker pragmas from other decl/impl pragmas.
compiler/prog_item.m:
    Previously, both decl and impl pragmas contained some pragma kinds
    that contained only the specification of a predicate or function.
    These served only to specify a marker to be applied to the named
    predicate or function.

    This diff separates out those kinds of pragmas from the types of
    both the decl pragmas and the impl pragmas (the difference is that
    decl pragmas may appear in module interfaces, while impl pragmas may not),
    and gives them two new representations: decl markers and impl markers.

    While in the old representation, each kind of marker had its own wrapper
    around the predicate/function specification, in the new representation,
    they are side-by-side, which allows simpler construction techniques
    and smaller code.

    Update the definition of parse_tree_module_src, parse_tree_plain_opt,
    parse_tree_int0 and parse_tree_int1 to include markers alongside
    pragmas of each kind. Use subtypes to restrict the kinds of markers
    that can appear in parse_tree_plain_opts to the set that we actually
    can put into them. (Source files of course can contain any markers,
    and .intN files either get put into them either all of the markers
    that occur in the source file in a given section, or none of them.)

    Delete the item_pragma_info type, which was a wrapper around
    the specific info of each pragma, and stored a context and an item
    sequence number alongside it. Move the context and the item sequence
    number into the representation of each pragma. This should reduce
    visual clutter in the source code at places that construct or deconstruct
    pragmas, and at runtime (with direct args) it should reduce both
    the number of memory cells we need to allocate, and the number
    of pointers we need to follow.

    Include decl vs impl in the names of some function symbols.

    Partly to counteract that, shorten some names to avoid excessive
    line lengths.

compiler/add_pragma.m:
    Add predicates to add decl and impl markers.

    Move the predicates looping over lists of pragma next to the
    predicates handling those pragmas.

compiler/make_hlds_passes.m:
    Add both decl and impl markers before adding foreign_procs.
    The ability to do this was the original motivation for this diff.
    Update the comments both about this issue, and about why we delay
    adding tabling pragmas to the HLDS.

compiler/check_module_interface.m:
    Conform to the changes above.

    Add an XXX about something fishy.

compiler/item_util.m:
    Delete aux functions that are no longer needed.

compiler/add_mutable_aux_preds.m:
compiler/add_pragma_tabling.m:
compiler/add_pragma_type_spec.m:
compiler/comp_unit_interface.m:
compiler/convert_parse_tree.m:
compiler/equiv_type.m:
compiler/get_dependencies.m:
compiler/grab_modules.m:
compiler/hlds_module.m:
compiler/intermod.m:
compiler/intermod_analysis.m:
compiler/make_hlds_separate_items.m:
compiler/mercury_compile_middle_passes.m:
compiler/module_qual.collect_mq_info.m:
compiler/module_qual.qual_errors.m:
compiler/module_qual.qualify_items.m:
compiler/parse_pragma.m:
compiler/parse_pragma_analysis.m:
compiler/parse_pragma_foreign.m:
compiler/parse_pragma_tabling.m:
compiler/parse_tree_out.m:
compiler/parse_tree_out_pragma.m:
compiler/prog_item_stats.m:
compiler/prog_mutable.m:
compiler/recompilation.check.m:
compiler/recompilation.usage.m:
compiler/recompilation.version.m:
compiler/unused_args.m:
    Conform to the changes above.
2023-08-06 12:33:55 +02:00

602 lines
24 KiB
Mathematica

%---------------------------------------------------------------------------%
% vim: ft=mercury ts=4 sw=4 expandtab
%---------------------------------------------------------------------------%
% Copyright (C) 1996-2011 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: parse_pragma.m.
%
% This module parses tabling pragmas.
%
%---------------------------------------------------------------------------%
:- module parse_tree.parse_pragma_tabling.
:- interface.
:- import_module mdbcomp.
:- import_module mdbcomp.sym_name.
:- import_module parse_tree.maybe_error.
:- import_module parse_tree.parse_types.
:- import_module parse_tree.prog_data.
:- import_module parse_tree.prog_data_pragma.
:- import_module list.
:- import_module term.
:- import_module varset.
%---------------------------------------------------------------------------%
% Parse a tabling pragma.
%
:- pred parse_tabling_pragma(module_name::in, varset::in, term::in,
string::in, list(term)::in, prog_context::in, item_seq_num::in,
tabled_eval_method::in, maybe1(item_or_marker)::out) is det.
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
:- implementation.
:- import_module parse_tree.error_spec.
:- import_module parse_tree.parse_tree_out_misc.
:- import_module parse_tree.parse_tree_out_term.
:- import_module parse_tree.parse_util.
:- import_module parse_tree.prog_item.
:- import_module assoc_list.
:- import_module bool.
:- import_module cord.
:- import_module maybe.
:- import_module pair.
:- import_module require.
%---------------------------------------------------------------------------%
parse_tabling_pragma(ModuleName, VarSet, ErrorTerm, PragmaName, PragmaTerms,
Context, SeqNum, TabledMethod0, MaybeIOM) :-
(
(
PragmaTerms = [PredOrProcSpecTerm0],
MaybeAttrs = no
;
PragmaTerms = [PredOrProcSpecTerm0, AttrListTerm0],
MaybeAttrs = yes(AttrListTerm0)
),
ContextPieces = cord.from_list([words("In the first argument of"),
pragma_decl(PragmaName), words("declaration:"), nl]),
parse_pred_pfu_name_arity_maybe_modes(ModuleName, ContextPieces,
VarSet, PredOrProcSpecTerm0, MaybePredOrProcSpec),
(
MaybePredOrProcSpec = ok1(PredOrProcSpec),
(
MaybeAttrs = no,
Tabled = impl_pragma_tabled_info(TabledMethod0, PredOrProcSpec,
no, Context, SeqNum),
ImplPragma = impl_pragma_tabled(Tabled),
Item = item_impl_pragma(ImplPragma),
MaybeIOM = ok1(iom_item(Item))
;
MaybeAttrs = yes(AttrsListTerm),
AttrContextPieces = cord.from_list(
[words("In the second argument of"),
pragma_decl(PragmaName), words("declaration:"), nl]),
parse_list_elements("tabling attributes",
parse_tabling_attribute(AttrContextPieces, TabledMethod0),
VarSet, AttrsListTerm, MaybeAttributeList),
(
MaybeAttributeList = ok1(AttributeList),
update_tabling_attributes(AttributeList,
default_memo_table_attributes, Attributes,
[], DuplicateSpecs),
(
DuplicateSpecs = [],
DisableWarning =
Attributes ^ table_attr_backend_warning,
(
DisableWarning = table_attr_ignore_with_warning,
TabledMethod = TabledMethod0
;
DisableWarning = table_attr_ignore_without_warning,
(
TabledMethod0 = tabled_memo(_),
TabledMethod = tabled_memo(
table_attr_ignore_without_warning)
;
( TabledMethod0 = tabled_loop_check
; TabledMethod0 = tabled_minimal(_)
),
TabledMethod = TabledMethod0
;
TabledMethod0 = tabled_io(_, _),
unexpected($pred, "non-pragma eval method")
)
),
Tabled = impl_pragma_tabled_info(TabledMethod,
PredOrProcSpec, yes(Attributes), Context, SeqNum),
ImplPragma = impl_pragma_tabled(Tabled),
Item = item_impl_pragma(ImplPragma),
MaybeIOM = ok1(iom_item(Item))
;
DuplicateSpecs = [_ | _],
MaybeIOM = error1(DuplicateSpecs)
)
;
MaybeAttributeList = error1(Specs),
MaybeIOM = error1(Specs)
)
)
;
MaybePredOrProcSpec = error1(Specs),
MaybeIOM = error1(Specs)
)
;
( PragmaTerms = []
; PragmaTerms = [_, _, _ | _]
),
Pieces = [words("Error: a"), pragma_decl(PragmaName),
words("declaration must have one or two arguments."), nl],
Spec = simplest_spec($pred, severity_error, phase_term_to_parse_tree,
get_term_context(ErrorTerm), Pieces),
MaybeIOM = error1([Spec])
).
%---------------------------------------------------------------------------%
:- pred parse_tabling_attribute(cord(format_piece)::in,
tabled_eval_method::in, varset::in, term::in,
maybe1(pair(term.context, single_tabling_attribute))::out) is det.
parse_tabling_attribute(ContextPieces, TabledMethod, VarSet, Term,
MaybeContextAttribute) :-
( if
Term = term.functor(term.atom(Functor), ArgTerms, Context),
( Functor = "fast_loose"
; Functor = "specified"
; Functor = "size_limit"
; Functor = "statistics"
; Functor = "allow_reset"
; Functor = "disable_warning_if_ignored"
)
then
(
Functor = "fast_loose",
parse_tabling_attr_fast_loose(ContextPieces, TabledMethod,
VarSet, Context, ArgTerms, MaybeContextAttribute)
;
Functor = "specified",
parse_tabling_attr_specified(ContextPieces, TabledMethod,
VarSet, Context, ArgTerms, MaybeContextAttribute)
;
Functor = "size_limit",
parse_tabling_attr_size_limit(ContextPieces, TabledMethod,
VarSet, Context, ArgTerms, MaybeContextAttribute)
;
Functor = "statistics",
parse_tabling_attr_statistics(ContextPieces, TabledMethod,
VarSet, Context, ArgTerms, MaybeContextAttribute)
;
Functor = "allow_reset",
parse_tabling_attr_allow_reset(ContextPieces, TabledMethod,
VarSet, Context, ArgTerms, MaybeContextAttribute)
;
Functor = "disable_warning_if_ignored",
parse_tabling_attr_backend_warning(ContextPieces, TabledMethod,
VarSet, Context, ArgTerms, MaybeContextAttribute)
)
else
TermStr = describe_error_term(VarSet, Term),
Pieces = cord.list(ContextPieces) ++ [lower_case_next_if_not_first,
words("Error: expected one of"),
quote("fast_loose"), suffix(","),
quote("specified(...)"), suffix(","),
quote("size_limit(...)"), suffix(","),
quote("statistics"), suffix(","),
quote("allow_reset"), suffix(","), words("and"),
quote("disable_warning_if_ignored"), suffix(","),
words("got"), quote(TermStr), suffix("."), nl],
Spec = simplest_spec($pred, severity_error, phase_term_to_parse_tree,
get_term_context(Term), Pieces),
MaybeContextAttribute = error1([Spec])
).
%---------------------%
:- pred parse_tabling_attr_fast_loose(cord(format_piece)::in,
tabled_eval_method::in, varset::in, term.context::in, list(term)::in,
maybe1(pair(term.context, single_tabling_attribute))::out) is det.
parse_tabling_attr_fast_loose(ContextPieces, TabledMethod, _VarSet,
Context, ArgTerms, MaybeContextAttribute) :-
(
ArgTerms = [],
require_tabling_fast_loose(ContextPieces, TabledMethod, Context,
FastLooseSpecs),
(
FastLooseSpecs = [],
Attribute = attr_strictness(cts_all_fast_loose),
MaybeContextAttribute = ok1(Context - Attribute)
;
FastLooseSpecs = [_ | _],
MaybeContextAttribute = error1(FastLooseSpecs)
)
;
ArgTerms = [_ | _],
Pieces = cord.list(ContextPieces) ++ [lower_case_next_if_not_first,
words("Error: fast_loose"),
words("must have no arguments."), nl],
Spec = simplest_spec($pred, severity_error, phase_term_to_parse_tree,
Context, Pieces),
MaybeContextAttribute = error1([Spec])
).
%---------------------%
:- pred parse_tabling_attr_specified(cord(format_piece)::in,
tabled_eval_method::in, varset::in, term.context::in, list(term)::in,
maybe1(pair(term.context, single_tabling_attribute))::out) is det.
parse_tabling_attr_specified(ContextPieces, TabledMethod, VarSet,
Context, ArgTerms, MaybeContextAttribute) :-
(
(
ArgTerms = [MethodsTerm],
MaybeHiddenArg = ok1(table_hidden_arg_value)
;
ArgTerms = [MethodsTerm, HiddenArgTerm],
( if
HiddenArgTerm = term.functor(
term.atom("hidden_arg_value"), [], _)
then
MaybeHiddenArg = ok1(table_hidden_arg_value)
else if
HiddenArgTerm = term.functor(
term.atom("hidden_arg_addr"), [], _)
then
MaybeHiddenArg = ok1(table_hidden_arg_addr)
else
HiddenArgTermStr = describe_error_term(VarSet, HiddenArgTerm),
HiddenArgPieces = cord.list(ContextPieces) ++
[lower_case_next_if_not_first,
words("In the second argument of specified:"), nl,
words("error: expected either"),
quote("hidden_arg_value"), words("or"),
quote("hidden_arg_addr"), suffix(","),
words("got"), quote(HiddenArgTermStr), suffix("."), nl],
HiddenArgSpec = simplest_spec($pred, severity_error,
phase_term_to_parse_tree,
get_term_context(HiddenArgTerm), HiddenArgPieces),
MaybeHiddenArg = error1([HiddenArgSpec])
)
),
MethodsContextPieces = ContextPieces ++
cord.from_list([lower_case_next_if_not_first,
words("In the first argument of specified:"), nl]),
parse_list_elements("argument tabling methods",
parse_arg_tabling_method(MethodsContextPieces),
VarSet, MethodsTerm, MaybeMaybeArgMethods),
require_tabling_fast_loose(ContextPieces, TabledMethod, Context,
FastLooseSpecs),
( if
MaybeMaybeArgMethods = ok1(MaybeArgMethods),
MaybeHiddenArg = ok1(HiddenArg),
FastLooseSpecs = []
then
Attribute = attr_strictness(
cts_specified(MaybeArgMethods, HiddenArg)),
MaybeContextAttribute = ok1(Context - Attribute)
else
Specs = get_any_errors1(MaybeMaybeArgMethods) ++
get_any_errors1(MaybeHiddenArg) ++
FastLooseSpecs,
MaybeContextAttribute = error1(Specs)
)
;
( ArgTerms = []
; ArgTerms = [_, _, _ | _]
),
Pieces = cord.list(ContextPieces) ++ [lower_case_next_if_not_first,
words("Error: specified must have one or two arguments."), nl],
Spec = simplest_spec($pred, severity_error, phase_term_to_parse_tree,
Context, Pieces),
MaybeContextAttribute = error1([Spec])
).
:- pred parse_arg_tabling_method(cord(format_piece)::in,
varset::in, term::in, maybe1(maybe(arg_tabling_method))::out) is det.
parse_arg_tabling_method(ContextPieces, VarSet, Term,
MaybeMaybeArgTablingMethod) :-
( if
Term = term.functor(term.atom(Functor), [], _),
(
Functor = "value",
MaybeArgTablingMethod = yes(arg_value)
;
Functor = "addr",
MaybeArgTablingMethod = yes(arg_addr)
;
Functor = "promise_implied",
MaybeArgTablingMethod = yes(arg_promise_implied)
;
Functor = "output",
MaybeArgTablingMethod = no
)
then
MaybeMaybeArgTablingMethod = ok1(MaybeArgTablingMethod)
else
TermStr = describe_error_term(VarSet, Term),
Pieces = cord.list(ContextPieces) ++ [lower_case_next_if_not_first,
words("Error: expected one of"),
quote("value"), suffix(","),
quote("addr"), suffix(","),
quote("promise_implied"), suffix(","), words("and"),
quote("output"), suffix(","),
words("got"), quote(TermStr), suffix("."), nl],
Spec = simplest_spec($pred, severity_error, phase_term_to_parse_tree,
get_term_context(Term), Pieces),
MaybeMaybeArgTablingMethod = error1([Spec])
).
%---------------------%
:- pred parse_tabling_attr_size_limit(cord(format_piece)::in,
tabled_eval_method::in, varset::in, term.context::in, list(term)::in,
maybe1(pair(term.context, single_tabling_attribute))::out) is det.
parse_tabling_attr_size_limit(ContextPieces, TabledMethod, VarSet,
Context, ArgTerms, MaybeContextAttribute) :-
(
ArgTerms = [LimitTerm],
LimitContextPieces = ContextPieces ++ cord.from_list(
[lower_case_next_if_not_first,
words("In the first argument of size_limit:"), nl]),
parse_decimal_int(LimitContextPieces, VarSet, LimitTerm, MaybeLimit),
AllowsSizeLimit = eval_method_allows_size_limit(TabledMethod),
(
AllowsSizeLimit = yes,
AllowSpecs = []
;
AllowsSizeLimit = no,
AllowPieces = cord.list(ContextPieces) ++
[lower_case_next_if_not_first,
words("Error: evaluation method"),
fixed(tabled_eval_method_to_string(TabledMethod)),
words("does not allow size limits."), nl],
AllowSpec = simplest_spec($pred, severity_error,
phase_term_to_parse_tree, Context, AllowPieces),
AllowSpecs = [AllowSpec]
),
( if
MaybeLimit = ok1(Limit),
AllowSpecs = []
then
Attribute = attr_size_limit(Limit),
MaybeContextAttribute = ok1(Context - Attribute)
else
Specs = get_any_errors1(MaybeLimit) ++ AllowSpecs,
MaybeContextAttribute = error1(Specs)
)
;
( ArgTerms = []
; ArgTerms = [_, _ | _]
),
Pieces = cord.list(ContextPieces) ++ [lower_case_next_if_not_first,
words("Error: size_limit must have one argument."), nl],
Spec = simplest_spec($pred, severity_error, phase_term_to_parse_tree,
Context, Pieces),
MaybeContextAttribute = error1([Spec])
).
%---------------------%
:- pred parse_tabling_attr_statistics(cord(format_piece)::in,
tabled_eval_method::in, varset::in, term.context::in, list(term)::in,
maybe1(pair(term.context, single_tabling_attribute))::out) is det.
parse_tabling_attr_statistics(ContextPieces, _TabledMethod, _VarSet,
Context, ArgTerms, MaybeContextAttribute) :-
(
ArgTerms = [],
Attribute = attr_statistics,
MaybeContextAttribute = ok1(Context - Attribute)
;
ArgTerms = [_ | _],
Pieces = cord.list(ContextPieces) ++ [lower_case_next_if_not_first,
words("Error: statistics must have no arguments."), nl],
Spec = simplest_spec($pred, severity_error, phase_term_to_parse_tree,
Context, Pieces),
MaybeContextAttribute = error1([Spec])
).
%---------------------%
:- pred parse_tabling_attr_allow_reset(cord(format_piece)::in,
tabled_eval_method::in, varset::in, term.context::in, list(term)::in,
maybe1(pair(term.context, single_tabling_attribute))::out) is det.
parse_tabling_attr_allow_reset(ContextPieces, _TabledMethod, _VarSet,
Context, ArgTerms, MaybeContextAttribute) :-
(
ArgTerms = [],
Attribute = attr_allow_reset,
MaybeContextAttribute = ok1(Context - Attribute)
;
ArgTerms = [_ | _],
Pieces = cord.list(ContextPieces) ++ [lower_case_next_if_not_first,
words("Error: allow_reset must have no arguments."), nl],
Spec = simplest_spec($pred, severity_error, phase_term_to_parse_tree,
Context, Pieces),
MaybeContextAttribute = error1([Spec])
).
%---------------------%
:- pred parse_tabling_attr_backend_warning(cord(format_piece)::in,
tabled_eval_method::in, varset::in, term.context::in, list(term)::in,
maybe1(pair(term.context, single_tabling_attribute))::out) is det.
parse_tabling_attr_backend_warning(ContextPieces, TabledMethod, _VarSet,
Context, ArgTerms, MaybeContextAttribute) :-
(
ArgTerms = [],
AllowsDisableWarning =
eval_method_allows_disable_warning_if_ignored(TabledMethod),
(
AllowsDisableWarning = yes,
Attribute = attr_ignore_without_warning,
MaybeContextAttribute = ok1(Context - Attribute)
;
AllowsDisableWarning = no,
Pieces = cord.list(ContextPieces) ++ [lower_case_next_if_not_first,
words("Error: evaluation method"),
fixed(tabled_eval_method_to_string(TabledMethod)),
words("does not allow disable_warning_if_ignored."), nl],
Spec = simplest_spec($pred, severity_error,
phase_term_to_parse_tree, Context, Pieces),
MaybeContextAttribute = error1([Spec])
)
;
ArgTerms = [_ | _],
Pieces = cord.list(ContextPieces) ++ [lower_case_next_if_not_first,
words("Error: allow_reset must have no arguments."), nl],
Spec = simplest_spec($pred, severity_error, phase_term_to_parse_tree,
Context, Pieces),
MaybeContextAttribute = error1([Spec])
).
%---------------------------------------------------------------------------%
:- pred require_tabling_fast_loose(cord(format_piece)::in,
tabled_eval_method::in, term.context::in, list(error_spec)::out) is det.
require_tabling_fast_loose(ContextPieces, TabledMethod, Context, Specs) :-
AllowsFastLoose = eval_method_allows_fast_loose(TabledMethod),
(
AllowsFastLoose = yes,
Specs = []
;
AllowsFastLoose = no,
Pieces = cord.list(ContextPieces) ++ [lower_case_next_if_not_first,
words("Error: evaluation method"),
fixed(tabled_eval_method_to_string(TabledMethod)),
words("does not allow fast_loose tabling."), nl],
Spec = simplest_spec($pred, severity_error,
phase_term_to_parse_tree, Context, Pieces),
Specs = [Spec]
).
%---------------------------------------------------------------------------%
:- func eval_method_allows_fast_loose(tabled_eval_method) = bool.
eval_method_allows_fast_loose(tabled_loop_check) = yes.
eval_method_allows_fast_loose(tabled_memo(_)) = yes.
eval_method_allows_fast_loose(tabled_io(_, _)) = no.
eval_method_allows_fast_loose(tabled_minimal(_)) = no.
:- func eval_method_allows_size_limit(tabled_eval_method) = bool.
eval_method_allows_size_limit(tabled_loop_check) = yes.
eval_method_allows_size_limit(tabled_memo(_)) = yes.
eval_method_allows_size_limit(tabled_io(_, _)) = no.
eval_method_allows_size_limit(tabled_minimal(_)) = no.
:- func eval_method_allows_disable_warning_if_ignored(tabled_eval_method)
= bool.
eval_method_allows_disable_warning_if_ignored(tabled_loop_check) = no.
eval_method_allows_disable_warning_if_ignored(tabled_memo(_)) = yes.
eval_method_allows_disable_warning_if_ignored(tabled_io(_, _)) = no.
eval_method_allows_disable_warning_if_ignored(tabled_minimal(_)) = no.
%---------------------------------------------------------------------------%
:- type single_tabling_attribute
---> attr_strictness(call_table_strictness)
; attr_size_limit(int)
; attr_statistics
; attr_allow_reset
; attr_ignore_without_warning.
:- pred update_tabling_attributes(
assoc_list(term.context, single_tabling_attribute)::in,
table_attributes::in, table_attributes::out,
list(error_spec)::in, list(error_spec)::out) is det.
update_tabling_attributes([], !Attributes, !Specs).
update_tabling_attributes([Context - Attr | ContextAttrs],
!Attributes, !Specs) :-
(
Attr = attr_strictness(Strictness),
( if !.Attributes ^ table_attr_strictness = cts_all_strict then
!Attributes ^ table_attr_strictness := Strictness
else
Pieces = [words("Error: duplicate argument tabling methods"),
words("attribute in"), pragma_decl("memo"),
words("declaration."), nl],
Spec = simplest_spec($pred, severity_error,
phase_term_to_parse_tree, Context, Pieces),
!:Specs = [Spec | !.Specs]
)
;
Attr = attr_size_limit(Limit),
( if !.Attributes ^ table_attr_size_limit = no then
!Attributes ^ table_attr_size_limit := yes(Limit)
else
Pieces = [words("Error: duplicate size limits attribute in"),
pragma_decl("memo"), words("declaration."), nl],
Spec = simplest_spec($pred, severity_error,
phase_term_to_parse_tree, Context, Pieces),
!:Specs = [Spec | !.Specs]
)
;
Attr = attr_statistics,
( if
!.Attributes ^ table_attr_statistics = table_dont_gather_statistics
then
!Attributes ^ table_attr_statistics := table_gather_statistics
else
Pieces = [words("Error: duplicate statistics attribute in"),
pragma_decl("memo"), words("declaration."), nl],
Spec = simplest_spec($pred, severity_error,
phase_term_to_parse_tree, Context, Pieces),
!:Specs = [Spec | !.Specs]
)
;
Attr = attr_allow_reset,
( if
!.Attributes ^ table_attr_allow_reset = table_dont_allow_reset
then
!Attributes ^ table_attr_allow_reset := table_allow_reset
else
Pieces = [words("Error: duplicate allow_reset attribute in"),
pragma_decl("memo"), words("declaration."), nl],
Spec = simplest_spec($pred, severity_error,
phase_term_to_parse_tree, Context, Pieces),
!:Specs = [Spec | !.Specs]
)
;
Attr = attr_ignore_without_warning,
( if
!.Attributes ^ table_attr_backend_warning =
table_attr_ignore_with_warning
then
!Attributes ^ table_attr_backend_warning :=
table_attr_ignore_without_warning
else
Pieces = [words("Error: duplicate disable_warning_if_ignored"),
words("attribute in"),
pragma_decl("memo"), words("declaration."), nl],
Spec = simplest_spec($pred, severity_error,
phase_term_to_parse_tree, Context, Pieces),
!:Specs = [Spec | !.Specs]
)
),
update_tabling_attributes(ContextAttrs, !Attributes, !Specs).
%---------------------------------------------------------------------------%
:- end_module parse_tree.parse_pragma_tabling.
%---------------------------------------------------------------------------%