mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-17 14:57:03 +00:00
362 lines
14 KiB
Mathematica
362 lines
14 KiB
Mathematica
%---------------------------------------------------------------------------%
|
|
% vim: ft=mercury ts=4 sw=4 et
|
|
%---------------------------------------------------------------------------%
|
|
% Copyright (C) 2016 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.
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
% This module defines predicates that parse lists of variables.
|
|
%
|
|
%---------------------------------------------------------------------------%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- module parse_tree.parse_vars.
|
|
:- interface.
|
|
|
|
:- import_module parse_tree.error_util.
|
|
:- import_module parse_tree.maybe_error.
|
|
|
|
:- import_module cord.
|
|
:- import_module list.
|
|
:- import_module term.
|
|
:- import_module varset.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
% parse_possibly_repeated_vars(Term, VarSet, ContextPieces, MaybeVars):
|
|
%
|
|
% Parse Term as a list of quantified variables Vars. If successful,
|
|
% return ok1(Vars). If not, return an error message that has
|
|
% ContextPieces as a prefix.
|
|
%
|
|
:- pred parse_possibly_repeated_vars(term(T)::in, varset(T)::in,
|
|
cord(format_component)::in, maybe1(list(var(T)))::out) is det.
|
|
|
|
% parse_vars(Term, VarSet, ContextPieces, MaybeVars):
|
|
%
|
|
% The same as parse_possibly_repeated_vars, but generate an error
|
|
% if a variable is in the list more than once.
|
|
%
|
|
:- pred parse_vars(term(T)::in, varset(T)::in,
|
|
cord(format_component)::in, maybe1(list(var(T)))::out) is det.
|
|
|
|
:- type plain_state_vars(T)
|
|
---> plain_state_vars(
|
|
list(var(T)), % plain variables
|
|
list(var(T)) % !V state variables
|
|
).
|
|
|
|
% parse_vars_state_vars(Term, VarSet, ContextPieces, MaybeVars):
|
|
%
|
|
% The same as parse_vars, but parse not just ordinary variables V,
|
|
% but also state variables !SV.
|
|
%
|
|
:- pred parse_vars_state_vars(term(T)::in, varset(T)::in,
|
|
cord(format_component)::in, maybe1(plain_state_vars(T))::out) is det.
|
|
|
|
:- type plain_state_dot_colon_vars(T)
|
|
---> plain_state_dot_colon_vars(
|
|
list(var(T)), % plain variables
|
|
list(var(T)), % !V state variables
|
|
list(var(T)), % !.V state variables
|
|
list(var(T)) % !:V state variables
|
|
).
|
|
|
|
% parse_vars_state_dot_colon_vars(Term, VarSet, ContextPieces, MaybeVars):
|
|
%
|
|
% The same as parse_vars, but parse not just ordinary variables V,
|
|
% but also state variables !SV, !.SV and !:SV.
|
|
%
|
|
:- pred parse_vars_state_dot_colon_vars(term(T)::in, varset(T)::in,
|
|
cord(format_component)::in, maybe1(plain_state_dot_colon_vars(T))::out)
|
|
is det.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
:- import_module parse_tree.parse_tree_out_term.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
parse_possibly_repeated_vars(Term, VarSet, ContextPieces, MaybeVars) :-
|
|
( if Term = term.functor(term.atom("[]"), [], _) then
|
|
MaybeVars = ok1([])
|
|
else if Term = term.functor(term.atom("[|]"), [HeadTerm, TailTerm], _) then
|
|
(
|
|
HeadTerm = term.variable(HeadVar0, _),
|
|
MaybeHeadVar = ok1(HeadVar0)
|
|
;
|
|
HeadTerm = term.functor(_, _, _),
|
|
generate_unexpected_term_message(ContextPieces, VarSet,
|
|
"a variable", HeadTerm, Spec),
|
|
MaybeHeadVar = error1([Spec])
|
|
),
|
|
parse_possibly_repeated_vars(TailTerm, VarSet, ContextPieces,
|
|
MaybeTailVars),
|
|
( if
|
|
MaybeHeadVar = ok1(HeadVar),
|
|
MaybeTailVars = ok1(TailVars)
|
|
then
|
|
MaybeVars = ok1([HeadVar | TailVars])
|
|
else
|
|
Specs = get_any_errors1(MaybeHeadVar) ++
|
|
get_any_errors1(MaybeTailVars),
|
|
MaybeVars = error1(Specs)
|
|
)
|
|
else
|
|
generate_unexpected_term_message(ContextPieces, VarSet,
|
|
"a list of variables", Term, Spec),
|
|
MaybeVars = error1([Spec])
|
|
).
|
|
|
|
parse_vars(Term, VarSet, ContextPieces, MaybeVars) :-
|
|
( if Term = functor(atom("[]"), [], _) then
|
|
MaybeVars = ok1([])
|
|
else if Term = functor(atom("[|]"), [HeadTerm, TailTerm], _) then
|
|
(
|
|
HeadTerm = variable(HeadVar0, _),
|
|
MaybeHeadVar = ok1(HeadVar0)
|
|
;
|
|
HeadTerm = functor(_, _, _),
|
|
generate_unexpected_term_message(ContextPieces, VarSet,
|
|
"a variable", HeadTerm, HeadSpec),
|
|
MaybeHeadVar = error1([HeadSpec])
|
|
),
|
|
parse_vars(TailTerm, VarSet, ContextPieces, MaybeTailVars),
|
|
( if
|
|
MaybeHeadVar = ok1(HeadVar),
|
|
MaybeTailVars = ok1(TailVars)
|
|
then
|
|
( if list.member(HeadVar, TailVars) then
|
|
generate_repeated_var_msg(ContextPieces, VarSet,
|
|
HeadTerm, Spec),
|
|
MaybeVars = error1([Spec])
|
|
else
|
|
Vars = [HeadVar | TailVars],
|
|
MaybeVars = ok1(Vars)
|
|
)
|
|
else
|
|
Specs = get_any_errors1(MaybeHeadVar) ++
|
|
get_any_errors1(MaybeTailVars),
|
|
MaybeVars = error1(Specs)
|
|
)
|
|
else
|
|
generate_unexpected_term_message(ContextPieces, VarSet,
|
|
"a list of variables", Term, Spec),
|
|
MaybeVars = error1([Spec])
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- type ordinary_state_var(T)
|
|
---> os_ordinary_var(var(T))
|
|
; os_state_var(var(T)).
|
|
|
|
parse_vars_state_vars(Term, VarSet, ContextPieces, MaybeVars) :-
|
|
( if Term = functor(atom("[]"), [], _) then
|
|
MaybeVars = ok1(plain_state_vars([], []))
|
|
else if Term = functor(atom("[|]"), [HeadTerm, TailTerm], _) then
|
|
( if
|
|
(
|
|
HeadTerm = variable(V0, _),
|
|
VarKind0 = os_ordinary_var(V0)
|
|
;
|
|
HeadTerm = functor(atom("!"), [variable(SV0, _)], _),
|
|
VarKind0 = os_state_var(SV0)
|
|
)
|
|
then
|
|
MaybeHeadVar = ok1(VarKind0)
|
|
else
|
|
generate_unexpected_term_message(ContextPieces, VarSet,
|
|
"a variable or state variable", HeadTerm, HeadSpec),
|
|
MaybeHeadVar = error1([HeadSpec])
|
|
),
|
|
parse_vars_state_vars(TailTerm, VarSet, ContextPieces, MaybeTailVars),
|
|
( if
|
|
MaybeHeadVar = ok1(VarKind),
|
|
MaybeTailVars = ok1(plain_state_vars(TailVars, TailStateVars))
|
|
then
|
|
(
|
|
VarKind = os_ordinary_var(V),
|
|
( if list.member(V, TailVars) then
|
|
generate_repeated_var_msg(ContextPieces, VarSet,
|
|
HeadTerm, Spec),
|
|
MaybeVars = error1([Spec])
|
|
else
|
|
Vars = [V | TailVars],
|
|
MaybeVars = ok1(plain_state_vars(Vars, TailStateVars))
|
|
)
|
|
;
|
|
VarKind = os_state_var(SV),
|
|
( if list.member(SV, TailStateVars) then
|
|
generate_repeated_state_var_msg(ContextPieces, VarSet,
|
|
HeadTerm, Spec),
|
|
MaybeVars = error1([Spec])
|
|
else
|
|
StateVars = [SV | TailStateVars],
|
|
MaybeVars = ok1(plain_state_vars(TailVars, StateVars))
|
|
)
|
|
)
|
|
else
|
|
Specs = get_any_errors1(MaybeHeadVar) ++
|
|
get_any_errors1(MaybeTailVars),
|
|
MaybeVars = error1(Specs)
|
|
)
|
|
else
|
|
generate_unexpected_term_message(ContextPieces, VarSet,
|
|
"a list of variables and/or state variables", Term, Spec),
|
|
MaybeVars = error1([Spec])
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- type ordinary_state_dot_colon_var(T)
|
|
---> osdc_ordinary_var(var(T))
|
|
; osdc_state_var(var(T))
|
|
; osdc_dot_var(var(T))
|
|
; osdc_colon_var(var(T)).
|
|
|
|
parse_vars_state_dot_colon_vars(Term, VarSet, ContextPieces, MaybeVars) :-
|
|
( if Term = functor(atom("[]"), [], _) then
|
|
MaybeVars = ok1(plain_state_dot_colon_vars([], [], [], []))
|
|
else if Term = functor(atom("[|]"), [HeadTerm, Tail], _) then
|
|
( if
|
|
(
|
|
HeadTerm = variable(V0, _),
|
|
VarKind0 = osdc_ordinary_var(V0)
|
|
;
|
|
HeadTerm = functor(atom("!"), [variable(SV0, _)], _),
|
|
VarKind0 = osdc_state_var(SV0)
|
|
;
|
|
HeadTerm = functor(atom("!."), [variable(SV0, _)], _),
|
|
VarKind0 = osdc_dot_var(SV0)
|
|
;
|
|
HeadTerm = functor(atom("!:"), [variable(SV0, _)], _),
|
|
VarKind0 = osdc_colon_var(SV0)
|
|
)
|
|
then
|
|
MaybeHeadVar = ok1(VarKind0)
|
|
else
|
|
generate_unexpected_term_message(ContextPieces, VarSet,
|
|
"a variable or state variable", HeadTerm, HeadSpec),
|
|
MaybeHeadVar = error1([HeadSpec])
|
|
),
|
|
parse_vars_state_dot_colon_vars(Tail, VarSet, ContextPieces,
|
|
MaybeTailVars),
|
|
( if
|
|
MaybeHeadVar = ok1(VarKind),
|
|
MaybeTailVars = ok1(plain_state_dot_colon_vars(TailVars,
|
|
TailStateVars, TailDotVars, TailColonVars))
|
|
then
|
|
(
|
|
VarKind = osdc_ordinary_var(V),
|
|
( if list.member(V, TailVars) then
|
|
generate_repeated_var_msg(ContextPieces, VarSet,
|
|
HeadTerm, Spec),
|
|
MaybeVars = error1([Spec])
|
|
else
|
|
Vars = [V | TailVars],
|
|
MaybeVars = ok1(plain_state_dot_colon_vars(Vars,
|
|
TailStateVars, TailDotVars, TailColonVars))
|
|
)
|
|
;
|
|
VarKind = osdc_state_var(SV),
|
|
( if
|
|
( list.member(SV, TailStateVars )
|
|
; list.member(SV, TailDotVars )
|
|
; list.member(SV, TailColonVars )
|
|
)
|
|
then
|
|
generate_repeated_var_msg(ContextPieces, VarSet,
|
|
HeadTerm, Spec),
|
|
MaybeVars = error1([Spec])
|
|
else
|
|
StateVars = [SV | TailStateVars],
|
|
MaybeVars = ok1(plain_state_dot_colon_vars(TailVars,
|
|
StateVars, TailDotVars, TailColonVars))
|
|
)
|
|
;
|
|
VarKind = osdc_dot_var(SV),
|
|
( if
|
|
( list.member(SV, TailStateVars )
|
|
; list.member(SV, TailDotVars )
|
|
; list.member(SV, TailColonVars )
|
|
)
|
|
then
|
|
generate_repeated_var_msg(ContextPieces, VarSet,
|
|
HeadTerm, Spec),
|
|
MaybeVars = error1([Spec])
|
|
else
|
|
DotVars = [SV | TailDotVars],
|
|
MaybeVars = ok1(plain_state_dot_colon_vars(TailVars,
|
|
TailStateVars, DotVars, TailColonVars))
|
|
)
|
|
;
|
|
VarKind = osdc_colon_var(SV),
|
|
( if
|
|
( list.member(SV, TailStateVars )
|
|
; list.member(SV, TailDotVars )
|
|
; list.member(SV, TailColonVars )
|
|
)
|
|
then
|
|
generate_repeated_var_msg(ContextPieces, VarSet,
|
|
HeadTerm, Spec),
|
|
MaybeVars = error1([Spec])
|
|
else
|
|
ColonVars = [SV | TailColonVars],
|
|
MaybeVars = ok1(plain_state_dot_colon_vars(TailVars,
|
|
TailStateVars, TailDotVars, ColonVars))
|
|
)
|
|
)
|
|
else
|
|
HeadSpecs = get_any_errors1(MaybeHeadVar),
|
|
TailSpecs = get_any_errors1(MaybeTailVars),
|
|
MaybeVars = error1(HeadSpecs ++ TailSpecs)
|
|
)
|
|
else
|
|
generate_unexpected_term_message(ContextPieces, VarSet,
|
|
"a list of variables and/or state variables", Term, Spec),
|
|
MaybeVars = error1([Spec])
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred generate_repeated_var_msg(cord(format_component)::in,
|
|
varset(T)::in, term(T)::in, error_spec::out) is det.
|
|
|
|
generate_repeated_var_msg(ContextPieces, VarSet, Term, Spec) :-
|
|
TermStr = describe_error_term(VarSet, Term),
|
|
Pieces = cord.list(ContextPieces) ++ [lower_case_next_if_not_first,
|
|
words("Repeated variable"), words(TermStr), suffix("."), nl],
|
|
Spec = simplest_spec(severity_error, phase_term_to_parse_tree,
|
|
get_term_context(Term), Pieces).
|
|
|
|
:- pred generate_repeated_state_var_msg(cord(format_component)::in,
|
|
varset(T)::in, term(T)::in, error_spec::out) is det.
|
|
|
|
generate_repeated_state_var_msg(ContextPieces, VarSet, Term, Spec) :-
|
|
TermStr = describe_error_term(VarSet, Term),
|
|
Pieces = cord.list(ContextPieces) ++ [lower_case_next_if_not_first,
|
|
words("Repeated state variable"), words(TermStr), suffix("."), nl],
|
|
Spec = simplest_spec(severity_error, phase_term_to_parse_tree,
|
|
get_term_context(Term), Pieces).
|
|
|
|
:- pred generate_unexpected_term_message(cord(format_component)::in,
|
|
varset(T)::in, string::in, term(T)::in, error_spec::out) is det.
|
|
|
|
generate_unexpected_term_message(ContextPieces, VarSet, Expected, Term,
|
|
Spec) :-
|
|
TermStr = describe_error_term(VarSet, Term),
|
|
Pieces = cord.list(ContextPieces) ++ [lower_case_next_if_not_first,
|
|
words("Expected"), words(Expected), suffix(","),
|
|
words("got"), quote(TermStr), suffix("."), nl],
|
|
Spec = simplest_spec(severity_error, phase_term_to_parse_tree,
|
|
get_term_context(Term), Pieces).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
:- end_module parse_tree.parse_vars.
|
|
%---------------------------------------------------------------------------%
|