[m-rev.] For review: State Variables
Ralph Becket
rafe at cs.mu.OZ.AU
Tue Jun 25 17:08:12 AEST 2002
On 11-Jun-2002, Simon Taylor wrote:
> On 07-Jun-2002, Ralph Becket <rafe at cs.mu.OZ.AU> wrote:
> > Index: make_hlds.m
> > ===================================================================
> > @@ -16,6 +16,9 @@
> > % super-homogenous form, and introduce implicit quantification.
> > %
> > % XXX we should record each error using module_info_incr_errors.
> > +%
> > +% XXX For state variables, we should allow quantifiers around if-then-else
> > +% expressions.
>
> Just to be clear, this needs to be done immediately.
Fixed.
The syntax was not documented. I've added docs to "Conditional
Expressions" in "Data terms" in the reference manual:
reference_manual.texi:
@@ -1121,6 +1325,9 @@
both data-terms. The semantics of a conditional expression is that
if @var{Goal} is true, then the expression has the meaning of
@var{Expression1}, else the expression has the meaning of @var{Expression2}.
+
+If @var{Goal} takes the form @code{some [X, Y, Z] ...} then the scope of
+ at var{X}, @var{Y}, and @var{Z} includes @var{Expression1}.
For reference, the accepted syntax is
if ( some [X] P ) then Q else R
where the scope of X includes Q.
> > @@ -6901,7 +7058,17 @@
> > % that each unification gets reduced to superhomogeneous form.
> > % It also gets passed a `arg_context', which indicates
> > % where the terms came from.
> > +
> > % We never insert unifications of the form X = X.
> > + % If ForPragmaC is yes, we process unifications of the form
> > + % X = Y by substituting the var expected by the outside environment
> > + % (the head variable) for the variable inside the goal (which was
> > + % created just for the pragma_c_code goal), while giving the headvar
> > + % the name of the just eliminated variable. The result will be
> > + % a proc_info in which the head variables have meaningful names
> > + % and the body goal is just a pragma C code. Without this special
> > + % treatment, the body goal will be a conjunction, which would
> > + % complicate the handling of code generation for nondet pragma C codes.
> >
> > :- type arg_context
> > --->
> > @@ -6919,80 +7086,89 @@
> > ).
> >
> > :- pred insert_arg_unifications(list(prog_var), list(prog_term),
> > - prog_context, arg_context, hlds_goal, prog_varset,
> > + prog_context, arg_context, bool, hlds_goal, prog_varset,
> > hlds_goal, prog_varset, transform_info, transform_info,
> > - io__state, io__state).
> > -:- mode insert_arg_unifications(in, in, in, in, in, in, out,
> > - out, in, out, di, uo) is det.
> > + svar_info, svar_info, io__state, io__state).
> > +:- mode insert_arg_unifications(in, in, in, in, in, in, in, out,
> > + out, in, out, in, out, di, uo) is det.
>
> This undoes a change I committed last week. Please go over your diff
> thoroughly to make sure there are no other stray changes.
Fixed.
> > @@ -7217,22 +7443,25 @@
> > % NewVar3 = A3.
> > % In the trivial case `X = c', no unravelling occurs.
> >
> > -unravel_unification(term__variable(X), RHS,
> > - Context, MainContext, SubContext, VarSet0, Purity,
> > - Goal, VarSet, Info0, Info) -->
> > - { RHS = term__functor(F, Args, FunctorContext) },
> > +unravel_unification_2(term__variable(X), RHS,
> > + Context, MainContext, SubContext, VarSet0, Purity,
> > + Goal, VarSet, Info0, Info, SInfo0, SInfo) -->
> > + { RHS = term__functor(F, Args0, FunctorContext) },
> > + { Args1 = expand_bang_state_var_args(Args0) },
>
> You're still not doing this consistently. For example, !X is not
> expanded in `aditi_insert(p(!X), DB, DB)' or `X ^ field(!X) := Value'.
It might be better to expand !X only in predicate clause heads and
predicate calls (!X doesn't really make sense in function calls).
Good point. Done and documented:
reference_manual.texi:
+There are three restrictions concerning state variables in lambdas: first,
+ at samp{!@var{X}} is not a legitimate function result, since it stands for two
+arguments, rather than one; second, @samp{!@var{X}} may not appear as a
+parameter term in the head of a lambda since there is no syntax for specifying
+the modes of the two implied parameters; third, @samp{!@var{X}} may not appear
+as an argument in a function application since this would not make sense given
+the usual interpretation of state variables and functions.
> > +:- func reconciled_svar_infos_dots(prog_varset, svar_info, svar, svar_info) =
> > + svar_info.
> > +
> > +reconciled_svar_infos_dots(VarSet, SInfoX, StateVar, SInfo0) = SInfo :-
> > + ( if
> > + DotX = SInfoX ^ dot ^ elem(StateVar),
> > + Dot0 = SInfo0 ^ dot ^ elem(StateVar)
> > + then
> > + NameX = varset__lookup_name(VarSet, DotX) `with_type` string,
> > + Name0 = varset__lookup_name(VarSet, Dot0) `with_type` string,
> > + compare(RDot, NameX, Name0),
> > + (
> > + RDot = (<),
> > + SInfo = ( SInfo0 ^ dot ^ elem(StateVar) := Dot0 )
> > + ;
> > + RDot = (=),
> > + SInfo = SInfo0
> > + ;
> > + RDot = (>),
> > + SInfo = ( SInfo0 ^ dot ^ elem(StateVar) := DotX )
> > + )
> > + else
> > + SInfo = SInfo0
> > + ).
>
> Does this work? For example, `STATE_VAR_X_2' will compare greater
> than `STATE_VAR_X_10'.
I've replaced string comparison with a special comparison function that
understands state variable names.
diff -u make_hlds.m make_hlds.m
--- make_hlds.m 7 Jun 2002 07:39:12 -0000
+++ make_hlds.m 25 Jun 2002 06:45:05 -0000
@@ -16,9 +16,6 @@
% super-homogenous form, and introduce implicit quantification.
%
% XXX we should record each error using module_info_incr_errors.
-%
-% XXX For state variables, we should allow quantifiers around if-then-else
-% expressions.
% WISHLIST - we should handle explicit module quantification
@@ -5541,7 +5538,6 @@
VarTypes1, HeadVars, ClauseList, TI_VarMap, TCI_VarMap,
_HasForeignClauses) },
-
% Find all the existing clauses for this mode, and
% extract their implementation language and clause number
% (that is, their index in the list).
@@ -5680,6 +5676,7 @@
io__set_exit_status(1)
;
{
+ Info = Info0,
% build the pragma_c_code
goal_info_init(GoalInfo0),
goal_info_set_context(GoalInfo0, Context, GoalInfo1),
@@ -5687,12 +5684,12 @@
% this foreign code is inlined
add_goal_info_purity_feature(GoalInfo1, Purity, GoalInfo),
HldsGoal0 = foreign_proc(Attributes, PredId,
- ProcId, Args, ArgInfo, OrigArgTypes, PragmaImpl)
+ ProcId, HeadVars, ArgInfo, OrigArgTypes, PragmaImpl)
- GoalInfo,
ModuleInfo = ModuleInfo1,
map__init(EmptyVarTypes),
implicitly_quantify_clause_body(HeadVars,
- HldsGoal1, VarSet2, EmptyVarTypes,
+ HldsGoal0, VarSet0, EmptyVarTypes,
HldsGoal, VarSet, _, _Warnings),
NewClause = clause([ProcId], HldsGoal,
foreign_language(NewLang), Context),
@@ -5751,7 +5748,7 @@
else
ArgContext = head(PredOrFunc, Arity),
insert_arg_unifications(HeadVars, Args, Context, ArgContext,
- no, Head0, VarSet1, Head, VarSet2, Info0, Info1,
+ Head0, VarSet1, Head, VarSet2, Info0, Info1,
SInfo1, SInfo2, IO1, IO2)
),
@@ -6021,8 +6018,7 @@
{ record_called_pred_or_func(predicate, Name, Arity,
Info0, Info1) },
- insert_arg_unifications(HeadVars, Args,
- Context, call(CallId), no,
+ insert_arg_unifications(HeadVars, Args, Context, call(CallId),
Goal0, VarSet1, Goal, VarSetX, Info1, Info,
SInfo1, SInfoX)
),
@@ -6629,7 +6625,7 @@
{ record_called_pred_or_func(PredOrFunc, SymName,
InsertArity, Info0, Info1) },
insert_arg_unifications(AllArgs, AllArgTerms,
- Context, call(CallId), no, Goal0,
+ Context, call(CallId), Goal0,
VarSet3, Goal, VarSet, Info1, Info,
SInfo0, SInfo)
;
@@ -6736,7 +6732,7 @@
PredGoal0, VarSet3, Info0, Info1, SInfo0, SInfo1),
{ ArgContext = head(PredOrFunc, PredArity) },
insert_arg_unifications(HeadArgs, HeadArgs1, Context,
- ArgContext, no, PredGoal0, VarSet3, PredGoal1, VarSet4,
+ ArgContext, PredGoal0, VarSet3, PredGoal1, VarSet4,
Info1, Info2, SInfo1, SInfo2),
% Quantification will reduce this down to
% the proper set of nonlocal arguments.
@@ -6807,7 +6803,7 @@
insert_arg_unifications(AllArgs,
[term__variable(LambdaVar), AditiState0Term,
AditiStateTerm],
- Context, CallId, no, UpdateConj,
+ Context, CallId, UpdateConj,
VarSet7, UpdateGoal, VarSet, Info4, Info, SInfo2, SInfo)
;
%
@@ -6848,7 +6844,7 @@
{ record_called_pred_or_func(PredOrFunc, SymName, Arity,
Info0, Info1) },
insert_arg_unifications(OtherArgs, OtherArgs0, Context, CallId,
- no, Call, VarSet1, UpdateGoal,
+ Call, VarSet1, UpdateGoal,
VarSet, Info1, Info, SInfo0, SInfo)
;
{ invalid_goal(Descr, Args0, GoalInfo,
@@ -7060,15 +7056,6 @@
% where the terms came from.
% We never insert unifications of the form X = X.
- % If ForPragmaC is yes, we process unifications of the form
- % X = Y by substituting the var expected by the outside environment
- % (the head variable) for the variable inside the goal (which was
- % created just for the pragma_c_code goal), while giving the headvar
- % the name of the just eliminated variable. The result will be
- % a proc_info in which the head variables have meaningful names
- % and the body goal is just a pragma C code. Without this special
- % treatment, the body goal will be a conjunction, which would
- % complicate the handling of code generation for nondet pragma C codes.
:- type arg_context
--->
@@ -7086,13 +7073,13 @@
).
:- pred insert_arg_unifications(list(prog_var), list(prog_term),
- prog_context, arg_context, bool, hlds_goal, prog_varset,
+ prog_context, arg_context, hlds_goal, prog_varset,
hlds_goal, prog_varset, transform_info, transform_info,
svar_info, svar_info, io__state, io__state).
-:- mode insert_arg_unifications(in, in, in, in, in, in, in, out,
+:- mode insert_arg_unifications(in, in, in, in, in, in, out,
out, in, out, in, out, di, uo) is det.
-insert_arg_unifications(HeadVars, Args0, Context, ArgContext, ForPragmaC,
+insert_arg_unifications(HeadVars, Args0, Context, ArgContext,
Goal0, VarSet0, Goal, VarSet, Info0, Info, SInfo0, SInfo) -->
( { HeadVars = [] } ->
{ Goal = Goal0 },
@@ -7105,42 +7092,42 @@
substitute_state_var_mappings(Args0, Args, VarSet0, VarSet1,
SInfo0, SInfo1),
insert_arg_unifications_2(HeadVars, Args, Context, ArgContext,
- ForPragmaC, 0, List0, VarSet1, List, VarSet,
+ 0, List0, VarSet1, List, VarSet,
Info0, Info, SInfo1, SInfo),
{ goal_info_set_context(GoalInfo0, Context, GoalInfo) },
{ conj_list_to_goal(List, GoalInfo, Goal) }
).
:- pred insert_arg_unifications_2(list(prog_var), list(prog_term),
- prog_context, arg_context, bool, int, list(hlds_goal),
+ prog_context, arg_context, int, list(hlds_goal),
prog_varset, list(hlds_goal), prog_varset,
transform_info, transform_info, svar_info, svar_info,
io__state, io__state).
-:- mode insert_arg_unifications_2(in, in, in, in, in, in, in, in,
+:- mode insert_arg_unifications_2(in, in, in, in, in, in, in,
out, out, in, out, in, out, di, uo) is det.
-insert_arg_unifications_2([], [_|_], _, _, _, _, _, _, _, _, _, _, _, _) -->
+insert_arg_unifications_2([], [_|_], _, _, _, _, _, _, _, _, _, _, _) -->
{ error("insert_arg_unifications_2: length mismatch") }.
-insert_arg_unifications_2([_|_], [], _, _, _, _, _, _, _, _, _, _, _, _) -->
+insert_arg_unifications_2([_|_], [], _, _, _, _, _, _, _, _, _, _, _) -->
{ error("insert_arg_unifications_2: length mismatch") }.
-insert_arg_unifications_2([], [], _, _, _, _, List, VarSet, List, VarSet,
+insert_arg_unifications_2([], [], _, _, _, List, VarSet, List, VarSet,
Info, Info, SInfo, SInfo) --> [].
insert_arg_unifications_2([Var|Vars], [Arg|Args], Context, ArgContext,
- ForPragmaC, N0, List0, VarSet0, List, VarSet,
+ N0, List0, VarSet0, List, VarSet,
Info0, Info, SInfo0, SInfo) -->
{ N1 is N0 + 1 },
insert_arg_unification(Var, Arg, Context, ArgContext,
- ForPragmaC, N1, List0, VarSet0, List1, VarSet1, ArgUnifyConj,
+ N1, List0, VarSet0, List1, VarSet1, ArgUnifyConj,
Info0, Info1, SInfo0, SInfo1),
(
{ ArgUnifyConj = [] }
->
insert_arg_unifications_2(Vars, Args, Context, ArgContext,
- ForPragmaC, N1, List1, VarSet1, List, VarSet,
+ N1, List1, VarSet1, List, VarSet,
Info1, Info, SInfo1, SInfo)
;
insert_arg_unifications_2(Vars, Args, Context, ArgContext,
- ForPragmaC, N1, List1, VarSet1, List2, VarSet,
+ N1, List1, VarSet1, List2, VarSet,
Info1, Info, SInfo1, SInfo),
{ list__append(ArgUnifyConj, List2, List) }
).
@@ -7196,7 +7183,7 @@
{ Terms = [Term | Terms1] },
{ ArgContexts = [ArgNumber - ArgContext | ArgContexts1] }
->
- insert_arg_unification(Var, Term, Context, ArgContext, no,
+ insert_arg_unification(Var, Term, Context, ArgContext,
ArgNumber, List0, VarSet0, List1, VarSet1,
UnifyConj, Info0, Info1, SInfo0, SInfo1),
insert_arg_unifications_with_supplied_contexts_2(Vars1, Terms1,
@@ -7208,14 +7195,14 @@
).
:- pred insert_arg_unification(prog_var, prog_term,
- prog_context, arg_context, bool, int,
+ prog_context, arg_context, int,
list(hlds_goal), prog_varset, list(hlds_goal), prog_varset,
list(hlds_goal), transform_info, transform_info,
svar_info, svar_info, io__state, io__state).
-:- mode insert_arg_unification(in, in, in, in, in, in,
+:- mode insert_arg_unification(in, in, in, in, in,
in, in, out, out, out, in, out, in, out, di, uo) is det.
-insert_arg_unification(Var, Arg, Context, ArgContext, ForPragmaC, N1,
+insert_arg_unification(Var, Arg, Context, ArgContext, N1,
List0, VarSet0, List1, VarSet1, ArgUnifyConj,
Info0, Info, SInfo0, SInfo) -->
(
@@ -7228,23 +7215,6 @@
{ List1 = List0 },
{ SInfo = SInfo0 }
;
- { Arg = term__variable(ArgVar) },
- { ForPragmaC = yes }
- ->
- % Handle unifications of the form `X = Y' by substitution
- % if this is safe.
- { Info = Info0 },
- { ArgUnifyConj = [] },
- { map__init(Subst0) },
- { map__det_insert(Subst0, ArgVar, Var, Subst) },
- { goal_util__rename_vars_in_goals(List0, no, Subst, List1) },
- { varset__search_name(VarSet0, ArgVar, ArgVarName) ->
- varset__name_var(VarSet0, Var, ArgVarName, VarSet1)
- ;
- VarSet1 = VarSet0
- },
- { SInfo = SInfo0 }
- ;
{ arg_context_to_unify_context(ArgContext, N1,
UnifyMainContext, UnifySubContext) },
unravel_unification(term__variable(Var), Arg,
@@ -7446,8 +7416,7 @@
unravel_unification_2(term__variable(X), RHS,
Context, MainContext, SubContext, VarSet0, Purity,
Goal, VarSet, Info0, Info, SInfo0, SInfo) -->
- { RHS = term__functor(F, Args0, FunctorContext) },
- { Args1 = expand_bang_state_var_args(Args0) },
+ { RHS = term__functor(F, Args1, FunctorContext) },
substitute_state_var_mappings(Args1, Args, VarSet0, VarSet1,
SInfo0, SInfo1),
(
@@ -7567,21 +7536,45 @@
},
{ term__coerce(IfTerm0, IfTerm) },
{ parse_some_vars_goal(IfTerm, VarSet1, Vars,
- IfParseTree, VarSet11) }
+ IfParseTree0, VarSet11) }
->
- { prepare_for_if_then_else_expr_condition(SInfo1, SInfo2) },
+ % The condition can introduce state variables that
+ % also range over the Then goal. We need to
+ % preserve these state variables for processing the
+ % Then goal and remove them afterwards.
+
+ { if IfParseTree0 = some_state_vars(StateVars0, IfParseTree1) -
+ _IfCtxt
+ then
+ StateVars = StateVars0,
+ IfParseTree = IfParseTree1
+ else
+ StateVars = [],
+ IfParseTree = IfParseTree0
+ },
+
+ { prepare_for_if_then_else_expr(StateVars, VarSet11, VarSet11a,
+ SInfo1, SInfo2) },
+
check_expr_purity(Purity, Context, Info0, Info1),
{ map__init(EmptySubst) },
- transform_goal(IfParseTree, VarSet11, EmptySubst,
+ transform_goal(IfParseTree, VarSet11a, EmptySubst,
IfGoal, VarSet22, Info1, Info2, SInfo2, SInfo3),
+
{ finish_if_then_else_expr_condition(SInfo1, SInfo3, SInfo4) },
+
unravel_unification(term__variable(X), ThenTerm,
Context, MainContext, SubContext, VarSet22,
pure, ThenGoal, VarSet33, Info2, Info3, SInfo4, SInfo5),
+
+ { finish_if_then_else_expr_then_goal(StateVars,
+ SInfo1, SInfo5, SInfo6) },
+
unravel_unification(term__variable(X), ElseTerm,
Context, MainContext, SubContext, VarSet33, pure,
- ElseGoal, VarSet, Info3, Info, SInfo5, SInfo),
- { IfThenElse = if_then_else(Vars, IfGoal,
+ ElseGoal, VarSet, Info3, Info, SInfo6, SInfo),
+
+ { IfThenElse = if_then_else(StateVars ++ Vars, IfGoal,
ThenGoal, ElseGoal) },
{ goal_info_init(Context, GoalInfo) },
{ Goal = IfThenElse - GoalInfo }
@@ -7695,7 +7688,7 @@
Purity, GoalInfo) },
{ Goal1 = GoalExpr - GoalInfo },
insert_arg_unifications(HeadVars, FunctorArgs,
- FunctorContext, ArgContext, no, Goal1,
+ FunctorContext, ArgContext, Goal1,
VarSet2, Goal, VarSet,
Info1, Info, SInfo1, SInfo)
)
@@ -7857,8 +7850,7 @@
{ Info = Info1 }
;
{ prepare_for_lambda(SInfo0, SInfo1) },
- { Args1 = expand_bang_state_var_args(Args0) },
- substitute_state_var_mappings(Args1, Args, VarSet0, VarSet1,
+ substitute_state_var_mappings(Args0, Args, VarSet0, VarSet1,
SInfo1, SInfo2),
{ list__length(Args, NumArgs) },
@@ -7868,7 +7860,7 @@
{ ArgContext = head(PredOrFunc, NumArgs) },
insert_arg_unifications(LambdaVars, Args, Context, ArgContext,
- no, Head0, VarSet2, Head, VarSet3, Info1, Info2,
+ Head0, VarSet2, Head, VarSet3, Info1, Info2,
SInfo2, SInfo3),
{ prepare_for_body(FinalSVarMap, VarSet3, VarSet4,
@@ -9032,7 +9024,7 @@
VarSet = VarSet0,
SInfo = SInfo0,
IO = IO0
- else if SInfo0 ^ colon `contains` StateVar then
+ else if SInfo0 `has_svar_colon_mapping_for` StateVar then
new_dot_state_var(StateVar, Var,
VarSet0, VarSet, SInfo0, SInfo),
report_unitialized_state_var(Context, VarSet, StateVar,
@@ -9041,11 +9033,22 @@
Var = StateVar,
VarSet = VarSet0,
SInfo = SInfo0,
- report_non_visible_state_var(Context, VarSet, StateVar,
- IO0, IO)
+ report_non_visible_state_var(".", Context,
+ VarSet, StateVar, IO0, IO)
)
).
+
+:- pred svar_info `has_svar_colon_mapping_for` svar.
+:- mode in `has_svar_colon_mapping_for` in is semidet.
+
+SInfo `has_svar_colon_mapping_for` StateVar :-
+ SInfo ^ colon `contains` StateVar.
+
+SInfo `has_svar_colon_mapping_for` StateVar :-
+ SInfo ^ ctxt = in_atom(_, ParentSInfo),
+ ParentSInfo `has_svar_colon_mapping_for` StateVar.
+
%------------------------------------------------------------------------------%
% Obtain the mapping for a !:X state variable reference.
@@ -9092,7 +9095,7 @@
SInfo = SInfo0,
PError = ( if SInfo0 ^ external_dot `contains` StateVar
then report_illegal_state_var_update
- else report_non_visible_state_var
+ else report_non_visible_state_var(":")
),
PError(Context, VarSet, StateVar, IO0, IO)
)
@@ -9510,7 +9513,7 @@
then
NameX = varset__lookup_name(VarSet, DotX) `with_type` string,
Name0 = varset__lookup_name(VarSet, Dot0) `with_type` string,
- compare(RDot, NameX, Name0),
+ compare_svar_names(RDot, NameX, Name0),
(
RDot = (<),
SInfo = ( SInfo0 ^ dot ^ elem(StateVar) := Dot0 )
@@ -9536,7 +9539,7 @@
then
NameX = varset__lookup_name(VarSet, ColonX) `with_type` string,
Name0 = varset__lookup_name(VarSet, Colon0) `with_type` string,
- compare(RColon, NameX, Name0),
+ compare_svar_names(RColon, NameX, Name0),
(
RColon = (<),
SInfo = ( SInfo0 ^ colon ^ elem(StateVar) := Colon0 )
@@ -9579,6 +9582,73 @@
%------------------------------------------------------------------------------%
+ % We implement a special purpose comparison for state variable
+ % names that compares the numbers appended at the right hand
+ % ends of the name strings.
+ %
+ % NOTE state variable names are either "..._X" or "..._X_N"
+ % where X is the name of the program variable used for the
+ % state variable and N is a decimal number with no leading
+ % zeroes.
+ %
+:- pred compare_svar_names(comparison_result, string, string).
+:- mode compare_svar_names(out, in, in) is det.
+
+compare_svar_names(R, A, B) :-
+ csvns_1(R, 1, A, length(A), B, length(B)).
+
+
+ % First find the start of the numbers at the right hand end, if
+ % present.
+ %
+:- pred csvns_1(comparison_result, int, string, int, string, int).
+:- mode csvns_1(out, in, in, in, in, in) is det.
+
+csvns_1(R, I, A, MaxA, B, MaxB) :-
+ ( if I < MaxA, I < MaxB then
+ X = A `unsafe_index` (MaxA - I),
+ Y = B `unsafe_index` (MaxB - I),
+ ( if is_digit(X), is_digit(Y) then
+ csvns_1(R, I + 1, A, MaxA, B, MaxB)
+ else if X = ('_'), is_digit(Y) then
+ R = (<)
+ else if is_digit(X), Y = ('_') then
+ R = (>)
+ else if X = ('_'), Y = ('_') then
+ csvns_2(R, I - 1, A, MaxA, B, MaxB)
+ else if X = Y then
+ R = (=)
+ else
+ error("make_hlds__compare_svar_names: \
+names are not in expected format")
+ )
+ else
+ error("make_hlds__compare_svar_names: \
+names are not in expected format")
+ ).
+
+
+ % Decide the greater of the two numbers at the right hand end
+ % (both numbers will have the same number of digits.)
+ %
+:- pred csvns_2(comparison_result, int, string, int, string, int).
+:- mode csvns_2(out, in, in, in, in, in) is det.
+
+csvns_2(R, I, A, MaxA, B, MaxB) :-
+ ( if 0 < I then
+ X = A `unsafe_index` (MaxA - I) `with_type` char,
+ Y = B `unsafe_index` (MaxB - I) `with_type` char,
+ compare(RXY, X, Y),
+ ( RXY = (<), R = (<)
+ ; RXY = (=), csvns_2(R, I - 1, A, MaxA, B, MaxB)
+ ; RXY = (>), R = (>)
+ )
+ else
+ R = (=)
+ ).
+
+%------------------------------------------------------------------------------%
+
% We treat equivalence goals as if they were negations (they are
% in a negated context after all.)
%
@@ -9638,17 +9708,21 @@
%------------------------------------------------------------------------------%
% The condition of an if-then-else expression is a goal in which
- % only !.X state variables are visible (although the goal may
- % use local state variables introduced via an explicit quantifier.)
+ % only !.X state variables in scope are visible (although the goal
+ % may use local state variables introduced via an explicit
+ % quantifier.) The StateVars are local to the condition and then-
+ % goal.
%
-:- pred prepare_for_if_then_else_expr_condition(svar_info, svar_info).
-:- mode prepare_for_if_then_else_expr_condition(in, out) is det.
+:- pred prepare_for_if_then_else_expr(svars, prog_varset, prog_varset,
+ svar_info, svar_info).
+:- mode prepare_for_if_then_else_expr(in, in, out, in, out) is det.
-prepare_for_if_then_else_expr_condition(SInfo0, SInfo) :-
- SInfo = (((( SInfo0 ^ ctxt := in_body )
- ^ external_dot := SInfo0 ^ dot )
- ^ dot := map__init )
- ^ colon := map__init ).
+prepare_for_if_then_else_expr(StateVars, VarSet0, VarSet, SInfo0, SInfo) :-
+ SInfo1 = ((( new_svar_info ^ ctxt := in_body )
+ ^ external_dot := SInfo0 ^ dot )
+ ^ num := SInfo0 ^ num ),
+ prepare_for_local_state_vars(StateVars, VarSet0, VarSet,
+ SInfo1, SInfo).
%------------------------------------------------------------------------------%
@@ -9656,7 +9730,16 @@
:- mode finish_if_then_else_expr_condition(in, in, out) is det.
finish_if_then_else_expr_condition(SInfoBefore, SInfo0, SInfo) :-
- SInfo = ( SInfoBefore ^ num := SInfo0 ^ num ).
+ SInfo = ( SInfo0 ^ ctxt := SInfoBefore ^ ctxt ).
+
+%------------------------------------------------------------------------------%
+
+:- pred finish_if_then_else_expr_then_goal(svars,
+ svar_info, svar_info, svar_info).
+:- mode finish_if_then_else_expr_then_goal(in, in, in, out) is det.
+
+finish_if_then_else_expr_then_goal(StateVars, SInfoBefore, SInfo0, SInfo) :-
+ finish_local_state_vars(StateVars, _, SInfoBefore, SInfo0, SInfo).
%------------------------------------------------------------------------------%
@@ -9866,7 +9949,7 @@
%------------------------------------------------------------------------------%
% We do not allow !X to appear as a lambda head argument.
- % XXX We could extend the syntax still further to accommodate
+ % We might extend the syntax still further to accommodate
% this as an option, e.g. !IO::(di, uo).
%
:- pred lambda_args_contain_bang_state_var(list(prog_term), prog_var).
@@ -9895,14 +9978,15 @@
%------------------------------------------------------------------------------%
-:- pred report_non_visible_state_var(prog_context, prog_varset, svar, io, io).
-:- mode report_non_visible_state_var(in, in, in, di, uo) is det.
+:- pred report_non_visible_state_var(string, prog_context, prog_varset, svar,
+ io, io).
+:- mode report_non_visible_state_var(in, in, in, in, di, uo) is det.
-report_non_visible_state_var(Context, VarSet, StateVar) -->
+report_non_visible_state_var(DorC, Context, VarSet, StateVar) -->
{ Name = varset__lookup_name(VarSet, StateVar) },
prog_out__write_context(Context),
report_error(string__format("\
-state variable !:%s is not visible in this context.\n", [s(Name)])).
+state variable !%s%s is not visible in this context.\n", [s(DorC), s(Name)])).
%------------------------------------------------------------------------------%
--------------------------------------------------------------------------
mercury-reviews mailing list
post: mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------
More information about the reviews
mailing list