diff options
Diffstat (limited to 'interp')
| -rw-r--r-- | interp/constrexpr_ops.ml | 7 | ||||
| -rw-r--r-- | interp/constrextern.ml | 13 | ||||
| -rw-r--r-- | interp/constrintern.ml | 119 | ||||
| -rw-r--r-- | interp/dumpglob.mli | 1 | ||||
| -rw-r--r-- | interp/modintern.ml | 9 | ||||
| -rw-r--r-- | interp/notation.ml | 272 | ||||
| -rw-r--r-- | interp/notation.mli | 32 | ||||
| -rw-r--r-- | interp/numTok.ml | 188 | ||||
| -rw-r--r-- | interp/numTok.mli | 52 | ||||
| -rw-r--r-- | interp/smartlocate.ml | 16 | ||||
| -rw-r--r-- | interp/syntax_def.ml | 16 | ||||
| -rw-r--r-- | interp/syntax_def.mli | 8 |
12 files changed, 495 insertions, 238 deletions
diff --git a/interp/constrexpr_ops.ml b/interp/constrexpr_ops.ml index d6097304ec..3d99e1d227 100644 --- a/interp/constrexpr_ops.ml +++ b/interp/constrexpr_ops.ml @@ -15,8 +15,8 @@ open Nameops open Libnames open Namegen open Glob_term -open Constrexpr open Notation +open Constrexpr (***********************) (* For binders parsing *) @@ -618,8 +618,9 @@ let interp_univ_constraints env evd cstrs = let cstrs' = Univ.Constraint.add cstr cstrs in try let evd = Evd.add_constraints evd (Univ.Constraint.singleton cstr) in evd, cstrs' - with Univ.UniverseInconsistency e -> - CErrors.user_err ~hdr:"interp_constraint" + with Univ.UniverseInconsistency e as exn -> + let _, info = Exninfo.capture exn in + CErrors.user_err ~hdr:"interp_constraint" ~info (Univ.explain_universe_inconsistency (Termops.pr_evd_level evd) e) in List.fold_left interp (evd,Univ.Constraint.empty) cstrs diff --git a/interp/constrextern.ml b/interp/constrextern.ml index d5a5bde616..63079993c8 100644 --- a/interp/constrextern.ml +++ b/interp/constrextern.ml @@ -19,13 +19,13 @@ open Libnames open Namegen open Impargs open CAst +open Notation open Constrexpr open Constrexpr_ops open Notation_ops open Glob_term open Glob_ops open Pattern -open Notation open Detyping module NamedDecl = Context.Named.Declaration @@ -836,7 +836,7 @@ let rec flatten_application c = match DAst.get c with let same_binder_type ty nal c = match nal, DAst.get c with - | _::_, GProd (_,_,ty',_) -> glob_constr_eq ty ty' + | _::_, (GProd (_,_,ty',_) | GLambda (_,_,ty',_)) -> glob_constr_eq ty ty' | [], _ -> true | _ -> assert false @@ -888,12 +888,19 @@ let q_infinity () = qualid_of_ref "num.float.infinity" let q_neg_infinity () = qualid_of_ref "num.float.neg_infinity" let q_nan () = qualid_of_ref "num.float.nan" +let get_printing_float = Goptions.declare_bool_option_and_ref + ~depr:false + ~key:["Printing";"Float"] + ~value:true + let extern_float f scopes = if Float64.is_nan f then CRef(q_nan (), None) else if Float64.is_infinity f then CRef(q_infinity (), None) else if Float64.is_neg_infinity f then CRef(q_neg_infinity (), None) else - let s = Float64.(to_string f) in + let s = + let hex = !Flags.raw_print || not (get_printing_float ()) in + if hex then Float64.to_hex_string f else Float64.to_string f in let n = NumTok.Signed.of_string s in extern_prim_token_delimiter_if_required (Numeral n) "float" "float_scope" scopes diff --git a/interp/constrintern.ml b/interp/constrintern.ml index f82783f47d..ee041ed088 100644 --- a/interp/constrintern.ml +++ b/interp/constrintern.ml @@ -115,7 +115,7 @@ type internalization_error = | NotAProjectionOf of qualid * qualid | ProjectionsOfDifferentRecords of qualid * qualid -exception InternalizationError of internalization_error Loc.located +exception InternalizationError of internalization_error let explain_variable_capture id id' = Id.print id ++ str " is dependent in the type of " ++ Id.print id' ++ @@ -164,8 +164,13 @@ let explain_internalization_error e = explain_projections_of_diff_records inductive1_id inductive2_id in pp ++ str "." -let error_bad_inductive_type ?loc = - user_err ?loc (str +let _ = CErrors.register_handler (function + | InternalizationError e -> + Some (explain_internalization_error e) + | _ -> None) + +let error_bad_inductive_type ?loc ?info () = + user_err ?loc ?info (str "This should be an inductive type applied to patterns.") let error_parameter_not_implicit ?loc = @@ -187,7 +192,7 @@ let empty_internalization_env = Id.Map.empty let compute_internalization_data env sigma id ty typ impl = let impl = compute_implicits_with_manual env sigma typ (is_implicit_args()) impl in - (ty, impl, compute_arguments_scope sigma typ, var_uid id) + (ty, impl, compute_arguments_scope env sigma typ, var_uid id) let compute_internalization_env env sigma ?(impls=empty_internalization_env) ty = List.fold_left3 @@ -368,7 +373,7 @@ let impls_term_list n ?(args = []) = (* Check if in binder "(x1 x2 .. xn : t)", none of x1 .. xn-1 occurs in t *) let rec check_capture ty = let open CAst in function | { loc; v = Name id } :: { v = Name id' } :: _ when occur_glob_constr id ty -> - raise (InternalizationError (loc,VariableCapture (id,id'))) + Loc.raise ?loc (InternalizationError (VariableCapture (id,id'))) | _::nal -> check_capture ty nal | [] -> @@ -976,10 +981,6 @@ let split_by_type_pat ?loc ids subst = assert (terms = [] && termlists = []); subst -let make_subst ids l = - let fold accu (id, scopes) a = Id.Map.add id (a, scopes) accu in - List.fold_left2 fold Id.Map.empty ids l - let intern_notation intern env ntnvars loc ntn fullargs = (* Adjust to parsing of { } *) let ntn,fullargs = contract_curly_brackets ntn fullargs in @@ -1090,7 +1091,9 @@ let intern_extended_global_of_qualid qid = let intern_reference qid = let r = try intern_extended_global_of_qualid qid - with Not_found -> Nametab.error_global_not_found qid + with Not_found as exn -> + let _, info = Exninfo.capture exn in + Nametab.error_global_not_found ~info qid in Smartlocate.global_of_extended_global r @@ -1113,8 +1116,7 @@ let intern_qualid ?(no_secvar=false) qid intern env ntnvars us args = if List.length args < nids then error_not_enough_arguments ?loc; let args1,args2 = List.chop nids args in check_no_explicitation args1; - let terms = make_subst ids (List.map fst args1) in - let subst = (terms, Id.Map.empty, Id.Map.empty, Id.Map.empty) in + let subst = split_by_type ids (List.map fst args1,[],[],[]) in let infos = (Id.Map.empty, env) in let c = instantiate_notation_constr loc intern intern_cases_pattern_as_binder ntnvars subst infos c in let loc = c.loc in @@ -1175,16 +1177,20 @@ let intern_applied_reference ~isproj intern env namedctx (_, ntnvars as lvar) us let r, realref, args2 = intern_qualid ~no_secvar:true qid intern env ntnvars us args in check_applied_projection isproj realref qid; find_appl_head_data r, args2 - with Not_found -> + with Not_found as exn -> (* Extra allowance for non globalizing functions *) if !interning_grammar || env.unb then (* check_applied_projection ?? *) (gvar (loc,qualid_basename qid) us, [], []), args - else Nametab.error_global_not_found qid + else + let _, info = Exninfo.capture exn in + Nametab.error_global_not_found ~info qid else let r,realref,args2 = try intern_qualid qid intern env ntnvars us args - with Not_found -> Nametab.error_global_not_found qid + with Not_found as exn -> + let _, info = Exninfo.capture exn in + Nametab.error_global_not_found ~info qid in check_applied_projection isproj realref qid; find_appl_head_data r, args2 @@ -1258,14 +1264,16 @@ let loc_of_lhs lhs = let check_linearity lhs ids = match has_duplicate ids with | Some id -> - raise (InternalizationError (loc_of_lhs lhs,NonLinearPattern id)) + let loc = loc_of_lhs lhs in + Loc.raise ?loc (InternalizationError (NonLinearPattern id)) | None -> () (* Match the number of pattern against the number of matched args *) let check_number_of_pattern loc n l = let p = List.length l in - if not (Int.equal n p) then raise (InternalizationError (loc,BadPatternsNumber (n,p))) + if not (Int.equal n p) then + Loc.raise ?loc (InternalizationError (BadPatternsNumber (n,p))) let check_or_pat_variables loc ids idsl = let eq_id {v=id} {v=id'} = Id.equal id id' in @@ -1397,7 +1405,7 @@ let find_constructor loc add_params ref = let find_pattern_variable qid = if qualid_is_ident qid then qualid_basename qid - else raise (InternalizationError(qid.CAst.loc,NotAConstructor qid)) + else Loc.raise ?loc:qid.CAst.loc (InternalizationError(NotAConstructor qid)) let check_duplicate ?loc fields = let eq (ref1, _) (ref2, _) = qualid_eq ref1 ref2 in @@ -1434,8 +1442,10 @@ let sort_fields ~complete loc fields completer = let gr = locate_reference first_field_ref in Dumpglob.add_glob ?loc:first_field_ref.CAst.loc gr; (gr, Recordops.find_projection gr) - with Not_found -> - raise (InternalizationError(first_field_ref.CAst.loc, NotAProjection first_field_ref)) + with Not_found as exn -> + let _, info = Exninfo.capture exn in + let info = Option.cata (Loc.add_loc info) info loc in + Exninfo.iraise (InternalizationError(NotAProjection first_field_ref), info) in (* the number of parameters *) let nparams = record.Recordops.s_EXPECTEDPARAM in @@ -1470,10 +1480,10 @@ let sort_fields ~complete loc fields completer = try Recordops.find_projection field_glob_ref with Not_found -> let inductive_ref = inductive_of_record floc record in - raise (InternalizationError(floc, NotAProjectionOf (field_ref, inductive_ref))) in + Loc.raise ?loc:floc (InternalizationError(NotAProjectionOf (field_ref, inductive_ref))) in let ind1 = inductive_of_record floc record in let ind2 = inductive_of_record floc this_field_record in - raise (InternalizationError(loc, ProjectionsOfDifferentRecords (ind1, ind2))) + Loc.raise ?loc (InternalizationError(ProjectionsOfDifferentRecords (ind1, ind2))) in if not regular && complete then (* "regular" is false when the field is defined @@ -1624,8 +1634,8 @@ let drop_notations_pattern looked_for genv = let nvars = List.length vars in if List.length pats < nvars then error_not_enough_arguments ?loc:qid.loc; let pats1,pats2 = List.chop nvars pats in - let subst = make_subst vars pats1 in - let idspl1 = List.map (in_not false qid.loc scopes (subst, Id.Map.empty) []) args in + let subst = split_by_type_pat vars (pats1,[]) in + let idspl1 = List.map (in_not false qid.loc scopes subst []) args in let (_,argscs) = find_remaining_scopes pats1 pats2 g in Some (g, idspl1, List.map2 (in_pat_sc scopes) argscs pats2) | _ -> raise Not_found @@ -1660,12 +1670,16 @@ let drop_notations_pattern looked_for genv = begin match drop_syndef top scopes head pl with | Some (a,b,c) -> DAst.make ?loc @@ RCPatCstr(a, b, c) - | None -> raise (InternalizationError (loc,NotAConstructor head)) + | None -> Loc.raise ?loc (InternalizationError (NotAConstructor head)) end | CPatCstr (qid, Some expl_pl, pl) -> - let g = try Nametab.locate qid - with Not_found -> - raise (InternalizationError (loc,NotAConstructor qid)) in + let g = + try Nametab.locate qid + with Not_found as exn -> + let _, info = Exninfo.capture exn in + let info = Option.cata (Loc.add_loc info) info loc in + Exninfo.iraise (InternalizationError (NotAConstructor qid), info) + in if expl_pl == [] then (* Convention: (@r) deactivates all further implicit arguments and scopes *) DAst.make ?loc @@ RCPatCstr (g, List.map (in_pat false scopes) pl, []) @@ -1815,20 +1829,22 @@ let intern_ind_pattern genv ntnvars scopes pat = let no_not = try drop_notations_pattern (function (GlobRef.IndRef _ | GlobRef.ConstructRef _) -> () | _ -> raise Not_found) genv scopes pat - with InternalizationError(loc,NotAConstructor _) -> error_bad_inductive_type ?loc + with InternalizationError(NotAConstructor _) as exn -> + let _, info = Exninfo.capture exn in + error_bad_inductive_type ~info () in let loc = no_not.CAst.loc in match DAst.get no_not with | RCPatCstr (head, expl_pl, pl) -> - let c = (function GlobRef.IndRef ind -> ind | _ -> error_bad_inductive_type ?loc) head in + let c = (function GlobRef.IndRef ind -> ind | _ -> error_bad_inductive_type ?loc ()) head in let with_letin, pl2 = add_implicits_check_ind_length genv loc c (List.length expl_pl) pl in let idslpl = List.map (intern_pat genv ntnvars empty_alias) (expl_pl@pl2) in (with_letin, match product_of_cases_patterns empty_alias idslpl with | ids,[asubst,pl] -> (c,ids,asubst,chop_params_pattern loc c pl with_letin) - | _ -> error_bad_inductive_type ?loc) - | x -> error_bad_inductive_type ?loc + | _ -> error_bad_inductive_type ?loc ()) + | x -> error_bad_inductive_type ?loc () (**********************************************************************) (* Utilities for application *) @@ -1904,8 +1920,10 @@ let internalize globalenv env pattern_mode (_, ntnvars as lvar) c = let dl = Array.of_list dl in let n = try List.index0 Id.equal iddef lf - with Not_found -> - raise (InternalizationError (locid,UnboundFixName (false,iddef))) + with Not_found as exn -> + let _, info = Exninfo.capture exn in + let info = Option.cata (Loc.add_loc info) info locid in + Exninfo.iraise (InternalizationError (UnboundFixName (false,iddef)),info) in let env = restart_lambda_binders env in let idl_temp = Array.map @@ -1947,8 +1965,10 @@ let internalize globalenv env pattern_mode (_, ntnvars as lvar) c = let dl = Array.of_list dl in let n = try List.index0 Id.equal iddef lf - with Not_found -> - raise (InternalizationError (locid,UnboundFixName (true,iddef))) + with Not_found as exn -> + let _, info = Exninfo.capture exn in + let info = Option.cata (Loc.add_loc info) info locid in + Exninfo.iraise (InternalizationError (UnboundFixName (true,iddef)), info) in let env = restart_lambda_binders env in let idl_tmp = Array.map @@ -2176,7 +2196,7 @@ let internalize globalenv env pattern_mode (_, ntnvars as lvar) c = DAst.make ?loc @@ GEvar (n, List.map (on_snd (intern_no_implicit env)) l) | CPatVar _ -> - raise (InternalizationError (loc,IllegalMetavariable)) + Loc.raise ?loc (InternalizationError IllegalMetavariable) (* end *) | CSort s -> DAst.make ?loc @@ @@ -2342,12 +2362,7 @@ let internalize globalenv env pattern_mode (_, ntnvars as lvar) c = (intern_no_implicit enva a) :: (intern_args env subscopes args) in - try - intern env c - with - InternalizationError (loc,e) -> - user_err ?loc ~hdr:"internalize" - (explain_internalization_error e) + intern env c (**************************************************************************) (* Functions to translate constr_expr into glob_constr *) @@ -2358,9 +2373,9 @@ let extract_ids env = (Termops.ids_of_rel_context (Environ.rel_context env)) Id.Set.empty -let scope_of_type_kind sigma = function +let scope_of_type_kind env sigma = function | IsType -> Notation.current_type_scope_name () - | OfType typ -> compute_type_scope sigma typ + | OfType typ -> compute_type_scope env sigma typ | WithoutTypeConstraint | UnknownIfTermOrType -> None let allowed_binder_kind_of_type_kind = function @@ -2377,7 +2392,7 @@ let empty_ltac_sign = { let intern_gen kind env sigma ?(impls=empty_internalization_env) ?(pattern_mode=false) ?(ltacvars=empty_ltac_sign) c = - let tmp_scope = scope_of_type_kind sigma kind in + let tmp_scope = scope_of_type_kind env sigma kind in let k = allowed_binder_kind_of_type_kind kind in internalize env {ids = extract_ids env; unb = false; tmp_scope = tmp_scope; scopes = []; @@ -2387,12 +2402,7 @@ let intern_gen kind env sigma let intern_constr env sigma c = intern_gen WithoutTypeConstraint env sigma c let intern_type env sigma c = intern_gen IsType env sigma c let intern_pattern globalenv patt = - try - intern_cases_pattern globalenv Id.Map.empty (None,[]) empty_alias patt - with - InternalizationError (loc,e) -> - user_err ?loc ~hdr:"internalize" (explain_internalization_error e) - + intern_cases_pattern globalenv Id.Map.empty (None,[]) empty_alias patt (*********************************************************************) (* Functions to parse and interpret constructions *) @@ -2462,7 +2472,7 @@ let intern_constr_pattern env sigma ?(as_type=false) ?(ltacvars=empty_ltac_sign) let intern_core kind env sigma ?(pattern_mode=false) ?(ltacvars=empty_ltac_sign) { Genintern.intern_ids = ids; Genintern.notation_variable_status = vl } c = - let tmp_scope = scope_of_type_kind sigma kind in + let tmp_scope = scope_of_type_kind env sigma kind in let impls = empty_internalization_env in let k = allowed_binder_kind_of_type_kind kind in internalize env @@ -2505,7 +2515,6 @@ let my_intern_constr env lvar acc c = internalize env acc false lvar c let intern_context env impl_env binders = - try let lvar = (empty_ltac_sign, Id.Map.empty) in let ids = (* We assume all ids around are parts of the prefix of the current @@ -2519,8 +2528,6 @@ let intern_context env impl_env binders = tmp_scope = None; scopes = []; impls = impl_env; binder_block_names = Some (Some AbsPi,ids)}, []) binders in (lenv.impls, List.map glob_local_binder_of_extended bl) - with InternalizationError (loc,e) -> - user_err ?loc ~hdr:"internalize" (explain_internalization_error e) let interp_glob_context_evars ?(program_mode=false) env sigma k bl = let open EConstr in diff --git a/interp/dumpglob.mli b/interp/dumpglob.mli index 14e5a81308..be1e3f05d2 100644 --- a/interp/dumpglob.mli +++ b/interp/dumpglob.mli @@ -49,3 +49,4 @@ val type_of_global_ref : Names.GlobRef.t -> string (** Registration of constant information *) val add_constant_kind : Names.Constant.t -> Decls.logical_kind -> unit +val constant_kind : Names.Constant.t -> Decls.logical_kind diff --git a/interp/modintern.ml b/interp/modintern.ml index ae152e1c1c..50f90ebea7 100644 --- a/interp/modintern.ml +++ b/interp/modintern.ml @@ -22,14 +22,15 @@ exception ModuleInternalizationError of module_internalization_error type module_kind = Module | ModType | ModAny -let error_not_a_module_loc kind loc qid = +let error_not_a_module_loc ~info kind loc qid = let s = string_of_qualid qid in let e = match kind with | Module -> Modops.ModuleTypingError (Modops.NotAModule s) | ModType -> Modops.ModuleTypingError (Modops.NotAModuleType s) | ModAny -> ModuleInternalizationError (NotAModuleNorModtype s) in - Loc.raise ?loc e + let info = Option.cata (Loc.add_loc info) info loc in + Exninfo.iraise (e,info) let error_application_to_not_path loc me = Loc.raise ?loc (Modops.ModuleTypingError (Modops.ApplicationToNotPath me)) @@ -57,7 +58,9 @@ let lookup_module_or_modtype kind qid = if kind == Module then raise Not_found; let mp = Nametab.locate_modtype qid in Dumpglob.dump_modref ?loc mp "mod"; (mp,ModType) - with Not_found -> error_not_a_module_loc kind loc qid + with Not_found as exn -> + let _, info = Exninfo.capture exn in + error_not_a_module_loc ~info kind loc qid let lookup_module lqid = fst (lookup_module_or_modtype Module lqid) diff --git a/interp/notation.ml b/interp/notation.ml index 7761606f11..d4a44d9622 100644 --- a/interp/notation.ml +++ b/interp/notation.ml @@ -125,13 +125,14 @@ let declare_scope scope = with Not_found -> scope_map := String.Map.add scope empty_scope !scope_map -let error_unknown_scope sc = - user_err ~hdr:"Notation" +let error_unknown_scope ~info sc = + user_err ~hdr:"Notation" ~info (str "Scope " ++ str sc ++ str " is not declared.") let find_scope ?(tolerant=false) scope = try String.Map.find scope !scope_map - with Not_found -> + with Not_found as exn -> + let _, info = Exninfo.capture exn in if tolerant then (* tolerant mode to be turn off after deprecation phase *) begin @@ -140,7 +141,7 @@ let find_scope ?(tolerant=false) scope = empty_scope end else - error_unknown_scope scope + error_unknown_scope ~info scope let check_scope ?(tolerant=false) scope = let _ = find_scope ~tolerant scope in () @@ -158,7 +159,9 @@ let normalize_scope sc = try let sc = String.Map.find sc !delimiters_map in let _ = String.Map.find sc !scope_map in sc - with Not_found -> error_unknown_scope sc + with Not_found as exn -> + let _, info = Exninfo.capture exn in + error_unknown_scope ~info sc (**********************************************************************) (* The global stack of scopes *) @@ -257,8 +260,10 @@ let remove_delimiters scope = try let _ = ignore (String.Map.find key !delimiters_map) in delimiters_map := String.Map.remove key !delimiters_map - with Not_found -> - assert false (* A delimiter for scope [scope] should exist *) + with Not_found as exn -> + let _, info = Exninfo.capture exn in + (* XXX info *) + CErrors.anomaly ~info (str "A delimiter for scope [scope] should exist") let find_delimiters_scope ?loc key = try String.Map.find key !delimiters_map @@ -382,7 +387,7 @@ module InnerPrimToken = struct | _ -> false let mkNumeral n = - Numeral (NumTok.Signed.of_bigint n) + Numeral (NumTok.Signed.of_bigint CDec n) let mkString = function | None -> None @@ -423,23 +428,32 @@ type numnot_option = | Abstract of NumTok.UnsignedNat.t type int_ty = - { uint : Names.inductive; + { dec_uint : Names.inductive; + dec_int : Names.inductive; + hex_uint : Names.inductive; + hex_int : Names.inductive; + uint : Names.inductive; int : Names.inductive } type z_pos_ty = { z_ty : Names.inductive; pos_ty : Names.inductive } -type decimal_ty = +type numeral_ty = { int : int_ty; - decimal : Names.inductive } + decimal : Names.inductive; + hexadecimal : Names.inductive; + numeral : Names.inductive } type target_kind = - | Int of int_ty (* Coq.Init.Decimal.int + uint *) - | UInt of Names.inductive (* Coq.Init.Decimal.uint *) + | Int of int_ty (* Coq.Init.Numeral.int + uint *) + | UInt of int_ty (* Coq.Init.Numeral.uint *) | Z of z_pos_ty (* Coq.Numbers.BinNums.Z and positive *) | Int63 (* Coq.Numbers.Cyclic.Int63.Int63.int *) - | Decimal of decimal_ty (* Coq.Init.Decimal.decimal + uint + int *) + | Numeral of numeral_ty (* Coq.Init.Numeral.numeral + uint + int *) + | DecimalInt of int_ty (* Coq.Init.Decimal.int + uint (deprecated) *) + | DecimalUInt of int_ty (* Coq.Init.Decimal.uint (deprecated) *) + | Decimal of numeral_ty (* Coq.Init.Decimal.Decimal + uint + int (deprecated) *) type string_target_kind = | ListByte @@ -601,17 +615,23 @@ let warn_abstract_large_num = (** Decimal.Nil has index 1, then Decimal.D0 has index 2 .. Decimal.D9 is 11 *) let digit_of_char c = - assert ('0' <= c && c <= '9'); - Char.code c - Char.code '0' + 2 + assert ('0' <= c && c <= '9' || 'a' <= c && c <= 'f'); + if c <= '9' then Char.code c - Char.code '0' + 2 + else Char.code c - Char.code 'a' + 12 let char_of_digit n = - assert (2<=n && n<=11); - Char.chr (n-2 + Char.code '0') + assert (2<=n && n<=17); + if n <= 11 then Char.chr (n-2 + Char.code '0') + else Char.chr (n-12 + Char.code 'a') -let coquint_of_rawnum uint n = +let coquint_of_rawnum inds c n = + let uint = match c with CDec -> inds.dec_uint | CHex -> inds.hex_uint in let nil = mkConstruct (uint,1) in match n with None -> nil | Some n -> let str = NumTok.UnsignedNat.to_string n in + let str = match c with + | CDec -> str + | CHex -> String.sub str 2 (String.length str - 2) in (* cut "0x" *) let rec do_chars s i acc = if i < 0 then acc else @@ -620,61 +640,126 @@ let coquint_of_rawnum uint n = in do_chars str (String.length str - 1) nil -let coqint_of_rawnum inds (sign,n) = - let uint = coquint_of_rawnum inds.uint (Some n) in +let coqint_of_rawnum inds c (sign,n) = + let ind = match c with CDec -> inds.dec_int | CHex -> inds.hex_int in + let uint = coquint_of_rawnum inds c (Some n) in let pos_neg = match sign with SPlus -> 1 | SMinus -> 2 in - mkApp (mkConstruct (inds.int, pos_neg), [|uint|]) + mkApp (mkConstruct (ind, pos_neg), [|uint|]) -let coqdecimal_of_rawnum inds n = - let i, f, e = NumTok.Signed.to_decimal_and_exponent n in - let i = coqint_of_rawnum inds.int i in - let f = coquint_of_rawnum inds.int.uint f in +let coqnumeral_of_rawnum inds c n = + let ind = match c with CDec -> inds.decimal | CHex -> inds.hexadecimal in + let i, f, e = NumTok.Signed.to_int_frac_and_exponent n in + let i = coqint_of_rawnum inds.int c i in + let f = coquint_of_rawnum inds.int c f in match e with - | None -> mkApp (mkConstruct (inds.decimal, 1), [|i; f|]) (* Decimal *) + | None -> mkApp (mkConstruct (ind, 1), [|i; f|]) (* (D|Hexad)ecimal *) | Some e -> - let e = coqint_of_rawnum inds.int e in - mkApp (mkConstruct (inds.decimal, 2), [|i; f; e|]) (* DecimalExp *) + let e = coqint_of_rawnum inds.int CDec e in + mkApp (mkConstruct (ind, 2), [|i; f; e|]) (* (D|Hexad)ecimalExp *) -let rawnum_of_coquint c = +let mkDecHex ind c n = match c with + | CDec -> mkApp (mkConstruct (ind, 1), [|n|]) (* (UInt|Int|)Dec *) + | CHex -> mkApp (mkConstruct (ind, 2), [|n|]) (* (UInt|Int|)Hex *) + +exception NonDecimal + +let decimal_coqnumeral_of_rawnum inds n = + if NumTok.Signed.classify n <> CDec then raise NonDecimal; + coqnumeral_of_rawnum inds CDec n + +let coqnumeral_of_rawnum inds n = + let c = NumTok.Signed.classify n in + let n = coqnumeral_of_rawnum inds c n in + mkDecHex inds.numeral c n + +let decimal_coquint_of_rawnum inds n = + if NumTok.UnsignedNat.classify n <> CDec then raise NonDecimal; + coquint_of_rawnum inds CDec (Some n) + +let coquint_of_rawnum inds n = + let c = NumTok.UnsignedNat.classify n in + let n = coquint_of_rawnum inds c (Some n) in + mkDecHex inds.uint c n + +let decimal_coqint_of_rawnum inds n = + if NumTok.SignedNat.classify n <> CDec then raise NonDecimal; + coqint_of_rawnum inds CDec n + +let coqint_of_rawnum inds n = + let c = NumTok.SignedNat.classify n in + let n = coqint_of_rawnum inds c n in + mkDecHex inds.int c n + +let rawnum_of_coquint cl c = let rec of_uint_loop c buf = match Constr.kind c with | Construct ((_,1), _) (* Nil *) -> () | App (c, [|a|]) -> (match Constr.kind c with - | Construct ((_,n), _) (* D0 to D9 *) -> + | Construct ((_,n), _) (* D0 to Df *) -> let () = Buffer.add_char buf (char_of_digit n) in of_uint_loop a buf | _ -> raise NotAValidPrimToken) | _ -> raise NotAValidPrimToken in let buf = Buffer.create 64 in + if cl = CHex then (Buffer.add_char buf '0'; Buffer.add_char buf 'x'); let () = of_uint_loop c buf in - if Int.equal (Buffer.length buf) 0 then + if Int.equal (Buffer.length buf) (match cl with CDec -> 0 | CHex -> 2) then (* To avoid ambiguities between Nil and (D0 Nil), we choose to not display Nil alone as "0" *) raise NotAValidPrimToken else NumTok.UnsignedNat.of_string (Buffer.contents buf) -let rawnum_of_coqint c = +let rawnum_of_coqint cl c = match Constr.kind c with | App (c,[|c'|]) -> (match Constr.kind c with - | Construct ((_,1), _) (* Pos *) -> (SPlus,rawnum_of_coquint c') - | Construct ((_,2), _) (* Neg *) -> (SMinus,rawnum_of_coquint c') + | Construct ((_,1), _) (* Pos *) -> (SPlus,rawnum_of_coquint cl c') + | Construct ((_,2), _) (* Neg *) -> (SMinus,rawnum_of_coquint cl c') | _ -> raise NotAValidPrimToken) | _ -> raise NotAValidPrimToken -let rawnum_of_decimal c = +let rawnum_of_coqnumeral cl c = let of_ife i f e = - let n = rawnum_of_coqint i in - let f = try Some (rawnum_of_coquint f) with NotAValidPrimToken -> None in - let e = match e with None -> None | Some e -> Some (rawnum_of_coqint e) in - NumTok.Signed.of_decimal_and_exponent n f e in + let n = rawnum_of_coqint cl i in + let f = try Some (rawnum_of_coquint cl f) with NotAValidPrimToken -> None in + let e = match e with None -> None | Some e -> Some (rawnum_of_coqint CDec e) in + NumTok.Signed.of_int_frac_and_exponent n f e in match Constr.kind c with | App (_,[|i; f|]) -> of_ife i f None | App (_,[|i; f; e|]) -> of_ife i f (Some e) | _ -> raise NotAValidPrimToken +let destDecHex c = match Constr.kind c with + | App (c,[|c'|]) -> + (match Constr.kind c with + | Construct ((_,1), _) (* (UInt|Int|)Dec *) -> CDec, c' + | Construct ((_,2), _) (* (UInt|Int|)Hex *) -> CHex, c' + | _ -> raise NotAValidPrimToken) + | _ -> raise NotAValidPrimToken + +let decimal_rawnum_of_coqnumeral c = + rawnum_of_coqnumeral CDec c + +let rawnum_of_coqnumeral c = + let cl, c = destDecHex c in + rawnum_of_coqnumeral cl c + +let decimal_rawnum_of_coquint c = + rawnum_of_coquint CDec c + +let rawnum_of_coquint c = + let cl, c = destDecHex c in + rawnum_of_coquint cl c + +let decimal_rawnum_of_coqint c = + rawnum_of_coqint CDec c + +let rawnum_of_coqint c = + let cl, c = destDecHex c in + rawnum_of_coqint cl c + (***********************************************************************) (** ** Conversion between Coq [Z] and internal bigint *) @@ -768,15 +853,24 @@ let interp o ?loc n = let c = match fst o.to_kind, NumTok.Signed.to_int n with | Int int_ty, Some n -> coqint_of_rawnum int_ty n - | UInt uint_ty, Some (SPlus, n) -> - coquint_of_rawnum uint_ty (Some n) + | UInt int_ty, Some (SPlus, n) -> + coquint_of_rawnum int_ty n + | DecimalInt int_ty, Some n -> + (try decimal_coqint_of_rawnum int_ty n + with NonDecimal -> no_such_prim_token "number" ?loc o.ty_name) + | DecimalUInt int_ty, Some (SPlus, n) -> + (try decimal_coquint_of_rawnum int_ty n + with NonDecimal -> no_such_prim_token "number" ?loc o.ty_name) | Z z_pos_ty, Some n -> z_of_bigint z_pos_ty (NumTok.SignedNat.to_bigint n) | Int63, Some n -> interp_int63 ?loc (NumTok.SignedNat.to_bigint n) - | (Int _ | UInt _ | Z _ | Int63), _ -> + | (Int _ | UInt _ | DecimalInt _ | DecimalUInt _ | Z _ | Int63), _ -> no_such_prim_token "number" ?loc o.ty_name - | Decimal decimal_ty, _ -> coqdecimal_of_rawnum decimal_ty n + | Numeral numeral_ty, _ -> coqnumeral_of_rawnum numeral_ty n + | Decimal numeral_ty, _ -> + (try decimal_coqnumeral_of_rawnum numeral_ty n + with NonDecimal -> no_such_prim_token "number" ?loc o.ty_name) in let env = Global.env () in let sigma = Evd.from_env env in @@ -797,9 +891,12 @@ let uninterp o n = begin function | (Int _, c) -> NumTok.Signed.of_int (rawnum_of_coqint c) | (UInt _, c) -> NumTok.Signed.of_nat (rawnum_of_coquint c) - | (Z _, c) -> NumTok.Signed.of_bigint (bigint_of_z c) - | (Int63, c) -> NumTok.Signed.of_bigint (bigint_of_int63 c) - | (Decimal _, c) -> rawnum_of_decimal c + | (Z _, c) -> NumTok.Signed.of_bigint CDec (bigint_of_z c) + | (Int63, c) -> NumTok.Signed.of_bigint CDec (bigint_of_int63 c) + | (Numeral _, c) -> rawnum_of_coqnumeral c + | (DecimalInt _, c) -> NumTok.Signed.of_int (decimal_rawnum_of_coqint c) + | (DecimalUInt _, c) -> NumTok.Signed.of_nat (decimal_rawnum_of_coquint c) + | (Decimal _, c) -> decimal_rawnum_of_coqnumeral c end o n end @@ -1031,12 +1128,17 @@ let declare_string_interpreter ?(local=false) sc dir interp (patl,uninterp,b) = let check_required_module ?loc sc (sp,d) = try let _ = Nametab.global_of_path sp in () - with Not_found -> + with Not_found as exn -> + let _, info = Exninfo.capture exn in match d with - | [] -> user_err ?loc ~hdr:"prim_token_interpreter" - (str "Cannot interpret in " ++ str sc ++ str " because " ++ pr_path sp ++ str " could not be found in the current environment.") - | _ -> user_err ?loc ~hdr:"prim_token_interpreter" - (str "Cannot interpret in " ++ str sc ++ str " without requiring first module " ++ str (List.last d) ++ str ".") + | [] -> + user_err ?loc ~info ~hdr:"prim_token_interpreter" + (str "Cannot interpret in " ++ str sc ++ str " because " ++ pr_path sp ++ + str " could not be found in the current environment.") + | _ -> + user_err ?loc ~info ~hdr:"prim_token_interpreter" + (str "Cannot interpret in " ++ str sc ++ str " without requiring first module " ++ + str (List.last d) ++ str ".") (* Look if some notation or numeral printer in [scope] can be used in the scope stack [scopes], and if yes, using delimiters or not *) @@ -1126,8 +1228,8 @@ let find_notation ntn sc = NotationMap.find ntn (find_scope sc).notations let notation_of_prim_token = function - | Numeral (SPlus,n) -> InConstrEntrySomeLevel, NumTok.Unsigned.sprint n - | Numeral (SMinus,n) -> InConstrEntrySomeLevel, "- "^NumTok.Unsigned.sprint n + | Constrexpr.Numeral (SPlus,n) -> InConstrEntrySomeLevel, NumTok.Unsigned.sprint n + | Constrexpr.Numeral (SMinus,n) -> InConstrEntrySomeLevel, "- "^NumTok.Unsigned.sprint n | String _ -> raise Not_found let find_prim_token check_allowed ?loc p sc = @@ -1158,8 +1260,9 @@ let interp_prim_token_gen ?loc g p local_scopes = try let (pat,loc), sc = find_interpretation p_as_ntn (find_prim_token ?loc g p) scopes in pat, (loc,sc) - with Not_found -> - user_err ?loc ~hdr:"interp_prim_token" + with Not_found as exn -> + let _, info = Exninfo.capture exn in + user_err ?loc ~info ~hdr:"interp_prim_token" ((match p with | Numeral _ -> str "No interpretation for numeral " ++ pr_notation (notation_of_prim_token p) @@ -1192,9 +1295,10 @@ let interp_notation ?loc ntn local_scopes = let (n,sc) = find_interpretation ntn (find_notation ntn) scopes in Option.iter (fun d -> warn_deprecated_notation ?loc (ntn,d)) n.not_deprecation; n.not_interp, (n.not_location, sc) - with Not_found -> - user_err ?loc - (str "Unknown interpretation for notation " ++ pr_notation ntn ++ str ".") + with Not_found as exn -> + let _, info = Exninfo.capture exn in + user_err ?loc ~info + (str "Unknown interpretation for notation " ++ pr_notation ntn ++ str ".") let uninterp_notations c = List.map_append (fun key -> keymap_find key !notations_key_table) @@ -1333,14 +1437,14 @@ let availability_of_prim_token n printer_scope local_scopes = let uid = snd (String.Map.find scope !prim_token_interp_infos) in let open InnerPrimToken in match n, uid with - | Numeral _, NumeralNotation _ -> true + | Constrexpr.Numeral _, NumeralNotation _ -> true | _, NumeralNotation _ -> false | String _, StringNotation _ -> true | _, StringNotation _ -> false | _, Uid uid -> let interp = Hashtbl.find prim_token_interpreters uid in match n, interp with - | Numeral _, (RawNumInterp _ | BigNumInterp _) -> true + | Constrexpr.Numeral _, (RawNumInterp _ | BigNumInterp _) -> true | String _, StringInterp _ -> true | _ -> false with Not_found -> false @@ -1448,8 +1552,8 @@ type scope_class = cl_typ let scope_class_compare : scope_class -> scope_class -> int = cl_typ_ord -let compute_scope_class sigma t = - let (cl,_,_) = find_class_type sigma t in +let compute_scope_class env sigma t = + let (cl,_,_) = find_class_type env sigma t in cl module ScopeClassOrd = @@ -1478,22 +1582,23 @@ let find_scope_class_opt = function (**********************************************************************) (* Special scopes associated to arguments of a global reference *) -let rec compute_arguments_classes sigma t = - match EConstr.kind sigma (Reductionops.whd_betaiotazeta sigma t) with - | Prod (_,t,u) -> - let cl = try Some (compute_scope_class sigma t) with Not_found -> None in - cl :: compute_arguments_classes sigma u +let rec compute_arguments_classes env sigma t = + match EConstr.kind sigma (Reductionops.whd_betaiotazeta env sigma t) with + | Prod (na, t, u) -> + let env = EConstr.push_rel (Context.Rel.Declaration.LocalAssum (na, t)) env in + let cl = try Some (compute_scope_class env sigma t) with Not_found -> None in + cl :: compute_arguments_classes env sigma u | _ -> [] -let compute_arguments_scope_full sigma t = - let cls = compute_arguments_classes sigma t in +let compute_arguments_scope_full env sigma t = + let cls = compute_arguments_classes env sigma t in let scs = List.map find_scope_class_opt cls in scs, cls -let compute_arguments_scope sigma t = fst (compute_arguments_scope_full sigma t) +let compute_arguments_scope env sigma t = fst (compute_arguments_scope_full env sigma t) -let compute_type_scope sigma t = - find_scope_class_opt (try Some (compute_scope_class sigma t) with Not_found -> None) +let compute_type_scope env sigma t = + find_scope_class_opt (try Some (compute_scope_class env sigma t) with Not_found -> None) let current_type_scope_name () = find_scope_class_opt (Some CL_SORT) @@ -1531,15 +1636,16 @@ let load_arguments_scope _ (_,(_,r,n,scl,cls)) = let cache_arguments_scope o = load_arguments_scope 1 o -let subst_scope_class subst cs = - try Some (subst_cl_typ subst cs) with Not_found -> None +let subst_scope_class env subst cs = + try Some (subst_cl_typ env subst cs) with Not_found -> None let subst_arguments_scope (subst,(req,r,n,scl,cls)) = let r' = fst (subst_global subst r) in let subst_cl ocl = match ocl with | None -> ocl | Some cl -> - match subst_scope_class subst cl with + let env = Global.env () in + match subst_scope_class env subst cl with | Some cl' as ocl' when cl' != cl -> ocl' | _ -> ocl in let cls' = List.Smart.map subst_cl cls in @@ -1565,7 +1671,7 @@ let rebuild_arguments_scope sigma (req,r,n,l,_) = | ArgsScopeAuto -> let env = Global.env () in (*FIXME?*) let typ = EConstr.of_constr @@ fst (Typeops.type_of_global_in_context env r) in - let scs,cls = compute_arguments_scope_full sigma typ in + let scs,cls = compute_arguments_scope_full env sigma typ in (req,r,List.length scs,scs,cls) | ArgsScopeManual -> (* Add to the manually given scopes the one found automatically @@ -1573,7 +1679,7 @@ let rebuild_arguments_scope sigma (req,r,n,l,_) = of the manually given scopes to avoid further re-computations. *) let env = Global.env () in (*FIXME?*) let typ = EConstr.of_constr @@ fst (Typeops.type_of_global_in_context env r) in - let l',cls = compute_arguments_scope_full sigma typ in + let l',cls = compute_arguments_scope_full env sigma typ in let l1 = List.firstn n l' in let cls1 = List.firstn n cls in (req,r,0,l1@l,cls1) @@ -1620,7 +1726,7 @@ let find_arguments_scope r = let declare_ref_arguments_scope sigma ref = let env = Global.env () in (* FIXME? *) let typ = EConstr.of_constr @@ fst @@ Typeops.type_of_global_in_context env ref in - let (scs,cls as o) = compute_arguments_scope_full sigma typ in + let (scs,cls as o) = compute_arguments_scope_full env sigma typ in declare_arguments_scope_gen ArgsScopeAuto ref (List.length scs) o (********************************) @@ -1807,10 +1913,10 @@ let browse_notation strict ntn map = map [] in List.sort (fun x y -> String.compare (snd (fst x)) (snd (fst y))) l -let global_reference_of_notation test (ntn,(sc,c,_)) = +let global_reference_of_notation ~head test (ntn,(sc,c,_)) = match c with | NRef ref when test ref -> Some (ntn,sc,ref) - | NApp (NRef ref, l) when List.for_all isNVar_or_NHole l && test ref -> + | NApp (NRef ref, l) when head || List.for_all isNVar_or_NHole l && test ref -> Some (ntn,sc,ref) | _ -> None @@ -1822,14 +1928,14 @@ let error_notation_not_reference ?loc ntn = (str "Unable to interpret " ++ quote (str ntn) ++ str " as a reference.") -let interp_notation_as_global_reference ?loc test ntn sc = +let interp_notation_as_global_reference ?loc ~head test ntn sc = let scopes = match sc with | Some sc -> let scope = find_scope (find_delimiters_scope sc) in String.Map.add sc scope String.Map.empty | None -> !scope_map in let ntns = browse_notation true ntn scopes in - let refs = List.map (global_reference_of_notation test) ntns in + let refs = List.map (global_reference_of_notation ~head test) ntns in match Option.List.flatten refs with | [_,_,ref] -> ref | [] -> error_notation_not_reference ?loc ntn diff --git a/interp/notation.mli b/interp/notation.mli index 842f2b1458..e7e917463b 100644 --- a/interp/notation.mli +++ b/interp/notation.mli @@ -74,7 +74,7 @@ val find_delimiters_scope : ?loc:Loc.t -> delimiters -> scope_name (** {6 Declare and uses back and forth an interpretation of primitive token } *) -(** A numeral interpreter is the pair of an interpreter for **decimal** +(** A numeral interpreter is the pair of an interpreter for **(hexa)decimal** numbers in terms and an optional interpreter in pattern, if non integer or negative numbers are not supported, the interpreter must fail with an appropriate error message *) @@ -120,23 +120,32 @@ type numnot_option = | Abstract of NumTok.UnsignedNat.t type int_ty = - { uint : Names.inductive; + { dec_uint : Names.inductive; + dec_int : Names.inductive; + hex_uint : Names.inductive; + hex_int : Names.inductive; + uint : Names.inductive; int : Names.inductive } type z_pos_ty = { z_ty : Names.inductive; pos_ty : Names.inductive } -type decimal_ty = +type numeral_ty = { int : int_ty; - decimal : Names.inductive } + decimal : Names.inductive; + hexadecimal : Names.inductive; + numeral : Names.inductive } type target_kind = - | Int of int_ty (* Coq.Init.Decimal.int + uint *) - | UInt of Names.inductive (* Coq.Init.Decimal.uint *) + | Int of int_ty (* Coq.Init.Numeral.int + uint *) + | UInt of int_ty (* Coq.Init.Numeral.uint *) | Z of z_pos_ty (* Coq.Numbers.BinNums.Z and positive *) | Int63 (* Coq.Numbers.Cyclic.Int63.Int63.int *) - | Decimal of decimal_ty (* Coq.Init.Decimal.decimal + uint + int *) + | Numeral of numeral_ty (* Coq.Init.Numeral.numeral + uint + int *) + | DecimalInt of int_ty (* Coq.Init.Decimal.int + uint (deprecated) *) + | DecimalUInt of int_ty (* Coq.Init.Decimal.uint (deprecated) *) + | Decimal of numeral_ty (* Coq.Init.Decimal.Decimal + uint + int (deprecated) *) type string_target_kind = | ListByte @@ -245,7 +254,8 @@ val availability_of_notation : specific_notation -> subscopes -> (** {6 Miscellaneous} *) -val interp_notation_as_global_reference : ?loc:Loc.t -> (GlobRef.t -> bool) -> +(** If head is true, also allows applied global references. *) +val interp_notation_as_global_reference : ?loc:Loc.t -> head:bool -> (GlobRef.t -> bool) -> notation_key -> delimiters option -> GlobRef.t (** Checks for already existing notations *) @@ -264,13 +274,13 @@ type scope_class val scope_class_compare : scope_class -> scope_class -> int val subst_scope_class : - Mod_subst.substitution -> scope_class -> scope_class option + Environ.env -> Mod_subst.substitution -> scope_class -> scope_class option val declare_scope_class : scope_name -> scope_class -> unit val declare_ref_arguments_scope : Evd.evar_map -> GlobRef.t -> unit -val compute_arguments_scope : Evd.evar_map -> EConstr.types -> scope_name option list -val compute_type_scope : Evd.evar_map -> EConstr.types -> scope_name option +val compute_arguments_scope : Environ.env -> Evd.evar_map -> EConstr.types -> scope_name option list +val compute_type_scope : Environ.env -> Evd.evar_map -> EConstr.types -> scope_name option (** Get the current scope bound to Sortclass, if it exists *) val current_type_scope_name : unit -> scope_name option diff --git a/interp/numTok.ml b/interp/numTok.ml index e254e9e972..bb14649b91 100644 --- a/interp/numTok.ml +++ b/interp/numTok.ml @@ -12,6 +12,10 @@ e.g. "e"/"E" or the presence of leading 0s, or the presence of a + in the exponent *) +type num_class = CDec | CHex + +let string_del_head n s = String.sub s n (String.length s - n) + module UnsignedNat = struct type t = string @@ -20,12 +24,15 @@ struct assert (s.[0] >= '0' && s.[0] <= '9'); s let to_string s = - String.(concat "" (split_on_char '_' s)) + String.(map Char.lowercase_ascii (concat "" (split_on_char '_' s))) let sprint s = s let print s = Pp.str (sprint s) - (** Comparing two raw numbers (base 10, big-endian, non-negative). + let classify s = + if String.length s >= 2 && (s.[1] = 'x' || s.[1] = 'X') then CHex else CDec + + (** Comparing two raw numbers (base 10 or 16, big-endian, non-negative). A bit nasty, but not critical: used e.g. to decide when a number is considered as large (see threshold warnings in notation.ml). *) @@ -45,12 +52,20 @@ struct 0 with Comp c -> c - let is_zero s = - compare s "0" = 0 + let compare n d = + assert (classify d = CDec); + match classify n with + | CDec -> compare (to_string n) (to_string d) + | CHex -> compare (string_del_head 2 (to_string n)) (to_string d) + + let is_zero s = + compare s "0" = 0 end type sign = SPlus | SMinus +type 'a exp = EDec of 'a | EBin of 'a + module SignedNat = struct type t = sign * UnsignedNat.t @@ -58,26 +73,89 @@ struct assert (String.length s > 0); let sign,n = match s.[0] with - | '-' -> (SMinus,String.sub s 1 (String.length s - 1)) - | '+' -> (SPlus,String.sub s 1 (String.length s - 1)) + | '-' -> (SMinus,string_del_head 1 s) + | '+' -> (SPlus,string_del_head 1 s) | _ -> (SPlus,s) in (sign,UnsignedNat.of_string n) let to_string (sign,n) = (match sign with SPlus -> "" | SMinus -> "-") ^ UnsignedNat.to_string n - let to_bigint n = Bigint.of_string (to_string n) - let of_bigint n = + let classify (_,n) = UnsignedNat.classify n + let bigint_of_string (sign,n) = + (* nasty code to remove when switching to zarith + since zarith's of_string handles hexadecimal *) + match UnsignedNat.classify n with + | CDec -> Bigint.of_string (to_string (sign,n)) + | CHex -> + let int_of_char c = match c with + | 'a'..'f' -> 10 + int_of_char c - int_of_char 'a' + | _ -> int_of_char c - int_of_char '0' in + let c16 = Bigint.of_int 16 in + let s = UnsignedNat.to_string n in + let n = ref Bigint.zero in + let len = String.length s in + for d = 2 to len - 1 do + n := Bigint.(add (mult !n c16) (of_int (int_of_char s.[d]))) + done; + match sign with SPlus -> !n | SMinus -> Bigint.neg !n + let to_bigint n = bigint_of_string n + let string_of_nonneg_bigint c n = + (* nasty code to remove when switching to zarith + since zarith's format handles hexadecimal *) + match c with + | CDec -> Bigint.to_string n + | CHex -> + let div16 n = + let n, r0 = Bigint.div2_with_rest n in + let n, r1 = Bigint.div2_with_rest n in + let n, r2 = Bigint.div2_with_rest n in + let n, r3 = Bigint.div2_with_rest n in + let r = match r3, r2, r1, r0 with + | false, false, false, false -> "0" + | false, false, false, true -> "1" + | false, false, true, false -> "2" + | false, false, true, true -> "3" + | false, true, false, false -> "4" + | false, true, false, true -> "5" + | false, true, true, false -> "6" + | false, true, true, true -> "7" + | true, false, false, false -> "8" + | true, false, false, true -> "9" + | true, false, true, false -> "a" + | true, false, true, true -> "b" + | true, true, false, false -> "c" + | true, true, false, true -> "d" + | true, true, true, false -> "e" + | true, true, true, true -> "f" in + n, r in + let n = ref n in + let l = ref [] in + while Bigint.is_strictly_pos !n do + let n', r = div16 !n in + n := n'; + l := r :: !l + done; + "0x" ^ String.concat "" (List.rev !l) + let of_bigint c n = let sign, n = if Bigint.is_strictly_neg n then (SMinus, Bigint.neg n) else (SPlus, n) in - (sign, Bigint.to_string n) + (sign, string_of_nonneg_bigint c n) end module Unsigned = struct type t = { - int : string; (** \[0-9\]\[0-9_\]* *) - frac : string; (** empty or \[0-9_\]+ *) - exp : string (** empty or \[eE\]\[+-\]?\[0-9\]\[0-9_\]* *) + int : string; + frac : string; + exp : string } + (** + - int: \[0-9\]\[0-9_\]* + - frac: empty or \[0-9_\]+ + - exp: empty or \[eE\]\[+-\]?\[0-9\]\[0-9_\]* + or + - int: 0\[xX\]\[0-9a-fA-F\]\[0-9a-fA-F_\]* + - frac: empty or \[0-9a-fA-F_\]+ + - exp: empty or \[pP\]\[+-\]?\[0-9\]\[0-9_\]* *) let equal n1 n2 = String.(equal n1.int n2.int && equal n1.frac n2.frac && equal n1.exp n2.exp) @@ -96,19 +174,35 @@ struct | Some ('0'..'9' as c) -> Stream.junk s; number (store len c) s | Some ('_' as c) when len > 0 -> Stream.junk s; number (store len c) s | _ -> len in + (* reads [0-9a-fA-F_]* *) + let rec hex_number len s = match Stream.peek s with + | Some (('0'..'9' | 'a'..'f' | 'A'..'F') as c) -> + Stream.junk s; hex_number (store len c) s + | Some ('_' as c) when len > 0 -> + Stream.junk s; hex_number (store len c) s + | _ -> len in fun s -> - let i = get_buff (number 0 s) in + let hex, i = + match Stream.npeek 3 s with + | '0' :: (('x' | 'X') as x) :: (('0'..'9' | 'a'..'f' | 'A'..'F') as c) :: _ -> + Stream.junk s; Stream.junk s; Stream.junk s; + true, get_buff (hex_number (store (store (store 0 '0') x) c) s) + | _ -> false, get_buff (number 0 s) in assert (i <> ""); let f = - match Stream.npeek 2 s with - | '.' :: (('0'..'9' | '_') as c) :: _ -> + match hex, Stream.npeek 2 s with + | true, '.' :: (('0'..'9' | 'a'..'f' | 'A'..'F' | '_') as c) :: _ -> + Stream.junk s; Stream.junk s; get_buff (hex_number (store 0 c) s) + | false, '.' :: (('0'..'9' | '_') as c) :: _ -> Stream.junk s; Stream.junk s; get_buff (number (store 0 c) s) | _ -> "" in let e = - match (Stream.npeek 2 s) with - | (('e'|'E') as e) :: ('0'..'9' as c) :: _ -> + match hex, Stream.npeek 2 s with + | true, (('p'|'P') as e) :: ('0'..'9' as c) :: _ + | false, (('e'|'E') as e) :: ('0'..'9' as c) :: _ -> Stream.junk s; Stream.junk s; get_buff (number (store (store 0 e) c) s) - | (('e'|'E') as e) :: (('+'|'-') as sign) :: _ -> + | true, (('p'|'P') as e) :: (('+'|'-') as sign) :: _ + | false, (('e'|'E') as e) :: (('+'|'-') as sign) :: _ -> begin match Stream.npeek 3 s with | _ :: _ :: ('0'..'9' as c) :: _ -> Stream.junk s; Stream.junk s; Stream.junk s; @@ -146,6 +240,7 @@ struct | { int = _; frac = ""; exp = "" } -> true | _ -> false + let classify n = UnsignedNat.classify n.int end open Unsigned @@ -162,19 +257,30 @@ struct | (SPlus,{int;frac;exp}) -> UnsignedNat.is_zero int && UnsignedNat.is_zero frac | _ -> false - let of_decimal_and_exponent (sign,int) f e = - let exp = match e with Some e -> "e" ^ SignedNat.to_string e | None -> "" in - let frac = match f with Some f -> UnsignedNat.to_string f | None -> "" in + let of_int_frac_and_exponent (sign,int) f e = + assert (match e with None -> true | Some e -> SignedNat.classify e = CDec); + let c = UnsignedNat.classify int in + let exp = match e with None -> "" | Some e -> + let e = SignedNat.to_string e in + match c with CDec -> "e" ^ e | CHex -> "p" ^ e in + let frac = match f with None -> "" | Some f -> + assert (c = UnsignedNat.classify f); + let f = UnsignedNat.to_string f in + match c with CDec -> f | CHex -> string_del_head 2 f in sign, { int; frac; exp } - let to_decimal_and_exponent (sign, { int; frac; exp }) = + let to_int_frac_and_exponent (sign, { int; frac; exp }) = let e = if exp = "" then None else Some (match exp.[1] with - | '-' -> SMinus, String.sub exp 2 (String.length exp - 2) - | '+' -> SPlus, String.sub exp 2 (String.length exp - 2) - | _ -> SPlus, String.sub exp 1 (String.length exp - 1)) in - let f = if frac = "" then None else Some frac in + | '-' -> SMinus, string_del_head 2 exp + | '+' -> SPlus, string_del_head 2 exp + | _ -> SPlus, string_del_head 1 exp) in + let f = + if frac = "" then None else + Some (match UnsignedNat.classify int with + | CDec -> frac + | CHex -> "0x" ^ frac) in (sign, int), f, e let of_nat i = @@ -211,8 +317,8 @@ struct let of_string s = assert (s <> ""); let sign,u = match s.[0] with - | '-' -> (SMinus, String.sub s 1 (String.length s - 1)) - | '+' -> (SPlus, String.sub s 1 (String.length s - 1)) + | '-' -> (SMinus, string_del_head 1 s) + | '+' -> (SPlus, string_del_head 1 s) | _ -> (SPlus, s) in (sign, Unsigned.of_string u) @@ -224,27 +330,31 @@ struct Some (SignedNat.to_bigint (sign,UnsignedNat.to_string n)) | _ -> None - let of_bigint n = - let sign, int = SignedNat.of_bigint n in - (sign, { int; frac = ""; exp = "" }) + let of_bigint c n = + of_int (SignedNat.of_bigint c n) let to_bigint_and_exponent (s, { int; frac; exp }) = - let s = match s with SPlus -> "" | SMinus -> "-" in + let c = UnsignedNat.classify int in let int = UnsignedNat.to_string int in let frac = UnsignedNat.to_string frac in - let i = Bigint.of_string (s ^ int ^ frac) in + let i = SignedNat.to_bigint (s, int ^ frac) in let e = let e = if exp = "" then Bigint.zero else match exp.[1] with - | '+' -> Bigint.of_string (UnsignedNat.to_string (String.sub exp 2 (String.length exp - 2))) - | '-' -> Bigint.(neg (of_string (UnsignedNat.to_string (String.sub exp 2 (String.length exp - 2))))) - | _ -> Bigint.of_string (UnsignedNat.to_string (String.sub exp 1 (String.length exp - 1))) in - Bigint.(sub e (of_int (String.length (String.concat "" (String.split_on_char '_' frac))))) in - (i,e) + | '+' -> Bigint.of_string (UnsignedNat.to_string (string_del_head 2 exp)) + | '-' -> Bigint.(neg (of_string (UnsignedNat.to_string (string_del_head 2 exp)))) + | _ -> Bigint.of_string (UnsignedNat.to_string (string_del_head 1 exp)) in + let l = String.length frac in + let l = match c with CDec -> l | CHex -> 4 * l in + Bigint.(sub e (of_int l)) in + (i, match c with CDec -> EDec e | CHex -> EBin e) let of_bigint_and_exponent i e = - of_decimal_and_exponent (SignedNat.of_bigint i) None (Some (SignedNat.of_bigint e)) + let c = match e with EDec _ -> CDec | EBin _ -> CHex in + let e = match e with EDec e | EBin e -> Some (SignedNat.of_bigint CDec e) in + of_int_frac_and_exponent (SignedNat.of_bigint c i) None e let is_bigger_int_than (s, { int; frac; exp }) i = frac = "" && exp = "" && UnsignedNat.compare int i >= 0 + let classify (_, n) = Unsigned.classify n end diff --git a/interp/numTok.mli b/interp/numTok.mli index ea289df237..11d5a0f980 100644 --- a/interp/numTok.mli +++ b/interp/numTok.mli @@ -11,7 +11,7 @@ (** Numerals in different forms: signed or unsigned, possibly with fractional part and exponent. - Numerals are represented using raw strings of decimal + Numerals are represented using raw strings of (hexa)decimal literals and a separate sign flag. Note that this representation is not unique, due to possible @@ -25,21 +25,29 @@ type sign = SPlus | SMinus +type num_class = CDec | CHex + +type 'a exp = EDec of 'a | EBin of 'a + (** {6 String representation of a natural number } *) module UnsignedNat : sig type t val of_string : string -> t - (** Convert from a non-empty sequence of digits (which may contain "_") *) + (** Convert from a non-empty sequence of digits (which may contain "_") + (or hexdigits when starting with "0x" or "0X") *) val to_string : t -> string - (** Convert to a non-empty sequence of digit that does not contain "_" *) + (** Convert to a non-empty sequence of digit that does not contain "_" + (or hexdigits, starting with "0x", all hexdigits are lower case) *) val sprint : t -> string val print : t -> Pp.t (** [sprint] and [print] returns the numeral as it was parsed, for printing *) + val classify : t -> num_class + val compare : t -> t -> int end @@ -49,13 +57,16 @@ module SignedNat : sig type t = sign * UnsignedNat.t val of_string : string -> t - (** Convert from a non-empty sequence of digits which may contain "_" *) + (** Convert from a non-empty sequence of (hex)digits which may contain "_" *) val to_string : t -> string - (** Convert to a non-empty sequence of digit that does not contain "_" *) + (** Convert to a non-empty sequence of (hex)digit that does not contain "_" + (hexadecimals start with "0x" and all hexdigits are lower case) *) + val classify : t -> num_class + + val of_bigint : num_class -> Bigint.bigint -> t val to_bigint : t -> Bigint.bigint - val of_bigint : Bigint.bigint -> t end (** {6 Unsigned decimal numerals } *) @@ -78,11 +89,17 @@ sig The recognized syntax is: - integer part: \[0-9\]\[0-9_\]* - - decimal part: empty or .\[0-9_\]+ - - exponent part: empty or \[eE\]\[+-\]?\[0-9\]\[0-9_\]* *) + - fractional part: empty or .\[0-9_\]+ + - exponent part: empty or \[eE\]\[+-\]?\[0-9\]\[0-9_\]* + or + - integer part: 0\[xX\]\[0-9a-fA-F\]\[0-9a-fA-F_\]* + - fractional part: empty or .\[0-9a-fA-F_\]+ + - exponent part: empty or \[pP\]\[+-\]?\[0-9\]\[0-9_\]* *) val parse_string : string -> t option - (** Parse the string as a positive Coq numeral, if possible *) + (** Parse the string as a non negative Coq numeral, if possible *) + + val classify : t -> num_class end @@ -114,17 +131,20 @@ sig val to_string : t -> string (** Returns a string in the syntax of OCaml's float_of_string *) - val of_bigint : Bigint.bigint -> t + val of_bigint : num_class -> Bigint.bigint -> t val to_bigint : t -> Bigint.bigint option (** Convert from and to bigint when the denotation of a bigint *) - val of_decimal_and_exponent : SignedNat.t -> UnsignedNat.t option -> SignedNat.t option -> t - val to_decimal_and_exponent : t -> SignedNat.t * UnsignedNat.t option * SignedNat.t option - (** n, p and q such that the number is n.p*10^q *) + val of_int_frac_and_exponent : SignedNat.t -> UnsignedNat.t option -> SignedNat.t option -> t + val to_int_frac_and_exponent : t -> SignedNat.t * UnsignedNat.t option * SignedNat.t option + (** n, p and q such that the number is n.p*10^q or n.p*2^q + pre/postcondition: classify n = classify p, classify q = CDec *) + + val of_bigint_and_exponent : Bigint.bigint -> Bigint.bigint exp -> t + val to_bigint_and_exponent : t -> Bigint.bigint * Bigint.bigint exp + (** n and p such that the number is n*10^p or n*2^p *) - val to_bigint_and_exponent : t -> Bigint.bigint * Bigint.bigint - val of_bigint_and_exponent : Bigint.bigint -> Bigint.bigint -> t - (** n and p such that the number is n*10^p *) + val classify : t -> num_class val is_bigger_int_than : t -> UnsignedNat.t -> bool (** Test if an integer whose absolute value is bounded *) diff --git a/interp/smartlocate.ml b/interp/smartlocate.ml index 98fa71e15d..33d8aa6064 100644 --- a/interp/smartlocate.ml +++ b/interp/smartlocate.ml @@ -56,21 +56,25 @@ let global_inductive_with_alias qid = | ref -> user_err ?loc:qid.CAst.loc ~hdr:"global_inductive" (pr_qualid qid ++ spc () ++ str "is not an inductive type.") - with Not_found -> Nametab.error_global_not_found qid + with Not_found as exn -> + let _, info = Exninfo.capture exn in + Nametab.error_global_not_found ~info qid let global_with_alias ?head qid = try locate_global_with_alias ?head qid - with Not_found -> Nametab.error_global_not_found qid + with Not_found as exn -> + let _, info = Exninfo.capture exn in + Nametab.error_global_not_found ~info qid -let smart_global ?head = let open Constrexpr in CAst.with_loc_val (fun ?loc -> function +let smart_global ?(head = false) = let open Constrexpr in CAst.with_loc_val (fun ?loc -> function | AN r -> - global_with_alias ?head r + global_with_alias ~head r | ByNotation (ntn,sc) -> - Notation.interp_notation_as_global_reference ?loc (fun _ -> true) ntn sc) + Notation.interp_notation_as_global_reference ?loc ~head (fun _ -> true) ntn sc) let smart_global_inductive = let open Constrexpr in CAst.with_loc_val (fun ?loc -> function | AN r -> global_inductive_with_alias r | ByNotation (ntn,sc) -> destIndRef - (Notation.interp_notation_as_global_reference ?loc isIndRef ntn sc)) + (Notation.interp_notation_as_global_reference ?loc ~head:false isIndRef ntn sc)) diff --git a/interp/syntax_def.ml b/interp/syntax_def.ml index 7184f5ea29..bd3e234a91 100644 --- a/interp/syntax_def.ml +++ b/interp/syntax_def.ml @@ -8,7 +8,6 @@ (* * (see LICENSE file for the text of the license) *) (************************************************************************) -open Util open Pp open CErrors open Names @@ -82,16 +81,9 @@ let in_syntax_constant : (bool * syndef) -> obj = subst_function = subst_syntax_constant; classify_function = classify_syntax_constant } -type syndef_interpretation = (Id.t * subscopes) list * notation_constr - -(* Coercions to the general format of notation that also supports - variables bound to list of expressions *) -let in_pat (ids,ac) = (List.map (fun (id,sc) -> (id,((Constrexpr.InConstrEntrySomeLevel,sc),NtnTypeConstr))) ids,ac) -let out_pat (ids,ac) = (List.map (fun (id,((_,sc),typ)) -> (id,sc)) ids,ac) - let declare_syntactic_definition ~local deprecation id ~onlyparsing pat = let syndef = - { syndef_pattern = in_pat pat; + { syndef_pattern = pat; syndef_onlyparsing = onlyparsing; syndef_deprecation = deprecation; } @@ -106,14 +98,12 @@ let warn_deprecated_syntactic_definition = let search_syntactic_definition ?loc kn = let syndef = KNmap.find kn !syntax_table in - let def = out_pat syndef.syndef_pattern in Option.iter (fun d -> warn_deprecated_syntactic_definition ?loc (kn,d)) syndef.syndef_deprecation; - def + syndef.syndef_pattern let search_filtered_syntactic_definition ?loc filter kn = let syndef = KNmap.find kn !syntax_table in - let def = out_pat syndef.syndef_pattern in - let res = filter def in + let res = filter syndef.syndef_pattern in if Option.has_some res then Option.iter (fun d -> warn_deprecated_syntactic_definition ?loc (kn,d)) syndef.syndef_deprecation; res diff --git a/interp/syntax_def.mli b/interp/syntax_def.mli index 8b323462a1..66a3132f2a 100644 --- a/interp/syntax_def.mli +++ b/interp/syntax_def.mli @@ -13,12 +13,10 @@ open Notation_term (** Syntactic definitions. *) -type syndef_interpretation = (Id.t * subscopes) list * notation_constr - val declare_syntactic_definition : local:bool -> Deprecation.t option -> Id.t -> - onlyparsing:bool -> syndef_interpretation -> unit + onlyparsing:bool -> interpretation -> unit -val search_syntactic_definition : ?loc:Loc.t -> KerName.t -> syndef_interpretation +val search_syntactic_definition : ?loc:Loc.t -> KerName.t -> interpretation val search_filtered_syntactic_definition : ?loc:Loc.t -> - (syndef_interpretation -> 'a option) -> KerName.t -> 'a option + (interpretation -> 'a option) -> KerName.t -> 'a option |
