diff options
-rw-r--r-- | interp/constrextern.ml | 99 | ||||
-rw-r--r-- | interp/constrintern.ml | 18 | ||||
-rw-r--r-- | library/impargs.ml | 4 | ||||
-rw-r--r-- | pretyping/constrMatching.ml | 23 | ||||
-rw-r--r-- | test-suite/success/primitiveproj.v | 112 | ||||
-rw-r--r-- | theories/FSets/FMapPositive.v | 4 | ||||
-rw-r--r-- | theories/Init/Datatypes.v | 4 | ||||
-rw-r--r-- | theories/Init/Specif.v | 2 | ||||
-rw-r--r-- | theories/Numbers/Cyclic/DoubleCyclic/DoubleType.v | 2 |
9 files changed, 214 insertions, 54 deletions
diff --git a/interp/constrextern.ml b/interp/constrextern.ml index 6f0491ca1..284bba1b7 100644 --- a/interp/constrextern.ml +++ b/interp/constrextern.ml @@ -437,15 +437,22 @@ let occur_name na aty = | Name id -> occur_var_constr_expr id aty | Anonymous -> false -let is_projection primproj nargs = function - | Some r when not !in_debugger && not !Flags.raw_print && !print_projections -> - if primproj then Some 1 - else +let is_projection primproj nargs cf = + if primproj then Some 1 + else + match cf with + | Some r when not !in_debugger && not !Flags.raw_print && !print_projections -> (try let n = Recordops.find_projection_nparams r + 1 in - if n <= nargs then Some n else None - with Not_found -> None) - | _ -> None + if n <= nargs then + (* For primitive projections, r.(p) and r.(@p) are reserved to the + non-eta-expanded version of the constant, we disallow printing + of the eta-expanded projection as a projection *) + if Environ.is_projection (destConstRef r) (Global.env()) then None + else Some n + else None + with Not_found -> None) + | _ -> None let is_hole = function CHole _ -> true | _ -> false @@ -455,6 +462,8 @@ let is_significant_implicit a = let is_needed_for_correct_partial_application tail imp = List.is_empty tail && not (maximal_insertion_of imp) +exception Expl + (* Implicit args indexes are in ascending order *) (* inctx is useful only if there is a last argument to be deduced from ctxt *) let explicitize loc inctx impl (cf,primproj,f) args = @@ -477,45 +486,60 @@ let explicitize loc inctx impl (cf,primproj,f) args = tail | a::args, _::impl -> (a,None) :: exprec (q+1) (args,impl) | args, [] -> List.map (fun a -> (a,None)) args (*In case of polymorphism*) - | [], _ -> [] in - match is_projection primproj (List.length args) cf with - | Some i as ip -> - if not (List.is_empty impl) && is_status_implicit (List.nth impl (i-1)) then - let args = exprec 1 (args,impl) in - if primproj then CApp (loc, (None, f), args) - else - let f',us = match f with CRef (f,us) -> f,us | _ -> assert false in - CAppExpl (loc,(ip,f',us),List.map fst args) - else - let (args1,args2) = List.chop i args in - let (impl1,impl2) = if List.is_empty impl then [],[] else List.chop i impl in - let args1 = exprec 1 (args1,impl1) in - let args2 = exprec (i+1) (args2,impl2) in - CApp (loc,(Some (List.length args1),f),args1@args2) - | None -> + | [], (imp :: _) when is_status_implicit imp && maximal_insertion_of imp -> + (* The non-explicit application cannot be parsed back with the same type *) + raise Expl + | [], _ -> [] + in + let ip = is_projection primproj (List.length args) cf in + let expl () = + match ip with + | Some i -> + if not (List.is_empty impl) && is_status_implicit (List.nth impl (i-1)) then + if primproj then + let args = exprec 1 (args,impl) in + CApp (loc, (None, f), args) + else raise Expl + else + let (args1,args2) = List.chop i args in + let (impl1,impl2) = if List.is_empty impl then [],[] else List.chop i impl in + let args1 = exprec 1 (args1,impl1) in + let args2 = exprec (i+1) (args2,impl2) in + let len = List.length args1 in + let ip = (* Printing primitive projection as application *) + if len == 1 && primproj && not !print_projections && not !Flags.raw_print then None + else Some len + in + CApp (loc,(ip,f),args1@args2) + | None -> match cf with - | Some (ConstRef p) when not !in_debugger && not primproj && Environ.is_projection p (Global.env ()) -> - (* Eta-expanded version of projection, print explicited if the implicit application would be parsed - as a primitive projection application. *) + | Some (ConstRef p) when not !in_debugger && not primproj + && Environ.is_projection p (Global.env ()) -> + (* Eta-expanded version of projection, print explicited if the implicit + application would be parsed as a primitive projection application. *) let proj = Environ.lookup_projection p (Global.env ()) in - let expl = - if List.length args > proj.Declarations.proj_npars then + if List.length args > proj.Declarations.proj_npars && List.for_all is_status_implicit (List.firstn proj.Declarations.proj_npars impl) - else false - in - if expl then - let f',us = match f with CRef (f,us) -> f,us | _ -> assert false in - CAppExpl (loc,(None,f',us),args) + then raise Expl else let args = exprec 1 (args,impl) in CApp (loc, (None, f), args) | _ -> let args = exprec 1 (args,impl) in if List.is_empty args then f else CApp (loc, (None, f), args) + in + try expl () + with Expl -> + let f',us = match f with CRef (f,us) -> f,us | _ -> assert false in + let ip = if primproj || !print_projections then ip else None in + CAppExpl (loc, (ip, f', us), args) + +let is_start_implicit = function + | imp :: _ -> is_status_implicit imp (* && maximal_insertion_of imp *) + | [] -> false let extern_global loc impl f us = - if not !Constrintern.parsing_explicit && - not (List.is_empty impl) && List.for_all is_status_implicit impl + if not !Constrintern.parsing_explicit && is_start_implicit impl then CAppExpl (loc, (None, f, us), []) else @@ -530,7 +554,10 @@ let extern_app loc inctx impl (cf,primproj,f) us args = (!print_implicits && not !print_implicits_explicit_args)) && List.exists is_status_implicit impl) then - CAppExpl (loc, (is_projection primproj (List.length args) cf,f,us), args) + if primproj then + CAppExpl (loc, (Some 1,f,us), args) + else + CAppExpl (loc, (is_projection primproj (List.length args) cf,f,us), args) else explicitize loc inctx impl (cf,primproj,CRef (f,us)) args diff --git a/interp/constrintern.ml b/interp/constrintern.ml index 7db2203c0..8f250e890 100644 --- a/interp/constrintern.ml +++ b/interp/constrintern.ml @@ -1458,13 +1458,19 @@ let internalize globalenv env allow_patvar lvar c = intern {env with tmp_scope = None; scopes = find_delimiters_scope loc key :: env.scopes} e | CAppExpl (loc, (isproj,ref,us), args) -> - let (f,_,args_scopes,_),_,args = + let (f,_,args_scopes,_),isprojf,args = let args = List.map (fun a -> (a,None)) args in intern_applied_reference intern env (Environ.named_context globalenv) - lvar us args ref in - (* check_projection isproj (List.length args) f; *) - (* Rem: GApp(_,f,[]) stands for @f *) - GApp (loc, f, intern_args env args_scopes (List.map fst args)) + lvar us args ref + in + (match isproj, isprojf with + | Some i, Some (r, n) -> (* Explicit application of primitive projection *) + let scopes = proj_scopes n args_scopes in + let args = intern_args env args_scopes (List.map fst args) in + GApp (loc, GProj (loc, r, List.hd args), List.tl args) + | _ -> + (* Rem: GApp(_,f,[]) stands for @f *) + GApp (loc, f, intern_args env args_scopes (List.map fst args))) | CApp (loc, (isproj,f), args) -> let isproj,f,args = match f with @@ -1737,7 +1743,7 @@ let internalize globalenv env allow_patvar lvar c = match isprojf with | Some (r, n) -> (match projection_implicits n (List.is_empty l) imp with - | Some imp -> + | Some imp -> (* A primitive projection *) let subscopes = proj_scopes n subscopes in let imp = if isproj != None then diff --git a/library/impargs.ml b/library/impargs.ml index 55e21b2c8..355cbe1fa 100644 --- a/library/impargs.ml +++ b/library/impargs.ml @@ -378,7 +378,9 @@ let set_manual_implicits env flags enriching autoimps l = l, imp, m in let imps' = merge (k+1) l' imps in - let m = Option.map (fun (b,f) -> set_maximality imps' b, f) m in + let m = Option.map (fun (b,f) -> + (* match imp with Some Manual -> (b,f) *) + (* | _ -> *)set_maximality imps' b, f) m in Option.map (set_implicit id imp) m :: imps' | (Anonymous,imp)::imps -> let l', forced = try_forced k l in diff --git a/pretyping/constrMatching.ml b/pretyping/constrMatching.ml index e23a4e440..15053505e 100644 --- a/pretyping/constrMatching.ml +++ b/pretyping/constrMatching.ml @@ -209,7 +209,7 @@ let matches_core env sigma convert allow_partial_app allow_bound_rels pat c = sorec stk env subst (PApp(h,Array.append a1 a2)) t | PApp (PMeta meta,args1), App (c2,args2) when allow_partial_app -> - let p = Array.length args2 - Array.length args1 in + (let p = Array.length args2 - Array.length args1 in if p >= 0 then let args21, args22 = Array.chop p args2 in let c = mkApp(c2,args21) in @@ -218,11 +218,18 @@ let matches_core env sigma convert allow_partial_app allow_bound_rels pat c = | None -> subst | Some n -> merge_binding allow_bound_rels stk n c subst in Array.fold_left2 (sorec stk env) subst args1 args22 - else raise PatternMatchingFailure + else (* Might be a projection on the right *) + match kind_of_term c2 with + | Proj _ -> + let subst = sorec stk env subst (PApp (PMeta meta, [|args1.(0)|])) c2 in + Array.fold_left2 (sorec stk env) subst (Array.tl args1) args2 + | _ -> raise PatternMatchingFailure) | PApp (c1,arg1), App (c2,arg2) -> + let diff = Array.length arg2 - Array.length arg1 in (match c1, kind_of_term c2 with - | PRef (ConstRef r), Proj (p,c) -> + (* eta-expanded version of projection against projection *) + | PRef (ConstRef r), Proj (p,c) when eq_constant r p -> let pb = Environ.lookup_projection p env in let npars = pb.Declarations.proj_npars in let narg1 = Array.length arg1 in @@ -232,9 +239,15 @@ let matches_core env sigma convert allow_partial_app allow_bound_rels pat c = try Array.fold_left2 (sorec stk env) subst args arg2 with Invalid_argument _ -> raise PatternMatchingFailure else raise PatternMatchingFailure + (* meta against projection *) + | PMeta meta, Proj (p,c) when diff != 0 -> + if diff == -1 then (* One more arg for the meta *) + Array.fold_left2 (sorec stk env) (sorec stk env subst (PApp (c1, [|arg1.(0)|])) c2) + (Array.tl arg1) arg2 + else raise PatternMatchingFailure | _ -> - (try Array.fold_left2 (sorec stk env) (sorec stk env subst c1 c2) arg1 arg2 - with Invalid_argument _ -> raise PatternMatchingFailure)) + try Array.fold_left2 (sorec stk env) (sorec stk env subst c1 c2) arg1 arg2 + with Invalid_argument _ -> raise PatternMatchingFailure) | PApp (PMeta (Some n), [|c1|]), Proj (p2, c2) -> let ty = Retyping.get_type_of env sigma c2 in diff --git a/test-suite/success/primitiveproj.v b/test-suite/success/primitiveproj.v index 4a9c81eb3..02cb43db0 100644 --- a/test-suite/success/primitiveproj.v +++ b/test-suite/success/primitiveproj.v @@ -61,3 +61,115 @@ Fixpoint yn (n : nat) (y : Y) : Y := Lemma eta_ind' (y: Y) : Some (yn 100 y) = Some {| next := (yn 100 y).(next) |}. Proof. reflexivity. Defined. + + +(* + Rules for parsing and printing of primitive projections and their eta expansions. + If r : R A where R is a primitive record with implicit parameter A. + If p : forall {A} (r : R A) {A : Set}, list (A * B). +*) + +Record R {A : Type} := { p : forall {X : Set}, A * X }. +Arguments R : clear implicits. + +Record R' {A : Type} := { p' : forall X : Set, A * X }. +Arguments R' : clear implicits. + +Unset Printing All. + +Parameter r : R nat. + +Check (r.(p)). +Set Printing Projections. +Check (r.(p)). +Unset Printing Projections. +Set Printing All. +Check (r.(p)). +Unset Printing All. + +(* Check (r.(p)). + Elaborates to a primitive application, X arg implicit. + Of type nat * ?ex + No Printing All: p r + Set Printing Projections.: r.(p) + Printing All: r.(@p) ?ex + *) + +Check p r. +Set Printing Projections. +Check p r. +Unset Printing Projections. +Set Printing All. +Check p r. +Unset Printing All. + +(* Same elaboration, printing for p r *) + +(** Explicit version of the primitive projection, under applied w.r.t implicit arguments + can be printed only using projection notation. r.(@p) *) +Check r.(@p). +Set Printing Projections. +Check r.(@p). +Unset Printing Projections. +Set Printing All. +Check r.(@p). +Unset Printing All. + +(** Explicit version of the primitive projection, applied to its implicit arguments + can be printed only using projection notation r.(p), r.(@p) in fully explicit form *) +Check r.(@p) nat. +Set Printing Projections. +Check r.(@p) nat. +Unset Printing Projections. +Set Printing All. +Check r.(@p) nat. +Unset Printing All. + +Parameter r' : R' nat. + +Check (r'.(p')). +Set Printing Projections. +Check (r'.(p')). +Unset Printing Projections. +Set Printing All. +Check (r'.(p')). +Unset Printing All. + +(* Check (r'.(p')). + Elaborates to a primitive application, X arg explicit. + Of type forall X : Set, nat * X + No Printing All: p' r' + Set Printing Projections.: r'.(p') + Printing All: r'.(p') + *) + +Check p' r'. +Set Printing Projections. +Check p' r'. +Unset Printing Projections. +Set Printing All. +Check p' r'. +Unset Printing All. + +(* Same elaboration, printing for p r *) + +(** Explicit version of the primitive projection, under applied w.r.t implicit arguments + can be printed only using projection notation. r.(@p) *) +Check r'.(@p'). +Set Printing Projections. +Check r'.(@p'). +Unset Printing Projections. +Set Printing All. +Check r'.(@p'). +Unset Printing All. + +(** Explicit version of the primitive projection, applied to its implicit arguments + can be printed only using projection notation r.(p), r.(@p) in fully explicit form *) +Check p' r' nat. +Set Printing Projections. +Check p' r' nat. +Unset Printing Projections. +Set Printing All. +Check p' r' nat. +Unset Printing All. + diff --git a/theories/FSets/FMapPositive.v b/theories/FSets/FMapPositive.v index c9d868c40..3eac15b03 100644 --- a/theories/FSets/FMapPositive.v +++ b/theories/FSets/FMapPositive.v @@ -82,7 +82,7 @@ Module PositiveMap <: S with Module E:=PositiveOrderedTypeBits. Section A. Variable A:Type. - Arguments Leaf [A]. + Arguments Leaf {A}. Definition empty : t A := Leaf. @@ -812,7 +812,7 @@ Module PositiveMap <: S with Module E:=PositiveOrderedTypeBits. Variable A B C : Type. Variable f : option A -> option B -> option C. - Arguments Leaf [A]. + Arguments Leaf {A}. Fixpoint xmap2_l (m : t A) : t C := match m with diff --git a/theories/Init/Datatypes.v b/theories/Init/Datatypes.v index c8d18f766..093a2c140 100644 --- a/theories/Init/Datatypes.v +++ b/theories/Init/Datatypes.v @@ -151,7 +151,7 @@ Inductive option (A:Type) : Type := | Some : A -> option A | None : option A. -Arguments None [A]. +Arguments None {A}. Definition option_map (A B:Type) (f:A->B) (o : option A) : option B := match o with @@ -224,7 +224,7 @@ Inductive list (A : Type) : Type := | nil : list A | cons : A -> list A -> list A. -Arguments nil [A]. +Arguments nil {A}. Infix "::" := cons (at level 60, right associativity) : list_scope. Delimit Scope list_scope with list. Bind Scope list_scope with list. diff --git a/theories/Init/Specif.v b/theories/Init/Specif.v index 1ddb59cf4..c3edcfdfd 100644 --- a/theories/Init/Specif.v +++ b/theories/Init/Specif.v @@ -285,7 +285,7 @@ Section Exc. Definition value := @Some A. Definition error := @None A. End Exc. -Arguments error [A]. +Arguments error {A}. Definition except := False_rec. (* for compatibility with previous versions *) diff --git a/theories/Numbers/Cyclic/DoubleCyclic/DoubleType.v b/theories/Numbers/Cyclic/DoubleCyclic/DoubleType.v index ce1c0bef1..900cb1db5 100644 --- a/theories/Numbers/Cyclic/DoubleCyclic/DoubleType.v +++ b/theories/Numbers/Cyclic/DoubleCyclic/DoubleType.v @@ -53,7 +53,7 @@ Section Zn2Z. End Zn2Z. -Arguments W0 [znz]. +Arguments W0 {znz}. (** From a cyclic representation [w], we iterate the [zn2z] construct [n] times, gaining the type of binary trees of depth at most [n], |