% -----------------------------------------------------------------------------
%  (C) Altran Praxis Limited
% -----------------------------------------------------------------------------
% 
%  The SPARK toolset is free software; you can redistribute it and/or modify it
%  under terms of the GNU General Public License as published by the Free
%  Software Foundation; either version 3, or (at your option) any later
%  version. The SPARK toolset is distributed in the hope that it will be
%  useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
%  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
%  Public License for more details. You should have received a copy of the GNU
%  General Public License distributed with the SPARK toolset; see file
%  COPYING3. If not, go to http://www.gnu.org/licenses for a complete copy of
%  the license.
% 
% =============================================================================


%-------------------------------------------------------------------------------
% RULE FAMILIES CONTAINED HEREIN :-
%
% record          : record-type simplification rules
% record_equality : equality of two record-type objects
% mk__record      : rules specific to SPARK record aggregates
%-------------------------------------------------------------------------------
% MODEL DECLARATIONS FOR THIS FILE :-
%
% rule_family record:
%         X requires [ X:any ].
%
% rule_family record_equality:
%         X=Y requires [ X:any, Y:any ].
%
% rule_family mk__record:
%         X requires [ X:any ].
%-------------------------------------------------------------------------------


/*** RECORD SIMPLIFICATION rules ***/

/* record(1): fld_F(upf_F(_, VALUE)) may_be_replaced_by VALUE. */
RECORD1:    FLD may_be_replaced_by VALUE if
                [ goal(nonvar(RECORD1)),
                  goal(RECORD1=record(1)),
                  goal(record_function(_, FLD, access, F, [RECORD], TYPE)),
                  goal(record_function(_, RECORD, update, F, [_, VALUE], TYPE)) ].

/* record(2): upf_F(REC, fld_F(REC)) may_be_replaced_by REC. */
RECORD2:    UPF may_be_replaced_by REC if
                [ goal(nonvar(RECORD2)),
                  goal(RECORD2=record(2)),
                  goal(record_function(_, UPF, update, F, [REC, VALUE], TYPE)),
                  goal(record_function(_, VALUE, access, F, [REC], TYPE)) ].

/* record(3): upf_F(upf_G(R,VG),VF) may_be_replaced_by upf_G(upf_F(R,VF),VG) if [ "F" <> "G" ]. */
RECORD3:    UPF_F may_be_replaced_by UPF_G if
                [ goal(nonvar(RECORD3)),
                  goal(RECORD3=record(3)),
                  goal(record_function(_, UPF_F, update, F, [REC1, VF], TYPE)),
                  goal(record_function(_, REC1,  update, G, [R, VG], TYPE)),
                  goal(F \= G),
                  goal(record_function(_, REC2,  update, F, [R, VF], TYPE)),
                  goal(record_function(_, UPF_G, update, G, [REC2, VG], TYPE)) ].

/* record(4): fld_F(upf_G(R, V)) may_be_replaced_by fld_F(R) if [ "F" <> "G" ]. */
RECORD4:    FLD_F_UPF_G may_be_replaced_by FLD_F_R if
                [ goal(nonvar(RECORD4)),
                  goal(RECORD4=record(4)),
                  goal(record_function(_, FLD_F_UPF_G, access, F, [UPF_G], TYPE)),
                  goal(record_function(_, UPF_G, update, G, [R, V], TYPE)),
                  goal(F \= G),
                  goal(record_function(_, FLD_F_R, access, F, [R], TYPE)) ].

/* record(5): upf_F(upf_F(R, _), V) may_be_replaced_by upf_F(R, V). */
RECORD5:    UPF_F_UPF_F_R may_be_replaced_by UPF_F_R if
                [ goal(nonvar(RECORD5)),
                  goal(RECORD5=record(5)),
                  goal(record_function(_, UPF_F_UPF_F_R, update, F, [UPF_F, V], TYPE)),
                  goal(record_function(_, UPF_F, update, F, [R, _], TYPE)),
                  goal(record_function(_, UPF_F_R, update, F, [R, V], TYPE)) ].



/*** RECORD EQUALITY RULES ***/

/* record_equality(1): {for records with ONE field}
        R=S may_be_deduced_from [ fld_F1(R)=fld_F1(S) ]. */
RECORD_EQUALITY1:
        R = S may_be_deduced_from
                [ goal(nonvar(RECORD_EQUALITY1)),
                  goal(RECORD_EQUALITY1=record_equality(1)),
                  goal(checktype(R,RECORD_TYPE)),
                  goal(type(RECORD_TYPE, record([[F1,_]]))),
                  goal(checktype(S,RECORD_TYPE)),
                  goal(record_function(_, R1, access, F1, [R], RECORD_TYPE)),
                  goal(record_function(_, S1, access, F1, [S], RECORD_TYPE)),
                  R1 = S1 ].

/* record_equality(2): {for records with TWO fields}
        R=S may_be_deduced_from [ fld_F1(R)=fld_F1(S), fld_F2(R)=fld_F2(S) ]. */
RECORD_EQUALITY2:
        R = S may_be_deduced_from
                [ goal(nonvar(RECORD_EQUALITY2)),
                  goal(RECORD_EQUALITY2=record_equality(2)),
                  goal(checktype(R,RECORD_TYPE)),
                  goal(type(RECORD_TYPE, record([[F1,_],[F2,_]]))),
                  goal(checktype(S,RECORD_TYPE)),
                  goal(record_function(_, R1, access, F1, [R], RECORD_TYPE)),
                  goal(record_function(_, S1, access, F1, [S], RECORD_TYPE)),
                  goal(record_function(_, R2, access, F2, [R], RECORD_TYPE)),
                  goal(record_function(_, S2, access, F2, [S], RECORD_TYPE)),
                  R1 = S1, R2 = S2 ].

/* record_equality(3): {for records with THREE fields}
        R=S may_be_deduced_from
           [ fld_F1(R)=fld_F1(S), fld_F2(R)=fld_F2(S), fld_F3(R)=fld_F3(S) ]. */
RECORD_EQUALITY3:
        R = S may_be_deduced_from
                [ goal(nonvar(RECORD_EQUALITY3)),
                  goal(RECORD_EQUALITY3=record_equality(3)),
                  goal(checktype(R,RECORD_TYPE)),
                  goal(type(RECORD_TYPE, record([[F1,_],[F2,_],[F3,_]]))),
                  goal(checktype(S,RECORD_TYPE)),
                  goal(record_function(_, R1, access, F1, [R], RECORD_TYPE)),
                  goal(record_function(_, S1, access, F1, [S], RECORD_TYPE)),
                  goal(record_function(_, R2, access, F2, [R], RECORD_TYPE)),
                  goal(record_function(_, S2, access, F2, [S], RECORD_TYPE)),
                  goal(record_function(_, R3, access, F3, [R], RECORD_TYPE)),
                  goal(record_function(_, S3, access, F3, [S], RECORD_TYPE)),
                  R1 = S1, R2 = S2, R3 = S3 ].

/* record_equality(4): {for records with FOUR fields}
        R=S may_be_deduced_from
           [ fld_F1(R)=fld_F1(S), fld_F2(R)=fld_F2(S),
             fld_F3(R)=fld_F3(S), fld_F4(R)=fld_F4(S) ]. */
RECORD_EQUALITY4:
        R = S may_be_deduced_from
                [ goal(nonvar(RECORD_EQUALITY4)),
                  goal(RECORD_EQUALITY4=record_equality(4)),
                  goal(checktype(R,RECORD_TYPE)),
                  goal(type(RECORD_TYPE,
                        record([[F1,_],[F2,_],[F3,_],[F4,_]]))),
                  goal(checktype(S,RECORD_TYPE)),
                  goal(record_function(_, R1, access, F1, [R], RECORD_TYPE)),
                  goal(record_function(_, S1, access, F1, [S], RECORD_TYPE)),
                  goal(record_function(_, R2, access, F2, [R], RECORD_TYPE)),
                  goal(record_function(_, S2, access, F2, [S], RECORD_TYPE)),
                  goal(record_function(_, R3, access, F3, [R], RECORD_TYPE)),
                  goal(record_function(_, S3, access, F3, [S], RECORD_TYPE)),
                  goal(record_function(_, R4, access, F4, [R], RECORD_TYPE)),
                  goal(record_function(_, S4, access, F4, [S], RECORD_TYPE)),
                  R1 = S1, R2 = S2, R3 = S3, R4 = S4 ].

/* record_equality(5): {for records with FIVE fields}
        R=S may_be_deduced_from
           [ fld_F1(R)=fld_F1(S), fld_F2(R)=fld_F2(S),
             fld_F3(R)=fld_F3(S), fld_F4(R)=fld_F4(S),
             fld_F5(R)=fld_F5(S) ]. */
RECORD_EQUALITY5:
        R = S may_be_deduced_from
                [ goal(nonvar(RECORD_EQUALITY5)),
                  goal(RECORD_EQUALITY5=record_equality(5)),
                  goal(checktype(R,RECORD_TYPE)),
                  goal(type(RECORD_TYPE,
                        record([[F1,_],[F2,_],[F3,_],[F4,_],[F5,_]]))),
                  goal(checktype(S,RECORD_TYPE)),
                  goal(record_function(_, R1, access, F1, [R], RECORD_TYPE)),
                  goal(record_function(_, S1, access, F1, [S], RECORD_TYPE)),
                  goal(record_function(_, R2, access, F2, [R], RECORD_TYPE)),
                  goal(record_function(_, S2, access, F2, [S], RECORD_TYPE)),
                  goal(record_function(_, R3, access, F3, [R], RECORD_TYPE)),
                  goal(record_function(_, S3, access, F3, [S], RECORD_TYPE)),
                  goal(record_function(_, R4, access, F4, [R], RECORD_TYPE)),
                  goal(record_function(_, S4, access, F4, [S], RECORD_TYPE)),
                  goal(record_function(_, R5, access, F5, [R], RECORD_TYPE)),
                  goal(record_function(_, S5, access, F5, [S], RECORD_TYPE)),
                  R1 = S1, R2 = S2, R3 = S3, R4 = S4, R5 = S5 ].

/* record_equality(6): {for records with SIX fields}
        R=S may_be_deduced_from
           [ fld_F1(R)=fld_F1(S), fld_F2(R)=fld_F2(S),
             fld_F3(R)=fld_F3(S), fld_F4(R)=fld_F4(S),
             fld_F5(R)=fld_F5(S), fld_F6(R)=fld_F6(S) ]. */
RECORD_EQUALITY6:
        R = S may_be_deduced_from
                [ goal(nonvar(RECORD_EQUALITY6)),
                  goal(RECORD_EQUALITY6=record_equality(6)),
                  goal(checktype(R,RECORD_TYPE)),
                  goal(type(RECORD_TYPE,
                        record([[F1,_],[F2,_],[F3,_],[F4,_],[F5,_],[F6,_]]))),
                  goal(checktype(S,RECORD_TYPE)),
                  goal(record_function(_, R1, access, F1, [R], RECORD_TYPE)),
                  goal(record_function(_, S1, access, F1, [S], RECORD_TYPE)),
                  goal(record_function(_, R2, access, F2, [R], RECORD_TYPE)),
                  goal(record_function(_, S2, access, F2, [S], RECORD_TYPE)),
                  goal(record_function(_, R3, access, F3, [R], RECORD_TYPE)),
                  goal(record_function(_, S3, access, F3, [S], RECORD_TYPE)),
                  goal(record_function(_, R4, access, F4, [R], RECORD_TYPE)),
                  goal(record_function(_, S4, access, F4, [S], RECORD_TYPE)),
                  goal(record_function(_, R5, access, F5, [R], RECORD_TYPE)),
                  goal(record_function(_, S5, access, F5, [S], RECORD_TYPE)),
                  goal(record_function(_, R6, access, F6, [R], RECORD_TYPE)),
                  goal(record_function(_, S6, access, F6, [S], RECORD_TYPE)),
                  R1 = S1, R2 = S2, R3 = S3, R4 = S4, R5 = S5, R6 = S6 ].

/* record_equality(7): {for records with SEVEN fields}
        R=S may_be_deduced_from
           [ fld_F1(R)=fld_F1(S), fld_F2(R)=fld_F2(S),
             fld_F3(R)=fld_F3(S), fld_F4(R)=fld_F4(S),
             fld_F5(R)=fld_F5(S), fld_F6(R)=fld_F6(S),
             fld_F7(R)=fld_F7(S) ]. */
RECORD_EQUALITY7:
        R = S may_be_deduced_from
                [ goal(nonvar(RECORD_EQUALITY7)),
                  goal(RECORD_EQUALITY7=record_equality(7)),
                  goal(checktype(R,RECORD_TYPE)),
                  goal(type(RECORD_TYPE,
                        record([[F1,_],[F2,_],[F3,_],[F4,_],[F5,_],[F6,_],
                                [F7,_]]))),
                  goal(checktype(S,RECORD_TYPE)),
                  goal(record_function(_, R1, access, F1, [R], RECORD_TYPE)),
                  goal(record_function(_, S1, access, F1, [S], RECORD_TYPE)),
                  goal(record_function(_, R2, access, F2, [R], RECORD_TYPE)),
                  goal(record_function(_, S2, access, F2, [S], RECORD_TYPE)),
                  goal(record_function(_, R3, access, F3, [R], RECORD_TYPE)),
                  goal(record_function(_, S3, access, F3, [S], RECORD_TYPE)),
                  goal(record_function(_, R4, access, F4, [R], RECORD_TYPE)),
                  goal(record_function(_, S4, access, F4, [S], RECORD_TYPE)),
                  goal(record_function(_, R5, access, F5, [R], RECORD_TYPE)),
                  goal(record_function(_, S5, access, F5, [S], RECORD_TYPE)),
                  goal(record_function(_, R6, access, F6, [R], RECORD_TYPE)),
                  goal(record_function(_, S6, access, F6, [S], RECORD_TYPE)),
                  goal(record_function(_, R7, access, F7, [R], RECORD_TYPE)),
                  goal(record_function(_, S7, access, F7, [S], RECORD_TYPE)),
                  R1=S1, R2=S2, R3=S3, R4=S4, R5=S5, R6=S6, R7=S7 ].

/* record_equality(8): {for records with EIGHT fields}
        R=S may_be_deduced_from
           [ fld_F1(R)=fld_F1(S), fld_F2(R)=fld_F2(S),
             fld_F3(R)=fld_F3(S), fld_F4(R)=fld_F4(S),
             fld_F5(R)=fld_F5(S), fld_F6(R)=fld_F6(S),
             fld_F7(R)=fld_F7(S), fld_F8(R)=fld_F8(S) ]. */
RECORD_EQUALITY8:
        R = S may_be_deduced_from
                [ goal(nonvar(RECORD_EQUALITY8)),
                  goal(RECORD_EQUALITY8=record_equality(8)),
                  goal(checktype(R,RECORD_TYPE)),
                  goal(type(RECORD_TYPE,
                        record([[F1,_],[F2,_],[F3,_],[F4,_],[F5,_],[F6,_],
                                [F7,_],[F8,_]]))),
                  goal(checktype(S,RECORD_TYPE)),
                  goal(record_function(_, R1, access, F1, [R], RECORD_TYPE)),
                  goal(record_function(_, S1, access, F1, [S], RECORD_TYPE)),
                  goal(record_function(_, R2, access, F2, [R], RECORD_TYPE)),
                  goal(record_function(_, S2, access, F2, [S], RECORD_TYPE)),
                  goal(record_function(_, R3, access, F3, [R], RECORD_TYPE)),
                  goal(record_function(_, S3, access, F3, [S], RECORD_TYPE)),
                  goal(record_function(_, R4, access, F4, [R], RECORD_TYPE)),
                  goal(record_function(_, S4, access, F4, [S], RECORD_TYPE)),
                  goal(record_function(_, R5, access, F5, [R], RECORD_TYPE)),
                  goal(record_function(_, S5, access, F5, [S], RECORD_TYPE)),
                  goal(record_function(_, R6, access, F6, [R], RECORD_TYPE)),
                  goal(record_function(_, S6, access, F6, [S], RECORD_TYPE)),
                  goal(record_function(_, R7, access, F7, [R], RECORD_TYPE)),
                  goal(record_function(_, S7, access, F7, [S], RECORD_TYPE)),
                  goal(record_function(_, R8, access, F8, [R], RECORD_TYPE)),
                  goal(record_function(_, S8, access, F8, [S], RECORD_TYPE)),
                  R1=S1, R2=S2, R3=S3, R4=S4, R5=S5, R6=S6, R7=S7, R8=S8 ].

/* record_equality(9): {for records with NINE fields}
        R=S may_be_deduced_from
           [ fld_F1(R)=fld_F1(S), fld_F2(R)=fld_F2(S),
             fld_F3(R)=fld_F3(S), fld_F4(R)=fld_F4(S),
             fld_F5(R)=fld_F5(S), fld_F6(R)=fld_F6(S),
             fld_F7(R)=fld_F7(S), fld_F8(R)=fld_F8(S),
             fld_F9(R)=fld_F9(S) ]. */
RECORD_EQUALITY9:
        R = S may_be_deduced_from
                [ goal(nonvar(RECORD_EQUALITY9)),
                  goal(RECORD_EQUALITY9=record_equality(9)),
                  goal(checktype(R,RECORD_TYPE)),
                  goal(type(RECORD_TYPE,
                        record([[F1,_],[F2,_],[F3,_],[F4,_],[F5,_],[F6,_],
                                [F7,_],[F8,_],[F9,_]]))),
                  goal(checktype(S,RECORD_TYPE)),
                  goal(record_function(_, R1, access, F1, [R], RECORD_TYPE)),
                  goal(record_function(_, S1, access, F1, [S], RECORD_TYPE)),
                  goal(record_function(_, R2, access, F2, [R], RECORD_TYPE)),
                  goal(record_function(_, S2, access, F2, [S], RECORD_TYPE)),
                  goal(record_function(_, R3, access, F3, [R], RECORD_TYPE)),
                  goal(record_function(_, S3, access, F3, [S], RECORD_TYPE)),
                  goal(record_function(_, R4, access, F4, [R], RECORD_TYPE)),
                  goal(record_function(_, S4, access, F4, [S], RECORD_TYPE)),
                  goal(record_function(_, R5, access, F5, [R], RECORD_TYPE)),
                  goal(record_function(_, S5, access, F5, [S], RECORD_TYPE)),
                  goal(record_function(_, R6, access, F6, [R], RECORD_TYPE)),
                  goal(record_function(_, S6, access, F6, [S], RECORD_TYPE)),
                  goal(record_function(_, R7, access, F7, [R], RECORD_TYPE)),
                  goal(record_function(_, S7, access, F7, [S], RECORD_TYPE)),
                  goal(record_function(_, R8, access, F8, [R], RECORD_TYPE)),
                  goal(record_function(_, S8, access, F8, [S], RECORD_TYPE)),
                  goal(record_function(_, R9, access, F9, [R], RECORD_TYPE)),
                  goal(record_function(_, S9, access, F9, [S], RECORD_TYPE)),
                  R1=S1, R2=S2, R3=S3, R4=S4, R5=S5, R6=S6, R7=S7, R8=S8,
                  R9=S9 ].

/* record_equality(10): {for records with TEN fields}
        R=S may_be_deduced_from
           [ fld_F1(R)=fld_F1(S), fld_F2(R)=fld_F2(S),
             fld_F3(R)=fld_F3(S), fld_F4(R)=fld_F4(S),
             fld_F5(R)=fld_F5(S), fld_F6(R)=fld_F6(S),
             fld_F7(R)=fld_F7(S), fld_F8(R)=fld_F8(S),
             fld_F9(R)=fld_F9(S), fld_F10(R)=fld_F10(S) ]. */
RECORD_EQUALITY10:
        R = S may_be_deduced_from
                [ goal(nonvar(RECORD_EQUALITY10)),
                  goal(RECORD_EQUALITY10=record_equality(10)),
                  goal(checktype(R,RECORD_TYPE)),
                  goal(type(RECORD_TYPE,
                        record([[F1,_],[F2,_],[F3,_],[F4,_],[F5,_],[F6,_],
                                [F7,_],[F8,_],[F9,_],[F10,_]]))),
                  goal(checktype(S,RECORD_TYPE)),
                  goal(record_function(_, R1, access, F1, [R], RECORD_TYPE)),
                  goal(record_function(_, S1, access, F1, [S], RECORD_TYPE)),
                  goal(record_function(_, R2, access, F2, [R], RECORD_TYPE)),
                  goal(record_function(_, S2, access, F2, [S], RECORD_TYPE)),
                  goal(record_function(_, R3, access, F3, [R], RECORD_TYPE)),
                  goal(record_function(_, S3, access, F3, [S], RECORD_TYPE)),
                  goal(record_function(_, R4, access, F4, [R], RECORD_TYPE)),
                  goal(record_function(_, S4, access, F4, [S], RECORD_TYPE)),
                  goal(record_function(_, R5, access, F5, [R], RECORD_TYPE)),
                  goal(record_function(_, S5, access, F5, [S], RECORD_TYPE)),
                  goal(record_function(_, R6, access, F6, [R], RECORD_TYPE)),
                  goal(record_function(_, S6, access, F6, [S], RECORD_TYPE)),
                  goal(record_function(_, R7, access, F7, [R], RECORD_TYPE)),
                  goal(record_function(_, S7, access, F7, [S], RECORD_TYPE)),
                  goal(record_function(_, R8, access, F8, [R], RECORD_TYPE)),
                  goal(record_function(_, S8, access, F8, [S], RECORD_TYPE)),
                  goal(record_function(_, R9, access, F9, [R], RECORD_TYPE)),
                  goal(record_function(_, S9, access, F9, [S], RECORD_TYPE)),
                  goal(record_function(_, R10, access, F10, [R], RECORD_TYPE)),
                  goal(record_function(_, S10, access, F10, [S], RECORD_TYPE)),
                  R1=S1, R2=S2, R3=S3, R4=S4, R5=S5, R6=S6, R7=S7, R8=S8,
                  R9=S9, R10=S10 ].

/* record_equality(11): {for records with ELEVEN or more fields}
        R=S may_be_deduced_from
           [ fld_F1(R)=fld_F1(S), fld_F2(R)=fld_F2(S),
             fld_F3(R)=fld_F3(S), fld_F4(R)=fld_F4(S),
             fld_F5(R)=fld_F5(S), fld_F6(R)=fld_F6(S),
             fld_F7(R)=fld_F7(S), fld_F8(R)=fld_F8(S),
             fld_F9(R)=fld_F9(S), fld_F10(R)=fld_F10(S), ... ]. */
RECORD_EQUALITY11:
        R = S may_be_deduced_from
                [ goal(nonvar(RECORD_EQUALITY11)),
                  goal(RECORD_EQUALITY11=record_equality(11)),
                  goal(checktype(R,RECORD_TYPE)),
                  goal(type(RECORD_TYPE,record(FIELD_LIST))),
                  goal(length(FIELD_LIST, NO_OF_FIELDS)),
                  goal(NO_OF_FIELDS > 10),
                  goal(checktype(S,RECORD_TYPE)),
                  goal(make_record_equality_goal(FIELD_LIST,R,S,GOAL)),
                  GOAL ].


/* mk__record(1):
	fld_FIELD(mk__record(LARGS...(FIELD := VALUE)...))
		may_be_replaced_by VALUE if
		[ \+ ((FIELD := ...) is_in LARGS),
		  \+ ((FIELD := ...) is_in RARGS) ].
	N.B.: Side conditions check uniqueness of assignment to FIELD. */
MK__RECORD1:
	FLD_FIELD_MK__RECORD_LARGS_FIELD_VALUE_RARGS may_be_replaced_by VALUE if
		[ goal(nonvar(MK__RECORD1)),
		  goal(MK__RECORD1 = mk__record(1)),
		  goal(record_function(_,
			FLD_FIELD_MK__RECORD_LARGS_FIELD_VALUE_RARGS,
			access, FIELD, [MK__RECORD_LARGS_FIELD_VALUE_RARGS], _)),
		  goal(nonvar(MK__RECORD_LARGS_FIELD_VALUE_RARGS)),
		  goal(MK__RECORD_LARGS_FIELD_VALUE_RARGS =..
			[mk__record|LARGS_FIELD_VALUE_RARGS]),
		  goal(append(LARGS, [(FIELD := VALUE)|RARGS],
			LARGS_FIELD_VALUE_RARGS)),
		  goal(\+ is_in((FIELD := _), LARGS)),
		  goal(\+ is_in((FIELD := _), RARGS)) ].


/* mk__record(2):
	upf_FIELD(mk__record(LARGS...(FIELD := OLDVAL)...RARGS), NEWVAL)
		may_be_replaced_by
	mk__record(LARGS...(FIELD := NEWVAL)...RARGS) if
		[ \+ ((FIELD := ...) is_in LARGS),
		  \+ ((FIELD := ...) is_in RARGS) ].
	N.B.: Side conditions check uniqueness of assignment to FIELD. */
MK__RECORD2:
	UPF_FIELD_MK__RECORD_LARGS_FIELD_OLDVAL_RARGS_NEWVAL
		may_be_replaced_by
	MK__RECORD_LARGS_FIELD_NEWVAL_RARGS if
		[ goal(nonvar(MK__RECORD2)),
		  goal(MK__RECORD2 = mk__record(2)),
		  goal(record_function(_,
			UPF_FIELD_MK__RECORD_LARGS_FIELD_OLDVAL_RARGS_NEWVAL,
			update, FIELD,
			[MK__RECORD_LARGS_FIELD_OLDVAL_RARGS, NEWVAL], _)),
		  goal(nonvar(MK__RECORD_LARGS_FIELD_OLDVAL_RARGS)),
		  goal(MK__RECORD_LARGS_FIELD_OLDVAL_RARGS =..
			[mk__record|LARGS_FIELD_OLDVAL_RARGS]),
		  goal(append(LARGS, [(FIELD := OLDVAL)|RARGS],
			LARGS_FIELD_OLDVAL_RARGS)),
		  goal(\+ is_in((FIELD := _), LARGS)),
		  goal(\+ is_in((FIELD := _), RARGS)),
		  goal(append(LARGS, [(FIELD := NEWVAL)|RARGS],
			LARGS_FIELD_NEWVAL_RARGS)),
		  goal(MK__RECORD_LARGS_FIELD_NEWVAL_RARGS =..
			[mk__record|LARGS_FIELD_NEWVAL_RARGS]) ].


/* mk__record(3):
	fld_FIELD(mk__RECORDTYPE(LARGS...(FIELD := VALUE)...))
		may_be_replaced_by VALUE if
		[ \+ ((FIELD := ...) is_in LARGS),
		  \+ ((FIELD := ...) is_in RARGS) ].
	N.B.: Side conditions check uniqueness of assignment to FIELD. */
MK__RECORD3:
	FLD_FIELD_MK__RECORD_LARGS_FIELD_VALUE_RARGS may_be_replaced_by VALUE if
		[ goal(nonvar(MK__RECORD3)),
		  goal(MK__RECORD3 = mk__record(3)),
		  goal(record_function(_,
			FLD_FIELD_MK__RECORD_LARGS_FIELD_VALUE_RARGS,
			access, FIELD, [MK__RECORD_LARGS_FIELD_VALUE_RARGS], _)),
		  goal(nonvar(MK__RECORD_LARGS_FIELD_VALUE_RARGS)),
		  goal(MK__RECORD_LARGS_FIELD_VALUE_RARGS =..
			[MK__RECORDTYPE|LARGS_FIELD_VALUE_RARGS]),
		  goal(mk__function_name(MK__RECORDTYPE, _, record)),
		  goal(append(LARGS, [(FIELD := VALUE)|RARGS],
			LARGS_FIELD_VALUE_RARGS)),
		  goal(\+ is_in((FIELD := _), LARGS)),
		  goal(\+ is_in((FIELD := _), RARGS)) ].


/* mk__record(4):
	upf_FIELD(mk__RECORDTYPE(LARGS...(FIELD := OLDVAL)...RARGS), NEWVAL)
		may_be_replaced_by
	mk__RECORDTYPE(LARGS...(FIELD := NEWVAL)...RARGS) if
		[ \+ ((FIELD := ...) is_in LARGS),
		  \+ ((FIELD := ...) is_in RARGS) ].
	N.B.: Side conditions check uniqueness of assignment to FIELD. */
MK__RECORD4:
	UPF_FIELD_MK__RECORD_LARGS_FIELD_OLDVAL_RARGS_NEWVAL
		may_be_replaced_by
	MK__RECORD_LARGS_FIELD_NEWVAL_RARGS if
		[ goal(nonvar(MK__RECORD4)),
		  goal(MK__RECORD4 = mk__record(4)),
		  goal(record_function(_,
			UPF_FIELD_MK__RECORD_LARGS_FIELD_OLDVAL_RARGS_NEWVAL,
			update, FIELD,
			[MK__RECORD_LARGS_FIELD_OLDVAL_RARGS, NEWVAL], _)),
		  goal(nonvar(MK__RECORD_LARGS_FIELD_OLDVAL_RARGS)),
		  goal(MK__RECORD_LARGS_FIELD_OLDVAL_RARGS =..
			[MK__RECORDTYPE|LARGS_FIELD_OLDVAL_RARGS]),
		  goal(mk__function_name(MK__RECORDTYPE, _, record)),
		  goal(append(LARGS, [(FIELD := OLDVAL)|RARGS],
			LARGS_FIELD_OLDVAL_RARGS)),
		  goal(\+ is_in((FIELD := _), LARGS)),
		  goal(\+ is_in((FIELD := _), RARGS)),
		  goal(append(LARGS, [(FIELD := NEWVAL)|RARGS],
			LARGS_FIELD_NEWVAL_RARGS)),
		  goal(MK__RECORD_LARGS_FIELD_NEWVAL_RARGS =..
			[MK__RECORDTYPE|LARGS_FIELD_NEWVAL_RARGS]) ].
