(************************************************************************)
(*         *   The Coq Proof Assistant / The Coq Development Team       *)
(*  v      *         Copyright INRIA, CNRS and contributors             *)
(* <O___,, * (see version control and CREDITS file for authors & dates) *)
(*   VV/  **************************************************************)
(*    //   *    This file is distributed under the terms of the         *)
(*         *     GNU Lesser General Public License Version 2.1          *)
(*         *     (see LICENSE file for the text of the license)         *)
(************************************************************************)

(************************************************************************)
(* SerAPI: Coq interaction protocol with bidirectional serialization    *)
(************************************************************************)
(* Copyright 2016-2019 MINES ParisTech -- License LGPL 2.1+             *)
(* Copyright 2019-2023 Inria           -- License LGPL 2.1+             *)
(* Written by: Emilio J. Gallego Arias and others                       *)
(************************************************************************)

open Cmdliner

let sertop_version = Sertop.Ser_version.ser_git_version

let sertop printer print0 debug set_impredicative_set disallow_sprop indices_matter lheader coq_path ml_path no_init topfile no_prelude lp1 lp2 _std_impl async deep_edits async_workers error_recovery omit_loc omit_att omit_env exn_on_opaque =

  let open  Sertop.Sertop_init         in
  let open! Sertop.Sertop_sexp         in

  let options = Serlib.Serlib_init.{ omit_loc; omit_att; exn_on_opaque; omit_env } in
  Serlib.Serlib_init.init ~options;

  let dft_ml_path, vo_path =
    Serapi.Serapi_paths.coq_loadpath_default ~implicit:true ~coq_path in
  let ml_path = dft_ml_path @ ml_path in
  let vo_path = vo_path @ lp1 @ lp2 in
  let allow_sprop = not disallow_sprop in

  ser_loop
    { in_chan  = stdin
    ; out_chan = stdout

    ; debug
    ; set_impredicative_set
    ; allow_sprop
    ; indices_matter
    ; printer
    ; print0
    ; lheader

    ; no_init
    ; no_prelude
    ; topfile
    ; ml_path
    ; vo_path
    ; async =
         { enable_async = async
         ; deep_edits
         ; async_workers
         ; error_recovery
       }
    }

let sertop_cmd =
  let open Sertop.Sertop_arg in
  let doc = "SerAPI Coq Toplevel" in
  let man = [
    `S "DESCRIPTION";
    `P "Experimental Coq Toplevel with Serialization Support";
    `S "USAGE";
    `P "To build a Coq document, use the `Add` command:";
    `Pre "(Add () \"Lemma addn0 n : n + 0. Proof. now induction n. Qed.\")";
    `P "SerAPI will parse and split the document into \"logical\" sentences.";
    `P "Then, you can ask Coq to check the proof with `Exec`:";
    `Pre "(Exec 5)";
    `P "Other queries are also possible; some examples:";
    `Pre "(Query ((sid 4)) Ast)";
    `P "Will print the AST at sentence 4.";
    `Pre "(Query ((sid 3)) Goals)";
    `P "Will print the goals at sentence 3.";
    `P "See the documentation on the project's webpage for more information"
  ]
  in
  let term =
    Term.(const sertop
          $ printer $ print0 $ debug $ set_impredicative_set $ disallow_sprop $ indices_matter $ length $ prelude $ ml_include_path $ no_init $topfile $ no_prelude $ load_path $ rload_path $ implicit_stdlib
          $ async $ deep_edits $ async_workers $ error_recovery $ omit_loc $ omit_att $ omit_env $ exn_on_opaque ) in
  let info = Cmd.info "sertop" ~version:sertop_version ~doc ~man in
  Cmd.v info term

let main () = exit (Cmd.eval sertop_cmd)

let _ = main ()
