aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--interp/symbols.ml59
-rw-r--r--interp/symbols.mli13
-rw-r--r--parsing/g_basevernac.ml414
-rw-r--r--toplevel/command.ml33
-rw-r--r--toplevel/metasyntax.ml91
-rw-r--r--toplevel/metasyntax.mli2
-rw-r--r--toplevel/vernacentries.ml2
-rw-r--r--toplevel/vernacexpr.ml3
-rw-r--r--translate/ppvernacnew.ml9
9 files changed, 145 insertions, 81 deletions
diff --git a/interp/symbols.ml b/interp/symbols.ml
index ef2cf6b0b..ec93062ee 100644
--- a/interp/symbols.ml
+++ b/interp/symbols.ml
@@ -42,11 +42,15 @@ open Ppextend
type scopes = scope_name list
type level = precedence * precedence list
type delimiters = string
+
type scope = {
- notations: (interpretation * (level * string)) Stringmap.t;
+ notations: (interpretation * string) Stringmap.t;
delimiters: delimiters option
}
+(* Uninterpreted notation map: notation -> level *)
+let notation_level_map = ref Stringmap.empty
+
(* Scopes table: scope_name -> symbol_interpretation *)
let scope_map = ref Stringmap.empty
@@ -204,14 +208,23 @@ let rec find_without_delimiters find ntn_scope = function
(* Can we switch to [scope]? Yes if it has defined delimiters *)
find_with_delimiters ntn_scope
+(* Uninterpreted notation levels *)
+
+let declare_notation_level ntn level =
+ if not !Options.v7 & Stringmap.mem ntn !notation_level_map then
+ error ("Notation "^ntn^" is already assigned a level");
+ notation_level_map := Stringmap.add ntn level !notation_level_map
+
+let level_of_notation ntn =
+ Stringmap.find ntn !notation_level_map
+
(* The mapping between notations and their interpretation *)
-let declare_notation_interpretation ntn scope pat prec df =
+let declare_notation_interpretation ntn scope pat df =
let sc = find_scope scope in
if Stringmap.mem ntn sc.notations && Options.is_verbose () then
warning ("Notation "^ntn^" is already used in scope "^scope);
- let sc =
- { sc with notations = Stringmap.add ntn (pat,(prec,df)) sc.notations } in
+ let sc = { sc with notations = Stringmap.add ntn (pat,df) sc.notations } in
scope_map := Stringmap.add scope sc !scope_map
let declare_uninterpretation rule (metas,c as pat) =
@@ -227,7 +240,7 @@ let rec find_interpretation f = function
let rec interp_notation ntn scopes =
let f scope = fst (Stringmap.find ntn scope.notations) in
try find_interpretation f (scopes @ !scope_stack)
- with Not_found -> anomaly ("Unknown interpretation for notation "^ntn)
+ with Not_found -> error ("Unknown interpretation for notation "^ntn)
let uninterp_notations c =
Gmapl.find (rawconstr_key c) !notations_key_table
@@ -278,20 +291,13 @@ let availability_of_numeral printer_scope scopes =
(* Miscellaneous *)
-let exists_notation_in_scope scope prec ntn r =
+let exists_notation_in_scope scope ntn r =
try
let sc = Stringmap.find scope !scope_map in
- let (r',(prec',_)) = Stringmap.find ntn sc.notations in
- r' = r & prec = prec'
+ let (r',_) = Stringmap.find ntn sc.notations in
+ r' = r
with Not_found -> false
-let exists_notation_prec prec nt sc =
- try fst (snd (Stringmap.find nt sc.notations)) = prec with Not_found -> false
-
-let exists_notation prec nt =
- Stringmap.fold (fun scn sc b -> b or exists_notation_prec prec nt sc)
- !scope_map false
-
(* Exportation of scopes *)
let cache_scope (_,(local,sc)) =
check_scope sc;
@@ -357,7 +363,7 @@ let pr_named_scope prraw scope sc =
str "Scope " ++ str scope ++ fnl ()
++ pr_delimiters_info sc.delimiters ++ fnl ()
++ Stringmap.fold
- (fun ntn ((_,r),(_,df)) strm ->
+ (fun ntn ((_,r),df) strm ->
pr_notation_info prraw df r ++ fnl () ++ strm)
sc.notations (mt ())
@@ -379,7 +385,7 @@ let locate_notation prraw ntn =
Stringmap.fold
(fun scope_name sc l ->
try
- let ((_,r),(_,df)) = Stringmap.find ntn sc.notations in
+ let ((_,r),df) = Stringmap.find ntn sc.notations in
(scope_name,r,df)::l
with Not_found -> l) !scope_map []
in
@@ -396,17 +402,6 @@ let locate_notation prraw ntn =
fnl ()))
l
-let find_notation_level ntn =
- let l =
- Stringmap.fold
- (fun _ sc l ->
- try fst (snd (Stringmap.find ntn sc.notations)) :: l
- with Not_found -> l) !scope_map [] in
- match l with
- | [] -> raise Not_found
- | [prec] -> prec
- | prec::_ -> warning ("Several parsing rules for notation \""^ntn^"\""); prec
-
(**********************************************************************)
(* Mapping notations to concrete syntax *)
@@ -427,11 +422,12 @@ let find_notation_printing_rule ntn =
(* Synchronisation with reset *)
let freeze () =
- (!scope_map, !scope_stack, !arguments_scope, !delimiters_map,
- !notations_key_table, !printing_rules)
+ (!scope_map, !notation_level_map, !scope_stack, !arguments_scope,
+ !delimiters_map, !notations_key_table, !printing_rules)
-let unfreeze (scm,scs,asc,dlm,fkm,pprules) =
+let unfreeze (scm,nlm,scs,asc,dlm,fkm,pprules) =
scope_map := scm;
+ notation_level_map := nlm;
scope_stack := scs;
delimiters_map := dlm;
arguments_scope := asc;
@@ -444,6 +440,7 @@ let init () =
scope_stack := Stringmap.empty
arguments_scope := Refmap.empty
*)
+ notation_level_map := Stringmap.empty;
delimiters_map := Stringmap.empty;
notations_key_table := Gmapl.empty;
printing_rules := Stringmap.empty
diff --git a/interp/symbols.mli b/interp/symbols.mli
index fa3d778f1..4c96d071b 100644
--- a/interp/symbols.mli
+++ b/interp/symbols.mli
@@ -83,7 +83,7 @@ type interp_rule =
| NotationRule of scope_name * notation
| SynDefRule of kernel_name
val declare_notation_interpretation : notation -> scope_name ->
- interpretation -> level -> string -> unit
+ interpretation -> string -> unit
val declare_uninterpretation : interp_rule -> interpretation -> unit
@@ -101,12 +101,16 @@ val uninterp_notations : rawconstr ->
val availability_of_notation : scope_name * notation -> scopes ->
(scope_name option * delimiters option) option
+(*s Declare and test the level of a (possibly uninterpreted) notation *)
+
+val declare_notation_level : notation -> level -> unit
+val level_of_notation : notation -> level (* [Not_found] if no level *)
+
(*s** Miscellaneous *)
(* Checks for already existing notations *)
-val exists_notation_in_scope : scope_name -> level -> notation ->
+val exists_notation_in_scope : scope_name -> notation ->
interpretation-> bool
-val exists_notation : level -> notation -> bool
(* Declares and looks for scopes associated to arguments of a global ref *)
val declare_arguments_scope: global_reference -> scope_name option list -> unit
@@ -117,9 +121,6 @@ val pr_scope : (rawconstr -> std_ppcmds) -> scope_name -> std_ppcmds
val pr_scopes : (rawconstr -> std_ppcmds) -> std_ppcmds
val locate_notation : (rawconstr -> std_ppcmds) -> notation -> std_ppcmds
-(* [raise Not_found] if non existing notation *)
-val find_notation_level : notation -> level
-
(**********************************************************************)
(*s Printing rules for notations *)
diff --git a/parsing/g_basevernac.ml4 b/parsing/g_basevernac.ml4
index 581726891..f64062279 100644
--- a/parsing/g_basevernac.ml4
+++ b/parsing/g_basevernac.ml4
@@ -242,8 +242,18 @@ GEXTEND Gram
VernacSyntax (u,el)
| IDENT "Uninterpreted"; IDENT "Notation"; local = locality; s = STRING;
- l = [ "("; l = LIST1 syntax_modifier SEP ","; ")" -> l | -> [] ]
- -> VernacSyntaxExtension (local,s,l)
+ modl = [ "("; l = LIST1 syntax_modifier SEP ","; ")" -> l | -> [] ];
+ (s8,mv8) =
+ [IDENT "V8only";
+ s8=OPT STRING;
+ mv8=OPT["(";mv8=LIST1 syntax_modifier SEP ","; ")" -> mv8] ->
+ (s8,mv8)
+ | -> (None,None)] ->
+ let s8 = match s8 with Some s -> s | _ -> s in
+ let mv8 = match mv8 with
+ Some mv8 -> mv8
+ | _ -> List.map map_modl modl in
+ VernacSyntaxExtension (local,s,modl,Some(s8,mv8))
| IDENT "Open"; local = locality; IDENT "Scope";
sc = IDENT -> VernacOpenScope (local,sc)
diff --git a/toplevel/command.ml b/toplevel/command.ml
index 337e321df..d9418f58f 100644
--- a/toplevel/command.ml
+++ b/toplevel/command.ml
@@ -214,14 +214,20 @@ let interp_mutual lparams lnamearconstrs finite =
(env0, [], []) lnamearconstrs
in
let lparnames = List.map (fun (na,_,_) -> na) params in
+ let notations =
+ List.map2 (fun (recname,ntnopt,_,_) ar ->
+ option_app (fun df ->
+ let larnames =
+ List.rev_append lparnames
+ (List.map fst (fst (decompose_prod ar))) in
+ (recname,larnames,df)) ntnopt)
+ lnamearconstrs arityl in
let fs = States.freeze() in
- List.iter2 (fun (recname,ntnopt,_,_) ar ->
- option_iter
- (fun (df,scope) ->
- let larnames = lparnames @ List.map fst (fst (decompose_prod ar)) in
- Metasyntax.add_notation_interpretation df
- (AVar recname,larnames) scope) ntnopt)
- lnamearconstrs arityl;
+ (* Declare the notations for the inductive types pushed in local context*)
+ try
+ List.iter (option_iter (fun (recname,larnames,(df,scope)) ->
+ Metasyntax.add_notation_interpretation df
+ (AVar recname,larnames) scope)) notations;
let ind_env_params = push_rel_context params ind_env in
let mispecvec =
List.map2
@@ -238,7 +244,9 @@ let interp_mutual lparams lnamearconstrs finite =
mind_entry_lc = constrs })
(List.rev arityl) lnamearconstrs
in
- { mind_entry_finite = finite; mind_entry_inds = mispecvec }
+ States.unfreeze fs;
+ notations, { mind_entry_finite = finite; mind_entry_inds = mispecvec }
+ with e -> States.unfreeze fs; raise e
let declare_mutual_with_eliminations mie =
let lrecnames =
@@ -277,8 +285,13 @@ let extract_coe_la_lc = function
let build_mutual lind finite =
let (coes,lparams,lnamearconstructs) = extract_coe_la_lc lind in
- let mie = interp_mutual lparams lnamearconstructs finite in
- let _ = declare_mutual_with_eliminations mie in
+ let notations,mie = interp_mutual lparams lnamearconstructs finite in
+ let kn = declare_mutual_with_eliminations mie in
+ (* Declare the notations now bound to the inductive types *)
+ list_iter_i (fun i ->
+ option_iter (fun (_,names,(df,scope)) ->
+ Metasyntax.add_notation_interpretation df
+ (ARef (IndRef (kn,i)),names) scope)) notations;
List.iter
(fun id ->
Class.try_add_new_coercion (locate (make_short_qualid id)) Global) coes
diff --git a/toplevel/metasyntax.ml b/toplevel/metasyntax.ml
index 51a9eec35..1e0077373 100644
--- a/toplevel/metasyntax.ml
+++ b/toplevel/metasyntax.ml
@@ -499,11 +499,25 @@ let make_pp_rule symbols typs n =
(* Syntax extenstion: common parsing/printing rules and no interpretation *)
let cache_syntax_extension (_,(_,prec,ntn,gr,se)) =
- if not (Symbols.exists_notation prec ntn) then begin
+ try
+ let oldprec = Symbols.level_of_notation ntn in
+ if oldprec <> prec then
+ if !Options.v7 then begin
+ Options.if_verbose
+ warning ("Notation "^ntn^" was already assigned a different level");
+ raise Not_found
+ end else
+ error ("Notation "^ntn^" is already assigned a different level")
+ else
+ (* The notation is already declared; no need to redeclare it *)
+ ()
+ with Not_found ->
+ (* Reserve the notation level *)
+ Symbols.declare_notation_level ntn prec;
+ (* Declare the parsing rule *)
Egrammar.extend_grammar (Egrammar.Notation gr);
- if se<>None then
- Symbols.declare_notation_printing_rule ntn (out_some se,fst prec)
- end
+ (* Declare the printing rule *)
+ Symbols.declare_notation_printing_rule ntn (se,fst prec)
let subst_notation_grammar subst x = x
@@ -512,7 +526,7 @@ let subst_printing_rule subst x = x
let subst_syntax_extension (_,subst,(local,prec,ntn,gr,se)) =
(local,prec,ntn,
subst_notation_grammar subst gr,
- option_app (subst_printing_rule subst) se)
+ subst_printing_rule subst se)
let classify_syntax_definition (_,(local,_,_,_,_ as o)) =
if local then Dispose else Substitute o
@@ -602,11 +616,11 @@ let recompute_assoc typs =
| _, Some Gramext.RightA -> Some Gramext.RightA
| _ -> None
-let add_syntax_extension local df modifiers =
+let add_syntax_extension local df modifiers mv8 =
let (assoc,n,etyps,onlyparse) = interp_notation_modifiers modifiers in
let inner = if !Options.v7 then (NumLevel 10,InternalProd) else
(NumLevel 200,InternalProd) in
- let (vars,symbs) = analyse_tokens (split df) in
+ let (_,symbs) = analyse_tokens (split df) in
let typs =
find_symbols
(NumLevel n,BorderProd(true,assoc)) inner
@@ -614,29 +628,45 @@ let add_syntax_extension local df modifiers =
let typs = List.map (set_entry_type etyps) typs in
let assoc = recompute_assoc typs in
let (prec,notation) = make_symbolic n symbs typs in
+ let (ppprec,ppn,pptyps,ppsymbols) =
+ let omodv8 = option_app (fun (s8,ml8) ->
+ let toks8 = split s8 in
+ let im8 = interp_notation_modifiers ml8 in
+ (toks8,im8)) mv8 in
+ match omodv8 with
+ Some(toks8,(a8,n8,typs8,_)) when Options.do_translate() ->
+ let (_,symbols) = analyse_tokens toks8 in
+ let typs =
+ find_symbols
+ (NumLevel n8,BorderProd(true,a8)) (NumLevel 200,InternalProd)
+ (NumLevel n8,BorderProd(false,a8))
+ symbols in
+ let typs = List.map (set_entry_type typs8) typs in
+ let (prec,notation) = make_symbolic n8 symbols typs in
+ (prec, n8, typs, symbols)
+ | _ -> (prec, n, typs, symbs) in
let gram_rule = make_grammar_rule n assoc typs symbs notation in
- let pp_rule = if onlyparse then None else Some (make_pp_rule typs symbs n) in
+ let pp_rule = make_pp_rule pptyps ppsymbols ppn in
Lib.add_anonymous_leaf
- (inSyntaxExtension(local,prec,notation,gram_rule,pp_rule))
+ (inSyntaxExtension(local,ppprec,notation,gram_rule,pp_rule))
(**********************************************************************)
(* Distfix, Infix, Notations *)
(* A notation comes with a grammar rule, a pretty-printing rule, an
identifiying pattern called notation and an associated scope *)
-let load_notation _ (_,(_,_,prec,ntn,scope,pat,onlyparse,_)) =
+let load_notation _ (_,(_,_,ntn,scope,pat,onlyparse,_)) =
Symbols.declare_scope scope
-let open_notation i (_,(_,oldse,prec,ntn,scope,pat,onlyparse,df)) =
-(*print_string ("Open notation "^ntn^" at "^string_of_int (fst prec)^"\n");*)
+let open_notation i (_,(_,oldse,ntn,scope,pat,onlyparse,df)) =
if i=1 then begin
- let b = Symbols.exists_notation_in_scope scope prec ntn pat in
+ let b = Symbols.exists_notation_in_scope scope ntn pat in
(* Declare the old printer rule and its interpretation *)
if not b & oldse <> None then
Esyntax.add_ppobject {sc_univ="constr";sc_entries=out_some oldse};
(* Declare the interpretation *)
if not b then
- Symbols.declare_notation_interpretation ntn scope pat prec df;
+ Symbols.declare_notation_interpretation ntn scope pat df;
if not b & not onlyparse then
Symbols.declare_uninterpretation (NotationRule (scope,ntn)) pat
end
@@ -645,17 +675,16 @@ let cache_notation o =
load_notation 1 o;
open_notation 1 o
-let subst_notation (_,subst,(lc,oldse,prec,ntn,scope,(metas,pat),b,df)) =
+let subst_notation (_,subst,(lc,oldse,ntn,scope,(metas,pat),b,df)) =
(lc,option_app
(list_smartmap (Extend.subst_syntax_entry Ast.subst_astpat subst)) oldse,
- prec,ntn,
- scope,
+ ntn,scope,
(metas,subst_aconstr subst pat), b, df)
-let classify_notation (_,(local,_,_,_,_,_,_,_ as o)) =
+let classify_notation (_,(local,_,_,_,_,_,_ as o)) =
if local then Dispose else Substitute o
-let export_notation (local,_,_,_,_,_,_,_ as o) =
+let export_notation (local,_,_,_,_,_,_ as o) =
if local then None else Some o
let (inNotation, outNotation) =
@@ -718,9 +747,7 @@ let add_notation_in_scope local df c (assoc,n,etyps,onlyparse) omodv8 sc toks =
(prec, n8, typs, symbols)
| _ -> (prec, n, typs, symbols) in
let gram_rule = make_grammar_rule n assoc typs symbols notation in
- let pp_rule =
- if onlyparse then None
- else Some (make_pp_rule pptyps ppsymbols n) in
+ let pp_rule = make_pp_rule pptyps ppsymbols ppn in
Lib.add_anonymous_leaf
(inSyntaxExtension(local,ppprec,notation,gram_rule,pp_rule));
let old_pp_rule =
@@ -732,7 +759,7 @@ let add_notation_in_scope local df c (assoc,n,etyps,onlyparse) omodv8 sc toks =
(* Declare the interpretation *)
let vars = List.map (fun id -> id,[] (* insert the right scope *)) vars in
Lib.add_anonymous_leaf
- (inNotation(local,old_pp_rule,ppprec,notation,scope,a,onlyparse,df))
+ (inNotation(local,old_pp_rule,notation,scope,a,onlyparse,df))
let add_notation local df a modifiers mv8 sc =
let toks = split df in
@@ -760,16 +787,28 @@ let add_notation_interpretation df (c,l) sc =
let scope = match sc with None -> Symbols.default_scope | Some sc -> sc in
let (vars,symbs) = analyse_tokens (split df) in
let notation = make_anon_notation symbs in
- let old_pp_rule = None in
- let prec = Symbols.find_notation_level notation in
+ let prec =
+ try Symbols.level_of_notation notation
+ with Not_found ->
+ error "Parsing rule for this notation has to be previously declared" in
List.iter (check_occur l) vars;
+ let old_pp_rule =
+ let c = match c with AVar id -> RVar (dummy_loc,id)
+ | ARef c -> RRef (dummy_loc,c)
+ | _ -> anomaly "add_notation_interpretation" in
+ let typs = List.map2
+ (fun id n -> id,ETConstr (NumLevel n,InternalProd)) vars (snd prec) in
+ let r = RApp (dummy_loc, c,
+ List.map (function Name id when List.mem id vars -> RVar (dummy_loc,id)
+ | _ -> RHole (dummy_loc,QuestionMark)) l) in
+ Some (make_old_pp_rule (fst prec) symbs typs r notation scope vars) in
let a = AApp (c,List.map (function Name id when List.mem id vars -> AVar id |
_ -> AHole QuestionMark) l) in
let la = List.map (fun id -> id,[]) vars in
let onlyparse = false in
let local = false in
Lib.add_anonymous_leaf
- (inNotation(local,old_pp_rule,prec,notation,scope,(la,a),onlyparse,df))
+ (inNotation(local,old_pp_rule,notation,scope,(la,a),onlyparse,df))
(* TODO add boxes information in the expression *)
diff --git a/toplevel/metasyntax.mli b/toplevel/metasyntax.mli
index 59e786fe3..641db8425 100644
--- a/toplevel/metasyntax.mli
+++ b/toplevel/metasyntax.mli
@@ -44,7 +44,7 @@ val add_notation : locality_flag -> string -> constr_expr
val add_notation_interpretation : string -> (aconstr * Names.name list)
-> scope_name option -> unit
-val add_syntax_extension : locality_flag -> string -> syntax_modifier list -> unit
+val add_syntax_extension : locality_flag -> string -> syntax_modifier list -> (string * syntax_modifier list) option -> unit
val print_grammar : string -> string -> unit
diff --git a/toplevel/vernacentries.ml b/toplevel/vernacentries.ml
index 9b11e6879..bc77424c5 100644
--- a/toplevel/vernacentries.ml
+++ b/toplevel/vernacentries.ml
@@ -1139,7 +1139,7 @@ let interp c = match c with
| VernacSyntax (whatfor,sel) -> vernac_syntax whatfor sel
| VernacTacticGrammar al -> Metasyntax.add_tactic_grammar al
| VernacGrammar (univ,al) -> vernac_grammar univ al
- | VernacSyntaxExtension (local,s,l) -> vernac_syntax_extension local s l
+ | VernacSyntaxExtension (lcl,s,l,l8) -> vernac_syntax_extension lcl s l l8
| VernacDelimiters (sc,lr) -> vernac_delimiters sc lr
| VernacOpenScope sc -> vernac_open_scope sc
| VernacArgumentsScope (qid,scl) -> vernac_arguments_scope qid scl
diff --git a/toplevel/vernacexpr.ml b/toplevel/vernacexpr.ml
index b2f82854c..b68fe7022 100644
--- a/toplevel/vernacexpr.ml
+++ b/toplevel/vernacexpr.ml
@@ -152,7 +152,8 @@ type vernac_expr =
| VernacTacticGrammar of
(string * (string * grammar_production list) * raw_tactic_expr) list
| VernacSyntax of string * raw_syntax_entry list
- | VernacSyntaxExtension of locality_flag * string * syntax_modifier list
+ | VernacSyntaxExtension of locality_flag * string *
+ syntax_modifier list * (string * syntax_modifier list) option
| VernacDistfix of locality_flag *
grammar_associativity * precedence * string * reference *
scope_name option
diff --git a/translate/ppvernacnew.ml b/translate/ppvernacnew.ml
index 161232a5f..49e455cbb 100644
--- a/translate/ppvernacnew.ml
+++ b/translate/ppvernacnew.ml
@@ -474,9 +474,12 @@ let rec pr_vernac = function
(match opt with
| None -> mt()
| Some sc -> str" :" ++ spc() ++ str sc))
- | VernacSyntaxExtension (local,a,b) ->
- str"Uninterpreted Notation" ++ spc() ++ pr_locality local ++ qs a ++
- (match b with | [] -> mt() | _ as l ->
+ | VernacSyntaxExtension (local,s,l,mv8) ->
+ let (s,l) = match mv8 with
+ None -> (s,l)
+ | Some ml -> ml in
+ str"Uninterpreted Notation" ++ spc() ++ pr_locality local ++ qs s ++
+ (match l with | [] -> mt() | _ as l ->
str"(" ++ prlist_with_sep sep_v2 pr_syntax_modifier l ++ str")")
(* Gallina *)