summaryrefslogtreecommitdiff
path: root/toplevel/coqtop.ml
diff options
context:
space:
mode:
Diffstat (limited to 'toplevel/coqtop.ml')
-rw-r--r--toplevel/coqtop.ml325
1 files changed, 325 insertions, 0 deletions
diff --git a/toplevel/coqtop.ml b/toplevel/coqtop.ml
new file mode 100644
index 00000000..aa765b16
--- /dev/null
+++ b/toplevel/coqtop.ml
@@ -0,0 +1,325 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+(* $Id: coqtop.ml,v 1.72.2.3 2004/07/16 19:31:47 herbelin Exp $ *)
+
+open Pp
+open Util
+open System
+open Options
+open Names
+open Libnames
+open Nameops
+open States
+open Toplevel
+open Coqinit
+
+let get_version_date () =
+ try
+ let ch = open_in (Coq_config.coqtop^"/make.result") in
+ let l = input_line ch in
+ let i = String.index l ' ' in
+ let j = String.index_from l (i+1) ' ' in
+ "checked out on "^(String.sub l (i+1) (j-i-1))
+ with _ -> Coq_config.date
+
+let print_header () =
+ Printf.printf "Welcome to Coq %s%s (%s)\n"
+ Coq_config.version
+ (if !Options.v7 then " (V7 syntax)" else "")
+ (get_version_date ());
+ flush stdout
+
+let memory_stat = ref false
+
+let print_memory_stat () =
+ if !memory_stat then
+ Format.printf "total heap size = %d kbytes\n" (heap_size_kb ())
+
+let _ = at_exit print_memory_stat
+
+let engagement = ref None
+let set_engagement c = engagement := Some c
+let engage () =
+ match !engagement with Some c -> Global.set_engagement c | None -> ()
+
+let set_batch_mode () = batch_mode := true
+
+let toplevel_name = ref (make_dirpath [id_of_string "Top"])
+let set_toplevel_name dir = toplevel_name := dir
+
+let remove_top_ml () = Mltop.remove ()
+
+let inputstate = ref None
+let set_inputstate s = inputstate:= Some s
+let inputstate () =
+ match !inputstate with
+ | Some "" -> ()
+ | Some s -> intern_state s
+ | None -> intern_state "initial.coq"
+
+let outputstate = ref ""
+let set_outputstate s = outputstate:=s
+let outputstate () = if !outputstate <> "" then extern_state !outputstate
+
+let check_coq_overwriting p =
+ if string_of_id (List.hd (repr_dirpath p)) = "Coq" then
+ error "The \"Coq\" logical root directory is reserved for the Coq library"
+
+let set_include d p = push_include (d,p)
+let set_rec_include d p = check_coq_overwriting p; push_rec_include (d,p)
+let set_default_include d = set_include d Nameops.default_root_prefix
+let set_default_rec_include d = set_rec_include d Nameops.default_root_prefix
+
+let load_vernacular_list = ref ([] : (string * bool) list)
+let add_load_vernacular verb s =
+ load_vernacular_list := ((make_suffix s ".v"),verb) :: !load_vernacular_list
+let load_vernacular () =
+ List.iter
+ (fun (s,b) ->
+ if Options.do_translate () then
+ with_option translate_file (Vernac.load_vernac b) s
+ else
+ Vernac.load_vernac b s)
+ (List.rev !load_vernacular_list)
+
+let load_vernacular_obj = ref ([] : string list)
+let add_vernac_obj s = load_vernacular_obj := s :: !load_vernacular_obj
+let load_vernac_obj () =
+ List.iter Library.read_library_from_file (List.rev !load_vernacular_obj)
+
+let require_list = ref ([] : string list)
+let add_require s = require_list := s :: !require_list
+let require () =
+ List.iter (fun s -> Library.require_library_from_file None None s false)
+ (List.rev !require_list)
+
+let compile_list = ref ([] : (bool * string) list)
+let add_compile verbose s =
+ set_batch_mode ();
+ Options.make_silent true;
+ compile_list := (verbose,s) :: !compile_list
+let compile_files () =
+ let init_state = States.freeze() in
+ List.iter
+ (fun (v,f) ->
+ States.unfreeze init_state;
+ if Options.do_translate () then
+ with_option translate_file (Vernac.compile v) f
+ else
+ Vernac.compile v f)
+ (List.rev !compile_list)
+
+let re_exec_version = ref ""
+let set_byte () = re_exec_version := "byte"
+let set_opt () = re_exec_version := "opt"
+
+(* Re-exec Coq in bytecode or native code if necessary. [s] is either
+ ["byte"] or ["opt"]. Notice that this is possible since the nature of
+ the toplevel has already been set in [Mltop] by the main file created
+ by coqmktop (see scripts/coqmktop.ml). *)
+
+let re_exec is_ide =
+ let s = !re_exec_version in
+ let is_native = (Mltop.get()) = Mltop.Native in
+ let prog = Sys.argv.(0) in
+ let coq = Filename.basename prog in
+ if (is_native && s = "byte") || ((not is_native) && s = "opt")
+ then begin
+ let s = if s = "" then if is_native then "opt" else "byte" else s in
+ let newprog =
+ let dir = Filename.dirname prog in
+ let coqtop = if is_ide then "coqide." else "coqtop." in
+ let com = coqtop ^ s ^ Coq_config.exec_extension in
+ if dir <> "." then Filename.concat dir com else com
+ in
+ Sys.argv.(0) <- newprog;
+ Unix.handle_unix_error (Unix.execvp newprog) Sys.argv
+ end
+
+(*s Parsing of the command line.
+ We no longer use [Arg.parse], in order to use share [Usage.print_usage]
+ between coqtop and coqc. *)
+
+let usage () =
+ if !batch_mode then
+ Usage.print_usage_coqc ()
+ else
+ Usage.print_usage_coqtop () ;
+ flush stderr ;
+ exit 1
+
+let warning s = msg_warning (str s)
+
+let ide_args = ref []
+let parse_args is_ide =
+ let rec parse = function
+ | [] -> ()
+
+ | "-impredicative-set" :: rem ->
+ set_engagement Environ.ImpredicativeSet; parse rem
+
+ | ("-I"|"-include") :: d :: rem -> set_default_include d; parse rem
+ | ("-I"|"-include") :: [] -> usage ()
+
+ | "-R" :: d :: p :: rem ->set_rec_include d (dirpath_of_string p);parse rem
+ | "-R" :: ([] | [_]) -> usage ()
+
+ | "-top" :: d :: rem -> set_toplevel_name (dirpath_of_string d); parse rem
+ | "-top" :: [] -> usage ()
+
+ | "-q" :: rem -> no_load_rc (); parse rem
+
+ | "-opt" :: rem -> set_opt(); parse rem
+ | "-byte" :: rem -> set_byte(); parse rem
+ | "-full" :: rem -> warning "option -full deprecated\n"; parse rem
+
+ | "-batch" :: rem -> set_batch_mode (); parse rem
+ | "-boot" :: rem -> boot := true; no_load_rc (); parse rem
+ | "-quality" :: rem -> term_quality := true; no_load_rc (); parse rem
+ | "-outputstate" :: s :: rem -> set_outputstate s; parse rem
+ | "-outputstate" :: [] -> usage ()
+
+ | "-nois" :: rem -> set_inputstate ""; parse rem
+
+ | ("-inputstate"|"-is") :: s :: rem -> set_inputstate s; parse rem
+ | ("-inputstate"|"-is") :: [] -> usage ()
+
+ | "-load-ml-object" :: f :: rem -> Mltop.dir_ml_load f; parse rem
+ | "-load-ml-object" :: [] -> usage ()
+
+ | "-load-ml-source" :: f :: rem -> Mltop.dir_ml_use f; parse rem
+ | "-load-ml-source" :: [] -> usage ()
+
+ | ("-load-vernac-source"|"-l") :: f :: rem ->
+ add_load_vernacular false f; parse rem
+ | ("-load-vernac-source"|"-l") :: [] -> usage ()
+
+ | ("-load-vernac-source-verbose"|"-lv") :: f :: rem ->
+ add_load_vernacular true f; parse rem
+ | ("-load-vernac-source-verbose"|"-lv") :: [] -> usage ()
+
+ | "-load-vernac-object" :: f :: rem -> add_vernac_obj f; parse rem
+ | "-load-vernac-object" :: [] -> usage ()
+
+ | "-dump-glob" :: f :: rem -> dump_into_file f; parse rem
+ | "-dump-glob" :: [] -> usage ()
+
+ | "-require" :: f :: rem -> add_require f; parse rem
+ | "-require" :: [] -> usage ()
+
+ | "-compile" :: f :: rem -> add_compile false f; parse rem
+ | "-compile" :: [] -> usage ()
+
+ | "-compile-verbose" :: f :: rem -> add_compile true f; parse rem
+ | "-compile-verbose" :: [] -> usage ()
+
+ | "-dont-load-proofs" :: rem -> Options.dont_load_proofs := true; parse rem
+
+ | "-translate" :: rem -> make_translate true; parse rem
+
+ | "-unsafe" :: f :: rem -> add_unsafe f; parse rem
+ | "-unsafe" :: [] -> usage ()
+
+ | "-debug" :: rem -> set_debug (); parse rem
+
+ | "-emacs" :: rem -> Options.print_emacs := true; parse rem
+
+ | "-where" :: _ -> print_endline Coq_config.coqlib; exit 0
+
+ | ("-quiet"|"-silent") :: rem -> Options.make_silent true; parse rem
+
+ | ("-?"|"-h"|"-H"|"-help"|"--help") :: _ -> usage ()
+
+ | ("-v"|"--version") :: _ -> Usage.version ()
+
+ | "-init-file" :: f :: rem -> set_rcfile f; parse rem
+ | "-init-file" :: [] -> usage ()
+
+ | "-user" :: u :: rem -> set_rcuser u; parse rem
+ | "-user" :: [] -> usage ()
+
+ | "-notactics" :: rem -> remove_top_ml (); parse rem
+
+ | "-just-parsing" :: rem -> Vernac.just_parsing := true; parse rem
+
+ | ("-m" | "--memory") :: rem -> memory_stat := true; parse rem
+
+ | "-xml" :: rem -> Options.xml_export := true; parse rem
+
+ (* Scanned in Options! *)
+ | "-v7" :: rem -> (* Options.v7 := true; *) parse rem
+ | "-v8" :: rem -> (* Options.v7 := false; *) parse rem
+
+ (* Translator options *)
+ | "-strict-implicit" :: rem ->
+ Options.translate_strict_impargs := false; parse rem
+
+ | s :: rem ->
+ if is_ide then begin
+ ide_args := s :: !ide_args;
+ parse rem
+ end else begin
+ prerr_endline ("Don't know what to do with " ^ s); usage ()
+ end
+ in
+ try
+ parse (List.tl (Array.to_list Sys.argv))
+ with
+ | UserError(_,s) as e -> begin
+ try
+ Stream.empty s; exit 1
+ with Stream.Failure ->
+ msgnl (Cerrors.explain_exn e); exit 1
+ end
+ | e -> begin msgnl (Cerrors.explain_exn e); exit 1 end
+
+
+(* To prevent from doing the initialization twice *)
+let initialized = ref false
+
+let init is_ide =
+ if not !initialized then begin
+ initialized := true;
+ Sys.catch_break false; (* Ctrl-C is fatal during the initialisation *)
+ Lib.init();
+ try
+ parse_args is_ide;
+ re_exec is_ide;
+ if_verbose print_header ();
+ init_load_path ();
+ inputstate ();
+ engage ();
+ if not !batch_mode then Declaremods.start_library !toplevel_name;
+ init_library_roots ();
+ load_vernac_obj ();
+ require ();
+ load_rcfile();
+ load_vernacular ();
+ compile_files ();
+ outputstate ();
+ with e ->
+ flush_all();
+ if not !batch_mode then message "Error during initialization :";
+ msgnl (Toplevel.print_toplevel_error e);
+ exit 1
+ end;
+ if !batch_mode then (flush_all(); Profile.print_profile (); exit 0);
+ Lib.declare_initial_state ()
+
+let init_ide () = init true; List.rev !ide_args
+
+let start () =
+ init false;
+ Toplevel.loop();
+ (* Initialise and launch the Ocaml toplevel *)
+ Coqinit.init_ocaml_path();
+ Mltop.ocaml_toploop();
+ exit 1
+
+(* [Coqtop.start] will be called by the code produced by coqmktop *)