diff --git a/apps/derive/elpi/eqb.elpi b/apps/derive/elpi/eqb.elpi index 2c1ad32ba..a55bce568 100644 --- a/apps/derive/elpi/eqb.elpi +++ b/apps/derive/elpi/eqb.elpi @@ -6,7 +6,13 @@ macro @pi-trm N T F :- pi x xx\ decl x N T => (feqb.trm->term xx x :- !) => F xx x. func derive.eqb.main gref, string -> list prop. -derive.eqb.main (indt I) Prefix CL :- std.do! [ +derive.eqb.main (indt T) Prefix C :- coq.mutual? T, !, + coq.mutual.members T TS, + derive.eqb.mutual.main T TS Prefix C. +derive.eqb.main T Prefix C :- derive.eqb.main1 T Prefix C. + +func derive.eqb.main1 gref, string -> list prop. +derive.eqb.main1 (indt I) Prefix CL :- std.do! [ std.assert! (eqType (indt I) FI) "this inductive is not supported", derive.eqb.eqbf.main FI FI [] [] R, @@ -27,9 +33,11 @@ derive.eqb.main (indt I) Prefix CL :- std.do! [ derive.eqb.eqbf.do-clause FI FI [] [] EQBF [] CL1, derive.eqb.eqb.do-clause FI FI [] [] EQB [] CL2, CL = [CL1,CL2,eqb-done (indt I)], - std.forall CL (x\ coq.elpi.accumulate _ "derive.eqb.db" (clause _ _ x)), + coq.elpi.accumulate _ "derive.eqb.db" (clause _ _ CL1), + coq.elpi.accumulate _ "derive.eqb.db" (clause _ (before "eqb-for:whd") CL2), + coq.elpi.accumulate _ "derive.eqb.db" (clause _ _ (eqb-done (indt I))), ]. -derive.eqb.main (const C) Prefix CL :- std.do! [ +derive.eqb.main1 (const C) Prefix CL :- std.do! [ coq.env.const C (some T) _, std.assert! (eqb-for T T EQB) "cannot derive eqb", Name is Prefix ^ "eqb", @@ -41,6 +49,186 @@ derive.eqb.main (const C) Prefix CL :- std.do! [ ]. % derive.eqb.main (indc _) _ _ :- stop "eqrive.eqb cannot be called on constructors". +namespace derive.eqb.mutual { + +func eqb-ty eqb.eqType, eqb.eqType, list term, list term -> term. +eqb-ty (eqb.type-param FI) (eqb.type-param FJ) PI PJ {{ forall (p : Type) (eqp : p -> p -> bool), lp:(R p eqp) }} :- !, + @pi-trm `p` {{ Type }} y\p\ + @pi-decl `eqp` {{ lp:p -> lp:p -> bool }} eqp\ + eqb-ty (FI y) (FJ y) [p|PI] [p|PJ] (R p eqp). +eqb-ty (eqb.value-param TYI FI) (eqb.value-param TYJ FJ) PI PJ {{ forall (x : lp:TI) (y : lp:TJ), lp:(R x y) }} :- !, + feqb.trm->term TYI TI, + feqb.trm->term TYJ TJ, + @pi-trm `x` TI xx\x\ + @pi-trm `y` TJ yy\y\ + eqb-ty (FI xx) (FJ yy) [x|PI] [y|PJ] (R x y). +eqb-ty (eqb.inductive Ind _) (eqb.inductive Ind _) PI PJ {{ lp:I -> lp:J -> bool }} :- + coq.env.global (indt Ind) IndT, + coq.mk-app IndT {std.rev PI} I, + coq.mk-app IndT {std.rev PJ} J. + +func eqbf-ty eqb.eqType, eqb.eqType, list term, list term -> term. +eqbf-ty (eqb.type-param FI) (eqb.type-param FJ) PI PJ {{ forall (p : Type) (eqp : p -> p -> bool), lp:(R p eqp) }} :- !, + @pi-trm `p` {{ Type }} y\p\ + @pi-decl `eqp` {{ lp:p -> lp:p -> bool }} eqp\ + eqbf-ty (FI y) (FJ y) [p|PI] [p|PJ] (R p eqp). +eqbf-ty (eqb.value-param TYI FI) (eqb.value-param TYJ FJ) PI PJ {{ forall (x : lp:TI) (y : lp:TJ), lp:(R x y) }} :- !, + feqb.trm->term TYI TI, + feqb.trm->term TYJ TJ, + @pi-trm `x` TI xx\x\ + @pi-trm `y` TJ yy\y\ + eqbf-ty (FI xx) (FJ yy) [x|PI] [y|PJ] (R x y). +eqbf-ty (eqb.inductive Ind _) (eqb.inductive Ind _) PI PJ {{ (lp:I -> lp:J -> bool) -> forall x : lib:elpi.derive.positive, lp:FieldsI x -> lp:FieldsJ x -> bool }} :- + coq.env.global (indt Ind) IndT, + coq.mk-app IndT {std.rev PI} I, + coq.mk-app IndT {std.rev PJ} J, + std.assert! (fields-for Ind F_t _ _ _) "derive.eqb: run derive.fields before", + coq.env.global (const F_t) FT, + coq.mk-app FT {std.rev PI} FieldsI, + coq.mk-app FT {std.rev PJ} FieldsJ. + +kind eqb-mutual-spec type. +type eqb-mutual-spec inductive -> term -> eqb.eqType -> list term -> eqb-mutual-spec. + +func eqb-mutual-spec-of inductive -> eqb-mutual-spec. +eqb-mutual-spec-of I (eqb-mutual-spec I (global (indt I)) FI []) :- + std.assert! (eqType (indt I) FI) "this inductive is not supported". + +func eqb-mutual-spec-ind eqb-mutual-spec -> inductive. +eqb-mutual-spec-ind (eqb-mutual-spec I _ _ _) I. + +func eqb-mutual-ty eqb-mutual-spec -> term. +eqb-mutual-ty (eqb-mutual-spec _ IT _ _) {{ lp:IT -> lp:IT -> bool }}. + +func eqb-mutual-clause eqb-mutual-spec, term -> prop. +eqb-mutual-clause (eqb-mutual-spec _ IT _ _) F (eqb-for IT IT F). + +func eqb-mutual-body eqb-mutual-spec, term -> term. +eqb-mutual-body (eqb-mutual-spec _ IT FI PI) F (fun `x1` IT (x1\ fun `x2` IT (x2\ Bo x1 x2))) :- std.do! [ + derive.eqb.eqbf.main FI FI PI PI Eqbf, + @pi-decl `x1` IT x1\ + @pi-decl `x2` IT x2\ + derive.eqb.eqb.do-match x1 IT x2 IT {coq.mk-app Eqbf [F]} (Bo x1 x2) +]. + +func eqb-mutual-mfix-aux list eqb-mutual-spec, list eqb-mutual-spec, list term -> mfix-block. +eqb-mutual-mfix-aux All [] RevF (mfix-bo Bodies) :- !, + std.rev RevF Funs, + std.map2 All Funs eqb-mutual-clause Clauses, + Clauses =!=> std.map2 All Funs eqb-mutual-body Bodies. +eqb-mutual-mfix-aux All [S|SS] RevF (mfix-ty N 0 Ty Rest) :- + S = eqb-mutual-spec I _ _ _, + coq.gref->id (indt I) ID, + coq.id->name ID N, + eqb-mutual-ty S Ty, + @pi-decl N Ty f\ eqb-mutual-mfix-aux All SS [f|RevF] (Rest f). + +func eqb-mutual-mfix list eqb-mutual-spec, int -> term. +eqb-mutual-mfix Specs Focus (mfix Focus 0 Block) :- + eqb-mutual-mfix-aux Specs Specs [] Block. + +func eqb-mutual-spec-apply-type-param eqb.trm, term, eqb-mutual-spec -> eqb-mutual-spec. +eqb-mutual-spec-apply-type-param X A (eqb-mutual-spec I IT (eqb.type-param F) PI) (eqb-mutual-spec I ITA (F X) [A|PI]) :- !, + coq.mk-app IT [A] ITA. +eqb-mutual-spec-apply-type-param _ _ _ _ :- stop "derive.eqb: mutual parameter mismatch". + +func eqb-body-mutual-params list eqb-mutual-spec, int -> term. +eqb-body-mutual-params ([eqb-mutual-spec _ _ (eqb.type-param _) _|_] as Specs) Focus R :- !, + R = {{ fun (a : Type) (eqA : a -> a -> bool) => lp:(Bo a eqA) }}, + @pi-trm `a` {{ Type }} x\a\ + @pi-decl `eqA` {{ lp:a -> lp:a -> bool }} eqA\ + sigma Specs1\ + std.map Specs (eqb-mutual-spec-apply-type-param x a) Specs1, + eqb-for a a eqA => + eqb-body-mutual-params Specs1 Focus (Bo a eqA). +eqb-body-mutual-params Specs Focus R :- + eqb-mutual-mfix Specs Focus R. + +func eqb-supported-arity term ->. +eqb-supported-arity (sort _) :- !. +eqb-supported-arity (prod _ S F) :- coq.sort? S, !, + @pi-decl `_` S x\ eqb-supported-arity (F x). + +func add-mutual-eqb-consts inductive, list eqb-mutual-spec, list eqb-mutual-spec, string, int -> list (pair inductive constant), list prop. +add-mutual-eqb-consts _ _ [] _ _ [] [] :- !. +add-mutual-eqb-consts Selected All [S|SS] Prefix Focus [pr I C|Cs] [Clause, eqb-done (indt I)|CLs] :- std.do! [ + S = eqb-mutual-spec I _ FI _, + eqb-body-mutual-params All Focus R, + std.assert-ok! (coq.typecheck R Ty) "derive.eqb generates illtyped mutual term", + derive.mutual.selected-prefix Selected Prefix I P, + Name is P ^ "eqb", + coq.ensure-fresh-global-id Name FName, + coq.env.add-const FName R Ty @transparent! C, + derive.eqb.eqb.do-clause FI FI [] [] (global (const C)) [] Clause, + coq.elpi.accumulate _ "derive.eqb.db" (clause _ (before "eqb-for:whd") Clause), + coq.elpi.accumulate _ "derive.eqb.db" (clause _ _ (eqb-done (indt I))), + Focus1 is Focus + 1, + add-mutual-eqb-consts Selected All SS Prefix Focus1 Cs CLs +]. + +func add-mutual-eqbf-consts inductive, list eqb-mutual-spec, string, list prop -> list prop. +add-mutual-eqbf-consts _ [] _ _ [] :- !. +add-mutual-eqbf-consts Selected [S|SS] Prefix EqbClauses [CL1|CLs] :- std.do! [ + S = eqb-mutual-spec I _ FI _, + EqbClauses =!=> derive.eqb.eqbf.main FI FI [] [] R, + std.assert-ok! (coq.typecheck R Ty) "derive.eqbf generates illtyped mutual term", + derive.mutual.selected-prefix Selected Prefix I P, + Name is P ^ "eqb_fields", + coq.ensure-fresh-global-id Name FName, + coq.env.add-const FName R Ty @transparent! C, + EqbClauses =!=> derive.eqb.eqbf.do-clause FI FI [] [] (global (const C)) [] CL1, + coq.elpi.accumulate _ "derive.eqb.db" (clause _ _ CL1), + add-mutual-eqbf-consts Selected SS Prefix EqbClauses CLs +]. + +func add-all-consts inductive, list inductive, string -> list prop. +add-all-consts Selected IS Prefix CL :- std.do! [ + std.map IS eqb-mutual-spec-of Specs, + add-mutual-eqb-consts Selected Specs Specs Prefix 0 _ EqbCL, + add-mutual-eqbf-consts Selected Specs Prefix EqbCL EqbfCL, + std.append EqbfCL EqbCL CL +]. + +func type-param1-eqb-ty inductive -> term. +type-param1-eqb-ty I EqbTy :- + coq.env.indt I _ 1 _ (prod N Ty _) _ _, !, + coq.env.global (indt I) IndT, + EqbTy = prod N Ty (p\ prod `eqp` (prod `_` p (_\ prod `_` p (_\ {{ bool }}))) (eqp\ prod `_` (Ip p) (_\ prod `_` (Ip p) (_\ {{ bool }})))), + @pi-decl N Ty p\ coq.mk-app IndT [p] (Ip p). + +func type-param1-eqbf-ty inductive -> term. +type-param1-eqbf-ty I EqbfTy :- + coq.env.indt I _ 1 _ (prod N Ty _) _ _, !, + coq.env.global (indt I) IndT, + std.assert! (fields-for I F_t _ _ _) "derive.eqb: run derive.fields before", + coq.env.global (const F_t) FT, + EqbfTy = prod N Ty (p\ prod `eqp` (prod `_` p (_\ prod `_` p (_\ {{ bool }}))) + (eqp\ prod `_` (prod `_` (Ip p) (_\ prod `_` (Ip p) (_\ {{ bool }}))) + (eqi\ prod `x` {{ lib:elpi.derive.positive }} (x\ prod `_` (app [Fields p, x]) (_\ prod `_` (app [Fields p, x]) (_\ {{ bool }})))))), + @pi-decl N Ty p\ + coq.mk-app IndT [p] (Ip p), + coq.mk-app FT [p] (Fields p). + +func add-one-param1 inductive, string -> list prop. +add-one-param1 I _ _ :- + coq.error "derive.eqb: mutual eqb generation for this parameterized shape still needs to be implemented" (indt I). + +func add-one inductive, string -> list prop. +add-one I Prefix CL :- eqType (indt I) (eqb.type-param _), coq.env.indt I _ 1 _ _ _ _, !, add-one-param1 I Prefix CL. +add-one I _ _ :- + std.assert! (eqType (indt I) _) "this inductive is not supported", + coq.error "derive.eqb: mutual eqb generation for this shape still needs to be implemented" (indt I). + +func main inductive, list inductive, string -> list prop. +main _ [] _ [] :- !. +main Selected ([First|_] as IS) Prefix CL :- coq.env.indt First _ Lno Lno Arity _ _, eqb-supported-arity Arity, !, + add-all-consts Selected IS Prefix CL. +main Selected IS Prefix CL :- + std.map IS (i\c\ sigma p\ derive.mutual.selected-prefix Selected Prefix i p, add-one i p c) CLS, + std.flatten CLS CL. + +} + namespace derive.eqb.eqb { % ----------------------------------------------------------------------------- @@ -112,8 +300,9 @@ do-clause (eqb.value-param _ AI) (eqb.value-param _ AJ) PI PJ F Todo (pi a b\ C do-clause (AI x) (AJ x) [a|PI] [b|PJ] {coq.mk-app F [a,b]} Todo (C a b). do-clause (eqb.inductive Ind _) (eqb.inductive Ind _) PI PJ F Todo (eqb-for I J F :- Todo) :- - coq.mk-app (global (indt Ind)) {std.rev PI} I, - coq.mk-app (global (indt Ind)) {std.rev PJ} J. + coq.env.global (indt Ind) IndT, + coq.mk-app IndT {std.rev PI} I, + coq.mk-app IndT {std.rev PJ} J. } @@ -236,8 +425,9 @@ do-clause (eqb.value-param _ AI) (eqb.value-param _ AJ) PI PJ F Todo (pi a b\ C do-clause (AI x) (AJ x) [a|PI] [b|PJ] {coq.mk-app F [a,b]} Todo (C a b). do-clause (eqb.inductive Ind _) (eqb.inductive Ind _) PI PJ F Todo (pi ela\ eqb-fields I J (F1 ela) :- [C ela|Todo]) :- !, - coq.mk-app (global (indt Ind)) {std.rev PI} I, - coq.mk-app (global (indt Ind)) {std.rev PJ} J, + coq.env.global (indt Ind) IndT, + coq.mk-app IndT {std.rev PI} I, + coq.mk-app IndT {std.rev PJ} J, pi ela\ (coq.mk-app F [ela] (F1 ela), C ela = eqb-for I J ela). diff --git a/apps/derive/elpi/eqbcorrect.elpi b/apps/derive/elpi/eqbcorrect.elpi index 2ae878955..94d5c9bf7 100644 --- a/apps/derive/elpi/eqbcorrect.elpi +++ b/apps/derive/elpi/eqbcorrect.elpi @@ -20,8 +20,101 @@ has-params? (eqb.value-param _ _). % eg: config {{ @eqb_correct }} {{ @eqb_correct_on }} {{ @eqb_body_correct }} "eqb_correct_on__solver" correct-lemma-for pred config o:term, o:term, o:term, o:string, o:(pred i:term, o:term). +namespace mutual { + +func correct-ty eqb.eqType, list term, term -> term. +correct-ty (eqb.type-param F) PI EQB {{ forall (p : Type) (eqp : p -> p -> bool), @eqb_correct p eqp -> lp:(R p eqp) }} :- !, + @pi-trm `p` {{ Type }} y\p\ + @pi-decl `eqp` {{ lp:p -> lp:p -> bool }} eqp\ + correct-ty (F y) [p|PI] {coq.mk-app EQB [p,eqp]} (R p eqp). +correct-ty (eqb.value-param TY F) PI EQB {{ forall (x y : lp:Ty), lp:(R x y) }} :- !, + feqb.trm->term TY Ty, + @pi-trm `x` Ty xx\x\ + @pi-trm `y` Ty yy\y\ + correct-ty (F xx) [x|PI] {coq.mk-app EQB [x,y]} (R x y). +correct-ty (eqb.inductive Ind _) PI EQB {{ forall x : lp:I, @eqb_correct_on lp:I lp:EQB x }} :- + coq.mk-app (global (indt Ind)) {std.rev PI} I. + +func refl-ty eqb.eqType, list term, term -> term. +refl-ty (eqb.type-param F) PI EQB {{ forall (p : Type) (eqp : p -> p -> bool), @eqb_reflexive p eqp -> lp:(R p eqp) }} :- !, + @pi-trm `p` {{ Type }} y\p\ + @pi-decl `eqp` {{ lp:p -> lp:p -> bool }} eqp\ + refl-ty (F y) [p|PI] {coq.mk-app EQB [p,eqp]} (R p eqp). +refl-ty (eqb.value-param TY F) PI EQB {{ forall (x y : lp:Ty), lp:(R x y) }} :- !, + feqb.trm->term TY Ty, + @pi-trm `x` Ty xx\x\ + @pi-trm `y` Ty yy\y\ + refl-ty (F xx) [x|PI] {coq.mk-app EQB [x,y]} (R x y). +refl-ty (eqb.inductive Ind _) PI EQB {{ forall x : lp:I, @eqb_refl_on lp:I lp:EQB x }} :- + coq.mk-app (global (indt Ind)) {std.rev PI} I. + +func aux-ty term, eqb.eqType, list term, list term, term -> term. +aux-ty Pred_on (eqb.type-param F) PI RealiArgs EQB {{ forall (p : Type) (eqp : p -> p -> bool), lp:(R p eqp) }} :- !, + @pi-trm `p` {{ Type }} y\p\ + @pi-decl `eqp` {{ lp:p -> lp:p -> bool }} eqp\ + sigma RealiArgs1\ sigma EQB1\ std.do! [ + std.append RealiArgs [p,{{ lp:Pred_on lp:p lp:eqp }}] RealiArgs1, + coq.mk-app EQB [p,eqp] EQB1, + aux-ty Pred_on (F y) [p|PI] RealiArgs1 EQB1 (R p eqp) + ]. +aux-ty Pred_on (eqb.value-param TY F) PI RealiArgs EQB {{ forall (x : lp:Ty) (px : lp:TR x), lp:(R x px) }} :- !, + feqb.trm->term TY Ty, + mk-reali Ty TR, + @pi-trm `x` Ty xx\x\ + @pi-decl `px` {{ lp:TR lp:x }} px\ + sigma RealiArgs1\ sigma EQB1\ std.do! [ + std.append RealiArgs [x,px] RealiArgs1, + coq.mk-app EQB [x,x] EQB1, + aux-ty Pred_on (F xx) [x|PI] RealiArgs1 EQB1 (R x px) + ]. +aux-ty Pred_on (eqb.inductive Ind _) PI RealiArgs EQB {{ forall x : lp:I, lp:IRR x -> lp:Pred_on lp:I lp:EQB x }} :- + coq.mk-app (global (indt Ind)) {std.rev PI} I, + mk-reali (global (indt Ind)) IR, + coq.mk-app IR RealiArgs IRR. + +func add-one list inductive, list eqb.eqType, list term, inductive, string -> list prop. +add-one _MutualInds MutualFIs MutualRealis I Prefix [Clause, ClauseC, ClauseR] :- std.do! [ + std.assert! (eqType (indt I) FI) "this inductive is not supported", + std.assert! (induction-db I Indu) "call derive.induction before", + + std.assert! ((config {{ @eqb_correct }} {{ @eqb_correct_on }} {{ @eqb_body_correct }} "eqb_correct_on__solver" correct-lemma-for => + common-mutual FI [] Indu MutualFIs MutualRealis CorrectTerm)) "derive.eqbcorrect: failed to build mutual correct proof", + std.assert-ok! (coq.typecheck CorrectTerm CTy) "derive.eqbcorrect: mutual correct proof is illtyped", + CName is Prefix ^ "eqb_correct", + coq.ensure-fresh-global-id CName FCName, + coq.env.add-const FCName CorrectTerm CTy @transparent! Correct, + + std.assert! ((config {{ @eqb_reflexive }} {{ @eqb_refl_on }} {{ @eqb_body_refl }} "eqb_refl_on__solver" refl-lemma-for => + common-mutual FI [] Indu MutualFIs MutualRealis ReflTerm)) "derive.eqbcorrect: failed to build mutual refl proof", + std.assert-ok! (coq.typecheck ReflTerm RTy) "derive.eqbcorrect: mutual refl proof is illtyped", + RName is Prefix ^ "eqb_refl", + coq.ensure-fresh-global-id RName FRName, + coq.env.add-const FRName ReflTerm RTy @transparent! Refl, + + Clause = eqcorrect-for (indt I) Correct Refl, + ClauseC = correct-lemma-for (global (indt I)) (global (const Correct)), + ClauseR = refl-lemma-for (global (indt I)) (global (const Refl)), + std.forall [Clause,ClauseC,ClauseR] (x\coq.elpi.accumulate _ "derive.eqbcorrect.db" (clause _ _ x)) +]. + +func main inductive, list inductive, string -> list prop. +main _ [] _ [] :- !. +main Selected IS Prefix CL :- + std.map IS (i\fi\ std.assert! (eqType (indt i) fi) "this inductive is not supported") MutualFIs, + std.map IS (i\r\ mk-reali (global (indt i)) r) MutualRealis, + std.map IS (i\c\ sigma p\ derive.mutual.selected-prefix Selected Prefix i p, add-one IS MutualFIs MutualRealis i p c) CLS, + std.flatten CLS CL. + +} + func main gref, string -> list prop. -main (indt I) Prefix CLs :- std.do! [ +main (indt T) Prefix C :- coq.mutual? T, !, + coq.mutual.members T TS, + mutual.main T TS Prefix C. +main T Prefix C :- main1 T Prefix C. + +func main1 gref, string -> list prop. +main1 (indt I) Prefix CLs :- std.do! [ std.assert! (eqType (indt I) FI) "this inductive is not supported", @@ -80,7 +173,7 @@ main (indt I) Prefix CLs :- std.do! [ std.forall CLs (x\coq.elpi.accumulate _ "derive.eqbcorrect.db" (clause _ _ x)), ]. -main (const C) Prefix [Clause4, ClauseC, ClauseR] :- std.do! [ +main1 (const C) Prefix [Clause4, ClauseC, ClauseR] :- std.do! [ std.assert! (eqb-for (global (const C)) (global (const C)) F) "run eqb first", coq.env.const C (some T) _, search-eqcorrect-for T Correct Refl, @@ -100,7 +193,7 @@ main (const C) Prefix [Clause4, ClauseC, ClauseR] :- std.do! [ coq.elpi.accumulate _ "derive.eqbcorrect.db" (clause _ _ ClauseC), coq.elpi.accumulate _ "derive.eqbcorrect.db" (clause _ _ ClauseR), ]. -main (indc _) _ _ :- stop "derive.eqbcorrect does not work on a constructor". +main1 (indc _) _ _ :- stop "derive.eqbcorrect does not work on a constructor". %--------------------------------------------------------------------------- @@ -210,6 +303,103 @@ common (eqb.inductive I Ks) ParamsRev Ind O :- std.do! [ O = {{ fun (x :lp:Ty) (common : lp:CommonTy := lp:Common) => lp:(R x common) }}, ]. +%--------------------------------------------------------------------------- +% Variant of common used for mutual inductives. Constructor hypotheses for +% recursive fields already receive the mutual induction hypothesis, so branch +% generation consumes that hypothesis instead of looking for a previously +% registered correctness lemma for another member of the same block. + +func mutual-reali list term, term ->. +mutual-reali [IR|_] EqbOn :- + coq.safe-dest-app EqbOn HD _, same_term HD IR, !. +mutual-reali [_|IRS] EqbOn :- mutual-reali IRS EqbOn. + +func build-mutual-branches list term, list term, list eqb.eqType, (func (list term) -> term) -> term. +build-mutual-branches _ _ [] K R :- K [] R. +build-mutual-branches MutualRealis Params [eqb.inductive I Ks|Rest] K R :- std.do! [ + config _Pred _Pred_on Pred_body _Solver _Db, + coq.mk-app (global (indt I)) Params Ty, + tag-for I TagC, + fields-for I Fields_tC FieldsC ConstructC ConstructPC, + coq.mk-app (global (const TagC)) Params Tag, + coq.mk-app (global (const Fields_tC)) Params Fields_t, + coq.mk-app (global (const FieldsC)) Params Fields, + coq.mk-app (global (const ConstructC)) Params Construct, + coq.mk-app (global (const ConstructPC)) Params ConstructP, + eqb-fields Ty Ty EqbFields, + Common = ({{ lp:Pred_body lp:Ty lp:Tag lp:Fields_t lp:Fields lp:Construct lp:ConstructP lp:EqbFields }} : term), + std.assert-ok! (coq.typecheck Common CommonTy) "WTF", + @pi-def `common` CommonTy Common c\ std.do! [ + (common-body c => fields-t Tag Fields_t Fields Construct => + pi i\ (feqb.trm->term i Ty :- !) => + std.map (Ks i) (branch-mutual MutualRealis Params) (Branches c)), + build-mutual-branches MutualRealis Params Rest (more\r\ K {std.append (Branches c) more} r) (Body c) + ], + R = (let `common` CommonTy Common c\ Body c) +]. + +func mutual-fis-apply-type-param eqb.trm, list eqb.eqType -> list eqb.eqType. +mutual-fis-apply-type-param _ [] []. +mutual-fis-apply-type-param A [eqb.type-param F|FS] [F A|FS1] :- + mutual-fis-apply-type-param A FS FS1. + +:index (1) +func common-mutual eqb.eqType, list term, term, list eqb.eqType, list term -> term. +common-mutual (eqb.type-param F) Params Ind MutualFIs MutualRealis O :- std.do! [ + config Pred Pred_on _Pred_body _Solver Db, + O = {{ fun (a : lp:Type) (eqA : a -> a -> bool) (eqAc : lp:Pred a eqA) => lp:(R a eqA eqAc) }}, + Type = sort (typ {coq.univ.new}), + @pi-trm `a` Type aa\a\ + @pi-decl `eqA` {{ lp:a -> lp:a -> bool }} eqA\ + @pi-decl `eqAc` {{ lp:Pred lp:a lp:eqA }} eqAc\ + param1-inhab-db {{ lp:Pred_on lp:a lp:eqA }} eqAc => + eqb-for a a eqA => + reali a {{ lp:Pred_on lp:a lp:eqA }} => + prove Db a {{ fun (x: lp:a) (Hx : lp:Pred_on lp:a lp:eqA x) => Hx }} => sigma MutualFIs1\ std.do! [ + std.assert! (mutual-fis-apply-type-param aa MutualFIs MutualFIs1) "derive.eqbcorrect: failed to apply mutual type parameter", + std.assert! (common-mutual (F aa) [a|Params] + {coq.mk-app Ind [a, {{ lp:Pred_on lp:a lp:eqA }} ] } + MutualFIs1 MutualRealis (R a eqA eqAc)) "derive.eqbcorrect: failed after mutual type parameter" + ] +]. + +common-mutual (eqb.value-param TY F) Params Ind MutualFIs MutualRealis O :- std.do! [ + feqb.trm->term TY T, + O = {{ fun (a : lp:T) => lp:(R a) }}, + mk-reali T TR, + std.assert! (param1-inhab-db TR Is_full) "not trivially inhabited", + @pi-trm `a` T aa\a\ + reali a {{ lp:Is_full lp:a }} => std.do! [ + std.map MutualFIs (fi\fi1\ sigma F1 TY1\ fi = eqb.value-param TY1 F1, fi1 = F1 aa) MutualFIs1, + common-mutual (F aa) [a|Params] + {{ lp:Ind lp:a (lp:Is_full lp:a) }} + MutualFIs1 MutualRealis (R a) + ] +]. + +common-mutual (eqb.inductive I _) ParamsRev Ind MutualFIs MutualRealis O :- std.do! [ + config _Pred Pred_on _Pred_body _Solver _Db, + std.rev ParamsRev Params, + coq.mk-app (global (indt I)) Params Ty, + + mk-reali (global (indt I)) IR, + coq.safe-dest-app Ind _ RealiArgs, + coq.mk-app IR RealiArgs TyR, + std.assert! (param1-inhab-db TyR Is_full) "not trivially inhabited", + + std.map MutualFIs (fi\m\ sigma J Ks TyJ CmpJ\ + fi = eqb.inductive J Ks, + coq.mk-app (global (indt J)) Params TyJ, + mk-eqb-for TyJ CmpJ, + m = {{ lp:Pred_on lp:TyJ lp:CmpJ }}) Motives, + + (@pi-decl `x` Ty x\ + build-mutual-branches MutualRealis Params MutualFIs + (branches\r\ coq.mk-app Ind {std.append Motives {std.append branches [x, app[Is_full,x]]}} r) + (R x)), + O = {{ fun (x :lp:Ty) => lp:(R x) }}, +]. + %--------------------------------------------------------------------------- :index (1) @@ -264,6 +454,64 @@ common-aux (eqb.inductive I Ks) ParamsRev Ind O :- std.do! [ %--------------------------------------------------------------------------- +func branch-mutual list term, list term, eqb.constructor -> term. +branch-mutual MutualRealis Params (eqb.constructor K Args) R :- + coq.mk-app (global (indc K)) Params KParams, + args-mutual MutualRealis Args KParams [] [] [] 0 R. + +:index (2) +func args-mutual list term, eqb.arguments, term, list term, list term, list term, int -> term. +args-mutual MutualRealis (eqb.irrelevant TY Args) K As Hs Bs N O :- !, std.do! [ + O = {{ fun (x : lp:T) (px : lp:EqbOn x) => lp:(R x px) }}, + feqb.trm->term TY T, + mk-reali T EqbOn, + @pi-decl `x` T x\ + @pi-decl `px` {{ lp:EqbOn lp:x }} px\ + args-mutual MutualRealis Args {coq.mk-app K [x]} [x|As] Hs Bs {calc (N + 1)} (R x px) +]. + +args-mutual MutualRealis (eqb.regular TY Args) K As Hs Bs N O :- !, std.do! [ + config _Pred Pred_on _Pred_body _Solver Db, + feqb.trm->term TY T, + mk-reali T EqbOn, + mk-eqb-for T Cmp, + EqbOn' = {{ lp:Pred_on lp:T lp:Cmp }}, + if (mutual-reali MutualRealis EqbOn) + (O = {{ fun (x : lp:T) (px : lp:EqbOn x) (h : lp:EqbOn' x) => lp:(R x px h) }}, + @pi-decl `x` T x\ + @pi-decl `px` {{ lp:EqbOn lp:x }} px\ + @pi-decl `h` {{ lp:EqbOn' lp:x }} h\ + args-mutual MutualRealis Args {coq.mk-app K [x]} [x|As] [h|Hs] [{{ lp:Cmp lp:x }}|Bs] N (R x px h)) + (O = {{ fun (x : lp:T) (px : lp:EqbOn x) (h : lp:EqbOn' x := lp:View x px) => lp:(R x px h) }}, + if (same_term EqbOn EqbOn') (View = {{ fun (x : lp:T) (px : lp:EqbOn x) => px }}) (prove Db T View), + @pi-decl `x` T x\ + @pi-decl `px` {{ lp:EqbOn lp:x }} px\ + @pi-def `h` {{ lp:EqbOn' lp:x }} {{ lp:View lp:x lp:px }} h\ + args-mutual MutualRealis Args {coq.mk-app K [x]} [x|As] [h|Hs] [{{ lp:Cmp lp:x }}|Bs] N (R x px h)) +]. + +args-mutual MutualRealis (eqb.dependent TY Args) K As Hs Bs N O :- !, std.do! [ + config _Pred Pred_on _Pred_body _Solver Db, + feqb.trm->term TY T, + mk-reali T EqbOn, + mk-eqb-for T Cmp, + EqbOn' = {{ lp:Pred_on lp:T lp:Cmp }}, + if (mutual-reali MutualRealis EqbOn) + (O = {{ fun (x : lp:T) (px : lp:EqbOn x) (h : lp:EqbOn' x) => lp:(R x px h) }}, + @pi-trm `x` T xx\x\ + @pi-decl `px` {{ lp:EqbOn lp:x }} px\ reali x px => + @pi-decl `h` {{ lp:EqbOn' lp:x }} h\ + args-mutual MutualRealis (Args xx) {coq.mk-app K [x]} [x|As] [h|Hs] [{{ lp:Cmp lp:x }}|Bs] {calc (N + 1)} (R x px h)) + (O = {{ fun (x : lp:T) (px : lp:EqbOn x) (h : lp:EqbOn' x := lp:View x px) => lp:(R x px h) }}, + if (same_term EqbOn EqbOn') (View = {{ fun (x : lp:T) (px : lp:EqbOn x) => px }}) (prove Db T View), + @pi-trm `x` T xx\x\ + @pi-decl `px` {{ lp:EqbOn lp:x }} px\ reali x px => + @pi-def `h` {{ lp:EqbOn' lp:x }} {{ lp:View lp:x lp:px }} h\ + args-mutual MutualRealis (Args xx) {coq.mk-app K [x]} [x|As] [h|Hs] [{{ lp:Cmp lp:x }}|Bs] {calc (N + 1)} (R x px h)) +]. + +args-mutual _ (eqb.stop TY) K As Hs Bs N O :- !, args (eqb.stop TY) K As Hs Bs N O. + func branch list term, eqb.constructor -> term. branch Params (eqb.constructor K Args) R :- coq.mk-app (global (indc K)) Params KParams, diff --git a/apps/derive/elpi/fields.elpi b/apps/derive/elpi/fields.elpi index aa4213d08..28d87a032 100644 --- a/apps/derive/elpi/fields.elpi +++ b/apps/derive/elpi/fields.elpi @@ -49,7 +49,7 @@ main I Prefix AllCL :- std.do! [ std.assert-ok! (coq.elaborate-skeleton Body_PSkel Ty_P Body_P) "derive.fields generates illtyped constructP", Name_P is Prefix ^ "constructP", coq.ensure-fresh-global-id Name_P FName_P, - coq.env.add-const FName_P Body_P Ty_P @opaque! ConstructP, + coq.env.add-const FName_P Body_P Ty_P @opaque! ConstructP, AllCL = [fields-for I Fields_t Fields Construct ConstructP|CLB], std.forall AllCL (x\ coq.elpi.accumulate _ "derive.fields.db" (clause _ _ x)), @@ -59,9 +59,15 @@ main I Prefix AllCL :- std.do! [ % ---------------------------------------------------------------------- :index (1) +func type-param-domain term -> term. +type-param-domain I Ty :- + std.assert-ok! (coq.typecheck I ITy) "derive.fields: illtyped type parameter head", + ITy = prod _ Ty _. + func fields_t.main eqb.eqType, term -> term. -fields_t.main (eqb.type-param F) I {{ fun p : Type => lp:(R p) }} :- !, - @pi-trm `p` {{ Type }} x\p\ +fields_t.main (eqb.type-param F) I (fun `p` Ty R) :- !, + type-param-domain I Ty, + @pi-trm `p` Ty x\p\ fields_t.main (F x) {coq.mk-app I [p]} (R p). fields_t.main (eqb.value-param TY F) I {{ fun p : lp:Ty => lp:(R p) }} :- !, @@ -86,8 +92,9 @@ fields_t.k Params (eqb.constructor K _) T :- % ---------------------------------------------------------------------- func fields.main eqb.eqType, term, term, term -> term. -fields.main (eqb.type-param F) I F_t Tag {{ fun p : Type => lp:(R p) }} :- !, - @pi-trm `p` {{ Type }} x\p\ +fields.main (eqb.type-param F) I F_t Tag (fun `p` Ty R) :- !, + type-param-domain I Ty, + @pi-trm `p` Ty x\p\ fields.main (F x) {coq.mk-app I [p]} {coq.mk-app F_t [p]} {coq.mk-app Tag [p]} (R p). fields.main (eqb.value-param TY F) I F_t Tag {{ fun p : lp:Ty => lp:(R p) }} :- !, @@ -136,9 +143,10 @@ kind box-spec type. func box.aux eqb.eqType, term -> list box-spec. box.aux (eqb.type-param F) I L :- - (@pi-trm `p` {{ Type }} x\y\ + type-param-domain I Ty, + (@pi-trm `p` Ty x\y\ box.aux (F x) {coq.mk-app I [y]} (L1 y)), - distribute L1 (f\r\ sigma U\ r = parameter "A" explicit (sort (typ U)) f) L. + distribute L1 (f\r\ r = parameter "A" explicit Ty f) L. box.aux (eqb.value-param TY F) I L :- feqb.trm->term TY Ty, @@ -180,8 +188,9 @@ distribute (x\ [same-box K| XS x]) F [same-box K|R] :- distribute XS F R. % ---------------------------------------------------------------------- :index(1) func construct.main eqb.eqType, term, constant -> term. -construct.main (eqb.type-param F) I F_t {{ fun p : Type => lp:(R p) }} :- - @pi-trm `p` {{ Type }} x\p\ +construct.main (eqb.type-param F) I F_t (fun `p` Ty R) :- + type-param-domain I Ty, + @pi-trm `p` Ty x\p\ construct.main (F x) {coq.mk-app I [p]} F_t (R p). construct.main (eqb.value-param TY F) I F_t {{ fun p : lp:Ty => lp:(R p) }} :- diff --git a/apps/derive/elpi/induction.elpi b/apps/derive/elpi/induction.elpi index 39b790139..e12b0c917 100644 --- a/apps/derive/elpi/induction.elpi +++ b/apps/derive/elpi/induction.elpi @@ -117,6 +117,474 @@ params 0 Ity K KT Arity (fun `P` Pty p\ Bo p) :- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +kind derive.induction.mutual-spec type. +type derive.induction.mutual-spec inductive -> inductive -> term -> term -> list term -> list term -> derive.induction.mutual-spec. + +func mutual-spec inductive -> derive.induction.mutual-spec. +mutual-spec GR (derive.induction.mutual-spec GR GRR (global (indt GRR)) Arity K KT) :- + reali (global (indt GR)) (global (indt GRR)), + coq.env.indt GRR _ _ _ Arity KGR KT, + std.map KGR (k\r\ r = global (indc k)) K. + +func mutual-spec-ind derive.induction.mutual-spec -> inductive. +mutual-spec-ind (derive.induction.mutual-spec _ GRR _ _ _ _) GRR. + +func mutual-spec-arity derive.induction.mutual-spec -> term. +mutual-spec-arity (derive.induction.mutual-spec _ _ _ Arity _ _) Arity. + +func mutual-spec-apply-param term, derive.induction.mutual-spec -> derive.induction.mutual-spec. +mutual-spec-apply-param A (derive.induction.mutual-spec GR GRR IsT (prod _ _ F) K KT) + (derive.induction.mutual-spec GR GRR IsTA (F A) KA KTA) :- !, + coq.mk-app IsT [A] IsTA, + map K (k\ coq.mk-app k [A]) KA, + map KT (coq.subst-prod [A]) KTA. +mutual-spec-apply-param _ _ _ :- stop "derive.induction: mutual parameter mismatch". + +func mutual-spec-apply-param2 term, term, derive.induction.mutual-spec -> derive.induction.mutual-spec. +mutual-spec-apply-param2 A PA (derive.induction.mutual-spec GR GRR IsT (prod _ _ (a\ prod _ _ (pa\ F a pa))) K KT) + (derive.induction.mutual-spec GR GRR IsTAP (F A PA) KAP KTAP) :- !, + coq.mk-app IsT [A,PA] IsTAP, + map K (k\ coq.mk-app k [A,PA]) KAP, + map KT (coq.subst-prod [A,PA]) KTAP. +mutual-spec-apply-param2 _ _ _ _ :- stop "derive.induction: mutual parameter mismatch". + +func mutual-specs-apply-param2 term, term, list derive.induction.mutual-spec -> list derive.induction.mutual-spec. +mutual-specs-apply-param2 _ _ [] []. +mutual-specs-apply-param2 A PA [S|SS] [S1|SS1] :- + mutual-spec-apply-param2 A PA S S1, + mutual-specs-apply-param2 A PA SS SS1. + +func mk-app-prefix term, list term -> term. +mk-app-prefix (app L) Args (app AllArgs) :- !, + std.append L Args AllArgs. +mk-app-prefix F Args (app [F|Args]) :- !. + +pred pred-prefix i:term, i:term, o:list term. +pred-prefix IsT T Rest :- + coq.safe-dest-app IsT HDI IArgs, + coq.safe-dest-app T HD Args, + same_term HD HDI, + appendR IArgs Rest Args. + +func pred-app list term, list term, term -> term. +pred-app [IsT|_] [P|_] T R :- + pred-prefix IsT T Args, !, + coq.mk-app P Args R. +pred-app [_|IS] [_|PS] T R :- pred-app IS PS T R. + +func hyp-mutual list term, list term, term -> term. +hyp-mutual IsTs Ps (prod N S T) (prod N S R) :- !, + @pi-decl N S x\ + if (pred-app IsTs Ps S IH) + (R x = prod `IH` IH (ih\ R1 x ih), + @pi-decl `IH` IH ih\ hyp-mutual IsTs Ps (T x) (R1 x ih)) + (hyp-mutual IsTs Ps (T x) (R x)). +hyp-mutual IsTs Ps S R :- pred-app IsTs Ps S R, !. +hyp-mutual _ _ S S. + +func conclusion-mutual term, term, term -> term. +conclusion-mutual Arity IsT P Ty :- conclusion-mutual.aux Arity IsT P [] Ty. +func conclusion-mutual.aux term, term, term, list term -> term. +conclusion-mutual.aux (prod N S T) IsT P RevArgs (prod N S R) :- !, + @pi-decl N S x\ conclusion-mutual.aux (T x) IsT P [x|RevArgs] (R x). +conclusion-mutual.aux (sort _) IsT P RevArgs (prod `H` IsTArgs _\ PArgs) :- !, + std.rev RevArgs Args, + coq.mk-app IsT Args IsTArgs, + coq.mk-app P Args PArgs. +conclusion-mutual.aux _ _ _ _ _ :- stop "derive.induction: mutual indexed data types not supported". + +func add-hyps list term, list term, list term, list term, term -> term. +add-hyps _ _ [] [] K K. +add-hyps IsTs Ps [Kc|KS] [KT|KTS] K Ty :- + hyp-mutual IsTs Ps KT HTy, + coq.term->gref Kc GRK, + coq.name-suffix `H` {coq.gref->id GRK} HN, + Ty = prod HN HTy R, + @pi-decl HN HTy h\ add-hyps IsTs Ps KS KTS K (R h). + +func collect-terms list derive.induction.mutual-spec -> list term, list term, list term. +collect-terms [] [] [] []. +collect-terms [derive.induction.mutual-spec _ _ IsT _ K KT|SS] [IsT|IS] KAll KTAll :- + collect-terms SS IS KRest KTRest, + std.append K KRest KAll, + std.append KT KTRest KTAll. + +func mutual-induction-type-base list derive.induction.mutual-spec, int -> term. +mutual-induction-type-base Specs Focus Ty :- + mutual-induction-type-motives Specs Specs [] Focus Ty. + +func mutual-induction-type-motives list derive.induction.mutual-spec, list derive.induction.mutual-spec, list term, int -> term. +mutual-induction-type-motives All [] RevPs Focus Ty :- !, + std.rev RevPs Ps, + collect-terms All IsTs KAll KTAll, + std.nth Focus All S, + S = derive.induction.mutual-spec _ _ IsT Arity _ _, + std.nth Focus Ps P, + conclusion-mutual Arity IsT P Conclusion, + add-hyps IsTs Ps KAll KTAll Conclusion Ty. +mutual-induction-type-motives All [S|SS] RevPs Focus (prod `P` PTy R) :- + S = derive.induction.mutual-spec _ _ _ Arity _ _, + truncated-predicate-ty Arity PTy, + @pi-decl `P` PTy p\ mutual-induction-type-motives All SS [p|RevPs] Focus (R p). + +func mutual-induction-type int, list derive.induction.mutual-spec, int -> term. +mutual-induction-type 0 Specs Focus Ty :- !, mutual-induction-type-base Specs Focus Ty. +mutual-induction-type 2 ([S|_] as Specs) Focus (prod A TA (a\ prod P (TP a) (pa\ Rest a pa))) :- + mutual-spec-arity S (prod A TA (a\ prod P (TP a) _)), coq.sort? TA, !, + @pi-decl A TA a\ @pi-decl P (TP a) pa\ sigma Specs1\ + mutual-specs-apply-param2 a pa Specs Specs1, + mutual-induction-type 0 Specs1 Focus (Rest a pa). +mutual-induction-type N ([S|_] as Specs) Focus (prod A TA R) :- N > 0, !, + mutual-spec-arity S (prod A TA _), + M is N - 1, + @pi-decl A TA a\ sigma Specs1\ + std.map Specs (mutual-spec-apply-param a) Specs1, + mutual-induction-type M Specs1 Focus (R a). + +func arity-recno term, int -> int. +arity-recno (prod _ _ T) N R :- !, + pi x\ arity-recno (T x) {calc (N + 1)} R. +arity-recno (sort _) N N :- !. +arity-recno X N R :- whd1 X X1, !, arity-recno X1 N R. +arity-recno _ _ _ :- stop "derive.induction: mutual indexed data types not supported". + +func mutual-induction-fix-ty derive.induction.mutual-spec, term -> term, int. +mutual-induction-fix-ty (derive.induction.mutual-spec _ _ IsT Arity _ _) P Ty Recno :- + conclusion-mutual Arity IsT P Ty, + arity-recno Arity 0 Recno. + +func rec-call list term, list term, term, term -> term. +rec-call [IsT|_] [F|_] S X R :- + pred-prefix IsT S Args, !, + std.append Args [X] ArgsX, + coq.mk-app F ArgsX R. +rec-call [_|IS] [_|FS] S X R :- rec-call IS FS S X R. + +func mutual-branch-args list term, list term, list term, list term, list term -> list term. +mutual-branch-args _ _ [] [] Acc Args :- !, std.rev Acc Args. +mutual-branch-args IsTs Fs [V|VS] [VT|VTS] Acc Args :- + if (rec-call IsTs Fs VT V IH) + (mutual-branch-args IsTs Fs VS VTS [IH,V|Acc] Args) + (mutual-branch-args IsTs Fs VS VTS [V|Acc] Args). + +func branch-mutual list term, list term, term, term, list term, list term -> term. +branch-mutual IsTs Fs K _ Vars Tys R :- + induction-hyp-db K IH, + mutual-branch-args IsTs Fs Vars Tys [] Args, + coq.mk-app IH Args R. + +func oty-mutual list term, list term, term, list term, list term -> term. +oty-mutual IsTs Ps _ _ Tys R :- + last Tys ProofTy, + pred-app IsTs Ps ProofTy R. + +func mutual-induction-fix-body list term, list term, list term, derive.induction.mutual-spec -> term. +mutual-induction-fix-body IsTs Ps Fs (derive.induction.mutual-spec _ _GRR IsT Arity _ _) Body :- + mutual-induction-fix-body.aux IsTs Ps Fs IsT Arity [] Body. + +func mutual-induction-fix-body.aux list term, list term, list term, term, term, list term -> term. +mutual-induction-fix-body.aux IsTs Ps Fs IsT (prod N S T) RevArgs (fun N S R) :- !, + @pi-decl N S x\ mutual-induction-fix-body.aux IsTs Ps Fs IsT (T x) [x|RevArgs] (R x). +mutual-induction-fix-body.aux IsTs Ps Fs IsT (sort _) RevArgs (fun `H` IsTArgs Bo) :- !, + std.rev RevArgs Args, + coq.mk-app IsT Args IsTArgs, + @pi-decl `H` IsTArgs h\ + coq.build-match h IsTArgs (oty-mutual IsTs Ps) (branch-mutual IsTs Fs) (Bo h). +mutual-induction-fix-body.aux _ _ _ _ _ _ _ :- stop "derive.induction: mutual indexed data types not supported". + +func mutual-induction-mfix-aux list derive.induction.mutual-spec, list derive.induction.mutual-spec, list term, list term, list term -> mfix-block. +mutual-induction-mfix-aux All [] AllPs [] RevF (mfix-bo Bodies) :- !, + std.rev RevF Fs, + collect-terms All IsTs _ _, + std.map All (mutual-induction-fix-body IsTs AllPs Fs) Bodies. +mutual-induction-mfix-aux All [S|SS] AllPs [P|PS] PsRevF (mfix-ty N Recno Ty Rest) :- + S = derive.induction.mutual-spec _ GRR _ _ _ _, + ID is {coq.gref->id (indt GRR)} ^ "_induction_rec", + coq.id->name ID N, + mutual-induction-fix-ty S P Ty Recno, + @pi-decl N Ty f\ mutual-induction-mfix-aux All SS AllPs PS [f|PsRevF] (Rest f). + +func mutual-induction-mfix list derive.induction.mutual-spec, list term, int -> term. +mutual-induction-mfix Specs Ps Focus (mfix Focus Recno Block) :- + std.nth Focus Specs S, + std.nth Focus Ps P, + mutual-induction-fix-ty S P _ Recno, + mutual-induction-mfix-aux Specs Specs Ps Ps [] Block. + +func mutual-induction-param1-recno list derive.induction.mutual-spec, int -> int. +mutual-induction-param1-recno Specs Focus Recno :- + std.nth Focus Specs S, + S = derive.induction.mutual-spec _ _ _ Arity _ _, + arity-recno Arity 0 RecArity, + std.length Specs MotNo, + collect-terms Specs _ KAll _, + std.length KAll KNo, + Recno is 2 + MotNo + KNo + RecArity. + +func mutual-induction-param1-fix-ty list derive.induction.mutual-spec, int -> term, int. +mutual-induction-param1-fix-ty All Focus (prod A TA (a\ prod P (TP a) (pa\ Rest a pa))) Recno :- + std.nth Focus All S, + S = derive.induction.mutual-spec _ _ _ (prod A TA (a\ prod P (TP a) _)) _ _, + coq.sort? TA, !, + @pi-decl A TA a\ @pi-decl P (TP a) pa\ sigma Specs1\ + mutual-specs-apply-param2 a pa All Specs1, + mutual-induction-type-base Specs1 Focus (Rest a pa), + mutual-induction-param1-recno Specs1 Focus Recno. + +func mutual-induction-param1-rty-motives list derive.induction.mutual-spec, list derive.induction.mutual-spec, list term, list term, list term, list term, int, term -> term. +mutual-induction-param1-rty-motives _ [] RevPs IsTs KAll KTAll _ ProofTy R :- !, + std.rev RevPs Ps, + pred-app IsTs Ps ProofTy Conclusion, + add-hyps IsTs Ps KAll KTAll Conclusion R. +mutual-induction-param1-rty-motives All [S|SS] RevPs IsTs KAll KTAll Focus ProofTy (prod `P` PTy R) :- + S = derive.induction.mutual-spec _ _ _ Arity _ _, + truncated-predicate-ty Arity PTy, + @pi-decl `P` PTy p\ mutual-induction-param1-rty-motives All SS [p|RevPs] IsTs KAll KTAll Focus ProofTy (R p). + +func mutual-induction-param1-rty list derive.induction.mutual-spec, int, term, list term, list term -> term. +mutual-induction-param1-rty All Focus _ _ Tys R :- + std.assert! (last Tys ProofTy) "derive.induction: failed to select parameterized match proof type", + std.assert! (coq.safe-dest-app ProofTy _ [A,PA|_]) "derive.induction: failed to read parameterized match proof type", + std.assert! (mutual-specs-apply-param2 A PA All Specs1) "derive.induction: failed to apply parameterized match params", + std.assert! (collect-terms Specs1 IsTs KAll KTAll) "derive.induction: failed to collect parameterized match terms", + std.assert! (mutual-induction-param1-rty-motives Specs1 Specs1 [] IsTs KAll KTAll Focus ProofTy R) "derive.induction: failed to build parameterized match return type". + +func apply-rec-funs list term, list term -> list term. +apply-rec-funs _ [] []. +apply-rec-funs Args [F|FS] [FA|FAS] :- + coq.mk-app F Args FA, + apply-rec-funs Args FS FAS. + +func branch-mutual-applied list term, list term, term, list term, list term -> term. +branch-mutual-applied IsTs Fs K Vars Tys R :- + induction-hyp-db K IH, + mutual-branch-args IsTs Fs Vars Tys [] Args, + coq.mk-app IH Args R. + +func branch-mutual-param1-hyps term, term, list term, list term, list term, list term, list term, list term, term, list term, list term -> term. +branch-mutual-param1-hyps A PA IsTs Ps [] [] RevHs Fs K Vars Tys R :- !, + std.rev RevHs Hs, + std.append [A,PA] Ps Args0, + std.append Args0 Hs Args, + apply-rec-funs Args Fs FsApplied, + branch-mutual-applied IsTs FsApplied K Vars Tys R. +branch-mutual-param1-hyps A PA IsTs Ps [Kc|KS] [KT|KTS] RevHs Fs K Vars Tys (fun HN HTy R) :- + hyp-mutual IsTs Ps KT HTy, + coq.term->gref Kc GRK, + coq.name-suffix `H` {coq.gref->id GRK} HN, + @pi-decl HN HTy h\ + induction-hyp-db Kc h =!=> + branch-mutual-param1-hyps A PA IsTs Ps KS KTS [h|RevHs] Fs K Vars Tys (R h). + +func branch-mutual-param1-motives term, term, list derive.induction.mutual-spec, list derive.induction.mutual-spec, list term, list term, list term, list term, list term, term, list term, list term -> term. +branch-mutual-param1-motives A PA _All [] RevPs IsTs KAll KTAll Fs K Vars Tys R :- !, + std.rev RevPs Ps, + branch-mutual-param1-hyps A PA IsTs Ps KAll KTAll [] Fs K Vars Tys R. +branch-mutual-param1-motives A PA All [S|SS] RevPs IsTs KAll KTAll Fs K Vars Tys (fun `P` PTy R) :- + S = derive.induction.mutual-spec _ _ _ Arity _ _, + truncated-predicate-ty Arity PTy, + @pi-decl `P` PTy p\ branch-mutual-param1-motives A PA All SS [p|RevPs] IsTs KAll KTAll Fs K Vars Tys (R p). + +func branch-mutual-param1 list derive.induction.mutual-spec, list term, term, term, list term, list term -> term. +branch-mutual-param1 All Fs K _ [A,PA|Vars] [_T,_TP|Tys] R :- !, + sigma Specs1 KAP IsTs KAll KTAll\ + std.assert! (mutual-specs-apply-param2 A PA All Specs1) "derive.induction: failed to apply parameterized branch params", + std.assert! (coq.mk-app K [A,PA] KAP) "derive.induction: failed to apply parameterized branch constructor", + std.assert! (collect-terms Specs1 IsTs KAll KTAll) "derive.induction: failed to collect parameterized branch terms", + std.assert! (branch-mutual-param1-motives A PA Specs1 Specs1 [] IsTs KAll KTAll Fs KAP Vars Tys R) "derive.induction: failed to build parameterized branch body". + +func mutual-induction-param1-fix-body-final-aux list derive.induction.mutual-spec, term, list term, list term, list term, int, term, list term -> term. +mutual-induction-param1-fix-body-final-aux OrigAll IsT Ps Hs Fs Focus (prod N S T) RevArgs (fun N S R) :- !, + @pi-decl N S x\ mutual-induction-param1-fix-body-final-aux OrigAll IsT Ps Hs Fs Focus (T x) [x|RevArgs] (R x). +mutual-induction-param1-fix-body-final-aux OrigAll IsT Ps Hs Fs Focus (sort _) RevArgs (fun `H` IsTArgs Bo) :- !, + std.rev RevArgs Args, + std.assert! (mk-app-prefix IsT Args IsTArgs) "derive.induction: failed to apply parameterized mutual fix body proof type", + @pi-decl `H` IsTArgs h\ sigma Match Args0\ + std.assert! (coq.build-match h IsTArgs (mutual-induction-param1-rty OrigAll Focus) (branch-mutual-param1 OrigAll Fs) Match) "derive.induction: failed to build parameterized mutual proof match", + std.append Ps Hs Args0, + std.assert! (coq.mk-app Match Args0 (Bo h)) "derive.induction: failed to apply parameterized mutual proof match". +mutual-induction-param1-fix-body-final-aux _ _ _ _ _ _ _ _ _ :- stop "derive.induction: mutual indexed data types not supported". + +func mutual-induction-param1-fix-body-final list derive.induction.mutual-spec, list derive.induction.mutual-spec, list term, list term, list term, int -> term. +mutual-induction-param1-fix-body-final OrigAll Specs Ps Hs Fs Focus R :- + std.assert! (std.nth Focus Specs SF) "derive.induction: failed to select parameterized mutual fix body spec", + SF = derive.induction.mutual-spec _ _ IsT Arity _ _, + mutual-induction-param1-fix-body-final-aux OrigAll IsT Ps Hs Fs Focus Arity [] R. + +func mutual-induction-param1-fix-body-hyps list derive.induction.mutual-spec, list derive.induction.mutual-spec, list term, list term, list term, list term, list term, int -> term. +mutual-induction-param1-fix-body-hyps OrigAll Specs Ps [] [] RevHs Fs Focus R :- !, + std.rev RevHs Hs, + std.assert! (mutual-induction-param1-fix-body-final OrigAll Specs Ps Hs Fs Focus R) "derive.induction: failed to build parameterized mutual fix body final match". +mutual-induction-param1-fix-body-hyps OrigAll Specs Ps [Kc|KS] [KT|KTS] RevHs Fs Focus (fun HN HTy R) :- + std.assert! (collect-terms Specs IsTs _ _) "derive.induction: failed to collect parameterized mutual body terms", + std.assert! (hyp-mutual IsTs Ps KT HTy) "derive.induction: failed to build parameterized mutual body hypothesis type", + std.assert! (coq.term->gref Kc GRK) "derive.induction: failed to identify parameterized mutual body constructor", + coq.name-suffix `H` {coq.gref->id GRK} HN, + @pi-decl HN HTy h\ + induction-hyp-db Kc h =!=> + std.assert! (mutual-induction-param1-fix-body-hyps OrigAll Specs Ps KS KTS [h|RevHs] Fs Focus (R h)) "derive.induction: failed to build rest parameterized mutual body hypotheses". + +func mutual-induction-param1-fix-body-motives list derive.induction.mutual-spec, list derive.induction.mutual-spec, list derive.induction.mutual-spec, list term, list term, int -> term. +mutual-induction-param1-fix-body-motives OrigAll Specs [] RevPs Fs Focus R :- !, + std.rev RevPs Ps, + std.assert! (collect-terms Specs _ KAll KTAll) "derive.induction: failed to collect parameterized mutual body constructors", + std.assert! (mutual-induction-param1-fix-body-hyps OrigAll Specs Ps KAll KTAll [] Fs Focus R) "derive.induction: failed to build parameterized mutual body hypotheses". +mutual-induction-param1-fix-body-motives OrigAll Specs [S|SS] RevPs Fs Focus (fun `P` PTy R) :- + S = derive.induction.mutual-spec _ _ _ Arity _ _, + std.assert! (truncated-predicate-ty Arity PTy) "derive.induction: failed to build parameterized mutual body motive type", + @pi-decl `P` PTy p\ std.assert! (mutual-induction-param1-fix-body-motives OrigAll Specs SS [p|RevPs] Fs Focus (R p)) "derive.induction: failed to build rest parameterized mutual body motives". + +func mutual-induction-param1-fix-body list derive.induction.mutual-spec, list term, int -> term. +mutual-induction-param1-fix-body All Fs Focus (fun A TA (a\ fun P (TP a) (pa\ Rest a pa))) :- + std.assert! (std.nth Focus All S) "derive.induction: failed to select parameterized mutual body spec", + S = derive.induction.mutual-spec _ _ _ (prod A TA (a\ prod P (TP a) _)) _ _, coq.sort? TA, !, + @pi-decl A TA a\ @pi-decl P (TP a) pa\ sigma Specs1\ + std.assert! (mutual-specs-apply-param2 a pa All Specs1) "derive.induction: failed to apply parameterized mutual body params", + std.assert! (mutual-induction-param1-fix-body-motives All Specs1 Specs1 [] Fs Focus (Rest a pa)) "derive.induction: failed to build parameterized mutual body after params". + +func mutual-induction-param1-bodies list derive.induction.mutual-spec, list term, list derive.induction.mutual-spec, int -> list term. +mutual-induction-param1-bodies _ _ [] _ []. +mutual-induction-param1-bodies All Fs [_|SS] Focus [B|BS] :- + std.assert! (mutual-induction-param1-fix-body All Fs Focus B) "derive.induction: failed to build one parameterized mutual fix body", + Focus1 is Focus + 1, + std.assert! (mutual-induction-param1-bodies All Fs SS Focus1 BS) "derive.induction: failed to build rest parameterized mutual fix bodies". + +func mutual-induction-param1-mfix-aux list derive.induction.mutual-spec, list derive.induction.mutual-spec, int, list term -> mfix-block. +mutual-induction-param1-mfix-aux All [] _ RevF (mfix-bo Bodies) :- !, + std.rev RevF Fs, + std.assert! (mutual-induction-param1-bodies All Fs All 0 Bodies) "derive.induction: failed to build parameterized mutual fix bodies". +mutual-induction-param1-mfix-aux All [S|SS] Focus RevF (mfix-ty N Recno Ty Rest) :- + S = derive.induction.mutual-spec _ GRR _ _ _ _, + ID is {coq.gref->id (indt GRR)} ^ "_induction_rec", + coq.id->name ID N, + std.assert! (mutual-induction-param1-fix-ty All Focus Ty Recno) "derive.induction: failed to build parameterized mutual fix type", + @pi-decl N Ty f\ + Focus1 is Focus + 1, + std.assert! (mutual-induction-param1-mfix-aux All SS Focus1 [f|RevF] (Rest f)) "derive.induction: failed to build rest parameterized mutual fix block". + +func mutual-induction-param1-mfix list derive.induction.mutual-spec, int -> term. +mutual-induction-param1-mfix Specs Focus (mfix Focus Recno Block) :- + std.assert! (mutual-induction-param1-fix-ty Specs Focus _ Recno) "derive.induction: failed to build selected parameterized mutual fix type", + std.assert! (mutual-induction-param1-mfix-aux Specs Specs 0 [] Block) "derive.induction: failed to build parameterized mutual fix block". + +func mutual-induction-param1-term-final-aux term, term, list derive.induction.mutual-spec, term, list term, list term, int, term, list term -> term. +mutual-induction-param1-term-final-aux A PA OrigAll IsT Ps Hs Focus (prod N S T) RevArgs (fun N S R) :- !, + @pi-decl N S x\ mutual-induction-param1-term-final-aux A PA OrigAll IsT Ps Hs Focus (T x) [x|RevArgs] (R x). +mutual-induction-param1-term-final-aux A PA OrigAll IsT Ps Hs Focus (sort _) RevArgs (fun `H` IsTArgs Bo) :- !, + std.rev RevArgs IndArgs, + std.assert! (mk-app-prefix IsT IndArgs IsTArgs) "derive.induction: failed to apply parameterized mutual proof type", + @pi-decl `H` IsTArgs h\ sigma Fix Args0 Args1 Args2 Args\ + std.assert! (mutual-induction-param1-mfix OrigAll Focus Fix) "derive.induction: failed to build parameterized mutual fixpoint", + std.append [A,PA] Ps Args0, + std.append Args0 Hs Args1, + std.append Args1 IndArgs Args2, + std.append Args2 [h] Args, + std.assert! (coq.mk-app Fix Args (Bo h)) "derive.induction: failed to apply parameterized mutual fixpoint". +mutual-induction-param1-term-final-aux _ _ _ _ _ _ _ _ _ _ :- stop "derive.induction: mutual indexed data types not supported". + +func mutual-induction-param1-term-final term, term, list derive.induction.mutual-spec, list derive.induction.mutual-spec, list term, list term, int -> term. +mutual-induction-param1-term-final A PA OrigAll Specs Ps Hs Focus R :- + std.assert! (std.nth Focus Specs SF) "derive.induction: failed to select parameterized mutual final spec", + SF = derive.induction.mutual-spec _ _ IsT Arity _ _, + mutual-induction-param1-term-final-aux A PA OrigAll IsT Ps Hs Focus Arity [] R. + +func mutual-induction-param1-term-hyps term, term, list derive.induction.mutual-spec, list derive.induction.mutual-spec, list term, list term, list term, list term, int -> term. +mutual-induction-param1-term-hyps A PA OrigAll Specs Ps [] [] RevHs Focus R :- !, + std.rev RevHs Hs, + std.assert! (mutual-induction-param1-term-final A PA OrigAll Specs Ps Hs Focus R) "derive.induction: failed to build parameterized mutual final application". +mutual-induction-param1-term-hyps A PA OrigAll Specs Ps [Kc|KS] [KT|KTS] RevHs Focus (fun HN HTy R) :- + std.assert! (collect-terms Specs IsTs _ _) "derive.induction: failed to collect parameterized mutual terms", + std.assert! (hyp-mutual IsTs Ps KT HTy) "derive.induction: failed to build parameterized mutual hypothesis type", + std.assert! (coq.term->gref Kc GRK) "derive.induction: failed to identify parameterized mutual constructor", + coq.name-suffix `H` {coq.gref->id GRK} HN, + @pi-decl HN HTy h\ + induction-hyp-db Kc h =!=> + std.assert! (mutual-induction-param1-term-hyps A PA OrigAll Specs Ps KS KTS [h|RevHs] Focus (R h)) "derive.induction: failed to build rest parameterized mutual hypotheses". + +func mutual-induction-param1-term-motives term, term, list derive.induction.mutual-spec, list derive.induction.mutual-spec, list derive.induction.mutual-spec, list term, int -> term. +mutual-induction-param1-term-motives A PA OrigAll Specs [] RevPs Focus R :- !, + std.rev RevPs Ps, + std.assert! (collect-terms Specs _ KAll KTAll) "derive.induction: failed to collect parameterized mutual constructors", + std.assert! (mutual-induction-param1-term-hyps A PA OrigAll Specs Ps KAll KTAll [] Focus R) "derive.induction: failed to build parameterized mutual hypotheses". +mutual-induction-param1-term-motives A PA OrigAll Specs [S|SS] RevPs Focus (fun `P` PTy R) :- + S = derive.induction.mutual-spec _ _ _ Arity _ _, + std.assert! (truncated-predicate-ty Arity PTy) "derive.induction: failed to build parameterized mutual motive type", + @pi-decl `P` PTy p\ std.assert! (mutual-induction-param1-term-motives A PA OrigAll Specs SS [p|RevPs] Focus (R p)) "derive.induction: failed to build rest parameterized mutual motives". + +func mutual-induction-param1-term list derive.induction.mutual-spec, int -> term. +mutual-induction-param1-term All Focus (fun A TA (a\ fun P (TP a) (pa\ Rest a pa))) :- + std.assert! (std.nth Focus All S) "derive.induction: failed to select parameterized mutual spec", + S = derive.induction.mutual-spec _ _ _ (prod A TA (a\ prod P (TP a) _)) _ _, coq.sort? TA, !, + @pi-decl A TA a\ @pi-decl P (TP a) pa\ sigma Specs1\ + std.assert! (mutual-specs-apply-param2 a pa All Specs1) "derive.induction: failed to apply parameterized mutual params", + std.assert! (mutual-induction-param1-term-motives a pa All Specs1 Specs1 [] Focus (Rest a pa)) "derive.induction: failed to build parameterized mutual term body". + +func add-hyps-body list term, list term, list term, list term, list derive.induction.mutual-spec, list term, int -> term. +add-hyps-body _ _ [] [] All Ps Focus R :- !, + mutual-induction-mfix All Ps Focus R. +add-hyps-body IsTs Ps [Kc|KS] [KT|KTS] All AllPs Focus (fun HN HTy R) :- + hyp-mutual IsTs Ps KT HTy, + coq.term->gref Kc GRK, + coq.name-suffix `H` {coq.gref->id GRK} HN, + @pi-decl HN HTy h\ + induction-hyp-db Kc h =!=> + add-hyps-body IsTs Ps KS KTS All AllPs Focus (R h). + +func mutual-induction-term-base list derive.induction.mutual-spec, int -> term. +mutual-induction-term-base Specs Focus R :- + mutual-induction-term-motives Specs Specs [] Focus R. + +func mutual-induction-term-motives list derive.induction.mutual-spec, list derive.induction.mutual-spec, list term, int -> term. +mutual-induction-term-motives All [] RevPs Focus R :- !, + std.rev RevPs Ps, + collect-terms All IsTs KAll KTAll, + add-hyps-body IsTs Ps KAll KTAll All Ps Focus R. +mutual-induction-term-motives All [S|SS] RevPs Focus (fun `P` PTy R) :- + S = derive.induction.mutual-spec _ _ _ Arity _ _, + truncated-predicate-ty Arity PTy, + @pi-decl `P` PTy p\ mutual-induction-term-motives All SS [p|RevPs] Focus (R p). + +func mutual-induction-term int, list derive.induction.mutual-spec, int -> term. +mutual-induction-term 0 Specs Focus R :- !, mutual-induction-term-base Specs Focus R. +mutual-induction-term 2 ([S|_] as Specs) Focus R :- + mutual-spec-arity S (prod _ TA _), coq.sort? TA, !, + std.assert! (mutual-induction-param1-term Specs Focus R) "derive.induction: failed to build parameterized mutual induction term". +mutual-induction-term N ([S|_] as Specs) Focus (fun A TA R) :- N > 0, !, + mutual-spec-arity S (prod A TA _), + M is N - 1, + @pi-decl A TA a\ sigma Specs1\ + std.map Specs (mutual-spec-apply-param a) Specs1, + mutual-induction-term M Specs1 Focus (R a). + +func add-mutual-induction-consts list derive.induction.mutual-spec, list derive.induction.mutual-spec, inductive, string, int, int -> list prop. +add-mutual-induction-consts _ [] _ _ _ _ [] :- !. +add-mutual-induction-consts All [S|SS] Selected Prefix Lno Focus [Clause|CS] :- std.do! [ + S = derive.induction.mutual-spec GR _ _ _ _ _, + mutual-induction-term Lno All Focus R, + std.assert-ok! (coq.typecheck R Ty) "derive.induction generates illtyped mutual term", + if (GR = Selected) + (Name is Prefix ^ "induction") + (Name is {coq.gref->id (indt GR)} ^ "_induction"), + coq.ensure-fresh-global-id Name FName, + coq.env.add-const FName R Ty @transparent! I, + Clause = (induction-db GR (global (const I)) :- !), + coq.elpi.accumulate _ "derive.induction.db" (clause _ (before "induction-db:fail") Clause), + Focus1 is Focus + 1, + add-mutual-induction-consts All SS Selected Prefix Lno Focus1 CS +]. + +func main-mutual inductive, list inductive, string -> list prop. +main-mutual Selected GRS Prefix Clauses :- std.do! [ + std.map GRS mutual-spec Specs, + Specs = [First|_], + mutual-spec-ind First FirstGRR, + coq.env.indt FirstGRR _ LnoIs Luno _ _ _, + assert! (LnoIs = Luno) "derive.induction: Non-uniform parameters not supported", + paramX.translated-lno GRS FirstGRR Lno, + if (coq.env.informative? FirstGRR) (Informative = [informative]) (Informative = []), + Informative =!=> add-mutual-induction-consts Specs Specs Selected Prefix Lno 0 Clauses +]. + func main inductive, string -> list prop. main GR Prefix [Clause] :- do! [ T = global (indt GR), diff --git a/apps/derive/elpi/param1_congr.elpi b/apps/derive/elpi/param1_congr.elpi index 78f3d0fb7..ba4adea32 100644 --- a/apps/derive/elpi/param1_congr.elpi +++ b/apps/derive/elpi/param1_congr.elpi @@ -50,9 +50,10 @@ main-k Prefix Lno K KT Clause :- do! [ ]. func main gref, gref, string -> list prop. -main _ (indt GR) Prefix Clauses2 :- +main Orig (indt GR) Prefix Clauses2 :- - coq.env.indt GR _ Lno _ _ K KT, + coq.env.indt GR _ _ _ _ K KT, + paramX.translated-lno-gref Orig (indt GR) Lno, map2-filter K KT (main-k Prefix Lno) Clauses, Clauses2 = [param1-congr-done (indt GR)|Clauses], forall Clauses2 diff --git a/apps/derive/elpi/param1_inhab.elpi b/apps/derive/elpi/param1_inhab.elpi index 5a3fa7ebb..17f2e409a 100644 --- a/apps/derive/elpi/param1_inhab.elpi +++ b/apps/derive/elpi/param1_inhab.elpi @@ -104,6 +104,158 @@ body-params _ IsT _ _ _ _ :- ". It does not look like a unary parametricity translation of an inductive with no indexes.", stop M. +kind mutual-spec type. +type mutual-spec inductive -> inductive -> term -> term -> list constructor -> list term -> list term -> mutual-spec. + +func mutual-spec inductive -> mutual-spec. +mutual-spec GR (mutual-spec GR GRR (global (indt GRR)) Arity KOrig K KT) :- std.do! [ + reali (global (indt GR)) (global (indt GRR)), + coq.env.indt GR _ _ _ _ KOrig _, + coq.env.indt GRR _ _ _ Arity KR KT, + std.map KR (k\r\ r = global (indc k)) K +]. + +func mutual-spec-arity mutual-spec -> term. +mutual-spec-arity (mutual-spec _ _ _ Arity _ _ _) Arity. + +func mutual-spec-ind mutual-spec -> inductive. +mutual-spec-ind (mutual-spec _ GRR _ _ _ _ _) GRR. + +func mutual-spec-apply-sort-param term, term, mutual-spec -> mutual-spec. +mutual-spec-apply-sort-param A P (mutual-spec GR GRR IsT (prod _ _ F) KOrig K KT) + (mutual-spec GR GRR IsTAP ArityAP KOrig KAP KTAP) :- !, + F A = prod _ _ G, + ArityAP = G P, + coq.mk-app IsT [A,P] IsTAP, + map K (k\ coq.mk-app k [A,P]) KAP, + map KT (coq.subst-prod [A,P]) KTAP. +mutual-spec-apply-sort-param _ _ _ _ :- stop "derive.param1_inhab: mutual parameter mismatch". + +func mutual-spec-apply-param term, mutual-spec -> mutual-spec. +mutual-spec-apply-param A (mutual-spec GR GRR IsT (prod _ _ F) KOrig K KT) + (mutual-spec GR GRR IsTA (F A) KOrig KA KTA) :- !, + coq.mk-app IsT [A] IsTA, + map K (k\ coq.mk-app k [A]) KA, + map KT (coq.subst-prod [A]) KTA. +mutual-spec-apply-param _ _ _ :- stop "derive.param1_inhab: mutual parameter mismatch". + +func mutual-inhab-ty mutual-spec -> term. +mutual-inhab-ty (mutual-spec _ _ IsT (prod _ T _\ sort _) _ _ _) Ty :- !, + Ty = prod `x` T R, + pi x\ coq.mk-app IsT [x] (R x). +mutual-inhab-ty _ _ :- stop "derive.param1_inhab: mutual indexed data types not supported". + +func mutual-inhab-body mutual-spec -> term. +mutual-inhab-body (mutual-spec _GR _ IsT (prod _ T _\ sort _) KOrig K KT) (fun `x` T Bo) :- !, + RT = (x\ {coq.mk-app IsT [x]}), + map2 KOrig {zip K KT} (a\b\r\ r = (global (indc a)) `-> b) K2KR, + K2KR =!=> @pi-decl `x` T x\ coq.build-match x T (oty RT) body (Bo x). +mutual-inhab-body _ _ :- stop "derive.param1_inhab: mutual indexed data types not supported". + +func mutual-inhab-db-clauses list mutual-spec, list term -> list prop. +mutual-inhab-db-clauses [] [] []. +mutual-inhab-db-clauses [S|SS] [F|FS] [C|CS] :- + S = mutual-spec _ _ IsT _ _ _ _, + C = (param1-inhab-db IsT F), + mutual-inhab-db-clauses SS FS CS. + +func mutual-inhab-mfix-aux list mutual-spec, list mutual-spec, list term -> mfix-block. +mutual-inhab-mfix-aux All [] RevF (mfix-bo Bodies) :- !, + rev RevF Funs, + mutual-inhab-db-clauses All Funs Clauses, + Clauses =!=> map All mutual-inhab-body Bodies. +mutual-inhab-mfix-aux All [S|SS] RevF (mfix-ty N 0 Ty Rest) :- + S = mutual-spec _ GRR _ _ _ _ _, + ID is {coq.gref->id (indt GRR)} ^ "_inhab_rec", + coq.id->name ID N, + mutual-inhab-ty S Ty, + @pi-decl N Ty f\ mutual-inhab-mfix-aux All SS [f|RevF] (Rest f). + +func mutual-inhab-mfix list mutual-spec, int -> term. +mutual-inhab-mfix Specs Focus (mfix Focus 0 Block) :- + mutual-inhab-mfix-aux Specs Specs [] Block. + +func body-mutual-params int, list mutual-spec, int -> term. +body-mutual-params 0 Specs Focus R :- !, mutual-inhab-mfix Specs Focus R. +body-mutual-params N ([S|_] as Specs) Focus R :- N > 0, + mutual-spec-arity S (prod A TA a\ prod P (TP a) _), coq.sort? TA, !, + M is N - 2, + R = (fun A TA a\ fun P (TP a) p\ fun _ {{ lib:elpi.derive.full lp:a lp:p }} pf\ Bo a p pf), + @pi-decl A TA a\ @pi-decl P (TP a) p\ @pi-decl _ {{ lib:elpi.derive.full lp:a lp:p }} pf\ + sigma Specs1\ + map Specs (mutual-spec-apply-sort-param a p) Specs1, + (reali a p :- !) => param1-inhab-db p pf => + body-mutual-params M Specs1 Focus (Bo a p pf). +body-mutual-params N ([S|_] as Specs) Focus R :- N > 0, !, + mutual-spec-arity S (prod A TA _F), + M is N - 1, + R = (fun A TA a\ Bo a), + @pi-decl A TA a\ + sigma Specs1\ + map Specs (mutual-spec-apply-param a) Specs1, + body-mutual-params M Specs1 Focus (Bo a). +body-mutual-params _ _ _ _ :- stop "derive.param1_inhab: wrong mutual shape". + +func full-ty term, term -> term. +full-ty T P (prod `x` T B) :- + pi x\ coq.mk-app P [x] (B x). + +func mutual-inhab-result-ty mutual-spec -> term. +mutual-inhab-result-ty (mutual-spec _ _ IsT (prod _ T _\ sort _) _ _ _) Ty :- !, + full-ty T IsT Ty. +mutual-inhab-result-ty _ _ :- stop "derive.param1_inhab: mutual indexed data types not supported". + +func body-mutual-params-ty int, mutual-spec -> term. +body-mutual-params-ty 0 S Ty :- !, + mutual-inhab-result-ty S Ty. +body-mutual-params-ty N S Ty :- N > 0, + mutual-spec-arity S (prod A TA a\ prod P (TP a) _), coq.sort? TA, !, + M is N - 2, + Ty = prod A TA (a\ prod P (TP a) (p\ prod _ (FullAP a p) (pf\ Rest a p pf))), + @pi-decl A TA a\ @pi-decl P (TP a) p\ + full-ty a p (FullAP a p), + @pi-decl _ (FullAP a p) pf\ + sigma S1\ + mutual-spec-apply-sort-param a p S S1, + body-mutual-params-ty M S1 (Rest a p pf). +body-mutual-params-ty N S Ty :- N > 0, !, + mutual-spec-arity S (prod A TA _), + M is N - 1, + Ty = prod A TA (a\ Rest a), + @pi-decl A TA a\ + sigma S1\ + mutual-spec-apply-param a S S1, + body-mutual-params-ty M S1 (Rest a). +body-mutual-params-ty _ _ _ :- stop "derive.param1_inhab: wrong mutual shape". + +func add-mutual-inhab-consts list mutual-spec, list mutual-spec, string, int, int -> list prop. +add-mutual-inhab-consts _ [] _ _ _ []. +add-mutual-inhab-consts All [S|SS] Suffix Lno Focus [ClauseW, param1-inhab-done (indt GRR)|CS] :- std.do! [ + S = mutual-spec _ GRR IsT _ _ _ _, + body-mutual-params Lno All Focus RSkel, + std.assert-ok! (coq.typecheck RSkel RT) "derive.param1_inhab generates illtyped mutual term", + R = RSkel, + Name is {coq.gref->id (indt GRR)} ^ Suffix, + coq.env.add-const Name R RT @transparent! Witness, + ClauseW = (param1-inhab-db IsT (global (const Witness))), + coq.elpi.accumulate _ "derive.param1.trivial.db" (clause _ _ ClauseW), + coq.elpi.accumulate _ "derive.param1.trivial.db" (clause _ _ (param1-inhab-done (indt GRR))), + Focus1 is Focus + 1, + add-mutual-inhab-consts All SS Suffix Lno Focus1 CS +]. + +func main-mutual list inductive, string -> list prop. +main-mutual GRS Suffix Clauses :- std.do! [ + map GRS mutual-spec Specs, + Specs = [First|_], + mutual-spec-ind First FirstGRR, + coq.env.indt FirstGRR Ind LnoIs Luno _ _ _, + assert! (Ind = tt) "derive.param1_inhab: Coinductive types are not supported", + assert! (LnoIs = Luno) "derive.param1_inhab: Non-uniform parameters not supported", + paramX.translated-lno GRS FirstGRR Lno, + add-mutual-inhab-consts Specs Specs Suffix Lno 0 Clauses +]. + func main gref, gref, string -> list prop. main _ (indt GR) Suffix [ClauseW, param1-inhab-done (indt GR)] :- do! [ diff --git a/apps/derive/elpi/param1_trivial.elpi b/apps/derive/elpi/param1_trivial.elpi index 071d878f2..5fa75cae1 100644 --- a/apps/derive/elpi/param1_trivial.elpi +++ b/apps/derive/elpi/param1_trivial.elpi @@ -112,6 +112,180 @@ body-params _ T _ _ :- ". It does not look like a unary parametricity translation of an inductive with no indexes.", fail. +kind mutual-spec type. +type mutual-spec inductive -> term -> term -> mutual-spec. + +func mutual-spec inductive -> mutual-spec. +mutual-spec GR (mutual-spec GRR (global (indt GRR)) Arity) :- + reali (global (indt GR)) (global (indt GRR)), + coq.env.indt GRR _ _ _ Arity _ _. + +func mutual-spec-ind mutual-spec -> inductive. +mutual-spec-ind (mutual-spec GRR _ _) GRR. + +func mutual-spec-arity mutual-spec -> term. +mutual-spec-arity (mutual-spec _ _ Arity) Arity. + +func mutual-spec-apply-sort-param term, term, mutual-spec -> mutual-spec. +mutual-spec-apply-sort-param A P (mutual-spec GRR IsT (prod _ _ F)) + (mutual-spec GRR IsTAP ArityAP) :- !, + F A = prod _ _ G, + ArityAP = G P, + coq.mk-app IsT [A,P] IsTAP. +mutual-spec-apply-sort-param _ _ _ _ :- stop "derive.param1_trivial: mutual parameter mismatch". + +func mutual-spec-apply-param term, mutual-spec -> mutual-spec. +mutual-spec-apply-param A (mutual-spec GRR IsT (prod _ _ F)) + (mutual-spec GRR IsTA (F A)) :- !, + coq.mk-app IsT [A] IsTA. +mutual-spec-apply-param _ _ _ :- stop "derive.param1_trivial: mutual parameter mismatch". + +func mutual-trivial-eq-ty mutual-spec, term -> term. +mutual-trivial-eq-ty (mutual-spec _ IsT (prod _ T _\ sort _)) W Ty :- !, + Ty = prod `x` T R1, + pi x\ sigma IsTx Wx\ + coq.mk-app IsT [x] IsTx, + coq.mk-app W [x] Wx, + R1 x = prod `y` IsTx (y\ {{ lib:@elpi.eq lp:IsTx lp:Wx lp:y }}). +mutual-trivial-eq-ty _ _ _ :- stop "derive.param1_trivial: mutual indexed data types not supported". + +func mutual-trivial-eq-body mutual-spec, term -> term. +mutual-trivial-eq-body (mutual-spec _ IsT (prod _ T _\ sort _)) W (fun `x` T Bo1) :- !, + @pi-decl `x` T x\ sigma IsTx\ + coq.mk-app IsT [x] IsTx, + Bo1 x = fun `y` IsTx (Bo2 x), + @pi-decl `y` IsTx y\ coq.build-match y IsTx (oty IsT W) (body IsT W) (Bo2 x y). +mutual-trivial-eq-body _ _ _ :- stop "derive.param1_trivial: mutual indexed data types not supported". + +func mutual-trivial-db-clauses list mutual-spec, list term, list term -> list prop. +mutual-trivial-db-clauses [] [] [] []. +mutual-trivial-db-clauses [S|SS] [W|WS] [F|FS] [C|CS] :- + S = mutual-spec _ IsT (prod _ T _\ sort _), + C = (param1-trivial-db IsT {{ fun x : lp:T => lib:elpi.derive.contracts lp:T lp:IsT x (lp:W x) (lp:F x) }}), + mutual-trivial-db-clauses SS WS FS CS. + +func mutual-trivial-mfix-aux list mutual-spec, list mutual-spec, list term, list term, list term -> mfix-block. +mutual-trivial-mfix-aux All [] AllWs [] RevF (mfix-bo Bodies) :- !, + std.rev RevF Funs, + mutual-trivial-db-clauses All AllWs Funs Clauses, + Clauses =!=> std.map2 All AllWs mutual-trivial-eq-body Bodies. +mutual-trivial-mfix-aux All [S|SS] AllWs [W|WS] RevF (mfix-ty N 1 Ty Rest) :- + S = mutual-spec GRR _ _, + ID is {coq.gref->id (indt GRR)} ^ "_trivial_rec", + coq.id->name ID N, + mutual-trivial-eq-ty S W Ty, + @pi-decl N Ty f\ mutual-trivial-mfix-aux All SS AllWs WS [f|RevF] (Rest f). + +func mutual-trivial-mfix list mutual-spec, list term, int -> term. +mutual-trivial-mfix Specs Ws Focus (mfix Focus 1 Block) :- + mutual-trivial-mfix-aux Specs Specs Ws Ws [] Block. + +func mutual-trivial-result mutual-spec, term, term -> term. +mutual-trivial-result (mutual-spec _ IsT (prod _ T _\ sort _)) W EqFun R :- !, + R = {{ fun x : lp:T => lib:elpi.derive.contracts lp:T lp:IsT x (lp:W x) (lp:EqFun x) }}. +mutual-trivial-result _ _ _ _ :- stop "derive.param1_trivial: mutual indexed data types not supported". + +func mutual-inhab-witness mutual-spec -> term. +mutual-inhab-witness (mutual-spec _ IsT _) W :- + std.assert! (param1-inhab-db IsT W) "derive.param1_trivial: use derive.param1_inhab first". + +func body-mutual-params int, list mutual-spec, int -> term. +body-mutual-params 0 Specs Focus R :- !, + std.map Specs mutual-inhab-witness Ws, + mutual-trivial-mfix Specs Ws Focus EqFun, + std.nth Focus Specs S, + std.nth Focus Ws W, + mutual-trivial-result S W EqFun R. +body-mutual-params N ([S|_] as Specs) Focus R :- N > 0, + mutual-spec-arity S (prod A TA a\ prod P (TP a) _), coq.sort? TA, !, + M is N - 2, + R = (fun A TA a\ fun P (TP a) p\ fun _ {{ lib:elpi.derive.trivial lp:a lp:p }} pf\ Bo a p pf), + @pi-decl A TA a\ @pi-decl P (TP a) p\ @pi-decl _ {{ lib:elpi.derive.trivial lp:a lp:p }} pf\ + sigma Specs1\ + std.map Specs (mutual-spec-apply-sort-param a p) Specs1, + (reali a p :- !) => + param1-trivial-db p pf => + param1-inhab-db p {{ lib:elpi.derive.trivial_full lp:a lp:p lp:pf }} => + body-mutual-params M Specs1 Focus (Bo a p pf). +body-mutual-params N ([S|_] as Specs) Focus R :- N > 0, !, + mutual-spec-arity S (prod A TA _F), + M is N - 1, + R = (fun A TA a\ Bo a), + @pi-decl A TA a\ + sigma Specs1\ + std.map Specs (mutual-spec-apply-param a) Specs1, + body-mutual-params M Specs1 Focus (Bo a). +body-mutual-params _ _ _ _ :- stop "derive.param1_trivial: wrong mutual shape". + +func contractible-ty term -> term. +contractible-ty T + (app [global (indt SigT), T, + fun `x` T (x\ prod `y` T (y\ app [global (indt Eq), T, x, y]))]) :- + coq.locate "sigT" (indt SigT), + coq.locate "eq" (indt Eq). + +func trivial-ty term, term -> term. +trivial-ty T P (prod `x` T B) :- + pi x\ sigma Px\ + coq.mk-app P [x] Px, + contractible-ty Px (B x). + +func mutual-trivial-result-ty mutual-spec -> term. +mutual-trivial-result-ty (mutual-spec _ IsT (prod _ T _\ sort _)) Ty :- !, + trivial-ty T IsT Ty. +mutual-trivial-result-ty _ _ :- stop "derive.param1_trivial: mutual indexed data types not supported". + +func body-mutual-params-ty int, mutual-spec -> term. +body-mutual-params-ty 0 S Ty :- !, + mutual-trivial-result-ty S Ty. +body-mutual-params-ty N S Ty :- N > 0, + mutual-spec-arity S (prod A TA a\ prod P (TP a) _), coq.sort? TA, !, + M is N - 2, + Ty = prod A TA (a\ prod P (TP a) (p\ prod _ (TrivAP a p) (pf\ Rest a p pf))), + @pi-decl A TA a\ @pi-decl P (TP a) p\ + trivial-ty a p (TrivAP a p), + @pi-decl _ (TrivAP a p) pf\ + sigma S1\ + mutual-spec-apply-sort-param a p S S1, + body-mutual-params-ty M S1 (Rest a p pf). +body-mutual-params-ty N S Ty :- N > 0, !, + mutual-spec-arity S (prod A TA _), + M is N - 1, + Ty = prod A TA (a\ Rest a), + @pi-decl A TA a\ + sigma S1\ + mutual-spec-apply-param a S S1, + body-mutual-params-ty M S1 (Rest a). +body-mutual-params-ty _ _ _ :- stop "derive.param1_trivial: wrong mutual shape". + +func add-mutual-trivial-consts list mutual-spec, list mutual-spec, string, int, int -> list prop. +add-mutual-trivial-consts _ [] _ _ _ []. +add-mutual-trivial-consts All [S|SS] Suffix Lno Focus [Clause,param1-trivial-done (indt GRR)|CS] :- std.do! [ + S = mutual-spec GRR IsT _, + Name is {coq.gref->id (indt GRR)} ^ Suffix, + if (Lno > 0) + (coq.error "derive.param1_trivial: mutual triviality generation for parameterized mutual inductives still needs to be implemented" (indt GRR)) + (body-mutual-params Lno All Focus R, + std.assert-ok! (coq.typecheck R RT) "derive.param1_trivial generates illtyped mutual term", + coq.env.add-const Name R RT @transparent! Cst), + Clause = (param1-trivial-db IsT (global (const Cst))), + coq.elpi.accumulate _ "derive.param1.trivial.db" (clause _ _ Clause), + coq.elpi.accumulate _ "derive.param1.trivial.db" (clause _ _ (param1-trivial-done (indt GRR))), + Focus1 is Focus + 1, + add-mutual-trivial-consts All SS Suffix Lno Focus1 CS +]. + +func main-mutual list inductive, string -> list prop. +main-mutual GRS Suffix Clauses :- std.do! [ + std.map GRS mutual-spec Specs, + Specs = [First|_], + mutual-spec-ind First FirstGRR, + coq.env.indt FirstGRR _ LnoIs Luno _ _ _, + assert! (LnoIs = Luno) "derive.param1_trivial: Non-uniform parameters not supported", + paramX.translated-lno GRS FirstGRR Lno, + add-mutual-trivial-consts Specs Specs Suffix Lno 0 Clauses +]. + func main gref, gref, string -> list prop. main _ (indt GR) Suffix [Clause,param1-trivial-done (indt GR)] :- do! [ coq.env.indt GR _ Lno _ Arity _ _, diff --git a/apps/derive/elpi/param2.elpi b/apps/derive/elpi/param2.elpi index 48a546044..813dfd5f4 100644 --- a/apps/derive/elpi/param2.elpi +++ b/apps/derive/elpi/param2.elpi @@ -485,9 +485,107 @@ store-param-indc Suffix K KR :- % toplevel predicates % %%%%%%%%%%%%%%%%%%%%%%% +% The upstream HOAS translation handles non-mutual declarations. Mutual +% blocks follow param1's block-level translation and need the corresponding +% constructor naming and translation helpers locally. +func rename-mutual-indc string, constructor -> pair constructor id. +rename-mutual-indc Suffix GR (pr GR FNameR) :- + coq.gref->id (indc GR) Name, + NameR is Name ^ Suffix, + coq.ensure-fresh-global-id NameR FNameR. + +func param-mutual-indc constructor, term -> term. +param-mutual-indc K T TRK :- !, + coq.arguments.name (indc K) LN, + rename T LN Tn, + param Tn _ TR, + coq.env.global (indc K) KT, + coq.subst-fun [KT, KT] TR TRK. + +kind raw-mindt-spec type. +type raw-mindt-spec inductive -> bool -> term -> list constructor -> list (pair constructor id) -> list term -> id -> raw-mindt-spec. + +func build-raw-mutual-spec string, inductive -> raw-mindt-spec. +build-raw-mutual-spec Suffix GR (raw-mindt-spec GR IsInd Ty KNames KNamesR KTypes FNameR) :- + coq.env.indt GR IsInd _ _ Ty KNames KTypes, + coq.gref->id (indt GR) ID, + NameR is ID ^ Suffix, + coq.ensure-fresh-global-id NameR FNameR, + map KNames (rename-mutual-indc Suffix) KNamesR. + +func translate-mutual-spec raw-mindt-spec, inductive -> coq.indt-spec. +translate-mutual-spec (raw-mindt-spec GR IsInd Ty KNames KNamesR KTypes FNameR) NewGR + (coq.indt-spec NewGR FNameR IsInd TyOut KNamesR KTypesR) :- + Ind = global (indt GR), + param Ty _ TyR, + map2 KNames KTypes param-mutual-indc KTypesR, + coq.subst-fun [Ind,Ind] TyR TyOut. + +func dispatch-mutual-gen list raw-mindt-spec, list raw-mindt-spec, list inductive -> list prop. +dispatch-mutual-gen All [] Acc Clauses :- !, + rev Acc NewGRs, + dispatch-mutual-do All NewGRs Clauses. +dispatch-mutual-gen All [raw-mindt-spec GR _ _ _ _ _ _|Rest] Acc Clauses :- + pi newGR\ (param (global (indt GR)) (global (indt GR)) (global (indt newGR)) :- !) => + dispatch-mutual-gen All Rest [newGR|Acc] Clauses. + +func mutual-store-indt list raw-mindt-spec, list inductive -> . +mutual-store-indt [] []. +mutual-store-indt [raw-mindt-spec GR _ _ _ _ _ FNameR|Raws] [RealGR|RealGRs] :- + store-param FNameR (global (indt GR)) (global (indt GR)) (global (indt RealGR)), + mutual-store-indt Raws RealGRs. + +func mutual-store-indcs string, list constructor, list constructor -> . +mutual-store-indcs _ [] []. +mutual-store-indcs Suffix [K|KS] [KR|KRS] :- + store-param-indc Suffix K KR, + mutual-store-indcs Suffix KS KRS. + +func mutual-stores string, list raw-mindt-spec, list inductive -> . +mutual-stores _ [] []. +mutual-stores Suffix [raw-mindt-spec _ _ _ KNames _ _ _|Raws] [RealGR|RealGRs] :- + coq.env.indt RealGR _ _ _ _ RealKNames _, + mutual-store-indcs Suffix KNames RealKNames, + mutual-stores Suffix Raws RealGRs. + +func mutual-clauses list raw-mindt-spec, list inductive -> list prop. +mutual-clauses [] [] []. +mutual-clauses [raw-mindt-spec GR _ _ KNames _ _ _|Raws] [RealGR|RealGRs] Clauses :- + coq.env.indt RealGR _ _ _ _ RealKNames _, + map2 KNames RealKNames (a\b\r\ r = (param.gref (indc a) (indc a) (indc b) :- !)) CK, + This = [param-done (indt GR), (param.gref (indt GR) (indt GR) (indt RealGR) :- !)|CK], + mutual-clauses Raws RealGRs Rest, + std.append This Rest Clauses. + +func accumulate-param2-clause prop ->. +accumulate-param2-clause (param-done _ as C) :- !, + coq.elpi.accumulate _ "derive.param2.db" (clause _ _ C). +accumulate-param2-clause C :- + coq.elpi.accumulate _ "derive.param2.db" (clause _ (before "param:fail") C). + +func dispatch-mutual-do list raw-mindt-spec, list inductive -> list prop. +dispatch-mutual-do Raws NewGRs Clauses :- std.do! [ + map2 Raws NewGRs translate-mutual-spec Specs, + coq.build-mindt-decl Specs 0 0 DeclR, + std.assert-ok! (coq.typecheck-indt-decl DeclR) "derive.param2 generates illtyped mutual inductive", + coq.env.add-indt DeclR RealGR, + coq.env.indt-block RealGR _ _ _ RealGRs _ _ _, + mutual-store-indt Raws RealGRs, + mutual-stores "_R" Raws RealGRs, + mutual-clauses Raws RealGRs Clauses1, + forall Clauses1 accumulate-param2-clause, + Clauses = Clauses1 +]. + :index (1) func dispatch gref, string -> list prop. +dispatch (indt GR) Suffix Clauses :- coq.env.indt-block GR _ Lno Luno GRS _ _ _, std.length GRS N, N > 1, !, std.do! [ + map GRS (build-raw-mutual-spec Suffix) Raws, + std.assert! (Lno = Luno) "derive.param2: Non-uniform parameters not supported", + dispatch-mutual-gen Raws Raws [] Clauses +]. + dispatch ((const GR) as C) Suffix Clauses :- do! [ % We need to check both projection and primitive-projection: a non-primitive % projection is still a projection, and a manual wrapper of a primitive projection diff --git a/apps/derive/tests/test_bcongr.v b/apps/derive/tests/test_bcongr.v index 351cf68de..f713f0457 100644 --- a/apps/derive/tests/test_bcongr.v +++ b/apps/derive/tests/test_bcongr.v @@ -1,4 +1,4 @@ -From elpi.apps Require Import derive.bcongr. +From elpi.apps Require Import derive derive.bcongr. From elpi.apps Require Import test_derive_corelib test_projK. @@ -108,3 +108,71 @@ Redirect "tmp" Check enum_bcongr_E1 : reflect (E1 = E1) true. Redirect "tmp" Check enum_bcongr_E2 : reflect (E2 = E2) true. Redirect "tmp" Check enum_bcongr_E3 : reflect (E3 = E3) true. +Module BcongrStandaloneFirst. + From elpi.apps Require Import derive.bcongr. + + Import test_derive_corelib.Mutual.Tree. + + Elpi derive.projK tree. + Elpi derive.bcongr tree. + + Redirect "tmp" Check tree_bcongr_node. + Redirect "tmp" Check forest_bcongr_empty. + Redirect "tmp" Check forest_bcongr_cons. + Redirect "tmp" Elpi Query derive.bcongr lp:{{ + coq.locate "node" (indc N), + coq.locate "cons" (indc C), + bcongr-db N _, + bcongr-db C _ + }}. +End BcongrStandaloneFirst. + +Module BcongrStandaloneSecond. + From elpi.apps Require Import derive.bcongr. + + Import test_derive_corelib.Mutual.Tree. + + Elpi derive.projK tree. + Elpi derive.bcongr forest. + + Redirect "tmp" Check tree_bcongr_node. + Redirect "tmp" Check forest_bcongr_empty. + Redirect "tmp" Check forest_bcongr_cons. +End BcongrStandaloneSecond. + +Module BcongrMetaFirst. + From elpi.apps Require Import derive.bcongr. + + Import test_derive_corelib.Mutual.Tree. + + #[only(projK,bcongr)] derive tree. + + Redirect "tmp" Check tree_bcongr_node. + Redirect "tmp" Check forest_bcongr_empty. + Redirect "tmp" Check forest_bcongr_cons. +End BcongrMetaFirst. + +Module BcongrMetaSecond. + From elpi.apps Require Import derive.bcongr. + + Import test_derive_corelib.Mutual.Tree. + + #[only(projK,bcongr)] derive forest. + + Redirect "tmp" Check tree_bcongr_node. + Redirect "tmp" Check forest_bcongr_empty. + Redirect "tmp" Check forest_bcongr_cons. +End BcongrMetaSecond. + +Module BcongrPrefixSecond. + From elpi.apps Require Import derive.bcongr. + + Import test_derive_corelib.Mutual.Tree. + + #[only(projK,bcongr), prefix="custom_"] derive forest. + + Redirect "tmp" Check tree_bcongr_node. + Redirect "tmp" Check custom_bcongr_empty. + Redirect "tmp" Check custom_bcongr_cons. +End BcongrPrefixSecond. + diff --git a/apps/derive/tests/test_derive_mutual.v b/apps/derive/tests/test_derive_mutual.v new file mode 100644 index 000000000..ce1639455 --- /dev/null +++ b/apps/derive/tests/test_derive_mutual.v @@ -0,0 +1,4716 @@ +(* This is the same derivation set exported by derive.std, kept explicit so + each standard derivation is tested independently. Each derive call below + lives in its own module and is checked against a signature documenting the + Coq definitions that derivation is expected to add. *) +From Corelib Require Import BinNums Nat ssrbool. +From elpi.apps.derive.tests Require Import test_derive_corelib. +Definition bool_is_true := is_true. +From elpi.apps.derive.elpi Extra Dependency "derive_hook.elpi" as derive_hook_for_mutual_wrapper_test. +From elpi.apps.derive.elpi Extra Dependency "derive.elpi" as derive_core_for_mutual_wrapper_test. +From elpi.apps Require Import + derive + derive.map + derive.lens + derive.lens_laws + derive.param1 + derive.param1_congr + derive.param1_trivial + derive.param1_functor + derive.param2 + derive.induction + derive.tag + derive.fields + derive.eqb + derive.eqbcorrect + derive.eqbOK + derive.isK + derive.projK + derive.bcongr. + +Elpi Command derive_mutual_wrapper_test. +#[synterp] Elpi Accumulate lp:{{ + main _ :- coq.env.begin-module "wleft" none, coq.env.end-module _. +}}. +Elpi Accumulate File derive_hook_for_mutual_wrapper_test. +Elpi Accumulate File derive_core_for_mutual_wrapper_test. +Elpi Accumulate lp:{{ + derivation (indt _) _ ff (derive "noop" (cl\ cl = []) true). + + main _ :- + D = (parameter "A" maximal {{ Type }} a\ + (minductive "wleft" tt (arity {{ Type }}) l\ + (minductive "wright" tt (arity {{ Type }}) r\ + (mblock [ + [constructor "wleftK" (arity {{ lp:a -> lp:l }})], + [constructor "wrightK" (arity {{ lp:a -> lp:r }})] + ])))), + get-option "module" "" ==> derive.decl+main "wleft" D. +}}. + +Module WrapperMutualDeclaration. + Elpi derive_mutual_wrapper_test. + + Check wright : Type. + Check wleftK 0 : wleft. + Check wrightK true : wright. +End WrapperMutualDeclaration. + +Module Type MutualBase. + Include test_derive_corelib.Mutual.Tree. +End MutualBase. + +Module Type MutualMapExpected. + Include MutualBase. + Definition tree_map : tree -> tree := + fix tree_map_rec (x : tree) : tree := + match x with + | node f => node (forest_map_rec f) + end + with forest_map_rec (x : forest) : forest := + match x with + | empty => empty + | cons t f => cons (tree_map_rec t) (forest_map_rec f) + end + for + tree_map_rec. + Definition forest_map : forest -> forest := + fix tree_map_rec (x : tree) : tree := + match x with + | node f => node (forest_map_rec f) + end + with forest_map_rec (x : forest) : forest := + match x with + | empty => empty + | cons t f => cons (tree_map_rec t) (forest_map_rec f) + end + for + forest_map_rec. +End MutualMapExpected. + +Module Type MutualLensExpected. + Include MutualBase. + (* tree/forest are not records, so lens derives no Coq definitions. *) +End MutualLensExpected. + +Module Type MutualLensLawsExpected. + Include MutualLensExpected. + (* No lenses means no lens-law constants. *) +End MutualLensLawsExpected. + +Module Type MutualParam1Expected. + Include MutualBase. + Universe tree_reali_u forest_reali_u. + Constraint Set < tree_reali_u. + Constraint Set < forest_reali_u. + Inductive is_tree : tree -> Type@{tree_reali_u} := + | is_node (f : forest) (Pf : is_forest f) : is_tree (node f) + with is_forest : forest -> Type@{forest_reali_u} := + | is_empty : is_forest empty + | is_cons (t : tree) (Pt : is_tree t) + (f : forest) (Pf : is_forest f) : is_forest (cons t f). + Definition reali_is_tree : param1.reali_db tree is_tree := + @param1.store_reali _ _ tree is_tree. + Definition reali_is_forest : param1.reali_db forest is_forest := + @param1.store_reali _ _ forest is_forest. + Definition reali_is_tree_node : param1.reali_db node is_node := + @param1.store_reali _ _ node is_node. + Definition reali_is_forest_empty : param1.reali_db empty is_empty := + @param1.store_reali _ _ empty is_empty. + Definition reali_is_forest_cons : param1.reali_db cons is_cons := + @param1.store_reali _ _ cons is_cons. +End MutualParam1Expected. + +Module Type MutualParam1CongrExpected. + Include MutualParam1Expected. + Definition congr_is_node : forall (x : forest) + (p1 p2 : is_forest x), + p1 = p2 -> + is_node x p1 = is_node x p2 := + fun (x : forest) (p1 p2 : is_forest x) + (e : p1 = p2) => + match + e in _ = i + return is_node x p1 = is_node x i + with + | eq_refl => eq_refl + end. + Definition congr_is_empty : is_empty = is_empty := + eq_refl. + Definition congr_is_cons : forall (x : tree) + (p1 p2 : is_tree x), + p1 = p2 -> + forall (x0 : forest) + (p3 p4 : is_forest x0), + p3 = p4 -> + is_cons x p1 x0 p3 = + is_cons x p2 x0 p4 := + fun (x : tree) (p1 p2 : is_tree x) + (e : p1 = p2) => + match + e in _ = i + return + (forall (x0 : forest) + (p3 p4 : is_forest x0), + p3 = p4 -> + is_cons x p1 x0 p3 = + is_cons x i x0 p4) + with + | eq_refl => + fun (x0 : forest) + (p3 p4 : is_forest x0) (e0 : p3 = p4) => + match + e0 in _ = i + return + is_cons x p1 x0 p3 = + is_cons x p1 x0 i + with + | eq_refl => eq_refl + end + end. +End MutualParam1CongrExpected. + +Module Type MutualParam1TrivialExpected. + Include MutualParam1CongrExpected. + Definition is_tree_inhab : forall x : tree, is_tree x := + fix is_tree_inhab_rec (x : tree) : + is_tree x := + match x as i return is_tree i with + | node f => + is_node f (is_forest_inhab_rec f) + end + with is_forest_inhab_rec (x : forest) : + is_forest x := + match x as i return is_forest i with + | empty => is_empty + | cons t f => + is_cons t (is_tree_inhab_rec t) f + (is_forest_inhab_rec f) + end + for + is_tree_inhab_rec. + Definition is_forest_inhab : forall x : forest, is_forest x := + fix is_tree_inhab_rec (x : tree) : + is_tree x := + match x as i return is_tree i with + | node f => + is_node f (is_forest_inhab_rec f) + end + with is_forest_inhab_rec (x : forest) : + is_forest x := + match x as i return is_forest i with + | empty => is_empty + | cons t f => + is_cons t (is_tree_inhab_rec t) f + (is_forest_inhab_rec f) + end + for + is_forest_inhab_rec. + Definition is_tree_trivial : forall x : tree, + {u : is_tree x & + forall v : is_tree x, u = v} := + fun x : tree => + param1.contracts tree is_tree x + (is_tree_inhab x) + ((fix is_tree_trivial_rec + (x0 : tree) (y : is_tree x0) + {struct y} : is_tree_inhab x0 = y := + match + y as i in is_tree s1 + return is_tree_inhab s1 = i + with + | is_node f Pf => + match + param1.trivial_uniq forest + is_forest + (fun x1 : forest => + param1.contracts forest + is_forest x1 + (is_forest_inhab x1) + (is_forest_trivial_rec x1)) + f Pf + in _ = H + return + is_node f + (param1.trivial_full forest + is_forest + (fun x1 : forest => + param1.contracts forest + is_forest x1 + (is_forest_inhab x1) + (is_forest_trivial_rec x1)) + f) = + is_node f H + with + | eq_refl => eq_refl + end + end + with is_forest_trivial_rec + (x0 : forest) + (y : is_forest x0) {struct y} : + is_forest_inhab x0 = y := + match + y as i in is_forest s1 + return is_forest_inhab s1 = i + with + | is_empty => eq_refl + | is_cons t Pt f Pf => + match + param1.trivial_uniq forest + is_forest + (fun x1 : forest => + param1.contracts forest + is_forest x1 + (is_forest_inhab x1) + (is_forest_trivial_rec x1)) + f Pf + in _ = H + return + is_cons t + (param1.trivial_full tree + is_tree + (fun x1 : tree => + param1.contracts tree + is_tree x1 + (is_tree_inhab x1) + (is_tree_trivial_rec x1)) + t) + f + (param1.trivial_full forest + is_forest + (fun x1 : forest => + param1.contracts forest + is_forest x1 + (is_forest_inhab x1) + (is_forest_trivial_rec x1)) + f) = + is_cons t Pt f H + with + | eq_refl => + match + param1.trivial_uniq tree + is_tree + (fun x1 : tree => + param1.contracts tree + is_tree x1 + (is_tree_inhab x1) + (is_tree_trivial_rec x1)) + t Pt + in _ = H + return + is_cons t + (param1.trivial_full tree + is_tree + (fun x1 : tree => + param1.contracts tree + is_tree x1 + (is_tree_inhab x1) + (is_tree_trivial_rec x1)) + t) + f + (param1.trivial_full forest + is_forest + (fun x1 : forest => + param1.contracts forest + is_forest x1 + (is_forest_inhab x1) + (is_forest_trivial_rec x1)) + f) = + is_cons t H f + (param1.trivial_full forest + is_forest + (fun x1 : forest => + param1.contracts forest + is_forest x1 + (is_forest_inhab x1) + (is_forest_trivial_rec x1)) + f) + with + | eq_refl => eq_refl + end + end + end + for + is_tree_trivial_rec) x). + Definition is_forest_trivial : forall x : forest, + {u : is_forest x & + forall v : is_forest x, u = v} := + fun x : forest => + param1.contracts forest is_forest x + (is_forest_inhab x) + ((fix is_tree_trivial_rec + (x0 : tree) (y : is_tree x0) + {struct y} : is_tree_inhab x0 = y := + match + y as i in is_tree s1 + return is_tree_inhab s1 = i + with + | is_node f Pf => + match + param1.trivial_uniq forest + is_forest + (fun x1 : forest => + param1.contracts forest + is_forest x1 + (is_forest_inhab x1) + (is_forest_trivial_rec x1)) + f Pf + in _ = H + return + is_node f + (param1.trivial_full forest + is_forest + (fun x1 : forest => + param1.contracts forest + is_forest x1 + (is_forest_inhab x1) + (is_forest_trivial_rec x1)) + f) = + is_node f H + with + | eq_refl => eq_refl + end + end + with is_forest_trivial_rec + (x0 : forest) + (y : is_forest x0) {struct y} : + is_forest_inhab x0 = y := + match + y as i in is_forest s1 + return is_forest_inhab s1 = i + with + | is_empty => eq_refl + | is_cons t Pt f Pf => + match + param1.trivial_uniq forest + is_forest + (fun x1 : forest => + param1.contracts forest + is_forest x1 + (is_forest_inhab x1) + (is_forest_trivial_rec x1)) + f Pf + in _ = H + return + is_cons t + (param1.trivial_full tree + is_tree + (fun x1 : tree => + param1.contracts tree + is_tree x1 + (is_tree_inhab x1) + (is_tree_trivial_rec x1)) + t) + f + (param1.trivial_full forest + is_forest + (fun x1 : forest => + param1.contracts forest + is_forest x1 + (is_forest_inhab x1) + (is_forest_trivial_rec x1)) + f) = + is_cons t Pt f H + with + | eq_refl => + match + param1.trivial_uniq tree + is_tree + (fun x1 : tree => + param1.contracts tree + is_tree x1 + (is_tree_inhab x1) + (is_tree_trivial_rec x1)) + t Pt + in _ = H + return + is_cons t + (param1.trivial_full tree + is_tree + (fun x1 : tree => + param1.contracts tree + is_tree x1 + (is_tree_inhab x1) + (is_tree_trivial_rec x1)) + t) + f + (param1.trivial_full forest + is_forest + (fun x1 : forest => + param1.contracts forest + is_forest x1 + (is_forest_inhab x1) + (is_forest_trivial_rec x1)) + f) = + is_cons t H f + (param1.trivial_full forest + is_forest + (fun x1 : forest => + param1.contracts forest + is_forest x1 + (is_forest_inhab x1) + (is_forest_trivial_rec x1)) + f) + with + | eq_refl => eq_refl + end + end + end + for + is_forest_trivial_rec) x). +End MutualParam1TrivialExpected. + +Module Type MutualParam1FunctorExpected. + Include MutualParam1Expected. + Definition is_tree_functor : forall x : tree, + is_tree x -> is_tree x := + fix is_tree_functor_rec + (x : tree) (x0 : is_tree x) {struct + x0} : is_tree x := + match + x0 in is_tree s1 + return is_tree s1 + with + | is_node f Pf => is_node f Pf + end + with is_forest_functor_rec + (x : forest) (x0 : is_forest x) + {struct x0} : is_forest x := + match + x0 in is_forest s1 + return is_forest s1 + with + | is_empty => is_empty + | is_cons t Pt f Pf => + is_cons t Pt f Pf + end + for + is_tree_functor_rec. + Definition is_forest_functor : forall x : forest, + is_forest x -> is_forest x := + fix is_tree_functor_rec + (x : tree) (x0 : is_tree x) {struct + x0} : is_tree x := + match + x0 in is_tree s1 + return is_tree s1 + with + | is_node f Pf => is_node f Pf + end + with is_forest_functor_rec + (x : forest) (x0 : is_forest x) + {struct x0} : is_forest x := + match + x0 in is_forest s1 + return is_forest s1 + with + | is_empty => is_empty + | is_cons t Pt f Pf => + is_cons t Pt f Pf + end + for + is_forest_functor_rec. +End MutualParam1FunctorExpected. + +Module Type MutualParam2Expected. + Include MutualBase. + Inductive tree_R : tree -> tree -> Set := + | node_R (f1 f2 : forest) (fR : forest_R f1 f2) : + tree_R (node f1) (node f2) + with forest_R : forest -> forest -> Set := + | empty_R : forest_R empty empty + | cons_R (t1 t2 : tree) (tR : tree_R t1 t2) + (f1 f2 : forest) (fR : forest_R f1 f2) : + forest_R (cons t1 f1) (cons t2 f2). + Definition param_tree_R : param2.param_db tree tree + tree_R := + @param2.store_param _ _ _ tree tree tree_R. + Definition param_forest_R : param2.param_db forest forest + forest_R := + @param2.store_param _ _ _ forest forest forest_R. + Definition param_node_R : param2.param_db node node + node_R := + @param2.store_param _ _ _ node node node_R. + Definition param_empty_R : param2.param_db empty empty + empty_R := + @param2.store_param _ _ _ empty empty empty_R. + Definition param_cons_R : param2.param_db cons cons + cons_R := + @param2.store_param _ _ _ cons cons cons_R. +End MutualParam2Expected. + +Module Type MutualInductionExpected. + Include MutualParam1FunctorExpected. + Definition tree_induction : forall (P : tree -> Type) + (P0 : forest -> Type), + (forall f : forest, + is_forest f -> P0 f -> P (node f)) -> + P0 empty -> + (forall t : tree, + is_tree t -> + P t -> + forall f : forest, + is_forest f -> P0 f -> P0 (cons t f)) -> + forall s1 : tree, is_tree s1 -> P s1 := + fun (P : tree -> Type) (P0 : forest -> Type) + (His_node : forall f : forest, + is_forest f -> + P0 f -> P (node f)) + (His_empty : P0 empty) + (His_cons : forall t : tree, + is_tree t -> + P t -> + forall f : forest, + is_forest f -> + P0 f -> P0 (cons t f)) => + fix is_tree_induction_rec + (s1 : tree) (H : is_tree s1) {struct H} : + P s1 := + match H in is_tree s2 return P s2 with + | is_node f Pf => + His_node f Pf (is_forest_induction_rec f Pf) + end + with is_forest_induction_rec + (s1 : forest) (H : is_forest s1) {struct H} : + P0 s1 := + match H in is_forest s2 return P0 s2 with + | is_empty => His_empty + | is_cons t Pt f Pf => + His_cons t Pt (is_tree_induction_rec t Pt) f Pf + (is_forest_induction_rec f Pf) + end + for + is_tree_induction_rec. +End MutualInductionExpected. + +Module Type MutualTagExpected. + Include MutualBase. + Definition tree_tag : tree -> BinNums.positive := + fun i : tree => match i with + | node _ => BinNums.xH + end. + Definition forest_tag : forest -> BinNums.positive := + fun i : forest => + match i with + | empty => BinNums.xH + | cons _ _ => BinNums.xO BinNums.xH + end. +End MutualTagExpected. + +Module Type MutualFieldsExpected. + Include MutualTagExpected. + Universe box_tree_node_u box_forest_empty_u box_forest_cons_u. + Constraint Set < box_tree_node_u. + Constraint Set < box_forest_empty_u. + Constraint Set < box_forest_cons_u. + Record box_tree_node : Type@{box_tree_node_u} := Box_tree_node { Box_tree_node_0 : forest }. + Record box_forest_empty : Type@{box_forest_empty_u} := Box_forest_empty {}. + Record box_forest_cons : Type@{box_forest_cons_u} := Box_forest_cons { + Box_forest_cons_0 : tree; + Box_forest_cons_1 : forest; + }. + Definition tree_fields_t : BinNums.positive -> Type := + fun _ : BinNums.positive => box_tree_node. + Definition tree_fields : forall i : tree, + tree_fields_t (tree_tag i) := + fun i : tree => + match + i as i0 return tree_fields_t (tree_tag i0) + with + | node f => {| Box_tree_node_0 := f |} + end. + Definition tree_construct : BinNums.positive -> + box_tree_node -> option tree := + fun (_ : BinNums.positive) (b : box_tree_node) => + match b with + | {| Box_tree_node_0 := Box_tree_node_0 |} => + Some (node Box_tree_node_0) + end. + Parameter tree_constructP : forall i : tree, + tree_construct (tree_tag i) + (tree_fields i) = + Some i. + Definition forest_fields_t : BinNums.positive -> Type := + fun p : BinNums.positive => + match p with + | BinNums.xI _ => unit + | BinNums.xO _ => box_forest_cons + | BinNums.xH => box_forest_empty + end. + Definition forest_fields : forall i : forest, + forest_fields_t (forest_tag i) := + fun i : forest => + match + i as i0 return forest_fields_t (forest_tag i0) + with + | empty => Box_forest_empty + | cons t f => + {| + Box_forest_cons_0 := t; + Box_forest_cons_1 := f + |} + end. + Definition forest_construct : forall p : BinNums.positive, + forest_fields_t p -> option forest := + fun p : BinNums.positive => + match + p as i return forest_fields_t i -> option forest + with + | BinNums.xI _ => fun _ : unit => None + | BinNums.xO _ => + fun b : box_forest_cons => + match b with + | {| + Box_forest_cons_0 := Box_forest_cons_0; + Box_forest_cons_1 := Box_forest_cons_1 + |} => Some (cons Box_forest_cons_0 Box_forest_cons_1) + end + | BinNums.xH => + fun _ : box_forest_empty => Some empty + end. + Parameter forest_constructP : forall i : forest, + forest_construct (forest_tag i) + (forest_fields i) = + Some i. +End MutualFieldsExpected. + +Module Type MutualEqbExpected. + Include MutualFieldsExpected. + Definition tree_eqb : tree -> tree -> bool := + fix tree (x1 x2 : tree) {struct x1} : bool := + match x1 with + | node f => + eqb_core_defs.eqb_body (tagB:=tree_tag) + (fields_tA:=fun _ : BinNums.positive => box_tree_node) + (fields_tB:=tree_fields_t) tree_fields + (fun (_ : BinNums.positive) (a b : box_tree_node) => + match a with + | {| Box_tree_node_0 := Box_tree_node_0 |} => + match b with + | {| Box_tree_node_0 := Box_tree_node_1 |} => + (forest Box_tree_node_0 Box_tree_node_1 && true)%bool + end + end) + (t1:=tree_tag (node f)) + {| Box_tree_node_0 := f |} x2 + end + with forest (x1 x2 : forest) {struct x1} : bool := + match x1 with + | empty => + eqb_core_defs.eqb_body (tagB:=forest_tag) + (fields_tA:=forest_fields_t) + (fields_tB:=forest_fields_t) forest_fields + (fun x : BinNums.positive => + match + x as i + return + forest_fields_t i -> + forest_fields_t i -> bool + with + | BinNums.xI _ => fun _ _ : unit => true + | BinNums.xO _ => + fun a b : box_forest_cons => + match a with + | {| + Box_forest_cons_0 := Box_forest_cons_0; + Box_forest_cons_1 := Box_forest_cons_1 + |} => + match b with + | {| + Box_forest_cons_0 := Box_forest_cons_2; + Box_forest_cons_1 := Box_forest_cons_3 + |} => + (tree Box_forest_cons_0 Box_forest_cons_2 && + (forest Box_forest_cons_1 Box_forest_cons_3 && true))%bool + end + end + | BinNums.xH => fun _ _ : box_forest_empty => true + end) + (t1:=forest_tag empty) Box_forest_empty + x2 + | cons t f => + eqb_core_defs.eqb_body (tagB:=forest_tag) + (fields_tA:=forest_fields_t) + (fields_tB:=forest_fields_t) forest_fields + (fun x : BinNums.positive => + match + x as i + return + forest_fields_t i -> + forest_fields_t i -> bool + with + | BinNums.xI _ => fun _ _ : unit => true + | BinNums.xO _ => + fun a b : box_forest_cons => + match a with + | {| + Box_forest_cons_0 := Box_forest_cons_0; + Box_forest_cons_1 := Box_forest_cons_1 + |} => + match b with + | {| + Box_forest_cons_0 := Box_forest_cons_2; + Box_forest_cons_1 := Box_forest_cons_3 + |} => + (tree Box_forest_cons_0 Box_forest_cons_2 && + (forest Box_forest_cons_1 Box_forest_cons_3 && true))%bool + end + end + | BinNums.xH => fun _ _ : box_forest_empty => true + end) + (t1:=forest_tag (cons t f)) + {| + Box_forest_cons_0 := t; Box_forest_cons_1 := f + |} x2 + end + for + tree. + Definition forest_eqb : forest -> forest -> bool := + fix tree (x1 x2 : tree) {struct x1} : bool := + match x1 with + | node f => + eqb_core_defs.eqb_body (tagB:=tree_tag) + (fields_tA:=fun _ : BinNums.positive => box_tree_node) + (fields_tB:=tree_fields_t) tree_fields + (fun (_ : BinNums.positive) (a b : box_tree_node) => + match a with + | {| Box_tree_node_0 := Box_tree_node_0 |} => + match b with + | {| Box_tree_node_0 := Box_tree_node_1 |} => + (forest Box_tree_node_0 Box_tree_node_1 && true)%bool + end + end) + (t1:=tree_tag (node f)) + {| Box_tree_node_0 := f |} x2 + end + with forest (x1 x2 : forest) {struct x1} : bool := + match x1 with + | empty => + eqb_core_defs.eqb_body (tagB:=forest_tag) + (fields_tA:=forest_fields_t) + (fields_tB:=forest_fields_t) forest_fields + (fun x : BinNums.positive => + match + x as i + return + forest_fields_t i -> + forest_fields_t i -> bool + with + | BinNums.xI _ => fun _ _ : unit => true + | BinNums.xO _ => + fun a b : box_forest_cons => + match a with + | {| + Box_forest_cons_0 := Box_forest_cons_0; + Box_forest_cons_1 := Box_forest_cons_1 + |} => + match b with + | {| + Box_forest_cons_0 := Box_forest_cons_2; + Box_forest_cons_1 := Box_forest_cons_3 + |} => + (tree Box_forest_cons_0 Box_forest_cons_2 && + (forest Box_forest_cons_1 Box_forest_cons_3 && true))%bool + end + end + | BinNums.xH => fun _ _ : box_forest_empty => true + end) + (t1:=forest_tag empty) Box_forest_empty + x2 + | cons t f => + eqb_core_defs.eqb_body (tagB:=forest_tag) + (fields_tA:=forest_fields_t) + (fields_tB:=forest_fields_t) forest_fields + (fun x : BinNums.positive => + match + x as i + return + forest_fields_t i -> + forest_fields_t i -> bool + with + | BinNums.xI _ => fun _ _ : unit => true + | BinNums.xO _ => + fun a b : box_forest_cons => + match a with + | {| + Box_forest_cons_0 := Box_forest_cons_0; + Box_forest_cons_1 := Box_forest_cons_1 + |} => + match b with + | {| + Box_forest_cons_0 := Box_forest_cons_2; + Box_forest_cons_1 := Box_forest_cons_3 + |} => + (tree Box_forest_cons_0 Box_forest_cons_2 && + (forest Box_forest_cons_1 Box_forest_cons_3 && true))%bool + end + end + | BinNums.xH => fun _ _ : box_forest_empty => true + end) + (t1:=forest_tag (cons t f)) + {| + Box_forest_cons_0 := t; Box_forest_cons_1 := f + |} x2 + end + for + forest. + Definition tree_eqb_fields : (tree -> tree -> bool) -> + BinNums.positive -> + box_tree_node -> box_tree_node -> bool := + fun (_ : tree -> tree -> bool) + (_ : BinNums.positive) (a b : box_tree_node) => + match a with + | {| Box_tree_node_0 := Box_tree_node_0 |} => + match b with + | {| Box_tree_node_0 := Box_tree_node_1 |} => + (forest_eqb Box_tree_node_0 Box_tree_node_1 && true)%bool + end + end. + Definition forest_eqb_fields : (forest -> forest -> bool) -> + forall x : BinNums.positive, + forest_fields_t x -> forest_fields_t x -> bool := + fun (rec : forest -> forest -> bool) + (x : BinNums.positive) => + match + x as i + return forest_fields_t i -> forest_fields_t i -> bool + with + | BinNums.xI _ => fun _ _ : unit => true + | BinNums.xO _ => + fun a b : box_forest_cons => + match a with + | {| + Box_forest_cons_0 := Box_forest_cons_0; + Box_forest_cons_1 := Box_forest_cons_1 + |} => + match b with + | {| + Box_forest_cons_0 := Box_forest_cons_2; + Box_forest_cons_1 := Box_forest_cons_3 + |} => + (tree_eqb Box_forest_cons_0 Box_forest_cons_2 && + (rec Box_forest_cons_1 Box_forest_cons_3 && true))%bool + end + end + | BinNums.xH => fun _ _ : box_forest_empty => true + end. +End MutualEqbExpected. + +Module Type MutualEqbCorrectExpected. + Include MutualEqbExpected. + Universe tree_reali_u forest_reali_u. + Constraint Set < tree_reali_u. + Constraint Set < forest_reali_u. + Inductive is_tree : tree -> Type@{tree_reali_u} := + | is_node (f : forest) (Pf : is_forest f) : is_tree (node f) + with is_forest : forest -> Type@{forest_reali_u} := + | is_empty : is_forest empty + | is_cons (t : tree) (Pt : is_tree t) + (f : forest) (Pf : is_forest f) : is_forest (cons t f). + Definition is_tree_inhab : forall x : tree, is_tree x := + fix is_tree_inhab_rec (x : tree) : + is_tree x := + match x as i return is_tree i with + | node f => + is_node f (is_forest_inhab_rec f) + end + with is_forest_inhab_rec (x : forest) : + is_forest x := + match x as i return is_forest i with + | empty => is_empty + | cons t f => + is_cons t (is_tree_inhab_rec t) f + (is_forest_inhab_rec f) + end + for + is_tree_inhab_rec. + Definition is_forest_inhab : forall x : forest, is_forest x := + fix is_tree_inhab_rec (x : tree) : + is_tree x := + match x as i return is_tree i with + | node f => + is_node f (is_forest_inhab_rec f) + end + with is_forest_inhab_rec (x : forest) : + is_forest x := + match x as i return is_forest i with + | empty => is_empty + | cons t f => + is_cons t (is_tree_inhab_rec t) f + (is_forest_inhab_rec f) + end + for + is_forest_inhab_rec. + Definition tree_induction : forall (P : tree -> Type) + (P0 : forest -> Type), + (forall f : forest, + is_forest f -> P0 f -> P (node f)) -> + P0 empty -> + (forall t : tree, + is_tree t -> + P t -> + forall f : forest, + is_forest f -> + P0 f -> P0 (cons t f)) -> + forall s1 : tree, is_tree s1 -> P s1 := + fun (P : tree -> Type) + (P0 : forest -> Type) + (His_node : forall f : forest, + is_forest f -> + P0 f -> P (node f)) + (His_empty : P0 empty) + (His_cons : forall t : tree, + is_tree t -> + P t -> + forall f : forest, + is_forest f -> + P0 f -> P0 (cons t f)) => + fix is_tree_induction_rec + (s1 : tree) (H : is_tree s1) {struct H} : + P s1 := + match H in is_tree s2 return P s2 with + | is_node f Pf => + His_node f Pf (is_forest_induction_rec f Pf) + end + with is_forest_induction_rec + (s1 : forest) (H : is_forest s1) {struct + H} : P0 s1 := + match H in is_forest s2 return P0 s2 with + | is_empty => His_empty + | is_cons t Pt f Pf => + His_cons t Pt (is_tree_induction_rec t Pt) f Pf + (is_forest_induction_rec f Pf) + end + for + is_tree_induction_rec. + Definition forest_induction : forall (P : tree -> Type) + (P0 : forest -> Type), + (forall f : forest, + is_forest f -> P0 f -> P (node f)) -> + P0 empty -> + (forall t : tree, + is_tree t -> + P t -> + forall f : forest, + is_forest f -> + P0 f -> P0 (cons t f)) -> + forall s1 : forest, + is_forest s1 -> P0 s1 := + fun (P : tree -> Type) + (P0 : forest -> Type) + (His_node : forall f : forest, + is_forest f -> + P0 f -> P (node f)) + (His_empty : P0 empty) + (His_cons : forall t : tree, + is_tree t -> + P t -> + forall f : forest, + is_forest f -> + P0 f -> P0 (cons t f)) => + fix is_tree_induction_rec + (s1 : tree) (H : is_tree s1) {struct H} : + P s1 := + match H in is_tree s2 return P s2 with + | is_node f Pf => + His_node f Pf (is_forest_induction_rec f Pf) + end + with is_forest_induction_rec + (s1 : forest) (H : is_forest s1) {struct + H} : P0 s1 := + match H in is_forest s2 return P0 s2 with + | is_empty => His_empty + | is_cons t Pt f Pf => + His_cons t Pt (is_tree_induction_rec t Pt) f Pf + (is_forest_induction_rec f Pf) + end + for + is_forest_induction_rec. + Parameter tree_eqb_correct : forall x : tree, @eqb_correct_on tree tree_eqb x. + Parameter forest_eqb_correct : forall x : forest, @eqb_correct_on forest forest_eqb x. + Parameter tree_eqb_refl : forall x : tree, @eqb_refl_on tree tree_eqb x. + Parameter forest_eqb_refl : forall x : forest, @eqb_refl_on forest forest_eqb x. +End MutualEqbCorrectExpected. + +Module Type MutualEqbOKExpected. + Include MutualEqbCorrectExpected. + Parameter tree_eqb_OK : forall x1 x2 : tree, reflect (@eq tree x1 x2) (tree_eqb x1 x2). + Parameter forest_eqb_OK : forall x1 x2 : forest, reflect (@eq forest x1 x2) (forest_eqb x1 x2). + Parameter tree_eqb_OK_sumbool : forall x y : tree, sumbool (@eq tree x y) (not (@eq tree x y)). + Parameter forest_eqb_OK_sumbool : forall x y : forest, sumbool (@eq forest x y) (not (@eq forest x y)). +End MutualEqbOKExpected. + +Module Type MutualIsKExpected. + Include MutualBase. + Definition tree_is_node : tree -> bool := + fun i : tree => match i with + | node _ => true + end. + Definition forest_is_empty : forest -> bool := + fun i : forest => + match i with + | empty => true + | cons _ _ => false + end. + Definition forest_is_cons : forest -> bool := + fun i : forest => + match i with + | empty => false + | cons _ _ => true + end. +End MutualIsKExpected. + +Module Type MutualProjKExpected. + Include MutualBase. + Definition tree_projnode1 : forest -> tree -> forest := + fun (_ : forest) (i : tree) => + match i with + | node f0 => f0 + end. + Definition forest_projcons1 : tree -> + forest -> forest -> tree := + fun (t : tree) (_ i : forest) => + match i with + | empty => t + | cons t0 _ => t0 + end. + Definition forest_projcons2 : tree -> + forest -> forest -> forest := + fun (_ : tree) (f i : forest) => + match i with + | empty => f + | cons _ f0 => f0 + end. +End MutualProjKExpected. + +Module Type MutualBcongrExpected. + Include MutualProjKExpected. + Parameter tree_bcongr_node : forall (x y : forest) (b : bool), + reflect (x = y) b -> + reflect (node x = node y) b. + Parameter forest_bcongr_empty : reflect (empty = empty) true. + Parameter forest_bcongr_cons : forall (x y : tree) (b : bool), + reflect (x = y) b -> + forall (x0 y0 : forest) (b0 : bool), + reflect (x0 = y0) b0 -> + reflect (cons x x0 = cons y y0) (b && b0). +End MutualBcongrExpected. + +Module Type ParametrizedMutualBase. + Include test_derive_corelib.Mutual.ParametrizedTree. +End ParametrizedMutualBase. + +Module Type ParametrizedMutualMapExpected. + Include ParametrizedMutualBase. + Definition ptree_map : forall A1 A2 : Type, + (A1 -> A2) -> + ptree A1 -> ptree A2 := + fun (A1 A2 : Type) (Af : A1 -> A2) => + fix ptree_map_rec (x : ptree A1) : + ptree A2 := + match x with + | pnode _ x0 f => + pnode A2 (Af x0) (pforest_map_rec f) + end + with pforest_map_rec (x : pforest A1) : + pforest A2 := + match x with + | pempty _ => pempty A2 + | pcons _ t f => + pcons A2 (ptree_map_rec t) (pforest_map_rec f) + end + for + ptree_map_rec. + Definition pforest_map : forall A1 A2 : Type, + (A1 -> A2) -> + pforest A1 -> pforest A2 := + fun (A1 A2 : Type) (Af : A1 -> A2) => + fix ptree_map_rec (x : ptree A1) : + ptree A2 := + match x with + | pnode _ x0 f => + pnode A2 (Af x0) (pforest_map_rec f) + end + with pforest_map_rec (x : pforest A1) : + pforest A2 := + match x with + | pempty _ => pempty A2 + | pcons _ t f => + pcons A2 (ptree_map_rec t) (pforest_map_rec f) + end + for + pforest_map_rec. +End ParametrizedMutualMapExpected. + +Module Type ParametrizedMutualLensExpected. + Include ParametrizedMutualBase. + (* ptree/pforest are not records, so lens derives no Coq definitions. *) +End ParametrizedMutualLensExpected. + +Module Type ParametrizedMutualLensLawsExpected. + Include ParametrizedMutualLensExpected. + (* No lenses means no lens-law constants. *) +End ParametrizedMutualLensLawsExpected. + +Module Type ParametrizedMutualParam1Expected. + Include ParametrizedMutualBase. + Universe is_ptree_u0 is_ptree_u1 is_ptree_u2 is_ptree_u3 is_ptree_u4 is_ptree_u5 is_ptree_u6. + Inductive is_ptree : forall A : Type, (A -> Type@{is_ptree_u0}) -> ptree A -> Type@{is_ptree_u1} := + | is_pnode : forall A (PA : A -> Type@{is_ptree_u2}) (x : A), PA x -> + forall f : pforest A, is_pforest A PA f -> is_ptree A PA (@pnode A x f) + with is_pforest : forall A : Type, (A -> Type@{is_ptree_u3}) -> pforest A -> Type@{is_ptree_u4} := + | is_pempty : forall A (PA : A -> Type@{is_ptree_u5}), is_pforest A PA (@pempty A) + | is_pcons : forall A (PA : A -> Type@{is_ptree_u6}) (t : ptree A), is_ptree A PA t -> + forall f : pforest A, is_pforest A PA f -> + is_pforest A PA (@pcons A t f). + Definition reali_is_ptree : param1.reali_db ptree + is_ptree := + @param1.store_reali _ _ ptree is_ptree. + Definition reali_is_pforest : param1.reali_db pforest + is_pforest := + @param1.store_reali _ _ pforest is_pforest. + Definition reali_is_ptree_pnode : param1.reali_db pnode + is_pnode := + @param1.store_reali _ _ pnode is_pnode. + Definition reali_is_pforest_pempty : param1.reali_db pempty + is_pempty := + @param1.store_reali _ _ pempty is_pempty. + Definition reali_is_pforest_pcons : param1.reali_db pcons + is_pcons := + @param1.store_reali _ _ pcons is_pcons. +End ParametrizedMutualParam1Expected. + +Module Type ParametrizedMutualParam1CongrExpected. + Include ParametrizedMutualParam1Expected. + Definition congr_is_pnode : forall (x : Type) (p : x -> Type) (x0 : x) (p1 p2 : p x0), + p1 = p2 -> + forall (x1 : pforest x) + (p3 p4 : is_pforest x p x1), + p3 = p4 -> + is_pnode x p x0 p1 x1 p3 = + is_pnode x p x0 p2 x1 p4 := + fun (x : Type) (p : x -> Type) (x0 : x) (p1 p2 : p x0) (e : p1 = p2) => + match + e in _ = i + return + (forall (x1 : pforest x) + (p3 p4 : is_pforest x p x1), + p3 = p4 -> + is_pnode x p x0 p1 x1 p3 = + is_pnode x p x0 i x1 p4) + with + | eq_refl => + fun (x1 : pforest x) + (p3 p4 : is_pforest x p x1) + (e0 : p3 = p4) => + match + e0 in _ = i + return + is_pnode x p x0 p1 x1 p3 = + is_pnode x p x0 p1 x1 i + with + | eq_refl => eq_refl + end + end. + Definition congr_is_pempty : forall (x : Type) (p : x -> Type), + is_pempty x p = + is_pempty x p := + fun (x : Type) (p : x -> Type) => eq_refl. + Definition congr_is_pcons : forall (x : Type) (p : x -> Type) + (x0 : ptree x) + (p1 p2 : is_ptree x p x0), + p1 = p2 -> + forall (x1 : pforest x) + (p3 p4 : is_pforest x p x1), + p3 = p4 -> + is_pcons x p x0 p1 x1 p3 = + is_pcons x p x0 p2 x1 p4 := + fun (x : Type) (p : x -> Type) (x0 : ptree x) + (p1 p2 : is_ptree x p x0) + (e : p1 = p2) => + match + e in _ = i + return + (forall (x1 : pforest x) + (p3 p4 : is_pforest x p x1), + p3 = p4 -> + is_pcons x p x0 p1 x1 p3 = + is_pcons x p x0 i x1 p4) + with + | eq_refl => + fun (x1 : pforest x) + (p3 p4 : is_pforest x p x1) + (e0 : p3 = p4) => + match + e0 in _ = i + return + is_pcons x p x0 p1 x1 p3 = + is_pcons x p x0 p1 x1 i + with + | eq_refl => eq_refl + end + end. +End ParametrizedMutualParam1CongrExpected. + +Module Type ParametrizedMutualParam1FunctorExpected. + Include ParametrizedMutualParam1Expected. + Definition is_ptree_functor : forall (A : Type) (PA PB : A -> Type), + (forall x : A, PA x -> PB x) -> + forall x : ptree A, is_ptree A PA x -> is_ptree A PB x := + fun (A : Type) (PA PB : A -> Type) (f : forall x : A, PA x -> PB x) + (x : ptree A) (H : is_ptree A PA x) => + (fix is_ptree_functor_rec (A0 : Type) (PA0 : A0 -> Type) + (x : ptree A0) (Hx : is_ptree A0 PA0 x) {struct Hx} : + forall PB0 : A0 -> Type, + (forall x : A0, PA0 x -> PB0 x) -> is_ptree A0 PB0 x := + match Hx in is_ptree A1 PA1 x0 return + forall PB1 : A1 -> Type, + (forall x : A1, PA1 x -> PB1 x) -> is_ptree A1 PB1 x0 with + | is_pnode A1 PA1 x0 Px p Pf => + fun PB1 f1 => is_pnode A1 PB1 x0 (f1 x0 Px) p + (is_pforest_functor_rec A1 PA1 p Pf PB1 f1) + end + with is_pforest_functor_rec (A0 : Type) (PA0 : A0 -> Type) + (x : pforest A0) (Hx : is_pforest A0 PA0 x) {struct Hx} : + forall PB0 : A0 -> Type, + (forall x : A0, PA0 x -> PB0 x) -> is_pforest A0 PB0 x := + match Hx in is_pforest A1 PA1 x0 return + forall PB1 : A1 -> Type, + (forall x : A1, PA1 x -> PB1 x) -> is_pforest A1 PB1 x0 with + | is_pempty A1 PA1 => fun PB1 _ => is_pempty A1 PB1 + | is_pcons A1 PA1 t Pt p Pf => + fun PB1 f1 => is_pcons A1 PB1 t + (is_ptree_functor_rec A1 PA1 t Pt PB1 f1) p + (is_pforest_functor_rec A1 PA1 p Pf PB1 f1) + end + for is_ptree_functor_rec) A PA x H PB f. + Definition is_pforest_functor : forall (A : Type) (PA PB : A -> Type), + (forall x : A, PA x -> PB x) -> + forall x : pforest A, is_pforest A PA x -> is_pforest A PB x := + fun (A : Type) (PA PB : A -> Type) (f : forall x : A, PA x -> PB x) + (x : pforest A) (H : is_pforest A PA x) => + (fix is_ptree_functor_rec (A0 : Type) (PA0 : A0 -> Type) + (x : ptree A0) (Hx : is_ptree A0 PA0 x) {struct Hx} : + forall PB0 : A0 -> Type, + (forall x : A0, PA0 x -> PB0 x) -> is_ptree A0 PB0 x := + match Hx in is_ptree A1 PA1 x0 return + forall PB1 : A1 -> Type, + (forall x : A1, PA1 x -> PB1 x) -> is_ptree A1 PB1 x0 with + | is_pnode A1 PA1 x0 Px p Pf => + fun PB1 f1 => is_pnode A1 PB1 x0 (f1 x0 Px) p + (is_pforest_functor_rec A1 PA1 p Pf PB1 f1) + end + with is_pforest_functor_rec (A0 : Type) (PA0 : A0 -> Type) + (x : pforest A0) (Hx : is_pforest A0 PA0 x) {struct Hx} : + forall PB0 : A0 -> Type, + (forall x : A0, PA0 x -> PB0 x) -> is_pforest A0 PB0 x := + match Hx in is_pforest A1 PA1 x0 return + forall PB1 : A1 -> Type, + (forall x : A1, PA1 x -> PB1 x) -> is_pforest A1 PB1 x0 with + | is_pempty A1 PA1 => fun PB1 _ => is_pempty A1 PB1 + | is_pcons A1 PA1 t Pt p Pf => + fun PB1 f1 => is_pcons A1 PB1 t + (is_ptree_functor_rec A1 PA1 t Pt PB1 f1) p + (is_pforest_functor_rec A1 PA1 p Pf PB1 f1) + end + for is_pforest_functor_rec) A PA x H PB f. +End ParametrizedMutualParam1FunctorExpected. + +Module Type ParametrizedMutualParam1TrivialExpected. + Include ParametrizedMutualParam1CongrExpected. + Definition is_ptree_inhab : forall (A : Type) (PA : A -> Type), + param1.trivial A PA -> forall x : ptree A, is_ptree A PA x := + fun (A : Type) (PA : A -> Type) (HPA : param1.trivial A PA) + (x : ptree A) => + (fix is_ptree_inhab_rec (A0 : Type) (x : ptree A0) {struct x} : + forall PA0 : A0 -> Type, param1.trivial A0 PA0 -> is_ptree A0 PA0 x := + match x return forall PA1 : A0 -> Type, + param1.trivial A0 PA1 -> is_ptree A0 PA1 x with + | pnode _ x0 f => fun PA1 HPA1 => + is_pnode A0 PA1 x0 (param1.trivial_full A0 PA1 HPA1 x0) f + (is_pforest_inhab_rec A0 f PA1 HPA1) + end + with is_pforest_inhab_rec (A0 : Type) (x : pforest A0) {struct x} : + forall PA0 : A0 -> Type, param1.trivial A0 PA0 -> is_pforest A0 PA0 x := + match x return forall PA1 : A0 -> Type, + param1.trivial A0 PA1 -> is_pforest A0 PA1 x with + | pempty _ => fun PA1 _ => is_pempty A0 PA1 + | pcons _ t f => fun PA1 HPA1 => + is_pcons A0 PA1 t (is_ptree_inhab_rec A0 t PA1 HPA1) f + (is_pforest_inhab_rec A0 f PA1 HPA1) + end + for is_ptree_inhab_rec) A x PA HPA. + Definition is_pforest_inhab : forall (A : Type) (PA : A -> Type), + param1.trivial A PA -> forall x : pforest A, is_pforest A PA x := + fun (A : Type) (PA : A -> Type) (HPA : param1.trivial A PA) + (x : pforest A) => + (fix is_ptree_inhab_rec (A0 : Type) (x : ptree A0) {struct x} : + forall PA0 : A0 -> Type, param1.trivial A0 PA0 -> is_ptree A0 PA0 x := + match x return forall PA1 : A0 -> Type, + param1.trivial A0 PA1 -> is_ptree A0 PA1 x with + | pnode _ x0 f => fun PA1 HPA1 => + is_pnode A0 PA1 x0 (param1.trivial_full A0 PA1 HPA1 x0) f + (is_pforest_inhab_rec A0 f PA1 HPA1) + end + with is_pforest_inhab_rec (A0 : Type) (x : pforest A0) {struct x} : + forall PA0 : A0 -> Type, param1.trivial A0 PA0 -> is_pforest A0 PA0 x := + match x return forall PA1 : A0 -> Type, + param1.trivial A0 PA1 -> is_pforest A0 PA1 x with + | pempty _ => fun PA1 _ => is_pempty A0 PA1 + | pcons _ t f => fun PA1 HPA1 => + is_pcons A0 PA1 t (is_ptree_inhab_rec A0 t PA1 HPA1) f + (is_pforest_inhab_rec A0 f PA1 HPA1) + end + for is_pforest_inhab_rec) A x PA HPA. + Definition is_ptree_trivial : forall (A : Type) (PA : A -> Type), + param1.trivial A PA -> + forall x : ptree A, + {u : is_ptree A PA x & forall v : is_ptree A PA x, u = v} := + fun (A : Type) (PA : A -> Type) (HPA : param1.trivial A PA) (x : ptree A) => + param1.contracts (ptree A) (is_ptree A PA) x (is_ptree_inhab A PA HPA x) + ((fix is_ptree_trivial_rec (A0 : Type) (PA0 : A0 -> Type) + (HPA0 : param1.trivial A0 PA0) (x0 : ptree A0) + (y : is_ptree A0 PA0 x0) {struct y} : + is_ptree_inhab A0 PA0 HPA0 x0 = y := + match y in is_ptree A1 PA1 x1 return + forall HPA1 : param1.trivial A1 PA1, + is_ptree_inhab A1 PA1 HPA1 x1 = y with + | is_pnode A1 PA1 x1 Px f Pf => + fun HPA1 => + match param1.trivial_uniq A1 PA1 HPA1 x1 Px in _ = Px' return + is_pnode A1 PA1 x1 (param1.trivial_full A1 PA1 HPA1 x1) f + (is_pforest_inhab A1 PA1 HPA1 f) = + is_pnode A1 PA1 x1 Px' f Pf with + | eq_refl => + match is_pforest_trivial_rec A1 PA1 HPA1 f Pf in _ = Pf' return + is_pnode A1 PA1 x1 (param1.trivial_full A1 PA1 HPA1 x1) f + (is_pforest_inhab A1 PA1 HPA1 f) = + is_pnode A1 PA1 x1 (param1.trivial_full A1 PA1 HPA1 x1) f Pf' with + | eq_refl => eq_refl + end + end + end HPA0 + with is_pforest_trivial_rec (A0 : Type) (PA0 : A0 -> Type) + (HPA0 : param1.trivial A0 PA0) (x0 : pforest A0) + (y : is_pforest A0 PA0 x0) {struct y} : + is_pforest_inhab A0 PA0 HPA0 x0 = y := + match y in is_pforest A1 PA1 x1 return + forall HPA1 : param1.trivial A1 PA1, + is_pforest_inhab A1 PA1 HPA1 x1 = y with + | is_pempty A1 PA1 => fun _ => eq_refl + | is_pcons A1 PA1 t Pt f Pf => + fun HPA1 => + match is_ptree_trivial_rec A1 PA1 HPA1 t Pt in _ = Pt' return + is_pcons A1 PA1 t (is_ptree_inhab A1 PA1 HPA1 t) f + (is_pforest_inhab A1 PA1 HPA1 f) = + is_pcons A1 PA1 t Pt' f Pf with + | eq_refl => + match is_pforest_trivial_rec A1 PA1 HPA1 f Pf in _ = Pf' return + is_pcons A1 PA1 t (is_ptree_inhab A1 PA1 HPA1 t) f + (is_pforest_inhab A1 PA1 HPA1 f) = + is_pcons A1 PA1 t (is_ptree_inhab A1 PA1 HPA1 t) f Pf' with + | eq_refl => eq_refl + end + end + end HPA0 + for is_ptree_trivial_rec) A PA HPA x). + Definition is_pforest_trivial : forall (A : Type) (PA : A -> Type), + param1.trivial A PA -> + forall x : pforest A, + {u : is_pforest A PA x & forall v : is_pforest A PA x, u = v} := + fun (A : Type) (PA : A -> Type) (HPA : param1.trivial A PA) (x : pforest A) => + param1.contracts (pforest A) (is_pforest A PA) x (is_pforest_inhab A PA HPA x) + ((fix is_ptree_trivial_rec (A0 : Type) (PA0 : A0 -> Type) + (HPA0 : param1.trivial A0 PA0) (x0 : ptree A0) + (y : is_ptree A0 PA0 x0) {struct y} : + is_ptree_inhab A0 PA0 HPA0 x0 = y := + match y in is_ptree A1 PA1 x1 return + forall HPA1 : param1.trivial A1 PA1, + is_ptree_inhab A1 PA1 HPA1 x1 = y with + | is_pnode A1 PA1 x1 Px f Pf => + fun HPA1 => + match param1.trivial_uniq A1 PA1 HPA1 x1 Px in _ = Px' return + is_pnode A1 PA1 x1 (param1.trivial_full A1 PA1 HPA1 x1) f + (is_pforest_inhab A1 PA1 HPA1 f) = + is_pnode A1 PA1 x1 Px' f Pf with + | eq_refl => + match is_pforest_trivial_rec A1 PA1 HPA1 f Pf in _ = Pf' return + is_pnode A1 PA1 x1 (param1.trivial_full A1 PA1 HPA1 x1) f + (is_pforest_inhab A1 PA1 HPA1 f) = + is_pnode A1 PA1 x1 (param1.trivial_full A1 PA1 HPA1 x1) f Pf' with + | eq_refl => eq_refl + end + end + end HPA0 + with is_pforest_trivial_rec (A0 : Type) (PA0 : A0 -> Type) + (HPA0 : param1.trivial A0 PA0) (x0 : pforest A0) + (y : is_pforest A0 PA0 x0) {struct y} : + is_pforest_inhab A0 PA0 HPA0 x0 = y := + match y in is_pforest A1 PA1 x1 return + forall HPA1 : param1.trivial A1 PA1, + is_pforest_inhab A1 PA1 HPA1 x1 = y with + | is_pempty A1 PA1 => fun _ => eq_refl + | is_pcons A1 PA1 t Pt f Pf => + fun HPA1 => + match is_ptree_trivial_rec A1 PA1 HPA1 t Pt in _ = Pt' return + is_pcons A1 PA1 t (is_ptree_inhab A1 PA1 HPA1 t) f + (is_pforest_inhab A1 PA1 HPA1 f) = + is_pcons A1 PA1 t Pt' f Pf with + | eq_refl => + match is_pforest_trivial_rec A1 PA1 HPA1 f Pf in _ = Pf' return + is_pcons A1 PA1 t (is_ptree_inhab A1 PA1 HPA1 t) f + (is_pforest_inhab A1 PA1 HPA1 f) = + is_pcons A1 PA1 t (is_ptree_inhab A1 PA1 HPA1 t) f Pf' with + | eq_refl => eq_refl + end + end + end HPA0 + for is_pforest_trivial_rec) A PA HPA x). +End ParametrizedMutualParam1TrivialExpected. + +Module Type ParametrizedMutualInductionExpected. + Include ParametrizedMutualParam1FunctorExpected. + Definition ptree_induction : forall (A : Type) (PA : A -> Type) + (P : ptree A -> Type) (P0 : pforest A -> Type), + (forall (x : A), PA x -> forall f : pforest A, + is_pforest A PA f -> P0 f -> P (pnode A x f)) -> + P0 (pempty A) -> + (forall t : ptree A, is_ptree A PA t -> P t -> forall f : pforest A, + is_pforest A PA f -> P0 f -> P0 (pcons A t f)) -> + forall s1 : ptree A, is_ptree A PA s1 -> P s1 := + fun (A : Type) (PA : A -> Type) (P : ptree A -> Type) (P0 : pforest A -> Type) + His_pnode His_pempty His_pcons s H => + (fix is_ptree_induction_rec (A0 : Type) (PA0 : A0 -> Type) + (P1 : ptree A0 -> Type) (P2 : pforest A0 -> Type) + (Hnode : forall (x : A0), PA0 x -> forall f : pforest A0, + is_pforest A0 PA0 f -> P2 f -> P1 (pnode A0 x f)) + (Hempty : P2 (pempty A0)) + (Hcons : forall t : ptree A0, is_ptree A0 PA0 t -> P1 t -> forall f : pforest A0, + is_pforest A0 PA0 f -> P2 f -> P2 (pcons A0 t f)) + (s1 : ptree A0) (H1 : is_ptree A0 PA0 s1) {struct H1} : P1 s1 := + match H1 in is_ptree A1 PA1 s2 return + forall (P1' : ptree A1 -> Type) (P2' : pforest A1 -> Type), + (forall (x : A1), PA1 x -> forall f : pforest A1, + is_pforest A1 PA1 f -> P2' f -> P1' (pnode A1 x f)) -> + P2' (pempty A1) -> + (forall t : ptree A1, is_ptree A1 PA1 t -> P1' t -> forall f : pforest A1, + is_pforest A1 PA1 f -> P2' f -> P2' (pcons A1 t f)) -> + P1' s2 with + | is_pnode A1 PA1 x Px f Pf => + fun P1' P2' Hnode' Hempty' Hcons' => + Hnode' x Px f Pf + (is_pforest_induction_rec A1 PA1 P1' P2' Hnode' Hempty' Hcons' f Pf) + end P1 P2 Hnode Hempty Hcons + with is_pforest_induction_rec (A0 : Type) (PA0 : A0 -> Type) + (P1 : ptree A0 -> Type) (P2 : pforest A0 -> Type) + (Hnode : forall (x : A0), PA0 x -> forall f : pforest A0, + is_pforest A0 PA0 f -> P2 f -> P1 (pnode A0 x f)) + (Hempty : P2 (pempty A0)) + (Hcons : forall t : ptree A0, is_ptree A0 PA0 t -> P1 t -> forall f : pforest A0, + is_pforest A0 PA0 f -> P2 f -> P2 (pcons A0 t f)) + (s1 : pforest A0) (H1 : is_pforest A0 PA0 s1) {struct H1} : P2 s1 := + match H1 in is_pforest A1 PA1 s2 return + forall (P1' : ptree A1 -> Type) (P2' : pforest A1 -> Type), + (forall (x : A1), PA1 x -> forall f : pforest A1, + is_pforest A1 PA1 f -> P2' f -> P1' (pnode A1 x f)) -> + P2' (pempty A1) -> + (forall t : ptree A1, is_ptree A1 PA1 t -> P1' t -> forall f : pforest A1, + is_pforest A1 PA1 f -> P2' f -> P2' (pcons A1 t f)) -> + P2' s2 with + | is_pempty A1 PA1 => fun _ P2' _ Hempty' _ => Hempty' + | is_pcons A1 PA1 t Pt f Pf => + fun P1' P2' Hnode' Hempty' Hcons' => + Hcons' t Pt (is_ptree_induction_rec A1 PA1 P1' P2' Hnode' Hempty' Hcons' t Pt) + f Pf (is_pforest_induction_rec A1 PA1 P1' P2' Hnode' Hempty' Hcons' f Pf) + end P1 P2 Hnode Hempty Hcons + for is_ptree_induction_rec) A PA P P0 His_pnode His_pempty His_pcons s H. + Definition pforest_induction : forall (A : Type) (PA : A -> Type) + (P : ptree A -> Type) (P0 : pforest A -> Type), + (forall (x : A), PA x -> forall f : pforest A, + is_pforest A PA f -> P0 f -> P (pnode A x f)) -> + P0 (pempty A) -> + (forall t : ptree A, is_ptree A PA t -> P t -> forall f : pforest A, + is_pforest A PA f -> P0 f -> P0 (pcons A t f)) -> + forall s1 : pforest A, is_pforest A PA s1 -> P0 s1 := + fun (A : Type) (PA : A -> Type) (P : ptree A -> Type) (P0 : pforest A -> Type) + His_pnode His_pempty His_pcons s H => + (fix is_ptree_induction_rec (A0 : Type) (PA0 : A0 -> Type) + (P1 : ptree A0 -> Type) (P2 : pforest A0 -> Type) + (Hnode : forall (x : A0), PA0 x -> forall f : pforest A0, + is_pforest A0 PA0 f -> P2 f -> P1 (pnode A0 x f)) + (Hempty : P2 (pempty A0)) + (Hcons : forall t : ptree A0, is_ptree A0 PA0 t -> P1 t -> forall f : pforest A0, + is_pforest A0 PA0 f -> P2 f -> P2 (pcons A0 t f)) + (s1 : ptree A0) (H1 : is_ptree A0 PA0 s1) {struct H1} : P1 s1 := + match H1 in is_ptree A1 PA1 s2 return + forall (P1' : ptree A1 -> Type) (P2' : pforest A1 -> Type), + (forall (x : A1), PA1 x -> forall f : pforest A1, + is_pforest A1 PA1 f -> P2' f -> P1' (pnode A1 x f)) -> + P2' (pempty A1) -> + (forall t : ptree A1, is_ptree A1 PA1 t -> P1' t -> forall f : pforest A1, + is_pforest A1 PA1 f -> P2' f -> P2' (pcons A1 t f)) -> + P1' s2 with + | is_pnode A1 PA1 x Px f Pf => + fun P1' P2' Hnode' Hempty' Hcons' => + Hnode' x Px f Pf + (is_pforest_induction_rec A1 PA1 P1' P2' Hnode' Hempty' Hcons' f Pf) + end P1 P2 Hnode Hempty Hcons + with is_pforest_induction_rec (A0 : Type) (PA0 : A0 -> Type) + (P1 : ptree A0 -> Type) (P2 : pforest A0 -> Type) + (Hnode : forall (x : A0), PA0 x -> forall f : pforest A0, + is_pforest A0 PA0 f -> P2 f -> P1 (pnode A0 x f)) + (Hempty : P2 (pempty A0)) + (Hcons : forall t : ptree A0, is_ptree A0 PA0 t -> P1 t -> forall f : pforest A0, + is_pforest A0 PA0 f -> P2 f -> P2 (pcons A0 t f)) + (s1 : pforest A0) (H1 : is_pforest A0 PA0 s1) {struct H1} : P2 s1 := + match H1 in is_pforest A1 PA1 s2 return + forall (P1' : ptree A1 -> Type) (P2' : pforest A1 -> Type), + (forall (x : A1), PA1 x -> forall f : pforest A1, + is_pforest A1 PA1 f -> P2' f -> P1' (pnode A1 x f)) -> + P2' (pempty A1) -> + (forall t : ptree A1, is_ptree A1 PA1 t -> P1' t -> forall f : pforest A1, + is_pforest A1 PA1 f -> P2' f -> P2' (pcons A1 t f)) -> + P2' s2 with + | is_pempty A1 PA1 => fun _ P2' _ Hempty' _ => Hempty' + | is_pcons A1 PA1 t Pt f Pf => + fun P1' P2' Hnode' Hempty' Hcons' => + Hcons' t Pt (is_ptree_induction_rec A1 PA1 P1' P2' Hnode' Hempty' Hcons' t Pt) + f Pf (is_pforest_induction_rec A1 PA1 P1' P2' Hnode' Hempty' Hcons' f Pf) + end P1 P2 Hnode Hempty Hcons + for is_pforest_induction_rec) A PA P P0 His_pnode His_pempty His_pcons s H. +End ParametrizedMutualInductionExpected. + +Module Type ParametrizedMutualParam2Expected. + Include ParametrizedMutualBase. + Universe ptree_R_arg_u ptree_R_u0 ptree_R_u1. + Inductive ptree_R : forall A1 A2 : Type@{ptree_R_arg_u}, (A1 -> A2 -> Type@{ptree_R_arg_u}) -> ptree A1 -> ptree A2 -> Type@{ptree_R_u0} := + | pnode_R : forall A1 A2 (A_R : A1 -> A2 -> Type@{ptree_R_arg_u}) (x1 : A1) (x2 : A2), + A_R x1 x2 -> forall (f1 : pforest A1) (f2 : pforest A2), + pforest_R A1 A2 A_R f1 f2 -> + ptree_R A1 A2 A_R (@pnode A1 x1 f1) (@pnode A2 x2 f2) + with pforest_R : forall A1 A2 : Type@{ptree_R_arg_u}, (A1 -> A2 -> Type@{ptree_R_arg_u}) -> pforest A1 -> pforest A2 -> Type@{ptree_R_u1} := + | pempty_R : forall A1 A2 (A_R : A1 -> A2 -> Type@{ptree_R_arg_u}), + pforest_R A1 A2 A_R (@pempty A1) (@pempty A2) + | pcons_R : forall A1 A2 (A_R : A1 -> A2 -> Type@{ptree_R_arg_u}) (t1 : ptree A1) (t2 : ptree A2), + ptree_R A1 A2 A_R t1 t2 -> forall (f1 : pforest A1) (f2 : pforest A2), + pforest_R A1 A2 A_R f1 f2 -> + pforest_R A1 A2 A_R (@pcons A1 t1 f1) (@pcons A2 t2 f2). + Definition param_ptree_R : param2.param_db ptree + ptree ptree_R := + @param2.store_param _ _ _ ptree ptree ptree_R. + Definition param_pforest_R : param2.param_db pforest + pforest pforest_R := + @param2.store_param _ _ _ pforest pforest pforest_R. + Definition param_pnode_R : param2.param_db pnode + pnode pnode_R := + @param2.store_param _ _ _ pnode pnode pnode_R. + Definition param_pempty_R : param2.param_db pempty + pempty pempty_R := + @param2.store_param _ _ _ pempty pempty pempty_R. + Definition param_pcons_R : param2.param_db pcons + pcons pcons_R := + @param2.store_param _ _ _ pcons pcons pcons_R. +End ParametrizedMutualParam2Expected. + +Module Type ParametrizedMutualTagExpected. + Include ParametrizedMutualBase. + Definition ptree_tag : forall A : Type, ptree A -> BinNums.positive := + fun (A : Type) (i : ptree A) => + match i with + | pnode _ _ _ => BinNums.xH + end. + Definition pforest_tag : forall A : Type, pforest A -> BinNums.positive := + fun (A : Type) (i : pforest A) => + match i with + | pempty _ => BinNums.xH + | pcons _ _ _ => BinNums.xO BinNums.xH + end. +End ParametrizedMutualTagExpected. + +Module Type ParametrizedMutualFieldsExpected. + Include ParametrizedMutualTagExpected. + Universe box_ptree_pnode_u box_pforest_pempty_u box_pforest_pcons_u. + Constraint Set < box_ptree_pnode_u. + Constraint Set < box_pforest_pempty_u. + Constraint Set < box_pforest_pcons_u. + Record box_ptree_pnode (A : Type) : Type@{box_ptree_pnode_u} := Box_ptree_pnode { + Box_ptree_pnode_0 : A; + Box_ptree_pnode_1 : pforest A; + }. + Record box_pforest_pempty (A : Type) : Type@{box_pforest_pempty_u} := Box_pforest_pempty {}. + Record box_pforest_pcons (A : Type) : Type@{box_pforest_pcons_u} := Box_pforest_pcons { + Box_pforest_pcons_0 : ptree A; + Box_pforest_pcons_1 : pforest A; + }. + Definition ptree_fields_t : Type -> BinNums.positive -> Type := + fun (p : Type) (_ : BinNums.positive) => + box_ptree_pnode p. + Definition ptree_fields : forall (p : Type) (i : ptree p), + ptree_fields_t p + (ptree_tag p i) := + fun (p : Type) (i : ptree p) => + match + i as i0 + return + ptree_fields_t p + (ptree_tag p i0) + with + | pnode _ x f => + {| + Box_ptree_pnode_0 := x; + Box_ptree_pnode_1 := f + |} + end. + Definition ptree_construct : forall p : Type, + BinNums.positive -> + box_ptree_pnode p -> + option (ptree p) := + fun (p : Type) (_ : BinNums.positive) + (b : box_ptree_pnode p) => + match b with + | {| + Box_ptree_pnode_0 := Box_ptree_pnode_0; + Box_ptree_pnode_1 := Box_ptree_pnode_1 + |} => + Some + (pnode p Box_ptree_pnode_0 Box_ptree_pnode_1) + end. + Parameter ptree_constructP : forall (A : Type) (i : ptree A), + ptree_construct A + (ptree_tag A i) + (ptree_fields A i) = + Some i. + Definition pforest_fields_t : Type -> BinNums.positive -> Type := + fun (p : Type) (p0 : BinNums.positive) => + match p0 with + | BinNums.xI _ => unit + | BinNums.xO _ => box_pforest_pcons p + | BinNums.xH => box_pforest_pempty p + end. + Definition pforest_fields : forall (p : Type) (i : pforest p), + pforest_fields_t p + (pforest_tag p i) := + fun (p : Type) (i : pforest p) => + match + i as i0 + return + pforest_fields_t p + (pforest_tag p i0) + with + | pempty _ => Box_pforest_pempty p + | pcons _ t f => + {| + Box_pforest_pcons_0 := t; + Box_pforest_pcons_1 := f + |} + end. + Definition pforest_construct : forall (p : Type) (p0 : BinNums.positive), + pforest_fields_t p p0 -> + option (pforest p) := + fun (p : Type) (p0 : BinNums.positive) => + match + p0 as i + return + pforest_fields_t p i -> + option (pforest p) + with + | BinNums.xI _ => fun _ : unit => None + | BinNums.xO _ => + fun b : box_pforest_pcons p => + match b with + | {| + Box_pforest_pcons_0 := Box_pforest_pcons_0; + Box_pforest_pcons_1 := Box_pforest_pcons_1 + |} => + Some + (pcons p Box_pforest_pcons_0 + Box_pforest_pcons_1) + end + | BinNums.xH => + fun _ : box_pforest_pempty p => + Some (pempty p) + end. + Parameter pforest_constructP : forall (A : Type) (i : pforest A), + pforest_construct A + (pforest_tag A i) + (pforest_fields A i) = + Some i. +End ParametrizedMutualFieldsExpected. + +Module Type ParametrizedMutualEqbExpected. + Include ParametrizedMutualFieldsExpected. + Definition ptree_eqb : forall a : Type, + (a -> a -> bool) -> + ptree a -> ptree a -> bool := + fun (a : Type) (eqA : a -> a -> bool) => + fix ptree (x1 x2 : ptree a) {struct x1} : bool := + match x1 with + | pnode _ x f => + eqb_core_defs.eqb_body (tagB:=ptree_tag a) + (fields_tA:=fun _ : BinNums.positive => + box_ptree_pnode a) + (fields_tB:=ptree_fields_t a) + (ptree_fields a) + (fun (_ : BinNums.positive) + (a0 b : box_ptree_pnode a) => + match a0 with + | {| + Box_ptree_pnode_0 := Box_ptree_pnode_0; + Box_ptree_pnode_1 := Box_ptree_pnode_1 + |} => + match b with + | {| + Box_ptree_pnode_0 := Box_ptree_pnode_2; + Box_ptree_pnode_1 := Box_ptree_pnode_3 + |} => + (eqA Box_ptree_pnode_0 Box_ptree_pnode_2 && + (pforest Box_ptree_pnode_1 Box_ptree_pnode_3 && true))%bool + end + end) + (t1:=ptree_tag a + (pnode a x f)) + {| + Box_ptree_pnode_0 := x; + Box_ptree_pnode_1 := f + |} x2 + end + with pforest (x1 x2 : pforest a) {struct x1} : bool := + match x1 with + | pempty _ => + eqb_core_defs.eqb_body (tagB:=pforest_tag a) + (fields_tA:=pforest_fields_t a) + (fields_tB:=pforest_fields_t a) + (pforest_fields a) + (fun x : BinNums.positive => + match + x as i + return + pforest_fields_t a i -> + pforest_fields_t a i -> bool + with + | BinNums.xI _ => fun _ _ : unit => true + | BinNums.xO _ => + fun a0 b : box_pforest_pcons a => + match a0 with + | {| + Box_pforest_pcons_0 := + Box_pforest_pcons_0; + Box_pforest_pcons_1 := + Box_pforest_pcons_1 + |} => + match b with + | {| + Box_pforest_pcons_0 := + Box_pforest_pcons_2; + Box_pforest_pcons_1 := + Box_pforest_pcons_3 + |} => + (ptree Box_pforest_pcons_0 Box_pforest_pcons_2 && + (pforest Box_pforest_pcons_1 Box_pforest_pcons_3 && + true))%bool + end + end + | BinNums.xH => + fun _ _ : box_pforest_pempty a => true + end) + (t1:=pforest_tag a + (pempty a)) + (Box_pforest_pempty a) x2 + | pcons _ t f => + eqb_core_defs.eqb_body (tagB:=pforest_tag a) + (fields_tA:=pforest_fields_t a) + (fields_tB:=pforest_fields_t a) + (pforest_fields a) + (fun x : BinNums.positive => + match + x as i + return + pforest_fields_t a i -> + pforest_fields_t a i -> bool + with + | BinNums.xI _ => fun _ _ : unit => true + | BinNums.xO _ => + fun a0 b : box_pforest_pcons a => + match a0 with + | {| + Box_pforest_pcons_0 := + Box_pforest_pcons_0; + Box_pforest_pcons_1 := + Box_pforest_pcons_1 + |} => + match b with + | {| + Box_pforest_pcons_0 := + Box_pforest_pcons_2; + Box_pforest_pcons_1 := + Box_pforest_pcons_3 + |} => + (ptree Box_pforest_pcons_0 Box_pforest_pcons_2 && + (pforest Box_pforest_pcons_1 Box_pforest_pcons_3 && + true))%bool + end + end + | BinNums.xH => + fun _ _ : box_pforest_pempty a => true + end) + (t1:=pforest_tag a + (pcons a t f)) + {| + Box_pforest_pcons_0 := t; + Box_pforest_pcons_1 := f + |} x2 + end + for + ptree. + Definition pforest_eqb : forall a : Type, + (a -> a -> bool) -> + pforest a -> + pforest a -> bool := + fun (a : Type) (eqA : a -> a -> bool) => + fix ptree (x1 x2 : ptree a) {struct x1} : bool := + match x1 with + | pnode _ x f => + eqb_core_defs.eqb_body (tagB:=ptree_tag a) + (fields_tA:=fun _ : BinNums.positive => + box_ptree_pnode a) + (fields_tB:=ptree_fields_t a) + (ptree_fields a) + (fun (_ : BinNums.positive) + (a0 b : box_ptree_pnode a) => + match a0 with + | {| + Box_ptree_pnode_0 := Box_ptree_pnode_0; + Box_ptree_pnode_1 := Box_ptree_pnode_1 + |} => + match b with + | {| + Box_ptree_pnode_0 := Box_ptree_pnode_2; + Box_ptree_pnode_1 := Box_ptree_pnode_3 + |} => + (eqA Box_ptree_pnode_0 Box_ptree_pnode_2 && + (pforest Box_ptree_pnode_1 Box_ptree_pnode_3 && true))%bool + end + end) + (t1:=ptree_tag a + (pnode a x f)) + {| + Box_ptree_pnode_0 := x; + Box_ptree_pnode_1 := f + |} x2 + end + with pforest (x1 x2 : pforest a) {struct x1} : bool := + match x1 with + | pempty _ => + eqb_core_defs.eqb_body (tagB:=pforest_tag a) + (fields_tA:=pforest_fields_t a) + (fields_tB:=pforest_fields_t a) + (pforest_fields a) + (fun x : BinNums.positive => + match + x as i + return + pforest_fields_t a i -> + pforest_fields_t a i -> bool + with + | BinNums.xI _ => fun _ _ : unit => true + | BinNums.xO _ => + fun a0 b : box_pforest_pcons a => + match a0 with + | {| + Box_pforest_pcons_0 := + Box_pforest_pcons_0; + Box_pforest_pcons_1 := + Box_pforest_pcons_1 + |} => + match b with + | {| + Box_pforest_pcons_0 := + Box_pforest_pcons_2; + Box_pforest_pcons_1 := + Box_pforest_pcons_3 + |} => + (ptree Box_pforest_pcons_0 Box_pforest_pcons_2 && + (pforest Box_pforest_pcons_1 Box_pforest_pcons_3 && + true))%bool + end + end + | BinNums.xH => + fun _ _ : box_pforest_pempty a => true + end) + (t1:=pforest_tag a + (pempty a)) + (Box_pforest_pempty a) x2 + | pcons _ t f => + eqb_core_defs.eqb_body (tagB:=pforest_tag a) + (fields_tA:=pforest_fields_t a) + (fields_tB:=pforest_fields_t a) + (pforest_fields a) + (fun x : BinNums.positive => + match + x as i + return + pforest_fields_t a i -> + pforest_fields_t a i -> bool + with + | BinNums.xI _ => fun _ _ : unit => true + | BinNums.xO _ => + fun a0 b : box_pforest_pcons a => + match a0 with + | {| + Box_pforest_pcons_0 := + Box_pforest_pcons_0; + Box_pforest_pcons_1 := + Box_pforest_pcons_1 + |} => + match b with + | {| + Box_pforest_pcons_0 := + Box_pforest_pcons_2; + Box_pforest_pcons_1 := + Box_pforest_pcons_3 + |} => + (ptree Box_pforest_pcons_0 Box_pforest_pcons_2 && + (pforest Box_pforest_pcons_1 Box_pforest_pcons_3 && + true))%bool + end + end + | BinNums.xH => + fun _ _ : box_pforest_pempty a => true + end) + (t1:=pforest_tag a + (pcons a t f)) + {| + Box_pforest_pcons_0 := t; + Box_pforest_pcons_1 := f + |} x2 + end + for + pforest. + Definition ptree_eqb_fields : forall p : Type, + (p -> p -> bool) -> + (ptree p -> + ptree p -> bool) -> + BinNums.positive -> + box_ptree_pnode p -> + box_ptree_pnode p -> bool := + fun (p : Type) (eqp : p -> p -> bool) + (_ : ptree p -> ptree p -> bool) + (_ : BinNums.positive) (a b : box_ptree_pnode p) => + match a with + | {| + Box_ptree_pnode_0 := Box_ptree_pnode_0; + Box_ptree_pnode_1 := Box_ptree_pnode_1 + |} => + match b with + | {| + Box_ptree_pnode_0 := Box_ptree_pnode_2; + Box_ptree_pnode_1 := Box_ptree_pnode_3 + |} => + (eqp Box_ptree_pnode_0 Box_ptree_pnode_2 && + (pforest_eqb p eqp Box_ptree_pnode_1 + Box_ptree_pnode_3 && + true))%bool + end + end. + Definition pforest_eqb_fields : forall p : Type, + (p -> p -> bool) -> + (pforest p -> + pforest p -> bool) -> + forall x : BinNums.positive, + pforest_fields_t p x -> + pforest_fields_t p x -> bool := + fun (p : Type) (eqp : p -> p -> bool) + (rec : pforest p -> + pforest p -> bool) + (x : BinNums.positive) => + match + x as i + return + pforest_fields_t p i -> + pforest_fields_t p i -> bool + with + | BinNums.xI _ => fun _ _ : unit => true + | BinNums.xO _ => + fun a b : box_pforest_pcons p => + match a with + | {| + Box_pforest_pcons_0 := Box_pforest_pcons_0; + Box_pforest_pcons_1 := Box_pforest_pcons_1 + |} => + match b with + | {| + Box_pforest_pcons_0 := Box_pforest_pcons_2; + Box_pforest_pcons_1 := Box_pforest_pcons_3 + |} => + (ptree_eqb p eqp Box_pforest_pcons_0 + Box_pforest_pcons_2 && + (rec Box_pforest_pcons_1 Box_pforest_pcons_3 && true))%bool + end + end + | BinNums.xH => fun _ _ : box_pforest_pempty p => true + end. +End ParametrizedMutualEqbExpected. + +Module Type ParametrizedMutualEqbCorrectExpected. + Include ParametrizedMutualEqbExpected. + Parameter ptree_eqb_correct : forall (A : Type) (eqA : A -> A -> bool), + eqb_core_defs.eqb_correct eqA -> + forall x : ptree A, eqb_core_defs.eqb_correct_on (ptree_eqb A eqA) x. + Parameter pforest_eqb_correct : forall (A : Type) (eqA : A -> A -> bool), + eqb_core_defs.eqb_correct eqA -> + forall x : pforest A, eqb_core_defs.eqb_correct_on (pforest_eqb A eqA) x. + Parameter ptree_eqb_refl : forall (A : Type) (eqA : A -> A -> bool), + eqb_core_defs.eqb_reflexive eqA -> + forall x : ptree A, eqb_core_defs.eqb_refl_on (ptree_eqb A eqA) x. + Parameter pforest_eqb_refl : forall (A : Type) (eqA : A -> A -> bool), + eqb_core_defs.eqb_reflexive eqA -> + forall x : pforest A, eqb_core_defs.eqb_refl_on (pforest_eqb A eqA) x. +End ParametrizedMutualEqbCorrectExpected. + +Module Type ParametrizedMutualEqbOKExpected. + Include ParametrizedMutualEqbCorrectExpected. + Parameter ptree_eqb_OK : forall (A : Type) (eqA : A -> A -> bool), + (forall x y : A, reflect (x = y) (eqA x y)) -> + forall x y : ptree A, reflect (x = y) (ptree_eqb A eqA x y). + Parameter pforest_eqb_OK : forall (A : Type) (eqA : A -> A -> bool), + (forall x y : A, reflect (x = y) (eqA x y)) -> + forall x y : pforest A, reflect (x = y) (pforest_eqb A eqA x y). + Parameter ptree_eqb_OK_sumbool : forall A : Type, + (forall x y : A, {x = y} + {x <> y}) -> + forall x y : ptree A, {x = y} + {x <> y}. + Parameter pforest_eqb_OK_sumbool : forall A : Type, + (forall x y : A, {x = y} + {x <> y}) -> + forall x y : pforest A, {x = y} + {x <> y}. +End ParametrizedMutualEqbOKExpected. + +Module Type ParametrizedMutualIsKExpected. + Include ParametrizedMutualBase. + Definition ptree_is_pnode : forall A : Type, ptree A -> bool := + fun (A : Type) (i : ptree A) => + match i with + | pnode _ _ _ => true + end. + Definition pforest_is_pempty : forall A : Type, pforest A -> bool := + fun (A : Type) (i : pforest A) => + match i with + | pempty _ => true + | pcons _ _ _ => false + end. + Definition pforest_is_pcons : forall A : Type, pforest A -> bool := + fun (A : Type) (i : pforest A) => + match i with + | pempty _ => false + | pcons _ _ _ => true + end. +End ParametrizedMutualIsKExpected. + +Module Type ParametrizedMutualProjKExpected. + Include ParametrizedMutualBase. + Definition ptree_projpnode1 : forall A : Type, + A -> + pforest A -> + ptree A -> A := + fun (A : Type) (_ : A) (_ : pforest A) + (i : ptree A) => + match i with + | pnode _ x0 _ => x0 + end. + Definition ptree_projpnode2 : forall A : Type, + A -> + pforest A -> + ptree A -> pforest A := + fun (A : Type) (_ : A) (_ : pforest A) + (i : ptree A) => + match i with + | pnode _ _ f0 => f0 + end. + Definition pforest_projpcons1 : forall A : Type, + ptree A -> + pforest A -> + pforest A -> ptree A := + fun (A : Type) (t : ptree A) + (_ i : pforest A) => + match i with + | pempty _ => t + | pcons _ t0 _ => t0 + end. + Definition pforest_projpcons2 : forall A : Type, + ptree A -> + pforest A -> + pforest A -> pforest A := + fun (A : Type) (_ : ptree A) + (f i : pforest A) => + match i with + | pempty _ => f + | pcons _ _ f0 => f0 + end. +End ParametrizedMutualProjKExpected. + +Module Type ParametrizedMutualBcongrExpected. + Include ParametrizedMutualProjKExpected. + Parameter ptree_bcongr_pnode : forall (A : Type) (x y : A) (b : bool), + reflect (x = y) b -> + forall (x0 y0 : pforest A) (b0 : bool), + reflect (x0 = y0) b0 -> + reflect + (pnode A x x0 = + pnode A y y0) + (b && b0). + Parameter pforest_bcongr_pempty : forall A : Type, + reflect + (pempty A = + pempty A) + true. + Parameter pforest_bcongr_pcons : forall (A : Type) (x y : ptree A) (b : bool), + reflect (x = y) b -> + forall (x0 y0 : pforest A) (b0 : bool), + reflect (x0 = y0) b0 -> + reflect + (pcons A x x0 = + pcons A y y0) + (b && b0). +End ParametrizedMutualBcongrExpected. + +Module Type TripleMutualBase. + Include test_derive_corelib.Mutual.Triple. +End TripleMutualBase. + +Module Type TripleMutualMapExpected. + Include TripleMutualBase. + Definition alpha_map : alpha -> alpha := + fix alpha_map_rec (x : alpha) : alpha := + match x with + | alpha0 => alpha0 + | alpha1 b => alpha1 (beta_map_rec b) + end + with beta_map_rec (x : beta) : beta := + match x with + | beta0 => beta0 + | beta1 g => beta1 (gamma_map_rec g) + end + with gamma_map_rec (x : gamma) : gamma := + match x with + | gamma0 => gamma0 + | gamma1 a b => gamma1 (alpha_map_rec a) (beta_map_rec b) + end + for + alpha_map_rec. + Definition beta_map : beta -> beta := + fix alpha_map_rec (x : alpha) : alpha := + match x with + | alpha0 => alpha0 + | alpha1 b => alpha1 (beta_map_rec b) + end + with beta_map_rec (x : beta) : beta := + match x with + | beta0 => beta0 + | beta1 g => beta1 (gamma_map_rec g) + end + with gamma_map_rec (x : gamma) : gamma := + match x with + | gamma0 => gamma0 + | gamma1 a b => gamma1 (alpha_map_rec a) (beta_map_rec b) + end + for + beta_map_rec. + Definition gamma_map : gamma -> gamma := + fix alpha_map_rec (x : alpha) : alpha := + match x with + | alpha0 => alpha0 + | alpha1 b => alpha1 (beta_map_rec b) + end + with beta_map_rec (x : beta) : beta := + match x with + | beta0 => beta0 + | beta1 g => beta1 (gamma_map_rec g) + end + with gamma_map_rec (x : gamma) : gamma := + match x with + | gamma0 => gamma0 + | gamma1 a b => gamma1 (alpha_map_rec a) (beta_map_rec b) + end + for + gamma_map_rec. +End TripleMutualMapExpected. + +Module Type TripleMutualEqbExpected. + Include TripleMutualBase. + Universe box_alpha_alpha0_u box_alpha_alpha1_u box_beta_beta0_u box_beta_beta1_u box_gamma_gamma0_u box_gamma_gamma1_u. + Constraint Set < box_alpha_alpha0_u. + Constraint Set < box_alpha_alpha1_u. + Constraint Set < box_beta_beta0_u. + Constraint Set < box_beta_beta1_u. + Constraint Set < box_gamma_gamma0_u. + Constraint Set < box_gamma_gamma1_u. + Record box_alpha_alpha0 : Type@{box_alpha_alpha0_u} := Box_alpha_alpha0 {}. + Record box_alpha_alpha1 : Type@{box_alpha_alpha1_u} := Box_alpha_alpha1 { + Box_alpha_alpha1_0 : beta; + }. + Record box_beta_beta0 : Type@{box_beta_beta0_u} := Box_beta_beta0 {}. + Record box_beta_beta1 : Type@{box_beta_beta1_u} := Box_beta_beta1 { + Box_beta_beta1_0 : gamma; + }. + Record box_gamma_gamma0 : Type@{box_gamma_gamma0_u} := Box_gamma_gamma0 {}. + Record box_gamma_gamma1 : Type@{box_gamma_gamma1_u} := Box_gamma_gamma1 { + Box_gamma_gamma1_0 : alpha; + Box_gamma_gamma1_1 : beta; + }. + Definition alpha_tag : alpha -> BinNums.positive := + fun i : alpha => + match i with + | alpha0 => BinNums.xH + | alpha1 _ => BinNums.xO BinNums.xH + end. + Definition beta_tag : beta -> BinNums.positive := + fun i : beta => + match i with + | beta0 => BinNums.xH + | beta1 _ => BinNums.xO BinNums.xH + end. + Definition gamma_tag : gamma -> BinNums.positive := + fun i : gamma => + match i with + | gamma0 => BinNums.xH + | gamma1 _ _ => BinNums.xO BinNums.xH + end. + Definition alpha_fields_t : BinNums.positive -> Type := + fun p : BinNums.positive => + match p with + | BinNums.xI _ => unit + | BinNums.xO _ => box_alpha_alpha1 + | BinNums.xH => box_alpha_alpha0 + end. + Definition beta_fields_t : BinNums.positive -> Type := + fun p : BinNums.positive => + match p with + | BinNums.xI _ => unit + | BinNums.xO _ => box_beta_beta1 + | BinNums.xH => box_beta_beta0 + end. + Definition gamma_fields_t : BinNums.positive -> Type := + fun p : BinNums.positive => + match p with + | BinNums.xI _ => unit + | BinNums.xO _ => box_gamma_gamma1 + | BinNums.xH => box_gamma_gamma0 + end. + Definition alpha_fields : forall i : alpha, + alpha_fields_t + (alpha_tag i) := + fun i : alpha => + match + i as i0 + return + alpha_fields_t + (alpha_tag i0) + with + | alpha0 => + Box_alpha_alpha0 + | alpha1 b => + {| Box_alpha_alpha1_0 := b |} + end. + Definition beta_fields : forall i : beta, + beta_fields_t + (beta_tag i) := + fun i : beta => + match + i as i0 + return + beta_fields_t + (beta_tag i0) + with + | beta0 => Box_beta_beta0 + | beta1 g => + {| Box_beta_beta1_0 := g |} + end. + Definition gamma_fields : forall i : gamma, + gamma_fields_t + (gamma_tag i) := + fun i : gamma => + match + i as i0 + return + gamma_fields_t + (gamma_tag i0) + with + | gamma0 => + Box_gamma_gamma0 + | gamma1 a b => + {| + Box_gamma_gamma1_0 := a; + Box_gamma_gamma1_1 := b + |} + end. + Definition alpha_construct : forall p : BinNums.positive, + alpha_fields_t p -> + option alpha := + fun p : BinNums.positive => + match + p as i + return + alpha_fields_t i -> + option alpha + with + | BinNums.xI _ => fun _ : unit => None + | BinNums.xO _ => + fun b : box_alpha_alpha1 => + match b with + | {| Box_alpha_alpha1_0 := Box_alpha_alpha1_0 |} => + Some (alpha1 Box_alpha_alpha1_0) + end + | BinNums.xH => + fun _ : box_alpha_alpha0 => + Some alpha0 + end. + Definition beta_construct : forall p : BinNums.positive, + beta_fields_t p -> + option beta := + fun p : BinNums.positive => + match + p as i + return + beta_fields_t i -> + option beta + with + | BinNums.xI _ => fun _ : unit => None + | BinNums.xO _ => + fun b : box_beta_beta1 => + match b with + | {| Box_beta_beta1_0 := Box_beta_beta1_0 |} => + Some (beta1 Box_beta_beta1_0) + end + | BinNums.xH => + fun _ : box_beta_beta0 => + Some beta0 + end. + Definition gamma_construct : forall p : BinNums.positive, + gamma_fields_t p -> + option gamma := + fun p : BinNums.positive => + match + p as i + return + gamma_fields_t i -> + option gamma + with + | BinNums.xI _ => fun _ : unit => None + | BinNums.xO _ => + fun b : box_gamma_gamma1 => + match b with + | {| + Box_gamma_gamma1_0 := Box_gamma_gamma1_0; + Box_gamma_gamma1_1 := Box_gamma_gamma1_1 + |} => + Some + (gamma1 Box_gamma_gamma1_0 + Box_gamma_gamma1_1) + end + | BinNums.xH => + fun _ : box_gamma_gamma0 => + Some gamma0 + end. + Parameter alpha_constructP : forall i : alpha, + alpha_construct + (alpha_tag i) + (alpha_fields i) = + Some i. + Parameter beta_constructP : forall i : beta, + beta_construct + (beta_tag i) + (beta_fields i) = + Some i. + Parameter gamma_constructP : forall i : gamma, + gamma_construct + (gamma_tag i) + (gamma_fields i) = + Some i. + Definition alpha_eqb : alpha -> alpha -> bool := + fix alpha (x1 x2 : alpha) {struct x1} : bool := + match x1 with + | alpha0 => + eqb_core_defs.eqb_body (tagB:=alpha_tag) + (fields_tA:=alpha_fields_t) + (fields_tB:=alpha_fields_t) + alpha_fields + (fun x : BinNums.positive => + match + x as i + return + alpha_fields_t i -> + alpha_fields_t i -> bool + with + | BinNums.xI _ => fun _ _ : unit => true + | BinNums.xO _ => + fun a b : box_alpha_alpha1 => + match a with + | {| + Box_alpha_alpha1_0 := + Box_alpha_alpha1_0 + |} => + match b with + | {| + Box_alpha_alpha1_0 := + Box_alpha_alpha1_1 + |} => + (beta Box_alpha_alpha1_0 Box_alpha_alpha1_1 && true)%bool + end + end + | BinNums.xH => + fun _ _ : box_alpha_alpha0 => true + end) + (t1:=alpha_tag + alpha0) + Box_alpha_alpha0 x2 + | alpha1 b => + eqb_core_defs.eqb_body (tagB:=alpha_tag) + (fields_tA:=alpha_fields_t) + (fields_tB:=alpha_fields_t) + alpha_fields + (fun x : BinNums.positive => + match + x as i + return + alpha_fields_t i -> + alpha_fields_t i -> bool + with + | BinNums.xI _ => fun _ _ : unit => true + | BinNums.xO _ => + fun a b0 : box_alpha_alpha1 => + match a with + | {| + Box_alpha_alpha1_0 := + Box_alpha_alpha1_0 + |} => + match b0 with + | {| + Box_alpha_alpha1_0 := + Box_alpha_alpha1_1 + |} => + (beta Box_alpha_alpha1_0 Box_alpha_alpha1_1 && true)%bool + end + end + | BinNums.xH => + fun _ _ : box_alpha_alpha0 => true + end) + (t1:=alpha_tag + (alpha1 b)) + {| Box_alpha_alpha1_0 := b |} x2 + end + with beta (x1 x2 : beta) {struct x1} : bool := + match x1 with + | beta0 => + eqb_core_defs.eqb_body (tagB:=beta_tag) + (fields_tA:=beta_fields_t) + (fields_tB:=beta_fields_t) + beta_fields + (fun x : BinNums.positive => + match + x as i + return + beta_fields_t i -> + beta_fields_t i -> bool + with + | BinNums.xI _ => fun _ _ : unit => true + | BinNums.xO _ => + fun a b : box_beta_beta1 => + match a with + | {| + Box_beta_beta1_0 := + Box_beta_beta1_0 + |} => + match b with + | {| + Box_beta_beta1_0 := + Box_beta_beta1_1 + |} => + (gamma Box_beta_beta1_0 Box_beta_beta1_1 && true)%bool + end + end + | BinNums.xH => + fun _ _ : box_beta_beta0 => true + end) + (t1:=beta_tag beta0) + Box_beta_beta0 x2 + | beta1 g => + eqb_core_defs.eqb_body (tagB:=beta_tag) + (fields_tA:=beta_fields_t) + (fields_tB:=beta_fields_t) + beta_fields + (fun x : BinNums.positive => + match + x as i + return + beta_fields_t i -> + beta_fields_t i -> bool + with + | BinNums.xI _ => fun _ _ : unit => true + | BinNums.xO _ => + fun a b : box_beta_beta1 => + match a with + | {| + Box_beta_beta1_0 := + Box_beta_beta1_0 + |} => + match b with + | {| + Box_beta_beta1_0 := + Box_beta_beta1_1 + |} => + (gamma Box_beta_beta1_0 Box_beta_beta1_1 && true)%bool + end + end + | BinNums.xH => + fun _ _ : box_beta_beta0 => true + end) + (t1:=beta_tag + (beta1 g)) + {| Box_beta_beta1_0 := g |} x2 + end + with gamma (x1 x2 : gamma) {struct x1} : bool := + match x1 with + | gamma0 => + eqb_core_defs.eqb_body (tagB:=gamma_tag) + (fields_tA:=gamma_fields_t) + (fields_tB:=gamma_fields_t) + gamma_fields + (fun x : BinNums.positive => + match + x as i + return + gamma_fields_t i -> + gamma_fields_t i -> bool + with + | BinNums.xI _ => fun _ _ : unit => true + | BinNums.xO _ => + fun a b : box_gamma_gamma1 => + match a with + | {| + Box_gamma_gamma1_0 := + Box_gamma_gamma1_0; + Box_gamma_gamma1_1 := + Box_gamma_gamma1_1 + |} => + match b with + | {| + Box_gamma_gamma1_0 := + Box_gamma_gamma1_2; + Box_gamma_gamma1_1 := + Box_gamma_gamma1_3 + |} => + (alpha Box_gamma_gamma1_0 Box_gamma_gamma1_2 && + (beta Box_gamma_gamma1_1 Box_gamma_gamma1_3 && true))%bool + end + end + | BinNums.xH => + fun _ _ : box_gamma_gamma0 => true + end) + (t1:=gamma_tag + gamma0) + Box_gamma_gamma0 x2 + | gamma1 a b => + eqb_core_defs.eqb_body (tagB:=gamma_tag) + (fields_tA:=gamma_fields_t) + (fields_tB:=gamma_fields_t) + gamma_fields + (fun x : BinNums.positive => + match + x as i + return + gamma_fields_t i -> + gamma_fields_t i -> bool + with + | BinNums.xI _ => fun _ _ : unit => true + | BinNums.xO _ => + fun a0 b0 : box_gamma_gamma1 => + match a0 with + | {| + Box_gamma_gamma1_0 := + Box_gamma_gamma1_0; + Box_gamma_gamma1_1 := + Box_gamma_gamma1_1 + |} => + match b0 with + | {| + Box_gamma_gamma1_0 := + Box_gamma_gamma1_2; + Box_gamma_gamma1_1 := + Box_gamma_gamma1_3 + |} => + (alpha Box_gamma_gamma1_0 Box_gamma_gamma1_2 && + (beta Box_gamma_gamma1_1 Box_gamma_gamma1_3 && true))%bool + end + end + | BinNums.xH => + fun _ _ : box_gamma_gamma0 => true + end) + (t1:=gamma_tag + (gamma1 a b)) + {| + Box_gamma_gamma1_0 := a; + Box_gamma_gamma1_1 := b + |} x2 + end + for + alpha. + Definition beta_eqb : beta -> beta -> bool := + fix alpha (x1 x2 : alpha) {struct x1} : bool := + match x1 with + | alpha0 => + eqb_core_defs.eqb_body (tagB:=alpha_tag) + (fields_tA:=alpha_fields_t) + (fields_tB:=alpha_fields_t) + alpha_fields + (fun x : BinNums.positive => + match + x as i + return + alpha_fields_t i -> + alpha_fields_t i -> bool + with + | BinNums.xI _ => fun _ _ : unit => true + | BinNums.xO _ => + fun a b : box_alpha_alpha1 => + match a with + | {| + Box_alpha_alpha1_0 := + Box_alpha_alpha1_0 + |} => + match b with + | {| + Box_alpha_alpha1_0 := + Box_alpha_alpha1_1 + |} => + (beta Box_alpha_alpha1_0 Box_alpha_alpha1_1 && true)%bool + end + end + | BinNums.xH => + fun _ _ : box_alpha_alpha0 => true + end) + (t1:=alpha_tag + alpha0) + Box_alpha_alpha0 x2 + | alpha1 b => + eqb_core_defs.eqb_body (tagB:=alpha_tag) + (fields_tA:=alpha_fields_t) + (fields_tB:=alpha_fields_t) + alpha_fields + (fun x : BinNums.positive => + match + x as i + return + alpha_fields_t i -> + alpha_fields_t i -> bool + with + | BinNums.xI _ => fun _ _ : unit => true + | BinNums.xO _ => + fun a b0 : box_alpha_alpha1 => + match a with + | {| + Box_alpha_alpha1_0 := + Box_alpha_alpha1_0 + |} => + match b0 with + | {| + Box_alpha_alpha1_0 := + Box_alpha_alpha1_1 + |} => + (beta Box_alpha_alpha1_0 Box_alpha_alpha1_1 && true)%bool + end + end + | BinNums.xH => + fun _ _ : box_alpha_alpha0 => true + end) + (t1:=alpha_tag + (alpha1 b)) + {| Box_alpha_alpha1_0 := b |} x2 + end + with beta (x1 x2 : beta) {struct x1} : bool := + match x1 with + | beta0 => + eqb_core_defs.eqb_body (tagB:=beta_tag) + (fields_tA:=beta_fields_t) + (fields_tB:=beta_fields_t) + beta_fields + (fun x : BinNums.positive => + match + x as i + return + beta_fields_t i -> + beta_fields_t i -> bool + with + | BinNums.xI _ => fun _ _ : unit => true + | BinNums.xO _ => + fun a b : box_beta_beta1 => + match a with + | {| + Box_beta_beta1_0 := + Box_beta_beta1_0 + |} => + match b with + | {| + Box_beta_beta1_0 := + Box_beta_beta1_1 + |} => + (gamma Box_beta_beta1_0 Box_beta_beta1_1 && true)%bool + end + end + | BinNums.xH => + fun _ _ : box_beta_beta0 => true + end) + (t1:=beta_tag beta0) + Box_beta_beta0 x2 + | beta1 g => + eqb_core_defs.eqb_body (tagB:=beta_tag) + (fields_tA:=beta_fields_t) + (fields_tB:=beta_fields_t) + beta_fields + (fun x : BinNums.positive => + match + x as i + return + beta_fields_t i -> + beta_fields_t i -> bool + with + | BinNums.xI _ => fun _ _ : unit => true + | BinNums.xO _ => + fun a b : box_beta_beta1 => + match a with + | {| + Box_beta_beta1_0 := + Box_beta_beta1_0 + |} => + match b with + | {| + Box_beta_beta1_0 := + Box_beta_beta1_1 + |} => + (gamma Box_beta_beta1_0 Box_beta_beta1_1 && true)%bool + end + end + | BinNums.xH => + fun _ _ : box_beta_beta0 => true + end) + (t1:=beta_tag + (beta1 g)) + {| Box_beta_beta1_0 := g |} x2 + end + with gamma (x1 x2 : gamma) {struct x1} : bool := + match x1 with + | gamma0 => + eqb_core_defs.eqb_body (tagB:=gamma_tag) + (fields_tA:=gamma_fields_t) + (fields_tB:=gamma_fields_t) + gamma_fields + (fun x : BinNums.positive => + match + x as i + return + gamma_fields_t i -> + gamma_fields_t i -> bool + with + | BinNums.xI _ => fun _ _ : unit => true + | BinNums.xO _ => + fun a b : box_gamma_gamma1 => + match a with + | {| + Box_gamma_gamma1_0 := + Box_gamma_gamma1_0; + Box_gamma_gamma1_1 := + Box_gamma_gamma1_1 + |} => + match b with + | {| + Box_gamma_gamma1_0 := + Box_gamma_gamma1_2; + Box_gamma_gamma1_1 := + Box_gamma_gamma1_3 + |} => + (alpha Box_gamma_gamma1_0 Box_gamma_gamma1_2 && + (beta Box_gamma_gamma1_1 Box_gamma_gamma1_3 && true))%bool + end + end + | BinNums.xH => + fun _ _ : box_gamma_gamma0 => true + end) + (t1:=gamma_tag + gamma0) + Box_gamma_gamma0 x2 + | gamma1 a b => + eqb_core_defs.eqb_body (tagB:=gamma_tag) + (fields_tA:=gamma_fields_t) + (fields_tB:=gamma_fields_t) + gamma_fields + (fun x : BinNums.positive => + match + x as i + return + gamma_fields_t i -> + gamma_fields_t i -> bool + with + | BinNums.xI _ => fun _ _ : unit => true + | BinNums.xO _ => + fun a0 b0 : box_gamma_gamma1 => + match a0 with + | {| + Box_gamma_gamma1_0 := + Box_gamma_gamma1_0; + Box_gamma_gamma1_1 := + Box_gamma_gamma1_1 + |} => + match b0 with + | {| + Box_gamma_gamma1_0 := + Box_gamma_gamma1_2; + Box_gamma_gamma1_1 := + Box_gamma_gamma1_3 + |} => + (alpha Box_gamma_gamma1_0 Box_gamma_gamma1_2 && + (beta Box_gamma_gamma1_1 Box_gamma_gamma1_3 && true))%bool + end + end + | BinNums.xH => + fun _ _ : box_gamma_gamma0 => true + end) + (t1:=gamma_tag + (gamma1 a b)) + {| + Box_gamma_gamma1_0 := a; + Box_gamma_gamma1_1 := b + |} x2 + end + for + beta. + Definition gamma_eqb : gamma -> + gamma -> bool := + fix alpha (x1 x2 : alpha) {struct x1} : bool := + match x1 with + | alpha0 => + eqb_core_defs.eqb_body (tagB:=alpha_tag) + (fields_tA:=alpha_fields_t) + (fields_tB:=alpha_fields_t) + alpha_fields + (fun x : BinNums.positive => + match + x as i + return + alpha_fields_t i -> + alpha_fields_t i -> bool + with + | BinNums.xI _ => fun _ _ : unit => true + | BinNums.xO _ => + fun a b : box_alpha_alpha1 => + match a with + | {| + Box_alpha_alpha1_0 := + Box_alpha_alpha1_0 + |} => + match b with + | {| + Box_alpha_alpha1_0 := + Box_alpha_alpha1_1 + |} => + (beta Box_alpha_alpha1_0 Box_alpha_alpha1_1 && true)%bool + end + end + | BinNums.xH => + fun _ _ : box_alpha_alpha0 => true + end) + (t1:=alpha_tag + alpha0) + Box_alpha_alpha0 x2 + | alpha1 b => + eqb_core_defs.eqb_body (tagB:=alpha_tag) + (fields_tA:=alpha_fields_t) + (fields_tB:=alpha_fields_t) + alpha_fields + (fun x : BinNums.positive => + match + x as i + return + alpha_fields_t i -> + alpha_fields_t i -> bool + with + | BinNums.xI _ => fun _ _ : unit => true + | BinNums.xO _ => + fun a b0 : box_alpha_alpha1 => + match a with + | {| + Box_alpha_alpha1_0 := + Box_alpha_alpha1_0 + |} => + match b0 with + | {| + Box_alpha_alpha1_0 := + Box_alpha_alpha1_1 + |} => + (beta Box_alpha_alpha1_0 Box_alpha_alpha1_1 && true)%bool + end + end + | BinNums.xH => + fun _ _ : box_alpha_alpha0 => true + end) + (t1:=alpha_tag + (alpha1 b)) + {| Box_alpha_alpha1_0 := b |} x2 + end + with beta (x1 x2 : beta) {struct x1} : bool := + match x1 with + | beta0 => + eqb_core_defs.eqb_body (tagB:=beta_tag) + (fields_tA:=beta_fields_t) + (fields_tB:=beta_fields_t) + beta_fields + (fun x : BinNums.positive => + match + x as i + return + beta_fields_t i -> + beta_fields_t i -> bool + with + | BinNums.xI _ => fun _ _ : unit => true + | BinNums.xO _ => + fun a b : box_beta_beta1 => + match a with + | {| + Box_beta_beta1_0 := + Box_beta_beta1_0 + |} => + match b with + | {| + Box_beta_beta1_0 := + Box_beta_beta1_1 + |} => + (gamma Box_beta_beta1_0 Box_beta_beta1_1 && true)%bool + end + end + | BinNums.xH => + fun _ _ : box_beta_beta0 => true + end) + (t1:=beta_tag beta0) + Box_beta_beta0 x2 + | beta1 g => + eqb_core_defs.eqb_body (tagB:=beta_tag) + (fields_tA:=beta_fields_t) + (fields_tB:=beta_fields_t) + beta_fields + (fun x : BinNums.positive => + match + x as i + return + beta_fields_t i -> + beta_fields_t i -> bool + with + | BinNums.xI _ => fun _ _ : unit => true + | BinNums.xO _ => + fun a b : box_beta_beta1 => + match a with + | {| + Box_beta_beta1_0 := + Box_beta_beta1_0 + |} => + match b with + | {| + Box_beta_beta1_0 := + Box_beta_beta1_1 + |} => + (gamma Box_beta_beta1_0 Box_beta_beta1_1 && true)%bool + end + end + | BinNums.xH => + fun _ _ : box_beta_beta0 => true + end) + (t1:=beta_tag + (beta1 g)) + {| Box_beta_beta1_0 := g |} x2 + end + with gamma (x1 x2 : gamma) {struct x1} : bool := + match x1 with + | gamma0 => + eqb_core_defs.eqb_body (tagB:=gamma_tag) + (fields_tA:=gamma_fields_t) + (fields_tB:=gamma_fields_t) + gamma_fields + (fun x : BinNums.positive => + match + x as i + return + gamma_fields_t i -> + gamma_fields_t i -> bool + with + | BinNums.xI _ => fun _ _ : unit => true + | BinNums.xO _ => + fun a b : box_gamma_gamma1 => + match a with + | {| + Box_gamma_gamma1_0 := + Box_gamma_gamma1_0; + Box_gamma_gamma1_1 := + Box_gamma_gamma1_1 + |} => + match b with + | {| + Box_gamma_gamma1_0 := + Box_gamma_gamma1_2; + Box_gamma_gamma1_1 := + Box_gamma_gamma1_3 + |} => + (alpha Box_gamma_gamma1_0 Box_gamma_gamma1_2 && + (beta Box_gamma_gamma1_1 Box_gamma_gamma1_3 && true))%bool + end + end + | BinNums.xH => + fun _ _ : box_gamma_gamma0 => true + end) + (t1:=gamma_tag + gamma0) + Box_gamma_gamma0 x2 + | gamma1 a b => + eqb_core_defs.eqb_body (tagB:=gamma_tag) + (fields_tA:=gamma_fields_t) + (fields_tB:=gamma_fields_t) + gamma_fields + (fun x : BinNums.positive => + match + x as i + return + gamma_fields_t i -> + gamma_fields_t i -> bool + with + | BinNums.xI _ => fun _ _ : unit => true + | BinNums.xO _ => + fun a0 b0 : box_gamma_gamma1 => + match a0 with + | {| + Box_gamma_gamma1_0 := + Box_gamma_gamma1_0; + Box_gamma_gamma1_1 := + Box_gamma_gamma1_1 + |} => + match b0 with + | {| + Box_gamma_gamma1_0 := + Box_gamma_gamma1_2; + Box_gamma_gamma1_1 := + Box_gamma_gamma1_3 + |} => + (alpha Box_gamma_gamma1_0 Box_gamma_gamma1_2 && + (beta Box_gamma_gamma1_1 Box_gamma_gamma1_3 && true))%bool + end + end + | BinNums.xH => + fun _ _ : box_gamma_gamma0 => true + end) + (t1:=gamma_tag + (gamma1 a b)) + {| + Box_gamma_gamma1_0 := a; + Box_gamma_gamma1_1 := b + |} x2 + end + for + gamma. + Definition alpha_eqb_fields : (alpha -> + alpha -> bool) -> + forall x : BinNums.positive, + alpha_fields_t x -> + alpha_fields_t x -> bool := + fun + (_ : alpha -> + alpha -> bool) + (x : BinNums.positive) => + match + x as i + return + alpha_fields_t i -> + alpha_fields_t i -> bool + with + | BinNums.xI _ => fun _ _ : unit => true + | BinNums.xO _ => + fun a b : box_alpha_alpha1 => + match a with + | {| Box_alpha_alpha1_0 := Box_alpha_alpha1_0 |} => + match b with + | {| + Box_alpha_alpha1_0 := Box_alpha_alpha1_1 + |} => + (beta_eqb Box_alpha_alpha1_0 + Box_alpha_alpha1_1 && + true)%bool + end + end + | BinNums.xH => fun _ _ : box_alpha_alpha0 => true + end. + Definition beta_eqb_fields : (beta -> + beta -> bool) -> + forall x : BinNums.positive, + beta_fields_t x -> + beta_fields_t x -> bool := + fun + (_ : beta -> beta -> bool) + (x : BinNums.positive) => + match + x as i + return + beta_fields_t i -> + beta_fields_t i -> bool + with + | BinNums.xI _ => fun _ _ : unit => true + | BinNums.xO _ => + fun a b : box_beta_beta1 => + match a with + | {| Box_beta_beta1_0 := Box_beta_beta1_0 |} => + match b with + | {| Box_beta_beta1_0 := Box_beta_beta1_1 |} => + (gamma_eqb Box_beta_beta1_0 + Box_beta_beta1_1 && + true)%bool + end + end + | BinNums.xH => fun _ _ : box_beta_beta0 => true + end. + Definition gamma_eqb_fields : (gamma -> + gamma -> bool) -> + forall x : BinNums.positive, + gamma_fields_t x -> + gamma_fields_t x -> bool := + fun + (_ : gamma -> + gamma -> bool) + (x : BinNums.positive) => + match + x as i + return + gamma_fields_t i -> + gamma_fields_t i -> bool + with + | BinNums.xI _ => fun _ _ : unit => true + | BinNums.xO _ => + fun a b : box_gamma_gamma1 => + match a with + | {| + Box_gamma_gamma1_0 := Box_gamma_gamma1_0; + Box_gamma_gamma1_1 := Box_gamma_gamma1_1 + |} => + match b with + | {| + Box_gamma_gamma1_0 := Box_gamma_gamma1_2; + Box_gamma_gamma1_1 := Box_gamma_gamma1_3 + |} => + (alpha_eqb Box_gamma_gamma1_0 + Box_gamma_gamma1_2 && + (beta_eqb Box_gamma_gamma1_1 + Box_gamma_gamma1_3 && + true))%bool + end + end + | BinNums.xH => fun _ _ : box_gamma_gamma0 => true + end. +End TripleMutualEqbExpected. + +Module Type TripleMutualEqbOKExpected. + Include TripleMutualEqbExpected. + Universe alpha_reali_u beta_reali_u gamma_reali_u. + Constraint Set < alpha_reali_u. + Constraint Set < beta_reali_u. + Constraint Set < gamma_reali_u. + Inductive is_alpha : alpha -> Type@{alpha_reali_u} := + | is_alpha0 : is_alpha alpha0 + | is_alpha1 (b : beta) (Pb : is_beta b) : is_alpha (alpha1 b) + with is_beta : beta -> Type@{beta_reali_u} := + | is_beta0 : is_beta beta0 + | is_beta1 (g : gamma) (Pg : is_gamma g) : is_beta (beta1 g) + with is_gamma : gamma -> Type@{gamma_reali_u} := + | is_gamma0 : is_gamma gamma0 + | is_gamma1 (a : alpha) (Pa : is_alpha a) + (b : beta) (Pb : is_beta b) : is_gamma (gamma1 a b). + Definition is_alpha_inhab : forall x : alpha, is_alpha x := + fix is_alpha_inhab_rec (x : alpha) : is_alpha x := + match x as i return is_alpha i with + | alpha0 => is_alpha0 + | alpha1 b => is_alpha1 b (is_beta_inhab_rec b) + end + with is_beta_inhab_rec (x : beta) : is_beta x := + match x as i return is_beta i with + | beta0 => is_beta0 + | beta1 g => is_beta1 g (is_gamma_inhab_rec g) + end + with is_gamma_inhab_rec (x : gamma) : is_gamma x := + match x as i return is_gamma i with + | gamma0 => is_gamma0 + | gamma1 a b => is_gamma1 a (is_alpha_inhab_rec a) b (is_beta_inhab_rec b) + end + for + is_alpha_inhab_rec. + Definition is_beta_inhab : forall x : beta, is_beta x := + fix is_alpha_inhab_rec (x : alpha) : is_alpha x := + match x as i return is_alpha i with + | alpha0 => is_alpha0 + | alpha1 b => is_alpha1 b (is_beta_inhab_rec b) + end + with is_beta_inhab_rec (x : beta) : is_beta x := + match x as i return is_beta i with + | beta0 => is_beta0 + | beta1 g => is_beta1 g (is_gamma_inhab_rec g) + end + with is_gamma_inhab_rec (x : gamma) : is_gamma x := + match x as i return is_gamma i with + | gamma0 => is_gamma0 + | gamma1 a b => is_gamma1 a (is_alpha_inhab_rec a) b (is_beta_inhab_rec b) + end + for + is_beta_inhab_rec. + Definition is_gamma_inhab : forall x : gamma, is_gamma x := + fix is_alpha_inhab_rec (x : alpha) : is_alpha x := + match x as i return is_alpha i with + | alpha0 => is_alpha0 + | alpha1 b => is_alpha1 b (is_beta_inhab_rec b) + end + with is_beta_inhab_rec (x : beta) : is_beta x := + match x as i return is_beta i with + | beta0 => is_beta0 + | beta1 g => is_beta1 g (is_gamma_inhab_rec g) + end + with is_gamma_inhab_rec (x : gamma) : is_gamma x := + match x as i return is_gamma i with + | gamma0 => is_gamma0 + | gamma1 a b => is_gamma1 a (is_alpha_inhab_rec a) b (is_beta_inhab_rec b) + end + for + is_gamma_inhab_rec. + Definition alpha_induction : forall (P : forall _ : alpha, Type) (P0 : forall _ : beta, Type) + (P1 : forall _ : gamma, Type) (_ : P alpha0) + (_ : forall (b : beta) (_ : is_beta b) (_ : P0 b), P (alpha1 b)) + (_ : P0 beta0) + (_ : forall (g : gamma) (_ : is_gamma g) (_ : P1 g), P0 (beta1 g)) + (_ : P1 gamma0) + (_ : forall (a : alpha) (_ : is_alpha a) + (_ : P a) (b : beta) (_ : is_beta b) + (_ : P0 b), + P1 (gamma1 a b)) + (s1 : alpha) (_ : is_alpha s1), + P s1 := + fun (P : forall _ : alpha, Type) (P0 : forall _ : beta, Type) + (P1 : forall _ : gamma, Type) (His_alpha0 : P alpha0) + (His_alpha1 : forall (b : beta) (_ : is_beta b) (_ : P0 b), P (alpha1 b)) + (His_beta0 : P0 beta0) + (His_beta1 : forall (g : gamma) (_ : is_gamma g) (_ : P1 g), P0 (beta1 g)) + (His_gamma0 : P1 gamma0) + (His_gamma1 : forall (a : alpha) (_ : is_alpha a) + (_ : P a) (b : beta) (_ : is_beta b) + (_ : P0 b), + P1 (gamma1 a b)) => + fix is_alpha_induction_rec (s1 : alpha) (H : is_alpha s1) {struct H} : + P s1 := + match H in is_alpha s2 return P s2 with + | is_alpha0 => His_alpha0 + | is_alpha1 b Pb => His_alpha1 b Pb (is_beta_induction_rec b Pb) + end + with is_beta_induction_rec (s1 : beta) (H : is_beta s1) {struct H} : P0 s1 := + match H in is_beta s2 return P0 s2 with + | is_beta0 => His_beta0 + | is_beta1 g Pg => His_beta1 g Pg (is_gamma_induction_rec g Pg) + end + with is_gamma_induction_rec (s1 : gamma) (H : is_gamma s1) {struct H} : + P1 s1 := + match H in is_gamma s2 return P1 s2 with + | is_gamma0 => His_gamma0 + | is_gamma1 a Pa b Pb => + His_gamma1 a Pa (is_alpha_induction_rec a Pa) b Pb + (is_beta_induction_rec b Pb) + end + for + is_alpha_induction_rec. + Definition beta_induction : forall (P : forall _ : alpha, Type) (P0 : forall _ : beta, Type) + (P1 : forall _ : gamma, Type) (_ : P alpha0) + (_ : forall (b : beta) (_ : is_beta b) (_ : P0 b), P (alpha1 b)) + (_ : P0 beta0) + (_ : forall (g : gamma) (_ : is_gamma g) (_ : P1 g), P0 (beta1 g)) + (_ : P1 gamma0) + (_ : forall (a : alpha) (_ : is_alpha a) + (_ : P a) (b : beta) (_ : is_beta b) + (_ : P0 b), + P1 (gamma1 a b)) + (s1 : beta) (_ : is_beta s1), + P0 s1 := + fun (P : forall _ : alpha, Type) (P0 : forall _ : beta, Type) + (P1 : forall _ : gamma, Type) (His_alpha0 : P alpha0) + (His_alpha1 : forall (b : beta) (_ : is_beta b) (_ : P0 b), P (alpha1 b)) + (His_beta0 : P0 beta0) + (His_beta1 : forall (g : gamma) (_ : is_gamma g) (_ : P1 g), P0 (beta1 g)) + (His_gamma0 : P1 gamma0) + (His_gamma1 : forall (a : alpha) (_ : is_alpha a) + (_ : P a) (b : beta) (_ : is_beta b) + (_ : P0 b), + P1 (gamma1 a b)) => + fix is_alpha_induction_rec (s1 : alpha) (H : is_alpha s1) {struct H} : + P s1 := + match H in is_alpha s2 return P s2 with + | is_alpha0 => His_alpha0 + | is_alpha1 b Pb => His_alpha1 b Pb (is_beta_induction_rec b Pb) + end + with is_beta_induction_rec (s1 : beta) (H : is_beta s1) {struct H} : P0 s1 := + match H in is_beta s2 return P0 s2 with + | is_beta0 => His_beta0 + | is_beta1 g Pg => His_beta1 g Pg (is_gamma_induction_rec g Pg) + end + with is_gamma_induction_rec (s1 : gamma) (H : is_gamma s1) {struct H} : + P1 s1 := + match H in is_gamma s2 return P1 s2 with + | is_gamma0 => His_gamma0 + | is_gamma1 a Pa b Pb => + His_gamma1 a Pa (is_alpha_induction_rec a Pa) b Pb + (is_beta_induction_rec b Pb) + end + for + is_beta_induction_rec. + Definition gamma_induction : forall (P : forall _ : alpha, Type) (P0 : forall _ : beta, Type) + (P1 : forall _ : gamma, Type) (_ : P alpha0) + (_ : forall (b : beta) (_ : is_beta b) (_ : P0 b), P (alpha1 b)) + (_ : P0 beta0) + (_ : forall (g : gamma) (_ : is_gamma g) (_ : P1 g), P0 (beta1 g)) + (_ : P1 gamma0) + (_ : forall (a : alpha) (_ : is_alpha a) + (_ : P a) (b : beta) (_ : is_beta b) + (_ : P0 b), + P1 (gamma1 a b)) + (s1 : gamma) (_ : is_gamma s1), + P1 s1 := + fun (P : forall _ : alpha, Type) (P0 : forall _ : beta, Type) + (P1 : forall _ : gamma, Type) (His_alpha0 : P alpha0) + (His_alpha1 : forall (b : beta) (_ : is_beta b) (_ : P0 b), P (alpha1 b)) + (His_beta0 : P0 beta0) + (His_beta1 : forall (g : gamma) (_ : is_gamma g) (_ : P1 g), P0 (beta1 g)) + (His_gamma0 : P1 gamma0) + (His_gamma1 : forall (a : alpha) (_ : is_alpha a) + (_ : P a) (b : beta) (_ : is_beta b) + (_ : P0 b), + P1 (gamma1 a b)) => + fix is_alpha_induction_rec (s1 : alpha) (H : is_alpha s1) {struct H} : + P s1 := + match H in is_alpha s2 return P s2 with + | is_alpha0 => His_alpha0 + | is_alpha1 b Pb => His_alpha1 b Pb (is_beta_induction_rec b Pb) + end + with is_beta_induction_rec (s1 : beta) (H : is_beta s1) {struct H} : P0 s1 := + match H in is_beta s2 return P0 s2 with + | is_beta0 => His_beta0 + | is_beta1 g Pg => His_beta1 g Pg (is_gamma_induction_rec g Pg) + end + with is_gamma_induction_rec (s1 : gamma) (H : is_gamma s1) {struct H} : + P1 s1 := + match H in is_gamma s2 return P1 s2 with + | is_gamma0 => His_gamma0 + | is_gamma1 a Pa b Pb => + His_gamma1 a Pa (is_alpha_induction_rec a Pa) b Pb + (is_beta_induction_rec b Pb) + end + for + is_gamma_induction_rec. + Parameter alpha_eqb_correct : forall x : alpha, @eqb_correct_on alpha alpha_eqb x. + Parameter beta_eqb_correct : forall x : beta, @eqb_correct_on beta beta_eqb x. + Parameter gamma_eqb_correct : forall x : gamma, @eqb_correct_on gamma gamma_eqb x. + Parameter alpha_eqb_refl : forall x : alpha, @eqb_refl_on alpha alpha_eqb x. + Parameter beta_eqb_refl : forall x : beta, @eqb_refl_on beta beta_eqb x. + Parameter gamma_eqb_refl : forall x : gamma, @eqb_refl_on gamma gamma_eqb x. + Parameter alpha_eqb_OK : forall x1 x2 : alpha, reflect (@eq alpha x1 x2) (alpha_eqb x1 x2). + Parameter beta_eqb_OK : forall x1 x2 : beta, reflect (@eq beta x1 x2) (beta_eqb x1 x2). + Parameter gamma_eqb_OK : forall x1 x2 : gamma, reflect (@eq gamma x1 x2) (gamma_eqb x1 x2). + Parameter alpha_eqb_OK_sumbool : forall x y : alpha, sumbool (@eq alpha x y) (not (@eq alpha x y)). + Parameter beta_eqb_OK_sumbool : forall x y : beta, sumbool (@eq beta x y) (not (@eq beta x y)). + Parameter gamma_eqb_OK_sumbool : forall x y : gamma, sumbool (@eq gamma x y) (not (@eq gamma x y)). +End TripleMutualEqbOKExpected. + +Module Type ParametrizedTripleMutualBase. + Include test_derive_corelib.Mutual.ParametrizedTriple. +End ParametrizedTripleMutualBase. + +Module MutualMap <: MutualMapExpected. + Include test_derive_corelib.Mutual.Tree. + + #[only(map)] derive tree. + + Example tree_map_computes : + tree_map (node (cons (node empty) empty)) = node (cons (node empty) empty). + Proof. vm_compute. reflexivity. Qed. + + Example forest_map_computes : + forest_map (cons (node empty) empty) = cons (node empty) empty. + Proof. vm_compute. reflexivity. Qed. +End MutualMap. + +Module MutualLens <: MutualLensExpected. + Include test_derive_corelib.Mutual.Tree. + + #[only(lens)] derive tree. +End MutualLens. + +Module MutualLensLaws <: MutualLensLawsExpected. + Include test_derive_corelib.Mutual.Tree. + + #[only(lens_laws)] derive tree. +End MutualLensLaws. + +Module MutualParam1 <: MutualParam1Expected. + Include test_derive_corelib.Mutual.Tree. + + #[only(param1)] derive tree. + + Example is_tree_match_computes : + (match is_node empty is_empty with + | is_node f _ => node f + end) = node empty. + Proof. vm_compute. reflexivity. Qed. + + Example is_forest_match_computes : + (match is_cons (node empty) (is_node empty is_empty) empty is_empty with + | is_empty => empty + | is_cons t _ f _ => cons t f + end) = cons (node empty) empty. + Proof. vm_compute. reflexivity. Qed. +End MutualParam1. + +Module MutualParam1Congr <: MutualParam1CongrExpected. + Include test_derive_corelib.Mutual.Tree. + + #[only(param1_congr)] derive tree. + + Example congr_is_node_computes : + congr_is_node empty is_empty is_empty eq_refl = eq_refl. + Proof. vm_compute. reflexivity. Qed. + + Example congr_is_cons_computes : + congr_is_cons (node empty) (is_node empty is_empty) (is_node empty is_empty) + eq_refl empty is_empty is_empty eq_refl = eq_refl. + Proof. vm_compute. reflexivity. Qed. +End MutualParam1Congr. + +Module MutualParam1Trivial <: MutualParam1TrivialExpected. + Include test_derive_corelib.Mutual.Tree. + + #[only(param1_trivial)] derive tree. + + Example is_tree_inhab_computes : + is_tree_inhab (node empty) = is_node empty is_empty. + Proof. vm_compute. reflexivity. Qed. + + Example is_forest_inhab_computes : + is_forest_inhab (cons (node empty) empty) = + is_cons (node empty) (is_node empty is_empty) empty is_empty. + Proof. vm_compute. reflexivity. Qed. + + Example is_tree_trivial_witness_computes : + projT1 (is_tree_trivial (node empty)) = is_node empty is_empty. + Proof. vm_compute. reflexivity. Qed. + + Example is_forest_trivial_witness_computes : + projT1 (is_forest_trivial (cons (node empty) empty)) = + is_cons (node empty) (is_node empty is_empty) empty is_empty. + Proof. vm_compute. reflexivity. Qed. +End MutualParam1Trivial. + +Module MutualParam1Functor <: MutualParam1FunctorExpected. + Include test_derive_corelib.Mutual.Tree. + + #[only(param1_functor)] derive tree. + + Example is_tree_functor_computes : + is_tree_functor (node empty) (is_node empty is_empty) = is_node empty is_empty. + Proof. vm_compute. reflexivity. Qed. + + Example is_forest_functor_computes : + is_forest_functor (cons (node empty) empty) + (is_cons (node empty) (is_node empty is_empty) empty is_empty) = + is_cons (node empty) (is_node empty is_empty) empty is_empty. + Proof. vm_compute. reflexivity. Qed. +End MutualParam1Functor. + +Module MutualParam2 <: MutualParam2Expected. + Include test_derive_corelib.Mutual.Tree. + + #[only(param2)] derive tree. + + Example tree_R_match_computes : + (match node_R empty empty empty_R with + | node_R f1 _ _ => node f1 + end) = node empty. + Proof. vm_compute. reflexivity. Qed. + + Example forest_R_match_computes : + (match cons_R (node empty) (node empty) (node_R empty empty empty_R) + empty empty empty_R with + | empty_R => empty + | cons_R t1 _ _ f1 _ _ => cons t1 f1 + end) = cons (node empty) empty. + Proof. vm_compute. reflexivity. Qed. +End MutualParam2. + +Module MutualInduction <: MutualInductionExpected. + Include test_derive_corelib.Mutual.Tree. + + #[only(induction)] derive tree. + + Example tree_induction_computes : + tree_induction + (fun _ => nat) (fun _ => nat) + (fun _ _ q => S q) + 0 + (fun _ _ pt _ _ qf => S (pt + qf)) + (node empty) (is_node empty is_empty) = 1. + Proof. vm_compute. reflexivity. Qed. + + Example forest_induction_computes : + forest_induction + (fun _ => nat) (fun _ => nat) + (fun _ _ q => S q) + 0 + (fun _ _ pt _ _ qf => S (pt + qf)) + (cons (node empty) empty) + (is_cons (node empty) (is_node empty is_empty) empty is_empty) = 2. + Proof. vm_compute. reflexivity. Qed. +End MutualInduction. + +Module MutualTag <: MutualTagExpected. + Include test_derive_corelib.Mutual.Tree. + + #[only(tag)] derive tree. + + Example tree_tag_computes : tree_tag (node empty) = xH. + Proof. vm_compute. reflexivity. Qed. + + Example forest_tag_empty_computes : forest_tag empty = xH. + Proof. vm_compute. reflexivity. Qed. + + Example forest_tag_cons_computes : forest_tag (cons (node empty) empty) = xO xH. + Proof. vm_compute. reflexivity. Qed. +End MutualTag. + +Module MutualFields <: MutualFieldsExpected. + Include test_derive_corelib.Mutual.Tree. + + #[only(fields)] derive tree. + + Example tree_construct_computes : + tree_construct (tree_tag (node empty)) (tree_fields (node empty)) = Some (node empty). + Proof. vm_compute. reflexivity. Qed. + + Example forest_construct_computes : + forest_construct (forest_tag (cons (node empty) empty)) + (forest_fields (cons (node empty) empty)) = Some (cons (node empty) empty). + Proof. vm_compute. reflexivity. Qed. +End MutualFields. + +Module MutualEqb <: MutualEqbExpected. + Include test_derive_corelib.Mutual.Tree. + + #[only(eqb)] derive tree. + + Example tree_eqb_computes_equal : + tree_eqb (node empty) (node empty) = true. + Proof. vm_compute. reflexivity. Qed. + + Example tree_eqb_computes_different : + tree_eqb (node empty) (node (cons (node empty) empty)) = false. + Proof. vm_compute. reflexivity. Qed. + + Example forest_eqb_computes_equal : + forest_eqb (cons (node empty) empty) (cons (node empty) empty) = true. + Proof. vm_compute. reflexivity. Qed. + + Example forest_eqb_computes_different : + forest_eqb empty (cons (node empty) empty) = false. + Proof. vm_compute. reflexivity. Qed. +End MutualEqb. + +Module NonRecursiveMutualEqb. + Include test_derive_corelib.Mutual.NonRecursive. + + #[only(eqb)] derive color. + + Example color_eqb_computes_equal : color_eqb red red = true. + Proof. vm_compute. reflexivity. Qed. + + Example color_eqb_computes_different : color_eqb red blue = false. + Proof. vm_compute. reflexivity. Qed. + + Example shape_eqb_computes_equal : shape_eqb circle circle = true. + Proof. vm_compute. reflexivity. Qed. + + Example shape_eqb_computes_different : shape_eqb circle square = false. + Proof. vm_compute. reflexivity. Qed. +End NonRecursiveMutualEqb. + +Module NonRecursiveMutualParam1. + Include test_derive_corelib.Mutual.NonRecursive. + + #[only(param1)] derive color. + + Check is_color : color -> Type. + Check is_shape : shape -> Type. + Check is_red : is_color red. + Check is_circle : is_shape circle. +End NonRecursiveMutualParam1. + +Module NonRecursiveMutualParam2. + Include test_derive_corelib.Mutual.NonRecursive. + + #[only(param2)] derive color. + + Check color_R : color -> color -> Set. + Check shape_R : shape -> shape -> Set. + Check red_R : color_R red red. + Check circle_R : shape_R circle circle. +End NonRecursiveMutualParam2. + +Module Type ValueParamMutualBase. + Inductive a (n : nat) : Type := + | ak (b0 : b) + with b (n : nat) : Type := + | bk (a0 : a). +End ValueParamMutualBase. + +Module Type ValueParamMutualEqbExpected. + Include ValueParamMutualBase. + Definition a_tag : forall n : nat, a n -> BinNums.positive := + fun (n : nat) (i : a n) => + match i with + | ak _ _ => BinNums.xH + end. + Definition b_tag : forall n : nat, b n -> BinNums.positive := + fun (n : nat) (i : b n) => + match i with + | bk _ _ => BinNums.xH + end. + Record box_a_ak (n : nat) : Type := Box_a_ak { Box_a_ak_0 : b n }. + Record box_b_bk (n : nat) : Type := Box_b_bk { Box_b_bk_0 : a n }. + Definition a_fields_t : nat -> BinNums.positive -> Type := + fun n _ => box_a_ak n. + Definition b_fields_t : nat -> BinNums.positive -> Type := + fun n _ => box_b_bk n. + Definition a_fields : forall (n : nat) (i : a n), a_fields_t n (a_tag n i) := + fun (n : nat) (i : a n) => + match i as i0 return a_fields_t n (a_tag n i0) with + | ak _ b0 => {| Box_a_ak_0 := b0 |} + end. + Definition b_fields : forall (n : nat) (i : b n), b_fields_t n (b_tag n i) := + fun (n : nat) (i : b n) => + match i as i0 return b_fields_t n (b_tag n i0) with + | bk _ a0 => {| Box_b_bk_0 := a0 |} + end. + Definition a_construct : forall n : nat, BinNums.positive -> a_fields_t n BinNums.xH -> option (a n) := + fun (n : nat) (_ : BinNums.positive) (bx : box_a_ak n) => + match bx with + | {| Box_a_ak_0 := b0 |} => Some (ak n b0) + end. + Definition b_construct : forall n : nat, BinNums.positive -> b_fields_t n BinNums.xH -> option (b n) := + fun (n : nat) (_ : BinNums.positive) (bx : box_b_bk n) => + match bx with + | {| Box_b_bk_0 := a0 |} => Some (bk n a0) + end. + Parameter a_constructP : forall (n : nat) (i : a n), + a_construct n (a_tag n i) (a_fields n i) = Some i. + Parameter b_constructP : forall (n : nat) (i : b n), + b_construct n (b_tag n i) (b_fields n i) = Some i. + Definition a_eqb : forall n m : nat, a n -> a m -> bool := + fix a_eqb_rec (n m : nat) (x : a n) (y : a m) {struct x} : bool := + match x with + | ak _ bx => + match y with + | ak _ by0 => b_eqb_rec n m bx by0 + end + end + with b_eqb_rec (n m : nat) (x : b n) (y : b m) {struct x} : bool := + match x with + | bk _ ax => + match y with + | bk _ ay => a_eqb_rec n m ax ay + end + end + for a_eqb_rec. + Definition b_eqb : forall n m : nat, b n -> b m -> bool := + fix a_eqb_rec (n m : nat) (x : a n) (y : a m) {struct x} : bool := + match x with + | ak _ bx => + match y with + | ak _ by0 => b_eqb_rec n m bx by0 + end + end + with b_eqb_rec (n m : nat) (x : b n) (y : b m) {struct x} : bool := + match x with + | bk _ ax => + match y with + | bk _ ay => a_eqb_rec n m ax ay + end + end + for b_eqb_rec. + Definition a_eqb_fields : forall n m : nat, + (a n -> a m -> bool) -> + BinNums.positive -> box_a_ak n -> box_a_ak m -> bool := + fun (n m : nat) (_ : a n -> a m -> bool) (_ : BinNums.positive) + (x : box_a_ak n) (y : box_a_ak m) => + match x with + | {| Box_a_ak_0 := bx |} => + match y with + | {| Box_a_ak_0 := by0 |} => b_eqb n m bx by0 + end + end. + Definition b_eqb_fields : forall n m : nat, + (b n -> b m -> bool) -> + BinNums.positive -> box_b_bk n -> box_b_bk m -> bool := + fun (n m : nat) (_ : b n -> b m -> bool) (_ : BinNums.positive) + (x : box_b_bk n) (y : box_b_bk m) => + match x with + | {| Box_b_bk_0 := ax |} => + match y with + | {| Box_b_bk_0 := ay |} => a_eqb n m ax ay + end + end. +End ValueParamMutualEqbExpected. + +Module ValueParamMutualEqbUnsupported. + Inductive a (n : nat) : Type := + | ak (b0 : b) + with b (n : nat) : Type := + | bk (a0 : a). + + Fail #[only(eqb)] derive a. +End ValueParamMutualEqbUnsupported. + +Module MutualEqbCorrect <: MutualEqbCorrectExpected. + Include test_derive_corelib.Mutual.Tree. + + #[only(eqbcorrect)] derive tree. + + Ltac transparent_function c := + let t := eval cbv delta [c] in c in + lazymatch t with + | fun _ => _ => idtac + | _ => fail 1 "expected" c "to unfold to a function" + end. + + Example tree_eqb_refl_is_transparent : True. + Proof. transparent_function tree_eqb_refl. exact I. Qed. + + Example forest_eqb_refl_is_transparent : True. + Proof. transparent_function forest_eqb_refl. exact I. Qed. + + Example tree_eqb_correct_is_transparent : True. + Proof. transparent_function tree_eqb_correct. exact I. Qed. + + Example forest_eqb_correct_is_transparent : True. + Proof. transparent_function forest_eqb_correct. exact I. Qed. +End MutualEqbCorrect. + +Module MutualEqbOK <: MutualEqbOKExpected. + Include test_derive_corelib.Mutual.Tree. + + #[only(eqbOK)] derive tree. +End MutualEqbOK. + +Module MutualIsK <: MutualIsKExpected. + Include test_derive_corelib.Mutual.Tree. + + #[only(isK)] derive tree. + + Example tree_is_node_computes : tree_is_node (node empty) = true. + Proof. vm_compute. reflexivity. Qed. + + Example forest_is_empty_computes : forest_is_empty empty = true. + Proof. vm_compute. reflexivity. Qed. + + Example forest_is_cons_computes : forest_is_cons (cons (node empty) empty) = true. + Proof. vm_compute. reflexivity. Qed. + + Example forest_is_empty_rejects_cons : forest_is_empty (cons (node empty) empty) = false. + Proof. vm_compute. reflexivity. Qed. +End MutualIsK. + +Module MutualProjK <: MutualProjKExpected. + Include test_derive_corelib.Mutual.Tree. + + #[only(projK)] derive tree. + + Example tree_projnode1_computes : + tree_projnode1 empty (node (cons (node empty) empty)) = cons (node empty) empty. + Proof. vm_compute. reflexivity. Qed. + + Example forest_projcons1_computes : + forest_projcons1 (node empty) empty (cons (node empty) empty) = node empty. + Proof. vm_compute. reflexivity. Qed. + + Example forest_projcons2_computes : + forest_projcons2 (node empty) empty (cons (node empty) (cons (node empty) empty)) = + cons (node empty) empty. + Proof. vm_compute. reflexivity. Qed. +End MutualProjK. + +Module MutualBcongr <: MutualBcongrExpected. + Include test_derive_corelib.Mutual.Tree. + + #[only(bcongr)] derive tree. + + Example tree_bcongr_node_works : + reflect (node empty = node empty) true. + Proof. exact (tree_bcongr_node empty empty true (ReflectT _ eq_refl)). Qed. + + Example forest_bcongr_cons_works : + reflect (cons (node empty) empty = cons (node empty) empty) true. + Proof. + exact (forest_bcongr_cons (node empty) (node empty) true (ReflectT _ eq_refl) + empty empty true (ReflectT _ eq_refl)). + Qed. +End MutualBcongr. + +Module ParametrizedMutualMap <: ParametrizedMutualMapExpected. + Include test_derive_corelib.Mutual.ParametrizedTree. + + #[only(map)] derive ptree. + + Example ptree_map_computes : + ptree_map nat bool Nat.even (pnode nat 2 (pempty nat)) = + pnode bool true (pempty bool). + Proof. vm_compute. reflexivity. Qed. + + Example pforest_map_computes : + pforest_map nat bool Nat.even + (pcons nat (pnode nat 3 (pempty nat)) (pempty nat)) = + pcons bool (pnode bool false (pempty bool)) (pempty bool). + Proof. vm_compute. reflexivity. Qed. +End ParametrizedMutualMap. + +Module ParametrizedMutualLens <: ParametrizedMutualLensExpected. + Include test_derive_corelib.Mutual.ParametrizedTree. + + #[only(lens)] derive ptree. +End ParametrizedMutualLens. + +Module ParametrizedMutualLensLaws <: ParametrizedMutualLensLawsExpected. + Include test_derive_corelib.Mutual.ParametrizedTree. + + #[only(lens_laws)] derive ptree. +End ParametrizedMutualLensLaws. + +Module ParametrizedMutualParam1 <: ParametrizedMutualParam1Expected. + Include test_derive_corelib.Mutual.ParametrizedTree. + + #[only(param1)] derive ptree. + + Example is_ptree_match_computes : + (match is_pnode nat (fun _ => unit) 2 tt (pempty nat) + (is_pempty nat (fun _ => unit)) + in is_ptree A _ _ return ptree A with + | is_pnode A _ x _ f _ => pnode A x f + end) = pnode nat 2 (pempty nat). + Proof. vm_compute. reflexivity. Qed. + + Example is_pforest_match_computes : + (match is_pcons nat (fun _ => unit) (pnode nat 2 (pempty nat)) + (is_pnode nat (fun _ => unit) 2 tt (pempty nat) + (is_pempty nat (fun _ => unit))) + (pempty nat) (is_pempty nat (fun _ => unit)) + in is_pforest A _ _ return pforest A with + | is_pempty A _ => pempty A + | is_pcons A _ t _ f _ => pcons A t f + end) = pcons nat (pnode nat 2 (pempty nat)) (pempty nat). + Proof. vm_compute. reflexivity. Qed. +End ParametrizedMutualParam1. + +Module ParametrizedMutualParam1Congr <: ParametrizedMutualParam1CongrExpected. + Include test_derive_corelib.Mutual.ParametrizedTree. + + #[only(param1_congr)] derive ptree. + + Example congr_is_pnode_computes : + congr_is_pnode nat (fun _ => unit) 2 tt tt eq_refl + (pempty nat) (is_pempty nat (fun _ => unit)) + (is_pempty nat (fun _ => unit)) eq_refl = eq_refl. + Proof. vm_compute. reflexivity. Qed. + + Example congr_is_pcons_computes : + congr_is_pcons nat (fun _ => unit) (pnode nat 2 (pempty nat)) + (is_pnode nat (fun _ => unit) 2 tt (pempty nat) + (is_pempty nat (fun _ => unit))) + (is_pnode nat (fun _ => unit) 2 tt (pempty nat) + (is_pempty nat (fun _ => unit))) eq_refl + (pempty nat) (is_pempty nat (fun _ => unit)) + (is_pempty nat (fun _ => unit)) eq_refl = eq_refl. + Proof. vm_compute. reflexivity. Qed. +End ParametrizedMutualParam1Congr. + +Module ParametrizedMutualParam1TrivialUnsupported. + Include test_derive_corelib.Mutual.ParametrizedTree. + + Fail #[only(param1_trivial)] derive ptree. +End ParametrizedMutualParam1TrivialUnsupported. + +Module ParametrizedMutualParam1Functor <: ParametrizedMutualParam1FunctorExpected. + Include test_derive_corelib.Mutual.ParametrizedTree. + + #[only(param1_functor)] derive ptree. +End ParametrizedMutualParam1Functor. + +Module ParametrizedMutualParam2 <: ParametrizedMutualParam2Expected. + Include test_derive_corelib.Mutual.ParametrizedTree. + + #[only(param2)] derive ptree. + + Definition nat_eq_relation := fun x y : nat => x = y. + Definition pnode_R_example := + pnode_R nat nat nat_eq_relation 2 2 eq_refl + (pempty nat) (pempty nat) (pempty_R nat nat nat_eq_relation). + + Example ptree_R_match_computes : + (match pnode_R_example in ptree_R A1 _ _ _ _ return ptree A1 with + | pnode_R A1 _ _ x1 _ _ f1 _ _ => pnode A1 x1 f1 + end) = pnode nat 2 (pempty nat). + Proof. vm_compute. reflexivity. Qed. + + Example pforest_R_match_computes : + (match pcons_R nat nat nat_eq_relation + (pnode nat 2 (pempty nat)) (pnode nat 2 (pempty nat)) pnode_R_example + (pempty nat) (pempty nat) (pempty_R nat nat nat_eq_relation) + in pforest_R A1 _ _ _ _ return pforest A1 with + | pempty_R A1 _ _ => pempty A1 + | pcons_R A1 _ _ t1 _ _ f1 _ _ => pcons A1 t1 f1 + end) = pcons nat (pnode nat 2 (pempty nat)) (pempty nat). + Proof. vm_compute. reflexivity. Qed. +End ParametrizedMutualParam2. + +Module ParametrizedMutualInduction <: ParametrizedMutualInductionExpected. + Include test_derive_corelib.Mutual.ParametrizedTree. + + #[only(induction)] derive ptree. +End ParametrizedMutualInduction. + +Module ParametrizedMutualTag <: ParametrizedMutualTagExpected. + Include test_derive_corelib.Mutual.ParametrizedTree. + + #[only(tag)] derive ptree. + + Example ptree_tag_computes : + ptree_tag nat (pnode nat 2 (pempty nat)) = xH. + Proof. vm_compute. reflexivity. Qed. + + Example pforest_tag_empty_computes : pforest_tag nat (pempty nat) = xH. + Proof. vm_compute. reflexivity. Qed. + + Example pforest_tag_cons_computes : + pforest_tag nat (pcons nat (pnode nat 2 (pempty nat)) (pempty nat)) = xO xH. + Proof. vm_compute. reflexivity. Qed. +End ParametrizedMutualTag. + +Module ParametrizedMutualFields <: ParametrizedMutualFieldsExpected. + Include test_derive_corelib.Mutual.ParametrizedTree. + + #[only(fields)] derive ptree. + + Example ptree_construct_computes : + ptree_construct nat (ptree_tag nat (pnode nat 2 (pempty nat))) + (ptree_fields nat (pnode nat 2 (pempty nat))) = Some (pnode nat 2 (pempty nat)). + Proof. vm_compute. reflexivity. Qed. + + Example pforest_construct_computes : + pforest_construct nat + (pforest_tag nat (pcons nat (pnode nat 2 (pempty nat)) (pempty nat))) + (pforest_fields nat (pcons nat (pnode nat 2 (pempty nat)) (pempty nat))) = + Some (pcons nat (pnode nat 2 (pempty nat)) (pempty nat)). + Proof. vm_compute. reflexivity. Qed. +End ParametrizedMutualFields. + +Module ParametrizedMutualEqb <: ParametrizedMutualEqbExpected. + Include test_derive_corelib.Mutual.ParametrizedTree. + + #[only(eqb)] derive ptree. + + Example ptree_eqb_computes_equal : + ptree_eqb nat Nat.eqb (pnode nat 2 (pempty nat)) (pnode nat 2 (pempty nat)) = true. + Proof. vm_compute. reflexivity. Qed. + + Example ptree_eqb_computes_different : + ptree_eqb nat Nat.eqb (pnode nat 2 (pempty nat)) (pnode nat 3 (pempty nat)) = false. + Proof. vm_compute. reflexivity. Qed. + + Example pforest_eqb_computes_equal : + pforest_eqb nat Nat.eqb + (pcons nat (pnode nat 2 (pempty nat)) (pempty nat)) + (pcons nat (pnode nat 2 (pempty nat)) (pempty nat)) = true. + Proof. vm_compute. reflexivity. Qed. + + Example pforest_eqb_computes_different : + pforest_eqb nat Nat.eqb + (pcons nat (pnode nat 2 (pempty nat)) (pempty nat)) + (pcons nat (pnode nat 3 (pempty nat)) (pempty nat)) = false. + Proof. vm_compute. reflexivity. Qed. +End ParametrizedMutualEqb. + +Module ParametrizedMutualEqbCorrect <: ParametrizedMutualEqbCorrectExpected. + Include test_derive_corelib.Mutual.ParametrizedTree. + + #[only(eqbcorrect)] derive ptree. +End ParametrizedMutualEqbCorrect. + +Module ParametrizedMutualEqbOK <: ParametrizedMutualEqbOKExpected. + Include test_derive_corelib.Mutual.ParametrizedTree. + + #[only(eqbOK)] derive ptree. +End ParametrizedMutualEqbOK. + +Module ParametrizedMutualIsK <: ParametrizedMutualIsKExpected. + Include test_derive_corelib.Mutual.ParametrizedTree. + + #[only(isK)] derive ptree. + + Example ptree_is_pnode_computes : + ptree_is_pnode nat (pnode nat 2 (pempty nat)) = true. + Proof. vm_compute. reflexivity. Qed. + + Example pforest_is_pempty_computes : pforest_is_pempty nat (pempty nat) = true. + Proof. vm_compute. reflexivity. Qed. + + Example pforest_is_pcons_computes : + pforest_is_pcons nat (pcons nat (pnode nat 2 (pempty nat)) (pempty nat)) = true. + Proof. vm_compute. reflexivity. Qed. +End ParametrizedMutualIsK. + +Module ParametrizedMutualProjK <: ParametrizedMutualProjKExpected. + Include test_derive_corelib.Mutual.ParametrizedTree. + + #[only(projK)] derive ptree. + + Example ptree_projpnode1_computes : + ptree_projpnode1 nat 0 (pempty nat) (pnode nat 2 (pempty nat)) = 2. + Proof. vm_compute. reflexivity. Qed. + + Example ptree_projpnode2_computes : + ptree_projpnode2 nat 0 (pempty nat) (pnode nat 2 (pcons nat (pnode nat 3 (pempty nat)) (pempty nat))) = + pcons nat (pnode nat 3 (pempty nat)) (pempty nat). + Proof. vm_compute. reflexivity. Qed. + + Example pforest_projpcons1_computes : + pforest_projpcons1 nat (pnode nat 0 (pempty nat)) (pempty nat) + (pcons nat (pnode nat 2 (pempty nat)) (pempty nat)) = pnode nat 2 (pempty nat). + Proof. vm_compute. reflexivity. Qed. + + Example pforest_projpcons2_computes : + pforest_projpcons2 nat (pnode nat 0 (pempty nat)) (pempty nat) + (pcons nat (pnode nat 2 (pempty nat)) (pcons nat (pnode nat 3 (pempty nat)) (pempty nat))) = + pcons nat (pnode nat 3 (pempty nat)) (pempty nat). + Proof. vm_compute. reflexivity. Qed. +End ParametrizedMutualProjK. + +Module ParametrizedMutualBcongr <: ParametrizedMutualBcongrExpected. + Include test_derive_corelib.Mutual.ParametrizedTree. + + #[only(bcongr)] derive ptree. + + Example ptree_bcongr_pnode_works : + reflect (pnode nat 2 (pempty nat) = pnode nat 2 (pempty nat)) true. + Proof. + exact (ptree_bcongr_pnode nat 2 2 true (ReflectT _ eq_refl) + (pempty nat) (pempty nat) true (ReflectT _ eq_refl)). + Qed. + + Example pforest_bcongr_pcons_works : + reflect (pcons nat (pnode nat 2 (pempty nat)) (pempty nat) = + pcons nat (pnode nat 2 (pempty nat)) (pempty nat)) true. + Proof. + exact (pforest_bcongr_pcons nat + (pnode nat 2 (pempty nat)) (pnode nat 2 (pempty nat)) true (ReflectT _ eq_refl) + (pempty nat) (pempty nat) true (ReflectT _ eq_refl)). + Qed. +End ParametrizedMutualBcongr. + +Module TripleMutualMapFromGamma <: TripleMutualMapExpected. + Include test_derive_corelib.Mutual.Triple. + + #[only(map)] derive gamma. + + Example alpha_map_computes : + alpha_map (alpha1 (beta1 gamma0)) = alpha1 (beta1 gamma0). + Proof. vm_compute. reflexivity. Qed. + + Example beta_map_computes : beta_map (beta1 gamma0) = beta1 gamma0. + Proof. vm_compute. reflexivity. Qed. + + Example gamma_map_computes : + gamma_map (gamma1 (alpha1 beta0) beta0) = gamma1 (alpha1 beta0) beta0. + Proof. vm_compute. reflexivity. Qed. +End TripleMutualMapFromGamma. + +Module TripleMutualEqbFromAlpha <: TripleMutualEqbExpected. + Include test_derive_corelib.Mutual.Triple. + + #[only(eqb)] derive alpha. +End TripleMutualEqbFromAlpha. + +Module TripleMutualEqbFromBeta <: TripleMutualEqbExpected. + Include test_derive_corelib.Mutual.Triple. + + #[only(eqb)] derive beta. +End TripleMutualEqbFromBeta. + +Module TripleMutualEqbFromGamma <: TripleMutualEqbExpected. + Include test_derive_corelib.Mutual.Triple. + + #[only(eqb)] derive gamma. +End TripleMutualEqbFromGamma. + +Module TripleMutualEqbOKFromBeta <: TripleMutualEqbOKExpected. + Include test_derive_corelib.Mutual.Triple. + + #[only(eqbOK)] derive beta. + + Example alpha_eqb_computes_equal : alpha_eqb (alpha1 beta0) (alpha1 beta0) = true. + Proof. vm_compute. reflexivity. Qed. + + Example alpha_eqb_computes_different : alpha_eqb alpha0 (alpha1 beta0) = false. + Proof. vm_compute. reflexivity. Qed. + + Example beta_eqb_computes_equal : beta_eqb (beta1 gamma0) (beta1 gamma0) = true. + Proof. vm_compute. reflexivity. Qed. + + Example gamma_eqb_computes_different : + gamma_eqb (gamma1 alpha0 beta0) (gamma1 (alpha1 beta0) beta0) = false. + Proof. vm_compute. reflexivity. Qed. +End TripleMutualEqbOKFromBeta. + +Module Type ParametrizedTripleMutualEqbOKExpected. + Include ParametrizedTripleMutualBase. + Definition palpha_tag : forall A : Type, palpha A -> positive := + fun (A : Type) (i : palpha A) => + match i with + | palpha0 _ => xH + | palpha1 _ _ _ => xO xH + end. + Definition pbeta_tag : forall A : Type, pbeta A -> positive := + fun (A : Type) (i : pbeta A) => + match i with + | pbeta0 _ => xH + | pbeta1 _ _ => xO xH + end. + Definition pgamma_tag : forall A : Type, pgamma A -> positive := + fun (A : Type) (i : pgamma A) => + match i with + | pgamma0 _ => xH + | pgamma1 _ _ _ => xO xH + end. + Record box_palpha_palpha0 (A : Type) : Type := Box_palpha_palpha0 {}. + Record box_palpha_palpha1 (A : Type) : Type := Box_palpha_palpha1 { + Box_palpha_palpha1_0 : A; + Box_palpha_palpha1_1 : pbeta A; + }. + Record box_pbeta_pbeta0 (A : Type) : Type := Box_pbeta_pbeta0 {}. + Record box_pbeta_pbeta1 (A : Type) : Type := Box_pbeta_pbeta1 { + Box_pbeta_pbeta1_0 : pgamma A; + }. + Record box_pgamma_pgamma0 (A : Type) : Type := Box_pgamma_pgamma0 {}. + Record box_pgamma_pgamma1 (A : Type) : Type := Box_pgamma_pgamma1 { + Box_pgamma_pgamma1_0 : palpha A; + Box_pgamma_pgamma1_1 : pbeta A; + }. + Definition palpha_fields_t : Type -> positive -> Type := + fun (A : Type) (i : positive) => + match i with + | xI _ => unit + | xO _ => box_palpha_palpha1 A + | xH => box_palpha_palpha0 A + end. + Definition pbeta_fields_t : Type -> positive -> Type := + fun (A : Type) (i : positive) => + match i with + | xI _ => unit + | xO _ => box_pbeta_pbeta1 A + | xH => box_pbeta_pbeta0 A + end. + Definition pgamma_fields_t : Type -> positive -> Type := + fun (A : Type) (i : positive) => + match i with + | xI _ => unit + | xO _ => box_pgamma_pgamma1 A + | xH => box_pgamma_pgamma0 A + end. + Definition palpha_fields : + forall (A : Type) (i : palpha A), palpha_fields_t A (palpha_tag A i) := + fun (A : Type) (i : palpha A) => + match i with + | palpha0 _ => Box_palpha_palpha0 A + | palpha1 _ x b => {| Box_palpha_palpha1_0 := x; Box_palpha_palpha1_1 := b |} + end. + Definition pbeta_fields : + forall (A : Type) (i : pbeta A), pbeta_fields_t A (pbeta_tag A i) := + fun (A : Type) (i : pbeta A) => + match i with + | pbeta0 _ => Box_pbeta_pbeta0 A + | pbeta1 _ g => {| Box_pbeta_pbeta1_0 := g |} + end. + Definition pgamma_fields : + forall (A : Type) (i : pgamma A), pgamma_fields_t A (pgamma_tag A i) := + fun (A : Type) (i : pgamma A) => + match i with + | pgamma0 _ => Box_pgamma_pgamma0 A + | pgamma1 _ a b => {| Box_pgamma_pgamma1_0 := a; Box_pgamma_pgamma1_1 := b |} + end. + Definition palpha_eqb : forall A : Type, + (A -> A -> bool) -> palpha A -> palpha A -> bool := + fun (a : Type) (eqA : a -> a -> bool) => + fix palpha (x1 x2 : palpha a) {struct x1} : bool := + match x1 with + | palpha0 _ => + eqb_body (tagB:=palpha_tag a) + (fields_tA:=palpha_fields_t a) (fields_tB:=palpha_fields_t a) + (palpha_fields a) + (fun x : positive => + match x as i return palpha_fields_t a i -> palpha_fields_t a i -> bool with + | xI _ => fun _ : unit => xpredT + | xO _ => + fun a0 b : box_palpha_palpha1 a => + match a0 with + | {| Box_palpha_palpha1_0 := Box_palpha_palpha1_0; + Box_palpha_palpha1_1 := Box_palpha_palpha1_1 |} => + match b with + | {| Box_palpha_palpha1_0 := Box_palpha_palpha1_2; + Box_palpha_palpha1_1 := Box_palpha_palpha1_3 |} => + [&& eqA Box_palpha_palpha1_0 Box_palpha_palpha1_2, + pbeta Box_palpha_palpha1_1 Box_palpha_palpha1_3 & true] + end + end + | xH => fun _ : box_palpha_palpha0 a => xpredT + end) + (t1:=palpha_tag a (palpha0 a)) (Box_palpha_palpha0 a) x2 + | palpha1 _ x b => + eqb_body (tagB:=palpha_tag a) + (fields_tA:=palpha_fields_t a) (fields_tB:=palpha_fields_t a) + (palpha_fields a) + (fun x0 : positive => + match x0 as i return palpha_fields_t a i -> palpha_fields_t a i -> bool with + | xI _ => fun _ : unit => xpredT + | xO _ => + fun a0 b0 : box_palpha_palpha1 a => + match a0 with + | {| Box_palpha_palpha1_0 := Box_palpha_palpha1_0; + Box_palpha_palpha1_1 := Box_palpha_palpha1_1 |} => + match b0 with + | {| Box_palpha_palpha1_0 := Box_palpha_palpha1_2; + Box_palpha_palpha1_1 := Box_palpha_palpha1_3 |} => + [&& eqA Box_palpha_palpha1_0 Box_palpha_palpha1_2, + pbeta Box_palpha_palpha1_1 Box_palpha_palpha1_3 & true] + end + end + | xH => fun _ : box_palpha_palpha0 a => xpredT + end) + (t1:=palpha_tag a (palpha1 a x b)) + {| Box_palpha_palpha1_0 := x; Box_palpha_palpha1_1 := b |} x2 + end + with pbeta (x1 x2 : pbeta a) {struct x1} : bool := + match x1 with + | pbeta0 _ => + eqb_body (tagB:=pbeta_tag a) + (fields_tA:=pbeta_fields_t a) (fields_tB:=pbeta_fields_t a) + (pbeta_fields a) + (fun x : positive => + match x as i return pbeta_fields_t a i -> pbeta_fields_t a i -> bool with + | xI _ => fun _ : unit => xpredT + | xO _ => + fun a0 b : box_pbeta_pbeta1 a => + match a0 with + | {| Box_pbeta_pbeta1_0 := Box_pbeta_pbeta1_0 |} => + match b with + | {| Box_pbeta_pbeta1_0 := Box_pbeta_pbeta1_1 |} => + pgamma Box_pbeta_pbeta1_0 Box_pbeta_pbeta1_1 && true + end + end + | xH => fun _ : box_pbeta_pbeta0 a => xpredT + end) + (t1:=pbeta_tag a (pbeta0 a)) (Box_pbeta_pbeta0 a) x2 + | pbeta1 _ g => + eqb_body (tagB:=pbeta_tag a) + (fields_tA:=pbeta_fields_t a) (fields_tB:=pbeta_fields_t a) + (pbeta_fields a) + (fun x : positive => + match x as i return pbeta_fields_t a i -> pbeta_fields_t a i -> bool with + | xI _ => fun _ : unit => xpredT + | xO _ => + fun a0 b : box_pbeta_pbeta1 a => + match a0 with + | {| Box_pbeta_pbeta1_0 := Box_pbeta_pbeta1_0 |} => + match b with + | {| Box_pbeta_pbeta1_0 := Box_pbeta_pbeta1_1 |} => + pgamma Box_pbeta_pbeta1_0 Box_pbeta_pbeta1_1 && true + end + end + | xH => fun _ : box_pbeta_pbeta0 a => xpredT + end) + (t1:=pbeta_tag a (pbeta1 a g)) {| Box_pbeta_pbeta1_0 := g |} x2 + end + with pgamma (x1 x2 : pgamma a) {struct x1} : bool := + match x1 with + | pgamma0 _ => + eqb_body (tagB:=pgamma_tag a) + (fields_tA:=pgamma_fields_t a) (fields_tB:=pgamma_fields_t a) + (pgamma_fields a) + (fun x : positive => + match x as i return pgamma_fields_t a i -> pgamma_fields_t a i -> bool with + | xI _ => fun _ : unit => xpredT + | xO _ => + fun a0 b : box_pgamma_pgamma1 a => + match a0 with + | {| Box_pgamma_pgamma1_0 := Box_pgamma_pgamma1_0; + Box_pgamma_pgamma1_1 := Box_pgamma_pgamma1_1 |} => + match b with + | {| Box_pgamma_pgamma1_0 := Box_pgamma_pgamma1_2; + Box_pgamma_pgamma1_1 := Box_pgamma_pgamma1_3 |} => + [&& palpha Box_pgamma_pgamma1_0 Box_pgamma_pgamma1_2, + pbeta Box_pgamma_pgamma1_1 Box_pgamma_pgamma1_3 & true] + end + end + | xH => fun _ : box_pgamma_pgamma0 a => xpredT + end) + (t1:=pgamma_tag a (pgamma0 a)) (Box_pgamma_pgamma0 a) x2 + | pgamma1 _ a0 b => + eqb_body (tagB:=pgamma_tag a) + (fields_tA:=pgamma_fields_t a) (fields_tB:=pgamma_fields_t a) + (pgamma_fields a) + (fun x : positive => + match x as i return pgamma_fields_t a i -> pgamma_fields_t a i -> bool with + | xI _ => fun _ : unit => xpredT + | xO _ => + fun a1 b0 : box_pgamma_pgamma1 a => + match a1 with + | {| Box_pgamma_pgamma1_0 := Box_pgamma_pgamma1_0; + Box_pgamma_pgamma1_1 := Box_pgamma_pgamma1_1 |} => + match b0 with + | {| Box_pgamma_pgamma1_0 := Box_pgamma_pgamma1_2; + Box_pgamma_pgamma1_1 := Box_pgamma_pgamma1_3 |} => + [&& palpha Box_pgamma_pgamma1_0 Box_pgamma_pgamma1_2, + pbeta Box_pgamma_pgamma1_1 Box_pgamma_pgamma1_3 & true] + end + end + | xH => fun _ : box_pgamma_pgamma0 a => xpredT + end) + (t1:=pgamma_tag a (pgamma1 a a0 b)) + {| Box_pgamma_pgamma1_0 := a0; Box_pgamma_pgamma1_1 := b |} x2 + end + for palpha. + Definition pbeta_eqb : forall A : Type, + (A -> A -> bool) -> pbeta A -> pbeta A -> bool := + fun (a : Type) (eqA : a -> a -> bool) => + fix palpha (x1 x2 : palpha a) {struct x1} : bool := + match x1 with + | palpha0 _ => + eqb_body (tagB:=palpha_tag a) + (fields_tA:=palpha_fields_t a) (fields_tB:=palpha_fields_t a) + (palpha_fields a) + (fun x : positive => + match x as i return palpha_fields_t a i -> palpha_fields_t a i -> bool with + | xI _ => fun _ : unit => xpredT + | xO _ => + fun a0 b : box_palpha_palpha1 a => + match a0 with + | {| Box_palpha_palpha1_0 := Box_palpha_palpha1_0; + Box_palpha_palpha1_1 := Box_palpha_palpha1_1 |} => + match b with + | {| Box_palpha_palpha1_0 := Box_palpha_palpha1_2; + Box_palpha_palpha1_1 := Box_palpha_palpha1_3 |} => + [&& eqA Box_palpha_palpha1_0 Box_palpha_palpha1_2, + pbeta Box_palpha_palpha1_1 Box_palpha_palpha1_3 & true] + end + end + | xH => fun _ : box_palpha_palpha0 a => xpredT + end) + (t1:=palpha_tag a (palpha0 a)) (Box_palpha_palpha0 a) x2 + | palpha1 _ x b => + eqb_body (tagB:=palpha_tag a) + (fields_tA:=palpha_fields_t a) (fields_tB:=palpha_fields_t a) + (palpha_fields a) + (fun x0 : positive => + match x0 as i return palpha_fields_t a i -> palpha_fields_t a i -> bool with + | xI _ => fun _ : unit => xpredT + | xO _ => + fun a0 b0 : box_palpha_palpha1 a => + match a0 with + | {| Box_palpha_palpha1_0 := Box_palpha_palpha1_0; + Box_palpha_palpha1_1 := Box_palpha_palpha1_1 |} => + match b0 with + | {| Box_palpha_palpha1_0 := Box_palpha_palpha1_2; + Box_palpha_palpha1_1 := Box_palpha_palpha1_3 |} => + [&& eqA Box_palpha_palpha1_0 Box_palpha_palpha1_2, + pbeta Box_palpha_palpha1_1 Box_palpha_palpha1_3 & true] + end + end + | xH => fun _ : box_palpha_palpha0 a => xpredT + end) + (t1:=palpha_tag a (palpha1 a x b)) + {| Box_palpha_palpha1_0 := x; Box_palpha_palpha1_1 := b |} x2 + end + with pbeta (x1 x2 : pbeta a) {struct x1} : bool := + match x1 with + | pbeta0 _ => + eqb_body (tagB:=pbeta_tag a) + (fields_tA:=pbeta_fields_t a) (fields_tB:=pbeta_fields_t a) + (pbeta_fields a) + (fun x : positive => + match x as i return pbeta_fields_t a i -> pbeta_fields_t a i -> bool with + | xI _ => fun _ : unit => xpredT + | xO _ => + fun a0 b : box_pbeta_pbeta1 a => + match a0 with + | {| Box_pbeta_pbeta1_0 := Box_pbeta_pbeta1_0 |} => + match b with + | {| Box_pbeta_pbeta1_0 := Box_pbeta_pbeta1_1 |} => + pgamma Box_pbeta_pbeta1_0 Box_pbeta_pbeta1_1 && true + end + end + | xH => fun _ : box_pbeta_pbeta0 a => xpredT + end) + (t1:=pbeta_tag a (pbeta0 a)) (Box_pbeta_pbeta0 a) x2 + | pbeta1 _ g => + eqb_body (tagB:=pbeta_tag a) + (fields_tA:=pbeta_fields_t a) (fields_tB:=pbeta_fields_t a) + (pbeta_fields a) + (fun x : positive => + match x as i return pbeta_fields_t a i -> pbeta_fields_t a i -> bool with + | xI _ => fun _ : unit => xpredT + | xO _ => + fun a0 b : box_pbeta_pbeta1 a => + match a0 with + | {| Box_pbeta_pbeta1_0 := Box_pbeta_pbeta1_0 |} => + match b with + | {| Box_pbeta_pbeta1_0 := Box_pbeta_pbeta1_1 |} => + pgamma Box_pbeta_pbeta1_0 Box_pbeta_pbeta1_1 && true + end + end + | xH => fun _ : box_pbeta_pbeta0 a => xpredT + end) + (t1:=pbeta_tag a (pbeta1 a g)) {| Box_pbeta_pbeta1_0 := g |} x2 + end + with pgamma (x1 x2 : pgamma a) {struct x1} : bool := + match x1 with + | pgamma0 _ => + eqb_body (tagB:=pgamma_tag a) + (fields_tA:=pgamma_fields_t a) (fields_tB:=pgamma_fields_t a) + (pgamma_fields a) + (fun x : positive => + match x as i return pgamma_fields_t a i -> pgamma_fields_t a i -> bool with + | xI _ => fun _ : unit => xpredT + | xO _ => + fun a0 b : box_pgamma_pgamma1 a => + match a0 with + | {| Box_pgamma_pgamma1_0 := Box_pgamma_pgamma1_0; + Box_pgamma_pgamma1_1 := Box_pgamma_pgamma1_1 |} => + match b with + | {| Box_pgamma_pgamma1_0 := Box_pgamma_pgamma1_2; + Box_pgamma_pgamma1_1 := Box_pgamma_pgamma1_3 |} => + [&& palpha Box_pgamma_pgamma1_0 Box_pgamma_pgamma1_2, + pbeta Box_pgamma_pgamma1_1 Box_pgamma_pgamma1_3 & true] + end + end + | xH => fun _ : box_pgamma_pgamma0 a => xpredT + end) + (t1:=pgamma_tag a (pgamma0 a)) (Box_pgamma_pgamma0 a) x2 + | pgamma1 _ a0 b => + eqb_body (tagB:=pgamma_tag a) + (fields_tA:=pgamma_fields_t a) (fields_tB:=pgamma_fields_t a) + (pgamma_fields a) + (fun x : positive => + match x as i return pgamma_fields_t a i -> pgamma_fields_t a i -> bool with + | xI _ => fun _ : unit => xpredT + | xO _ => + fun a1 b0 : box_pgamma_pgamma1 a => + match a1 with + | {| Box_pgamma_pgamma1_0 := Box_pgamma_pgamma1_0; + Box_pgamma_pgamma1_1 := Box_pgamma_pgamma1_1 |} => + match b0 with + | {| Box_pgamma_pgamma1_0 := Box_pgamma_pgamma1_2; + Box_pgamma_pgamma1_1 := Box_pgamma_pgamma1_3 |} => + [&& palpha Box_pgamma_pgamma1_0 Box_pgamma_pgamma1_2, + pbeta Box_pgamma_pgamma1_1 Box_pgamma_pgamma1_3 & true] + end + end + | xH => fun _ : box_pgamma_pgamma0 a => xpredT + end) + (t1:=pgamma_tag a (pgamma1 a a0 b)) + {| Box_pgamma_pgamma1_0 := a0; Box_pgamma_pgamma1_1 := b |} x2 + end + for pbeta. + Definition pgamma_eqb : forall A : Type, + (A -> A -> bool) -> pgamma A -> pgamma A -> bool := + fun (a : Type) (eqA : a -> a -> bool) => + fix palpha (x1 x2 : palpha a) {struct x1} : bool := + match x1 with + | palpha0 _ => + eqb_body (tagB:=palpha_tag a) + (fields_tA:=palpha_fields_t a) (fields_tB:=palpha_fields_t a) + (palpha_fields a) + (fun x : positive => + match x as i return palpha_fields_t a i -> palpha_fields_t a i -> bool with + | xI _ => fun _ : unit => xpredT + | xO _ => + fun a0 b : box_palpha_palpha1 a => + match a0 with + | {| Box_palpha_palpha1_0 := Box_palpha_palpha1_0; + Box_palpha_palpha1_1 := Box_palpha_palpha1_1 |} => + match b with + | {| Box_palpha_palpha1_0 := Box_palpha_palpha1_2; + Box_palpha_palpha1_1 := Box_palpha_palpha1_3 |} => + [&& eqA Box_palpha_palpha1_0 Box_palpha_palpha1_2, + pbeta Box_palpha_palpha1_1 Box_palpha_palpha1_3 & true] + end + end + | xH => fun _ : box_palpha_palpha0 a => xpredT + end) + (t1:=palpha_tag a (palpha0 a)) (Box_palpha_palpha0 a) x2 + | palpha1 _ x b => + eqb_body (tagB:=palpha_tag a) + (fields_tA:=palpha_fields_t a) (fields_tB:=palpha_fields_t a) + (palpha_fields a) + (fun x0 : positive => + match x0 as i return palpha_fields_t a i -> palpha_fields_t a i -> bool with + | xI _ => fun _ : unit => xpredT + | xO _ => + fun a0 b0 : box_palpha_palpha1 a => + match a0 with + | {| Box_palpha_palpha1_0 := Box_palpha_palpha1_0; + Box_palpha_palpha1_1 := Box_palpha_palpha1_1 |} => + match b0 with + | {| Box_palpha_palpha1_0 := Box_palpha_palpha1_2; + Box_palpha_palpha1_1 := Box_palpha_palpha1_3 |} => + [&& eqA Box_palpha_palpha1_0 Box_palpha_palpha1_2, + pbeta Box_palpha_palpha1_1 Box_palpha_palpha1_3 & true] + end + end + | xH => fun _ : box_palpha_palpha0 a => xpredT + end) + (t1:=palpha_tag a (palpha1 a x b)) + {| Box_palpha_palpha1_0 := x; Box_palpha_palpha1_1 := b |} x2 + end + with pbeta (x1 x2 : pbeta a) {struct x1} : bool := + match x1 with + | pbeta0 _ => + eqb_body (tagB:=pbeta_tag a) + (fields_tA:=pbeta_fields_t a) (fields_tB:=pbeta_fields_t a) + (pbeta_fields a) + (fun x : positive => + match x as i return pbeta_fields_t a i -> pbeta_fields_t a i -> bool with + | xI _ => fun _ : unit => xpredT + | xO _ => + fun a0 b : box_pbeta_pbeta1 a => + match a0 with + | {| Box_pbeta_pbeta1_0 := Box_pbeta_pbeta1_0 |} => + match b with + | {| Box_pbeta_pbeta1_0 := Box_pbeta_pbeta1_1 |} => + pgamma Box_pbeta_pbeta1_0 Box_pbeta_pbeta1_1 && true + end + end + | xH => fun _ : box_pbeta_pbeta0 a => xpredT + end) + (t1:=pbeta_tag a (pbeta0 a)) (Box_pbeta_pbeta0 a) x2 + | pbeta1 _ g => + eqb_body (tagB:=pbeta_tag a) + (fields_tA:=pbeta_fields_t a) (fields_tB:=pbeta_fields_t a) + (pbeta_fields a) + (fun x : positive => + match x as i return pbeta_fields_t a i -> pbeta_fields_t a i -> bool with + | xI _ => fun _ : unit => xpredT + | xO _ => + fun a0 b : box_pbeta_pbeta1 a => + match a0 with + | {| Box_pbeta_pbeta1_0 := Box_pbeta_pbeta1_0 |} => + match b with + | {| Box_pbeta_pbeta1_0 := Box_pbeta_pbeta1_1 |} => + pgamma Box_pbeta_pbeta1_0 Box_pbeta_pbeta1_1 && true + end + end + | xH => fun _ : box_pbeta_pbeta0 a => xpredT + end) + (t1:=pbeta_tag a (pbeta1 a g)) {| Box_pbeta_pbeta1_0 := g |} x2 + end + with pgamma (x1 x2 : pgamma a) {struct x1} : bool := + match x1 with + | pgamma0 _ => + eqb_body (tagB:=pgamma_tag a) + (fields_tA:=pgamma_fields_t a) (fields_tB:=pgamma_fields_t a) + (pgamma_fields a) + (fun x : positive => + match x as i return pgamma_fields_t a i -> pgamma_fields_t a i -> bool with + | xI _ => fun _ : unit => xpredT + | xO _ => + fun a0 b : box_pgamma_pgamma1 a => + match a0 with + | {| Box_pgamma_pgamma1_0 := Box_pgamma_pgamma1_0; + Box_pgamma_pgamma1_1 := Box_pgamma_pgamma1_1 |} => + match b with + | {| Box_pgamma_pgamma1_0 := Box_pgamma_pgamma1_2; + Box_pgamma_pgamma1_1 := Box_pgamma_pgamma1_3 |} => + [&& palpha Box_pgamma_pgamma1_0 Box_pgamma_pgamma1_2, + pbeta Box_pgamma_pgamma1_1 Box_pgamma_pgamma1_3 & true] + end + end + | xH => fun _ : box_pgamma_pgamma0 a => xpredT + end) + (t1:=pgamma_tag a (pgamma0 a)) (Box_pgamma_pgamma0 a) x2 + | pgamma1 _ a0 b => + eqb_body (tagB:=pgamma_tag a) + (fields_tA:=pgamma_fields_t a) (fields_tB:=pgamma_fields_t a) + (pgamma_fields a) + (fun x : positive => + match x as i return pgamma_fields_t a i -> pgamma_fields_t a i -> bool with + | xI _ => fun _ : unit => xpredT + | xO _ => + fun a1 b0 : box_pgamma_pgamma1 a => + match a1 with + | {| Box_pgamma_pgamma1_0 := Box_pgamma_pgamma1_0; + Box_pgamma_pgamma1_1 := Box_pgamma_pgamma1_1 |} => + match b0 with + | {| Box_pgamma_pgamma1_0 := Box_pgamma_pgamma1_2; + Box_pgamma_pgamma1_1 := Box_pgamma_pgamma1_3 |} => + [&& palpha Box_pgamma_pgamma1_0 Box_pgamma_pgamma1_2, + pbeta Box_pgamma_pgamma1_1 Box_pgamma_pgamma1_3 & true] + end + end + | xH => fun _ : box_pgamma_pgamma0 a => xpredT + end) + (t1:=pgamma_tag a (pgamma1 a a0 b)) + {| Box_pgamma_pgamma1_0 := a0; Box_pgamma_pgamma1_1 := b |} x2 + end + for pgamma. + Parameter palpha_eqb_correct : forall (A : Type) (eqA : A -> A -> bool), + eqb_core_defs.eqb_correct eqA -> + forall x : palpha A, eqb_core_defs.eqb_correct_on (palpha_eqb A eqA) x. + Parameter pbeta_eqb_correct : forall (A : Type) (eqA : A -> A -> bool), + eqb_core_defs.eqb_correct eqA -> + forall x : pbeta A, eqb_core_defs.eqb_correct_on (pbeta_eqb A eqA) x. + Parameter pgamma_eqb_correct : forall (A : Type) (eqA : A -> A -> bool), + eqb_core_defs.eqb_correct eqA -> + forall x : pgamma A, eqb_core_defs.eqb_correct_on (pgamma_eqb A eqA) x. + Parameter palpha_eqb_refl : forall (A : Type) (eqA : A -> A -> bool), + eqb_core_defs.eqb_reflexive eqA -> + forall x : palpha A, eqb_core_defs.eqb_refl_on (palpha_eqb A eqA) x. + Parameter pbeta_eqb_refl : forall (A : Type) (eqA : A -> A -> bool), + eqb_core_defs.eqb_reflexive eqA -> + forall x : pbeta A, eqb_core_defs.eqb_refl_on (pbeta_eqb A eqA) x. + Parameter pgamma_eqb_refl : forall (A : Type) (eqA : A -> A -> bool), + eqb_core_defs.eqb_reflexive eqA -> + forall x : pgamma A, eqb_core_defs.eqb_refl_on (pgamma_eqb A eqA) x. + Parameter palpha_eqb_OK : forall (A : Type) (eqA : A -> A -> bool), + (forall x y : A, reflect (x = y) (eqA x y)) -> + forall x y : palpha A, reflect (x = y) (palpha_eqb A eqA x y). + Parameter pbeta_eqb_OK : forall (A : Type) (eqA : A -> A -> bool), + (forall x y : A, reflect (x = y) (eqA x y)) -> + forall x y : pbeta A, reflect (x = y) (pbeta_eqb A eqA x y). + Parameter pgamma_eqb_OK : forall (A : Type) (eqA : A -> A -> bool), + (forall x y : A, reflect (x = y) (eqA x y)) -> + forall x y : pgamma A, reflect (x = y) (pgamma_eqb A eqA x y). + Parameter palpha_eqb_OK_sumbool : forall A : Type, + (forall x y : A, {x = y} + {x <> y}) -> + forall x y : palpha A, {x = y} + {x <> y}. + Parameter pbeta_eqb_OK_sumbool : forall A : Type, + (forall x y : A, {x = y} + {x <> y}) -> + forall x y : pbeta A, {x = y} + {x <> y}. + Parameter pgamma_eqb_OK_sumbool : forall A : Type, + (forall x y : A, {x = y} + {x <> y}) -> + forall x y : pgamma A, {x = y} + {x <> y}. +End ParametrizedTripleMutualEqbOKExpected. + +Module ParametrizedTripleMutualEqbOKFromBeta <: ParametrizedTripleMutualEqbOKExpected. + Include test_derive_corelib.Mutual.ParametrizedTriple. + + #[only(eqbOK)] derive pbeta. +End ParametrizedTripleMutualEqbOKFromBeta. diff --git a/apps/derive/tests/test_derive_mutual_indexed.v b/apps/derive/tests/test_derive_mutual_indexed.v new file mode 100644 index 000000000..dbc3a7c7f --- /dev/null +++ b/apps/derive/tests/test_derive_mutual_indexed.v @@ -0,0 +1,104 @@ +From Corelib Require Import Nat BinNums. +Definition bool_is_true := is_true. +From elpi.apps.derive.tests Require Import test_derive_corelib. +From elpi.apps Require Import + derive + derive.tag + derive.isK + derive.projK + derive.map + derive.param1 + derive.param1_congr + derive.param1_functor + derive.param2 + derive.induction. + +Module StandaloneTagIsKProjK. + Import test_derive_corelib.Mutual.Indexed. + + Elpi derive.tag itree. + Redirect "tmp" Check itree_tag : forall A n, itree A n -> positive. + Redirect "tmp" Check iforest_tag : forall A n, iforest A n -> positive. + + Elpi derive.isK itree. + Redirect "tmp" Check itree_is_ileaf : forall A n, itree A n -> bool. + Redirect "tmp" Check itree_is_inode : forall A n, itree A n -> bool. + Redirect "tmp" Check iforest_is_inil : forall A n, iforest A n -> bool. + Redirect "tmp" Check iforest_is_icons : forall A n, iforest A n -> bool. + + Elpi derive.projK itree. + Redirect "tmp" Check projileaf1. + Redirect "tmp" Check projinode1. + Redirect "tmp" Check projinode2. + Redirect "tmp" Check iforest_projicons1. + Redirect "tmp" Check iforest_projicons2. +End StandaloneTagIsKProjK. + +Module StandaloneMap. + Import test_derive_corelib.Mutual.Indexed. + + Elpi derive.map itree. + Redirect "tmp" Check itree_map : forall A B, (A -> B) -> forall n, itree A n -> itree B n. + Redirect "tmp" Check iforest_map : forall A B, (A -> B) -> forall n, iforest A n -> iforest B n. + + Example itree_map_computes : + itree_map nat bool Nat.even 0 (ileaf nat 2) = ileaf bool true. + Proof. vm_compute. reflexivity. Qed. +End StandaloneMap. + +Module StandaloneParam1Param2. + Import test_derive_corelib.Mutual.Indexed. + + Elpi derive.param1 nat. + Elpi derive.param1 itree. + Redirect "tmp" Check is_itree : forall A, (A -> Type) -> forall n, is_nat n -> itree A n -> Type. + Redirect "tmp" Check is_iforest : forall A, (A -> Type) -> forall n, is_nat n -> iforest A n -> Type. + + Elpi derive.param2 nat. + Elpi derive.param2 itree. + Redirect "tmp" Check itree_R : + forall A1 A2, (A1 -> A2 -> Type) -> + forall n1 n2, nat_R n1 n2 -> itree A1 n1 -> itree A2 n2 -> Type. + Redirect "tmp" Check iforest_R : + forall A1 A2, (A1 -> A2 -> Type) -> + forall n1 n2, nat_R n1 n2 -> iforest A1 n1 -> iforest A2 n2 -> Type. +End StandaloneParam1Param2. + +Module StandaloneParam1CongrFunctorInduction. + Import test_derive_corelib.Mutual.Indexed. + + Elpi derive.param1 nat. + Elpi derive.param1 itree. + Elpi derive.param1.congr is_itree. + Redirect "tmp" Check congr_is_ileaf. + Redirect "tmp" Check congr_is_inil. + + Elpi derive.param1.functor is_itree. + Redirect "tmp" Check is_itree_functor : forall A (PA PB : A -> Type), + (forall x, PA x -> PB x) -> forall n pn x, is_itree A PA n pn x -> is_itree A PB n pn x. + Redirect "tmp" Check is_iforest_functor : forall A (PA PB : A -> Type), + (forall x, PA x -> PB x) -> forall n pn x, is_iforest A PA n pn x -> is_iforest A PB n pn x. + + Elpi derive.induction itree. + Redirect "tmp" Check itree_induction. + Redirect "tmp" Check iforest_induction. +End StandaloneParam1CongrFunctorInduction. + +Module HookMap. + Import test_derive_corelib.Mutual.Indexed. + + #[only(map)] derive itree. + Redirect "tmp" Check itree_map : forall A B, (A -> B) -> forall n, itree A n -> itree B n. + Redirect "tmp" Check iforest_map : forall A B, (A -> B) -> forall n, iforest A n -> iforest B n. +End HookMap. + +Module HookInduction. + Import test_derive_corelib.Mutual.Indexed. + + Elpi derive.param1 nat. + #[only(induction)] derive itree. + Redirect "tmp" Check is_itree_functor : forall A (PA PB : A -> Type), + (forall x, PA x -> PB x) -> forall n pn x, is_itree A PA n pn x -> is_itree A PB n pn x. + Redirect "tmp" Check itree_induction. + Redirect "tmp" Check iforest_induction. +End HookInduction. diff --git a/apps/derive/tests/test_eqb.v b/apps/derive/tests/test_eqb.v index 432cb65cf..365db91e5 100644 --- a/apps/derive/tests/test_eqb.v +++ b/apps/derive/tests/test_eqb.v @@ -42,9 +42,9 @@ Elpi derive.eqb val. Elpi derive.eqb alias. Elpi derive.eqb mempty. Elpi derive.eqb munit. -Fail Elpi derive.eqb mpeano. +Elpi derive.eqb mpeano. Elpi derive.eqb moption. -Fail Elpi derive.eqb mtree. +Elpi derive.eqb mtree. End Coverage. @@ -83,3 +83,115 @@ Redirect "tmp" Check ord2_eqb : forall p1 p2, eq_test2 (ord2 p1) (ord2 p2). Redirect "tmp" Check val_eqb : eq_test val. Redirect "tmp" Check alias_eqb : eq_test alias. + +Redirect "tmp" Check mempty_eqb : eq_test mempty. +Redirect "tmp" Check mempty'_eqb : eq_test mempty'. +Redirect "tmp" Check munit_eqb : eq_test munit. +Redirect "tmp" Check munit'_eqb : eq_test munit'. +Redirect "tmp" Check mpeano_eqb : eq_test mpeano. +Redirect "tmp" Check mpeano'_eqb : eq_test mpeano'. +Redirect "tmp" Check moption_eqb : forall A, eq_test A -> eq_test (moption A). +Redirect "tmp" Check moption'_eqb : forall A, eq_test A -> eq_test (moption' A). +Redirect "tmp" Check mtree_eqb : forall A, eq_test A -> eq_test (mtree A). +Redirect "tmp" Check mforest_eqb : forall A, eq_test A -> eq_test (mforest A). + + +Module EqbStandaloneFirst. + + Import test_derive_corelib.Mutual.Tree. + + Elpi derive.eqType.ast tree. + Elpi derive.tag tree. + Elpi derive.fields tree. + Elpi derive.eqb tree. + + Redirect "tmp" Check tree_eqb : tree -> tree -> bool. + Redirect "tmp" Check forest_eqb : forest -> forest -> bool. + Redirect "tmp" Check tree_eqb_fields. + Redirect "tmp" Check forest_eqb_fields. + Redirect "tmp" Elpi Query derive.eqb lp:{{ + eqb-done {{:gref tree}}, + eqb-done {{:gref forest}} + }}. +End EqbStandaloneFirst. + +Module EqbStandaloneSecond. + + Import test_derive_corelib.Mutual.Tree. + + Elpi derive.eqType.ast tree. + Elpi derive.tag tree. + Elpi derive.fields tree. + Elpi derive.eqb forest. + + Redirect "tmp" Check tree_eqb : tree -> tree -> bool. + Redirect "tmp" Check forest_eqb : forest -> forest -> bool. + Redirect "tmp" Check tree_eqb_fields. + Redirect "tmp" Check forest_eqb_fields. +End EqbStandaloneSecond. + +Module EqbComputation. + + Import test_derive_corelib.Mutual.Tree. + + Elpi derive.eqType.ast tree. + Elpi derive.tag tree. + Elpi derive.fields tree. + Elpi derive.eqb tree. + + Example tree_eqb_refl_node : tree_eqb (node empty) (node empty) = true := eq_refl. + Example forest_eqb_neq : forest_eqb empty (cons (node empty) empty) = false := eq_refl. +End EqbComputation. + +Module EqbParametrized. + + Import test_derive_corelib.Mutual.ParametrizedTree. + + Elpi derive.eqType.ast ptree. + Elpi derive.tag ptree. + Elpi derive.fields ptree. + Elpi derive.eqb ptree. + + Redirect "tmp" Check ptree_eqb : forall A, (A -> A -> bool) -> ptree A -> ptree A -> bool. + Redirect "tmp" Check pforest_eqb : forall A, (A -> A -> bool) -> pforest A -> pforest A -> bool. +End EqbParametrized. + +Module EqbUnsupportedValueParam. + + Inductive a (n : nat) : Type := ak (b0 : b n) + with b (n : nat) : Type := bk (a0 : a n). + + Elpi derive.eqType.ast a. + Elpi derive.tag a. + Elpi derive.fields a. + (* Value-parameterized mutual eqb is intentionally unsupported for now. *) + Fail Elpi derive.eqb a. +End EqbUnsupportedValueParam. + +Module EqbTripleFromBeta. + + Import test_derive_corelib.Mutual.CyclicTriple. + + Elpi derive.eqType.ast alpha. + Elpi derive.tag alpha. + Elpi derive.fields alpha. + Elpi derive.eqb alpha. + + Redirect "tmp" Check alpha_eqb : alpha -> alpha -> bool. + Redirect "tmp" Check beta_eqb : beta -> beta -> bool. + Redirect "tmp" Check gamma_eqb : gamma -> gamma -> bool. +End EqbTripleFromBeta. + +Module EqbTripleFromGamma. + + Import test_derive_corelib.Mutual.CyclicTriple. + + Elpi derive.eqType.ast gamma. + Elpi derive.tag gamma. + Elpi derive.fields gamma. + Elpi derive.eqb gamma. + + Redirect "tmp" Check alpha_eqb : alpha -> alpha -> bool. + Redirect "tmp" Check beta_eqb : beta -> beta -> bool. + Redirect "tmp" Check gamma_eqb : gamma -> gamma -> bool. +End EqbTripleFromGamma. diff --git a/apps/derive/tests/test_eqbOK.v b/apps/derive/tests/test_eqbOK.v index c8761df02..a090988fc 100644 --- a/apps/derive/tests/test_eqbOK.v +++ b/apps/derive/tests/test_eqbOK.v @@ -1,4 +1,4 @@ -From elpi.apps Require Import derive.eqbOK. +From elpi.apps Require Import derive derive.eqbOK. From elpi.apps.derive.tests Require Import test_derive_corelib test_eqb test_eqbcorrect. @@ -45,9 +45,9 @@ Elpi derive.eqbOK ord. Elpi derive.eqbOK ord2. Elpi derive.eqbOK val. Elpi derive.eqbOK alias. -Fail Elpi derive.eqbOK mempty. -Fail Elpi derive.eqbOK munit. -Fail Elpi derive.eqbOK mpeano. +Elpi derive.eqbOK mempty. +Elpi derive.eqbOK munit. +Elpi derive.eqbOK mpeano. Fail Elpi derive.eqbOK moption. Fail Elpi derive.eqbOK mtree. @@ -59,3 +59,114 @@ Redirect "tmp" Check peano_eqb_OK : forall n m, Datatypes.reflect (n = m) (peano Redirect "tmp" Check seq_eqb_OK : forall A eqA (h : forall a1 a2 : A, Datatypes.reflect (a1 = a2) (eqA a1 a2)) l1 l2, Datatypes.reflect (l1 = l2) (seq_eqb A eqA l1 l2). Redirect "tmp" Check ord_eqb_OK : forall n (o1 o2 : ord n), Datatypes.reflect (o1 = o2) (ord_eqb n n o1 o2). Redirect "tmp" Check alias_eqb_OK : forall x y : alias, Datatypes.reflect (x = y) (alias_eqb x y). + +Module EqbOKStandaloneFirst. + From elpi.apps Require Import derive.eqbOK. + + Import test_derive_corelib.Mutual.Tree. + + #[only(param1,param1_functor,param1_inhab,induction,eqType_ast,tag,fields,eqb,eqbcorrect)] derive tree. + Elpi derive.eqbOK tree. + + Redirect "tmp" Check tree_eqb_OK. + Redirect "tmp" Check forest_eqb_OK. + Redirect "tmp" Check tree_eqb_OK_sumbool. + Redirect "tmp" Check forest_eqb_OK_sumbool. + Redirect "tmp" Elpi Query derive.eqbOK lp:{{ + eqbok-for {{:gref tree}} _, + eqbok-for {{:gref forest}} _ + }}. +End EqbOKStandaloneFirst. + +Module EqbOKStandaloneSecond. + From elpi.apps Require Import derive.eqbOK. + + Import test_derive_corelib.Mutual.Tree. + + #[only(param1,param1_functor,param1_inhab,induction,eqType_ast,tag,fields,eqb,eqbcorrect)] derive tree. + Elpi derive.eqbOK forest. + + Redirect "tmp" Check tree_eqb_OK. + Redirect "tmp" Check forest_eqb_OK. + Redirect "tmp" Check tree_eqb_OK_sumbool. + Redirect "tmp" Check forest_eqb_OK_sumbool. +End EqbOKStandaloneSecond. + +Module EqbOKMetaFirst. + From elpi.apps Require Import derive.eqbOK. + + Import test_derive_corelib.Mutual.Tree. + + #[only(param1,param1_functor,param1_inhab,induction,eqType_ast,tag,fields,eqb,eqbcorrect,eqbOK)] derive tree. + + Redirect "tmp" Check tree_eqb_OK. + Redirect "tmp" Check forest_eqb_OK. + Redirect "tmp" Check tree_eqb_OK_sumbool. + Redirect "tmp" Check forest_eqb_OK_sumbool. +End EqbOKMetaFirst. + +Module EqbOKMetaSecond. + From elpi.apps Require Import derive.eqbOK. + + Import test_derive_corelib.Mutual.Tree. + + #[only(param1,param1_functor,param1_inhab,induction,eqType_ast,tag,fields,eqb,eqbcorrect,eqbOK)] derive forest. + + Redirect "tmp" Check tree_eqb_OK. + Redirect "tmp" Check forest_eqb_OK. + Redirect "tmp" Check tree_eqb_OK_sumbool. + Redirect "tmp" Check forest_eqb_OK_sumbool. +End EqbOKMetaSecond. + +Module EqbOKPrefixSecond. + From elpi.apps Require Import derive.eqbOK. + + Import test_derive_corelib.Mutual.Tree. + + #[only(param1,param1_functor,param1_inhab,induction,eqType_ast,tag,fields,eqb,eqbcorrect,eqbOK), prefix="custom_"] derive forest. + + Redirect "tmp" Check tree_eqb_OK. + Redirect "tmp" Check tree_eqb_OK_sumbool. + Redirect "tmp" Check custom_eqb_OK. + Redirect "tmp" Check custom_eqb_OK_sumbool. +End EqbOKPrefixSecond. + +Module EqbOKChainVisibility. + From elpi.apps Require Import derive.eqbOK. + + Import test_derive_corelib.Mutual.Tree. + + #[only(param1,param1_functor,param1_inhab,induction,eqType_ast,tag,fields,eqb,eqbcorrect,eqbOK)] derive forest. + + Redirect "tmp" Check tree_eqb_correct. + Redirect "tmp" Check forest_eqb_correct. + Redirect "tmp" Check tree_eqb_OK. + Redirect "tmp" Check forest_eqb_OK. +End EqbOKChainVisibility. + +Module EqbOKTripleFromBeta. + From elpi.apps Require Import derive.eqbOK. + + Import test_derive_corelib.Mutual.CyclicTriple. + + #[only(param1,param1_functor,param1_inhab,induction,eqType_ast,tag,fields,eqb,eqbcorrect,eqbOK)] derive beta. + + Redirect "tmp" Check alpha_eqb_OK. + Redirect "tmp" Check beta_eqb_OK. + Redirect "tmp" Check gamma_eqb_OK. + Redirect "tmp" Check alpha_eqb_OK_sumbool. + Redirect "tmp" Check beta_eqb_OK_sumbool. + Redirect "tmp" Check gamma_eqb_OK_sumbool. +End EqbOKTripleFromBeta. + +Module EqbOKTripleFromGamma. + From elpi.apps Require Import derive.eqbOK. + + Import test_derive_corelib.Mutual.CyclicTriple. + + #[only(param1,param1_functor,param1_inhab,induction,eqType_ast,tag,fields,eqb,eqbcorrect,eqbOK)] derive gamma. + + Redirect "tmp" Check alpha_eqb_OK. + Redirect "tmp" Check beta_eqb_OK. + Redirect "tmp" Check gamma_eqb_OK. +End EqbOKTripleFromGamma. diff --git a/apps/derive/tests/test_eqbcorrect.v b/apps/derive/tests/test_eqbcorrect.v index dff9f016f..71e550105 100644 --- a/apps/derive/tests/test_eqbcorrect.v +++ b/apps/derive/tests/test_eqbcorrect.v @@ -51,11 +51,11 @@ Elpi derive.eqbcorrect ord. Elpi derive.eqbcorrect ord2. Elpi derive.eqbcorrect val. Elpi derive.eqbcorrect alias. -Fail Elpi derive.eqbcorrent mempty. -Fail Elpi derive.eqbcorrent munit. -Fail Elpi derive.eqbcorrent mpeano. -Fail Elpi derive.eqbcorrent moption. -Fail Elpi derive.eqbcorrent mtree. +Elpi derive.eqbcorrect mempty. +Elpi derive.eqbcorrect munit. +Elpi derive.eqbcorrect mpeano. +Fail Elpi derive.eqbcorrect moption. +Fail Elpi derive.eqbcorrect mtree. End Coverage. @@ -76,3 +76,47 @@ Redirect "tmp" Check val_eqb_refl : eqb_reflexive val_eqb. Redirect "tmp" Check alias_eqb_correct : eqb_correct alias_eqb. Redirect "tmp" Check alias_eqb_refl : eqb_reflexive alias_eqb. + +Module EqbCorrectStandaloneFirst. + + Import test_derive_corelib.Mutual.Tree. + + Elpi derive.eqType.ast tree. + Elpi derive.tag tree. + Elpi derive.fields tree. + Elpi derive.param1 tree. + Elpi derive.param1.functor is_tree. + Elpi derive.induction tree. + Elpi derive.param1.inhab is_tree. + Elpi derive.eqb tree. + Elpi derive.eqbcorrect tree. + + Redirect "tmp" Check tree_eqb_correct. + Redirect "tmp" Check tree_eqb_refl. + Redirect "tmp" Check forest_eqb_correct. + Redirect "tmp" Check forest_eqb_refl. + Redirect "tmp" Elpi Query derive.eqbcorrect lp:{{ + eqcorrect-for {{:gref tree}} _ _, + eqcorrect-for {{:gref forest}} _ _ + }}. +End EqbCorrectStandaloneFirst. + +Module EqbCorrectStandaloneSecond. + + Import test_derive_corelib.Mutual.Tree. + + Elpi derive.eqType.ast tree. + Elpi derive.tag tree. + Elpi derive.fields tree. + Elpi derive.param1 tree. + Elpi derive.param1.functor is_tree. + Elpi derive.induction tree. + Elpi derive.param1.inhab is_tree. + Elpi derive.eqb tree. + Elpi derive.eqbcorrect forest. + + Redirect "tmp" Check tree_eqb_correct. + Redirect "tmp" Check tree_eqb_refl. + Redirect "tmp" Check forest_eqb_correct. + Redirect "tmp" Check forest_eqb_refl. +End EqbCorrectStandaloneSecond. diff --git a/apps/derive/tests/test_fields.v b/apps/derive/tests/test_fields.v index 92541c1e2..04887b447 100644 --- a/apps/derive/tests/test_fields.v +++ b/apps/derive/tests/test_fields.v @@ -1,4 +1,4 @@ -From elpi.apps Require Import derive.fields. +From elpi.apps Require Import derive derive.fields. From elpi.apps.derive.tests Require Import test_derive_corelib test_eqType_ast test_tag. Import test_derive_corelib.Coverage test_eqType_ast.Coverage test_tag.Coverage. @@ -162,3 +162,103 @@ Redirect "tmp" Check val_fields : forall i : val, val_fields_t (val_tag i). Redirect "tmp" Check val_construct : forall (p: Numbers.BinNums.positive), val_fields_t p -> Datatypes.option val. Redirect "tmp" Check val_constructP : forall (v:val), val_construct (val_tag v) (val_fields v) = Datatypes.Some v. +Module FieldsStandaloneFirst. + From elpi.apps Require Import derive.fields. + + Import test_derive_corelib.Mutual.NonRecursive. + + Elpi derive.eqType.ast color. + Elpi derive.tag color. + Elpi derive.fields color. + + Redirect "tmp" Check color_fields_t. + Redirect "tmp" Check color_fields. + Redirect "tmp" Check color_construct. + Redirect "tmp" Check shape_fields_t. + Redirect "tmp" Check shape_fields. + Redirect "tmp" Check shape_construct. + Redirect "tmp" Elpi Query derive.fields lp:{{ + coq.locate "color" (indt C), + coq.locate "shape" (indt S), + fields-for C _ _ _ _, + fields-for S _ _ _ _ + }}. +End FieldsStandaloneFirst. + +Module FieldsStandaloneSecond. + From elpi.apps Require Import derive.fields. + + Import test_derive_corelib.Mutual.NonRecursive. + + Elpi derive.eqType.ast color. + Elpi derive.tag color. + Elpi derive.fields shape. + + Redirect "tmp" Check color_fields_t. + Redirect "tmp" Check color_fields. + Redirect "tmp" Check color_construct. + Redirect "tmp" Check shape_fields_t. + Redirect "tmp" Check shape_fields. + Redirect "tmp" Check shape_construct. +End FieldsStandaloneSecond. + +Module FieldsMetaFirst. + From elpi.apps Require Import derive.fields. + + Import test_derive_corelib.Mutual.NonRecursive. + + #[only(eqType_ast,tag,fields)] derive color. + + Redirect "tmp" Check color_fields_t. + Redirect "tmp" Check color_fields. + Redirect "tmp" Check color_construct. + Redirect "tmp" Check shape_fields_t. + Redirect "tmp" Check shape_fields. + Redirect "tmp" Check shape_construct. +End FieldsMetaFirst. + +Module FieldsMetaSecond. + From elpi.apps Require Import derive.fields. + + Import test_derive_corelib.Mutual.NonRecursive. + + #[only(eqType_ast,tag,fields)] derive shape. + + Redirect "tmp" Check color_fields_t. + Redirect "tmp" Check color_fields. + Redirect "tmp" Check color_construct. + Redirect "tmp" Check shape_fields_t. + Redirect "tmp" Check shape_fields. + Redirect "tmp" Check shape_construct. +End FieldsMetaSecond. + +Module FieldsPrefixSecond. + From elpi.apps Require Import derive.fields. + + Import test_derive_corelib.Mutual.Tree. + + #[only(eqType_ast,tag,fields), prefix="custom_"] derive forest. + + Redirect "tmp" Check tree_fields_t. + Redirect "tmp" Check tree_fields. + Redirect "tmp" Check tree_construct. + Redirect "tmp" Check custom_fields_t. + Redirect "tmp" Check custom_fields. + Redirect "tmp" Check custom_construct. +End FieldsPrefixSecond. + +Module FieldsParametrized. + From elpi.apps Require Import derive.fields. + + Import test_derive_corelib.Mutual.ParametrizedTree. + + #[only(eqType_ast,tag,fields)] derive pforest. + + Redirect "tmp" Check ptree_fields_t. + Redirect "tmp" Check ptree_fields. + Redirect "tmp" Check ptree_construct. + Redirect "tmp" Check pforest_fields_t. + Redirect "tmp" Check pforest_fields. + Redirect "tmp" Check pforest_construct. +End FieldsParametrized. + diff --git a/apps/derive/tests/test_induction.v b/apps/derive/tests/test_induction.v index 83951b567..817b68d6f 100644 --- a/apps/derive/tests/test_induction.v +++ b/apps/derive/tests/test_induction.v @@ -1,4 +1,4 @@ -From elpi.apps Require Import derive.induction. +From elpi.apps Require Import derive derive.induction. From elpi.apps Require Import test_derive_corelib test_param1 test_param1_functor. @@ -75,5 +75,74 @@ Redirect "tmp" Check sigma_bool_induction. Redirect "tmp" Check sigma_bool2_induction. Redirect "tmp" Check ord_induction : forall p Pp P, (forall n Pn l, is_eq bool is_bool (is_leq n p) (is_is_leq n Pn p Pp) true is_true l -> P (mkOrd p n l)) -> forall (o : ord p), is_ord p Pp o -> P o. Redirect "tmp" Check ord2_induction : forall p Pp P, (forall (o1 : ord p), is_ord p Pp o1 -> forall (o2 : ord p), is_ord p Pp o2 -> P (mkOrd2 p o1 o2)) -> forall (o : ord2 p), is_ord2 p Pp o -> P o. -Fail Redirect "tmp" Check mpeano'_induction. -Fail Redirect "tmp" Check mforest_induction. \ No newline at end of file + +Module InductionStandaloneFirst. + From elpi.apps Require Import derive.induction. + + Import test_derive_corelib.Mutual.Tree. + + Elpi derive.param1 tree. + Elpi derive.param1.functor is_tree. + Elpi derive.induction tree. + + Redirect "tmp" Check tree_induction. + Redirect "tmp" Check forest_induction. +End InductionStandaloneFirst. + +Module InductionStandaloneSecond. + From elpi.apps Require Import derive.induction. + + Import test_derive_corelib.Mutual.Tree. + + Elpi derive.param1 tree. + Elpi derive.param1.functor is_tree. + Elpi derive.induction forest. + + Redirect "tmp" Check tree_induction. + Redirect "tmp" Check forest_induction. +End InductionStandaloneSecond. + +Module InductionMetaFirst. + From elpi.apps Require Import derive.induction. + + Import test_derive_corelib.Mutual.Tree. + + #[only(param1,param1_functor,induction)] derive tree. + + Redirect "tmp" Check tree_induction. + Redirect "tmp" Check forest_induction. +End InductionMetaFirst. + +Module InductionMetaSecond. + From elpi.apps Require Import derive.induction. + + Import test_derive_corelib.Mutual.Tree. + + #[only(param1,param1_functor,induction)] derive forest. + + Redirect "tmp" Check tree_induction. + Redirect "tmp" Check forest_induction. +End InductionMetaSecond. + +Module InductionParametrized. + From elpi.apps Require Import derive.induction. + + Import test_derive_corelib.Mutual.ParametrizedTree. + + #[only(param1,param1_functor,induction)] derive pforest. + + Redirect "tmp" Check ptree_induction. + Redirect "tmp" Check pforest_induction. +End InductionParametrized. + +Module InductionIndexed. + From elpi.apps Require Import derive.induction. + + Import test_derive_corelib.Mutual.Indexed. + + Elpi derive.param1 nat. + #[only(param1,param1_functor,induction)] derive iforest. + + Redirect "tmp" Check itree_induction. + Redirect "tmp" Check iforest_induction. +End InductionIndexed. diff --git a/apps/derive/tests/test_lens.v b/apps/derive/tests/test_lens.v index bf2e887c6..8faddbc63 100644 --- a/apps/derive/tests/test_lens.v +++ b/apps/derive/tests/test_lens.v @@ -1,4 +1,4 @@ -From elpi.apps Require Import test_derive_corelib derive.lens. +From elpi.apps Require Import test_derive_corelib derive derive.lens. Import test_derive_corelib.Coverage. @@ -58,3 +58,14 @@ Proof. rewrite Hpr. reflexivity. Qed. + +Module LensMutualSkip. + From elpi.apps Require Import derive.lens. + + Import test_derive_corelib.Mutual.Tree. + + #[only(lens)] derive tree. + + Fail Check tree_lens. + Fail Check forest_lens. +End LensMutualSkip. diff --git a/apps/derive/tests/test_lens_laws.v b/apps/derive/tests/test_lens_laws.v index a2b251fe6..ec3ba0b1b 100644 --- a/apps/derive/tests/test_lens_laws.v +++ b/apps/derive/tests/test_lens_laws.v @@ -1,5 +1,5 @@ -From elpi.apps Require Import derive.lens_laws. +From elpi.apps Require Import derive derive.lens_laws. From elpi.apps Require Import test_derive_corelib test_lens. @@ -45,3 +45,16 @@ Redirect "tmp" Check _f4_f3_exchange : forall A, exchange (_f4 A) (_f3 A). Redirect "tmp" Check _pf3_pf4_exchange : forall A, exchange (_pf3 A) (_pf4 A). Redirect "tmp" Check _pf4_pf3_exchange : forall A, exchange (_pf4 A) (_pf3 A). +Module LensLawsMutualSkip. + From elpi.apps Require Import derive.lens_laws. + + Import test_derive_corelib.Mutual.Tree. + + #[only(lens,lens_laws)] derive tree. + + Fail Check tree_lens. + Fail Check forest_lens. + Fail Check tree_lens_view_set. + Fail Check forest_lens_view_set. +End LensLawsMutualSkip. + diff --git a/apps/derive/tests/test_param1_congr.v b/apps/derive/tests/test_param1_congr.v index 625933ff9..a0deb0efc 100644 --- a/apps/derive/tests/test_param1_congr.v +++ b/apps/derive/tests/test_param1_congr.v @@ -1,4 +1,4 @@ -From elpi.apps Require Import derive.param1_congr. +From elpi.apps Require Import derive derive.param1_congr. From elpi.apps Require Import test_derive_corelib test_param1. Import test_derive_corelib.Coverage. @@ -93,6 +93,64 @@ Redirect "tmp" Check congr_is_Build_pa_record : forall A PA n p1 p2, p1 = p2 -> Redirect "tmp" Check congr_is_Build_pr_record : forall A pr n p1 p2, p1 = p2 -> forall b q1 q2, q1 = q2 -> is_Build_pr_record A pr n p1 b q1= is_Build_pr_record A pr n p2 b q2. Redirect "tmp" Check congr_is_E1 : is_E1 = is_E1. +Module MutualStandaloneFirst. + From elpi.apps Require Import derive.param1_congr. -Fail Redirect "tmp" Check congr_is_mpeano'. -Fail Redirect "tmp" Check congr_is_mforest. \ No newline at end of file + Import test_derive_corelib.Mutual.Tree. + + Elpi derive.param1 tree. + Elpi derive.param1.congr is_tree. + + Redirect "tmp" Check congr_is_node. + Redirect "tmp" Check congr_is_empty. + Redirect "tmp" Check congr_is_cons. +End MutualStandaloneFirst. + +Module MutualStandaloneSecond. + From elpi.apps Require Import derive.param1_congr. + + Import test_derive_corelib.Mutual.Tree. + + Elpi derive.param1 tree. + Elpi derive.param1.congr is_forest. + + Redirect "tmp" Check congr_is_node. + Redirect "tmp" Check congr_is_empty. + Redirect "tmp" Check congr_is_cons. +End MutualStandaloneSecond. + +Module MutualMetaFirst. + From elpi.apps Require Import derive.param1_congr. + + Import test_derive_corelib.Mutual.Tree. + + #[only(param1,param1_congr)] derive tree. + + Redirect "tmp" Check congr_is_node. + Redirect "tmp" Check congr_is_empty. + Redirect "tmp" Check congr_is_cons. +End MutualMetaFirst. + +Module MutualMetaSecond. + From elpi.apps Require Import derive.param1_congr. + + Import test_derive_corelib.Mutual.Tree. + + #[only(param1,param1_congr)] derive forest. + + Redirect "tmp" Check congr_is_node. + Redirect "tmp" Check congr_is_empty. + Redirect "tmp" Check congr_is_cons. +End MutualMetaSecond. + +Module ParametrizedMutual. + From elpi.apps Require Import derive.param1_congr. + + Import test_derive_corelib.Mutual.ParametrizedTree. + + #[only(param1,param1_congr)] derive ptree. + + Redirect "tmp" Check congr_is_pnode. + Redirect "tmp" Check congr_is_pempty. + Redirect "tmp" Check congr_is_pcons. +End ParametrizedMutual. diff --git a/apps/derive/tests/test_param1_trivial.v b/apps/derive/tests/test_param1_trivial.v index 8745df116..081c9e773 100644 --- a/apps/derive/tests/test_param1_trivial.v +++ b/apps/derive/tests/test_param1_trivial.v @@ -1,4 +1,4 @@ -From elpi.apps Require Import derive.param1_trivial. +From elpi.apps Require Import derive derive.param1_trivial. From elpi.apps Require Import test_derive_corelib test_param1 test_param1_congr. Import derive.param1. (* for is_eq *) @@ -46,9 +46,9 @@ Elpi derive.param1.trivial is_val. Elpi derive.param1.trivial is_alias. Elpi derive.param1.trivial is_mempty. Elpi derive.param1.trivial is_munit. -Fail Elpi derive.param1.trivial is_mpeano. -Fail Elpi derive.param1.trivial is_moption. -Fail Elpi derive.param1.trivial is_mtree. +Elpi derive.param1.trivial is_mpeano. +Elpi derive.param1.trivial is_moption. +Elpi derive.param1.trivial is_mtree. End Coverage. @@ -113,3 +113,78 @@ Redirect "tmp" Check is_ord2_inhab : forall p px, full (ord2 p) (is_ord2 p px). Redirect "tmp" Check is_val_inhab : full val is_val. Redirect "tmp" Check is_alias_inhab : full alias is_alias. + +Redirect "tmp" Check is_mempty_trivial : trivial mempty is_mempty. +Redirect "tmp" Check is_munit_trivial : trivial munit is_munit. +Redirect "tmp" Check is_mpeano_trivial : trivial mpeano is_mpeano. +Redirect "tmp" Check is_moption_trivial : trivial moption is_moption. +Redirect "tmp" Check is_mtree_trivial : trivial mtree is_mtree. + +Redirect "tmp" Check is_mempty_inhab : inhab mempty is_mempty. +Redirect "tmp" Check is_munit_inhab : inhab munit is_munit. +Redirect "tmp" Check is_mpeano_inhab : inhab mpeano is_mpeano. +Redirect "tmp" Check is_moption_inhab : inhab moption is_moption. +Redirect "tmp" Check is_mtree_inhab : inhab mtree is_mtree. + +Module InhabStandaloneFirst. + + Import test_derive_corelib.Mutual.Tree. + + Elpi derive.param1 tree. + Elpi derive.param1.inhab is_tree. + + Redirect "tmp" Check is_tree_inhab : forall x : tree, is_tree x. + Redirect "tmp" Check is_forest_inhab : forall x : forest, is_forest x. +End InhabStandaloneFirst. + +Module InhabStandaloneSecond. + + Import test_derive_corelib.Mutual.Tree. + + Elpi derive.param1 tree. + Elpi derive.param1.inhab is_forest. + + Redirect "tmp" Check is_tree_inhab : forall x : tree, is_tree x. + Redirect "tmp" Check is_forest_inhab : forall x : forest, is_forest x. +End InhabStandaloneSecond. + +Module TrivialStandaloneFirst. + + Import test_derive_corelib.Mutual.Tree. + + Elpi derive.param1 tree. + Elpi derive.param1.congr is_tree. + Elpi derive.param1.trivial is_tree. + + Redirect "tmp" Check is_tree_inhab : forall x : tree, is_tree x. + Redirect "tmp" Check is_forest_inhab : forall x : forest, is_forest x. + Redirect "tmp" Check is_tree_trivial. + Redirect "tmp" Check is_forest_trivial. +End TrivialStandaloneFirst. + +Module TrivialStandaloneSecond. + + Import test_derive_corelib.Mutual.Tree. + + Elpi derive.param1 tree. + Elpi derive.param1.congr is_tree. + Elpi derive.param1.trivial is_forest. + + Redirect "tmp" Check is_tree_inhab : forall x : tree, is_tree x. + Redirect "tmp" Check is_forest_inhab : forall x : forest, is_forest x. + Redirect "tmp" Check is_tree_trivial. + Redirect "tmp" Check is_forest_trivial. +End TrivialStandaloneSecond. + +Module TrivialParametrizedFail. + + Import test_derive_corelib.Mutual.ParametrizedTree. + + Elpi derive.param1 tree. + Elpi derive.param1.congr is_tree. + Elpi derive.param1.trivial is_forest. + + Redirect "tmp" Check is_tree_trivial. + Redirect "tmp" Check is_forest_trivial. + +End TrivialParametrizedFail. diff --git a/apps/derive/tests/test_param2.v b/apps/derive/tests/test_param2.v index ed6f05562..a10d37aea 100644 --- a/apps/derive/tests/test_param2.v +++ b/apps/derive/tests/test_param2.v @@ -1,4 +1,5 @@ -From elpi.apps Require Import derive.param2. +From elpi.apps Require Import derive derive.param2. +From elpi.apps.derive.tests Require Import test_derive_corelib. Set Uniform Inductive Parameters. @@ -130,12 +131,6 @@ Inductive RenamedParam (n : nat) := renamedParam (_ : unit). Arguments renamedParam m t : rename. Elpi derive.param2 RenamedParam. -Fail Elpi derive.param2 mempty. -Fail Elpi derive.param2 munit. -Fail Elpi derive.param2 mpeano. -Fail Elpi derive.param2 moption. -Fail Elpi derive.param2 mtree. - Record Box (A : Type) := mkBox { unbox : A @@ -158,3 +153,82 @@ Definition boxP := mkBoxP. Elpi derive.param2 boxP. Unset Primitive Projections. + +Module MutualCoreTests. + +Import test_derive_corelib.Coverage. +Import test_derive_corelib.Mutual.Dependency. + +Elpi derive.param2 mempty. +Redirect "tmp" Check mempty_R : mempty -> mempty -> Type. +Redirect "tmp" Check mempty'_R : mempty' -> mempty' -> Type. + +Elpi derive.param2 munit. +Redirect "tmp" Check munit_R : munit -> munit -> Type. +Redirect "tmp" Check munit'_R : munit' -> munit' -> Type. + +Elpi derive.param2 mpeano. +Redirect "tmp" Check mpeano_R : mpeano -> mpeano -> Type. +Redirect "tmp" Check mpeano'_R : mpeano' -> mpeano' -> Type. + +Elpi derive.param2 moption. +Redirect "tmp" Check moption_R : forall A A1, (A -> A1 -> Type) -> moption A -> moption A1 -> Type. +Redirect "tmp" Check moption'_R : forall A A1, (A -> A1 -> Type) -> moption' A -> moption' A1 -> Type. + +Elpi derive.param2 mtree. +Redirect "tmp" Check mtree_R : forall A A1, (A -> A1 -> Type) -> mtree A -> mtree A1 -> Type. +Redirect "tmp" Check mforest_R : forall A A1, (A -> A1 -> Type) -> mforest A -> mforest A1 -> Type. + +Elpi derive.param2 a. +Elpi derive.param2 c. +Redirect "tmp" Check c_R : c -> c -> Type. + +End MutualCoreTests. + +Module MutualCoreNonFirst. + From elpi.apps Require Import derive.param2. + + Import test_derive_corelib.Mutual.Tree. + + Elpi derive.param2 forest. + + Redirect "tmp" Check tree_R : tree -> tree -> Type. + Redirect "tmp" Check forest_R : forest -> forest -> Type. + Redirect "tmp" Check node_R. + Redirect "tmp" Check empty_R. + Redirect "tmp" Check cons_R. + Redirect "tmp" Elpi Query derive.param2 lp:{{ + param.gref {{:gref tree}} {{:gref tree}} _, + param.gref {{:gref forest}} {{:gref forest}} _ + }}. +End MutualCoreNonFirst. + +Module MutualMetaFirst. + From elpi.apps Require Import derive.param2. + + Import test_derive_corelib.Mutual.Tree. + + #[only(param2)] derive tree. + + Redirect "tmp" Check tree_R : tree -> tree -> Type. + Redirect "tmp" Check forest_R : forest -> forest -> Type. + Redirect "tmp" Elpi Query derive.param2 lp:{{ + param.gref {{:gref tree}} {{:gref tree}} _, + param.gref {{:gref forest}} {{:gref forest}} _ + }}. +End MutualMetaFirst. + +Module MutualMetaSecond. + From elpi.apps Require Import derive.param2. + + Import test_derive_corelib.Mutual.Tree. + + #[only(param2)] derive forest. + + Redirect "tmp" Check tree_R : tree -> tree -> Type. + Redirect "tmp" Check forest_R : forest -> forest -> Type. + Redirect "tmp" Elpi Query derive.param2 lp:{{ + param.gref {{:gref tree}} {{:gref tree}} _, + param.gref {{:gref forest}} {{:gref forest}} _ + }}. +End MutualMetaSecond. diff --git a/apps/derive/theories/derive/bcongr.v b/apps/derive/theories/derive/bcongr.v index 52b5fd12c..3b9134488 100644 --- a/apps/derive/theories/derive/bcongr.v +++ b/apps/derive/theories/derive/bcongr.v @@ -42,11 +42,19 @@ Elpi Accumulate Db derive.projK.db. Elpi Accumulate File injection. Elpi Accumulate File bcongr. Elpi Accumulate lp:{{ + func derive.bcongr.standalone-main inductive, string -> list prop. + derive.bcongr.standalone-main T Prefix C :- + coq.mutual? T, !, + coq.mutual.members T TS, + std.map TS (t\c\ sigma p\ derive.mutual.selected-prefix T Prefix t p, derive.bcongr.main t p c) CS, + std.flatten CS C. + derive.bcongr.standalone-main T Prefix C :- derive.bcongr.main T Prefix C. + main [str I] :- !, coq.locate I (indt GR), coq.gref->id (indt GR) Tname, Prefix is Tname ^ "_", - derive.bcongr.main GR Prefix _. + derive.bcongr.standalone-main GR Prefix _. main _ :- usage. usage :- coq.error "Usage: derive.bcongr ". @@ -69,7 +77,14 @@ dep1 "bcongr" "projK". }}. Elpi Accumulate derive lp:{{ + +func derive.bcongr.derive-main inductive, string -> list prop. +derive.bcongr.derive-main T Prefix C :- coq.mutual? T, !, + coq.mutual.members T TS, + std.map TS (t\c\ sigma p\ derive.mutual.selected-prefix T Prefix t p, derive.bcongr.main t p c) CS, + std.flatten CS C. +derive.bcongr.derive-main T Prefix C :- derive.bcongr.main T Prefix C. -derivation (indt T) N ff (derive "bcongr" (derive.bcongr.main T N) (derive.exists-indc T (K\bcongr-db K _))). +derivation (indt T) N ff (derive "bcongr" (derive.bcongr.derive-main T N) (derive.exists-indc T (K\bcongr-db K _))). }}. diff --git a/apps/derive/theories/derive/eqbOK.v b/apps/derive/theories/derive/eqbOK.v index 4135e2aa4..a5dfebf57 100644 --- a/apps/derive/theories/derive/eqbOK.v +++ b/apps/derive/theories/derive/eqbOK.v @@ -50,11 +50,19 @@ Elpi Accumulate Db derive.eqbOK.db. Elpi Accumulate File eqbOK. Elpi Accumulate File eqType. Elpi Accumulate lp:{{ + func derive.eqbOK.standalone-main gref, string -> list prop. + derive.eqbOK.standalone-main (indt T) Prefix C :- + coq.mutual? T, !, + coq.mutual.members T TS, + std.map TS (t\c\ sigma p\ derive.mutual.selected-prefix T Prefix t p, derive.eqbOK.main (indt t) p c) CS, + std.flatten CS C. + derive.eqbOK.standalone-main T Prefix C :- derive.eqbOK.main T Prefix C. + main [str I] :- !, coq.locate I GR, coq.gref->id GR Tname, Prefix is Tname ^ "_", - derive.eqbOK.main GR Prefix _. + derive.eqbOK.standalone-main GR Prefix _. main _ :- usage. @@ -78,8 +86,15 @@ dep1 "eqbOK_alias" "eqbcorrect_alias". Elpi Accumulate derive lp:{{ -derivation (indt T) Prefix ff (derive "eqbOK" (derive.eqbOK.main (indt T) Prefix) (eqbok-for (indt T) _)). -derivation (const T) Prefix ff (derive "eqbOK_alias" (derive.eqbOK.main (const T) Prefix) (eqbok-for (const T) _)). +func derive.eqbOK.derive-main gref, string -> list prop. +derive.eqbOK.derive-main (indt T) Prefix C :- coq.mutual? T, !, + coq.mutual.members T TS, + std.map TS (t\c\ sigma p\ derive.mutual.selected-prefix T Prefix t p, derive.eqbOK.main (indt t) p c) CS, + std.flatten CS C. +derive.eqbOK.derive-main T Prefix C :- derive.eqbOK.main T Prefix C. + +derivation (indt T) Prefix ff (derive "eqbOK" (derive.eqbOK.derive-main (indt T) Prefix) (eqbok-for (indt T) _)). +derivation (const T) Prefix ff (derive "eqbOK_alias" (derive.eqbOK.derive-main (const T) Prefix) (eqbok-for (const T) _)). }}. diff --git a/apps/derive/theories/derive/eqbcorrect.v b/apps/derive/theories/derive/eqbcorrect.v index 4e3fddfa5..9bc45a985 100644 --- a/apps/derive/theories/derive/eqbcorrect.v +++ b/apps/derive/theories/derive/eqbcorrect.v @@ -99,6 +99,7 @@ Elpi Accumulate File eqType. Elpi Accumulate Db derive.param1.db. Elpi Accumulate lp:{{ + main [str I] :- !, coq.locate I GR, coq.gref->id GR Tname, diff --git a/apps/derive/theories/derive/fields.v b/apps/derive/theories/derive/fields.v index 5f2021e01..fd30fa657 100644 --- a/apps/derive/theories/derive/fields.v +++ b/apps/derive/theories/derive/fields.v @@ -30,20 +30,28 @@ func box-for constructor -> inductive, constructor. Elpi Command derive.fields. Elpi Accumulate Db Header derive.eqType.db. Elpi Accumulate Db Header derive.tag.db. +Elpi Accumulate File derive_hook. Elpi Accumulate File eqType. Elpi Accumulate Db Header derive.fields.db. -Elpi Accumulate File derive_hook. Elpi Accumulate File fields. Elpi Accumulate Db derive.eqType.db. Elpi Accumulate Db derive.tag.db. Elpi Accumulate Db derive.fields.db. Elpi Accumulate lp:{{ + func derive.fields.standalone-main inductive, string -> list prop. + derive.fields.standalone-main T Prefix C :- + coq.mutual? T, !, + coq.mutual.members T TS, + std.map TS (t\c\ sigma p\ derive.mutual.selected-prefix T Prefix t p, derive.fields.main t p c) CS, + std.flatten CS C. + derive.fields.standalone-main T Prefix C :- derive.fields.main T Prefix C. + main [str I] :- !, coq.locate I (indt GR), coq.gref->id (indt GR) Tname, Prefix is Tname ^ "_", - derive.fields.main GR Prefix _. + derive.fields.standalone-main GR Prefix _. main _ :- usage. @@ -67,6 +75,13 @@ dep1 "fields" "eqType_ast". Elpi Accumulate derive lp:{{ -derivation (indt T) Prefix ff (derive "fields" (derive.fields.main T Prefix) (fields-for T _ _ _ _)). +func derive.fields.derive-main inductive, string -> list prop. +derive.fields.derive-main T Prefix C :- coq.mutual? T, !, + coq.mutual.members T TS, + std.map TS (t\c\ sigma p\ derive.mutual.selected-prefix T Prefix t p, derive.fields.main t p c) CS, + std.flatten CS C. +derive.fields.derive-main T Prefix C :- derive.fields.main T Prefix C. + +derivation (indt T) Prefix ff (derive "fields" (derive.fields.derive-main T Prefix) (fields-for T _ _ _ _)). }}. diff --git a/apps/derive/theories/derive/induction.v b/apps/derive/theories/derive/induction.v index 6433b5534..5fd4c462f 100644 --- a/apps/derive/theories/derive/induction.v +++ b/apps/derive/theories/derive/induction.v @@ -34,9 +34,16 @@ Elpi Accumulate Db derive.param1.functor.db. Elpi Accumulate Db derive.induction.db. Elpi Accumulate File induction. Elpi Accumulate lp:{{ + func derive.induction.standalone-main inductive, string -> list prop. + derive.induction.standalone-main T Prefix C :- + coq.mutual? T, !, + coq.mutual.members T TS, + derive.induction.main-mutual T TS Prefix C. + derive.induction.standalone-main T Prefix C :- derive.induction.main T Prefix C. + main [str I] :- !, coq.locate I (indt GR), Name is {coq.gref->id (indt GR)} ^ "_", - derive.induction.main GR Name _. + derive.induction.standalone-main GR Name _. main _ :- usage. usage :- @@ -58,6 +65,12 @@ dep1 "induction" "param1_functor". Elpi Accumulate derive lp:{{ -derivation (indt T) N ff (derive "induction" (derive.induction.main T N) (induction-db T _)). +func derive.induction.derive-main inductive, string -> list prop. +derive.induction.derive-main T N C :- coq.mutual? T, !, + coq.mutual.members T TS, + derive.induction.main-mutual T TS N C. +derive.induction.derive-main T N C :- derive.induction.main T N C. + +derivation (indt T) N ff (derive "induction" (derive.induction.derive-main T N) (induction-db T _)). }}. diff --git a/apps/derive/theories/derive/lens.v b/apps/derive/theories/derive/lens.v index 431ad70ae..908441431 100644 --- a/apps/derive/theories/derive/lens.v +++ b/apps/derive/theories/derive/lens.v @@ -58,5 +58,9 @@ Elpi Accumulate derive File lens. }}. Elpi Accumulate derive lp:{{ - derivation (indt T) Prefix ff (derive "lens" (derive.lens.main T N) (lens-db T _ _)) :- N is Prefix ^ "_". + func derive.lens.derive-main inductive, string -> list prop. + derive.lens.derive-main T _ [] :- coq.mutual? T, !. + derive.lens.derive-main T N C :- derive.lens.main T N C. + + derivation (indt T) Prefix ff (derive "lens" (derive.lens.derive-main T N) (lens-db T _ _)) :- N is Prefix ^ "_". }}. diff --git a/apps/derive/theories/derive/param1_congr.v b/apps/derive/theories/derive/param1_congr.v index 27105d2c6..25a8f28c4 100644 --- a/apps/derive/theories/derive/param1_congr.v +++ b/apps/derive/theories/derive/param1_congr.v @@ -25,16 +25,27 @@ Elpi Accumulate Db derive.param1.db. Elpi Accumulate Db derive.param1.congr.db. Elpi Accumulate File param1_congr. Elpi Accumulate lp:{{ + func derive.param1.congr.standalone-main inductive, inductive, string -> list prop. + derive.param1.congr.standalone-main GR _IsGR Prefix C :- + coq.mutual? GR, !, + coq.mutual.members GR TS, + std.map TS (t\c\ sigma IsT\ + reali (global (indt t)) (global (indt IsT)), + derive.param1.congr.main (indt t) (indt IsT) Prefix c) CS, + std.flatten CS C. + derive.param1.congr.standalone-main GR IsGR Prefix C :- + derive.param1.congr.main (indt GR) (indt IsGR) Prefix C. + main [str I, str O] :- !, coq.locate I (indt IsGR), realiR T {coq.env.global (indt IsGR)}, coq.env.global (indt GR) T, - derive.param1.congr.main (indt GR) (indt IsGR) O _. + derive.param1.congr.standalone-main GR IsGR O _. main [str I] :- !, coq.locate I (indt IsGR), realiR T {coq.env.global (indt IsGR)}, coq.env.global (indt GR) T, - derive.param1.congr.main (indt GR) (indt IsGR) "congr_" _. + derive.param1.congr.standalone-main GR IsGR "congr_" _. main _ :- usage. usage :- @@ -56,6 +67,13 @@ dep1 "param1_congr" "param1". Elpi Accumulate derive lp:{{ -derivation T _ ff (derive "param1_congr" (derive.on_param1 T derive.param1.congr.main "congr_") (derive.on_param1 T (_\T\_\_\param1-congr-done T) _ _)). +func derive.param1.congr.derive-main gref -> list prop. +derive.param1.congr.derive-main (indt T) C :- coq.mutual? T, !, + coq.mutual.members T TS, + std.map TS (t\c\ derive.on_param1 (indt t) derive.param1.congr.main "congr_" c) CS, + std.flatten CS C. +derive.param1.congr.derive-main T C :- derive.on_param1 T derive.param1.congr.main "congr_" C. + +derivation T _ ff (derive "param1_congr" (derive.param1.congr.derive-main T) (derive.on_param1 T (_\T\_\_\param1-congr-done T) _ _)). }}. diff --git a/apps/derive/theories/derive/param1_trivial.v b/apps/derive/theories/derive/param1_trivial.v index 3ef82fd0b..cfe904981 100644 --- a/apps/derive/theories/derive/param1_trivial.v +++ b/apps/derive/theories/derive/param1_trivial.v @@ -89,11 +89,20 @@ Elpi Accumulate Db derive.param1.trivial.db. Elpi Accumulate File param1_inhab. Elpi Accumulate File param1_trivial. Elpi Accumulate lp:{{ + func derive.param1.trivial.standalone-main gref, gref -> list prop. + derive.param1.trivial.standalone-main (indt GR) _IsGR C :- + coq.mutual? GR, !, + coq.mutual.members GR TS, + derive.param1.inhab.main-mutual TS "_inhab" CL, + CL =!=> derive.param1.trivial.main-mutual TS "_trivial" C. + derive.param1.trivial.standalone-main GR IsGR C :- + derive.param1.inhab.main GR IsGR "_inhab" CL, + CL =!=> derive.param1.trivial.main GR IsGR "_trivial" C. + main [str I] :- coq.locate I IsGR, !, realiR T {coq.env.global IsGR}, coq.env.global GR T, - derive.param1.inhab.main GR IsGR "_inhab" CL, - CL =!=> derive.param1.trivial.main GR IsGR "_trivial" _. + derive.param1.trivial.standalone-main GR IsGR _. main _ :- usage. usage :- @@ -111,10 +120,18 @@ Elpi Accumulate Db derive.param1.congr.db. Elpi Accumulate Db derive.param1.trivial.db. Elpi Accumulate File param1_inhab. Elpi Accumulate lp:{{ + func derive.param1.inhab.standalone-main gref, gref -> list prop. + derive.param1.inhab.standalone-main (indt GR) _IsGR C :- + coq.mutual? GR, !, + coq.mutual.members GR TS, + derive.param1.inhab.main-mutual TS "_inhab" C. + derive.param1.inhab.standalone-main GR IsGR C :- + derive.param1.inhab.main GR IsGR "_inhab" C. + main [str I] :- coq.locate I IsGR, !, realiR T {coq.env.global IsGR}, coq.env.global GR T, - derive.param1.inhab.main GR IsGR "_inhab" _. + derive.param1.inhab.standalone-main GR IsGR _. main _ :- usage. usage :- @@ -266,7 +283,19 @@ dep1 "param1_inhab" "param1". Elpi Accumulate derive lp:{{ -derivation T _ ff (derive "param1_inhab" (derive.on_param1 T derive.param1.inhab.main "_inhab") (derive.on_param1 T (_\T\_\_\param1-inhab-done T) _ _)). -derivation T _ ff (derive "param1_trivial" (derive.on_param1 T derive.param1.trivial.main "_trivial") (derive.on_param1 T (_\T\_\_\param1-trivial-done T) _ _)). +func derive.param1.inhab.derive-main gref -> list prop. +derive.param1.inhab.derive-main (indt T) C :- coq.mutual? T, !, + coq.mutual.members T TS, + derive.param1.inhab.main-mutual TS "_inhab" C. +derive.param1.inhab.derive-main T C :- derive.on_param1 T derive.param1.inhab.main "_inhab" C. + +func derive.param1.trivial.derive-main gref -> list prop. +derive.param1.trivial.derive-main (indt T) C :- coq.mutual? T, !, + coq.mutual.members T TS, + derive.param1.trivial.main-mutual TS "_trivial" C. +derive.param1.trivial.derive-main T C :- derive.on_param1 T derive.param1.trivial.main "_trivial" C. + +derivation T _ ff (derive "param1_inhab" (derive.param1.inhab.derive-main T) (derive.on_param1 T (_\T\_\_\param1-inhab-done T) _ _)). +derivation T _ ff (derive "param1_trivial" (derive.param1.trivial.derive-main T) (derive.on_param1 T (_\T\_\_\param1-trivial-done T) _ _)). }}.